Merge branch 'master' into record

This commit is contained in:
RustDesk
2022-09-27 15:32:27 +08:00
committed by GitHub
76 changed files with 1734 additions and 1072 deletions

View File

@@ -5,14 +5,16 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common/widgets/address_book.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:get/get.dart';
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';
import '../widgets/button.dart';
/// Connection page for connecting to a remote peer.
class ConnectionPage extends StatefulWidget {
@@ -74,10 +76,18 @@ class _ConnectionPageState extends State<ConnectionPage> {
translate('Address Book')
],
children: [
RecentPeerWidget(),
FavoritePeerWidget(),
DiscoveredPeerWidget(),
const AddressBook(),
RecentPeersView(
menuPadding: EdgeInsets.only(left: 12.0, right: 3.0),
),
FavoritePeersView(
menuPadding: EdgeInsets.only(left: 12.0, right: 3.0),
),
DiscoveredPeersView(
menuPadding: EdgeInsets.only(left: 12.0, right: 3.0),
),
const AddressBook(
menuPadding: EdgeInsets.only(left: 12.0, right: 3.0),
),
],
)),
],
@@ -100,10 +110,6 @@ class _ConnectionPageState extends State<ConnectionPage> {
/// UI for the remote ID TextField.
/// Search for a peer and connect to it if the id exists.
Widget _buildRemoteIDTextField(BuildContext context) {
RxBool ftHover = false.obs;
RxBool ftPressed = false.obs;
RxBool connHover = false.obs;
RxBool connPressed = false.obs;
RxBool inputFocused = false.obs;
FocusNode focusNode = FocusNode();
focusNode.addListener(() {
@@ -113,7 +119,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
width: 320 + 20 * 2,
padding: const EdgeInsets.fromLTRB(20, 24, 20, 22),
decoration: BoxDecoration(
color: MyTheme.color(context).bg,
color: Theme.of(context).backgroundColor,
borderRadius: const BorderRadius.all(Radius.circular(13)),
),
child: Ink(
@@ -123,7 +129,10 @@ class _ConnectionPageState extends State<ConnectionPage> {
children: [
Text(
translate('Control Remote Desktop'),
style: const TextStyle(fontSize: 19, height: 1),
style: Theme.of(context)
.textTheme
.titleLarge
?.merge(TextStyle(height: 1)),
),
],
).marginOnly(bottom: 15),
@@ -142,13 +151,12 @@ class _ConnectionPageState extends State<ConnectionPage> {
height: 1,
),
maxLines: 1,
cursorColor: MyTheme.color(context).text!,
cursorColor:
Theme.of(context).textTheme.titleLarge?.color,
decoration: InputDecoration(
hintText: inputFocused.value
? null
: translate('Enter Remote ID'),
hintStyle: TextStyle(
color: MyTheme.color(context).placeholder),
border: OutlineInputBorder(
borderRadius: BorderRadius.zero,
borderSide: BorderSide(
@@ -180,84 +188,17 @@ class _ConnectionPageState extends State<ConnectionPage> {
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Obx(() => InkWell(
onTapDown: (_) => ftPressed.value = true,
onTapUp: (_) => ftPressed.value = false,
onTapCancel: () => ftPressed.value = false,
onHover: (value) => ftHover.value = value,
onTap: () {
onConnect(isFileTransfer: true);
},
child: Container(
height: 27,
alignment: Alignment.center,
decoration: BoxDecoration(
color: ftPressed.value
? MyTheme.accent
: Colors.transparent,
border: Border.all(
color: ftPressed.value
? MyTheme.accent
: ftHover.value
? MyTheme.hoverBorder
: MyTheme.border,
),
borderRadius: BorderRadius.circular(5),
),
child: Text(
translate(
"Transfer File",
),
style: TextStyle(
fontSize: 12,
color: ftPressed.value
? MyTheme.color(context).bg
: MyTheme.color(context).text),
).marginSymmetric(horizontal: 12),
),
)),
Button(
isOutline: true,
onTap: () {
onConnect(isFileTransfer: true);
},
text: "Transfer File",
),
const SizedBox(
width: 17,
),
Obx(
() => InkWell(
onTapDown: (_) => connPressed.value = true,
onTapUp: (_) => connPressed.value = false,
onTapCancel: () => connPressed.value = false,
onHover: (value) => connHover.value = value,
onTap: onConnect,
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 80.0,
),
child: Container(
height: 27,
decoration: BoxDecoration(
color: connPressed.value
? MyTheme.accent
: MyTheme.button,
border: Border.all(
color: connPressed.value
? MyTheme.accent
: connHover.value
? MyTheme.hoverBorder
: MyTheme.button,
),
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: Text(
translate(
"Connect",
),
style: TextStyle(
fontSize: 12,
color: MyTheme.color(context).bg),
),
).marginSymmetric(horizontal: 12),
)),
),
),
Button(onTap: onConnect, text: "Connect"),
],
),
)
@@ -289,7 +230,11 @@ class _ConnectionPageState extends State<ConnectionPage> {
width: 8,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: svcStopped.value ? Colors.redAccent : Colors.green,
color: svcStopped.value || svcStatusCode.value == 0
? kColorWarn
: (svcStatusCode.value == 1
? Color.fromARGB(255, 50, 190, 166)
: Color.fromARGB(255, 224, 79, 95)),
),
).paddingSymmetric(horizontal: 12.0);
if (svcStopped.value) {

View File

@@ -5,6 +5,8 @@ import 'package:flutter/material.dart' hide MenuItem;
import 'package:flutter/services.dart';
import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/desktop/pages/connection_page.dart';
import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart';
import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
import 'package:flutter_hbb/models/platform_model.dart';
import 'package:flutter_hbb/models/server_model.dart';
import 'package:flutter_hbb/utils/multi_window_manager.dart';
@@ -12,6 +14,9 @@ import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'package:tray_manager/tray_manager.dart';
import 'package:window_manager/window_manager.dart';
import 'package:url_launcher/url_launcher.dart';
import '../widgets/button.dart';
class DesktopHomePage extends StatefulWidget {
const DesktopHomePage({Key? key}) : super(key: key);
@@ -26,6 +31,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
with TrayListener, WindowListener, AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
var updateUrl = '';
@override
void onWindowClose() async {
@@ -68,12 +74,13 @@ class _DesktopHomePageState extends State<DesktopHomePage>
value: gFFI.serverModel,
child: Container(
width: 200,
color: MyTheme.color(context).bg,
color: Theme.of(context).backgroundColor,
child: Column(
children: [
buildTip(context),
buildIDBoard(context),
buildPasswordBoard(context),
buildHelpCards(),
],
),
),
@@ -82,7 +89,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
buildRightPane(BuildContext context) {
return Container(
color: MyTheme.color(context).grayBg,
color: Theme.of(context).scaffoldBackgroundColor,
child: ConnectionPage(),
);
}
@@ -116,7 +123,11 @@ class _DesktopHomePageState extends State<DesktopHomePage>
translate("ID"),
style: TextStyle(
fontSize: 14,
color: MyTheme.color(context).lightText),
color: Theme.of(context)
.textTheme
.titleLarge
?.color
?.withOpacity(0.5)),
).marginOnly(top: 5),
buildPopupMenu(context)
],
@@ -152,21 +163,20 @@ class _DesktopHomePageState extends State<DesktopHomePage>
}
Widget buildPopupMenu(BuildContext context) {
final textColor = Theme.of(context).textTheme.titleLarge?.color;
RxBool hover = false.obs;
return InkWell(
onTap: () async {},
onTap: DesktopTabPage.onAddSetting,
child: Obx(
() => CircleAvatar(
radius: 15,
backgroundColor: hover.value
? MyTheme.color(context).grayBg!
: MyTheme.color(context).bg!,
? Theme.of(context).scaffoldBackgroundColor
: Theme.of(context).backgroundColor,
child: Icon(
Icons.more_vert_outlined,
size: 20,
color: hover.value
? MyTheme.color(context).text
: MyTheme.color(context).lightText,
color: hover.value ? textColor : textColor?.withOpacity(0.5),
),
),
),
@@ -178,6 +188,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
final model = gFFI.serverModel;
RxBool refreshHover = false.obs;
RxBool editHover = false.obs;
final textColor = Theme.of(context).textTheme.titleLarge?.color;
return Container(
margin: EdgeInsets.only(left: 20.0, right: 16, top: 13, bottom: 13),
child: Row(
@@ -198,7 +209,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
Text(
translate("Password"),
style: TextStyle(
fontSize: 14, color: MyTheme.color(context).lightText),
fontSize: 14, color: textColor?.withOpacity(0.5)),
),
Row(
children: [
@@ -228,8 +239,8 @@ class _DesktopHomePageState extends State<DesktopHomePage>
() => Icon(
Icons.refresh,
color: refreshHover.value
? MyTheme.color(context).text
: Color(0xFFDDDDDD),
? textColor
: Color(0xFFDDDDDD), // TODO
size: 22,
).marginOnly(right: 8, bottom: 2),
),
@@ -241,12 +252,12 @@ class _DesktopHomePageState extends State<DesktopHomePage>
() => Icon(
Icons.edit,
color: editHover.value
? MyTheme.color(context).text
: Color(0xFFDDDDDD),
? textColor
: Color(0xFFDDDDDD), // TODO
size: 22,
).marginOnly(right: 8, bottom: 2),
),
onTap: () => {},
onTap: () => DesktopSettingPage.switch2page(1),
onHover: (value) => editHover.value = value,
),
],
@@ -270,7 +281,11 @@ class _DesktopHomePageState extends State<DesktopHomePage>
children: [
Text(
translate("Your Desktop"),
style: TextStyle(fontWeight: FontWeight.normal, fontSize: 19),
style: Theme.of(context).textTheme.titleLarge,
// style: TextStyle(
// // color: MyTheme.color(context).text,
// fontWeight: FontWeight.normal,
// fontSize: 19),
),
SizedBox(
height: 10.0,
@@ -278,16 +293,93 @@ class _DesktopHomePageState extends State<DesktopHomePage>
Text(
translate("desk_tip"),
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: 12,
color: MyTheme.color(context).lighterText,
height: 1.25),
style: Theme.of(context).textTheme.bodySmall,
)
],
),
);
}
Widget buildHelpCards() {
if (Platform.isWindows) {
if (!bind.mainIsInstalled()) {
return buildInstallCard(
"", "install_tip", "Install", bind.mainGotoInstall);
} else if (bind.mainIsInstalledLowerVersion()) {
return buildInstallCard("Status", "Your installation is lower version.",
"Click to upgrade", bind.mainUpdateMe);
}
}
if (updateUrl.isNotEmpty) {
return buildInstallCard(
"Status",
"There is a newer version of ${bind.mainGetAppNameSync()} ${bind.mainGetNewVersion()} available.",
"Click to download", () async {
final Uri url = Uri.parse('https://rustdesk.com');
await launchUrl(url);
});
}
if (Platform.isMacOS) {}
if (bind.mainIsInstalledLowerVersion()) {}
return Container();
}
Widget buildInstallCard(String title, String content, String btnText,
GestureTapCallback onPressed) {
return Container(
margin: EdgeInsets.only(top: 20),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color.fromARGB(255, 226, 66, 188),
Color.fromARGB(255, 244, 114, 124),
],
)),
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: (title.isNotEmpty
? <Widget>[
Center(
child: Text(
translate(title),
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 15),
).marginOnly(bottom: 6)),
]
: <Widget>[]) +
<Widget>[
Text(
translate(content),
style: TextStyle(
height: 1.5,
color: Colors.white,
fontWeight: FontWeight.normal,
fontSize: 13),
).marginOnly(bottom: 20),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Button(
padding: 8,
isOutline: true,
text: translate(btnText),
textColor: Colors.white,
borderColor: Colors.white,
textSize: 20,
radius: 10,
onTap: onPressed,
)
]),
],
)),
);
}
@override
void onTrayMenuItemClick(MenuItem menuItem) {
debugPrint('click ${menuItem.key}');
@@ -305,6 +397,10 @@ class _DesktopHomePageState extends State<DesktopHomePage>
@override
void initState() {
super.initState();
Timer(const Duration(seconds: 5), () async {
updateUrl = await bind.mainGetSoftwareUpdateUrl();
if (updateUrl.isNotEmpty) setState(() {});
});
trayManager.addListener(this);
windowManager.addListener(this);
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
@@ -331,7 +427,7 @@ Future<bool> 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 +445,7 @@ Future<bool> loginDialog() async {
});
}
userName = userContontroller.text;
userName = userController.text;
pass = pwdController.text;
if (userName.isEmpty) {
userNameMsg = translate("Username missed");
@@ -385,6 +481,7 @@ Future<bool> loginDialog() async {
close();
}
// 登录dialog
return CustomAlertDialog(
title: Text(translate("Login")),
content: ConstrainedBox(
@@ -411,7 +508,7 @@ Future<bool> loginDialog() async {
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: userNameMsg.isNotEmpty ? userNameMsg : null),
controller: userContontroller,
controller: userController,
focusNode: FocusNode()..requestFocus(),
),
),

View File

@@ -5,7 +5,9 @@ import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/desktop/pages/desktop_home_page.dart';
import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
import 'package:flutter_hbb/models/platform_model.dart';
import 'package:flutter_hbb/models/server_model.dart';
import 'package:get/get.dart';
@@ -18,7 +20,7 @@ import '../../common/widgets/dialog.dart';
const double _kTabWidth = 235;
const double _kTabHeight = 42;
const double _kCardFixedWidth = 560;
const double _kCardFixedWidth = 540;
const double _kCardLeftMargin = 15;
const double _kContentHMargin = 15;
const double _kContentHSubMargin = _kContentHMargin + 33;
@@ -28,6 +30,8 @@ const double _kListViewBottomMargin = 15;
const double _kTitleFontSize = 20;
const double _kContentFontSize = 15;
const Color _accentColor = MyTheme.accent;
const String _kSettingPageControllerTag = "settingPageController";
const String _kSettingPageIndexTag = "settingPageIndex";
class _TabInfo {
late final String label;
@@ -37,10 +41,30 @@ class _TabInfo {
}
class DesktopSettingPage extends StatefulWidget {
const DesktopSettingPage({Key? key}) : super(key: key);
final int initialPage;
const DesktopSettingPage({Key? key, required this.initialPage})
: super(key: key);
@override
State<DesktopSettingPage> createState() => _DesktopSettingPageState();
static void switch2page(int page) {
if (page >= 5) return;
try {
if (Get.isRegistered<PageController>(tag: _kSettingPageControllerTag)) {
DesktopTabPage.onAddSetting(initialPage: page);
PageController controller = Get.find(tag: _kSettingPageControllerTag);
RxInt selectedIndex = Get.find(tag: _kSettingPageIndexTag);
selectedIndex.value = page;
controller.jumpToPage(page);
} else {
DesktopTabPage.onAddSetting(initialPage: page);
}
} catch (e) {
debugPrint('$e');
}
}
}
class _DesktopSettingPageState extends State<DesktopSettingPage>
@@ -50,12 +74,12 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
_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)
];
late PageController controller;
RxInt selectedIndex = 0.obs;
late RxInt selectedIndex;
@override
bool get wantKeepAlive => true;
@@ -63,14 +87,24 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
@override
void initState() {
super.initState();
controller = PageController();
selectedIndex = (widget.initialPage < 5 ? widget.initialPage : 0).obs;
Get.put<RxInt>(selectedIndex, tag: _kSettingPageIndexTag);
controller = PageController(initialPage: widget.initialPage);
Get.put<PageController>(controller, tag: _kSettingPageControllerTag);
}
@override
void dispose() {
super.dispose();
Get.delete<PageController>(tag: _kSettingPageControllerTag);
Get.delete<RxInt>(tag: _kSettingPageIndexTag);
}
@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
backgroundColor: MyTheme.color(context).bg,
backgroundColor: Theme.of(context).backgroundColor,
body: Row(
children: <Widget>[
SizedBox(
@@ -85,7 +119,7 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
const VerticalDivider(thickness: 1, width: 1),
Expanded(
child: Container(
color: MyTheme.color(context).grayBg,
color: Theme.of(context).scaffoldBackgroundColor,
child: DesktopScrollWrapper(
scrollController: controller,
child: PageView(
@@ -94,7 +128,7 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
_General(),
_Safety(),
_Network(),
_Acount(),
_Account(),
_About(),
],
)),
@@ -387,7 +421,7 @@ class _Safety extends StatefulWidget {
class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
bool locked = true;
bool locked = bind.mainIsInstalled();
final scrollController = ScrollController();
@override
@@ -533,7 +567,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
_OptionCheckBox(context, 'Deny remote access', 'stop-service',
checkedIcon: const Icon(
Icons.warning_amber_rounded,
color: Color.fromARGB(255, 255, 204, 0),
color: kColorWarn,
),
enabled: enabled),
Offstage(
@@ -541,6 +575,8 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
child: _OptionCheckBox(context, 'Enable RDP', 'enable-rdp',
enabled: enabled),
),
_OptionCheckBox(context, 'Deny LAN Discovery', 'enable-lan-discovery',
reverse: true, enabled: enabled),
...directIp(context),
whitelist(),
]);
@@ -700,14 +736,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();
@@ -717,12 +753,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) {
@@ -730,12 +766,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()
});
});
}
@@ -859,7 +897,9 @@ Widget _Card({required String title, required List<Widget> children}) {
}
Color? _disabledTextColor(BuildContext context, bool enabled) {
return enabled ? null : MyTheme.color(context).lighterText;
return enabled
? null
: Theme.of(context).textTheme.titleLarge?.color?.withOpacity(0.6);
}
// ignore: non_constant_identifier_names
@@ -1339,91 +1379,6 @@ void changeServer() async {
});
}
void changeWhiteList({Function()? callback}) async {
Map<String, dynamic> oldOptions = jsonDecode(await bind.mainGetOptions());
var newWhiteList = ((oldOptions['whitelist'] ?? "") as String).split(',');
var newWhiteListField = newWhiteList.join('\n');
var controller = TextEditingController(text: newWhiteListField);
var msg = "";
var isInProgress = false;
gFFI.dialogManager.show((setState, close) {
return CustomAlertDialog(
title: Text(translate("IP Whitelisting")),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("whitelist_sep")),
const SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: TextField(
maxLines: null,
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg),
),
controller: controller,
focusNode: FocusNode()..requestFocus()),
),
],
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(
onPressed: () async {
await bind.mainSetOption(key: 'whitelist', value: '');
callback?.call();
close();
},
child: Text(translate("Clear"))),
TextButton(
onPressed: () async {
setState(() {
msg = "";
isInProgress = true;
});
newWhiteListField = controller.text.trim();
var newWhiteList = "";
if (newWhiteListField.isEmpty) {
// pass
} else {
final ips =
newWhiteListField.trim().split(RegExp(r"[\s,;\n]+"));
// test ip
final ipMatch = RegExp(r"^\d+\.\d+\.\d+\.\d+$");
for (final ip in ips) {
if (!ipMatch.hasMatch(ip)) {
msg = "${translate("Invalid IP")} $ip";
setState(() {
isInProgress = false;
});
return;
}
}
newWhiteList = ips.join(',');
}
oldOptions['whitelist'] = newWhiteList;
await bind.mainSetOptions(json: jsonEncode(oldOptions));
callback?.call();
close();
},
child: Text(translate("OK"))),
],
onCancel: close,
);
});
}
void changeSocks5Proxy() async {
var socks = await bind.mainGetSocks();

View File

@@ -14,6 +14,23 @@ class DesktopTabPage extends StatefulWidget {
@override
State<DesktopTabPage> createState() => _DesktopTabPageState();
static void onAddSetting({int initialPage = 0}) {
try {
DesktopTabController tabController = Get.find();
tabController.add(TabInfo(
key: kTabLabelSettingPage,
label: kTabLabelSettingPage,
selectedIcon: Icons.build_sharp,
unselectedIcon: Icons.build_outlined,
page: DesktopSettingPage(
key: const ValueKey(kTabLabelSettingPage),
initialPage: initialPage,
)));
} catch (e) {
debugPrint('$e');
}
}
}
class _DesktopTabPageState extends State<DesktopTabPage> {
@@ -22,6 +39,7 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
@override
void initState() {
super.initState();
Get.put<DesktopTabController>(tabController);
tabController.add(TabInfo(
key: kTabLabelHomePage,
label: kTabLabelHomePage,
@@ -33,6 +51,12 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
)));
}
@override
void dispose() {
super.dispose();
Get.delete<DesktopTabController>();
}
@override
Widget build(BuildContext context) {
RxBool fullscreen = false.obs;
@@ -42,13 +66,13 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
OverlayEntry(builder: (context) {
gFFI.dialogManager.setOverlayState(Overlay.of(context));
return Scaffold(
backgroundColor: MyTheme.color(context).bg,
backgroundColor: Theme.of(context).backgroundColor,
body: DesktopTab(
controller: tabController,
tail: ActionIcon(
message: 'Settings',
icon: IconFont.menu,
onTap: onAddSetting,
onTap: DesktopTabPage.onAddSetting,
isClose: false,
),
));
@@ -62,13 +86,4 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
fullscreen.value ? kFullScreenEdgeSize : kWindowEdgeSize,
child: tabWidget));
}
void onAddSetting() {
tabController.add(TabInfo(
key: kTabLabelSettingPage,
label: kTabLabelSettingPage,
selectedIcon: Icons.build_sharp,
unselectedIcon: Icons.build_outlined,
page: DesktopSettingPage(key: const ValueKey(kTabLabelSettingPage))));
}
}

