imporove setting page
This commit is contained in:
parent
752a94a5b5
commit
4377baf062
@ -10,6 +10,7 @@ import 'package:flutter_hbb/models/server_model.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_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart';
|
||||||
|
|
||||||
import '../../common/widgets/dialog.dart';
|
import '../../common/widgets/dialog.dart';
|
||||||
|
|
||||||
@ -44,7 +45,6 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
|||||||
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
||||||
final List<_TabInfo> settingTabs = <_TabInfo>[
|
final List<_TabInfo> settingTabs = <_TabInfo>[
|
||||||
_TabInfo('General', Icons.settings_outlined, Icons.settings),
|
_TabInfo('General', Icons.settings_outlined, Icons.settings),
|
||||||
_TabInfo('Language', Icons.language_outlined, Icons.language),
|
|
||||||
_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),
|
||||||
@ -84,17 +84,18 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
color: MyTheme.color(context).grayBg,
|
color: MyTheme.color(context).grayBg,
|
||||||
child: PageView(
|
child: DesktopScrollWrapper(
|
||||||
controller: controller,
|
scrollController: controller,
|
||||||
children: const [
|
child: PageView(
|
||||||
_General(),
|
controller: controller,
|
||||||
_Language(),
|
children: const [
|
||||||
_Safety(),
|
_General(),
|
||||||
_Network(),
|
_Safety(),
|
||||||
_Acount(),
|
_Network(),
|
||||||
_About(),
|
_Acount(),
|
||||||
],
|
_About(),
|
||||||
),
|
],
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -123,14 +124,18 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _listView({required List<_TabInfo> tabs}) {
|
Widget _listView({required List<_TabInfo> tabs}) {
|
||||||
return ListView(
|
final scrollController = ScrollController();
|
||||||
controller: ScrollController(),
|
return DesktopScrollWrapper(
|
||||||
children: tabs
|
scrollController: scrollController,
|
||||||
.asMap()
|
child: ListView(
|
||||||
.entries
|
physics: NeverScrollableScrollPhysics(),
|
||||||
.map((tab) => _listItem(tab: tab.value, index: tab.key))
|
controller: scrollController,
|
||||||
.toList(),
|
children: tabs
|
||||||
);
|
.asMap()
|
||||||
|
.entries
|
||||||
|
.map((tab) => _listItem(tab: tab.value, index: tab.key))
|
||||||
|
.toList(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _listItem({required _TabInfo tab, required int index}) {
|
Widget _listItem({required _TabInfo tab, required int index}) {
|
||||||
@ -183,15 +188,20 @@ class _General extends StatefulWidget {
|
|||||||
class _GeneralState extends State<_General> {
|
class _GeneralState extends State<_General> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView(
|
final scrollController = ScrollController();
|
||||||
controller: ScrollController(),
|
return DesktopScrollWrapper(
|
||||||
children: [
|
scrollController: scrollController,
|
||||||
theme(),
|
child: ListView(
|
||||||
abr(),
|
physics: NeverScrollableScrollPhysics(),
|
||||||
hwcodec(),
|
controller: scrollController,
|
||||||
audio(context),
|
children: [
|
||||||
],
|
theme(),
|
||||||
).marginOnly(bottom: _kListViewBottomMargin);
|
abr(),
|
||||||
|
hwcodec(),
|
||||||
|
audio(context),
|
||||||
|
_Card(title: 'Language', children: [language()]),
|
||||||
|
],
|
||||||
|
).marginOnly(bottom: _kListViewBottomMargin));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget theme() {
|
Widget theme() {
|
||||||
@ -273,30 +283,6 @@ class _GeneralState extends State<_General> {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class _Language extends StatefulWidget {
|
|
||||||
const _Language({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<_Language> createState() => _LanguageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LanguageState extends State<_Language>
|
|
||||||
with AutomaticKeepAliveClientMixin {
|
|
||||||
@override
|
|
||||||
bool get wantKeepAlive => true;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
super.build(context);
|
|
||||||
return ListView(
|
|
||||||
controller: ScrollController(),
|
|
||||||
children: [
|
|
||||||
_Card(title: 'Language', children: [language()]),
|
|
||||||
],
|
|
||||||
).marginOnly(bottom: _kListViewBottomMargin);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget language() {
|
Widget language() {
|
||||||
return _futureBuilder(future: () async {
|
return _futureBuilder(future: () async {
|
||||||
@ -340,31 +326,37 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
@override
|
@override
|
||||||
bool get wantKeepAlive => true;
|
bool get wantKeepAlive => true;
|
||||||
bool locked = true;
|
bool locked = true;
|
||||||
|
final scrollController = ScrollController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
return ListView(
|
return DesktopScrollWrapper(
|
||||||
controller: ScrollController(),
|
scrollController: scrollController,
|
||||||
children: [
|
child: SingleChildScrollView(
|
||||||
Column(
|
physics: NeverScrollableScrollPhysics(),
|
||||||
children: [
|
controller: scrollController,
|
||||||
_lock(locked, 'Unlock Security Settings', () {
|
child: Column(
|
||||||
locked = false;
|
children: [
|
||||||
setState(() => {});
|
_lock(locked, 'Unlock Security Settings', () {
|
||||||
}),
|
locked = false;
|
||||||
AbsorbPointer(
|
setState(() => {});
|
||||||
absorbing: locked,
|
}),
|
||||||
child: Column(children: [
|
AbsorbPointer(
|
||||||
permissions(context),
|
absorbing: locked,
|
||||||
password(context),
|
child: Column(children: [
|
||||||
connection(context),
|
permissions(context),
|
||||||
]),
|
password(context),
|
||||||
),
|
_Card(title: 'ID', children: [changeId()]),
|
||||||
],
|
connection(context),
|
||||||
)
|
]),
|
||||||
],
|
),
|
||||||
).marginOnly(bottom: _kListViewBottomMargin);
|
],
|
||||||
|
)).marginOnly(bottom: _kListViewBottomMargin));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget changeId() {
|
||||||
|
return _Button('Change ID', changeIdDialog, enabled: !locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget permissions(context) {
|
Widget permissions(context) {
|
||||||
@ -378,6 +370,8 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
enabled: enabled),
|
enabled: enabled),
|
||||||
_OptionCheckBox(context, 'Enable Audio', 'enable-audio',
|
_OptionCheckBox(context, 'Enable Audio', 'enable-audio',
|
||||||
enabled: enabled),
|
enabled: enabled),
|
||||||
|
_OptionCheckBox(context, 'Enable TCP Tunneling', 'enable-tunnel',
|
||||||
|
enabled: enabled),
|
||||||
_OptionCheckBox(context, 'Enable Remote Restart', 'enable-remote-restart',
|
_OptionCheckBox(context, 'Enable Remote Restart', 'enable-remote-restart',
|
||||||
enabled: enabled),
|
enabled: enabled),
|
||||||
_OptionCheckBox(context, 'Enable remote configuration modification',
|
_OptionCheckBox(context, 'Enable remote configuration modification',
|
||||||
@ -470,15 +464,13 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
|
|
||||||
Widget connection(BuildContext context) {
|
Widget connection(BuildContext context) {
|
||||||
bool enabled = !locked;
|
bool enabled = !locked;
|
||||||
return _Card(title: 'Connection', children: [
|
return _Card(title: 'Security', children: [
|
||||||
_OptionCheckBox(context, 'Deny remote access', 'stop-service',
|
_OptionCheckBox(context, 'Deny remote access', 'stop-service',
|
||||||
checkedIcon: const Icon(
|
checkedIcon: const Icon(
|
||||||
Icons.warning,
|
Icons.warning,
|
||||||
color: Colors.yellowAccent,
|
color: Colors.yellowAccent,
|
||||||
),
|
),
|
||||||
enabled: enabled),
|
enabled: enabled),
|
||||||
_OptionCheckBox(context, 'Enable TCP Tunneling', 'enable-tunnel',
|
|
||||||
enabled: enabled),
|
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: !Platform.isWindows,
|
offstage: !Platform.isWindows,
|
||||||
child: _OptionCheckBox(context, 'Enable RDP', 'enable-rdp',
|
child: _OptionCheckBox(context, 'Enable RDP', 'enable-rdp',
|
||||||
@ -615,27 +607,30 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
bool enabled = !locked;
|
bool enabled = !locked;
|
||||||
return ListView(controller: ScrollController(), children: [
|
final scrollController = ScrollController();
|
||||||
Column(
|
return DesktopScrollWrapper(
|
||||||
children: [
|
scrollController: scrollController,
|
||||||
_lock(locked, 'Unlock Network Settings', () {
|
child: ListView(
|
||||||
locked = false;
|
controller: scrollController,
|
||||||
setState(() => {});
|
physics: NeverScrollableScrollPhysics(),
|
||||||
}),
|
children: [
|
||||||
AbsorbPointer(
|
_lock(locked, 'Unlock Network Settings', () {
|
||||||
absorbing: locked,
|
locked = false;
|
||||||
child: Column(children: [
|
setState(() => {});
|
||||||
_Card(title: 'Server', children: [
|
}),
|
||||||
_Button('ID/Relay Server', changeServer, enabled: enabled),
|
AbsorbPointer(
|
||||||
]),
|
absorbing: locked,
|
||||||
_Card(title: 'Proxy', children: [
|
child: Column(children: [
|
||||||
_Button('Socks5 Proxy', changeSocks5Proxy, enabled: enabled),
|
_Card(title: 'Server', children: [
|
||||||
]),
|
_Button('ID/Relay Server', changeServer, enabled: enabled),
|
||||||
]),
|
]),
|
||||||
),
|
_Card(title: 'Proxy', children: [
|
||||||
],
|
_Button('Socks5 Proxy', changeSocks5Proxy,
|
||||||
)
|
enabled: enabled),
|
||||||
]).marginOnly(bottom: _kListViewBottomMargin);
|
]),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]).marginOnly(bottom: _kListViewBottomMargin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,13 +644,16 @@ class _Acount extends StatefulWidget {
|
|||||||
class _AcountState extends State<_Acount> {
|
class _AcountState extends State<_Acount> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView(
|
final scrollController = ScrollController();
|
||||||
controller: ScrollController(),
|
return DesktopScrollWrapper(
|
||||||
children: [
|
scrollController: scrollController,
|
||||||
_Card(title: 'Acount', children: [login()]),
|
child: ListView(
|
||||||
_Card(title: 'ID', children: [changeId()]),
|
physics: NeverScrollableScrollPhysics(),
|
||||||
],
|
controller: scrollController,
|
||||||
).marginOnly(bottom: _kListViewBottomMargin);
|
children: [
|
||||||
|
_Card(title: 'Acount', children: [login()]),
|
||||||
|
],
|
||||||
|
).marginOnly(bottom: _kListViewBottomMargin));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget login() {
|
Widget login() {
|
||||||
@ -675,10 +673,6 @@ class _AcountState extends State<_Acount> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget changeId() {
|
|
||||||
return _Button('Change ID', changeIdDialog);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _About extends StatefulWidget {
|
class _About extends StatefulWidget {
|
||||||
@ -699,61 +693,66 @@ class _AboutState extends State<_About> {
|
|||||||
final license = data['license'].toString();
|
final license = data['license'].toString();
|
||||||
final version = data['version'].toString();
|
final version = data['version'].toString();
|
||||||
const linkStyle = TextStyle(decoration: TextDecoration.underline);
|
const linkStyle = TextStyle(decoration: TextDecoration.underline);
|
||||||
return ListView(controller: ScrollController(), children: [
|
final scrollController = ScrollController();
|
||||||
_Card(title: "About RustDesk", children: [
|
return DesktopScrollWrapper(
|
||||||
Column(
|
scrollController: scrollController,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: SingleChildScrollView(
|
||||||
children: [
|
controller: scrollController,
|
||||||
const SizedBox(
|
physics: NeverScrollableScrollPhysics(),
|
||||||
height: 8.0,
|
child: _Card(title: "About RustDesk", children: [
|
||||||
),
|
Column(
|
||||||
Text("Version: $version").marginSymmetric(vertical: 4.0),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
InkWell(
|
children: [
|
||||||
onTap: () {
|
const SizedBox(
|
||||||
launchUrlString("https://rustdesk.com/privacy");
|
height: 8.0,
|
||||||
},
|
),
|
||||||
child: const Text(
|
Text("Version: $version").marginSymmetric(vertical: 4.0),
|
||||||
"Privacy Statement",
|
InkWell(
|
||||||
style: linkStyle,
|
onTap: () {
|
||||||
).marginSymmetric(vertical: 4.0)),
|
launchUrlString("https://rustdesk.com/privacy");
|
||||||
InkWell(
|
},
|
||||||
onTap: () {
|
child: const Text(
|
||||||
launchUrlString("https://rustdesk.com");
|
"Privacy Statement",
|
||||||
},
|
style: linkStyle,
|
||||||
child: const Text(
|
).marginSymmetric(vertical: 4.0)),
|
||||||
"Website",
|
InkWell(
|
||||||
style: linkStyle,
|
onTap: () {
|
||||||
).marginSymmetric(vertical: 4.0)),
|
launchUrlString("https://rustdesk.com");
|
||||||
Container(
|
},
|
||||||
decoration: const BoxDecoration(color: Color(0xFF2c8cff)),
|
child: const Text(
|
||||||
padding:
|
"Website",
|
||||||
const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
|
style: linkStyle,
|
||||||
child: Row(
|
).marginSymmetric(vertical: 4.0)),
|
||||||
children: [
|
Container(
|
||||||
Expanded(
|
decoration: const BoxDecoration(color: Color(0xFF2c8cff)),
|
||||||
child: Column(
|
padding:
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
|
||||||
children: [
|
child: Row(
|
||||||
Text(
|
children: [
|
||||||
"Copyright © 2022 Purslane Ltd.\n$license",
|
Expanded(
|
||||||
style: const TextStyle(color: Colors.white),
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Copyright © 2022 Purslane Ltd.\n$license",
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"Made with heart in this chaotic world!",
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
color: Colors.white),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const Text(
|
),
|
||||||
"Made with heart in this chaotic world!",
|
],
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
color: Colors.white),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
).marginSymmetric(vertical: 4.0)
|
||||||
),
|
],
|
||||||
).marginSymmetric(vertical: 4.0)
|
).marginOnly(left: _kContentHMargin)
|
||||||
],
|
]),
|
||||||
).marginOnly(left: _kContentHMargin)
|
));
|
||||||
]),
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user