| 
									
										
										
										
											2022-09-15 17:41:10 +08:00
										 |  |  | // original cm window in Sciter version.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  | import 'dart:async'; | 
					
						
							| 
									
										
										
										
											2023-02-10 21:18:55 +08:00
										 |  |  | import 'dart:io'; | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-06 11:18:12 +08:00
										 |  |  | import 'package:flutter_hbb/consts.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-22 20:18:31 +08:00
										 |  |  | import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; | 
					
						
							|  |  |  | import 'package:flutter_hbb/models/chat_model.dart'; | 
					
						
							| 
									
										
										
										
											2023-02-10 21:18:55 +08:00
										 |  |  | import 'package:flutter_hbb/utils/platform_channel.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  | import 'package:get/get.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  | import 'package:provider/provider.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  | import 'package:window_manager/window_manager.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-27 18:34:05 +08:00
										 |  |  | import 'package:flutter_svg/flutter_svg.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import '../../common.dart'; | 
					
						
							| 
									
										
										
										
											2022-10-25 21:36:01 +09:00
										 |  |  | import '../../common/widgets/chat_page.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  | import '../../models/platform_model.dart'; | 
					
						
							|  |  |  | import '../../models/server_model.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  | class DesktopServerPage extends StatefulWidget { | 
					
						
							| 
									
										
										
										
											2022-09-06 02:08:59 -07:00
										 |  |  |   const DesktopServerPage({Key? key}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-09-06 02:08:59 -07:00
										 |  |  |   State<DesktopServerPage> createState() => _DesktopServerPageState(); | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  | class _DesktopServerPageState extends State<DesktopServerPage> | 
					
						
							| 
									
										
										
										
											2022-08-23 21:28:44 +08:00
										 |  |  |     with WindowListener, AutomaticKeepAliveClientMixin { | 
					
						
							| 
									
										
										
										
											2022-09-01 21:18:53 +08:00
										 |  |  |   final tabController = gFFI.serverModel.tabController; | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |   void initState() { | 
					
						
							|  |  |  |     gFFI.ffiModel.updateEventListener(""); | 
					
						
							| 
									
										
										
										
											2022-08-23 21:28:44 +08:00
										 |  |  |     windowManager.addListener(this); | 
					
						
							| 
									
										
										
										
											2023-01-23 22:07:50 +08:00
										 |  |  |     tabController.onRemoved = (_, id) { | 
					
						
							|  |  |  |       onRemoveId(id); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     tabController.onSelected = (_, id) { | 
					
						
							|  |  |  |       windowManager.setTitle(getWindowNameWithId(id)); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |     super.initState(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-23 21:28:44 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     windowManager.removeListener(this); | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void onWindowClose() { | 
					
						
							| 
									
										
										
										
											2023-02-10 21:18:55 +08:00
										 |  |  |     Future.wait([ | 
					
						
							|  |  |  |       gFFI.serverModel.closeAll(), | 
					
						
							|  |  |  |       gFFI.close() | 
					
						
							|  |  |  |     ]).then((_)  { | 
					
						
							|  |  |  |       if (Platform.isMacOS) { | 
					
						
							|  |  |  |         RdPlatformChannel.instance.terminate(); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         windowManager.setPreventClose(false); | 
					
						
							|  |  |  |         windowManager.close(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2022-08-23 21:28:44 +08:00
										 |  |  |     super.onWindowClose(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-01 21:18:53 +08:00
										 |  |  |   void onRemoveId(String id) { | 
					
						
							|  |  |  |     if (tabController.state.value.tabs.isEmpty) { | 
					
						
							|  |  |  |       windowManager.close(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  |     super.build(context); | 
					
						
							| 
									
										
										
										
											2022-08-22 20:18:31 +08:00
										 |  |  |     return MultiProvider( | 
					
						
							|  |  |  |         providers: [ | 
					
						
							|  |  |  |           ChangeNotifierProvider.value(value: gFFI.serverModel), | 
					
						
							|  |  |  |           ChangeNotifierProvider.value(value: gFFI.chatModel), | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  |         child: Consumer<ServerModel>( | 
					
						
							| 
									
										
										
										
											2022-08-22 17:58:48 +08:00
										 |  |  |             builder: (context, serverModel, child) => Container( | 
					
						
							| 
									
										
										
										
											2023-02-08 21:54:48 +09:00
										 |  |  |                 decoration: BoxDecoration( | 
					
						
							|  |  |  |                     border: Border.all(color: MyTheme.color(context).border!)), | 
					
						
							|  |  |  |                 child: Scaffold( | 
					
						
							|  |  |  |                   backgroundColor: Theme.of(context).backgroundColor, | 
					
						
							|  |  |  |                   body: Center( | 
					
						
							|  |  |  |                     child: Column( | 
					
						
							|  |  |  |                       mainAxisAlignment: MainAxisAlignment.start, | 
					
						
							|  |  |  |                       children: [ | 
					
						
							|  |  |  |                         Expanded(child: ConnectionManager()), | 
					
						
							|  |  |  |                       ], | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 )))); | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   bool get wantKeepAlive => true; | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 20:18:31 +08:00
										 |  |  | class ConnectionManager extends StatefulWidget { | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   State<StatefulWidget> createState() => ConnectionManagerState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ConnectionManagerState extends State<ConnectionManager> { | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     gFFI.serverModel.updateClientState(); | 
					
						
							| 
									
										
										
										
											2022-10-27 10:56:14 +08:00
										 |  |  |     gFFI.serverModel.tabController.onSelected = (index, _) => | 
					
						
							| 
									
										
										
										
											2022-08-24 21:52:21 +08:00
										 |  |  |         gFFI.chatModel.changeCurrentID(gFFI.serverModel.clients[index].id); | 
					
						
							| 
									
										
										
										
											2022-11-04 21:43:51 +08:00
										 |  |  |     gFFI.chatModel.isConnManager = true; | 
					
						
							| 
									
										
										
										
											2022-08-22 20:18:31 +08:00
										 |  |  |     super.initState(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     final serverModel = Provider.of<ServerModel>(context); | 
					
						
							| 
									
										
										
										
											2022-11-23 14:23:57 +08:00
										 |  |  |     pointerHandler(PointerEvent e) { | 
					
						
							|  |  |  |       if (serverModel.cmHiddenTimer != null) { | 
					
						
							|  |  |  |         serverModel.cmHiddenTimer!.cancel(); | 
					
						
							|  |  |  |         serverModel.cmHiddenTimer = null; | 
					
						
							|  |  |  |         debugPrint("CM hidden timer has been canceled"); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  |     return serverModel.clients.isEmpty | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  |         ? Column( | 
					
						
							|  |  |  |             children: [ | 
					
						
							| 
									
										
										
										
											2022-09-06 11:18:12 +08:00
										 |  |  |               buildTitleBar(), | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  |               Expanded( | 
					
						
							|  |  |  |                 child: Center( | 
					
						
							|  |  |  |                   child: Text(translate("Waiting")), | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             ], | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  |           ) | 
					
						
							| 
									
										
										
										
											2022-10-26 21:39:28 +09:00
										 |  |  |         : Listener( | 
					
						
							|  |  |  |             onPointerDown: pointerHandler, | 
					
						
							|  |  |  |             onPointerMove: pointerHandler, | 
					
						
							|  |  |  |             child: DesktopTab( | 
					
						
							|  |  |  |                 showTitle: false, | 
					
						
							|  |  |  |                 showMaximize: false, | 
					
						
							|  |  |  |                 showMinimize: true, | 
					
						
							|  |  |  |                 showClose: true, | 
					
						
							| 
									
										
										
										
											2022-11-06 21:21:57 +08:00
										 |  |  |                 onWindowCloseButton: handleWindowCloseButton, | 
					
						
							| 
									
										
										
										
											2022-10-26 21:39:28 +09:00
										 |  |  |                 controller: serverModel.tabController, | 
					
						
							|  |  |  |                 maxLabelWidth: 100, | 
					
						
							|  |  |  |                 tail: buildScrollJumper(), | 
					
						
							|  |  |  |                 selectedTabBackgroundColor: | 
					
						
							|  |  |  |                     Theme.of(context).hintColor.withOpacity(0.2), | 
					
						
							|  |  |  |                 tabBuilder: (key, icon, label, themeConf) { | 
					
						
							| 
									
										
										
										
											2022-10-26 23:50:36 +09:00
										 |  |  |                   final client = serverModel.clients.firstWhereOrNull( | 
					
						
							|  |  |  |                       (client) => client.id.toString() == key); | 
					
						
							| 
									
										
										
										
											2022-10-26 21:39:28 +09:00
										 |  |  |                   return Row( | 
					
						
							|  |  |  |                     mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |                     children: [ | 
					
						
							|  |  |  |                       Tooltip( | 
					
						
							|  |  |  |                           message: key, | 
					
						
							|  |  |  |                           waitDuration: Duration(seconds: 1), | 
					
						
							|  |  |  |                           child: label), | 
					
						
							| 
									
										
										
										
											2022-10-26 23:50:36 +09:00
										 |  |  |                       Obx(() => Offstage( | 
					
						
							|  |  |  |                           offstage: | 
					
						
							|  |  |  |                               !(client?.hasUnreadChatMessage.value ?? false), | 
					
						
							|  |  |  |                           child: | 
					
						
							|  |  |  |                               Icon(Icons.circle, color: Colors.red, size: 10))) | 
					
						
							| 
									
										
										
										
											2022-10-26 21:39:28 +09:00
										 |  |  |                     ], | 
					
						
							|  |  |  |                   ); | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 pageViewBuilder: (pageView) => Row(children: [ | 
					
						
							|  |  |  |                       Expanded(child: pageView), | 
					
						
							|  |  |  |                       Consumer<ChatModel>( | 
					
						
							| 
									
										
										
										
											2022-11-04 21:43:51 +08:00
										 |  |  |                           builder: (_, model, child) => model.isShowCMChatPage | 
					
						
							| 
									
										
										
										
											2022-10-26 21:39:28 +09:00
										 |  |  |                               ? Expanded(child: Scaffold(body: ChatPage())) | 
					
						
							|  |  |  |                               : Offstage()) | 
					
						
							|  |  |  |                     ]))); | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-06 11:18:12 +08:00
										 |  |  |   Widget buildTitleBar() { | 
					
						
							|  |  |  |     return SizedBox( | 
					
						
							|  |  |  |       height: kDesktopRemoteTabBarHeight, | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  |       child: Row( | 
					
						
							|  |  |  |         crossAxisAlignment: CrossAxisAlignment.center, | 
					
						
							|  |  |  |         children: [ | 
					
						
							| 
									
										
										
										
											2022-09-06 11:18:12 +08:00
										 |  |  |           const _AppIcon(), | 
					
						
							|  |  |  |           Expanded( | 
					
						
							|  |  |  |             child: GestureDetector( | 
					
						
							|  |  |  |               onPanStart: (d) { | 
					
						
							|  |  |  |                 windowManager.startDragging(); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               child: Container( | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |                 color: Theme.of(context).backgroundColor, | 
					
						
							| 
									
										
										
										
											2022-09-06 11:18:12 +08:00
										 |  |  |               ), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ), | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  |           const SizedBox( | 
					
						
							|  |  |  |             width: 4.0, | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |           ), | 
					
						
							| 
									
										
										
										
											2022-09-06 11:18:12 +08:00
										 |  |  |           const _CloseButton() | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |         ], | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-10-20 23:22:02 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Widget buildScrollJumper() { | 
					
						
							|  |  |  |     final offstage = gFFI.serverModel.clients.length < 2; | 
					
						
							|  |  |  |     final sc = gFFI.serverModel.tabController.state.value.scrollController; | 
					
						
							|  |  |  |     return Offstage( | 
					
						
							|  |  |  |         offstage: offstage, | 
					
						
							|  |  |  |         child: Row( | 
					
						
							|  |  |  |           children: [ | 
					
						
							|  |  |  |             ActionIcon( | 
					
						
							|  |  |  |                 icon: Icons.arrow_left, iconSize: 22, onTap: sc.backward), | 
					
						
							|  |  |  |             ActionIcon( | 
					
						
							|  |  |  |                 icon: Icons.arrow_right, iconSize: 22, onTap: sc.forward), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-11-06 21:21:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Future<bool> handleWindowCloseButton() async { | 
					
						
							|  |  |  |     var tabController = gFFI.serverModel.tabController; | 
					
						
							|  |  |  |     final connLength = tabController.length; | 
					
						
							|  |  |  |     if (connLength <= 1) { | 
					
						
							|  |  |  |       windowManager.close(); | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       final opt = "enable-confirm-closing-tabs"; | 
					
						
							|  |  |  |       final bool res; | 
					
						
							|  |  |  |       if (!option2bool(opt, await bind.mainGetOption(key: opt))) { | 
					
						
							|  |  |  |         res = true; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         res = await closeConfirmDialog(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (res) { | 
					
						
							|  |  |  |         windowManager.close(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return res; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 21:52:21 +08:00
										 |  |  | Widget buildConnectionCard(Client client) { | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |   return Consumer<ServerModel>( | 
					
						
							|  |  |  |       builder: (context, value, child) => Column( | 
					
						
							|  |  |  |             mainAxisAlignment: MainAxisAlignment.start, | 
					
						
							|  |  |  |             crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |             key: ValueKey(client.id), | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |               _CmHeader(client: client), | 
					
						
							| 
									
										
										
										
											2022-12-04 18:47:02 +08:00
										 |  |  |               client.type_() != ClientType.remote || client.disconnected | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |                   ? Offstage() | 
					
						
							|  |  |  |                   : _PrivilegeBoard(client: client), | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                   child: Align( | 
					
						
							|  |  |  |                 alignment: Alignment.bottomCenter, | 
					
						
							|  |  |  |                 child: _CmControlPanel(client: client), | 
					
						
							|  |  |  |               )) | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           ).paddingSymmetric(vertical: 8.0, horizontal: 8.0)); | 
					
						
							| 
									
										
										
										
											2022-08-24 21:52:21 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  | class _AppIcon extends StatelessWidget { | 
					
						
							|  |  |  |   const _AppIcon({Key? key}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return Container( | 
					
						
							|  |  |  |       margin: EdgeInsets.symmetric(horizontal: 4.0), | 
					
						
							| 
									
										
										
										
											2022-09-27 18:34:05 +08:00
										 |  |  |       child: SvgPicture.asset( | 
					
						
							|  |  |  |         'assets/logo.svg', | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  |         width: 30, | 
					
						
							|  |  |  |         height: 30, | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _CloseButton extends StatelessWidget { | 
					
						
							|  |  |  |   const _CloseButton({Key? key}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-09-06 11:18:12 +08:00
										 |  |  |     return IconButton( | 
					
						
							|  |  |  |       onPressed: () { | 
					
						
							|  |  |  |         windowManager.close(); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       icon: const Icon( | 
					
						
							|  |  |  |         IconFont.close, | 
					
						
							|  |  |  |         size: 18, | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |       splashColor: Colors.transparent, | 
					
						
							|  |  |  |       hoverColor: Colors.transparent, | 
					
						
							| 
									
										
										
										
											2022-08-18 11:07:53 +08:00
										 |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  | class _CmHeader extends StatefulWidget { | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |   final Client client; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const _CmHeader({Key? key, required this.client}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   State<_CmHeader> createState() => _CmHeaderState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _CmHeaderState extends State<_CmHeader> | 
					
						
							|  |  |  |     with AutomaticKeepAliveClientMixin { | 
					
						
							|  |  |  |   Client get client => widget.client; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |   final _time = 0.obs; | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  |   Timer? _timer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							|  |  |  |     _timer = Timer.periodic(Duration(seconds: 1), (_) { | 
					
						
							| 
									
										
										
										
											2022-11-21 18:45:36 +08:00
										 |  |  |       if (client.authorized && !client.disconnected) { | 
					
						
							|  |  |  |         _time.value = _time.value + 1; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     _timer?.cancel(); | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  |     super.build(context); | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |     return Row( | 
					
						
							|  |  |  |       crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |       children: [ | 
					
						
							|  |  |  |         // icon
 | 
					
						
							|  |  |  |         Container( | 
					
						
							| 
									
										
										
										
											2022-08-19 19:17:45 +08:00
										 |  |  |           width: 90, | 
					
						
							|  |  |  |           height: 90, | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |           alignment: Alignment.center, | 
					
						
							|  |  |  |           decoration: BoxDecoration(color: str2color(client.name)), | 
					
						
							|  |  |  |           child: Text( | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |             client.name[0], | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |             style: TextStyle( | 
					
						
							| 
									
										
										
										
											2022-08-19 19:17:45 +08:00
										 |  |  |                 fontWeight: FontWeight.bold, color: Colors.white, fontSize: 65), | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |           ), | 
					
						
							|  |  |  |         ).marginOnly(left: 4.0, right: 8.0), | 
					
						
							|  |  |  |         Expanded( | 
					
						
							|  |  |  |           child: Column( | 
					
						
							|  |  |  |             mainAxisAlignment: MainAxisAlignment.start, | 
					
						
							|  |  |  |             crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |             children: [ | 
					
						
							| 
									
										
										
										
											2022-08-19 19:17:45 +08:00
										 |  |  |               FittedBox( | 
					
						
							|  |  |  |                   child: Text( | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |                 client.name, | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |                 style: TextStyle( | 
					
						
							|  |  |  |                   color: MyTheme.cmIdColor, | 
					
						
							|  |  |  |                   fontWeight: FontWeight.bold, | 
					
						
							|  |  |  |                   fontSize: 20, | 
					
						
							|  |  |  |                   overflow: TextOverflow.ellipsis, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 maxLines: 1, | 
					
						
							| 
									
										
										
										
											2022-08-19 19:17:45 +08:00
										 |  |  |               )), | 
					
						
							|  |  |  |               FittedBox( | 
					
						
							|  |  |  |                   child: Text("(${client.peerId})", | 
					
						
							|  |  |  |                       style: | 
					
						
							|  |  |  |                           TextStyle(color: MyTheme.cmIdColor, fontSize: 14))), | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |               SizedBox( | 
					
						
							|  |  |  |                 height: 16.0, | 
					
						
							|  |  |  |               ), | 
					
						
							| 
									
										
										
										
											2022-08-19 19:17:45 +08:00
										 |  |  |               FittedBox( | 
					
						
							|  |  |  |                   child: Row( | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  |                 children: [ | 
					
						
							| 
									
										
										
										
											2022-11-21 18:45:36 +08:00
										 |  |  |                   Text(client.authorized | 
					
						
							|  |  |  |                           ? client.disconnected | 
					
						
							|  |  |  |                               ? translate("Disconnected") | 
					
						
							|  |  |  |                               : translate("Connected") | 
					
						
							|  |  |  |                           : "${translate("Request access to your device")}...") | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |                       .marginOnly(right: 8.0), | 
					
						
							| 
									
										
										
										
											2022-11-21 18:45:36 +08:00
										 |  |  |                   if (client.authorized) | 
					
						
							|  |  |  |                     Obx(() => Text( | 
					
						
							|  |  |  |                         formatDurationToTime(Duration(seconds: _time.value)))) | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  |                 ], | 
					
						
							| 
									
										
										
										
											2022-08-19 19:17:45 +08:00
										 |  |  |               )) | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |             ], | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |         Offstage( | 
					
						
							| 
									
										
										
										
											2022-12-04 18:47:02 +08:00
										 |  |  |           offstage: !client.authorized || client.type_() != ClientType.remote, | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |           child: IconButton( | 
					
						
							| 
									
										
										
										
											2022-10-26 21:13:32 +09:00
										 |  |  |               onPressed: () => checkClickTime( | 
					
						
							|  |  |  |                   client.id, () => gFFI.chatModel.toggleCMChatPage(client.id)), | 
					
						
							|  |  |  |               icon: Icon(Icons.message_outlined), | 
					
						
							|  |  |  |               splashRadius: kDesktopIconButtonSplashRadius), | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |       ], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 00:34:04 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   bool get wantKeepAlive => true; | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  | class _PrivilegeBoard extends StatefulWidget { | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |   final Client client; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const _PrivilegeBoard({Key? key, required this.client}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   State<StatefulWidget> createState() => _PrivilegeBoardState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _PrivilegeBoardState extends State<_PrivilegeBoard> { | 
					
						
							|  |  |  |   late final client = widget.client; | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |   Widget buildPermissionIcon( | 
					
						
							|  |  |  |       bool enabled, ImageProvider icon, Function(bool)? onTap, String tooltip) { | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |     return Tooltip( | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |       message: tooltip, | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |       child: Ink( | 
					
						
							|  |  |  |         decoration: | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |             BoxDecoration(color: enabled ? MyTheme.accent80 : Colors.grey), | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |         padding: EdgeInsets.all(4.0), | 
					
						
							|  |  |  |         child: InkWell( | 
					
						
							| 
									
										
										
										
											2022-08-30 16:50:25 +08:00
										 |  |  |           onTap: () => | 
					
						
							|  |  |  |               checkClickTime(widget.client.id, () => onTap?.call(!enabled)), | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |           child: Image( | 
					
						
							|  |  |  |             image: icon, | 
					
						
							|  |  |  |             width: 50, | 
					
						
							|  |  |  |             height: 50, | 
					
						
							|  |  |  |             fit: BoxFit.scaleDown, | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ).marginSymmetric(horizontal: 4.0), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return Container( | 
					
						
							|  |  |  |       margin: EdgeInsets.only(top: 16.0, bottom: 8.0), | 
					
						
							|  |  |  |       child: Column( | 
					
						
							|  |  |  |         crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |         children: [ | 
					
						
							|  |  |  |           Text( | 
					
						
							|  |  |  |             translate("Permissions"), | 
					
						
							|  |  |  |             style: TextStyle(fontSize: 16), | 
					
						
							|  |  |  |           ).marginOnly(left: 4.0), | 
					
						
							|  |  |  |           SizedBox( | 
					
						
							|  |  |  |             height: 8.0, | 
					
						
							|  |  |  |           ), | 
					
						
							| 
									
										
										
										
											2022-08-19 19:17:45 +08:00
										 |  |  |           FittedBox( | 
					
						
							|  |  |  |               child: Row( | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |             children: [ | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |               buildPermissionIcon(client.keyboard, iconKeyboard, (enabled) { | 
					
						
							|  |  |  |                 bind.cmSwitchPermission( | 
					
						
							|  |  |  |                     connId: client.id, name: "keyboard", enabled: enabled); | 
					
						
							|  |  |  |                 setState(() { | 
					
						
							|  |  |  |                   client.keyboard = enabled; | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |               }, translate('Allow using keyboard and mouse')), | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |               buildPermissionIcon(client.clipboard, iconClipboard, (enabled) { | 
					
						
							|  |  |  |                 bind.cmSwitchPermission( | 
					
						
							|  |  |  |                     connId: client.id, name: "clipboard", enabled: enabled); | 
					
						
							|  |  |  |                 setState(() { | 
					
						
							|  |  |  |                   client.clipboard = enabled; | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |               }, translate('Allow using clipboard')), | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |               buildPermissionIcon(client.audio, iconAudio, (enabled) { | 
					
						
							|  |  |  |                 bind.cmSwitchPermission( | 
					
						
							|  |  |  |                     connId: client.id, name: "audio", enabled: enabled); | 
					
						
							|  |  |  |                 setState(() { | 
					
						
							|  |  |  |                   client.audio = enabled; | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |               }, translate('Allow hearing sound')), | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |               buildPermissionIcon(client.file, iconFile, (enabled) { | 
					
						
							|  |  |  |                 bind.cmSwitchPermission( | 
					
						
							|  |  |  |                     connId: client.id, name: "file", enabled: enabled); | 
					
						
							|  |  |  |                 setState(() { | 
					
						
							|  |  |  |                   client.file = enabled; | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |               }, translate('Allow file copy and paste')), | 
					
						
							| 
									
										
										
										
											2022-08-18 19:49:41 +08:00
										 |  |  |               buildPermissionIcon(client.restart, iconRestart, (enabled) { | 
					
						
							|  |  |  |                 bind.cmSwitchPermission( | 
					
						
							|  |  |  |                     connId: client.id, name: "restart", enabled: enabled); | 
					
						
							|  |  |  |                 setState(() { | 
					
						
							|  |  |  |                   client.restart = enabled; | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2022-10-04 18:20:23 +08:00
										 |  |  |               }, translate('Allow remote restart')), | 
					
						
							| 
									
										
										
										
											2022-09-22 09:55:34 +08:00
										 |  |  |               buildPermissionIcon(client.recording, iconRecording, (enabled) { | 
					
						
							|  |  |  |                 bind.cmSwitchPermission( | 
					
						
							|  |  |  |                     connId: client.id, name: "recording", enabled: enabled); | 
					
						
							|  |  |  |                 setState(() { | 
					
						
							|  |  |  |                   client.recording = enabled; | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2022-10-11 09:59:27 +09:00
										 |  |  |               }, translate('Allow recording session')) | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |             ], | 
					
						
							| 
									
										
										
										
											2022-08-19 19:17:45 +08:00
										 |  |  |           )), | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |         ], | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2022-08-11 18:59:26 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  | const double bigMargin = 15; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  | class _CmControlPanel extends StatelessWidget { | 
					
						
							|  |  |  |   final Client client; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const _CmControlPanel({Key? key, required this.client}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |     return client.authorized | 
					
						
							|  |  |  |         ? client.disconnected | 
					
						
							|  |  |  |             ? buildDisconnected(context) | 
					
						
							|  |  |  |             : buildAuthorized(context) | 
					
						
							|  |  |  |         : buildUnAuthorized(context); | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  |   buildAuthorized(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-11-10 10:27:13 +08:00
										 |  |  |     final bool canElevate = bind.cmCanElevate(); | 
					
						
							|  |  |  |     final model = Provider.of<ServerModel>(context); | 
					
						
							| 
									
										
										
										
											2022-12-04 18:47:02 +08:00
										 |  |  |     final showElevation = canElevate && | 
					
						
							|  |  |  |         model.showElevation && | 
					
						
							|  |  |  |         client.type_() == ClientType.remote; | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |     return Column( | 
					
						
							|  |  |  |       mainAxisAlignment: MainAxisAlignment.end, | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |       children: [ | 
					
						
							| 
									
										
										
										
											2023-02-07 16:11:55 +08:00
										 |  |  |         Offstage( | 
					
						
							|  |  |  |           offstage: !client.inVoiceCall, | 
					
						
							|  |  |  |           child: buildButton(context, | 
					
						
							| 
									
										
										
										
											2023-02-07 17:09:36 +08:00
										 |  |  |               color: Colors.red, | 
					
						
							| 
									
										
										
										
											2023-02-07 16:11:55 +08:00
										 |  |  |               onClick: () => closeVoiceCall(), | 
					
						
							| 
									
										
										
										
											2023-02-07 17:16:06 +08:00
										 |  |  |               icon: Icon(Icons.phone_disabled_rounded, color: Colors.white), | 
					
						
							| 
									
										
										
										
											2023-02-07 16:11:55 +08:00
										 |  |  |               text: "Stop voice call", | 
					
						
							|  |  |  |               textColor: Colors.white), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         Offstage( | 
					
						
							|  |  |  |           offstage: !client.incomingVoiceCall, | 
					
						
							|  |  |  |           child: Row( | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                 child: buildButton(context, | 
					
						
							|  |  |  |                     color: MyTheme.accent, | 
					
						
							|  |  |  |                     onClick: () => handleVoiceCall(true), | 
					
						
							| 
									
										
										
										
											2023-02-07 17:09:36 +08:00
										 |  |  |                     icon: Icon(Icons.phone_enabled, color: Colors.white), | 
					
						
							| 
									
										
										
										
											2023-02-07 16:11:55 +08:00
										 |  |  |                     text: "Accept", | 
					
						
							|  |  |  |                     textColor: Colors.white), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                 child: buildButton(context, | 
					
						
							|  |  |  |                     color: Colors.red, | 
					
						
							|  |  |  |                     onClick: () => handleVoiceCall(false), | 
					
						
							| 
									
										
										
										
											2023-02-07 17:09:36 +08:00
										 |  |  |                     icon: | 
					
						
							|  |  |  |                         Icon(Icons.phone_disabled_rounded, color: Colors.white), | 
					
						
							| 
									
										
										
										
											2023-02-07 17:16:06 +08:00
										 |  |  |                     text: "Dismiss", | 
					
						
							| 
									
										
										
										
											2023-02-07 16:11:55 +08:00
										 |  |  |                     textColor: Colors.white), | 
					
						
							|  |  |  |               ) | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2023-01-17 13:28:33 +08:00
										 |  |  |         Offstage( | 
					
						
							|  |  |  |           offstage: !client.fromSwitch, | 
					
						
							|  |  |  |           child: buildButton(context, | 
					
						
							|  |  |  |               color: Colors.purple, | 
					
						
							|  |  |  |               onClick: () => handleSwitchBack(context), | 
					
						
							|  |  |  |               icon: Icon(Icons.reply, color: Colors.white), | 
					
						
							|  |  |  |               text: "Switch Sides", | 
					
						
							|  |  |  |               textColor: Colors.white), | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-11-10 10:27:13 +08:00
										 |  |  |         Offstage( | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |           offstage: !showElevation, | 
					
						
							|  |  |  |           child: buildButton(context, color: Colors.green[700], onClick: () { | 
					
						
							|  |  |  |             handleElevate(context); | 
					
						
							|  |  |  |             windowManager.minimize(); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |               icon: Icon( | 
					
						
							|  |  |  |                 Icons.security_sharp, | 
					
						
							|  |  |  |                 color: Colors.white, | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |               text: 'Elevate', | 
					
						
							|  |  |  |               textColor: Colors.white), | 
					
						
							| 
									
										
										
										
											2022-11-10 10:27:13 +08:00
										 |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |         Row( | 
					
						
							|  |  |  |           children: [ | 
					
						
							|  |  |  |             Expanded( | 
					
						
							|  |  |  |                 child: buildButton(context, | 
					
						
							|  |  |  |                     color: Colors.redAccent, | 
					
						
							|  |  |  |                     onClick: handleDisconnect, | 
					
						
							|  |  |  |                     text: 'Disconnect', | 
					
						
							|  |  |  |                     textColor: Colors.white)), | 
					
						
							|  |  |  |           ], | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |         ) | 
					
						
							|  |  |  |       ], | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |     ) | 
					
						
							|  |  |  |         .marginOnly(bottom: showElevation ? 0 : bigMargin) | 
					
						
							|  |  |  |         .marginSymmetric(horizontal: showElevation ? 0 : bigMargin); | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |   buildDisconnected(BuildContext context) { | 
					
						
							|  |  |  |     return Row( | 
					
						
							|  |  |  |       mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |       children: [ | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |         Expanded( | 
					
						
							|  |  |  |             child: buildButton(context, | 
					
						
							|  |  |  |                 color: MyTheme.accent, | 
					
						
							|  |  |  |                 onClick: handleClose, | 
					
						
							|  |  |  |                 text: 'Close', | 
					
						
							|  |  |  |                 textColor: Colors.white)), | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |       ], | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |     ).marginOnly(bottom: 15).marginSymmetric(horizontal: bigMargin); | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  |   buildUnAuthorized(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-11-10 10:27:13 +08:00
										 |  |  |     final bool canElevate = bind.cmCanElevate(); | 
					
						
							|  |  |  |     final model = Provider.of<ServerModel>(context); | 
					
						
							| 
									
										
										
										
											2022-12-04 18:47:02 +08:00
										 |  |  |     final showElevation = canElevate && | 
					
						
							|  |  |  |         model.showElevation && | 
					
						
							|  |  |  |         client.type_() == ClientType.remote; | 
					
						
							| 
									
										
										
										
											2022-11-20 15:53:08 +08:00
										 |  |  |     final showAccept = model.approveMode != 'password'; | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |     return Column( | 
					
						
							|  |  |  |       mainAxisAlignment: MainAxisAlignment.end, | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |       children: [ | 
					
						
							| 
									
										
										
										
											2022-11-10 10:27:13 +08:00
										 |  |  |         Offstage( | 
					
						
							| 
									
										
										
										
											2022-11-20 15:53:08 +08:00
										 |  |  |           offstage: !showElevation || !showAccept, | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |           child: buildButton(context, color: Colors.green[700], onClick: () { | 
					
						
							|  |  |  |             handleAccept(context); | 
					
						
							|  |  |  |             handleElevate(context); | 
					
						
							|  |  |  |             windowManager.minimize(); | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |               text: 'Accept', | 
					
						
							|  |  |  |               icon: Icon( | 
					
						
							|  |  |  |                 Icons.security_sharp, | 
					
						
							|  |  |  |                 color: Colors.white, | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |               textColor: Colors.white), | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |         Row( | 
					
						
							|  |  |  |           mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |           children: [ | 
					
						
							| 
									
										
										
										
											2022-11-20 15:53:08 +08:00
										 |  |  |             if (showAccept) | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                 child: Column( | 
					
						
							|  |  |  |                   children: [ | 
					
						
							|  |  |  |                     buildButton(context, color: MyTheme.accent, onClick: () { | 
					
						
							|  |  |  |                       handleAccept(context); | 
					
						
							|  |  |  |                       windowManager.minimize(); | 
					
						
							|  |  |  |                     }, text: 'Accept', textColor: Colors.white), | 
					
						
							|  |  |  |                   ], | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |               ), | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |             Expanded( | 
					
						
							|  |  |  |                 child: buildButton(context, | 
					
						
							|  |  |  |                     color: Colors.transparent, | 
					
						
							|  |  |  |                     border: Border.all(color: Colors.grey), | 
					
						
							|  |  |  |                     onClick: handleDisconnect, | 
					
						
							|  |  |  |                     text: 'Cancel', | 
					
						
							|  |  |  |                     textColor: null)), | 
					
						
							|  |  |  |           ], | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |         ), | 
					
						
							|  |  |  |       ], | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |     ) | 
					
						
							|  |  |  |         .marginOnly(bottom: showElevation ? 0 : bigMargin) | 
					
						
							|  |  |  |         .marginSymmetric(horizontal: showElevation ? 0 : bigMargin); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-07 16:11:55 +08:00
										 |  |  |   Widget buildButton( | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |     BuildContext context, { | 
					
						
							|  |  |  |     required Color? color, | 
					
						
							|  |  |  |     required Function() onClick, | 
					
						
							|  |  |  |     Icon? icon, | 
					
						
							|  |  |  |     BoxBorder? border, | 
					
						
							|  |  |  |     required String text, | 
					
						
							|  |  |  |     required Color? textColor, | 
					
						
							|  |  |  |   }) { | 
					
						
							|  |  |  |     Widget textWidget; | 
					
						
							|  |  |  |     if (icon != null) { | 
					
						
							|  |  |  |       textWidget = Text( | 
					
						
							|  |  |  |         translate(text), | 
					
						
							|  |  |  |         style: TextStyle(color: textColor), | 
					
						
							|  |  |  |         textAlign: TextAlign.center, | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       textWidget = Expanded( | 
					
						
							|  |  |  |         child: Text( | 
					
						
							|  |  |  |           translate(text), | 
					
						
							|  |  |  |           style: TextStyle(color: textColor), | 
					
						
							|  |  |  |           textAlign: TextAlign.center, | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return Container( | 
					
						
							| 
									
										
										
										
											2022-11-20 15:53:08 +08:00
										 |  |  |       height: 30, | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |       decoration: BoxDecoration( | 
					
						
							|  |  |  |           color: color, borderRadius: BorderRadius.circular(4), border: border), | 
					
						
							|  |  |  |       child: InkWell( | 
					
						
							|  |  |  |           onTap: () => checkClickTime(client.id, onClick), | 
					
						
							|  |  |  |           child: Row( | 
					
						
							|  |  |  |             mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |               Offstage(offstage: icon == null, child: icon), | 
					
						
							|  |  |  |               textWidget, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           )), | 
					
						
							|  |  |  |     ).marginAll(4); | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |   void handleDisconnect() { | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  |     bind.cmCloseConnection(connId: client.id); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-17 21:46:56 +08:00
										 |  |  |   void handleAccept(BuildContext context) { | 
					
						
							|  |  |  |     final model = Provider.of<ServerModel>(context, listen: false); | 
					
						
							|  |  |  |     model.sendLoginResponse(client, true); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 10:27:13 +08:00
										 |  |  |   void handleElevate(BuildContext context) { | 
					
						
							|  |  |  |     final model = Provider.of<ServerModel>(context, listen: false); | 
					
						
							|  |  |  |     model.setShowElevation(false); | 
					
						
							|  |  |  |     bind.cmElevatePortable(connId: client.id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 17:06:27 +08:00
										 |  |  |   void handleClose() async { | 
					
						
							| 
									
										
										
										
											2022-10-08 20:15:02 +08:00
										 |  |  |     await bind.cmRemoveDisconnectedConnection(connId: client.id); | 
					
						
							|  |  |  |     if (await bind.cmGetClientsLength() == 0) { | 
					
						
							|  |  |  |       windowManager.close(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-01-17 13:28:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   void handleSwitchBack(BuildContext context) { | 
					
						
							|  |  |  |     bind.cmSwitchBack(connId: client.id); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-02-07 16:11:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   void handleVoiceCall(bool accept) { | 
					
						
							|  |  |  |     bind.cmHandleIncomingVoiceCall(id: client.id, accept: accept); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void closeVoiceCall() { | 
					
						
							|  |  |  |     bind.cmCloseVoiceCall(id: client.id); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-17 21:28:36 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-30 16:50:25 +08:00
										 |  |  | void checkClickTime(int id, Function() callback) async { | 
					
						
							|  |  |  |   var clickCallbackTime = DateTime.now().millisecondsSinceEpoch; | 
					
						
							|  |  |  |   await bind.cmCheckClickTime(connId: id); | 
					
						
							|  |  |  |   Timer(const Duration(milliseconds: 120), () async { | 
					
						
							|  |  |  |     var d = clickCallbackTime - await bind.cmGetClickTime(); | 
					
						
							|  |  |  |     if (d > 120) callback(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } |