| 
									
										
										
										
											2022-12-16 23:15:26 +09:00
										 |  |  | import 'dart:async'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  | import 'package:flutter/services.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-24 23:33:00 +08:00
										 |  |  | import 'package:flutter_hbb/mobile/widgets/dialog.dart'; | 
					
						
							| 
									
										
										
										
											2023-07-09 19:14:57 +08:00
										 |  |  | import 'package:flutter_hbb/models/chat_model.dart'; | 
					
						
							| 
									
										
										
										
											2023-03-01 08:55:21 +01:00
										 |  |  | import 'package:get/get.dart'; | 
					
						
							| 
									
										
										
										
											2022-02-02 17:25:56 +08:00
										 |  |  | import 'package:provider/provider.dart'; | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-24 23:33:00 +08:00
										 |  |  | import '../../common.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-16 21:52:08 +08:00
										 |  |  | import '../../common/widgets/dialog.dart'; | 
					
						
							| 
									
										
										
										
											2023-03-01 18:00:56 +01:00
										 |  |  | import '../../consts.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  | import '../../models/platform_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-24 23:33:00 +08:00
										 |  |  | import '../../models/server_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-02-28 18:29:25 +08:00
										 |  |  | import 'home_page.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 20:36:52 +08:00
										 |  |  | class ServerPage extends StatefulWidget implements PageShape { | 
					
						
							| 
									
										
										
										
											2022-02-28 18:29:25 +08:00
										 |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-03-23 15:28:21 +08:00
										 |  |  |   final title = translate("Share Screen"); | 
					
						
							| 
									
										
										
										
											2022-02-28 18:29:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |   final icon = const Icon(Icons.mobile_screen_share); | 
					
						
							| 
									
										
										
										
											2022-02-28 18:29:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   final appBarActions = [ | 
					
						
							| 
									
										
										
										
											2022-04-04 01:38:53 +08:00
										 |  |  |     PopupMenuButton<String>( | 
					
						
							| 
									
										
										
										
											2023-06-29 10:26:03 +08:00
										 |  |  |         tooltip: "", | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |         icon: const Icon(Icons.more_vert), | 
					
						
							| 
									
										
										
										
											2022-04-04 01:38:53 +08:00
										 |  |  |         itemBuilder: (context) { | 
					
						
							| 
									
										
										
										
											2023-06-28 20:22:57 +08:00
										 |  |  |           listTile(String text, bool checked) { | 
					
						
							|  |  |  |             return ListTile( | 
					
						
							|  |  |  |                 title: Text(translate(text)), | 
					
						
							|  |  |  |                 trailing: Icon( | 
					
						
							|  |  |  |                   Icons.check, | 
					
						
							|  |  |  |                   color: checked ? null : Colors.transparent, | 
					
						
							|  |  |  |                 )); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           final approveMode = gFFI.serverModel.approveMode; | 
					
						
							|  |  |  |           final verificationMethod = gFFI.serverModel.verificationMethod; | 
					
						
							|  |  |  |           final showPasswordOption = approveMode != 'click'; | 
					
						
							| 
									
										
										
										
											2022-04-04 01:38:53 +08:00
										 |  |  |           return [ | 
					
						
							|  |  |  |             PopupMenuItem( | 
					
						
							| 
									
										
										
										
											2023-06-26 23:27:18 +08:00
										 |  |  |               enabled: gFFI.serverModel.connectStatus > 0, | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |               padding: const EdgeInsets.symmetric(horizontal: 16.0), | 
					
						
							| 
									
										
										
										
											2022-04-04 01:38:53 +08:00
										 |  |  |               value: "changeID", | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |               child: Text(translate("Change ID")), | 
					
						
							| 
									
										
										
										
											2022-04-04 01:38:53 +08:00
										 |  |  |             ), | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |             const PopupMenuDivider(), | 
					
						
							| 
									
										
										
										
											2022-04-04 01:38:53 +08:00
										 |  |  |             PopupMenuItem( | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |               padding: const EdgeInsets.symmetric(horizontal: 0.0), | 
					
						
							| 
									
										
										
										
											2023-06-28 20:22:57 +08:00
										 |  |  |               value: 'AcceptSessionsViaPassword', | 
					
						
							|  |  |  |               child: listTile( | 
					
						
							|  |  |  |                   'Accept sessions via password', approveMode == 'password'), | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |             ), | 
					
						
							| 
									
										
										
										
											2022-07-29 22:07:45 +08:00
										 |  |  |             PopupMenuItem( | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |               padding: const EdgeInsets.symmetric(horizontal: 0.0), | 
					
						
							| 
									
										
										
										
											2023-06-28 20:22:57 +08:00
										 |  |  |               value: 'AcceptSessionsViaClick', | 
					
						
							|  |  |  |               child: | 
					
						
							|  |  |  |                   listTile('Accept sessions via click', approveMode == 'click'), | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |             ), | 
					
						
							| 
									
										
										
										
											2022-07-29 22:07:45 +08:00
										 |  |  |             PopupMenuItem( | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |               padding: const EdgeInsets.symmetric(horizontal: 0.0), | 
					
						
							| 
									
										
										
										
											2023-06-28 20:22:57 +08:00
										 |  |  |               value: "AcceptSessionsViaBoth", | 
					
						
							|  |  |  |               child: listTile("Accept sessions via both", | 
					
						
							|  |  |  |                   approveMode != 'password' && approveMode != 'click'), | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |             ), | 
					
						
							| 
									
										
										
										
											2023-06-28 20:22:57 +08:00
										 |  |  |             if (showPasswordOption) const PopupMenuDivider(), | 
					
						
							|  |  |  |             if (showPasswordOption && | 
					
						
							|  |  |  |                 verificationMethod != kUseTemporaryPassword) | 
					
						
							|  |  |  |               PopupMenuItem( | 
					
						
							|  |  |  |                 padding: const EdgeInsets.symmetric(horizontal: 16.0), | 
					
						
							|  |  |  |                 value: "setPermanentPassword", | 
					
						
							|  |  |  |                 child: Text(translate("Set permanent password")), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             if (showPasswordOption && | 
					
						
							|  |  |  |                 verificationMethod != kUsePermanentPassword) | 
					
						
							|  |  |  |               PopupMenuItem( | 
					
						
							|  |  |  |                 padding: const EdgeInsets.symmetric(horizontal: 16.0), | 
					
						
							|  |  |  |                 value: "setTemporaryPasswordLength", | 
					
						
							|  |  |  |                 child: Text(translate("One-time password length")), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             if (showPasswordOption) const PopupMenuDivider(), | 
					
						
							|  |  |  |             if (showPasswordOption) | 
					
						
							|  |  |  |               PopupMenuItem( | 
					
						
							|  |  |  |                 padding: const EdgeInsets.symmetric(horizontal: 0.0), | 
					
						
							|  |  |  |                 value: kUseTemporaryPassword, | 
					
						
							|  |  |  |                 child: listTile('Use one-time password', | 
					
						
							|  |  |  |                     verificationMethod == kUseTemporaryPassword), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             if (showPasswordOption) | 
					
						
							|  |  |  |               PopupMenuItem( | 
					
						
							|  |  |  |                 padding: const EdgeInsets.symmetric(horizontal: 0.0), | 
					
						
							|  |  |  |                 value: kUsePermanentPassword, | 
					
						
							|  |  |  |                 child: listTile('Use permanent password', | 
					
						
							|  |  |  |                     verificationMethod == kUsePermanentPassword), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             if (showPasswordOption) | 
					
						
							|  |  |  |               PopupMenuItem( | 
					
						
							|  |  |  |                 padding: const EdgeInsets.symmetric(horizontal: 0.0), | 
					
						
							|  |  |  |                 value: kUseBothPasswords, | 
					
						
							|  |  |  |                 child: listTile( | 
					
						
							|  |  |  |                     'Use both passwords', | 
					
						
							|  |  |  |                     verificationMethod != kUseTemporaryPassword && | 
					
						
							|  |  |  |                         verificationMethod != kUsePermanentPassword), | 
					
						
							|  |  |  |               ), | 
					
						
							| 
									
										
										
										
											2022-04-04 01:38:53 +08:00
										 |  |  |           ]; | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         onSelected: (value) { | 
					
						
							|  |  |  |           if (value == "changeID") { | 
					
						
							| 
									
										
										
										
											2022-09-16 21:52:08 +08:00
										 |  |  |             changeIdDialog(); | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |           } else if (value == "setPermanentPassword") { | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |             setPermanentPasswordDialog(gFFI.dialogManager); | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |           } else if (value == "setTemporaryPasswordLength") { | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |             setTemporaryPasswordLengthDialog(gFFI.dialogManager); | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |           } else if (value == kUsePermanentPassword || | 
					
						
							|  |  |  |               value == kUseTemporaryPassword || | 
					
						
							|  |  |  |               value == kUseBothPasswords) { | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  |             bind.mainSetOption(key: "verification-method", value: value); | 
					
						
							| 
									
										
										
										
											2022-08-01 10:44:05 +08:00
										 |  |  |             gFFI.serverModel.updatePasswordModel(); | 
					
						
							| 
									
										
										
										
											2023-06-28 20:22:57 +08:00
										 |  |  |           } else if (value.startsWith("AcceptSessionsVia")) { | 
					
						
							|  |  |  |             value = value.substring("AcceptSessionsVia".length); | 
					
						
							|  |  |  |             if (value == "Password") { | 
					
						
							|  |  |  |               gFFI.serverModel.setApproveMode('password'); | 
					
						
							|  |  |  |             } else if (value == "Click") { | 
					
						
							|  |  |  |               gFFI.serverModel.setApproveMode('click'); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |               gFFI.serverModel.setApproveMode(''); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-03-30 23:09:19 +08:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2022-04-04 01:38:53 +08:00
										 |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-02-28 18:29:25 +08:00
										 |  |  |   ]; | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |   ServerPage({Key? key}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 20:36:52 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   State<StatefulWidget> createState() => _ServerPageState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _ServerPageState extends State<ServerPage> { | 
					
						
							| 
									
										
										
										
											2022-12-16 23:15:26 +09:00
										 |  |  |   Timer? _updateTimer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 20:36:52 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							| 
									
										
										
										
											2022-12-16 23:15:26 +09:00
										 |  |  |     _updateTimer = periodic_immediate(const Duration(seconds: 3), () async { | 
					
						
							|  |  |  |       await gFFI.serverModel.fetchID(); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2022-08-09 20:36:52 +08:00
										 |  |  |     gFFI.serverModel.checkAndroidPermission(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-16 23:15:26 +09:00
										 |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     _updateTimer?.cancel(); | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-02-08 22:45:48 +08:00
										 |  |  |     checkService(); | 
					
						
							| 
									
										
										
										
											2022-03-25 16:34:27 +08:00
										 |  |  |     return ChangeNotifierProvider.value( | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  |         value: gFFI.serverModel, | 
					
						
							| 
									
										
										
										
											2022-03-25 16:34:27 +08:00
										 |  |  |         child: Consumer<ServerModel>( | 
					
						
							|  |  |  |             builder: (context, serverModel, child) => SingleChildScrollView( | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  |                   controller: gFFI.serverModel.controller, | 
					
						
							| 
									
										
										
										
											2022-03-25 16:34:27 +08:00
										 |  |  |                   child: Center( | 
					
						
							|  |  |  |                     child: Column( | 
					
						
							|  |  |  |                       mainAxisAlignment: MainAxisAlignment.start, | 
					
						
							|  |  |  |                       children: [ | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  |                         gFFI.serverModel.isStart | 
					
						
							|  |  |  |                             ? ServerInfo() | 
					
						
							|  |  |  |                             : ServiceNotRunningNotification(), | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |                         const ConnectionManager(), | 
					
						
							| 
									
										
										
										
											2023-03-02 14:56:51 +01:00
										 |  |  |                         const PermissionChecker(), | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |                         SizedBox.fromSize(size: const Size(0, 15.0)), | 
					
						
							| 
									
										
										
										
											2022-03-25 16:34:27 +08:00
										 |  |  |                       ], | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 ))); | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 14:54:00 +08:00
										 |  |  | void checkService() async { | 
					
						
							| 
									
										
										
										
											2023-03-01 18:00:56 +01:00
										 |  |  |   gFFI.invokeMethod("check_service"); | 
					
						
							|  |  |  |   // for Android 10/11, request MANAGE_EXTERNAL_STORAGE permission from system setting page
 | 
					
						
							|  |  |  |   if (AndroidPermissionManager.isWaitingFile() && !gFFI.serverModel.fileOk) { | 
					
						
							|  |  |  |     AndroidPermissionManager.complete(kManageExternalStorage, | 
					
						
							|  |  |  |         await AndroidPermissionManager.check(kManageExternalStorage)); | 
					
						
							| 
									
										
										
										
											2022-04-04 14:54:00 +08:00
										 |  |  |     debugPrint("file permission finished"); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-02-08 22:45:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  | class ServiceNotRunningNotification extends StatelessWidget { | 
					
						
							|  |  |  |   ServiceNotRunningNotification({Key? key}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     final serverModel = Provider.of<ServerModel>(context); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return PaddingCard( | 
					
						
							| 
									
										
										
										
											2023-03-07 11:45:20 +01:00
										 |  |  |         title: translate("Service is not running"), | 
					
						
							|  |  |  |         titleIcon: | 
					
						
							|  |  |  |             const Icon(Icons.warning_amber_sharp, color: Colors.redAccent), | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  |         child: Column( | 
					
						
							| 
									
										
										
										
											2023-03-07 11:45:20 +01:00
										 |  |  |           crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  |           children: [ | 
					
						
							| 
									
										
										
										
											2023-03-07 11:45:20 +01:00
										 |  |  |             Text(translate("android_start_service_tip"), | 
					
						
							|  |  |  |                     style: | 
					
						
							|  |  |  |                         const TextStyle(fontSize: 12, color: MyTheme.darkGray)) | 
					
						
							|  |  |  |                 .marginOnly(bottom: 8), | 
					
						
							|  |  |  |             ElevatedButton.icon( | 
					
						
							|  |  |  |                 icon: const Icon(Icons.play_arrow), | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |                 onPressed: () { | 
					
						
							|  |  |  |                   if (gFFI.userModel.userName.value.isEmpty && bind.mainGetLocalOption(key: "show-scam-warning") != "N") { | 
					
						
							|  |  |  |                     _showScamWarning(context, serverModel); | 
					
						
							|  |  |  |                   } else { | 
					
						
							|  |  |  |                     serverModel.toggleService(); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2023-03-07 11:45:20 +01:00
										 |  |  |                 label: Text(translate("Start Service"))) | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  |           ], | 
					
						
							| 
									
										
										
										
											2023-03-07 11:45:20 +01:00
										 |  |  |         )); | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |   void _showScamWarning(BuildContext context, ServerModel serverModel) { | 
					
						
							|  |  |  |     showDialog( | 
					
						
							|  |  |  |       context: context, | 
					
						
							|  |  |  |       builder: (BuildContext context) { | 
					
						
							|  |  |  |         return ScamWarningDialog(serverModel: serverModel); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ScamWarningDialog extends StatefulWidget { | 
					
						
							|  |  |  |   final ServerModel serverModel; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ScamWarningDialog({required this.serverModel}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   _ScamWarningDialogState createState() => _ScamWarningDialogState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _ScamWarningDialogState extends State<ScamWarningDialog> { | 
					
						
							| 
									
										
										
										
											2023-09-13 10:19:43 +08:00
										 |  |  |   int _countdown = 12; | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |   bool show_warning = false; | 
					
						
							|  |  |  |   late Timer _timer; | 
					
						
							|  |  |  |   late ServerModel _serverModel; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							|  |  |  |     _serverModel = widget.serverModel; | 
					
						
							|  |  |  |     startCountdown(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void startCountdown() { | 
					
						
							|  |  |  |     const oneSecond = Duration(seconds: 1); | 
					
						
							|  |  |  |     _timer = Timer.periodic(oneSecond, (timer) { | 
					
						
							|  |  |  |       setState(() { | 
					
						
							|  |  |  |         _countdown--; | 
					
						
							|  |  |  |         if (_countdown <= 0) { | 
					
						
							|  |  |  |           timer.cancel(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     _timer.cancel(); | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     final isButtonLocked = _countdown > 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return AlertDialog( | 
					
						
							|  |  |  |       content: Container( | 
					
						
							|  |  |  |         decoration: BoxDecoration( | 
					
						
							|  |  |  |           gradient: LinearGradient( | 
					
						
							|  |  |  |             begin: Alignment.topRight, | 
					
						
							|  |  |  |             end: Alignment.bottomLeft, | 
					
						
							|  |  |  |             colors: [ | 
					
						
							|  |  |  |               Color(0xffe242bc), | 
					
						
							|  |  |  |               Color(0xfff4727c), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           borderRadius: BorderRadius.circular(20.0), | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         padding: EdgeInsets.all(25.0), | 
					
						
							|  |  |  |         child: Column( | 
					
						
							|  |  |  |           mainAxisSize: MainAxisSize.min, | 
					
						
							|  |  |  |           crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |           children: [ | 
					
						
							|  |  |  |             Row( | 
					
						
							|  |  |  |               children: [ | 
					
						
							|  |  |  |                 Icon( | 
					
						
							|  |  |  |                   Icons.warning_amber_sharp, | 
					
						
							|  |  |  |                   color: Colors.white, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 SizedBox(width: 10), | 
					
						
							|  |  |  |                 Text( | 
					
						
							|  |  |  |                   translate("Warning"), | 
					
						
							|  |  |  |                   style: TextStyle( | 
					
						
							|  |  |  |                     color: Colors.white, | 
					
						
							|  |  |  |                     fontWeight: FontWeight.bold, | 
					
						
							|  |  |  |                     fontSize: 20.0, | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |               ], | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             SizedBox(height: 20), | 
					
						
							|  |  |  |             Center( | 
					
						
							|  |  |  |               child: Image.asset('assets/scam.png', | 
					
						
							|  |  |  |               width: 180, | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             SizedBox(height: 18), | 
					
						
							|  |  |  |             Text( | 
					
						
							| 
									
										
										
										
											2023-09-13 11:00:07 +05:30
										 |  |  |               translate("scam_title"), | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |               textAlign: TextAlign.center, | 
					
						
							|  |  |  |               style: TextStyle( | 
					
						
							|  |  |  |                 color: Colors.white, | 
					
						
							|  |  |  |                 fontWeight: FontWeight.bold, | 
					
						
							|  |  |  |                 fontSize: 22.0, | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             SizedBox(height: 18), | 
					
						
							| 
									
										
										
										
											2023-10-10 20:58:58 +05:30
										 |  |  |             SizedBox( | 
					
						
							| 
									
										
										
										
											2023-10-10 21:32:05 +05:30
										 |  |  |               height: 220, | 
					
						
							| 
									
										
										
										
											2023-10-10 20:58:58 +05:30
										 |  |  |               child: Scrollbar( | 
					
						
							|  |  |  |                 child: SingleChildScrollView( | 
					
						
							|  |  |  |                   child: Text( | 
					
						
							|  |  |  |                       translate("scam_text1")+"\n\n" | 
					
						
							|  |  |  |                       +translate("scam_text2")+"\n", | 
					
						
							|  |  |  |                       style: TextStyle( | 
					
						
							|  |  |  |                         color: Colors.white, | 
					
						
							|  |  |  |                         fontWeight: FontWeight.bold, | 
					
						
							|  |  |  |                         fontSize: 16.0, | 
					
						
							|  |  |  |                       ), | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 ), | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |               ), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             Row( | 
					
						
							|  |  |  |               children: <Widget>[ | 
					
						
							|  |  |  |                 Checkbox( | 
					
						
							|  |  |  |                   value: show_warning, | 
					
						
							|  |  |  |                   onChanged: (value) { | 
					
						
							|  |  |  |                     setState((){ | 
					
						
							|  |  |  |                       show_warning = value!; | 
					
						
							|  |  |  |                     }); | 
					
						
							|  |  |  |                   }, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 Text( | 
					
						
							|  |  |  |                   translate("Don't show again"), | 
					
						
							|  |  |  |                   style: TextStyle( | 
					
						
							|  |  |  |                     color: Colors.white, | 
					
						
							|  |  |  |                     fontWeight: FontWeight.bold, | 
					
						
							|  |  |  |                     fontSize: 15.0, | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |               ], | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             SizedBox(height: 10), | 
					
						
							|  |  |  |             Row( | 
					
						
							|  |  |  |               mainAxisAlignment: MainAxisAlignment.end, | 
					
						
							|  |  |  |               children: [ | 
					
						
							| 
									
										
										
										
											2023-10-10 22:48:23 +05:30
										 |  |  |                 Container( | 
					
						
							|  |  |  |                   constraints: BoxConstraints(maxWidth: 150), | 
					
						
							|  |  |  |                   child: ElevatedButton( | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |                   onPressed: isButtonLocked | 
					
						
							|  |  |  |                       ? null | 
					
						
							|  |  |  |                       : () { | 
					
						
							|  |  |  |                           Navigator.of(context).pop(); | 
					
						
							|  |  |  |                           _serverModel.toggleService(); | 
					
						
							|  |  |  |                           if (show_warning) { | 
					
						
							|  |  |  |                             bind.mainSetLocalOption(key: "show-scam-warning", value: "N"); | 
					
						
							|  |  |  |                           } | 
					
						
							|  |  |  |                         }, | 
					
						
							|  |  |  |                   style: ElevatedButton.styleFrom( | 
					
						
							|  |  |  |                     primary: Colors.blueAccent, | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                   child: Text( | 
					
						
							|  |  |  |                   isButtonLocked ? translate("I Agree")+" (${_countdown}s)" : translate("I Agree"), | 
					
						
							|  |  |  |                     style: TextStyle( | 
					
						
							|  |  |  |                         fontWeight: FontWeight.bold, | 
					
						
							|  |  |  |                         fontSize: 13.0, | 
					
						
							|  |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2023-10-10 22:48:23 +05:30
										 |  |  |                     maxLines: 2, | 
					
						
							|  |  |  |                     overflow: TextOverflow.ellipsis, | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |                   ), | 
					
						
							|  |  |  |                 ), | 
					
						
							| 
									
										
										
										
											2023-10-10 22:48:23 +05:30
										 |  |  |                 ), | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |                 SizedBox(width: 15), | 
					
						
							| 
									
										
										
										
											2023-10-10 22:48:23 +05:30
										 |  |  |                 Container( | 
					
						
							|  |  |  |                   constraints: BoxConstraints(maxWidth: 150), | 
					
						
							|  |  |  |                   child: ElevatedButton( | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |                   onPressed: () { | 
					
						
							|  |  |  |                     Navigator.of(context).pop();  | 
					
						
							|  |  |  |                   }, | 
					
						
							|  |  |  |                   style: ElevatedButton.styleFrom( | 
					
						
							|  |  |  |                     primary: Colors.blueAccent, | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                   child: Text( | 
					
						
							|  |  |  |                     translate("Decline"), | 
					
						
							|  |  |  |                     style: TextStyle( | 
					
						
							|  |  |  |                         fontWeight: FontWeight.bold, | 
					
						
							|  |  |  |                         fontSize: 13.0, | 
					
						
							|  |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2023-10-10 22:48:23 +05:30
										 |  |  |                     maxLines: 2, | 
					
						
							|  |  |  |                     overflow: TextOverflow.ellipsis, | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |                   ), | 
					
						
							|  |  |  |                 ), | 
					
						
							| 
									
										
										
										
											2023-10-10 22:48:23 +05:30
										 |  |  |                 ), | 
					
						
							| 
									
										
										
										
											2023-09-11 21:48:36 +05:30
										 |  |  |               ], | 
					
						
							|  |  |  |     )])), | 
					
						
							|  |  |  |     contentPadding: EdgeInsets.all(0.0), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  | class ServerInfo extends StatelessWidget { | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  |   final model = gFFI.serverModel; | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |   final emptyController = TextEditingController(text: "-"); | 
					
						
							| 
									
										
										
										
											2022-03-19 23:28:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |   ServerInfo({Key? key}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-07-29 18:34:25 +08:00
										 |  |  |     final isPermanent = model.verificationMethod == kUsePermanentPassword; | 
					
						
							| 
									
										
										
										
											2023-06-23 18:25:42 +08:00
										 |  |  |     final serverModel = Provider.of<ServerModel>(context); | 
					
						
							| 
									
										
										
										
											2023-03-02 03:05:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |     const Color colorPositive = Colors.green; | 
					
						
							|  |  |  |     const Color colorNegative = Colors.red; | 
					
						
							|  |  |  |     const double iconMarginRight = 15; | 
					
						
							|  |  |  |     const double iconSize = 24; | 
					
						
							|  |  |  |     const TextStyle textStyleHeading = TextStyle( | 
					
						
							|  |  |  |         fontSize: 16.0, fontWeight: FontWeight.bold, color: Colors.grey); | 
					
						
							|  |  |  |     const TextStyle textStyleValue = | 
					
						
							|  |  |  |         TextStyle(fontSize: 25.0, fontWeight: FontWeight.bold); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void copyToClipboard(String value) { | 
					
						
							|  |  |  |       Clipboard.setData(ClipboardData(text: value)); | 
					
						
							|  |  |  |       showToast(translate('Copied')); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-02 03:05:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 18:25:42 +08:00
										 |  |  |     Widget ConnectionStateNotification() { | 
					
						
							|  |  |  |       if (serverModel.connectStatus == -1) { | 
					
						
							|  |  |  |         return Row(children: [ | 
					
						
							|  |  |  |           const Icon(Icons.warning_amber_sharp, | 
					
						
							|  |  |  |                   color: colorNegative, size: iconSize) | 
					
						
							|  |  |  |               .marginOnly(right: iconMarginRight), | 
					
						
							|  |  |  |           Expanded(child: Text(translate('not_ready_status'))) | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  |       } else if (serverModel.connectStatus == 0) { | 
					
						
							|  |  |  |         return Row(children: [ | 
					
						
							|  |  |  |           SizedBox(width: 20, height: 20, child: CircularProgressIndicator()) | 
					
						
							|  |  |  |               .marginOnly(left: 4, right: iconMarginRight), | 
					
						
							|  |  |  |           Expanded(child: Text(translate('connecting_status'))) | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         return Row(children: [ | 
					
						
							|  |  |  |           const Icon(Icons.check, color: colorPositive, size: iconSize) | 
					
						
							|  |  |  |               .marginOnly(right: iconMarginRight), | 
					
						
							|  |  |  |           Expanded(child: Text(translate('Ready'))) | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-02 03:05:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  |     return PaddingCard( | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |         title: translate('Your Device'), | 
					
						
							| 
									
										
										
										
											2023-03-06 15:27:22 +01:00
										 |  |  |         child: Column( | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |           // ID
 | 
					
						
							|  |  |  |           children: [ | 
					
						
							|  |  |  |             Row(children: [ | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |               const Icon(Icons.perm_identity, | 
					
						
							|  |  |  |                       color: Colors.grey, size: iconSize) | 
					
						
							|  |  |  |                   .marginOnly(right: iconMarginRight), | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |               Text( | 
					
						
							|  |  |  |                 translate('ID'), | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |                 style: textStyleHeading, | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |               ) | 
					
						
							|  |  |  |             ]), | 
					
						
							|  |  |  |             Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ | 
					
						
							|  |  |  |               Text( | 
					
						
							|  |  |  |                 model.serverId.value.text, | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |                 style: textStyleValue, | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |               ), | 
					
						
							|  |  |  |               IconButton( | 
					
						
							|  |  |  |                   visualDensity: VisualDensity.compact, | 
					
						
							|  |  |  |                   icon: Icon(Icons.copy_outlined), | 
					
						
							|  |  |  |                   onPressed: () { | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |                     copyToClipboard(model.serverId.value.text.trim()); | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |                   }) | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |             ]).marginOnly(left: 39, bottom: 10), | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |             // Password
 | 
					
						
							|  |  |  |             Row(children: [ | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |               const Icon(Icons.lock_outline, color: Colors.grey, size: iconSize) | 
					
						
							|  |  |  |                   .marginOnly(right: iconMarginRight), | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |               Text( | 
					
						
							|  |  |  |                 translate('One-time Password'), | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |                 style: textStyleHeading, | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |               ) | 
					
						
							|  |  |  |             ]), | 
					
						
							|  |  |  |             Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ | 
					
						
							|  |  |  |               Text( | 
					
						
							|  |  |  |                 isPermanent ? '-' : model.serverPasswd.value.text, | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |                 style: textStyleValue, | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |               ), | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |               isPermanent | 
					
						
							|  |  |  |                   ? SizedBox.shrink() | 
					
						
							|  |  |  |                   : Row(children: [ | 
					
						
							|  |  |  |                       IconButton( | 
					
						
							|  |  |  |                           visualDensity: VisualDensity.compact, | 
					
						
							|  |  |  |                           icon: const Icon(Icons.refresh), | 
					
						
							|  |  |  |                           onPressed: () => bind.mainUpdateTemporaryPassword()), | 
					
						
							|  |  |  |                       IconButton( | 
					
						
							|  |  |  |                           visualDensity: VisualDensity.compact, | 
					
						
							|  |  |  |                           icon: Icon(Icons.copy_outlined), | 
					
						
							|  |  |  |                           onPressed: () { | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |                             copyToClipboard( | 
					
						
							|  |  |  |                                 model.serverPasswd.value.text.trim()); | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |                           }) | 
					
						
							|  |  |  |                     ]) | 
					
						
							| 
									
										
										
										
											2023-03-09 17:25:29 +01:00
										 |  |  |             ]).marginOnly(left: 40, bottom: 15), | 
					
						
							| 
									
										
										
										
											2023-03-09 16:40:30 +01:00
										 |  |  |             ConnectionStateNotification() | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         )); | 
					
						
							| 
									
										
										
										
											2022-02-09 17:04:13 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class PermissionChecker extends StatefulWidget { | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |   const PermissionChecker({Key? key}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |   State<PermissionChecker> createState() => _PermissionCheckerState(); | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _PermissionCheckerState extends State<PermissionChecker> { | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-02-02 17:25:56 +08:00
										 |  |  |     final serverModel = Provider.of<ServerModel>(context); | 
					
						
							| 
									
										
										
										
											2022-03-25 16:34:27 +08:00
										 |  |  |     final hasAudioPermission = androidVersion >= 30; | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |     return PaddingCard( | 
					
						
							| 
									
										
										
										
											2022-04-20 15:45:51 +08:00
										 |  |  |         title: translate("Permissions"), | 
					
						
							| 
									
										
										
										
											2023-03-01 08:55:21 +01:00
										 |  |  |         child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ | 
					
						
							| 
									
										
										
										
											2023-03-02 03:05:03 +01:00
										 |  |  |           serverModel.mediaOk | 
					
						
							|  |  |  |               ? ElevatedButton.icon( | 
					
						
							|  |  |  |                       style: ButtonStyle( | 
					
						
							|  |  |  |                           backgroundColor: | 
					
						
							|  |  |  |                               MaterialStateProperty.all(Colors.red)), | 
					
						
							|  |  |  |                       icon: const Icon(Icons.stop), | 
					
						
							|  |  |  |                       onPressed: serverModel.toggleService, | 
					
						
							|  |  |  |                       label: Text(translate("Stop service"))) | 
					
						
							|  |  |  |                   .marginOnly(bottom: 8) | 
					
						
							|  |  |  |               : SizedBox.shrink(), | 
					
						
							| 
									
										
										
										
											2023-03-01 08:55:21 +01:00
										 |  |  |           PermissionRow(translate("Screen Capture"), serverModel.mediaOk, | 
					
						
							|  |  |  |               serverModel.toggleService), | 
					
						
							|  |  |  |           PermissionRow(translate("Input Control"), serverModel.inputOk, | 
					
						
							|  |  |  |               serverModel.toggleInput), | 
					
						
							|  |  |  |           PermissionRow(translate("Transfer File"), serverModel.fileOk, | 
					
						
							|  |  |  |               serverModel.toggleFile), | 
					
						
							|  |  |  |           hasAudioPermission | 
					
						
							|  |  |  |               ? PermissionRow(translate("Audio Capture"), serverModel.audioOk, | 
					
						
							|  |  |  |                   serverModel.toggleAudio) | 
					
						
							| 
									
										
										
										
											2023-03-07 10:43:55 +01:00
										 |  |  |               : Row(children: [ | 
					
						
							|  |  |  |                   Icon(Icons.info_outline).marginOnly(right: 15), | 
					
						
							|  |  |  |                   Expanded( | 
					
						
							|  |  |  |                       child: Text( | 
					
						
							|  |  |  |                     translate("android_version_audio_tip"), | 
					
						
							|  |  |  |                     style: const TextStyle(color: MyTheme.darkGray), | 
					
						
							|  |  |  |                   )) | 
					
						
							|  |  |  |                 ]) | 
					
						
							| 
									
										
										
										
											2023-03-01 08:55:21 +01:00
										 |  |  |         ])); | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-02-02 17:25:56 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class PermissionRow extends StatelessWidget { | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |   const PermissionRow(this.name, this.isOk, this.onPressed, {Key? key}) | 
					
						
							|  |  |  |       : super(key: key); | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   final String name; | 
					
						
							|  |  |  |   final bool isOk; | 
					
						
							|  |  |  |   final VoidCallback onPressed; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2023-03-07 10:11:06 +01:00
										 |  |  |     return SwitchListTile( | 
					
						
							|  |  |  |         visualDensity: VisualDensity.compact, | 
					
						
							|  |  |  |         contentPadding: EdgeInsets.all(0), | 
					
						
							|  |  |  |         title: Text(name), | 
					
						
							|  |  |  |         value: isOk, | 
					
						
							|  |  |  |         onChanged: (bool value) { | 
					
						
							|  |  |  |           onPressed(); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 17:25:56 +08:00
										 |  |  | class ConnectionManager extends StatelessWidget { | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |   const ConnectionManager({Key? key}) : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 17:25:56 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     final serverModel = Provider.of<ServerModel>(context); | 
					
						
							| 
									
										
										
										
											2022-03-19 23:28:29 +08:00
										 |  |  |     return Column( | 
					
						
							| 
									
										
										
										
											2022-08-22 20:18:31 +08:00
										 |  |  |         children: serverModel.clients | 
					
						
							|  |  |  |             .map((client) => PaddingCard( | 
					
						
							|  |  |  |                 title: translate(client.isFileTransfer | 
					
						
							| 
									
										
										
										
											2022-03-25 16:34:27 +08:00
										 |  |  |                     ? "File Connection" | 
					
						
							|  |  |  |                     : "Screen Connection"), | 
					
						
							| 
									
										
										
										
											2022-08-22 20:18:31 +08:00
										 |  |  |                 titleIcon: client.isFileTransfer | 
					
						
							| 
									
										
										
										
											2023-03-07 11:45:20 +01:00
										 |  |  |                     ? Icon(Icons.folder_outlined) | 
					
						
							|  |  |  |                     : Icon(Icons.mobile_screen_share), | 
					
						
							| 
									
										
										
										
											2023-03-09 18:31:34 +01:00
										 |  |  |                 child: Column(children: [ | 
					
						
							|  |  |  |                   Row( | 
					
						
							|  |  |  |                     mainAxisAlignment: MainAxisAlignment.spaceBetween, | 
					
						
							| 
									
										
										
										
											2023-03-07 13:20:14 +01:00
										 |  |  |                     children: [ | 
					
						
							| 
									
										
										
										
											2023-03-09 18:31:34 +01:00
										 |  |  |                       Expanded(child: ClientInfo(client)), | 
					
						
							|  |  |  |                       Expanded( | 
					
						
							|  |  |  |                           flex: -1, | 
					
						
							|  |  |  |                           child: client.isFileTransfer || !client.authorized | 
					
						
							|  |  |  |                               ? const SizedBox.shrink() | 
					
						
							|  |  |  |                               : IconButton( | 
					
						
							|  |  |  |                                   onPressed: () { | 
					
						
							| 
									
										
										
										
											2023-07-10 16:02:47 +08:00
										 |  |  |                                     gFFI.chatModel.changeCurrentKey( | 
					
						
							| 
									
										
										
										
											2023-07-09 19:14:57 +08:00
										 |  |  |                                         MessageKey(client.peerId, client.id)); | 
					
						
							| 
									
										
										
										
											2023-03-09 18:31:34 +01:00
										 |  |  |                                     final bar = navigationBarKey.currentWidget; | 
					
						
							|  |  |  |                                     if (bar != null) { | 
					
						
							|  |  |  |                                       bar as BottomNavigationBar; | 
					
						
							|  |  |  |                                       bar.onTap!(1); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                   }, | 
					
						
							| 
									
										
										
										
											2023-07-10 21:03:35 +08:00
										 |  |  |                                   icon: unreadTopRightBuilder( | 
					
						
							|  |  |  |                                       client.unreadChatMessageCount))) | 
					
						
							| 
									
										
										
										
											2023-03-09 18:31:34 +01:00
										 |  |  |                     ], | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                   client.authorized | 
					
						
							|  |  |  |                       ? const SizedBox.shrink() | 
					
						
							|  |  |  |                       : Text( | 
					
						
							|  |  |  |                           translate("android_new_connection_tip"), | 
					
						
							|  |  |  |                           style: Theme.of(context).textTheme.bodyMedium, | 
					
						
							|  |  |  |                         ).marginOnly(bottom: 5), | 
					
						
							|  |  |  |                   client.authorized | 
					
						
							|  |  |  |                       ? Container( | 
					
						
							|  |  |  |                           alignment: Alignment.centerRight, | 
					
						
							|  |  |  |                           child: ElevatedButton.icon( | 
					
						
							|  |  |  |                               style: ButtonStyle( | 
					
						
							|  |  |  |                                   backgroundColor: | 
					
						
							|  |  |  |                                       MaterialStatePropertyAll(Colors.red)), | 
					
						
							|  |  |  |                               icon: const Icon(Icons.close), | 
					
						
							|  |  |  |                               onPressed: () { | 
					
						
							|  |  |  |                                 bind.cmCloseConnection(connId: client.id); | 
					
						
							|  |  |  |                                 gFFI.invokeMethod( | 
					
						
							|  |  |  |                                     "cancel_notification", client.id); | 
					
						
							|  |  |  |                               }, | 
					
						
							|  |  |  |                               label: Text(translate("Disconnect")))) | 
					
						
							|  |  |  |                       : Row( | 
					
						
							|  |  |  |                           mainAxisAlignment: MainAxisAlignment.end, | 
					
						
							|  |  |  |                           children: [ | 
					
						
							|  |  |  |                               TextButton( | 
					
						
							|  |  |  |                                   child: Text(translate("Dismiss")), | 
					
						
							|  |  |  |                                   onPressed: () { | 
					
						
							|  |  |  |                                     serverModel.sendLoginResponse( | 
					
						
							|  |  |  |                                         client, false); | 
					
						
							|  |  |  |                                   }).marginOnly(right: 15), | 
					
						
							| 
									
										
										
										
											2023-06-28 20:22:57 +08:00
										 |  |  |                               if (serverModel.approveMode != 'password') | 
					
						
							|  |  |  |                                 ElevatedButton.icon( | 
					
						
							|  |  |  |                                     icon: const Icon(Icons.check), | 
					
						
							|  |  |  |                                     label: Text(translate("Accept")), | 
					
						
							|  |  |  |                                     onPressed: () { | 
					
						
							|  |  |  |                                       serverModel.sendLoginResponse( | 
					
						
							|  |  |  |                                           client, true); | 
					
						
							|  |  |  |                                     }), | 
					
						
							| 
									
										
										
										
											2023-03-09 18:31:34 +01:00
										 |  |  |                             ]), | 
					
						
							|  |  |  |                 ]))) | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |             .toList()); | 
					
						
							| 
									
										
										
										
											2022-02-02 17:25:56 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  | class PaddingCard extends StatelessWidget { | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |   const PaddingCard({Key? key, required this.child, this.title, this.titleIcon}) | 
					
						
							|  |  |  |       : super(key: key); | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |   final String? title; | 
					
						
							| 
									
										
										
										
											2023-03-07 11:45:20 +01:00
										 |  |  |   final Icon? titleIcon; | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |   final Widget child; | 
					
						
							| 
									
										
										
										
											2022-02-02 17:25:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     final children = [child]; | 
					
						
							|  |  |  |     if (title != null) { | 
					
						
							|  |  |  |       children.insert( | 
					
						
							|  |  |  |           0, | 
					
						
							|  |  |  |           Padding( | 
					
						
							| 
									
										
										
										
											2023-03-07 12:12:31 +01:00
										 |  |  |               padding: const EdgeInsets.fromLTRB(0, 5, 0, 8), | 
					
						
							| 
									
										
										
										
											2022-03-22 21:47:42 +08:00
										 |  |  |               child: Row( | 
					
						
							|  |  |  |                 children: [ | 
					
						
							| 
									
										
										
										
											2023-03-09 18:31:34 +01:00
										 |  |  |                   titleIcon?.marginOnly(right: 10) ?? const SizedBox.shrink(), | 
					
						
							| 
									
										
										
										
											2023-03-07 11:45:20 +01:00
										 |  |  |                   Expanded( | 
					
						
							| 
									
										
										
										
											2023-03-09 12:09:45 +01:00
										 |  |  |                     child: Text(title!, | 
					
						
							|  |  |  |                         style: Theme.of(context) | 
					
						
							|  |  |  |                             .textTheme | 
					
						
							|  |  |  |                             .titleLarge | 
					
						
							|  |  |  |                             ?.merge(TextStyle(fontWeight: FontWeight.bold))), | 
					
						
							| 
									
										
										
										
											2022-03-22 21:47:42 +08:00
										 |  |  |                   ) | 
					
						
							|  |  |  |                 ], | 
					
						
							| 
									
										
										
										
											2022-03-25 16:34:27 +08:00
										 |  |  |               ))); | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |     return SizedBox( | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |         width: double.maxFinite, | 
					
						
							|  |  |  |         child: Card( | 
					
						
							| 
									
										
										
										
											2023-03-09 12:31:13 +01:00
										 |  |  |           shape: RoundedRectangleBorder( | 
					
						
							|  |  |  |             borderRadius: BorderRadius.circular(13), | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           margin: const EdgeInsets.fromLTRB(12.0, 10.0, 12.0, 0), | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |           child: Padding( | 
					
						
							| 
									
										
										
										
											2022-09-16 20:43:15 +08:00
										 |  |  |             padding: | 
					
						
							| 
									
										
										
										
											2023-03-09 18:31:34 +01:00
										 |  |  |                 const EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0), | 
					
						
							| 
									
										
										
										
											2022-03-22 16:40:23 +08:00
										 |  |  |             child: Column( | 
					
						
							|  |  |  |               children: children, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-02-02 17:25:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 21:53:50 +08:00
										 |  |  | class ClientInfo extends StatelessWidget { | 
					
						
							|  |  |  |   final Client client; | 
					
						
							|  |  |  |   ClientInfo(this.client); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return Padding( | 
					
						
							|  |  |  |         padding: const EdgeInsets.symmetric(vertical: 8), | 
					
						
							| 
									
										
										
										
											2023-03-09 18:31:34 +01:00
										 |  |  |         child: Column(children: [ | 
					
						
							| 
									
										
										
										
											2022-09-29 21:53:50 +08:00
										 |  |  |           Row( | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                   flex: -1, | 
					
						
							|  |  |  |                   child: Padding( | 
					
						
							|  |  |  |                       padding: const EdgeInsets.only(right: 12), | 
					
						
							|  |  |  |                       child: CircleAvatar( | 
					
						
							| 
									
										
										
										
											2023-03-07 14:19:28 +01:00
										 |  |  |                           backgroundColor: str2color( | 
					
						
							|  |  |  |                               client.name, | 
					
						
							|  |  |  |                               Theme.of(context).brightness == Brightness.light | 
					
						
							|  |  |  |                                   ? 255 | 
					
						
							|  |  |  |                                   : 150), | 
					
						
							| 
									
										
										
										
											2022-09-29 21:53:50 +08:00
										 |  |  |                           child: Text(client.name[0])))), | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                   child: Column( | 
					
						
							|  |  |  |                       crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |                       children: [ | 
					
						
							| 
									
										
										
										
											2023-03-07 12:12:31 +01:00
										 |  |  |                     Text(client.name, style: const TextStyle(fontSize: 18)), | 
					
						
							| 
									
										
										
										
											2022-09-29 21:53:50 +08:00
										 |  |  |                     const SizedBox(width: 8), | 
					
						
							| 
									
										
										
										
											2023-03-07 12:12:31 +01:00
										 |  |  |                     Text(client.peerId, style: const TextStyle(fontSize: 10)) | 
					
						
							| 
									
										
										
										
											2022-09-29 21:53:50 +08:00
										 |  |  |                   ])) | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ])); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-01-23 21:37:19 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-02-10 02:07:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-23 14:12:30 +08:00
										 |  |  | void androidChannelInit() { | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  |   gFFI.setMethodCallHandler((method, arguments) { | 
					
						
							| 
									
										
										
										
											2022-02-25 21:54:05 +08:00
										 |  |  |     debugPrint("flutter got android msg,$method,$arguments"); | 
					
						
							| 
									
										
										
										
											2022-02-10 02:07:53 +08:00
										 |  |  |     try { | 
					
						
							|  |  |  |       switch (method) { | 
					
						
							|  |  |  |         case "start_capture": | 
					
						
							|  |  |  |           { | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |             gFFI.dialogManager.dismissAll(); | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  |             gFFI.serverModel.updateClientState(); | 
					
						
							| 
									
										
										
										
											2022-02-10 02:07:53 +08:00
										 |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2022-04-04 14:54:00 +08:00
										 |  |  |         case "on_state_changed": | 
					
						
							| 
									
										
										
										
											2022-02-10 02:07:53 +08:00
										 |  |  |           { | 
					
						
							|  |  |  |             var name = arguments["name"] as String; | 
					
						
							|  |  |  |             var value = arguments["value"] as String == "true"; | 
					
						
							| 
									
										
										
										
											2022-04-04 14:54:00 +08:00
										 |  |  |             debugPrint("from jvm:on_state_changed,$name:$value"); | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  |             gFFI.serverModel.changeStatue(name, value); | 
					
						
							| 
									
										
										
										
											2022-02-10 02:07:53 +08:00
										 |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2022-04-04 14:54:00 +08:00
										 |  |  |         case "on_android_permission_result": | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             var type = arguments["type"] as String; | 
					
						
							|  |  |  |             var result = arguments["result"] as bool; | 
					
						
							| 
									
										
										
										
											2023-03-01 18:00:56 +01:00
										 |  |  |             AndroidPermissionManager.complete(type, result); | 
					
						
							| 
									
										
										
										
											2022-04-04 14:54:00 +08:00
										 |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2022-04-12 20:54:29 +08:00
										 |  |  |         case "on_media_projection_canceled": | 
					
						
							|  |  |  |           { | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  |             gFFI.serverModel.stopService(); | 
					
						
							| 
									
										
										
										
											2022-04-12 20:54:29 +08:00
										 |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2022-02-10 02:07:53 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } catch (e) { | 
					
						
							| 
									
										
										
										
											2022-12-09 10:49:47 +08:00
										 |  |  |       debugPrintStack(label: "MethodCallHandler err:$e"); | 
					
						
							| 
									
										
										
										
											2022-02-10 02:07:53 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return ""; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } |