| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'dart:convert'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 16:37:11 +08:00
										 |  |  | import 'package:desktop_multi_window/desktop_multi_window.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-28 22:04:10 +08:00
										 |  |  | import 'package:flutter_hbb/common.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-29 18:48:12 +08:00
										 |  |  | import 'package:flutter_hbb/common/shared_state.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-03 15:31:19 +08:00
										 |  |  | import 'package:flutter_hbb/consts.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'package:flutter_hbb/desktop/pages/remote_page.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-06 17:08:48 +08:00
										 |  |  | import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'package:flutter_hbb/utils/multi_window_manager.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-28 22:04:10 +08:00
										 |  |  | import 'package:get/get.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 19:26:55 +08:00
										 |  |  | import '../../mobile/widgets/dialog.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | class ConnectionTabPage extends StatefulWidget { | 
					
						
							|  |  |  |   final Map<String, dynamic> params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const ConnectionTabPage({Key? key, required this.params}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   State<ConnectionTabPage> createState() => _ConnectionTabPageState(params); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 10:54:09 +08:00
										 |  |  | class _ConnectionTabPageState extends State<ConnectionTabPage> { | 
					
						
							| 
									
										
										
										
											2022-09-01 21:18:53 +08:00
										 |  |  |   final tabController = | 
					
						
							|  |  |  |       Get.put(DesktopTabController(tabType: DesktopTabType.remoteScreen)); | 
					
						
							| 
									
										
										
										
											2022-08-29 18:48:12 +08:00
										 |  |  |   static const IconData selectedIcon = Icons.desktop_windows_sharp; | 
					
						
							|  |  |  |   static const IconData unselectedIcon = Icons.desktop_windows_outlined; | 
					
						
							| 
									
										
										
										
											2022-08-05 10:27:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   var connectionMap = RxList<Widget>.empty(growable: true); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   _ConnectionTabPageState(Map<String, dynamic> params) { | 
					
						
							| 
									
										
										
										
											2022-08-26 23:28:08 +08:00
										 |  |  |     final RxBool fullscreen = Get.find(tag: 'fullscreen'); | 
					
						
							| 
									
										
										
										
											2022-08-29 22:46:19 +08:00
										 |  |  |     final peerId = params['id']; | 
					
						
							|  |  |  |     if (peerId != null) { | 
					
						
							|  |  |  |       ConnectionTypeState.init(peerId); | 
					
						
							| 
									
										
										
										
											2022-08-26 12:14:14 +08:00
										 |  |  |       tabController.add(TabInfo( | 
					
						
							| 
									
										
										
										
											2022-08-29 22:46:19 +08:00
										 |  |  |           key: peerId, | 
					
						
							|  |  |  |           label: peerId, | 
					
						
							| 
									
										
										
										
											2022-08-18 10:54:09 +08:00
										 |  |  |           selectedIcon: selectedIcon, | 
					
						
							| 
									
										
										
										
											2022-08-24 20:56:42 +08:00
										 |  |  |           unselectedIcon: unselectedIcon, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:03:20 +08:00
										 |  |  |           onTabCloseButton: () => handleTabCloseButton(peerId), | 
					
						
							| 
									
										
										
										
											2022-09-08 20:43:27 +08:00
										 |  |  |           page: RemotePage( | 
					
						
							|  |  |  |             key: ValueKey(peerId), | 
					
						
							|  |  |  |             id: peerId, | 
					
						
							|  |  |  |             tabBarHeight: fullscreen.isTrue ? 0 : kDesktopRemoteTabBarHeight, | 
					
						
							|  |  |  |           ))); | 
					
						
							| 
									
										
										
										
											2022-05-31 16:27:54 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							| 
									
										
										
										
											2022-08-24 20:56:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     tabController.onRemove = (_, id) => onRemoveId(id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |     rustDeskWinManager.setMethodHandler((call, fromWindowId) async { | 
					
						
							|  |  |  |       print( | 
					
						
							|  |  |  |           "call ${call.method} with args ${call.arguments} from window ${fromWindowId}"); | 
					
						
							| 
									
										
										
										
											2022-08-26 23:28:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       final RxBool fullscreen = Get.find(tag: 'fullscreen'); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |       // for simplify, just replace connectionId
 | 
					
						
							|  |  |  |       if (call.method == "new_remote_desktop") { | 
					
						
							| 
									
										
										
										
											2022-08-05 10:27:06 +08:00
										 |  |  |         final args = jsonDecode(call.arguments); | 
					
						
							|  |  |  |         final id = args['id']; | 
					
						
							| 
									
										
										
										
											2022-09-01 21:18:53 +08:00
										 |  |  |         ConnectionTypeState.init(id); | 
					
						
							| 
									
										
										
										
											2022-08-09 19:32:19 +08:00
										 |  |  |         window_on_top(windowId()); | 
					
						
							| 
									
										
										
										
											2022-08-31 18:41:55 +08:00
										 |  |  |         ConnectionTypeState.init(id); | 
					
						
							| 
									
										
										
										
											2022-08-24 20:56:42 +08:00
										 |  |  |         tabController.add(TabInfo( | 
					
						
							|  |  |  |             key: id, | 
					
						
							|  |  |  |             label: id, | 
					
						
							|  |  |  |             selectedIcon: selectedIcon, | 
					
						
							|  |  |  |             unselectedIcon: unselectedIcon, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:03:20 +08:00
										 |  |  |             onTabCloseButton: () => handleTabCloseButton(id), | 
					
						
							| 
									
										
										
										
											2022-09-08 20:43:27 +08:00
										 |  |  |             page: RemotePage( | 
					
						
							|  |  |  |               key: ValueKey(id), | 
					
						
							|  |  |  |               id: id, | 
					
						
							|  |  |  |               tabBarHeight: fullscreen.isTrue ? 0 : kDesktopRemoteTabBarHeight, | 
					
						
							|  |  |  |             ))); | 
					
						
							| 
									
										
										
										
											2022-06-28 22:04:10 +08:00
										 |  |  |       } else if (call.method == "onDestroy") { | 
					
						
							| 
									
										
										
										
											2022-08-30 20:48:03 +08:00
										 |  |  |         tabController.clear(); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-08-26 23:28:08 +08:00
										 |  |  |     final RxBool fullscreen = Get.find(tag: 'fullscreen'); | 
					
						
							|  |  |  |     return Obx(() => SubWindowDragToResizeArea( | 
					
						
							|  |  |  |           resizeEdgeSize: fullscreen.value ? 1.0 : 8.0, | 
					
						
							|  |  |  |           windowId: windowId(), | 
					
						
							|  |  |  |           child: Container( | 
					
						
							|  |  |  |             decoration: BoxDecoration( | 
					
						
							|  |  |  |                 border: Border.all(color: MyTheme.color(context).border!)), | 
					
						
							|  |  |  |             child: Scaffold( | 
					
						
							|  |  |  |                 backgroundColor: MyTheme.color(context).bg, | 
					
						
							| 
									
										
										
										
											2022-09-08 20:43:27 +08:00
										 |  |  |                 body: DesktopTab( | 
					
						
							|  |  |  |                   controller: tabController, | 
					
						
							|  |  |  |                   showTabBar: fullscreen.isFalse, | 
					
						
							| 
									
										
										
										
											2022-09-09 19:29:19 +08:00
										 |  |  |                   onWindowCloseButton: handleWindowCloseButton, | 
					
						
							| 
									
										
										
										
											2022-09-13 19:10:55 -07:00
										 |  |  |                   tail: const AddButton().paddingOnly(left: 10), | 
					
						
							| 
									
										
										
										
											2022-09-08 20:43:27 +08:00
										 |  |  |                   pageViewBuilder: (pageView) { | 
					
						
							|  |  |  |                     WindowController.fromWindowId(windowId()) | 
					
						
							|  |  |  |                         .setFullscreen(fullscreen.isTrue); | 
					
						
							|  |  |  |                     return pageView; | 
					
						
							|  |  |  |                   }, | 
					
						
							|  |  |  |                   tabBuilder: (key, icon, label, themeConf) => Obx(() { | 
					
						
							|  |  |  |                     final connectionType = ConnectionTypeState.find(key); | 
					
						
							|  |  |  |                     if (!connectionType.isValid()) { | 
					
						
							|  |  |  |                       return Row( | 
					
						
							|  |  |  |                         mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |                         children: [ | 
					
						
							|  |  |  |                           icon, | 
					
						
							|  |  |  |                           label, | 
					
						
							|  |  |  |                         ], | 
					
						
							|  |  |  |                       ); | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                       final msgDirect = translate(connectionType.direct.value == | 
					
						
							|  |  |  |                               ConnectionType.strDirect | 
					
						
							|  |  |  |                           ? 'Direct Connection' | 
					
						
							|  |  |  |                           : 'Relay Connection'); | 
					
						
							|  |  |  |                       final msgSecure = translate(connectionType.secure.value == | 
					
						
							|  |  |  |                               ConnectionType.strSecure | 
					
						
							|  |  |  |                           ? 'Secure Connection' | 
					
						
							|  |  |  |                           : 'Insecure Connection'); | 
					
						
							|  |  |  |                       return Row( | 
					
						
							|  |  |  |                         mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |                         children: [ | 
					
						
							|  |  |  |                           icon, | 
					
						
							|  |  |  |                           Tooltip( | 
					
						
							|  |  |  |                             message: '$msgDirect\n$msgSecure', | 
					
						
							|  |  |  |                             child: Image.asset( | 
					
						
							|  |  |  |                               'assets/${connectionType.secure.value}${connectionType.direct.value}.png', | 
					
						
							|  |  |  |                               width: themeConf.iconSize, | 
					
						
							|  |  |  |                               height: themeConf.iconSize, | 
					
						
							|  |  |  |                             ).paddingOnly(right: 5), | 
					
						
							|  |  |  |                           ), | 
					
						
							|  |  |  |                           label, | 
					
						
							|  |  |  |                         ], | 
					
						
							|  |  |  |                       ); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                   }), | 
					
						
							|  |  |  |                 )), | 
					
						
							| 
									
										
										
										
											2022-08-26 23:28:08 +08:00
										 |  |  |           ), | 
					
						
							|  |  |  |         )); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-05-31 16:27:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   void onRemoveId(String id) { | 
					
						
							| 
									
										
										
										
											2022-08-30 16:45:47 +08:00
										 |  |  |     if (tabController.state.value.tabs.isEmpty) { | 
					
						
							|  |  |  |       WindowController.fromWindowId(windowId()).hide(); | 
					
						
							| 
									
										
										
										
											2022-08-09 09:01:06 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-08-29 22:46:19 +08:00
										 |  |  |     ConnectionTypeState.delete(id); | 
					
						
							| 
									
										
										
										
											2022-05-31 16:27:54 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-09 16:37:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   int windowId() { | 
					
						
							|  |  |  |     return widget.params["windowId"]; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:03:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   void handleTabCloseButton(String peerId) { | 
					
						
							|  |  |  |     final session = ffi(peerId); | 
					
						
							|  |  |  |     if (session.ffiModel.pi.hostname.isNotEmpty) { | 
					
						
							|  |  |  |       tabController.jumpBy(peerId); | 
					
						
							|  |  |  |       clientClose(session.dialogManager); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       tabController.closeBy(peerId); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-09 19:29:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Future<bool> handleWindowCloseButton() async { | 
					
						
							|  |  |  |     final connLength = tabController.state.value.tabs.length; | 
					
						
							|  |  |  |     if (connLength < 1) { | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } else if (connLength == 1) { | 
					
						
							|  |  |  |       final currentConn = tabController.state.value.tabs[0]; | 
					
						
							|  |  |  |       handleTabCloseButton(currentConn.key); | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       final res = await closeConfirmDialog(); | 
					
						
							|  |  |  |       if (res) { | 
					
						
							|  |  |  |         tabController.clear(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return res; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | } |