diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 365ce3dd5..5cd54a0a8 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -17,6 +17,8 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:window_manager/window_manager.dart'; import 'common/widgets/overlay.dart'; +import 'mobile/pages/file_manager_page.dart'; +import 'mobile/pages/remote_page.dart'; import 'models/model.dart'; import 'models/platform_model.dart'; @@ -1071,14 +1073,38 @@ void connect(BuildContext context, String id, assert(!(isFileTransfer && isTcpTunneling && isRDP), "more than one connect type"); - FocusScopeNode currentFocus = FocusScope.of(context); - if (isFileTransfer) { - await rustDeskWinManager.newFileTransfer(id); - } else if (isTcpTunneling || isRDP) { - await rustDeskWinManager.newPortForward(id, isRDP); + if (isDesktop) { + if (isFileTransfer) { + await rustDeskWinManager.newFileTransfer(id); + } else if (isTcpTunneling || isRDP) { + await rustDeskWinManager.newPortForward(id, isRDP); + } else { + await rustDeskWinManager.newRemoteDesktop(id); + } } else { - await rustDeskWinManager.newRemoteDesktop(id); + if (isFileTransfer) { + if (!await PermissionManager.check("file")) { + if (!await PermissionManager.request("file")) { + return; + } + } + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => FileManagerPage(id: id), + ), + ); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => RemotePage(id: id), + ), + ); + } } + + FocusScopeNode currentFocus = FocusScope.of(context); if (!currentFocus.hasPrimaryFocus) { currentFocus.unfocus(); } diff --git a/flutter/lib/common/widgets/address_book.dart b/flutter/lib/common/widgets/address_book.dart index beecf47f2..9fac81723 100644 --- a/flutter/lib/common/widgets/address_book.dart +++ b/flutter/lib/common/widgets/address_book.dart @@ -1,12 +1,13 @@ import 'package:contextmenu/contextmenu.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_hbb/common/widgets/peer_widget.dart'; +import 'package:flutter_hbb/common/widgets/peers_view.dart'; import 'package:flutter_hbb/models/ab_model.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import '../../common.dart'; import '../../desktop/pages/desktop_home_page.dart'; +import '../../mobile/pages/settings_page.dart'; import '../../models/platform_model.dart'; class AddressBook extends StatefulWidget { @@ -37,11 +38,16 @@ class _AddressBookState extends State { }); handleLogin() { - loginDialog().then((success) { - if (success) { - setState(() {}); - } - }); + // TODO refactor login dialog for desktop and mobile + if (isDesktop) { + loginDialog().then((success) { + if (success) { + setState(() {}); + } + }); + } else { + showLogin(gFFI.dialogManager); + } } Future buildAddressBook(BuildContext context) async { @@ -174,7 +180,7 @@ class _AddressBookState extends State { Expanded( child: Align( alignment: Alignment.topLeft, - child: AddressBookPeerWidget()), + child: AddressBookPeersView()), ) ], )); diff --git a/flutter/lib/common/widgets/peercard_widget.dart b/flutter/lib/common/widgets/peer_card.dart similarity index 96% rename from flutter/lib/common/widgets/peercard_widget.dart rename to flutter/lib/common/widgets/peer_card.dart index 1f30c89df..9c0c997bc 100644 --- a/flutter/lib/common/widgets/peercard_widget.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -77,8 +77,11 @@ class _PeerCardState extends State<_PeerCard> subtitle: Text('${peer.username}@${peer.hostname}'), title: Text(peer.alias.isEmpty ? formatID(peer.id) : peer.alias), leading: Container( + decoration: BoxDecoration( + color: str2color('${peer.id}${peer.platform}', 0x7f), + borderRadius: BorderRadius.circular(4), + ), padding: const EdgeInsets.all(6), - color: str2color('${peer.id}${peer.platform}', 0x7f), child: getPlatformImage(peer.platform)), trailing: InkWell( child: const Padding( @@ -458,7 +461,7 @@ abstract class BasePeerCard extends StatelessWidget { } await bind.mainSetPeerOption(id: id, key: option, value: value); }, - dismissOnClicked: true, + dismissOnClicked: false, ); } @@ -489,7 +492,6 @@ abstract class BasePeerCard extends StatelessWidget { await bind.mainRemovePeer(id: id); removePreference(id); await reloadFunc(); - // Get.forceAppUpdate(); // TODO use inner model / state }(); }, dismissOnClicked: true, @@ -544,7 +546,6 @@ abstract class BasePeerCard extends StatelessWidget { if (favs.remove(id)) { await bind.mainStoreFav(favs: favs); await reloadFunc(); - // Get.forceAppUpdate(); // TODO use inner model / state } }(); }, @@ -589,8 +590,6 @@ abstract class BasePeerCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - padding: - const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), child: Form( child: TextFormField( controller: controller, @@ -625,15 +624,13 @@ class RecentPeerCard extends BasePeerCard { final List> menuItems = [ _connectAction(context, peer), _transferFileAction(context, peer.id), - _tcpTunnelingAction(context, peer.id), ]; - MenuEntryBase? rdpAction; - if (peer.platform == 'Windows') { - rdpAction = _rdpAction(context, peer.id); + if (isDesktop) { + menuItems.add(_tcpTunnelingAction(context, peer.id)); } menuItems.add(await _forceAlwaysRelayAction(peer.id)); - if (rdpAction != null) { - menuItems.add(rdpAction); + if (peer.platform == 'Windows') { + menuItems.add(_rdpAction(context, peer.id)); } menuItems.add(_wolAction(peer.id)); menuItems.add(MenuEntryDivider()); @@ -657,15 +654,13 @@ class FavoritePeerCard extends BasePeerCard { final List> menuItems = [ _connectAction(context, peer), _transferFileAction(context, peer.id), - _tcpTunnelingAction(context, peer.id), ]; - MenuEntryBase? rdpAction; - if (peer.platform == 'Windows') { - rdpAction = _rdpAction(context, peer.id); + if (isDesktop) { + menuItems.add(_tcpTunnelingAction(context, peer.id)); } menuItems.add(await _forceAlwaysRelayAction(peer.id)); - if (rdpAction != null) { - menuItems.add(rdpAction); + if (peer.platform == 'Windows') { + menuItems.add(_rdpAction(context, peer.id)); } menuItems.add(_wolAction(peer.id)); menuItems.add(MenuEntryDivider()); @@ -691,15 +686,13 @@ class DiscoveredPeerCard extends BasePeerCard { final List> menuItems = [ _connectAction(context, peer), _transferFileAction(context, peer.id), - _tcpTunnelingAction(context, peer.id), ]; - MenuEntryBase? rdpAction; - if (peer.platform == 'Windows') { - rdpAction = _rdpAction(context, peer.id); + if (isDesktop) { + menuItems.add(_tcpTunnelingAction(context, peer.id)); } menuItems.add(await _forceAlwaysRelayAction(peer.id)); - if (rdpAction != null) { - menuItems.add(rdpAction); + if (peer.platform == 'Windows') { + menuItems.add(_rdpAction(context, peer.id)); } menuItems.add(_wolAction(peer.id)); menuItems.add(MenuEntryDivider()); @@ -722,15 +715,13 @@ class AddressBookPeerCard extends BasePeerCard { final List> menuItems = [ _connectAction(context, peer), _transferFileAction(context, peer.id), - _tcpTunnelingAction(context, peer.id), ]; - MenuEntryBase? rdpAction; - if (peer.platform == 'Windows') { - rdpAction = _rdpAction(context, peer.id); + if (isDesktop) { + menuItems.add(_tcpTunnelingAction(context, peer.id)); } menuItems.add(await _forceAlwaysRelayAction(peer.id)); - if (rdpAction != null) { - menuItems.add(rdpAction); + if (peer.platform == 'Windows') { + menuItems.add(_rdpAction(context, peer.id)); } menuItems.add(_wolAction(peer.id)); menuItems.add(MenuEntryDivider()); diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index fefe74671..3ed3dc11d 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_hbb/common/widgets/peer_widget.dart'; -import 'package:flutter_hbb/common/widgets/peercard_widget.dart'; +import 'package:flutter_hbb/common/widgets/peers_view.dart'; +import 'package:flutter_hbb/common/widgets/peer_card.dart'; import 'package:flutter_hbb/consts.dart'; import 'package:get/get.dart'; @@ -113,7 +113,7 @@ class _PeerTabPageState extends State color: _tabIndex.value == t.key ? MyTheme.color(context).bg : null, - borderRadius: BorderRadius.circular(2), + borderRadius: BorderRadius.circular(isDesktop ? 2 : 6), ), child: Align( alignment: Alignment.center, diff --git a/flutter/lib/common/widgets/peer_widget.dart b/flutter/lib/common/widgets/peers_view.dart similarity index 86% rename from flutter/lib/common/widgets/peer_widget.dart rename to flutter/lib/common/widgets/peers_view.dart index e6236ff4e..cf9c4299a 100644 --- a/flutter/lib/common/widgets/peer_widget.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -11,34 +11,34 @@ import 'package:window_manager/window_manager.dart'; import '../../common.dart'; import '../../models/peer_model.dart'; import '../../models/platform_model.dart'; -import 'peercard_widget.dart'; +import 'peer_card.dart'; typedef OffstageFunc = bool Function(Peer peer); -typedef PeerCardWidgetFunc = Widget Function(Peer peer); +typedef PeerCardBuilder = BasePeerCard Function(Peer peer); /// for peer search text, global obs value final peerSearchText = "".obs; final peerSearchTextController = TextEditingController(text: peerSearchText.value); -class _PeerWidget extends StatefulWidget { +class _PeersView extends StatefulWidget { final Peers peers; final OffstageFunc offstageFunc; - final PeerCardWidgetFunc peerCardWidgetFunc; + final PeerCardBuilder peerCardBuilder; - const _PeerWidget( + const _PeersView( {required this.peers, required this.offstageFunc, - required this.peerCardWidgetFunc, + required this.peerCardBuilder, Key? key}) : super(key: key); @override - _PeerWidgetState createState() => _PeerWidgetState(); + _PeersViewState createState() => _PeersViewState(); } /// State for the peer widget. -class _PeerWidgetState extends State<_PeerWidget> with WindowListener { +class _PeersViewState extends State<_PeersView> with WindowListener { static const int _maxQueryCount = 3; final space = isDesktop ? 12.0 : 8.0; final _curPeers = {}; @@ -60,7 +60,7 @@ class _PeerWidgetState extends State<_PeerWidget> with WindowListener { return width; }(); - _PeerWidgetState() { + _PeersViewState() { _startCheckOnlines(); } @@ -119,7 +119,7 @@ class _PeerWidgetState extends State<_PeerWidget> with WindowListener { } _lastChangeTime = DateTime.now(); }, - child: widget.peerCardWidgetFunc(peer), + child: widget.peerCardBuilder(peer), ); cards.add(Offstage( key: ValueKey("off${peer.id}"), @@ -198,39 +198,39 @@ class _PeerWidgetState extends State<_PeerWidget> with WindowListener { } } -abstract class BasePeerWidget extends StatelessWidget { +abstract class BasePeersView extends StatelessWidget { final String name; final String loadEvent; final OffstageFunc offstageFunc; - final PeerCardWidgetFunc peerCardWidgetFunc; + final PeerCardBuilder peerCardBuilder; final List initPeers; - const BasePeerWidget({ + const BasePeersView({ Key? key, required this.name, required this.loadEvent, required this.offstageFunc, - required this.peerCardWidgetFunc, + required this.peerCardBuilder, required this.initPeers, }) : super(key: key); @override Widget build(BuildContext context) { - return _PeerWidget( + return _PeersView( peers: Peers(name: name, loadEvent: loadEvent, peers: initPeers), offstageFunc: offstageFunc, - peerCardWidgetFunc: peerCardWidgetFunc); + peerCardBuilder: peerCardBuilder); } } -class RecentPeerWidget extends BasePeerWidget { - RecentPeerWidget({Key? key}) +class RecentPeersView extends BasePeersView { + RecentPeersView({Key? key}) : super( key: key, name: 'recent peer', loadEvent: 'load_recent_peers', offstageFunc: (Peer peer) => false, - peerCardWidgetFunc: (Peer peer) => RecentPeerCard( + peerCardBuilder: (Peer peer) => RecentPeerCard( peer: peer, ), initPeers: [], @@ -244,14 +244,14 @@ class RecentPeerWidget extends BasePeerWidget { } } -class FavoritePeerWidget extends BasePeerWidget { - FavoritePeerWidget({Key? key}) +class FavoritePeersView extends BasePeersView { + FavoritePeersView({Key? key}) : super( key: key, name: 'favorite peer', loadEvent: 'load_fav_peers', offstageFunc: (Peer peer) => false, - peerCardWidgetFunc: (Peer peer) => FavoritePeerCard( + peerCardBuilder: (Peer peer) => FavoritePeerCard( peer: peer, ), initPeers: [], @@ -265,14 +265,14 @@ class FavoritePeerWidget extends BasePeerWidget { } } -class DiscoveredPeerWidget extends BasePeerWidget { - DiscoveredPeerWidget({Key? key}) +class DiscoveredPeersView extends BasePeersView { + DiscoveredPeersView({Key? key}) : super( key: key, name: 'discovered peer', loadEvent: 'load_lan_peers', offstageFunc: (Peer peer) => false, - peerCardWidgetFunc: (Peer peer) => DiscoveredPeerCard( + peerCardBuilder: (Peer peer) => DiscoveredPeerCard( peer: peer, ), initPeers: [], @@ -286,15 +286,15 @@ class DiscoveredPeerWidget extends BasePeerWidget { } } -class AddressBookPeerWidget extends BasePeerWidget { - AddressBookPeerWidget({Key? key}) +class AddressBookPeersView extends BasePeersView { + AddressBookPeersView({Key? key}) : super( key: key, name: 'address book peer', loadEvent: 'load_address_book_peers', offstageFunc: (Peer peer) => !_hitTag(gFFI.abModel.selectedTags, peer.tags), - peerCardWidgetFunc: (Peer peer) => AddressBookPeerCard( + peerCardBuilder: (Peer peer) => AddressBookPeerCard( peer: peer, ), initPeers: _loadPeers(), diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index ad8e430f4..6a8c58f7b 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -11,7 +11,7 @@ import 'package:url_launcher/url_launcher_string.dart'; import '../../common.dart'; import '../../common/formatter/id_formatter.dart'; import '../../common/widgets/peer_tab_page.dart'; -import '../../common/widgets/peer_widget.dart'; +import '../../common/widgets/peers_view.dart'; import '../../models/platform_model.dart'; /// Connection page for connecting to a remote peer. @@ -74,9 +74,9 @@ class _ConnectionPageState extends State { translate('Address Book') ], children: [ - RecentPeerWidget(), - FavoritePeerWidget(), - DiscoveredPeerWidget(), + RecentPeersView(), + FavoritePeersView(), + DiscoveredPeersView(), const AddressBook(), ], )), diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index edae7deeb..833a914cd 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -331,7 +331,7 @@ Future loginDialog() async { var userNameMsg = ""; String pass = ""; var passMsg = ""; - var userContontroller = TextEditingController(text: userName); + var userController = TextEditingController(text: userName); var pwdController = TextEditingController(text: pass); var isInProgress = false; @@ -349,7 +349,7 @@ Future loginDialog() async { }); } - userName = userContontroller.text; + userName = userController.text; pass = pwdController.text; if (userName.isEmpty) { userNameMsg = translate("Username missed"); @@ -385,6 +385,7 @@ Future loginDialog() async { close(); } + // 登录dialog return CustomAlertDialog( title: Text(translate("Login")), content: ConstrainedBox( @@ -411,7 +412,7 @@ Future loginDialog() async { decoration: InputDecoration( border: const OutlineInputBorder(), errorText: userNameMsg.isNotEmpty ? userNameMsg : null), - controller: userContontroller, + controller: userController, focusNode: FocusNode()..requestFocus(), ), ), diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 60bc96b47..0918fc59b 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -48,7 +48,7 @@ class _DesktopSettingPageState extends State _TabInfo('Security', Icons.enhanced_encryption_outlined, Icons.enhanced_encryption), _TabInfo('Network', Icons.link_outlined, Icons.link), - _TabInfo('Acount', Icons.person_outline, Icons.person), + _TabInfo('Account', Icons.person_outline, Icons.person), _TabInfo('About', Icons.info_outline, Icons.info) ]; @@ -92,7 +92,7 @@ class _DesktopSettingPageState extends State _General(), _Safety(), _Network(), - _Acount(), + _Account(), _About(), ], )), @@ -641,14 +641,14 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin { } } -class _Acount extends StatefulWidget { - const _Acount({Key? key}) : super(key: key); +class _Account extends StatefulWidget { + const _Account({Key? key}) : super(key: key); @override - State<_Acount> createState() => _AcountState(); + State<_Account> createState() => _AccountState(); } -class _AcountState extends State<_Acount> { +class _AccountState extends State<_Account> { @override Widget build(BuildContext context) { final scrollController = ScrollController(); @@ -658,12 +658,12 @@ class _AcountState extends State<_Acount> { physics: NeverScrollableScrollPhysics(), controller: scrollController, children: [ - _Card(title: 'Acount', children: [login()]), + _Card(title: 'Account', children: [accountAction()]), ], ).marginOnly(bottom: _kListViewBottomMargin)); } - Widget login() { + Widget accountAction() { return _futureBuilder(future: () async { return await gFFI.userModel.getUserName(); }(), hasData: (data) { @@ -671,12 +671,14 @@ class _AcountState extends State<_Acount> { return _Button( username.isEmpty ? 'Login' : 'Logout', () => { - loginDialog().then((success) { - if (success) { - // refresh frame - setState(() {}); - } - }) + username.isEmpty + ? loginDialog().then((success) { + if (success) { + // refresh frame + setState(() {}); + } + }) + : gFFI.userModel.logOut() }); }); } diff --git a/flutter/lib/mobile/pages/connection_page.dart b/flutter/lib/mobile/pages/connection_page.dart index edc2f5f6d..6156223b5 100644 --- a/flutter/lib/mobile/pages/connection_page.dart +++ b/flutter/lib/mobile/pages/connection_page.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common/formatter/id_formatter.dart'; -import 'package:flutter_hbb/mobile/pages/file_manager_page.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -10,12 +9,11 @@ import 'package:url_launcher/url_launcher.dart'; import '../../common.dart'; import '../../common/widgets/address_book.dart'; import '../../common/widgets/peer_tab_page.dart'; -import '../../common/widgets/peer_widget.dart'; +import '../../common/widgets/peers_view.dart'; import '../../consts.dart'; import '../../models/model.dart'; import '../../models/platform_model.dart'; import 'home_page.dart'; -import 'remote_page.dart'; import 'scan_page.dart'; import 'settings_page.dart'; @@ -84,9 +82,9 @@ class _ConnectionPageState extends State { translate('Address Book') ], children: [ - RecentPeerWidget(), - FavoritePeerWidget(), - DiscoveredPeerWidget(), + RecentPeersView(), + FavoritePeersView(), + DiscoveredPeersView(), const AddressBook(), ], )), @@ -97,38 +95,7 @@ class _ConnectionPageState extends State { /// Connects to the selected peer. void onConnect() { var id = _idController.id; - connect(id); - } - - /// Connect to a peer with [id]. - /// If [isFileTransfer], starts a session only for file transfer. - void connect(String id, {bool isFileTransfer = false}) async { - if (id == '') return; - id = id.replaceAll(' ', ''); - if (isFileTransfer) { - if (!await PermissionManager.check("file")) { - if (!await PermissionManager.request("file")) { - return; - } - } - Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => FileManagerPage(id: id), - ), - ); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => RemotePage(id: id), - ), - ); - } - FocusScopeNode currentFocus = FocusScope.of(context); - if (!currentFocus.hasPrimaryFocus) { - currentFocus.unfocus(); - } + connect(context, id); } /// UI for software update. diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index 6f986ee78..985fe2df0 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -25,14 +25,13 @@ class SettingsPage extends StatefulWidget implements PageShape { final appBarActions = [ScanButton()]; @override - _SettingsState createState() => _SettingsState(); + State createState() => _SettingsState(); } const url = 'https://rustdesk.com/'; final _hasIgnoreBattery = androidVersion >= 26; var _ignoreBatteryOpt = false; var _enableAbr = false; -var _isDarkMode = false; class _SettingsState extends State with WidgetsBindingObserver { String? username; @@ -60,8 +59,6 @@ class _SettingsState extends State with WidgetsBindingObserver { _enableAbr = enableAbrRes; } - // _isDarkMode = MyTheme.currentDarkMode(); // TODO - if (update) { setState(() {}); } @@ -100,7 +97,7 @@ class _SettingsState extends State with WidgetsBindingObserver { Provider.of(context); final enhancementsTiles = [ SettingsTile.switchTile( - title: Text(translate('Adaptive Bitrate') + ' (beta)'), + title: Text('${translate('Adaptive Bitrate')} (beta)'), initialValue: _enableAbr, onToggle: (v) { bind.mainSetOption(key: "enable-abr", value: v ? "" : "N"); @@ -152,7 +149,7 @@ class _SettingsState extends State with WidgetsBindingObserver { SettingsTile.navigation( title: Text(username == null ? translate("Login") - : translate("Logout") + ' ($username)'), + : '${translate("Logout")} ($username)'), leading: Icon(Icons.person), onPressed: (context) { if (username == null) { @@ -177,15 +174,11 @@ class _SettingsState extends State with WidgetsBindingObserver { onPressed: (context) { showLanguageSettings(gFFI.dialogManager); }), - SettingsTile.switchTile( + SettingsTile.navigation( title: Text(translate('Dark Theme')), leading: Icon(Icons.dark_mode), - initialValue: _isDarkMode, - onToggle: (v) { - setState(() { - _isDarkMode = !_isDarkMode; - // MyTheme.changeDarkMode(_isDarkMode); // TODO - }); + onPressed: (context) { + showThemeSettings(gFFI.dialogManager); }, ) ]), @@ -232,7 +225,7 @@ void showLanguageSettings(OverlayDialogManager dialogManager) async { final langs = json.decode(await bind.mainGetLangs()) as List; var lang = await bind.mainGetLocalOption(key: "lang"); dialogManager.show((setState, close) { - final setLang = (v) { + setLang(v) { if (lang != v) { setState(() { lang = v; @@ -241,7 +234,8 @@ void showLanguageSettings(OverlayDialogManager dialogManager) async { HomePage.homeKey.currentState?.refreshPages(); Future.delayed(Duration(milliseconds: 200), close); } - }; + } + return CustomAlertDialog( title: SizedBox.shrink(), content: Column( @@ -257,13 +251,41 @@ void showLanguageSettings(OverlayDialogManager dialogManager) async { ), actions: []); }, backDismiss: true, clickMaskDismiss: true); - } catch (_e) {} + } 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); } void showAbout(OverlayDialogManager dialogManager) { dialogManager.show((setState, close) { return CustomAlertDialog( - title: Text(translate('About') + ' RustDesk'), + title: Text('${translate('About')} RustDesk'), content: Wrap(direction: Axis.vertical, spacing: 12, children: [ Text('Version: $version'), InkWell( @@ -429,7 +451,7 @@ void showLogin(OverlayDialogManager dialogManager) { ), controller: nameController, ), - PasswordWidget(controller: passwordController), + PasswordWidget(controller: passwordController, autoFocus: false), ]), actions: (loading ? [CircularProgressIndicator()] diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 503b82c50..c17045236 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -6,8 +6,7 @@ import '../../models/model.dart'; import '../../models/platform_model.dart'; void clientClose(OverlayDialogManager dialogManager) { - msgBox('', 'Close', 'Are you sure to close the connection?', - dialogManager); + msgBox('', 'Close', 'Are you sure to close the connection?', dialogManager); } void showSuccess() { @@ -131,7 +130,7 @@ void setTemporaryPasswordLengthDialog( if (index < 0) index = 0; length = lengths[index]; dialogManager.show((setState, close) { - final setLength = (newValue) { + setLength(newValue) { final oldValue = length; if (oldValue == newValue) return; setState(() { @@ -143,7 +142,8 @@ void setTemporaryPasswordLengthDialog( close(); showSuccess(); }); - }; + } + return CustomAlertDialog( title: Text(translate("Set temporary password length")), content: Column( @@ -230,12 +230,14 @@ void wrongPasswordDialog(String id, OverlayDialogManager dialogManager) { } class PasswordWidget extends StatefulWidget { - PasswordWidget({Key? key, required this.controller}) : super(key: key); + PasswordWidget({Key? key, required this.controller, this.autoFocus = true}) + : super(key: key); final TextEditingController controller; + final bool autoFocus; @override - _PasswordWidgetState createState() => _PasswordWidgetState(); + State createState() => _PasswordWidgetState(); } class _PasswordWidgetState extends State { @@ -245,7 +247,9 @@ class _PasswordWidgetState extends State { @override void initState() { super.initState(); - Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus()); + if (widget.autoFocus) { + Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus()); + } } @override diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 664d6f05b..47f3c0870 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "适应窗口"), ("General", "常规"), ("Security", "安全"), - ("Acount", "账户"), + ("Account", "账户"), ("Theme", "主题"), ("Dark Theme", "暗黑主题"), ("Enable hardware codec", "使用硬件编解码"), diff --git a/src/lang/cs.rs b/src/lang/cs.rs index ace56788f..9d203f9ce 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Měřítko adaptivní"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/da.rs b/src/lang/da.rs index 27724f7b3..a07539719 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Skala adaptiv"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/de.rs b/src/lang/de.rs index 8d90be381..fa589a564 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Adaptiv skalieren"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 6c7bb5aa8..cc28525e5 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Skalo adapta"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/es.rs b/src/lang/es.rs index c8296ced5..9704a3f84 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -337,7 +337,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Adaptable a escala"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/fr.rs b/src/lang/fr.rs index d9a42e934..8276a54f2 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Échelle adaptative"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/hu.rs b/src/lang/hu.rs index b35224c03..e322053ac 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Skála adaptív"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/id.rs b/src/lang/id.rs index 657014141..a285e15de 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -337,7 +337,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Skala adaptif"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/it.rs b/src/lang/it.rs index 8f6dfb3d9..917d5e9b2 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -323,7 +323,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Translate mode", ""), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 6d0a2a2f7..446bbc944 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -321,7 +321,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "フィットウィンドウ"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/ko.rs b/src/lang/ko.rs index ca939e2b8..cb223f77d 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -318,7 +318,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "맞는 창"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/pl.rs b/src/lang/pl.rs index fe45ddf3e..e6696fed5 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -322,7 +322,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Skala adaptacyjna"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 858afd8a1..783d93635 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -318,7 +318,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Escala adaptável"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index af4f0b52e..ac1688d13 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", ""), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 04cfed485..a005dc6ad 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Масштаб адаптивный"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 8ae17b1ad..837e491ce 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Prispôsobivá mierka"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/template.rs b/src/lang/template.rs index 914b103df..5c68cef37 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", ""), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/tr.rs b/src/lang/tr.rs index b1b029b39..a0cd3ed8d 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -337,7 +337,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Ölçek uyarlanabilir"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""), diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 764f666e7..c3c0849f0 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "適應窗口"), ("General", "常規"), ("Security", "安全"), - ("Acount", "賬戶"), + ("Account", "賬戶"), ("Theme", "主題"), ("Dark Theme", "暗黑主題"), ("Enable hardware codec", "使用硬件編解碼"), diff --git a/src/lang/vn.rs b/src/lang/vn.rs index f177581f9..88aa79dbf 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Scale adaptive", "Quy mô thích ứng"), ("General", ""), ("Security", ""), - ("Acount", ""), + ("Account", ""), ("Theme", ""), ("Dark Theme", ""), ("Enable hardware codec", ""),