自习室优化ok
This commit is contained in:
73
lib/widgets/room/board/board_dialog.dart
Normal file
73
lib/widgets/room/board/board_dialog.dart
Normal file
@@ -0,0 +1,73 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:remixicon/remixicon.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
|
||||
class BoardDialog extends StatefulWidget {
|
||||
final WebViewController controller;
|
||||
const BoardDialog({super.key, required this.controller});
|
||||
|
||||
@override
|
||||
State<BoardDialog> createState() => _BoardDialogState();
|
||||
}
|
||||
|
||||
class _BoardDialogState extends State<BoardDialog> {
|
||||
bool _loading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// 绑定加载事件
|
||||
widget.controller.setNavigationDelegate(
|
||||
NavigationDelegate(
|
||||
onPageStarted: (_) {
|
||||
setState(() => _loading = true);
|
||||
},
|
||||
onPageFinished: (_) {
|
||||
setState(() => _loading = false);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('白板', style: Theme.of(context).textTheme.titleSmall),
|
||||
IconButton(
|
||||
onPressed: () => context.pop(),
|
||||
icon: const Icon(RemixIcons.close_circle_fill),
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
WebViewWidget(
|
||||
controller: widget.controller,
|
||||
),
|
||||
if (_loading)
|
||||
Container(
|
||||
color: Colors.white,
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
101
lib/widgets/room/board/board_manager.dart
Normal file
101
lib/widgets/room/board/board_manager.dart
Normal file
@@ -0,0 +1,101 @@
|
||||
import 'package:app/global/config.dart';
|
||||
import 'package:app/request/api/room_api.dart';
|
||||
import 'package:app/request/dto/room/board_token_dto.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
import 'board_dialog.dart';
|
||||
|
||||
class BoardManager {
|
||||
BoardManager._();
|
||||
|
||||
static final BoardManager _instance = BoardManager._();
|
||||
|
||||
factory BoardManager() => _instance;
|
||||
|
||||
WebViewController? _webViewController;
|
||||
BoardTokenDto? _boardToken;
|
||||
|
||||
///获取token
|
||||
Future<void> _fetchToken(int roomId) async {
|
||||
final now = DateTime.now();
|
||||
|
||||
if (_boardToken == null) {
|
||||
EasyLoading.show(status: "开启白板中");
|
||||
_boardToken = await getBoardTokenApi(roomId);
|
||||
} else {
|
||||
//离过期差多少小时
|
||||
int remainSeconds = _boardToken!.expiresAt.difference(now).inSeconds;
|
||||
// 剩余不足 2 小时 = 7200 秒
|
||||
if (remainSeconds <= 7200) {
|
||||
EasyLoading.show(status: "开启白板中");
|
||||
_boardToken = await getBoardTokenApi(roomId);
|
||||
}
|
||||
}
|
||||
EasyLoading.dismiss();
|
||||
}
|
||||
|
||||
///生成完整 URL
|
||||
/// -[uid] 用户
|
||||
/// -[roomId] 房间id
|
||||
/// -[isTeacher] 是否是老师
|
||||
Future<String> buildUrl({
|
||||
required String uid,
|
||||
required int roomId,
|
||||
required bool isTeacher,
|
||||
}) async {
|
||||
await _fetchToken(roomId);
|
||||
|
||||
Map<String, dynamic> params = {
|
||||
"appid": _boardToken!.whiteboardAppid,
|
||||
"uid": uid,
|
||||
"uuid": _boardToken!.whiteboardUuid,
|
||||
"room_token": _boardToken!.whiteboardToken,
|
||||
"write": isTeacher ? 1 : 0,
|
||||
};
|
||||
String paramStr = params.entries.map((e) => "${e.key}=${e.value}").join("&");
|
||||
|
||||
return "${Config.webUrl}/board?$paramStr";
|
||||
}
|
||||
|
||||
/// 获取全局唯一 WebViewController
|
||||
Future<WebViewController> getController(String url) async {
|
||||
if (_webViewController != null) return _webViewController!;
|
||||
|
||||
_webViewController = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setNavigationDelegate(
|
||||
// ⭐ 加上加载监听(BoardDialog 再 listen 一次也没关系)
|
||||
NavigationDelegate(
|
||||
onPageStarted: (_) {},
|
||||
onPageFinished: (_) {},
|
||||
),
|
||||
)
|
||||
..loadRequest(Uri.parse(url));
|
||||
|
||||
return _webViewController!;
|
||||
}
|
||||
|
||||
///打开白板
|
||||
/// -[uid] 用户名+id
|
||||
/// -[roomId] 房间id
|
||||
/// -[isTeacher] 是否是老师
|
||||
Future<void> showBoardDialog(
|
||||
BuildContext context, {
|
||||
required String uid,
|
||||
required int roomId,
|
||||
required bool isTeacher,
|
||||
}) async {
|
||||
String url = await buildUrl(
|
||||
uid: uid,
|
||||
roomId: roomId,
|
||||
isTeacher: isTeacher,
|
||||
);
|
||||
final controller = await getController(url);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => BoardDialog(controller: controller),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:app/config/theme/base/app_theme_ext.dart';
|
||||
import 'package:app/global/theme/base/app_theme_ext.dart';
|
||||
import 'package:app/utils/transfer/upload.dart';
|
||||
import 'package:app/widgets/base/actionSheet/action_sheet.dart';
|
||||
import 'package:app/widgets/base/actionSheet/type.dart';
|
||||
@@ -150,7 +150,7 @@ class _FileDrawerState extends State<FileDrawer> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${widget.name ?? ""}上传文件列表",
|
||||
"${widget.name ?? ""}文件列表",
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
Expanded(
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 举手按钮
|
||||
class HandRaiseButton extends StatelessWidget {
|
||||
final void Function() onTap;
|
||||
|
||||
const HandRaiseButton({super.key, required this.onTap});
|
||||
|
||||
@override
|
||||
@@ -24,3 +26,41 @@ class HandRaiseButton extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
///topBar的操作按钮
|
||||
class ActionButton extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String text;
|
||||
final Color? color;
|
||||
final void Function()? onTap;
|
||||
|
||||
const ActionButton({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.text,
|
||||
this.color,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
margin: EdgeInsets.only(right: 15),
|
||||
decoration: BoxDecoration(
|
||||
color: color ?? Color(0xff4a4f4f),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 16),
|
||||
SizedBox(width: 8),
|
||||
Text(text, style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user