diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 3670bbd00..9bd4b091e 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -848,7 +848,7 @@ class OverlayDialogManager { } } -void showToast(String text, {Duration timeout = const Duration(seconds: 2)}) { +void showToast(String text, {Duration timeout = const Duration(seconds: 3)}) { final overlayState = globalKey.currentState?.overlay; if (overlayState == null) return; final entry = OverlayEntry(builder: (_) { @@ -1963,6 +1963,13 @@ List? urlLinkToCmdArgs(Uri uri) { // For compatibility command = '--connect'; id = uri.path.substring("/new/".length); + } else if (uri.authority == "config") { + final config = uri.path.substring("/".length); + // add a timer to make showToast work + Timer(Duration(seconds: 1), () { + importConfig(null, null, config); + }); + return null; } else if (options.contains(uri.authority)) { final optionIndex = options.indexOf(uri.authority); command = '--${uri.authority}'; @@ -2822,3 +2829,90 @@ class _ReconnectCountDownButtonState extends State<_ReconnectCountDownButton> { ); } } + +importConfig( + List? controllers, + List? errMsgs, + String? text) { + if (text != null && text.isNotEmpty) { + try { + final sc = ServerConfig.decode(text); + if (sc.idServer.isNotEmpty) { + Future success = setServerConfig(controllers, errMsgs, sc); + success.then((value) { + if (value) { + showToast( + translate('Import server configuration successfully')); + } else { + showToast(translate('Invalid server configuration')); + } + }); + } else { + showToast(translate('Invalid server configuration')); + } + return sc; + } catch (e) { + showToast(translate('Invalid server configuration')); + } + } else { + showToast(translate('Clipboard is empty')); + } +} + +Future setServerConfig( + List? controllers, + List? errMsgs, + ServerConfig config, +) async { + config.idServer = config.idServer.trim(); + config.relayServer = config.relayServer.trim(); + config.apiServer = config.apiServer.trim(); + config.key = config.key.trim(); + if (controllers != null) { + controllers[0].text = config.idServer; + controllers[1].text = config.relayServer; + controllers[2].text = config.apiServer; + controllers[3].text = config.key; + } + // id + if (config.idServer.isNotEmpty && errMsgs != null) { + errMsgs[0].value = + translate(await bind.mainTestIfValidServer(server: config.idServer)); + if (errMsgs[0].isNotEmpty) { + return false; + } + } + // relay + if (config.relayServer.isNotEmpty && errMsgs != null) { + errMsgs[1].value = + translate(await bind.mainTestIfValidServer(server: config.relayServer)); + if (errMsgs[1].isNotEmpty) { + return false; + } + } + // api + if (config.apiServer.isNotEmpty && errMsgs != null) { + if (!config.apiServer.startsWith('http://') && + !config.apiServer.startsWith('https://')) { + errMsgs[2].value = + '${translate("API Server")}: ${translate("invalid_http")}'; + return false; + } + } + final oldApiServer = await bind.mainGetApiServer(); + + // should set one by one + await bind.mainSetOption( + key: 'custom-rendezvous-server', value: config.idServer); + await bind.mainSetOption(key: 'relay-server', value: config.relayServer); + await bind.mainSetOption(key: 'api-server', value: config.apiServer); + await bind.mainSetOption(key: 'key', value: config.key); + + final newApiServer = await bind.mainGetApiServer(); + if (oldApiServer.isNotEmpty && + oldApiServer != newApiServer && + gFFI.userModel.isLogin) { + gFFI.userModel.logOut(apiServer: oldApiServer); + } + return true; +} \ No newline at end of file diff --git a/flutter/lib/common/widgets/setting_widgets.dart b/flutter/lib/common/widgets/setting_widgets.dart index e5a7c0e76..a970fca57 100644 --- a/flutter/lib/common/widgets/setting_widgets.dart +++ b/flutter/lib/common/widgets/setting_widgets.dart @@ -170,91 +170,13 @@ customImageQualitySetting() { showMoreQuality: true); } -Future setServerConfig( - List controllers, - List errMsgs, - ServerConfig config, -) async { - config.idServer = config.idServer.trim(); - config.relayServer = config.relayServer.trim(); - config.apiServer = config.apiServer.trim(); - config.key = config.key.trim(); - // id - if (config.idServer.isNotEmpty) { - errMsgs[0].value = - translate(await bind.mainTestIfValidServer(server: config.idServer)); - if (errMsgs[0].isNotEmpty) { - return false; - } - } - // relay - if (config.relayServer.isNotEmpty) { - errMsgs[1].value = - translate(await bind.mainTestIfValidServer(server: config.relayServer)); - if (errMsgs[1].isNotEmpty) { - return false; - } - } - // api - if (config.apiServer.isNotEmpty) { - if (!config.apiServer.startsWith('http://') && - !config.apiServer.startsWith('https://')) { - errMsgs[2].value = - '${translate("API Server")}: ${translate("invalid_http")}'; - return false; - } - } - final oldApiServer = await bind.mainGetApiServer(); - - // should set one by one - await bind.mainSetOption( - key: 'custom-rendezvous-server', value: config.idServer); - await bind.mainSetOption(key: 'relay-server', value: config.relayServer); - await bind.mainSetOption(key: 'api-server', value: config.apiServer); - await bind.mainSetOption(key: 'key', value: config.key); - - final newApiServer = await bind.mainGetApiServer(); - if (oldApiServer.isNotEmpty && - oldApiServer != newApiServer && - gFFI.userModel.isLogin) { - gFFI.userModel.logOut(apiServer: oldApiServer); - } - return true; -} - List ServerConfigImportExportWidgets( List controllers, List errMsgs, ) { import() { Clipboard.getData(Clipboard.kTextPlain).then((value) { - final text = value?.text; - if (text != null && text.isNotEmpty) { - try { - final sc = ServerConfig.decode(text); - if (sc.idServer.isNotEmpty) { - controllers[0].text = sc.idServer; - controllers[1].text = sc.relayServer; - controllers[2].text = sc.apiServer; - controllers[3].text = sc.key; - Future success = setServerConfig(controllers, errMsgs, sc); - success.then((value) { - if (value) { - showToast( - translate('Import server configuration successfully')); - } else { - showToast(translate('Invalid server configuration')); - } - }); - } else { - showToast(translate('Invalid server configuration')); - } - } catch (e) { - showToast(translate('Invalid server configuration')); - } - } else { - showToast(translate('Clipboard is empty')); - } + importConfig(controllers, errMsgs, value?.text); }); } diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index c4261b4c9..ce80bfbd0 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1087,7 +1087,7 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin { submit() async { bool result = await setServerConfig( - controllers, + null, errMsgs, ServerConfig( idServer: idController.text, diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 6b480c46e..68d253d7b 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -171,7 +171,7 @@ void showServerSettingsWithValue( isInProgress = true; }); bool ret = await setServerConfig( - controllers, + null, errMsgs, ServerConfig( idServer: idCtrl.text.trim(), diff --git a/res/osx-dist.sh b/res/osx-dist.sh index 3e616e558..fd9c1fa6e 100755 --- a/res/osx-dist.sh +++ b/res/osx-dist.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash echo $MACOS_CODESIGN_IDENTITY -cargo install flutter_rust_bridge_codegen --version 1.75.3 --features uuid +cargo install flutter_rust_bridge_codegen --version 1.80.1 --features uuid cd flutter; flutter pub get; cd - ~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart --c-output ./flutter/macos/Runner/bridge_generated.h ./build.py --flutter