优化了老师端的等待状态判断逻辑
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
|
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../viewmodel/stu_room_vm.dart';
|
||||||
|
|
||||||
class TeacherVideo extends StatefulWidget {
|
class TeacherVideo extends StatefulWidget {
|
||||||
const TeacherVideo({super.key});
|
const TeacherVideo({super.key});
|
||||||
@@ -10,10 +14,44 @@ class TeacherVideo extends StatefulWidget {
|
|||||||
class _TeacherVideoState extends State<TeacherVideo> {
|
class _TeacherVideoState extends State<TeacherVideo> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final vm = context.read<StuRoomVM>();
|
||||||
|
final teacherInfo = vm.teacherInfo;
|
||||||
|
|
||||||
|
///没开始
|
||||||
|
if (vm.roomStatus == 0) {
|
||||||
|
return _empty("自习室还没开始");
|
||||||
|
}
|
||||||
|
|
||||||
|
///开始
|
||||||
|
if (vm.roomStatus == 1 && vm.engine != null) {
|
||||||
|
if (teacherInfo == null) {
|
||||||
|
return _empty("老师不在自习室内");
|
||||||
|
}
|
||||||
|
if (teacherInfo.online == 0) {
|
||||||
|
return _empty("老师掉线了,请耐心等待");
|
||||||
|
}
|
||||||
|
return AgoraVideoView(
|
||||||
|
controller: VideoViewController(
|
||||||
|
rtcEngine: vm.engine!,
|
||||||
|
canvas: VideoCanvas(
|
||||||
|
uid: vm.teacherInfo!.userId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
///结束
|
||||||
|
if (vm.roomStatus == 2) {
|
||||||
|
return _empty("自习室已结束");
|
||||||
|
}
|
||||||
|
return _empty("加载中");
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _empty(String title) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Align(
|
child: Align(
|
||||||
child: Text(
|
child: Text(
|
||||||
"画面准备中",
|
title,
|
||||||
style: TextStyle(color: Colors.white),
|
style: TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
|
||||||
|
import 'package:app/config/config.dart';
|
||||||
import 'package:app/providers/user_store.dart';
|
import 'package:app/providers/user_store.dart';
|
||||||
import 'package:app/request/dto/room/room_info_dto.dart';
|
import 'package:app/request/dto/room/room_info_dto.dart';
|
||||||
import 'package:app/request/dto/room/room_type_dto.dart';
|
import 'package:app/request/dto/room/room_type_dto.dart';
|
||||||
@@ -36,12 +38,48 @@ class StuRoomVM extends ChangeNotifier {
|
|||||||
final RoomWebSocket _ws = RoomWebSocket();
|
final RoomWebSocket _ws = RoomWebSocket();
|
||||||
StreamSubscription<RoomMessage>? _sub;
|
StreamSubscription<RoomMessage>? _sub;
|
||||||
|
|
||||||
RtcTokenDto? get rtcToken => _ws.rtcToken;
|
/// 声网sdk管理
|
||||||
|
RtcEngine? _engine;
|
||||||
|
|
||||||
|
RtcEngine? get engine => _engine;
|
||||||
|
|
||||||
StuRoomVM({required this.roomInfo, required this.uid}) {
|
StuRoomVM({required this.roomInfo, required this.uid}) {
|
||||||
_startRoom();
|
_startRoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///初始化声网
|
||||||
|
Future<void> _initRtc() async {
|
||||||
|
_engine = createAgoraRtcEngine();
|
||||||
|
//初始化 RtcEngine,设置频道场景为 channelProfileLiveBroadcasting(直播场景)
|
||||||
|
await _engine!.initialize(
|
||||||
|
RtcEngineContext(
|
||||||
|
appId: Config.swAppId,
|
||||||
|
channelProfile: ChannelProfileType.channelProfileCommunication,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
//启动视频模块
|
||||||
|
await _engine!.enableVideo();
|
||||||
|
//加入频道
|
||||||
|
await _engine!.joinChannel(
|
||||||
|
token: _ws.rtcToken!.token,
|
||||||
|
channelId: _ws.rtcToken!.channel,
|
||||||
|
uid: uid,
|
||||||
|
// uid: _ws.rtcToken!.uid,
|
||||||
|
options: ChannelMediaOptions(
|
||||||
|
// 自动订阅所有视频流
|
||||||
|
autoSubscribeVideo: true,
|
||||||
|
// 自动订阅所有音频流
|
||||||
|
autoSubscribeAudio: true,
|
||||||
|
// 发布摄像头采集的视频
|
||||||
|
publishCameraTrack: true,
|
||||||
|
// 发布麦克风采集的音频
|
||||||
|
publishMicrophoneTrack: true,
|
||||||
|
// 设置用户角色为 clientRoleBroadcaster(主播)或 clientRoleAudience(观众)
|
||||||
|
clientRoleType: ClientRoleType.clientRoleBroadcaster,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
///开始链接房间
|
///开始链接房间
|
||||||
Future<void> _startRoom() async {
|
Future<void> _startRoom() async {
|
||||||
//如果socket的token没有,先初始化
|
//如果socket的token没有,先初始化
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import 'package:app/pages/teacher/home/viewmodel/home_view_model.dart';
|
|
||||||
import 'package:app/request/dto/room/room_info_dto.dart';
|
|
||||||
import 'package:app/router/route_paths.dart';
|
import 'package:app/router/route_paths.dart';
|
||||||
import 'package:app/utils/permission.dart';
|
import 'package:app/utils/permission.dart';
|
||||||
import 'package:app/widgets/base/button/index.dart';
|
import 'package:app/widgets/base/button/index.dart';
|
||||||
import 'package:app/widgets/base/card/g_card.dart';
|
import 'package:app/widgets/base/card/g_card.dart';
|
||||||
import 'package:app/widgets/base/config/config.dart';
|
import 'package:app/widgets/base/config/config.dart';
|
||||||
|
import 'package:app/widgets/base/dialog/config_dialog.dart';
|
||||||
import 'package:app/widgets/base/empty/index.dart';
|
import 'package:app/widgets/base/empty/index.dart';
|
||||||
|
import 'package:app/widgets/room/file_drawer.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@@ -14,6 +14,8 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:remixicon/remixicon.dart';
|
import 'package:remixicon/remixicon.dart';
|
||||||
import 'package:skeletonizer/skeletonizer.dart';
|
import 'package:skeletonizer/skeletonizer.dart';
|
||||||
|
|
||||||
|
import '../viewmodel/home_view_model.dart';
|
||||||
|
|
||||||
class TodayCard extends StatefulWidget {
|
class TodayCard extends StatefulWidget {
|
||||||
const TodayCard({super.key});
|
const TodayCard({super.key});
|
||||||
|
|
||||||
@@ -28,7 +30,7 @@ class _TodayCardState extends State<TodayCard> {
|
|||||||
permissions: [Permission.microphone, Permission.camera],
|
permissions: [Permission.microphone, Permission.camera],
|
||||||
onGranted: () {
|
onGranted: () {
|
||||||
final vm = context.read<HomeViewModel>();
|
final vm = context.read<HomeViewModel>();
|
||||||
context.push(RoutePaths.tRoom,extra: vm.roomInfo);
|
context.push(RoutePaths.tRoom, extra: vm.roomInfo);
|
||||||
},
|
},
|
||||||
onDenied: () {
|
onDenied: () {
|
||||||
EasyLoading.showError("请开启权限");
|
EasyLoading.showError("请开启权限");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:app/request/dto/room/room_info_dto.dart';
|
import 'package:app/request/dto/room/room_info_dto.dart';
|
||||||
|
import 'package:app/request/dto/room/room_type_dto.dart';
|
||||||
import 'package:app/request/dto/room/room_user_dto.dart';
|
import 'package:app/request/dto/room/room_user_dto.dart';
|
||||||
import 'package:app/request/dto/room/rtc_token_dto.dart';
|
import 'package:app/request/dto/room/rtc_token_dto.dart';
|
||||||
import 'package:app/request/websocket/room_protocol.dart';
|
import 'package:app/request/websocket/room_protocol.dart';
|
||||||
@@ -11,7 +12,10 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'type.dart';
|
import 'type.dart';
|
||||||
|
|
||||||
class TchRoomVM extends ChangeNotifier {
|
class TchRoomVM extends ChangeNotifier {
|
||||||
TchRoomVM({required this.roomInfo, String? start}) {
|
TchRoomVM({
|
||||||
|
required this.roomInfo,
|
||||||
|
String? start,
|
||||||
|
}) {
|
||||||
_startRoom();
|
_startRoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,6 +24,7 @@ class TchRoomVM extends ChangeNotifier {
|
|||||||
|
|
||||||
///房间的基础信息
|
///房间的基础信息
|
||||||
final RoomInfoDto roomInfo;
|
final RoomInfoDto roomInfo;
|
||||||
|
int roomStatus = -1; // //-1加载中,0没开始,1进行中,2关闭
|
||||||
|
|
||||||
///老师选中的学生id
|
///老师选中的学生id
|
||||||
int activeSId = 0;
|
int activeSId = 0;
|
||||||
@@ -37,7 +42,8 @@ class TchRoomVM extends ChangeNotifier {
|
|||||||
|
|
||||||
///websocket管理
|
///websocket管理
|
||||||
final RoomWebSocket _ws = RoomWebSocket();
|
final RoomWebSocket _ws = RoomWebSocket();
|
||||||
bool wsConnected = false; // socket连接状态
|
|
||||||
|
// bool wsConnected = false; // socket连接状态
|
||||||
StreamSubscription<RoomMessage>? _sub;
|
StreamSubscription<RoomMessage>? _sub;
|
||||||
|
|
||||||
RtcTokenDto? get rtcToken => _ws.rtcToken;
|
RtcTokenDto? get rtcToken => _ws.rtcToken;
|
||||||
@@ -50,12 +56,13 @@ class TchRoomVM extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
//启动连接
|
//启动连接
|
||||||
await _ws.connect();
|
await _ws.connect();
|
||||||
wsConnected = true;
|
|
||||||
//监听各种ws事件
|
//监听各种ws事件
|
||||||
_sub = _ws.stream.listen((msg) {
|
_sub = _ws.stream.listen((msg) {
|
||||||
// 自习室人员变化
|
// 自习室人员变化
|
||||||
if (msg.event == RoomEvent.changeUser) {
|
if (msg.event == RoomEvent.changeUser) {
|
||||||
final list = RoomUserDto.listFromJson(msg.data['user_list']);
|
final list = RoomUserDto.listFromJson(msg.data['user_list']);
|
||||||
|
final room = RoomTypeDto.fromJson(msg.data['room_info']);
|
||||||
|
roomStatus = room.roomStatus;
|
||||||
onStudentChange(list);
|
onStudentChange(list);
|
||||||
} else if ([
|
} else if ([
|
||||||
RoomEvent.openSpeaker,
|
RoomEvent.openSpeaker,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
|
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
|
||||||
import 'package:app/config/config.dart';
|
import 'package:app/config/config.dart';
|
||||||
|
import 'package:app/providers/user_store.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
@@ -14,17 +15,23 @@ class ContentView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ContentViewState extends State<ContentView> {
|
class _ContentViewState extends State<ContentView> {
|
||||||
|
|
||||||
//声网数据
|
//声网数据
|
||||||
RtcEngine? _engine;
|
RtcEngine? _engine;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// _initRtc();
|
_initRtc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
_dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initRtc() async {
|
void _initRtc() async {
|
||||||
|
UserStore userStore = context.read<UserStore>();
|
||||||
final vm = context.read<TchRoomVM>();
|
final vm = context.read<TchRoomVM>();
|
||||||
_engine = createAgoraRtcEngine();
|
_engine = createAgoraRtcEngine();
|
||||||
//初始化 RtcEngine,设置频道场景为 channelProfileLiveBroadcasting(直播场景)
|
//初始化 RtcEngine,设置频道场景为 channelProfileLiveBroadcasting(直播场景)
|
||||||
@@ -44,8 +51,7 @@ class _ContentViewState extends State<ContentView> {
|
|||||||
// 远端用户或主播加入当前频道回调
|
// 远端用户或主播加入当前频道回调
|
||||||
onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {},
|
onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {},
|
||||||
// 远端用户或主播离开当前频道回调
|
// 远端用户或主播离开当前频道回调
|
||||||
onUserOffline:
|
onUserOffline: (RtcConnection connection, int remoteUid, UserOfflineReasonType reason) {},
|
||||||
(RtcConnection connection, int remoteUid, UserOfflineReasonType reason) {},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
//启动视频模块
|
//启动视频模块
|
||||||
@@ -54,7 +60,7 @@ class _ContentViewState extends State<ContentView> {
|
|||||||
await _engine!.joinChannel(
|
await _engine!.joinChannel(
|
||||||
token: vm.rtcToken!.token,
|
token: vm.rtcToken!.token,
|
||||||
channelId: vm.rtcToken!.channel,
|
channelId: vm.rtcToken!.channel,
|
||||||
uid: vm.rtcToken!.uid,
|
uid: userStore.userInfo!.id,
|
||||||
options: ChannelMediaOptions(
|
options: ChannelMediaOptions(
|
||||||
// 自动订阅所有视频流
|
// 自动订阅所有视频流
|
||||||
autoSubscribeVideo: true,
|
autoSubscribeVideo: true,
|
||||||
@@ -70,6 +76,14 @@ class _ContentViewState extends State<ContentView> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//销毁
|
||||||
|
Future<void> _dispose() async {
|
||||||
|
if (_engine != null) {
|
||||||
|
await _engine!.leaveChannel();
|
||||||
|
await _engine!.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<TchRoomVM>(
|
return Consumer<TchRoomVM>(
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:app/utils/time.dart';
|
import 'package:app/utils/time.dart';
|
||||||
|
import 'package:app/widgets/base/dialog/config_dialog.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'content_view.dart';
|
import 'content_view.dart';
|
||||||
@@ -15,86 +17,97 @@ class StatusView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _StatusViewState extends State<StatusView> {
|
class _StatusViewState extends State<StatusView> {
|
||||||
///房间状态
|
|
||||||
RoomStatus status = RoomStatus.loading;
|
|
||||||
|
|
||||||
///剩余秒
|
|
||||||
int _seconds = 0;
|
int _seconds = 0;
|
||||||
Timer? _timer;
|
Timer? _timer;
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_init();
|
|
||||||
final vm = context.read<TchRoomVM>();
|
|
||||||
vm.addListener(openRoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
_timer = null;
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _init() {
|
void _startCountDown(DateTime startTime) {
|
||||||
final vm = context.read<TchRoomVM>();
|
// 避免重复计时器
|
||||||
//如果房间到点可以开始
|
if (_timer != null) return;
|
||||||
if (vm.canEnterRoom) {
|
|
||||||
status = RoomStatus.start;
|
final now = DateTime.now();
|
||||||
// openRoom();
|
int diff = startTime.difference(now).inSeconds;
|
||||||
} else {
|
|
||||||
status = RoomStatus.waiting;
|
if (diff <= 0) {
|
||||||
startCountDown();
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
///开始倒计时
|
|
||||||
void startCountDown() {
|
|
||||||
final vm = context.read<TchRoomVM>();
|
|
||||||
//当前时间
|
|
||||||
DateTime now = DateTime.now();
|
|
||||||
//远端时间
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_seconds = parseTime(vm.roomInfo.startTime).difference(now).inSeconds;
|
_seconds = diff;
|
||||||
});
|
});
|
||||||
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
|
|
||||||
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
_seconds--;
|
_seconds--;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (_seconds <= 0) {
|
if (_seconds <= 0) {
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
_timer = null;
|
_timer = null;
|
||||||
setState(() {
|
|
||||||
status = RoomStatus.start;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
///开启自习室
|
///开播中返回拦截弹窗
|
||||||
void openRoom() {
|
void _interceptPop() {
|
||||||
final vm = context.read<TchRoomVM>();
|
showDialog(
|
||||||
vm.toggleRoom(isOpen: true);
|
context: context,
|
||||||
vm.removeListener(openRoom);
|
builder: (context) {
|
||||||
|
return ConfigDialog(
|
||||||
|
content: "是否退出自习室",
|
||||||
|
onCancel: () {
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
|
onConfirm: () {
|
||||||
|
context.pop();
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (status == RoomStatus.waiting) {
|
final vm = context.watch<TchRoomVM>();
|
||||||
|
|
||||||
|
/// 1. 未加载
|
||||||
|
if (vm.roomStatus == -1) {
|
||||||
|
return const Align(
|
||||||
|
child: Text("加载中", style: TextStyle(color: Colors.white)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 2. 未开始的房间
|
||||||
|
if (vm.roomStatus == 0) {
|
||||||
|
if (vm.canEnterRoom) {
|
||||||
|
// 到时间了 → 自动开播
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
vm.toggleRoom(isOpen: true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 没到时间 → 启动倒计时
|
||||||
|
_startCountDown(parseTime(vm.roomInfo.startTime));
|
||||||
|
}
|
||||||
|
|
||||||
return Align(
|
return Align(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const Text(
|
||||||
"未到开播时间,到点后自动开播",
|
"未到开播时间,到点后自动开播",
|
||||||
style: TextStyle(color: Colors.white),
|
style: TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 10),
|
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||||
child: Text(
|
child: Text(
|
||||||
formatSeconds(_seconds),
|
formatSeconds(_seconds),
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 26,
|
fontSize: 26,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@@ -104,15 +117,21 @@ class _StatusViewState extends State<StatusView> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else if (status == RoomStatus.start) {
|
|
||||||
return ContentView();
|
|
||||||
}
|
}
|
||||||
return SizedBox();
|
|
||||||
|
/// 3. 已开播
|
||||||
|
if (vm.roomStatus == 1) {
|
||||||
|
return PopScope(
|
||||||
|
canPop: false,
|
||||||
|
onPopInvokedWithResult: (didPop, _) {
|
||||||
|
if (!didPop) {
|
||||||
|
_interceptPop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const ContentView(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RoomStatus {
|
|
||||||
loading, // 加载中
|
|
||||||
waiting, //房间倒计时等待中
|
|
||||||
start, //房间开始中
|
|
||||||
}
|
|
||||||
|
|||||||
91
lib/widgets/base/dialog/config_dialog.dart
Normal file
91
lib/widgets/base/dialog/config_dialog.dart
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ConfigDialog extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final String content;
|
||||||
|
final TextStyle? contentStyle;
|
||||||
|
final String confirmText;
|
||||||
|
final String cancelText;
|
||||||
|
final bool showCancel;
|
||||||
|
final void Function()? onConfirm;
|
||||||
|
final void Function()? onCancel;
|
||||||
|
|
||||||
|
const ConfigDialog({
|
||||||
|
super.key,
|
||||||
|
this.title = "",
|
||||||
|
required this.content,
|
||||||
|
this.contentStyle,
|
||||||
|
this.confirmText = '确定',
|
||||||
|
this.cancelText = '取消',
|
||||||
|
this.showCancel = true,
|
||||||
|
this.onConfirm,
|
||||||
|
this.onCancel,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Color borderColor = Theme.of(context).colorScheme.surfaceContainer;
|
||||||
|
return AlertDialog(
|
||||||
|
actionsPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0),
|
||||||
|
elevation: 0,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
title: Visibility(
|
||||||
|
visible: title.isNotEmpty,
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(bottom: 15),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w700),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
content: Container(
|
||||||
|
padding: const EdgeInsets.only(bottom: 20, left: 20, right: 20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(width: 1, color: borderColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(content, textAlign: TextAlign.center, style: contentStyle),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
if (showCancel) ...[
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: onCancel,
|
||||||
|
child: Text(
|
||||||
|
cancelText,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 1,
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
color: borderColor,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: onConfirm,
|
||||||
|
child: Text(
|
||||||
|
confirmText,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
lib/widgets/room/exit_room_dialog.dart
Normal file
0
lib/widgets/room/exit_room_dialog.dart
Normal file
Reference in New Issue
Block a user