Merge pull request #1600 from Heap-Hop/master

Update flutter
This commit is contained in:
RustDesk 2022-09-22 17:46:47 +08:00 committed by GitHub
commit 4f6c6ab483
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 198 additions and 179 deletions

View File

@ -17,6 +17,8 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
import 'common/widgets/overlay.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/model.dart';
import 'models/platform_model.dart'; import 'models/platform_model.dart';
@ -1071,14 +1073,38 @@ void connect(BuildContext context, String id,
assert(!(isFileTransfer && isTcpTunneling && isRDP), assert(!(isFileTransfer && isTcpTunneling && isRDP),
"more than one connect type"); "more than one connect type");
FocusScopeNode currentFocus = FocusScope.of(context); if (isDesktop) {
if (isFileTransfer) { if (isFileTransfer) {
await rustDeskWinManager.newFileTransfer(id); await rustDeskWinManager.newFileTransfer(id);
} else if (isTcpTunneling || isRDP) { } else if (isTcpTunneling || isRDP) {
await rustDeskWinManager.newPortForward(id, isRDP); await rustDeskWinManager.newPortForward(id, isRDP);
} else {
await rustDeskWinManager.newRemoteDesktop(id);
}
} else { } 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) { if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus(); currentFocus.unfocus();
} }

View File

@ -1,12 +1,13 @@
import 'package:contextmenu/contextmenu.dart'; import 'package:contextmenu/contextmenu.dart';
import 'package:flutter/material.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:flutter_hbb/models/ab_model.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../common.dart'; import '../../common.dart';
import '../../desktop/pages/desktop_home_page.dart'; import '../../desktop/pages/desktop_home_page.dart';
import '../../mobile/pages/settings_page.dart';
import '../../models/platform_model.dart'; import '../../models/platform_model.dart';
class AddressBook extends StatefulWidget { class AddressBook extends StatefulWidget {
@ -37,11 +38,16 @@ class _AddressBookState extends State<AddressBook> {
}); });
handleLogin() { handleLogin() {
loginDialog().then((success) { // TODO refactor login dialog for desktop and mobile
if (success) { if (isDesktop) {
setState(() {}); loginDialog().then((success) {
} if (success) {
}); setState(() {});
}
});
} else {
showLogin(gFFI.dialogManager);
}
} }
Future<Widget> buildAddressBook(BuildContext context) async { Future<Widget> buildAddressBook(BuildContext context) async {
@ -174,7 +180,7 @@ class _AddressBookState extends State<AddressBook> {
Expanded( Expanded(
child: Align( child: Align(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: AddressBookPeerWidget()), child: AddressBookPeersView()),
) )
], ],
)); ));

View File

