| 
									
										
										
										
											2022-07-14 17:44:37 +08:00
										 |  |  | import 'dart:async'; | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  | import 'dart:convert'; | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-26 11:21:40 +08:00
										 |  |  | import 'package:get/get.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  | import 'package:provider/provider.dart'; | 
					
						
							|  |  |  | import 'package:settings_ui/settings_ui.dart'; | 
					
						
							|  |  |  | import 'package:url_launcher/url_launcher.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-24 23:33:00 +08:00
										 |  |  | import '../../common.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-26 11:21:40 +08:00
										 |  |  | import '../../common/widgets/dialog.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-24 23:33:00 +08:00
										 |  |  | import '../../models/model.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-05 20:29:43 +08:00
										 |  |  | import '../../models/platform_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-06-13 21:07:26 +08:00
										 |  |  | import '../widgets/dialog.dart'; | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  | import 'home_page.dart'; | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  | import 'scan_page.dart'; | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  | class SettingsPage extends StatefulWidget implements PageShape { | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-03-23 15:28:21 +08:00
										 |  |  |   final title = translate("Settings"); | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   final icon = Icon(Icons.settings); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |   final appBarActions = [ScanButton()]; | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-09-22 15:12:23 +08:00
										 |  |  |   State<SettingsPage> createState() => _SettingsState(); | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 17:24:02 +08:00
										 |  |  | const url = 'https://rustdesk.com/'; | 
					
						
							|  |  |  | final _hasIgnoreBattery = androidVersion >= 26; | 
					
						
							|  |  |  | var _ignoreBatteryOpt = false; | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  | var _enableAbr = false; | 
					
						
							| 
									
										
										
										
											2022-09-26 11:21:40 +08:00
										 |  |  | var _denyLANDiscovery = false; | 
					
						
							|  |  |  | var _onlyWhiteList = false; | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  | var _enableDirectIPAccess = false; | 
					
						
							| 
									
										
										
										
											2022-10-25 10:16:11 +09:00
										 |  |  | var _enableRecordSession = false; | 
					
						
							|  |  |  | var _autoRecordIncomingSession = false; | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  | var _localIP = ""; | 
					
						
							|  |  |  | var _directAccessPort = ""; | 
					
						
							| 
									
										
										
										
											2022-07-14 17:44:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 17:24:02 +08:00
										 |  |  | class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver { | 
					
						
							| 
									
										
										
										
											2022-07-14 17:44:37 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |     WidgetsBinding.instance.addObserver(this); | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     () async { | 
					
						
							|  |  |  |       var update = false; | 
					
						
							|  |  |  |       if (_hasIgnoreBattery) { | 
					
						
							|  |  |  |         update = await updateIgnoreBatteryStatus(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       final enableAbrRes = await bind.mainGetOption(key: "enable-abr") != "N"; | 
					
						
							|  |  |  |       if (enableAbrRes != _enableAbr) { | 
					
						
							|  |  |  |         update = true; | 
					
						
							|  |  |  |         _enableAbr = enableAbrRes; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 11:21:40 +08:00
										 |  |  |       final denyLanDiscovery = !option2bool('enable-lan-discovery', | 
					
						
							|  |  |  |           await bind.mainGetOption(key: 'enable-lan-discovery')); | 
					
						
							|  |  |  |       if (denyLanDiscovery != _denyLANDiscovery) { | 
					
						
							|  |  |  |         update = true; | 
					
						
							|  |  |  |         _denyLANDiscovery = denyLanDiscovery; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       final onlyWhiteList = | 
					
						
							|  |  |  |           (await bind.mainGetOption(key: 'whitelist')).isNotEmpty; | 
					
						
							|  |  |  |       if (onlyWhiteList != _onlyWhiteList) { | 
					
						
							|  |  |  |         update = true; | 
					
						
							|  |  |  |         _onlyWhiteList = onlyWhiteList; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  |       final enableDirectIPAccess = option2bool( | 
					
						
							|  |  |  |           'direct-server', await bind.mainGetOption(key: 'direct-server')); | 
					
						
							|  |  |  |       if (enableDirectIPAccess != _enableDirectIPAccess) { | 
					
						
							|  |  |  |         update = true; | 
					
						
							|  |  |  |         _enableDirectIPAccess = enableDirectIPAccess; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-25 10:16:11 +09:00
										 |  |  |       final enableRecordSession = option2bool('enable-record-session', | 
					
						
							|  |  |  |           await bind.mainGetOption(key: 'enable-record-session')); | 
					
						
							|  |  |  |       if (enableRecordSession != _enableRecordSession) { | 
					
						
							|  |  |  |         update = true; | 
					
						
							|  |  |  |         _enableRecordSession = enableRecordSession; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       final autoRecordIncomingSession = option2bool( | 
					
						
							|  |  |  |           'allow-auto-record-incoming', | 
					
						
							|  |  |  |           await bind.mainGetOption(key: 'allow-auto-record-incoming')); | 
					
						
							|  |  |  |       if (autoRecordIncomingSession != _autoRecordIncomingSession) { | 
					
						
							|  |  |  |         update = true; | 
					
						
							|  |  |  |         _autoRecordIncomingSession = autoRecordIncomingSession; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  |       final localIP = await bind.mainGetOption(key: 'local-ip-addr'); | 
					
						
							|  |  |  |       if (localIP != _localIP) { | 
					
						
							|  |  |  |         update = true; | 
					
						
							|  |  |  |         _localIP = localIP; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       final directAccessPort = | 
					
						
							|  |  |  |           await bind.mainGetOption(key: 'direct-access-port'); | 
					
						
							|  |  |  |       if (directAccessPort != _directAccessPort) { | 
					
						
							|  |  |  |         update = true; | 
					
						
							|  |  |  |         _directAccessPort = directAccessPort; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  |       if (update) { | 
					
						
							|  |  |  |         setState(() {}); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }(); | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     WidgetsBinding.instance.removeObserver(this); | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void didChangeAppLifecycleState(AppLifecycleState state) { | 
					
						
							|  |  |  |     if (state == AppLifecycleState.resumed) { | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  |       () async { | 
					
						
							|  |  |  |         if (await updateIgnoreBatteryStatus()) { | 
					
						
							|  |  |  |           setState(() {}); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }(); | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<bool> updateIgnoreBatteryStatus() async { | 
					
						
							|  |  |  |     final res = await PermissionManager.check("ignore_battery_optimizations"); | 
					
						
							|  |  |  |     if (_ignoreBatteryOpt != res) { | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  |       _ignoreBatteryOpt = res; | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |       return true; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return false; | 
					
						
							| 
									
										
										
										
											2022-07-14 17:44:37 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |     Provider.of<FfiModel>(context); | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  |     final List<AbstractSettingsTile> enhancementsTiles = []; | 
					
						
							|  |  |  |     final List<AbstractSettingsTile> shareScreenTiles = [ | 
					
						
							| 
									
										
										
										
											2022-09-26 11:21:40 +08:00
										 |  |  |       SettingsTile.switchTile( | 
					
						
							|  |  |  |         title: Text(translate('Deny LAN Discovery')), | 
					
						
							|  |  |  |         initialValue: _denyLANDiscovery, | 
					
						
							|  |  |  |         onToggle: (v) async { | 
					
						
							|  |  |  |           await bind.mainSetOption( | 
					
						
							|  |  |  |               key: "enable-lan-discovery", | 
					
						
							|  |  |  |               value: bool2option("enable-lan-discovery", !v)); | 
					
						
							|  |  |  |           final newValue = !option2bool('enable-lan-discovery', | 
					
						
							|  |  |  |               await bind.mainGetOption(key: 'enable-lan-discovery')); | 
					
						
							|  |  |  |           setState(() { | 
					
						
							|  |  |  |             _denyLANDiscovery = newValue; | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |       SettingsTile.switchTile( | 
					
						
							|  |  |  |         title: Row(children: [ | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  |           Expanded(child: Text(translate('Use IP Whitelisting'))), | 
					
						
							| 
									
										
										
										
											2022-09-26 11:21:40 +08:00
										 |  |  |           Offstage( | 
					
						
							|  |  |  |                   offstage: !_onlyWhiteList, | 
					
						
							|  |  |  |                   child: const Icon(Icons.warning_amber_rounded, | 
					
						
							|  |  |  |                       color: Color.fromARGB(255, 255, 204, 0))) | 
					
						
							|  |  |  |               .marginOnly(left: 5) | 
					
						
							|  |  |  |         ]), | 
					
						
							|  |  |  |         initialValue: _onlyWhiteList, | 
					
						
							|  |  |  |         onToggle: (_) async { | 
					
						
							|  |  |  |           update() async { | 
					
						
							|  |  |  |             final onlyWhiteList = | 
					
						
							|  |  |  |                 (await bind.mainGetOption(key: 'whitelist')).isNotEmpty; | 
					
						
							|  |  |  |             if (onlyWhiteList != _onlyWhiteList) { | 
					
						
							|  |  |  |               setState(() { | 
					
						
							|  |  |  |                 _onlyWhiteList = onlyWhiteList; | 
					
						
							|  |  |  |               }); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           changeWhiteList(callback: update); | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  |       ), | 
					
						
							|  |  |  |       SettingsTile.switchTile( | 
					
						
							|  |  |  |         title: Text('${translate('Adaptive Bitrate')} (beta)'), | 
					
						
							|  |  |  |         initialValue: _enableAbr, | 
					
						
							|  |  |  |         onToggle: (v) async { | 
					
						
							|  |  |  |           await bind.mainSetOption(key: "enable-abr", value: v ? "" : "N"); | 
					
						
							|  |  |  |           final newValue = await bind.mainGetOption(key: "enable-abr") != "N"; | 
					
						
							|  |  |  |           setState(() { | 
					
						
							|  |  |  |             _enableAbr = newValue; | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       ), | 
					
						
							| 
									
										
										
										
											2022-10-25 10:16:11 +09:00
										 |  |  |       SettingsTile.switchTile( | 
					
						
							|  |  |  |         title: Text(translate('Enable Recording Session')), | 
					
						
							|  |  |  |         initialValue: _enableRecordSession, | 
					
						
							|  |  |  |         onToggle: (v) async { | 
					
						
							|  |  |  |           await bind.mainSetOption( | 
					
						
							|  |  |  |               key: "enable-record-session", value: v ? "" : "N"); | 
					
						
							|  |  |  |           final newValue = | 
					
						
							|  |  |  |               await bind.mainGetOption(key: "enable-record-session") != "N"; | 
					
						
							|  |  |  |           setState(() { | 
					
						
							|  |  |  |             _enableRecordSession = newValue; | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       ), | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  |       SettingsTile.switchTile( | 
					
						
							|  |  |  |         title: Row( | 
					
						
							|  |  |  |             mainAxisAlignment: MainAxisAlignment.spaceBetween, | 
					
						
							|  |  |  |             crossAxisAlignment: CrossAxisAlignment.center, | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                   child: Column( | 
					
						
							|  |  |  |                       crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |                       children: [ | 
					
						
							|  |  |  |                     Text(translate("Direct IP Access")), | 
					
						
							|  |  |  |                     Offstage( | 
					
						
							|  |  |  |                         offstage: !_enableDirectIPAccess, | 
					
						
							|  |  |  |                         child: Text( | 
					
						
							|  |  |  |                           '${translate("Local Address")}: $_localIP${_directAccessPort.isEmpty ? "" : ":$_directAccessPort"}', | 
					
						
							|  |  |  |                           style: Theme.of(context).textTheme.bodySmall, | 
					
						
							|  |  |  |                         )), | 
					
						
							|  |  |  |                   ])), | 
					
						
							|  |  |  |               Offstage( | 
					
						
							|  |  |  |                   offstage: !_enableDirectIPAccess, | 
					
						
							|  |  |  |                   child: IconButton( | 
					
						
							|  |  |  |                       padding: EdgeInsets.zero, | 
					
						
							|  |  |  |                       icon: Icon( | 
					
						
							|  |  |  |                         Icons.edit, | 
					
						
							|  |  |  |                         size: 20, | 
					
						
							|  |  |  |                       ), | 
					
						
							|  |  |  |                       onPressed: () async { | 
					
						
							|  |  |  |                         final port = await changeDirectAccessPort( | 
					
						
							|  |  |  |                             _localIP, _directAccessPort); | 
					
						
							|  |  |  |                         setState(() { | 
					
						
							|  |  |  |                           _directAccessPort = port; | 
					
						
							|  |  |  |                         }); | 
					
						
							|  |  |  |                       })) | 
					
						
							|  |  |  |             ]), | 
					
						
							|  |  |  |         initialValue: _enableDirectIPAccess, | 
					
						
							|  |  |  |         onToggle: (_) async { | 
					
						
							|  |  |  |           _enableDirectIPAccess = !_enableDirectIPAccess; | 
					
						
							|  |  |  |           String value = bool2option('direct-server', _enableDirectIPAccess); | 
					
						
							|  |  |  |           await bind.mainSetOption(key: 'direct-server', value: value); | 
					
						
							|  |  |  |           setState(() {}); | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2022-09-26 11:21:40 +08:00
										 |  |  |       ) | 
					
						
							|  |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |     if (_hasIgnoreBattery) { | 
					
						
							| 
									
										
										
										
											2022-07-14 18:33:41 +08:00
										 |  |  |       enhancementsTiles.insert( | 
					
						
							|  |  |  |           0, | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |           SettingsTile.switchTile( | 
					
						
							|  |  |  |               initialValue: _ignoreBatteryOpt, | 
					
						
							| 
									
										
										
										
											2022-09-29 13:07:20 +08:00
										 |  |  |               title: Column( | 
					
						
							|  |  |  |                   crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |                   children: [ | 
					
						
							|  |  |  |                     Text(translate('Keep RustDesk background service')), | 
					
						
							|  |  |  |                     Text('* ${translate('Ignore Battery Optimizations')}', | 
					
						
							|  |  |  |                         style: Theme.of(context).textTheme.bodySmall), | 
					
						
							|  |  |  |                   ]), | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |               onToggle: (v) async { | 
					
						
							|  |  |  |                 if (v) { | 
					
						
							|  |  |  |                   PermissionManager.request("ignore_battery_optimizations"); | 
					
						
							|  |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |                   final res = await gFFI.dialogManager | 
					
						
							|  |  |  |                       .show<bool>((setState, close) => CustomAlertDialog( | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |                             title: Text(translate("Open System Setting")), | 
					
						
							|  |  |  |                             content: Text(translate( | 
					
						
							|  |  |  |                                 "android_open_battery_optimizations_tip")), | 
					
						
							|  |  |  |                             actions: [ | 
					
						
							|  |  |  |                               TextButton( | 
					
						
							|  |  |  |                                   onPressed: () => close(), | 
					
						
							|  |  |  |                                   child: Text(translate("Cancel"))), | 
					
						
							|  |  |  |                               ElevatedButton( | 
					
						
							|  |  |  |                                   onPressed: () => close(true), | 
					
						
							|  |  |  |                                   child: | 
					
						
							|  |  |  |                                       Text(translate("Open System Setting"))), | 
					
						
							|  |  |  |                             ], | 
					
						
							|  |  |  |                           )); | 
					
						
							|  |  |  |                   if (res == true) { | 
					
						
							|  |  |  |                     PermissionManager.request("application_details_settings"); | 
					
						
							| 
									
										
										
										
											2022-07-14 18:33:41 +08:00
										 |  |  |                   } | 
					
						
							| 
									
										
										
										
											2022-07-16 22:31:44 +08:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-07-14 18:33:41 +08:00
										 |  |  |               })); | 
					
						
							| 
									
										
										
										
											2022-07-14 17:44:37 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  |     return SettingsList( | 
					
						
							|  |  |  |       sections: [ | 
					
						
							|  |  |  |         SettingsSection( | 
					
						
							| 
									
										
										
										
											2022-10-22 22:19:14 +08:00
										 |  |  |           title: Text(translate('Account')), | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |           tiles: [ | 
					
						
							|  |  |  |             SettingsTile.navigation( | 
					
						
							| 
									
										
										
										
											2022-10-09 19:41:50 +09:00
										 |  |  |               title: Obx(() => Text(gFFI.userModel.userName.value.isEmpty | 
					
						
							| 
									
										
										
										
											2022-10-22 22:19:14 +08:00
										 |  |  |                   ? translate('Login') | 
					
						
							|  |  |  |                   : '${translate('Logout')} (${gFFI.userModel.userName.value})')), | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |               leading: Icon(Icons.person), | 
					
						
							|  |  |  |               onPressed: (context) { | 
					
						
							| 
									
										
										
										
											2022-10-09 19:41:50 +09:00
										 |  |  |                 if (gFFI.userModel.userName.value.isEmpty) { | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |                   showLogin(gFFI.dialogManager); | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2022-10-09 19:41:50 +09:00
										 |  |  |                   gFFI.userModel.logOut(); | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |                 } | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-07-14 18:33:41 +08:00
										 |  |  |         SettingsSection(title: Text(translate("Settings")), tiles: [ | 
					
						
							|  |  |  |           SettingsTile.navigation( | 
					
						
							| 
									
										
										
										
											2022-03-24 21:31:47 +08:00
										 |  |  |               title: Text(translate('ID/Relay Server')), | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  |               leading: Icon(Icons.cloud), | 
					
						
							|  |  |  |               onPressed: (context) { | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |                 showServerSettings(gFFI.dialogManager); | 
					
						
							| 
									
										
										
										
											2022-08-04 17:24:02 +08:00
										 |  |  |               }), | 
					
						
							|  |  |  |           SettingsTile.navigation( | 
					
						
							|  |  |  |               title: Text(translate('Language')), | 
					
						
							|  |  |  |               leading: Icon(Icons.translate), | 
					
						
							|  |  |  |               onPressed: (context) { | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |                 showLanguageSettings(gFFI.dialogManager); | 
					
						
							| 
									
										
										
										
											2022-09-19 20:26:39 +08:00
										 |  |  |               }), | 
					
						
							| 
									
										
										
										
											2022-09-22 15:12:23 +08:00
										 |  |  |           SettingsTile.navigation( | 
					
						
							| 
									
										
										
										
											2022-09-19 20:26:39 +08:00
										 |  |  |             title: Text(translate('Dark Theme')), | 
					
						
							|  |  |  |             leading: Icon(Icons.dark_mode), | 
					
						
							| 
									
										
										
										
											2022-09-22 15:12:23 +08:00
										 |  |  |             onPressed: (context) { | 
					
						
							|  |  |  |               showThemeSettings(gFFI.dialogManager); | 
					
						
							| 
									
										
										
										
											2022-09-19 20:26:39 +08:00
										 |  |  |             }, | 
					
						
							|  |  |  |           ) | 
					
						
							| 
									
										
										
										
											2022-07-14 18:33:41 +08:00
										 |  |  |         ]), | 
					
						
							| 
									
										
										
										
											2022-10-25 10:16:11 +09:00
										 |  |  |         SettingsSection( | 
					
						
							|  |  |  |           title: Text(translate("Recording")), | 
					
						
							|  |  |  |           tiles: [ | 
					
						
							|  |  |  |             SettingsTile.switchTile( | 
					
						
							|  |  |  |               title: Text(translate('Automatically record incoming sessions')), | 
					
						
							|  |  |  |               leading: Icon(Icons.videocam), | 
					
						
							|  |  |  |               description: FutureBuilder( | 
					
						
							|  |  |  |                   builder: (ctx, data) => Offstage( | 
					
						
							|  |  |  |                       offstage: !data.hasData, | 
					
						
							|  |  |  |                       child: Text("${translate("Directory")}: ${data.data}")), | 
					
						
							|  |  |  |                   future: bind.mainDefaultVideoSaveDirectory()), | 
					
						
							|  |  |  |               initialValue: _autoRecordIncomingSession, | 
					
						
							|  |  |  |               onToggle: (v) async { | 
					
						
							|  |  |  |                 await bind.mainSetOption( | 
					
						
							|  |  |  |                     key: "allow-auto-record-incoming", | 
					
						
							|  |  |  |                     value: bool2option("allow-auto-record-incoming", v)); | 
					
						
							|  |  |  |                 final newValue = option2bool( | 
					
						
							|  |  |  |                     'allow-auto-record-incoming', | 
					
						
							|  |  |  |                     await bind.mainGetOption( | 
					
						
							|  |  |  |                         key: 'allow-auto-record-incoming')); | 
					
						
							|  |  |  |                 setState(() { | 
					
						
							|  |  |  |                   _autoRecordIncomingSession = newValue; | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-09-26 11:21:40 +08:00
										 |  |  |         SettingsSection( | 
					
						
							|  |  |  |           title: Text(translate("Share Screen")), | 
					
						
							|  |  |  |           tiles: shareScreenTiles, | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |         SettingsSection( | 
					
						
							| 
									
										
										
										
											2022-07-14 18:33:41 +08:00
										 |  |  |           title: Text(translate("Enhancements")), | 
					
						
							|  |  |  |           tiles: enhancementsTiles, | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  |         ), | 
					
						
							|  |  |  |         SettingsSection( | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |           title: Text(translate("About")), | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  |           tiles: [ | 
					
						
							|  |  |  |             SettingsTile.navigation( | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |                 onPressed: (context) async { | 
					
						
							| 
									
										
										
										
											2022-06-19 17:15:37 +01:00
										 |  |  |                   if (await canLaunchUrl(Uri.parse(url))) { | 
					
						
							|  |  |  |                     await launchUrl(Uri.parse(url)); | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |                   } | 
					
						
							|  |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |                 title: Text(translate("Version: ") + version), | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  |                 value: Padding( | 
					
						
							|  |  |  |                   padding: EdgeInsets.symmetric(vertical: 8), | 
					
						
							|  |  |  |                   child: Text('rustdesk.com', | 
					
						
							|  |  |  |                       style: TextStyle( | 
					
						
							|  |  |  |                         decoration: TextDecoration.underline, | 
					
						
							|  |  |  |                       )), | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  |                 ), | 
					
						
							|  |  |  |                 leading: Icon(Icons.info)), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  | void showServerSettings(OverlayDialogManager dialogManager) async { | 
					
						
							| 
									
										
										
										
											2022-08-08 17:53:51 +08:00
										 |  |  |   Map<String, dynamic> options = jsonDecode(await bind.mainGetOptions()); | 
					
						
							|  |  |  |   String id = options['custom-rendezvous-server'] ?? ""; | 
					
						
							|  |  |  |   String relay = options['relay-server'] ?? ""; | 
					
						
							|  |  |  |   String api = options['api-server'] ?? ""; | 
					
						
							|  |  |  |   String key = options['key'] ?? ""; | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |   showServerSettingsWithValue(id, relay, key, api, dialogManager); | 
					
						
							| 
									
										
										
										
											2022-02-28 21:26:44 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-03-24 20:57:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  | void showLanguageSettings(OverlayDialogManager dialogManager) async { | 
					
						
							| 
									
										
										
										
											2022-08-04 17:24:02 +08:00
										 |  |  |   try { | 
					
						
							| 
									
										
										
										
											2022-08-08 22:27:27 +08:00
										 |  |  |     final langs = json.decode(await bind.mainGetLangs()) as List<dynamic>; | 
					
						
							| 
									
										
										
										
											2022-08-05 20:29:43 +08:00
										 |  |  |     var lang = await bind.mainGetLocalOption(key: "lang"); | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |     dialogManager.show((setState, close) { | 
					
						
							| 
									
										
										
										
											2022-09-22 15:12:23 +08:00
										 |  |  |       setLang(v) { | 
					
						
							| 
									
										
										
										
											2022-08-04 17:24:02 +08:00
										 |  |  |         if (lang != v) { | 
					
						
							|  |  |  |           setState(() { | 
					
						
							|  |  |  |             lang = v; | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2022-08-05 20:29:43 +08:00
										 |  |  |           bind.mainSetLocalOption(key: "lang", value: v); | 
					
						
							|  |  |  |           HomePage.homeKey.currentState?.refreshPages(); | 
					
						
							| 
									
										
										
										
											2022-08-04 17:24:02 +08:00
										 |  |  |           Future.delayed(Duration(milliseconds: 200), close); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-22 15:12:23 +08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-04 17:24:02 +08:00
										 |  |  |       return CustomAlertDialog( | 
					
						
							|  |  |  |           title: SizedBox.shrink(), | 
					
						
							|  |  |  |           content: Column( | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |                   getRadio('Default', '', lang, setLang), | 
					
						
							|  |  |  |                   Divider(color: MyTheme.border), | 
					
						
							|  |  |  |                 ] + | 
					
						
							|  |  |  |                 langs.map((e) { | 
					
						
							|  |  |  |                   final key = e[0] as String; | 
					
						
							|  |  |  |                   final name = e[1] as String; | 
					
						
							|  |  |  |                   return getRadio(name, key, lang, setLang); | 
					
						
							|  |  |  |                 }).toList(), | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           actions: []); | 
					
						
							|  |  |  |     }, backDismiss: true, clickMaskDismiss: true); | 
					
						
							| 
									
										
										
										
											2022-09-22 15:12:23 +08:00
										 |  |  |   } catch (e) { | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void showThemeSettings(OverlayDialogManager dialogManager) async { | 
					
						
							|  |  |  |   var themeMode = MyTheme.getThemeModePreference(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dialogManager.show((setState, close) { | 
					
						
							|  |  |  |     setTheme(v) { | 
					
						
							|  |  |  |       if (themeMode != v) { | 
					
						
							|  |  |  |         setState(() { | 
					
						
							|  |  |  |           themeMode = v; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         MyTheme.changeDarkMode(themeMode); | 
					
						
							|  |  |  |         Future.delayed(Duration(milliseconds: 200), close); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |         title: SizedBox.shrink(), | 
					
						
							|  |  |  |         contentPadding: 10, | 
					
						
							|  |  |  |         content: Column(children: [ | 
					
						
							|  |  |  |           getRadio('Light', ThemeMode.light, themeMode, setTheme), | 
					
						
							|  |  |  |           getRadio('Dark', ThemeMode.dark, themeMode, setTheme), | 
					
						
							|  |  |  |           getRadio('Follow System', ThemeMode.system, themeMode, setTheme) | 
					
						
							|  |  |  |         ]), | 
					
						
							|  |  |  |         actions: []); | 
					
						
							|  |  |  |   }, backDismiss: true, clickMaskDismiss: true); | 
					
						
							| 
									
										
										
										
											2022-08-04 17:24:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  | void showAbout(OverlayDialogManager dialogManager) { | 
					
						
							|  |  |  |   dialogManager.show((setState, close) { | 
					
						
							| 
									
										
										
										
											2022-03-24 20:57:30 +08:00
										 |  |  |     return CustomAlertDialog( | 
					
						
							| 
									
										
										
										
											2022-09-22 15:12:23 +08:00
										 |  |  |       title: Text('${translate('About')} RustDesk'), | 
					
						
							| 
									
										
										
										
											2022-03-24 20:57:30 +08:00
										 |  |  |       content: Wrap(direction: Axis.vertical, spacing: 12, children: [ | 
					
						
							|  |  |  |         Text('Version: $version'), | 
					
						
							|  |  |  |         InkWell( | 
					
						
							|  |  |  |             onTap: () async { | 
					
						
							|  |  |  |               const url = 'https://rustdesk.com/'; | 
					
						
							| 
									
										
										
										
											2022-06-19 17:15:37 +01:00
										 |  |  |               if (await canLaunchUrl(Uri.parse(url))) { | 
					
						
							|  |  |  |                 await launchUrl(Uri.parse(url)); | 
					
						
							| 
									
										
										
										
											2022-03-24 20:57:30 +08:00
										 |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             child: Padding( | 
					
						
							|  |  |  |               padding: EdgeInsets.symmetric(vertical: 8), | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |               child: Text('rustdesk.com', | 
					
						
							| 
									
										
										
										
											2022-03-24 20:57:30 +08:00
										 |  |  |                   style: TextStyle( | 
					
						
							|  |  |  |                     decoration: TextDecoration.underline, | 
					
						
							|  |  |  |                   )), | 
					
						
							|  |  |  |             )), | 
					
						
							|  |  |  |       ]), | 
					
						
							| 
									
										
										
										
											2022-03-24 21:23:22 +08:00
										 |  |  |       actions: [], | 
					
						
							| 
									
										
										
										
											2022-03-24 20:57:30 +08:00
										 |  |  |     ); | 
					
						
							| 
									
										
										
										
											2022-04-21 10:02:47 +08:00
										 |  |  |   }, clickMaskDismiss: true, backDismiss: true); | 
					
						
							| 
									
										
										
										
											2022-03-24 20:57:30 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  | void showLogin(OverlayDialogManager dialogManager) { | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |   final passwordController = TextEditingController(); | 
					
						
							|  |  |  |   final nameController = TextEditingController(); | 
					
						
							|  |  |  |   var loading = false; | 
					
						
							|  |  |  |   var error = ''; | 
					
						
							| 
									
										
										
										
											2022-08-12 18:42:02 +08:00
										 |  |  |   dialogManager.show((setState, close) { | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |     return CustomAlertDialog( | 
					
						
							|  |  |  |       title: Text(translate('Login')), | 
					
						
							|  |  |  |       content: Column(mainAxisSize: MainAxisSize.min, children: [ | 
					
						
							|  |  |  |         TextField( | 
					
						
							|  |  |  |           autofocus: true, | 
					
						
							|  |  |  |           autocorrect: false, | 
					
						
							|  |  |  |           enableSuggestions: false, | 
					
						
							|  |  |  |           keyboardType: TextInputType.visiblePassword, | 
					
						
							|  |  |  |           decoration: InputDecoration( | 
					
						
							|  |  |  |             labelText: translate('Username'), | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           controller: nameController, | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2022-09-22 17:38:18 +08:00
										 |  |  |         PasswordWidget(controller: passwordController, autoFocus: false), | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |       ]), | 
					
						
							|  |  |  |       actions: (loading | 
					
						
							|  |  |  |               ? <Widget>[CircularProgressIndicator()] | 
					
						
							|  |  |  |               : (error != "" | 
					
						
							|  |  |  |                   ? <Widget>[ | 
					
						
							|  |  |  |                       Text(translate(error), | 
					
						
							|  |  |  |                           style: TextStyle(color: Colors.red)) | 
					
						
							|  |  |  |                     ] | 
					
						
							|  |  |  |                   : <Widget>[])) + | 
					
						
							|  |  |  |           <Widget>[ | 
					
						
							|  |  |  |             TextButton( | 
					
						
							|  |  |  |               style: flatButtonStyle, | 
					
						
							|  |  |  |               onPressed: loading | 
					
						
							|  |  |  |                   ? null | 
					
						
							|  |  |  |                   : () { | 
					
						
							|  |  |  |                       close(); | 
					
						
							|  |  |  |                       setState(() { | 
					
						
							|  |  |  |                         loading = false; | 
					
						
							|  |  |  |                       }); | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |               child: Text(translate('Cancel')), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             TextButton( | 
					
						
							|  |  |  |               style: flatButtonStyle, | 
					
						
							|  |  |  |               onPressed: loading | 
					
						
							|  |  |  |                   ? null | 
					
						
							|  |  |  |                   : () async { | 
					
						
							|  |  |  |                       final name = nameController.text.trim(); | 
					
						
							|  |  |  |                       final pass = passwordController.text.trim(); | 
					
						
							|  |  |  |                       if (name != "" && pass != "") { | 
					
						
							|  |  |  |                         setState(() { | 
					
						
							|  |  |  |                           loading = true; | 
					
						
							|  |  |  |                         }); | 
					
						
							| 
									
										
										
										
											2022-10-09 19:41:50 +09:00
										 |  |  |                         final resp = await gFFI.userModel.login(name, pass); | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |                         setState(() { | 
					
						
							|  |  |  |                           loading = false; | 
					
						
							|  |  |  |                         }); | 
					
						
							| 
									
										
										
										
											2022-10-09 19:41:50 +09:00
										 |  |  |                         if (resp.containsKey('error')) { | 
					
						
							|  |  |  |                           error = resp['error']; | 
					
						
							|  |  |  |                           return; | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-10-09 19:41:50 +09:00
										 |  |  |                         gFFI.abModel.pullAb(); | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |                       } | 
					
						
							| 
									
										
										
										
											2022-10-09 19:41:50 +09:00
										 |  |  |                       close(); | 
					
						
							| 
									
										
										
										
											2022-03-28 15:44:45 +08:00
										 |  |  |                     }, | 
					
						
							|  |  |  |               child: Text(translate('OK')), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-15 17:50:15 +08:00
										 |  |  | class ScanButton extends StatelessWidget { | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return IconButton( | 
					
						
							|  |  |  |       icon: Icon(Icons.qr_code_scanner), | 
					
						
							|  |  |  |       onPressed: () { | 
					
						
							|  |  |  |         Navigator.push( | 
					
						
							|  |  |  |           context, | 
					
						
							|  |  |  |           MaterialPageRoute( | 
					
						
							|  |  |  |             builder: (BuildContext context) => ScanPage(), | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |