| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  | import 'package:debounce_throttle/debounce_throttle.dart'; | 
					
						
							|  |  |  | import 'package:flutter/material.dart'; | 
					
						
							|  |  |  | import 'package:flutter/services.dart'; | 
					
						
							|  |  |  | import 'package:flutter_hbb/common.dart'; | 
					
						
							| 
									
										
										
										
											2023-11-13 19:29:16 +08:00
										 |  |  | import 'package:flutter_hbb/consts.dart'; | 
					
						
							| 
									
										
										
										
											2023-12-11 15:32:13 +08:00
										 |  |  | import 'package:flutter_hbb/models/desktop_render_texture.dart'; | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  | import 'package:flutter_hbb/models/platform_model.dart'; | 
					
						
							|  |  |  | import 'package:get/get.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | customImageQualityWidget( | 
					
						
							|  |  |  |     {required double initQuality, | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |     required double initFps, | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |     required Function(double) setQuality, | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |     required Function(double) setFps, | 
					
						
							|  |  |  |     required bool showFps, | 
					
						
							| 
									
										
										
										
											2023-11-02 20:39:56 +08:00
										 |  |  |     required bool showMoreQuality}) { | 
					
						
							| 
									
										
										
										
											2023-11-13 19:29:16 +08:00
										 |  |  |   if (initQuality < kMinQuality || | 
					
						
							|  |  |  |       initQuality > (showMoreQuality ? kMaxMoreQuality : kMaxQuality)) { | 
					
						
							|  |  |  |     initQuality = kDefaultQuality; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (initFps < kMinFps || initFps > kMaxFps) { | 
					
						
							|  |  |  |     initFps = kDefaultFps; | 
					
						
							| 
									
										
										
										
											2023-11-02 20:39:56 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |   final qualityValue = initQuality.obs; | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |   final fpsValue = initFps.obs; | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-13 19:29:16 +08:00
										 |  |  |   final RxBool moreQualityChecked = RxBool(qualityValue.value > kMaxQuality); | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |   final debouncerQuality = Debouncer<double>( | 
					
						
							|  |  |  |     Duration(milliseconds: 1000), | 
					
						
							|  |  |  |     onChanged: (double v) { | 
					
						
							|  |  |  |       setQuality(v); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     initialValue: qualityValue.value, | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |   final debouncerFps = Debouncer<double>( | 
					
						
							|  |  |  |     Duration(milliseconds: 1000), | 
					
						
							|  |  |  |     onChanged: (double v) { | 
					
						
							|  |  |  |       setFps(v); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     initialValue: fpsValue.value, | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   onMoreChanged(bool? value) { | 
					
						
							|  |  |  |     if (value == null) return; | 
					
						
							|  |  |  |     moreQualityChecked.value = value; | 
					
						
							|  |  |  |     if (!value && qualityValue.value > 100) { | 
					
						
							|  |  |  |       qualityValue.value = 100; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     debouncerQuality.value = qualityValue.value; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return Column( | 
					
						
							|  |  |  |     children: [ | 
					
						
							|  |  |  |       Obx(() => Row( | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                 flex: 3, | 
					
						
							|  |  |  |                 child: Slider( | 
					
						
							|  |  |  |                   value: qualityValue.value, | 
					
						
							| 
									
										
										
										
											2023-11-13 19:29:16 +08:00
										 |  |  |                   min: kMinQuality, | 
					
						
							|  |  |  |                   max: moreQualityChecked.value ? kMaxMoreQuality : kMaxQuality, | 
					
						
							|  |  |  |                   divisions: moreQualityChecked.value | 
					
						
							|  |  |  |                       ? ((kMaxMoreQuality - kMinQuality) / 10).round() | 
					
						
							|  |  |  |                       : ((kMaxQuality - kMinQuality) / 5).round(), | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |                   onChanged: (double value) async { | 
					
						
							|  |  |  |                     qualityValue.value = value; | 
					
						
							|  |  |  |                     debouncerQuality.value = value; | 
					
						
							|  |  |  |                   }, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                   flex: 1, | 
					
						
							|  |  |  |                   child: Text( | 
					
						
							|  |  |  |                     '${qualityValue.value.round()}%', | 
					
						
							|  |  |  |                     style: const TextStyle(fontSize: 15), | 
					
						
							|  |  |  |                   )), | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                   flex: isMobile ? 2 : 1, | 
					
						
							|  |  |  |                   child: Text( | 
					
						
							|  |  |  |                     translate('Bitrate'), | 
					
						
							|  |  |  |                     style: const TextStyle(fontSize: 15), | 
					
						
							|  |  |  |                   )), | 
					
						
							|  |  |  |               // mobile doesn't have enough space
 | 
					
						
							| 
									
										
										
										
											2023-11-02 20:39:56 +08:00
										 |  |  |               if (showMoreQuality && !isMobile) | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |                 Expanded( | 
					
						
							|  |  |  |                     flex: 1, | 
					
						
							|  |  |  |                     child: Row( | 
					
						
							|  |  |  |                       children: [ | 
					
						
							|  |  |  |                         Checkbox( | 
					
						
							|  |  |  |                           value: moreQualityChecked.value, | 
					
						
							|  |  |  |                           onChanged: onMoreChanged, | 
					
						
							|  |  |  |                         ), | 
					
						
							|  |  |  |                         Expanded( | 
					
						
							|  |  |  |                           child: Text(translate('More')), | 
					
						
							|  |  |  |                         ) | 
					
						
							|  |  |  |                       ], | 
					
						
							|  |  |  |                     )) | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           )), | 
					
						
							| 
									
										
										
										
											2023-11-02 20:39:56 +08:00
										 |  |  |       if (showMoreQuality && isMobile) | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |         Obx(() => Row( | 
					
						
							|  |  |  |               children: [ | 
					
						
							|  |  |  |                 Expanded( | 
					
						
							|  |  |  |                   child: Align( | 
					
						
							|  |  |  |                     alignment: Alignment.centerRight, | 
					
						
							|  |  |  |                     child: Checkbox( | 
					
						
							|  |  |  |                       value: moreQualityChecked.value, | 
					
						
							|  |  |  |                       onChanged: onMoreChanged, | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 Expanded( | 
					
						
							|  |  |  |                   child: Text(translate('More')), | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |               ], | 
					
						
							|  |  |  |             )), | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |       if (showFps) | 
					
						
							|  |  |  |         Obx(() => Row( | 
					
						
							|  |  |  |               children: [ | 
					
						
							|  |  |  |                 Expanded( | 
					
						
							|  |  |  |                   flex: 3, | 
					
						
							|  |  |  |                   child: Slider( | 
					
						
							|  |  |  |                     value: fpsValue.value, | 
					
						
							| 
									
										
										
										
											2023-11-13 19:29:16 +08:00
										 |  |  |                     min: kMinFps, | 
					
						
							|  |  |  |                     max: kMaxFps, | 
					
						
							|  |  |  |                     divisions: ((kMaxFps - kMinFps) / 5).round(), | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |                     onChanged: (double value) async { | 
					
						
							|  |  |  |                       fpsValue.value = value; | 
					
						
							|  |  |  |                       debouncerFps.value = value; | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 Expanded( | 
					
						
							|  |  |  |                     flex: 1, | 
					
						
							|  |  |  |                     child: Text( | 
					
						
							|  |  |  |                       '${fpsValue.value.round()}', | 
					
						
							|  |  |  |                       style: const TextStyle(fontSize: 15), | 
					
						
							|  |  |  |                     )), | 
					
						
							|  |  |  |                 Expanded( | 
					
						
							|  |  |  |                     flex: 2, | 
					
						
							|  |  |  |                     child: Text( | 
					
						
							|  |  |  |                       translate('FPS'), | 
					
						
							|  |  |  |                       style: const TextStyle(fontSize: 15), | 
					
						
							|  |  |  |                     )) | 
					
						
							|  |  |  |               ], | 
					
						
							|  |  |  |             )), | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |     ], | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | customImageQualitySetting() { | 
					
						
							|  |  |  |   final qualityKey = 'custom_image_quality'; | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |   final fpsKey = 'custom-fps'; | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   var initQuality = | 
					
						
							| 
									
										
										
										
											2023-11-13 19:29:16 +08:00
										 |  |  |       (double.tryParse(bind.mainGetUserDefaultOption(key: qualityKey)) ?? | 
					
						
							|  |  |  |           kDefaultQuality); | 
					
						
							|  |  |  |   var initFps = (double.tryParse(bind.mainGetUserDefaultOption(key: fpsKey)) ?? | 
					
						
							|  |  |  |       kDefaultFps); | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return customImageQualityWidget( | 
					
						
							|  |  |  |       initQuality: initQuality, | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |       initFps: initFps, | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |       setQuality: (v) { | 
					
						
							|  |  |  |         bind.mainSetUserDefaultOption(key: qualityKey, value: v.toString()); | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2023-11-09 15:24:57 +08:00
										 |  |  |       setFps: (v) { | 
					
						
							|  |  |  |         bind.mainSetUserDefaultOption(key: fpsKey, value: v.toString()); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       showFps: true, | 
					
						
							| 
									
										
										
										
											2023-11-02 20:39:56 +08:00
										 |  |  |       showMoreQuality: true); | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | List<Widget> ServerConfigImportExportWidgets( | 
					
						
							|  |  |  |   List<TextEditingController> controllers, | 
					
						
							|  |  |  |   List<RxString> errMsgs, | 
					
						
							|  |  |  | ) { | 
					
						
							|  |  |  |   import() { | 
					
						
							|  |  |  |     Clipboard.getData(Clipboard.kTextPlain).then((value) { | 
					
						
							| 
									
										
										
										
											2023-12-03 20:31:48 +08:00
										 |  |  |       importConfig(controllers, errMsgs, value?.text); | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   export() { | 
					
						
							|  |  |  |     final text = ServerConfig( | 
					
						
							|  |  |  |             idServer: controllers[0].text.trim(), | 
					
						
							|  |  |  |             relayServer: controllers[1].text.trim(), | 
					
						
							|  |  |  |             apiServer: controllers[2].text.trim(), | 
					
						
							|  |  |  |             key: controllers[3].text.trim()) | 
					
						
							|  |  |  |         .encode(); | 
					
						
							|  |  |  |     debugPrint("ServerConfig export: $text"); | 
					
						
							|  |  |  |     Clipboard.setData(ClipboardData(text: text)); | 
					
						
							|  |  |  |     showToast(translate('Export server configuration successfully')); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return [ | 
					
						
							|  |  |  |     Tooltip( | 
					
						
							| 
									
										
										
										
											2023-11-06 20:12:01 +08:00
										 |  |  |       message: translate('Import server config'), | 
					
						
							| 
									
										
										
										
											2023-08-31 20:30:20 +08:00
										 |  |  |       child: IconButton( | 
					
						
							|  |  |  |           icon: Icon(Icons.paste, color: Colors.grey), onPressed: import), | 
					
						
							|  |  |  |     ), | 
					
						
							|  |  |  |     Tooltip( | 
					
						
							|  |  |  |         message: translate('Export Server Config'), | 
					
						
							|  |  |  |         child: IconButton( | 
					
						
							|  |  |  |             icon: Icon(Icons.copy, color: Colors.grey), onPressed: export)) | 
					
						
							|  |  |  |   ]; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-12-11 15:32:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | List<(String, String)> otherDefaultSettings() { | 
					
						
							|  |  |  |   List<(String, String)> v = [ | 
					
						
							|  |  |  |     ('View Mode', 'view_only'), | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if ((isDesktop || isWebDesktop)) ('show_monitors_tip', kKeyShowMonitorsToolbar), | 
					
						
							|  |  |  |     if ((isDesktop || isWebDesktop)) ('Collapse toolbar', 'collapse_toolbar'), | 
					
						
							| 
									
										
										
										
											2023-12-11 15:32:13 +08:00
										 |  |  |     ('Show remote cursor', 'show_remote_cursor'), | 
					
						
							| 
									
										
										
										
											2024-04-25 10:56:02 +05:30
										 |  |  |     ('Follow remote cursor', 'follow_remote_cursor'), | 
					
						
							|  |  |  |     ('Follow remote window focus', 'follow_remote_window'), | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if ((isDesktop || isWebDesktop)) ('Zoom cursor', 'zoom-cursor'), | 
					
						
							| 
									
										
										
										
											2023-12-11 15:32:13 +08:00
										 |  |  |     ('Show quality monitor', 'show_quality_monitor'), | 
					
						
							|  |  |  |     ('Mute', 'disable_audio'), | 
					
						
							|  |  |  |     if (isDesktop) ('Enable file copy and paste', 'enable_file_transfer'), | 
					
						
							|  |  |  |     ('Disable clipboard', 'disable_clipboard'), | 
					
						
							|  |  |  |     ('Lock after session end', 'lock_after_session_end'), | 
					
						
							|  |  |  |     ('Privacy mode', 'privacy_mode'), | 
					
						
							|  |  |  |     if (isMobile) ('Touch mode', 'touch-mode'), | 
					
						
							|  |  |  |     ('True color (4:4:4)', 'i444'), | 
					
						
							| 
									
										
										
										
											2024-02-23 22:49:53 +08:00
										 |  |  |     ('Reverse mouse wheel', kKeyReverseMouseWheel), | 
					
						
							| 
									
										
										
										
											2023-12-11 15:32:13 +08:00
										 |  |  |     ('swap-left-right-mouse', 'swap-left-right-mouse'), | 
					
						
							|  |  |  |     if (isDesktop && useTextureRender) | 
					
						
							|  |  |  |       ( | 
					
						
							|  |  |  |         'Show displays as individual windows', | 
					
						
							|  |  |  |         kKeyShowDisplaysAsIndividualWindows | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     if (isDesktop && useTextureRender) | 
					
						
							|  |  |  |       ( | 
					
						
							|  |  |  |         'Use all my displays for the remote session', | 
					
						
							|  |  |  |         kKeyUseAllMyDisplaysForTheRemoteSession | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return v; | 
					
						
							|  |  |  | } |