@ -77,8 +77,11 @@ class _PeerCardState extends State<_PeerCard>
subtitle: Text('${peer.username}@${peer.hostname}'), subtitle: Text('${peer.username}@${peer.hostname}'),
title: Text(peer.alias.isEmpty ? formatID(peer.id) : peer.alias), title: Text(peer.alias.isEmpty ? formatID(peer.id) : peer.alias),
leading: Container( leading: Container(
decoration: BoxDecoration(
color: str2color('${peer.id}${peer.platform}', 0x7f),
borderRadius: BorderRadius.circular(4),
),
padding: const EdgeInsets.all(6), padding: const EdgeInsets.all(6),
color: str2color('${peer.id}${peer.platform}', 0x7f),
child: getPlatformImage(peer.platform)), child: getPlatformImage(peer.platform)),
trailing: InkWell( trailing: InkWell(
child: const Padding( child: const Padding(
@ -458,7 +461,7 @@ abstract class BasePeerCard extends StatelessWidget {
} }
await bind.mainSetPeerOption(id: id, key: option, value: value); 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); await bind.mainRemovePeer(id: id);
removePreference(id); removePreference(id);
await reloadFunc(); await reloadFunc();
// Get.forceAppUpdate(); // TODO use inner model / state
}(); }();
}, },
dismissOnClicked: true, dismissOnClicked: true,
@ -544,7 +546,6 @@ abstract class BasePeerCard extends StatelessWidget {
if (favs.remove(id)) { if (favs.remove(id)) {
await bind.mainStoreFav(favs: favs); await bind.mainStoreFav(favs: favs);
await reloadFunc(); await reloadFunc();
// Get.forceAppUpdate(); // TODO use inner model / state
} }
}(); }();
}, },
@ -589,8 +590,6 @@ abstract class BasePeerCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Container(
padding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Form( child: Form(
child: TextFormField( child: TextFormField(
controller: controller, controller: controller,
@ -625,15 +624,13 @@ class RecentPeerCard extends BasePeerCard {
final List<MenuEntryBase<String>> menuItems = [ final List<MenuEntryBase<String>> menuItems = [
_connectAction(context, peer), _connectAction(context, peer),
_transferFileAction(context, peer.id), _transferFileAction(context, peer.id),
_tcpTunnelingAction(context, peer.id),
]; ];
MenuEntryBase<String>? rdpAction; if (isDesktop) {
if (peer.platform == 'Windows') { menuItems.add(_tcpTunnelingAction(context, peer.id));
rdpAction = _rdpAction(context, peer.id);
} }
menuItems.add(await _forceAlwaysRelayAction(peer.id)); menuItems.add(await _forceAlwaysRelayAction(peer.id));
if (rdpAction != null) { if (peer.platform == 'Windows') {
menuItems.add(rdpAction); menuItems.add(_rdpAction(context, peer.id));
} }
menuItems.add(_wolAction(peer.id)); menuItems.add(_wolAction(peer.id));
menuItems.add(MenuEntryDivider()); menuItems.add(MenuEntryDivider());
@ -657,15 +654,13 @@ class FavoritePeerCard extends BasePeerCard {
final List<MenuEntryBase<String>> menuItems = [ final List<MenuEntryBase<String>> menuItems = [
_connectAction(context, peer), _connectAction(context, peer),
_transferFileAction(context, peer.id), _transferFileAction(context, peer.id),
_tcpTunnelingAction(context, peer.id),
]; ];
MenuEntryBase<String>? rdpAction; if (isDesktop) {
if (peer.platform == 'Windows') { menuItems.add(_tcpTunnelingAction(context, peer.id));
rdpAction = _rdpAction(context, peer.id);
} }
menuItems.add(await _forceAlwaysRelayAction(peer.id)); menuItems.add(await _forceAlwaysRelayAction(peer.id));
if (rdpAction != null) { if (peer.platform == 'Windows') {
menuItems.add(rdpAction); menuItems.add(_rdpAction(context, peer.id));
} }
menuItems.add(_wolAction(peer.id)); menuItems.add(_wolAction(peer.id));
menuItems.add(MenuEntryDivider()); menuItems.add(MenuEntryDivider());
@ -691,15 +686,13 @@ class DiscoveredPeerCard extends BasePeerCard {
final List<MenuEntryBase<String>> menuItems = [ final List<MenuEntryBase<String>> menuItems = [
_connectAction(context, peer), _connectAction(context, peer),
_transferFileAction(context, peer.id), _transferFileAction(context, peer.id),
_tcpTunnelingAction(context, peer.id),
]; ];
MenuEntryBase<String>? rdpAction; if (isDesktop) {
if (peer.platform == 'Windows') { menuItems.add(_tcpTunnelingAction(context, peer.id));
rdpAction = _rdpAction(context, peer.id);
} }
menuItems.add(await _forceAlwaysRelayAction(peer.id)); menuItems.add(await _forceAlwaysRelayAction(peer.id));
if (rdpAction != null) { if (peer.platform == 'Windows') {
menuItems.add(rdpAction); menuItems.add(_rdpAction(context, peer.id));
} }
menuItems.add(_wolAction(peer.id)); menuItems.add(_wolAction(peer.id));
menuItems.add(MenuEntryDivider()); menuItems.add(MenuEntryDivider());
@ -722,15 +715,13 @@ class AddressBookPeerCard extends BasePeerCard {
final List<MenuEntryBase<String>> menuItems = [ final List<MenuEntryBase<String>> menuItems = [
_connectAction(context, peer), _connectAction(context, peer),
_transferFileAction(context, peer.id), _transferFileAction(context, peer.id),
_tcpTunnelingAction(context, peer.id),
]; ];
MenuEntryBase<String>? rdpAction; if (isDesktop) {
if (peer.platform == 'Windows') { menuItems.add(_tcpTunnelingAction(context, peer.id));
rdpAction = _rdpAction(context, peer.id);
} }
menuItems.add(await _forceAlwaysRelayAction(peer.id)); menuItems.add(await _forceAlwaysRelayAction(peer.id));
if (rdpAction != null) { if (peer.platform == 'Windows') {
menuItems.add(rdpAction); menuItems.add(_rdpAction(context, peer.id));
} }
menuItems.add(_wolAction(peer.id)); menuItems.add(_wolAction(peer.id));
menuItems.add(MenuEntryDivider()); menuItems.add(MenuEntryDivider());

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.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/common/widgets/peercard_widget.dart'; import 'package:flutter_hbb/common/widgets/peer_card.dart';
import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/consts.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@ -113,7 +113,7 @@ class _PeerTabPageState extends State<PeerTabPage>
color: _tabIndex.value == t.key color: _tabIndex.value == t.key
? MyTheme.color(context).bg ? MyTheme.color(context).bg
: null, : null,
borderRadius: BorderRadius.circular(2), borderRadius: BorderRadius.circular(isDesktop ? 2 : 6),
), ),
child: Align( child: Align(
alignment: Alignment.center, alignment: Alignment.center,

View File

@ -11,34 +11,34 @@ import 'package:window_manager/window_manager.dart';
import '../../common.dart'; import '../../common.dart';
import '../../models/peer_model.dart'; import '../../models/peer_model.dart';
import '../../models/platform_model.dart'; import '../../models/platform_model.dart';
import 'peercard_widget.dart'; import 'peer_card.dart';
typedef OffstageFunc = bool Function(Peer peer); 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 /// for peer search text, global obs value
final peerSearchText = "".obs; final peerSearchText = "".obs;
final peerSearchTextController = final peerSearchTextController =
TextEditingController(text: peerSearchText.value); TextEditingController(text: peerSearchText.value);
class _PeerWidget extends StatefulWidget { class _PeersView extends StatefulWidget {
final Peers peers; final Peers peers;
final OffstageFunc offstageFunc; final OffstageFunc offstageFunc;
final PeerCardWidgetFunc peerCardWidgetFunc; final PeerCardBuilder peerCardBuilder;
const _PeerWidget( const _PeersView(
{required this.peers, {required this.peers,
required this.offstageFunc, required this.offstageFunc,
required this.peerCardWidgetFunc, required this.peerCardBuilder,
Key? key}) Key? key})
: super(key: key); : super(key: key);
@override @override
_PeerWidgetState createState() => _PeerWidgetState(); _PeersViewState createState() => _PeersViewState();
} }
/// State for the peer widget. /// State for the peer widget.
class _PeerWidgetState extends State<_PeerWidget> with WindowListener { class _PeersViewState extends State<_PeersView> with WindowListener {
static const int _maxQueryCount = 3; static const int _maxQueryCount = 3;
final space = isDesktop ? 12.0 : 8.0; final space = isDesktop ? 12.0 : 8.0;
final _curPeers = <String>{}; final _curPeers = <String>{};
@ -60,7 +60,7 @@ class _PeerWidgetState extends State<_PeerWidget> with WindowListener {
return width; return width;
}(); }();
_PeerWidgetState() { _PeersViewState() {
_startCheckOnlines(); _startCheckOnlines();
} }
@ -119,7 +119,7 @@ class _PeerWidgetState extends State<_PeerWidget> with WindowListener {
} }
_lastChangeTime = DateTime.now(); _lastChangeTime = DateTime.now();
}, },
child: widget.peerCardWidgetFunc(peer), child: widget.peerCardBuilder(peer),
); );
cards.add(Offstage( cards.add(Offstage(
key: ValueKey("off${peer.id}"), 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 name;
final String loadEvent; final String loadEvent;
final OffstageFunc offstageFunc; final OffstageFunc offstageFunc;
final PeerCardWidgetFunc peerCardWidgetFunc; final PeerCardBuilder peerCardBuilder;
final List<Peer> initPeers; final List<Peer> initPeers;
const BasePeerWidget({ const BasePeersView({
Key? key, Key? key,
required this.name, required this.name,
required this.loadEvent, required this.loadEvent,
required this.offstageFunc, required this.offstageFunc,
required this.peerCardWidgetFunc, required this.peerCardBuilder,
required this.initPeers, required this.initPeers,
}) : super(key: key); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _PeerWidget( return _PeersView(
peers: Peers(name: name, loadEvent: loadEvent, peers: initPeers), peers: Peers(name: name, loadEvent: loadEvent, peers: initPeers),
offstageFunc: offstageFunc, offstageFunc: offstageFunc,
peerCardWidgetFunc: peerCardWidgetFunc); peerCardBuilder: peerCardBuilder);
} }
} }
class RecentPeerWidget extends BasePeerWidget { class RecentPeersView extends BasePeersView {
RecentPeerWidget({Key? key}) RecentPeersView({Key? key})
: super( : super(
key: key, key: key,
name: 'recent peer', name: 'recent peer',
loadEvent: 'load_recent_peers', loadEvent: 'load_recent_peers',
offstageFunc: (Peer peer) => false, offstageFunc: (Peer peer) => false,
peerCardWidgetFunc: (Peer peer) => RecentPeerCard( peerCardBuilder: (Peer peer) => RecentPeerCard(
peer: peer, peer: peer,
), ),
initPeers: [], initPeers: [],
@ -244,14 +244,14 @@ class RecentPeerWidget extends BasePeerWidget {
} }
} }
class FavoritePeerWidget extends BasePeerWidget { class FavoritePeersView extends BasePeersView {
FavoritePeerWidget({Key? key}) FavoritePeersView({Key? key})
: super( : super(
key: key, key: key,
name: 'favorite peer', name: 'favorite peer',
loadEvent: 'load_fav_peers', loadEvent: 'load_fav_peers',
offstageFunc: (Peer peer) => false, offstageFunc: (Peer peer) => false,
peerCardWidgetFunc: (Peer peer) => FavoritePeerCard( peerCardBuilder: (Peer peer) => FavoritePeerCard(
peer: peer, peer: peer,
), ),
initPeers: [], initPeers: [],
@ -265,14 +265,14 @@ class FavoritePeerWidget extends BasePeerWidget {
} }
} }
class DiscoveredPeerWidget extends BasePeerWidget { class DiscoveredPeersView extends BasePeersView {
DiscoveredPeerWidget({Key? key}) DiscoveredPeersView({Key? key})
: super( : super(
key: key, key: key,
name: 'discovered peer', name: 'discovered peer',
loadEvent: 'load_lan_peers', loadEvent: 'load_lan_peers',
offstageFunc: (Peer peer) => false, offstageFunc: (Peer peer) => false,
peerCardWidgetFunc: (Peer peer) => DiscoveredPeerCard( peerCardBuilder: (Peer peer) => DiscoveredPeerCard(
peer: peer, peer: peer,
), ),
initPeers: [], initPeers: [],
@ -286,15 +286,15 @@ class DiscoveredPeerWidget extends BasePeerWidget {
} }
} }
class AddressBookPeerWidget extends BasePeerWidget { class AddressBookPeersView extends BasePeersView {
AddressBookPeerWidget({Key? key}) AddressBookPeersView({Key? key})
: super( : super(
key: key, key: key,
name: 'address book peer', name: 'address book peer',
loadEvent: 'load_address_book_peers', loadEvent: 'load_address_book_peers',
offstageFunc: (Peer peer) => offstageFunc: (Peer peer) =>
!_hitTag(gFFI.abModel.selectedTags, peer.tags), !_hitTag(gFFI.abModel.selectedTags, peer.tags),
peerCardWidgetFunc: (Peer peer) => AddressBookPeerCard( peerCardBuilder: (Peer peer) => AddressBookPeerCard(
peer: peer, peer: peer,
), ),
initPeers: _loadPeers(), initPeers: _loadPeers(),

View File

@ -11,7 +11,7 @@ import 'package:url_launcher/url_launcher_string.dart';
import '../../common.dart'; import '../../common.dart';
import '../../common/formatter/id_formatter.dart'; import '../../common/formatter/id_formatter.dart';
import '../../common/widgets/peer_tab_page.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'; import '../../models/platform_model.dart';
/// Connection page for connecting to a remote peer. /// Connection page for connecting to a remote peer.
@ -74,9 +74,9 @@ class _ConnectionPageState extends State<ConnectionPage> {
translate('Address Book') translate('Address Book')
], ],
children: [ children: [
RecentPeerWidget(), RecentPeersView(),
FavoritePeerWidget(), FavoritePeersView(),
DiscoveredPeerWidget(), DiscoveredPeersView(),
const AddressBook(), const AddressBook(),
], ],
)), )),

View File

@ -331,7 +331,7 @@ Future<bool> loginDialog() async {
var userNameMsg = ""; var userNameMsg = "";
String pass = ""; String pass = "";
var passMsg = ""; var passMsg = "";
var userContontroller = TextEditingController(text: userName); var userController = TextEditingController(text: userName);
var pwdController = TextEditingController(text: pass); var pwdController = TextEditingController(text: pass);
var isInProgress = false; var isInProgress = false;
@ -349,7 +349,7 @@ Future<bool> loginDialog() async {
}); });
} }
userName = userContontroller.text; userName = userController.text;
pass = pwdController.text; pass = pwdController.text;
if (userName.isEmpty) { if (userName.isEmpty) {
userNameMsg = translate("Username missed"); userNameMsg = translate("Username missed");
@ -385,6 +385,7 @@ Future<bool> loginDialog() async {
close(); close();
} }
// dialog
return CustomAlertDialog( return CustomAlertDialog(
title: Text(translate("Login")), title: Text(translate("Login")),
content: ConstrainedBox( content: ConstrainedBox(
@ -411,7 +412,7 @@ Future<bool> loginDialog() async {
decoration: InputDecoration( decoration: InputDecoration(
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
errorText: userNameMsg.isNotEmpty ? userNameMsg : null), errorText: userNameMsg.isNotEmpty ? userNameMsg : null),
controller: userContontroller, controller: userController,
focusNode: FocusNode()..requestFocus(), focusNode: FocusNode()..requestFocus(),
), ),
), ),

View File

@ -48,7 +48,7 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
_TabInfo('Security', Icons.enhanced_encryption_outlined, _TabInfo('Security', Icons.enhanced_encryption_outlined,
Icons.enhanced_encryption), Icons.enhanced_encryption),
_TabInfo('Network', Icons.link_outlined, Icons.link), _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) _TabInfo('About', Icons.info_outline, Icons.info)
]; ];
@ -92,7 +92,7 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
_General(), _General(),
_Safety(), _Safety(),
_Network(), _Network(),
_Acount(), _Account(),
_About(), _About(),
], ],
)), )),
@ -641,14 +641,14 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
} }
} }
class _Acount extends StatefulWidget { class _Account extends StatefulWidget {
const _Acount({Key? key}) : super(key: key); const _Account({Key? key}) : super(key: key);
@override @override
State<_Acount> createState() => _AcountState(); State<_Account> createState() => _AccountState();
} }
class _AcountState extends State<_Acount> { class _AccountState extends State<_Account> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final scrollController = ScrollController(); final scrollController = ScrollController();
@ -658,12 +658,12 @@ class _AcountState extends State<_Acount> {
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
controller: scrollController, controller: scrollController,
children: [ children: [
_Card(title: 'Acount', children: [login()]), _Card(title: 'Account', children: [accountAction()]),
], ],
).marginOnly(bottom: _kListViewBottomMargin)); ).marginOnly(bottom: _kListViewBottomMargin));
} }
Widget login() { Widget accountAction() {
return _futureBuilder(future: () async { return _futureBuilder(future: () async {
return await gFFI.userModel.getUserName(); return await gFFI.userModel.getUserName();
}(), hasData: (data) { }(), hasData: (data) {
@ -671,12 +671,14 @@ class _AcountState extends State<_Acount> {
return _Button( return _Button(
username.isEmpty ? 'Login' : 'Logout', username.isEmpty ? 'Login' : 'Logout',
() => { () => {
loginDialog().then((success) { username.isEmpty
if (success) { ? loginDialog().then((success) {
// refresh frame if (success) {
setState(() {}); // refresh frame
} setState(() {});
}) }
})
: gFFI.userModel.logOut()
}); });
}); });
} }

