diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 5dd33f14bdcf..270913ee8714 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1521,6 +1521,9 @@ class LastWindowPosition { } } +String get windowFramePrefix => + bind.isQs() ? "${kWindowPrefix}qs_" : kWindowPrefix; + /// Save window position and size on exit /// Note that windowId must be provided if it's subwindow Future saveWindowPosition(WindowType type, {int? windowId}) async { @@ -1536,7 +1539,7 @@ Future saveWindowPosition(WindowType type, {int? windowId}) async { (Platform.isMacOS && stateGlobal.closeOnFullscreen == true); setFrameIfMaximized() { if (isMaximized) { - final pos = bind.getLocalFlutterOption(k: kWindowPrefix + type.name); + final pos = bind.getLocalFlutterOption(k: windowFramePrefix + type.name); var lpos = LastWindowPosition.loadFromString(pos); position = Offset( lpos?.offsetWidth ?? position.dx, lpos?.offsetHeight ?? position.dy); @@ -1584,7 +1587,7 @@ Future saveWindowPosition(WindowType type, {int? windowId}) async { "Saving frame: $windowId: ${pos.width}/${pos.height}, offset:${pos.offsetWidth}/${pos.offsetHeight}, isMaximized:${pos.isMaximized}, isFullscreen:${pos.isFullscreen}"); await bind.setLocalFlutterOption( - k: kWindowPrefix + type.name, v: pos.toString()); + k: windowFramePrefix + type.name, v: pos.toString()); if (type == WindowType.RemoteDesktop && windowId != null) { await _saveSessionWindowPosition( @@ -1599,7 +1602,7 @@ Future _saveSessionWindowPosition(WindowType windowType, int windowId, getPeerPos(String peerId) { if (isMaximized) { final peerPos = bind.mainGetPeerFlutterOptionSync( - id: peerId, k: kWindowPrefix + windowType.name); + id: peerId, k: windowFramePrefix + windowType.name); var lpos = LastWindowPosition.loadFromString(peerPos); return LastWindowPosition( lpos?.width ?? pos.offsetWidth, @@ -1618,7 +1621,7 @@ Future _saveSessionWindowPosition(WindowType windowType, int windowId, for (final peerId in remoteList.split(',')) { bind.mainSetPeerFlutterOptionSync( id: peerId, - k: kWindowPrefix + windowType.name, + k: windowFramePrefix + windowType.name, v: getPeerPos(peerId)); } } @@ -1736,14 +1739,14 @@ Future restoreWindowPosition(WindowType type, // Because the session may not be read at this time. if (desktopType == DesktopType.main) { pos = bind.mainGetPeerFlutterOptionSync( - id: peerId, k: kWindowPrefix + type.name); + id: peerId, k: windowFramePrefix + type.name); } else { pos = await bind.sessionGetFlutterOptionByPeerId( - id: peerId, k: kWindowPrefix + type.name); + id: peerId, k: windowFramePrefix + type.name); } isRemotePeerPos = pos != null; } - pos ??= bind.getLocalFlutterOption(k: kWindowPrefix + type.name); + pos ??= bind.getLocalFlutterOption(k: windowFramePrefix + type.name); var lpos = LastWindowPosition.loadFromString(pos); if (lpos == null) { @@ -1790,9 +1793,13 @@ Future restoreWindowPosition(WindowType type, } if (lpos.isMaximized == true) { await restorePos(); - await windowManager.maximize(); + if (!bind.isQs()) { + await windowManager.maximize(); + } } else { - await windowManager.setSize(size); + if (!bind.isQs()) { + await windowManager.setSize(size); + } await restorePos(); } return true; @@ -3082,3 +3089,15 @@ Widget loadLogo(double size) { height: size, )); } + +var desktopQsHomeLeftPaneSize = Size(280, 300); +Size getDesktopQsHomeSize() { + final magicWidth = 11.0; + final magicHeight = 8.0; + return desktopQsHomeLeftPaneSize + + Offset(magicWidth, kDesktopRemoteTabBarHeight + magicHeight); +} + +Size getDesktopQsSettingsSize() { + return Size(768, 600); +} diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index c1f8fab0dfdf..49158d26ffc7 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -20,6 +20,144 @@ import '../../common/widgets/autocomplete.dart'; import '../../models/platform_model.dart'; import '../widgets/button.dart'; +class OnlineStatusWidget extends StatefulWidget { + const OnlineStatusWidget({Key? key}) : super(key: key); + + @override + State createState() => _OnlineStatusWidgetState(); +} + +/// State for the connection page. +class _OnlineStatusWidgetState extends State { + final _svcStopped = Get.find(tag: 'stop-service'); + final _svcIsUsingPublicServer = true.obs; + Timer? _updateTimer; + + double get em => 14.0; + double get height => em * 3; + + void onUsePublicServerGuide() { + const url = "https://rustdesk.com/pricing.html"; + canLaunchUrlString(url).then((can) { + if (can) { + launchUrlString(url); + } + }); + } + + @override + void initState() { + super.initState(); + _updateTimer = periodic_immediate(Duration(seconds: 1), () async { + updateStatus(); + }); + } + + @override + void dispose() { + _updateTimer?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + height: height, + child: Obx(() => Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 8, + width: 8, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: _svcStopped.value || + stateGlobal.svcStatus.value == SvcStatus.connecting + ? kColorWarn + : (stateGlobal.svcStatus.value == SvcStatus.ready + ? Color.fromARGB(255, 50, 190, 166) + : Color.fromARGB(255, 224, 79, 95)), + ), + ).marginSymmetric(horizontal: em), + Text( + _svcStopped.value + ? translate("Service is not running") + : stateGlobal.svcStatus.value == SvcStatus.connecting + ? translate("connecting_status") + : stateGlobal.svcStatus.value == SvcStatus.notReady + ? translate("not_ready_status") + : translate('Ready'), + style: TextStyle(fontSize: em)), + // stop + Offstage( + offstage: !_svcStopped.value, + child: InkWell( + onTap: () async { + await start_service(true); + }, + child: Text(translate("Start service"), + style: TextStyle( + decoration: TextDecoration.underline, + fontSize: em))) + .marginOnly(left: em), + ), + // ready && public + Flexible( + child: Offstage( + offstage: !(!_svcStopped.value && + stateGlobal.svcStatus.value == SvcStatus.ready && + _svcIsUsingPublicServer.value), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(', ', style: TextStyle(fontSize: em)), + Flexible( + child: InkWell( + onTap: onUsePublicServerGuide, + child: Row( + children: [ + Flexible( + child: Text( + translate('setup_server_tip'), + style: TextStyle( + decoration: TextDecoration.underline, + fontSize: em), + ), + ), + ], + ), + ), + ) + ], + ), + ), + ) + ], + )), + ).paddingOnly(right: bind.isQs() ? 8 : 0); + } + + updateStatus() async { + final status = + jsonDecode(await bind.mainGetConnectStatus()) as Map; + final statusNum = status['status_num'] as int; + final preStatus = stateGlobal.svcStatus.value; + if (statusNum == 0) { + stateGlobal.svcStatus.value = SvcStatus.connecting; + } else if (statusNum == -1) { + stateGlobal.svcStatus.value = SvcStatus.notReady; + } else if (statusNum == 1) { + stateGlobal.svcStatus.value = SvcStatus.ready; + if (preStatus != SvcStatus.ready) { + gFFI.userModel.refreshCurrentUser(); + } + } else { + stateGlobal.svcStatus.value = SvcStatus.notReady; + } + _svcIsUsingPublicServer.value = await bind.mainIsUsingPublicServer(); + } +} + /// Connection page for connecting to a remote peer. class ConnectionPage extends StatefulWidget { const ConnectionPage({Key? key}) : super(key: key); @@ -34,13 +172,8 @@ class _ConnectionPageState extends State /// Controller for the id input bar. final _idController = IDTextEditingController(); - Timer? _updateTimer; - final RxBool _idInputFocused = false.obs; - var svcStopped = Get.find(tag: 'stop-service'); - var svcIsUsingPublicServer = true.obs; - bool isWindowMinimized = false; List peers = []; @@ -60,9 +193,6 @@ class _ConnectionPageState extends State } }(); } - _updateTimer = periodic_immediate(Duration(seconds: 1), () async { - updateStatus(); - }); Get.put(_idController); windowManager.addListener(this); } @@ -70,7 +200,6 @@ class _ConnectionPageState extends State @override void dispose() { _idController.dispose(); - _updateTimer?.cancel(); windowManager.removeListener(this); if (Get.isRegistered()) { Get.delete(); @@ -132,7 +261,7 @@ class _ConnectionPageState extends State ], ).paddingOnly(left: 12.0)), const Divider(height: 1), - buildStatus() + OnlineStatusWidget() ], ); } @@ -383,111 +512,4 @@ class _ConnectionPageState extends State return Container( constraints: const BoxConstraints(maxWidth: 600), child: w); } - - Widget buildStatus() { - final em = 14.0; - return Container( - height: 3 * em, - child: Obx(() => Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - height: 8, - width: 8, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - color: svcStopped.value || - stateGlobal.svcStatus.value == SvcStatus.connecting - ? kColorWarn - : (stateGlobal.svcStatus.value == SvcStatus.ready - ? Color.fromARGB(255, 50, 190, 166) - : Color.fromARGB(255, 224, 79, 95)), - ), - ).marginSymmetric(horizontal: em), - Text( - svcStopped.value - ? translate("Service is not running") - : stateGlobal.svcStatus.value == SvcStatus.connecting - ? translate("connecting_status") - : stateGlobal.svcStatus.value == SvcStatus.notReady - ? translate("not_ready_status") - : translate('Ready'), - style: TextStyle(fontSize: em)), - // stop - Offstage( - offstage: !svcStopped.value, - child: InkWell( - onTap: () async { - await start_service(true); - }, - child: Text(translate("Start service"), - style: TextStyle( - decoration: TextDecoration.underline, - fontSize: em))) - .marginOnly(left: em), - ), - // ready && public - Flexible( - child: Offstage( - offstage: !(!svcStopped.value && - stateGlobal.svcStatus.value == SvcStatus.ready && - svcIsUsingPublicServer.value), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text(', ', style: TextStyle(fontSize: em)), - Flexible( - child: InkWell( - onTap: onUsePublicServerGuide, - child: Row( - children: [ - Flexible( - child: Text( - translate('setup_server_tip'), - style: TextStyle( - decoration: TextDecoration.underline, - fontSize: em), - ), - ), - ], - ), - ), - ) - ], - ), - ), - ) - ], - )), - ); - } - - void onUsePublicServerGuide() { - const url = "https://rustdesk.com/pricing.html"; - canLaunchUrlString(url).then((can) { - if (can) { - launchUrlString(url); - } - }); - } - - updateStatus() async { - final status = - jsonDecode(await bind.mainGetConnectStatus()) as Map; - final statusNum = status['status_num'] as int; - final preStatus = stateGlobal.svcStatus.value; - if (statusNum == 0) { - stateGlobal.svcStatus.value = SvcStatus.connecting; - } else if (statusNum == -1) { - stateGlobal.svcStatus.value = SvcStatus.notReady; - } else if (statusNum == 1) { - stateGlobal.svcStatus.value = SvcStatus.ready; - if (preStatus != SvcStatus.ready) { - gFFI.userModel.refreshCurrentUser(); - } - } else { - stateGlobal.svcStatus.value = SvcStatus.notReady; - } - svcIsUsingPublicServer.value = await bind.mainIsUsingPublicServer(); - } } diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 65611434b739..a05afaf2338c 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -20,6 +20,7 @@ import 'package:flutter_hbb/utils/multi_window_manager.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:window_manager/window_manager.dart'; import 'package:window_size/window_size.dart' as window_size; import '../widgets/button.dart'; @@ -50,26 +51,60 @@ class _DesktopHomePageState extends State Timer? _updateTimer; bool isCardClosed = false; + final GlobalKey _childKey = GlobalKey(); + @override Widget build(BuildContext context) { super.build(context); + + final children = [buildLeftPane(context)]; + if (!bind.isQs()) { + children.addAll([ + const VerticalDivider(width: 1), + Expanded(child: buildRightPane(context)), + ]); + } return Row( crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildLeftPane(context), - const VerticalDivider(width: 1), - Expanded( - child: buildRightPane(context), - ), - ], + children: children, ); } Widget buildLeftPane(BuildContext context) { + final children = [ + buildTip(context), + buildIDBoard(context), + buildPasswordBoard(context), + FutureBuilder( + future: buildHelpCards(), + builder: (_, data) { + if (data.hasData) { + if (bind.isQs()) { + Future.delayed(Duration(milliseconds: 300), () { + _updateWindowSize(); + }); + } + return data.data!; + } else { + return const Offstage(); + } + }, + ), + buildPluginEntry(), + ]; + if (bind.isQs()) { + children.addAll([ + Divider(), + Container( + margin: EdgeInsets.fromLTRB(0, 0, 8, 6), + child: OnlineStatusWidget(), + ), + ]); + } return ChangeNotifierProvider.value( value: gFFI.serverModel, child: Container( - width: 200, + width: bind.isQs() ? 280.0 : 200.0, color: Theme.of(context).colorScheme.background, child: DesktopScrollWrapper( scrollController: _leftPaneScrollController, @@ -77,22 +112,8 @@ class _DesktopHomePageState extends State controller: _leftPaneScrollController, physics: DraggableNeverScrollableScrollPhysics(), child: Column( - children: [ - buildTip(context), - buildIDBoard(context), - buildPasswordBoard(context), - FutureBuilder( - future: buildHelpCards(), - builder: (_, data) { - if (data.hasData) { - return data.data!; - } else { - return const Offstage(); - } - }, - ), - buildPluginEntry() - ], + key: _childKey, + children: children, ), ), ), @@ -452,7 +473,8 @@ class _DesktopHomePageState extends State return Stack( children: [ Container( - margin: EdgeInsets.only(top: marginTop), + margin: + EdgeInsets.fromLTRB(0, marginTop, 0, bind.isQs() ? marginTop : 0), child: Container( decoration: BoxDecoration( gradient: LinearGradient( @@ -670,6 +692,19 @@ class _DesktopHomePageState extends State } }); _uniLinksSubscription = listenUniLinks(); + + if (bind.isQs()) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _updateWindowSize(); + }); + } + } + + _updateWindowSize() { + RenderBox renderBox = + _childKey.currentContext?.findRenderObject() as RenderBox; + desktopQsHomeLeftPaneSize = renderBox.size; + windowManager.setSize(getDesktopQsHomeSize()); } @override diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index a1c6d4a9d69d..65e55cbc8b58 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -109,14 +109,18 @@ class _DesktopSettingPageState extends State _TabInfo('Security', Icons.enhanced_encryption_outlined, Icons.enhanced_encryption), _TabInfo('Network', Icons.link_outlined, Icons.link), - _TabInfo( - 'Display', Icons.desktop_windows_outlined, Icons.desktop_windows), _TabInfo('Account', Icons.person_outline, Icons.person), _TabInfo('About', Icons.info_outline, Icons.info) ]; - if (bind.pluginFeatureIsEnabled()) { + if (!bind.isQs()) { settingTabs.insert( - 4, _TabInfo('Plugin', Icons.extension_outlined, Icons.extension)); + 3, + _TabInfo('Display', Icons.desktop_windows_outlined, + Icons.desktop_windows)); + if (bind.pluginFeatureIsEnabled()) { + settingTabs.insert( + 4, _TabInfo('Plugin', Icons.extension_outlined, Icons.extension)); + } } return settingTabs; } @@ -126,12 +130,14 @@ class _DesktopSettingPageState extends State _General(), _Safety(), _Network(), - _Display(), _Account(), _About(), ]; - if (bind.pluginFeatureIsEnabled()) { - children.insert(4, _Plugin()); + if (!bind.isQs()) { + children.insert(3, _Display()); + if (bind.pluginFeatureIsEnabled()) { + children.insert(4, _Plugin()); + } } return children; } @@ -318,31 +324,38 @@ class _GeneralState extends State<_General> { } Widget other() { - final children = [ - _OptionCheckBox(context, 'Confirm before closing multiple tabs', - 'enable-confirm-closing-tabs', - isServer: false), + final children = []; + if (!bind.isQs()) { + children.add(_OptionCheckBox(context, + 'Confirm before closing multiple tabs', 'enable-confirm-closing-tabs', + isServer: false)); + } + children.addAll([ _OptionCheckBox(context, 'Adaptive bitrate', 'enable-abr'), - wallpaper(), - _OptionCheckBox( - context, - 'Open connection in new tab', - kOptionOpenNewConnInTabs, - isServer: false, - ), - ]; - // though this is related to GUI, but opengl problem affects all users, so put in config rather than local - children.add(Tooltip( - message: translate('software_render_tip'), - child: _OptionCheckBox(context, "Always use software rendering", - 'allow-always-software-render'), - )); - children.add(_OptionCheckBox( - context, - 'Check for software update on startup', - 'enable-check-update', - isServer: false, - )); + wallpaper() + ]); + if (!bind.isQs()) { + children.addAll([ + _OptionCheckBox( + context, + 'Open connection in new tab', + kOptionOpenNewConnInTabs, + isServer: false, + ), + // though this is related to GUI, but opengl problem affects all users, so put in config rather than local + Tooltip( + message: translate('software_render_tip'), + child: _OptionCheckBox(context, "Always use software rendering", + 'allow-always-software-render'), + ), + _OptionCheckBox( + context, + 'Check for software update on startup', + 'enable-check-update', + isServer: false, + ) + ]); + } if (bind.mainShowOption(key: 'allow-linux-headless')) { children.add(_OptionCheckBox( context, 'Allow linux headless', 'allow-linux-headless')); diff --git a/flutter/lib/desktop/pages/desktop_tab_page.dart b/flutter/lib/desktop/pages/desktop_tab_page.dart index a642e2590ba8..de3ed2ea253a 100644 --- a/flutter/lib/desktop/pages/desktop_tab_page.dart +++ b/flutter/lib/desktop/pages/desktop_tab_page.dart @@ -6,6 +6,7 @@ import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/desktop/pages/desktop_home_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart'; import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; +import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; import 'package:get/get.dart'; import 'package:window_manager/window_manager.dart'; @@ -53,6 +54,17 @@ class _DesktopTabPageState extends State { page: DesktopHomePage( key: const ValueKey(kTabLabelHomePage), ))); + if (bind.isQs()) { + tabController.onSelected = (key) { + if (key == kTabLabelHomePage) { + windowManager.setSize(getDesktopQsHomeSize()); + windowManager.setResizable(false); + } else { + windowManager.setSize(getDesktopQsSettingsSize()); + windowManager.setResizable(true); + } + }; + } } @override @@ -68,11 +80,14 @@ class _DesktopTabPageState extends State { backgroundColor: Theme.of(context).colorScheme.background, body: DesktopTab( controller: tabController, - tail: ActionIcon( - message: 'Settings', - icon: IconFont.menu, - onTap: DesktopTabPage.onAddSetting, - isClose: false, + tail: Offstage( + offstage: bind.isQs(), + child: ActionIcon( + message: 'Settings', + icon: IconFont.menu, + onTap: DesktopTabPage.onAddSetting, + isClose: false, + ), ), ))); return Platform.isMacOS || kUseCompatibleUiMode diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index b371012ff5aa..6d53a38873fe 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -13,7 +13,6 @@ import 'package:flutter_hbb/desktop/pages/remote_page.dart'; import 'package:flutter_hbb/main.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; import 'package:scroll_pos/scroll_pos.dart'; @@ -166,7 +165,7 @@ class DesktopTabController { })); } }); - if (callOnSelected) { + if ((isDesktop && bind.isQs()) || callOnSelected) { if (state.value.tabs.length > index) { final key = state.value.tabs[index].key; onSelected?.call(key); diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index b6a2aad96207..a8298ccc7b10 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -98,9 +98,11 @@ Future main(List args) async { } } -Future initEnv(String appType) async { +Future initEnv(String appType) async { // global shared preference - await platformFFI.init(appType); + if (!await platformFFI.init(appType)) { + return false; + } // global FFI, use this **ONLY** for global configuration // for convenience, use global FFI on mobile platform // focus on multi-ffi on desktop first @@ -109,11 +111,14 @@ Future initEnv(String appType) async { _registerEventHandler(); // Update the system theme. updateSystemWindowTheme(); + return true; } void runMainApp(bool startService) async { // register uni links - await initEnv(kAppTypeMain); + if (!await initEnv(kAppTypeMain)) { + return; + } // trigger connection status updater await bind.mainCheckConnectStatus(); if (startService) { @@ -142,11 +147,14 @@ void runMainApp(bool startService) async { } windowManager.setOpacity(1); windowManager.setTitle(getWindowName()); + windowManager.setResizable(!bind.isQs()); }); } void runMobileApp() async { - await initEnv(kAppTypeMain); + if (!await initEnv(kAppTypeMain)) { + return; + } if (isAndroid) androidChannelInit(); platformFFI.syncAndroidServiceAppDirConfigPath(); await Future.wait([gFFI.abModel.loadCache(), gFFI.groupModel.loadCache()]); @@ -159,7 +167,9 @@ void runMultiWindow( Map argument, String appType, ) async { - await initEnv(appType); + if (!await initEnv(appType)) { + return; + } final title = getWindowName(); // set prevent close to true, we handle close event manually WindowController.fromWindowId(kWindowId!).setPreventClose(true); @@ -222,7 +232,9 @@ void runMultiWindow( } void runConnectionManagerScreen() async { - await initEnv(kAppTypeConnectionManager); + if (!await initEnv(kAppTypeConnectionManager)) { + return; + } _runApp( '', const DesktopServerPage(), @@ -325,7 +337,9 @@ void _runApp( void runInstallPage() async { await windowManager.ensureInitialized(); - await initEnv(kAppTypeMain); + if (!await initEnv(kAppTypeMain)) { + return; + } _runApp('', const InstallPage(), MyTheme.currentThemeMode()); WindowOptions windowOptions = getHiddenTitleBarWindowOptions(size: Size(800, 600), center: true); diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index cdb3f857d784..1d0d27117e5f 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -109,7 +109,7 @@ class PlatformFFI { sessionId: sessionId, display: display, ptr: ptr); /// Init the FFI class, loads the native Rust core library. - Future init(String appType) async { + Future init(String appType) async { _appType = appType; final dylib = Platform.isAndroid ? DynamicLibrary.open('librustdesk.so') @@ -130,6 +130,10 @@ class PlatformFFI { debugPrint('Failed to get documents directory: $e'); } _ffiBind = RustdeskImpl(dylib); + if (_ffiBind.isQs() && (_appType != kAppTypeMain && _appType != kAppTypeConnectionManager)) { + return false; + } + if (Platform.isLinux) { // Start a dbus service, no need to await _ffiBind.mainStartDbusServer(); @@ -202,6 +206,7 @@ class PlatformFFI { debugPrintStack(label: 'initialize failed: $e'); } version = await getVersion(); + return true; } Future tryHandle(Map evt) async { diff --git a/src/core_main.rs b/src/core_main.rs index 734202f9e454..22db6f5e123e 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -62,7 +62,11 @@ pub fn core_main() -> Option> { ] .contains(&arg.as_str()) { - _is_flutter_invoke_new_connection = true; + if crate::flutter_ffi::is_qs().0 { + return None; + } else { + _is_flutter_invoke_new_connection = true; + } } if arg == "--elevate" { _is_elevate = true; diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index d09186850232..64b0f54f1549 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1813,6 +1813,10 @@ pub fn main_support_remove_wallpaper() -> bool { support_remove_wallpaper() } +pub fn is_qs() -> SyncReturn { + SyncReturn(false) +} + /// Send a url scheme throught the ipc. /// /// * macOS only diff --git a/src/lang/bg.rs b/src/lang/bg.rs index 4cd015408fb7..8bd2d900510e 100644 --- a/src/lang/bg.rs +++ b/src/lang/bg.rs @@ -451,8 +451,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", ""), ("No transfers in progress", ""), ("Set one-time password length", ""), - ("install_cert_tip", "Инсталирайте сертификат на RustDesk"), - ("confirm_install_cert_tip", "Това е сертификат за тестване на RustDesk, на който може да се вярва. Сертификатът ще се използва за доверие и инсталиране на драйвери на RustDesk, когато е необходимо."), ("RDP Settings", "RDP настройки"), ("Sort by", ""), ("New Connection", "Ново свързване"),