View File

@@ -104,7 +104,7 @@ class _FileManagerPageState extends State<FileManagerPage>
return false;
},
child: Scaffold(
backgroundColor: MyTheme.color(context).bg,
backgroundColor: Theme.of(context).backgroundColor,
body: Row(
children: [
Flexible(flex: 3, child: body(isLocal: true)),

View File

@@ -72,7 +72,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
decoration: BoxDecoration(
border: Border.all(color: MyTheme.color(context).border!)),
child: Scaffold(
backgroundColor: MyTheme.color(context).bg,
backgroundColor: Theme.of(context).backgroundColor,
body: DesktopTab(
controller: tabController,
onWindowCloseButton: handleWindowCloseButton,

View File

@@ -70,7 +70,7 @@ class _PortForwardPageState extends State<PortForwardPage>
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
backgroundColor: MyTheme.color(context).grayBg,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: FutureBuilder(future: () async {
if (!widget.isRDP) {
refreshTunnelConfig();
@@ -80,7 +80,8 @@ class _PortForwardPageState extends State<PortForwardPage>
return Container(
decoration: BoxDecoration(
border: Border.all(
width: 20, color: MyTheme.color(context).grayBg!)),
width: 20,
color: Theme.of(context).scaffoldBackgroundColor)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
@@ -88,7 +89,7 @@ class _PortForwardPageState extends State<PortForwardPage>
Flexible(
child: Container(
decoration: BoxDecoration(
color: MyTheme.color(context).bg,
color: Theme.of(context).backgroundColor,
border: Border.all(width: 1, color: MyTheme.border)),
child:
widget.isRDP ? buildRdp(context) : buildTunnel(context),
@@ -131,7 +132,7 @@ class _PortForwardPageState extends State<PortForwardPage>
return Theme(
data: Theme.of(context)
.copyWith(backgroundColor: MyTheme.color(context).bg),
.copyWith(backgroundColor: Theme.of(context).backgroundColor),
child: Obx(() => ListView.builder(
controller: ScrollController(),
itemCount: pfs.length + 2,
@@ -139,7 +140,7 @@ class _PortForwardPageState extends State<PortForwardPage>
if (index == 0) {
return Container(
height: 25,
color: MyTheme.color(context).grayBg,
color: Theme.of(context).scaffoldBackgroundColor,
child: Row(children: [
text('Local Port'),
const SizedBox(width: _kColumn1Width),
@@ -166,7 +167,7 @@ class _PortForwardPageState extends State<PortForwardPage>
return Container(
height: _kRowHeight,
decoration: BoxDecoration(color: MyTheme.color(context).bg),
decoration: BoxDecoration(color: Theme.of(context).backgroundColor),
child: Row(children: [
buildTunnelInputCell(context,
controller: localPortController,
@@ -216,11 +217,12 @@ class _PortForwardPageState extends State<PortForwardPage>
{required TextEditingController controller,
List<TextInputFormatter>? inputFormatters,
String? hint}) {
final textColor = Theme.of(context).textTheme.titleLarge?.color;
return Expanded(
child: TextField(
controller: controller,
inputFormatters: inputFormatters,
cursorColor: MyTheme.color(context).text,
cursorColor: textColor,
cursorHeight: 20,
cursorWidth: 1,
decoration: InputDecoration(
@@ -228,12 +230,12 @@ class _PortForwardPageState extends State<PortForwardPage>
borderSide: BorderSide(color: MyTheme.color(context).border!)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: MyTheme.color(context).border!)),
fillColor: MyTheme.color(context).bg,
fillColor: Theme.of(context).backgroundColor,
contentPadding: const EdgeInsets.all(10),
hintText: hint,
hintStyle: TextStyle(
color: MyTheme.color(context).placeholder, fontSize: 16)),
style: TextStyle(color: MyTheme.color(context).text, fontSize: 16),
hintStyle:
TextStyle(color: Theme.of(context).hintColor, fontSize: 16)),
style: TextStyle(color: textColor, fontSize: 16),
).marginAll(10),
);
}
@@ -250,7 +252,7 @@ class _PortForwardPageState extends State<PortForwardPage>
? MyTheme.currentThemeMode() == ThemeMode.dark
? const Color(0xFF202020)
: const Color(0xFFF4F5F6)
: MyTheme.color(context).bg),
: Theme.of(context).backgroundColor),
child: Row(children: [
text(pf.localPort.toString()),
const SizedBox(width: _kColumn1Width),
@@ -292,7 +294,7 @@ class _PortForwardPageState extends State<PortForwardPage>
).marginOnly(left: _kTextLeftMargin));
return Theme(
data: Theme.of(context)
.copyWith(backgroundColor: MyTheme.color(context).bg),
.copyWith(backgroundColor: Theme.of(context).backgroundColor),
child: ListView.builder(
controller: ScrollController(),
itemCount: 2,
@@ -300,7 +302,7 @@ class _PortForwardPageState extends State<PortForwardPage>
if (index == 0) {
return Container(
height: 25,
color: MyTheme.color(context).grayBg,
color: Theme.of(context).scaffoldBackgroundColor,
child: Row(children: [
text1('Local Port'),
const SizedBox(width: _kColumn1Width),
@@ -311,7 +313,8 @@ class _PortForwardPageState extends State<PortForwardPage>
} else {
return Container(
height: _kRowHeight,
decoration: BoxDecoration(color: MyTheme.color(context).bg),
decoration:
BoxDecoration(color: Theme.of(context).backgroundColor),
child: Row(children: [
Expanded(
child: Align(

View File

@@ -80,7 +80,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
decoration: BoxDecoration(
border: Border.all(color: MyTheme.color(context).border!)),
child: Scaffold(
backgroundColor: MyTheme.color(context).bg,
backgroundColor: Theme.of(context).backgroundColor,
body: DesktopTab(
controller: tabController,
onWindowCloseButton: () async {

View File

@@ -11,7 +11,6 @@ import 'package:provider/provider.dart';
import 'package:wakelock/wakelock.dart';
import 'package:flutter_custom_cursor/flutter_custom_cursor.dart';
import '../../consts.dart';
import '../widgets/remote_menubar.dart';
import '../../common.dart';
import '../../mobile/widgets/dialog.dart';
@@ -45,7 +44,6 @@ class _RemotePageState extends State<RemotePage>
late RxBool _keyboardEnabled;
final FocusNode _rawKeyFocusNode = FocusNode();
var _isPhysicalMouse = false;
var _imageFocused = false;
Function(bool)? _onEnterOrLeaveImage4Menubar;
@@ -139,7 +137,7 @@ class _RemotePageState extends State<RemotePage>
Widget buildBody(BuildContext context) {
return Scaffold(
backgroundColor: MyTheme.color(context).bg,
backgroundColor: Theme.of(context).backgroundColor,
body: Overlay(
initialEntries: [
OverlayEntry(builder: (context) {
@@ -445,6 +443,7 @@ class ImagePainter extends CustomPainter {
}
class QualityMonitor extends StatelessWidget {
static const textStyle = TextStyle(color: MyTheme.grayBg);
final QualityMonitorModel qualityMonitorModel;
QualityMonitor(this.qualityMonitorModel);
@@ -464,23 +463,23 @@ class QualityMonitor extends StatelessWidget {
children: [
Text(
"Speed: ${qualityMonitorModel.data.speed ?? ''}",
style: const TextStyle(color: MyTheme.grayBg),
style: textStyle,
),
Text(
"FPS: ${qualityMonitorModel.data.fps ?? ''}",
style: const TextStyle(color: MyTheme.grayBg),
style: textStyle,
),
Text(
"Delay: ${qualityMonitorModel.data.delay ?? ''} ms",
style: const TextStyle(color: MyTheme.grayBg),
style: textStyle,
),
Text(
"Target Bitrate: ${qualityMonitorModel.data.targetBitrate ?? ''}kb",
style: const TextStyle(color: MyTheme.grayBg),
style: textStyle,
),
Text(
"Codec: ${qualityMonitorModel.data.codecFormat ?? ''}",
style: const TextStyle(color: MyTheme.grayBg),
style: textStyle,
),
],
),

View File

@@ -91,7 +91,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
decoration: BoxDecoration(
border: Border.all(color: MyTheme.color(context).border!)),
child: Scaffold(
backgroundColor: MyTheme.color(context).bg,
backgroundColor: Theme.of(context).backgroundColor,
body: DesktopTab(
controller: tabController,
showTabBar: fullscreen.isFalse,

View File

@@ -69,7 +69,7 @@ class _DesktopServerPageState extends State<DesktopServerPage>
OverlayEntry(builder: (context) {
gFFI.dialogManager.setOverlayState(Overlay.of(context));
return Scaffold(
backgroundColor: MyTheme.color(context).bg,
backgroundColor: Theme.of(context).backgroundColor,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
@@ -145,7 +145,7 @@ class ConnectionManagerState extends State<ConnectionManager> {
windowManager.startDragging();
},
child: Container(
color: MyTheme.color(context).bg,
color: Theme.of(context).backgroundColor,
),
),
),
@@ -310,14 +310,15 @@ class _CmHeaderState extends State<_CmHeader>
],
),
),
Offstage(
offstage: client.isFileTransfer,
child: IconButton(
onPressed: () => checkClickTime(
client.id, () => gFFI.chatModel.toggleCMChatPage(client.id)),
icon: Icon(Icons.message_outlined),
),
)
Consumer<ServerModel>(
builder: (_, model, child) => Offstage(
offstage: !client.authorized || client.isFileTransfer,
child: IconButton(
onPressed: () => checkClickTime(client.id,
() => gFFI.chatModel.toggleCMChatPage(client.id)),
icon: Icon(Icons.message_outlined),
),
))
],
);
}