View File

@ -2,7 +2,6 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hbb/common/formatter/id_formatter.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:get/get.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -10,12 +9,11 @@ import 'package:url_launcher/url_launcher.dart';
import '../../common.dart'; import '../../common.dart';
import '../../common/widgets/address_book.dart'; import '../../common/widgets/address_book.dart';
import '../../common/widgets/peer_tab_page.dart'; import '../../common/widgets/peer_tab_page.dart';
import '../../common/widgets/peer_widget.dart'; import '../../common/widgets/peers_view.dart';
import '../../consts.dart'; import '../../consts.dart';
import '../../models/model.dart'; import '../../models/model.dart';
import '../../models/platform_model.dart'; import '../../models/platform_model.dart';
import 'home_page.dart'; import 'home_page.dart';
import 'remote_page.dart';
import 'scan_page.dart'; import 'scan_page.dart';
import 'settings_page.dart'; import 'settings_page.dart';
@ -84,9 +82,9 @@ class _ConnectionPageState extends State<ConnectionPage> {
translate('Address Book') translate('Address Book')
], ],
children: [ children: [
RecentPeerWidget(), RecentPeersView(),
FavoritePeerWidget(), FavoritePeersView(),
DiscoveredPeerWidget(), DiscoveredPeersView(),
const AddressBook(), const AddressBook(),
], ],
)), )),
@ -97,38 +95,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
/// Connects to the selected peer. /// Connects to the selected peer.
void onConnect() { void onConnect() {
var id = _idController.id; var id = _idController.id;
connect(id); connect(context, 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();
}
} }
/// UI for software update. /// UI for software update.

View File

@ -25,14 +25,13 @@ class SettingsPage extends StatefulWidget implements PageShape {
final appBarActions = [ScanButton()]; final appBarActions = [ScanButton()];
@override @override
_SettingsState createState() => _SettingsState(); State<SettingsPage> createState() => _SettingsState();
} }
const url = 'https://rustdesk.com/'; const url = 'https://rustdesk.com/';
final _hasIgnoreBattery = androidVersion >= 26; final _hasIgnoreBattery = androidVersion >= 26;
var _ignoreBatteryOpt = false; var _ignoreBatteryOpt = false;
var _enableAbr = false; var _enableAbr = false;
var _isDarkMode = false;
class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver { class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
String? username; String? username;
@ -60,8 +59,6 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
_enableAbr = enableAbrRes; _enableAbr = enableAbrRes;
} }
// _isDarkMode = MyTheme.currentDarkMode(); // TODO
if (update) { if (update) {
setState(() {}); setState(() {});
} }
@ -100,7 +97,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
Provider.of<FfiModel>(context); Provider.of<FfiModel>(context);
final enhancementsTiles = [ final enhancementsTiles = [
SettingsTile.switchTile( SettingsTile.switchTile(
title: Text(translate('Adaptive Bitrate') + ' (beta)'), title: Text('${translate('Adaptive Bitrate')} (beta)'),
initialValue: _enableAbr, initialValue: _enableAbr,
onToggle: (v) { onToggle: (v) {
bind.mainSetOption(key: "enable-abr", value: v ? "" : "N"); bind.mainSetOption(key: "enable-abr", value: v ? "" : "N");
@ -152,7 +149,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
SettingsTile.navigation( SettingsTile.navigation(
title: Text(username == null title: Text(username == null
? translate("Login") ? translate("Login")
: translate("Logout") + ' ($username)'), : '${translate("Logout")} ($username)'),
leading: Icon(Icons.person), leading: Icon(Icons.person),
onPressed: (context) { onPressed: (context) {
if (username == null) { if (username == null) {
@ -177,15 +174,11 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
onPressed: (context) { onPressed: (context) {
showLanguageSettings(gFFI.dialogManager); showLanguageSettings(gFFI.dialogManager);
}), }),
SettingsTile.switchTile( SettingsTile.navigation(
title: Text(translate('Dark Theme')), title: Text(translate('Dark Theme')),
leading: Icon(Icons.dark_mode), leading: Icon(Icons.dark_mode),
initialValue: _isDarkMode, onPressed: (context) {
onToggle: (v) { showThemeSettings(gFFI.dialogManager);
setState(() {
_isDarkMode = !_isDarkMode;
// MyTheme.changeDarkMode(_isDarkMode); // TODO
});
}, },
) )
]), ]),
@ -232,7 +225,7 @@ void showLanguageSettings(OverlayDialogManager dialogManager) async {
final langs = json.decode(await bind.mainGetLangs()) as List<dynamic>; final langs = json.decode(await bind.mainGetLangs()) as List<dynamic>;
var lang = await bind.mainGetLocalOption(key: "lang"); var lang = await bind.mainGetLocalOption(key: "lang");
dialogManager.show((setState, close) { dialogManager.show((setState, close) {
final setLang = (v) { setLang(v) {
if (lang != v) { if (lang != v) {
setState(() { setState(() {
lang = v; lang = v;
@ -241,7 +234,8 @@ void showLanguageSettings(OverlayDialogManager dialogManager) async {
HomePage.homeKey.currentState?.refreshPages(); HomePage.homeKey.currentState?.refreshPages();
Future.delayed(Duration(milliseconds: 200), close); Future.delayed(Duration(milliseconds: 200), close);
} }
}; }
return CustomAlertDialog( return CustomAlertDialog(
title: SizedBox.shrink(), title: SizedBox.shrink(),
content: Column( content: Column(
@ -257,13 +251,41 @@ void showLanguageSettings(OverlayDialogManager dialogManager) async {
), ),
actions: []); actions: []);
}, backDismiss: true, clickMaskDismiss: true); }, 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) { void showAbout(OverlayDialogManager dialogManager) {
dialogManager.show((setState, close) { dialogManager.show((setState, close) {
return CustomAlertDialog( return CustomAlertDialog(
title: Text(translate('About') + ' RustDesk'), title: Text('${translate('About')} RustDesk'),
content: Wrap(direction: Axis.vertical, spacing: 12, children: [ content: Wrap(direction: Axis.vertical, spacing: 12, children: [
Text('Version: $version'), Text('Version: $version'),
InkWell( InkWell(
@ -429,7 +451,7 @@ void showLogin(OverlayDialogManager dialogManager) {
), ),
controller: nameController, controller: nameController,
), ),
PasswordWidget(controller: passwordController), PasswordWidget(controller: passwordController, autoFocus: false),
]), ]),
actions: (loading actions: (loading
? <Widget>[CircularProgressIndicator()] ? <Widget>[CircularProgressIndicator()]

View File

@ -6,8 +6,7 @@ import '../../models/model.dart';
import '../../models/platform_model.dart'; import '../../models/platform_model.dart';
void clientClose(OverlayDialogManager dialogManager) { void clientClose(OverlayDialogManager dialogManager) {
msgBox('', 'Close', 'Are you sure to close the connection?', msgBox('', 'Close', 'Are you sure to close the connection?', dialogManager);
dialogManager);
} }
void showSuccess() { void showSuccess() {
@ -131,7 +130,7 @@ void setTemporaryPasswordLengthDialog(
if (index < 0) index = 0; if (index < 0) index = 0;
length = lengths[index]; length = lengths[index];
dialogManager.show((setState, close) { dialogManager.show((setState, close) {
final setLength = (newValue) { setLength(newValue) {
final oldValue = length; final oldValue = length;
if (oldValue == newValue) return; if (oldValue == newValue) return;
setState(() { setState(() {
@ -143,7 +142,8 @@ void setTemporaryPasswordLengthDialog(
close(); close();
showSuccess(); showSuccess();
}); });
}; }
return CustomAlertDialog( return CustomAlertDialog(
title: Text(translate("Set temporary password length")), title: Text(translate("Set temporary password length")),
content: Column( content: Column(
@ -230,12 +230,14 @@ void wrongPasswordDialog(String id, OverlayDialogManager dialogManager) {
} }
class PasswordWidget extends StatefulWidget { 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 TextEditingController controller;
final bool autoFocus;
@override @override
_PasswordWidgetState createState() => _PasswordWidgetState(); State<PasswordWidget> createState() => _PasswordWidgetState();
} }
class _PasswordWidgetState extends State<PasswordWidget> { class _PasswordWidgetState extends State<PasswordWidget> {
@ -245,7 +247,9 @@ class _PasswordWidgetState extends State<PasswordWidget> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus()); if (widget.autoFocus) {
Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus());
}
} }
@override @override

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "适应窗口"), ("Scale adaptive", "适应窗口"),
("General", "常规"), ("General", "常规"),
("Security", "安全"), ("Security", "安全"),
("Acount", "账户"), ("Account", "账户"),
("Theme", "主题"), ("Theme", "主题"),
("Dark Theme", "暗黑主题"), ("Dark Theme", "暗黑主题"),
("Enable hardware codec", "使用硬件编解码"), ("Enable hardware codec", "使用硬件编解码"),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Měřítko adaptivní"), ("Scale adaptive", "Měřítko adaptivní"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Skala adaptiv"), ("Scale adaptive", "Skala adaptiv"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Adaptiv skalieren"), ("Scale adaptive", "Adaptiv skalieren"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Skalo adapta"), ("Scale adaptive", "Skalo adapta"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -337,7 +337,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Adaptable a escala"), ("Scale adaptive", "Adaptable a escala"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Échelle adaptative"), ("Scale adaptive", "Échelle adaptative"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Skála adaptív"), ("Scale adaptive", "Skála adaptív"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -337,7 +337,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Skala adaptif"), ("Scale adaptive", "Skala adaptif"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -323,7 +323,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Translate mode", ""), ("Translate mode", ""),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -321,7 +321,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "フィットウィンドウ"), ("Scale adaptive", "フィットウィンドウ"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -318,7 +318,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "맞는 창"), ("Scale adaptive", "맞는 창"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -322,7 +322,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Skala adaptacyjna"), ("Scale adaptive", "Skala adaptacyjna"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -318,7 +318,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Escala adaptável"), ("Scale adaptive", "Escala adaptável"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", ""), ("Scale adaptive", ""),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Масштаб адаптивный"), ("Scale adaptive", "Масштаб адаптивный"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Prispôsobivá mierka"), ("Scale adaptive", "Prispôsobivá mierka"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", ""), ("Scale adaptive", ""),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -337,7 +337,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Ölçek uyarlanabilir"), ("Scale adaptive", "Ölçek uyarlanabilir"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "適應窗口"), ("Scale adaptive", "適應窗口"),
("General", "常規"), ("General", "常規"),
("Security", "安全"), ("Security", "安全"),
("Acount", "賬戶"), ("Account", "賬戶"),
("Theme", "主題"), ("Theme", "主題"),
("Dark Theme", "暗黑主題"), ("Dark Theme", "暗黑主題"),
("Enable hardware codec", "使用硬件編解碼"), ("Enable hardware codec", "使用硬件編解碼"),

View File

@ -324,7 +324,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Scale adaptive", "Quy mô thích ứng"), ("Scale adaptive", "Quy mô thích ứng"),
("General", ""), ("General", ""),
("Security", ""), ("Security", ""),
("Acount", ""), ("Account", ""),
("Theme", ""), ("Theme", ""),
("Dark Theme", ""), ("Dark Theme", ""),
("Enable hardware codec", ""), ("Enable hardware codec", ""),