remove menu from desktop home page
This commit is contained in:
parent
0df6517adb
commit
e0d759c3bb
@ -1,29 +1,6 @@
|
|||||||
# This file configures the analyzer, which statically analyzes Dart code to
|
include: package:lints/recommended.yaml
|
||||||
# check for errors, warnings, and lints.
|
|
||||||
#
|
|
||||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
|
||||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
|
||||||
# invoked from the command line by running `flutter analyze`.
|
|
||||||
|
|
||||||
# The following line activates a set of recommended lints for Flutter apps,
|
|
||||||
# packages, and plugins designed to encourage good coding practices.
|
|
||||||
include: package:flutter_lints/flutter.yaml
|
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
# The lint rules applied to this project can be customized in the
|
|
||||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
|
||||||
# included above or to enable additional rules. A list of all available lints
|
|
||||||
# and their documentation is published at
|
|
||||||
# https://dart-lang.github.io/linter/lints/index.html.
|
|
||||||
#
|
|
||||||
# Instead of disabling a lint rule for the entire project in the
|
|
||||||
# section below, it can also be suppressed for a single line of code
|
|
||||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
|
||||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
|
||||||
# producing the lint.
|
|
||||||
rules:
|
rules:
|
||||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
non_constant_identifier_names: false
|
||||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
sort_child_properties_last: false
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
|
||||||
# https://dart.dev/guides/language/analysis-options
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// main window right pane
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
@ -5,29 +5,14 @@ import 'package:flutter/material.dart' hide MenuItem;
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
import 'package:flutter_hbb/desktop/pages/connection_page.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/widgets/popup_menu.dart';
|
|
||||||
import 'package:flutter_hbb/desktop/widgets/material_mod_popup_menu.dart'
|
|
||||||
as mod_menu;
|
|
||||||
import 'package:flutter_hbb/models/platform_model.dart';
|
import 'package:flutter_hbb/models/platform_model.dart';
|
||||||
import 'package:flutter_hbb/models/server_model.dart';
|
import 'package:flutter_hbb/models/server_model.dart';
|
||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:tray_manager/tray_manager.dart';
|
import 'package:tray_manager/tray_manager.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
import '../../common/widgets/dialog.dart';
|
|
||||||
|
|
||||||
class _MenubarTheme {
|
|
||||||
static const Color commonColor = MyTheme.accent;
|
|
||||||
// kMinInteractiveDimension
|
|
||||||
static const double height = 25.0;
|
|
||||||
static const double dividerHeight = 12.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DesktopHomePage extends StatefulWidget {
|
class DesktopHomePage extends StatefulWidget {
|
||||||
const DesktopHomePage({Key? key}) : super(key: key);
|
const DesktopHomePage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@ -66,19 +51,19 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
super.build(context);
|
super.build(context);
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
buildServerInfo(context),
|
buildLeftPane(context),
|
||||||
const VerticalDivider(
|
const VerticalDivider(
|
||||||
width: 1,
|
width: 1,
|
||||||
thickness: 1,
|
thickness: 1,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: buildServerBoard(context),
|
child: buildRightPane(context),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildServerInfo(BuildContext context) {
|
buildLeftPane(BuildContext context) {
|
||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
value: gFFI.serverModel,
|
value: gFFI.serverModel,
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -95,7 +80,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildServerBoard(BuildContext context) {
|
buildRightPane(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
color: MyTheme.color(context).grayBg,
|
color: MyTheme.color(context).grayBg,
|
||||||
child: ConnectionPage(),
|
child: ConnectionPage(),
|
||||||
@ -167,93 +152,9 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPopupMenu(BuildContext context) {
|
Widget buildPopupMenu(BuildContext context) {
|
||||||
var position;
|
|
||||||
RxBool hover = false.obs;
|
RxBool hover = false.obs;
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTapDown: (detail) {
|
onTap: () async {},
|
||||||
final x = detail.globalPosition.dx;
|
|
||||||
final y = detail.globalPosition.dy;
|
|
||||||
position = RelativeRect.fromLTRB(x, y, x, y);
|
|
||||||
},
|
|
||||||
onTap: () async {
|
|
||||||
final userName = await gFFI.userModel.getUserName();
|
|
||||||
final enabledInput = await bind.mainGetOption(key: 'enable-audio');
|
|
||||||
final defaultInput = await gFFI.getDefaultAudioInput();
|
|
||||||
var menu = <PopupMenuEntry>[
|
|
||||||
await genEnablePopupMenuItem(
|
|
||||||
translate("Enable Keyboard/Mouse"),
|
|
||||||
'enable-keyboard',
|
|
||||||
),
|
|
||||||
await genEnablePopupMenuItem(
|
|
||||||
translate("Enable Clipboard"),
|
|
||||||
'enable-clipboard',
|
|
||||||
),
|
|
||||||
await genEnablePopupMenuItem(
|
|
||||||
translate("Enable File Transfer"),
|
|
||||||
'enable-file-transfer',
|
|
||||||
),
|
|
||||||
await genEnablePopupMenuItem(
|
|
||||||
translate("Enable TCP Tunneling"),
|
|
||||||
'enable-tunnel',
|
|
||||||
),
|
|
||||||
genAudioInputPopupMenuItem(enabledInput != "N", defaultInput),
|
|
||||||
PopupMenuDivider(),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Text(translate("ID/Relay Server")),
|
|
||||||
value: 'custom-server',
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Text(translate("IP Whitelisting")),
|
|
||||||
value: 'whitelist',
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Text(translate("Socks5 Proxy")),
|
|
||||||
value: 'socks5-proxy',
|
|
||||||
),
|
|
||||||
PopupMenuDivider(),
|
|
||||||
await genEnablePopupMenuItem(
|
|
||||||
translate("Enable Service"),
|
|
||||||
'stop-service',
|
|
||||||
),
|
|
||||||
// TODO: direct server
|
|
||||||
await genEnablePopupMenuItem(
|
|
||||||
translate("Always connected via relay"),
|
|
||||||
'allow-always-relay',
|
|
||||||
),
|
|
||||||
await genEnablePopupMenuItem(
|
|
||||||
translate("Start ID/relay service"),
|
|
||||||
'stop-rendezvous-service',
|
|
||||||
),
|
|
||||||
PopupMenuDivider(),
|
|
||||||
userName.isEmpty
|
|
||||||
? PopupMenuItem(
|
|
||||||
child: Text(translate("Login")),
|
|
||||||
value: 'login',
|
|
||||||
)
|
|
||||||
: PopupMenuItem(
|
|
||||||
child: Text("${translate("Logout")} $userName"),
|
|
||||||
value: 'logout',
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Text(translate("Change ID")),
|
|
||||||
value: 'change-id',
|
|
||||||
),
|
|
||||||
PopupMenuDivider(),
|
|
||||||
await genEnablePopupMenuItem(
|
|
||||||
translate("Dark Theme"),
|
|
||||||
'allow-darktheme',
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Text(translate("About")),
|
|
||||||
value: 'about',
|
|
||||||
),
|
|
||||||
];
|
|
||||||
final v =
|
|
||||||
await showMenu(context: context, position: position, items: menu);
|
|
||||||
if (v != null) {
|
|
||||||
onSelectMenu(v);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => CircleAvatar(
|
() => CircleAvatar(
|
||||||
radius: 15,
|
radius: 15,
|
||||||
@ -276,6 +177,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
buildPasswordBoard(BuildContext context) {
|
buildPasswordBoard(BuildContext context) {
|
||||||
final model = gFFI.serverModel;
|
final model = gFFI.serverModel;
|
||||||
RxBool refreshHover = false.obs;
|
RxBool refreshHover = false.obs;
|
||||||
|
RxBool editHover = false.obs;
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.only(left: 20.0, right: 16, top: 13, bottom: 13),
|
margin: EdgeInsets.only(left: 20.0, right: 16, top: 13, bottom: 13),
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -334,7 +236,19 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
onTap: () => bind.mainUpdateTemporaryPassword(),
|
onTap: () => bind.mainUpdateTemporaryPassword(),
|
||||||
onHover: (value) => refreshHover.value = value,
|
onHover: (value) => refreshHover.value = value,
|
||||||
),
|
),
|
||||||
const _PasswordPopupMenu(),
|
InkWell(
|
||||||
|
child: Obx(
|
||||||
|
() => Icon(
|
||||||
|
Icons.edit,
|
||||||
|
color: editHover.value
|
||||||
|
? MyTheme.color(context).text
|
||||||
|
: Color(0xFFDDDDDD),
|
||||||
|
size: 22,
|
||||||
|
).marginOnly(right: 8, bottom: 2),
|
||||||
|
),
|
||||||
|
onTap: () => {},
|
||||||
|
onHover: (value) => editHover.value = value,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -408,236 +322,6 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
windowManager.removeListener(this);
|
windowManager.removeListener(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeTheme(String choice) async {
|
|
||||||
if (choice == "Y") {
|
|
||||||
Get.changeTheme(MyTheme.darkTheme);
|
|
||||||
} else {
|
|
||||||
Get.changeTheme(MyTheme.lightTheme);
|
|
||||||
}
|
|
||||||
Get.find<SharedPreferences>().setString("darkTheme", choice);
|
|
||||||
Get.forceAppUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void onSelectMenu(String key) async {
|
|
||||||
if (key.startsWith('enable-')) {
|
|
||||||
final option = await bind.mainGetOption(key: key);
|
|
||||||
bind.mainSetOption(key: key, value: option == "N" ? "" : "N");
|
|
||||||
} else if (key.startsWith('allow-')) {
|
|
||||||
final option = await bind.mainGetOption(key: key);
|
|
||||||
final choice = option == "Y" ? "" : "Y";
|
|
||||||
bind.mainSetOption(key: key, value: choice);
|
|
||||||
if (key == "allow-darktheme") changeTheme(choice);
|
|
||||||
} else if (key == "stop-service") {
|
|
||||||
final option = await bind.mainGetOption(key: key);
|
|
||||||
bind.mainSetOption(key: key, value: option == "Y" ? "" : "Y");
|
|
||||||
} else if (key == "change-id") {
|
|
||||||
changeIdDialog();
|
|
||||||
} else if (key == "custom-server") {
|
|
||||||
changeServer();
|
|
||||||
} else if (key == "whitelist") {
|
|
||||||
changeWhiteList();
|
|
||||||
} else if (key == "socks5-proxy") {
|
|
||||||
changeSocks5Proxy();
|
|
||||||
} else if (key == "about") {
|
|
||||||
about();
|
|
||||||
} else if (key == "logout") {
|
|
||||||
logOut();
|
|
||||||
} else if (key == "login") {
|
|
||||||
login();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<PopupMenuItem<String>> genEnablePopupMenuItem(
|
|
||||||
String label, String key) async {
|
|
||||||
final v = await bind.mainGetOption(key: key);
|
|
||||||
bool enable;
|
|
||||||
if (key == "stop-service") {
|
|
||||||
enable = v != "Y";
|
|
||||||
} else if (key.startsWith("allow-")) {
|
|
||||||
enable = v == "Y";
|
|
||||||
} else {
|
|
||||||
enable = v != "N";
|
|
||||||
}
|
|
||||||
|
|
||||||
return PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.check,
|
|
||||||
color: enable ? null : MyTheme.accent.withAlpha(00)),
|
|
||||||
Text(
|
|
||||||
label,
|
|
||||||
style: genTextStyle(enable),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
value: key,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextStyle genTextStyle(bool isPositive) {
|
|
||||||
return isPositive
|
|
||||||
? TextStyle()
|
|
||||||
: TextStyle(
|
|
||||||
color: Colors.redAccent, decoration: TextDecoration.lineThrough);
|
|
||||||
}
|
|
||||||
|
|
||||||
PopupMenuItem<String> genAudioInputPopupMenuItem(
|
|
||||||
bool enableInput, String defaultAudioInput) {
|
|
||||||
final defaultInput = defaultAudioInput.obs;
|
|
||||||
final enabled = enableInput.obs;
|
|
||||||
|
|
||||||
return PopupMenuItem(
|
|
||||||
child: FutureBuilder<List<String>>(
|
|
||||||
future: gFFI.getAudioInputs(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
final inputs = snapshot.data!.toList();
|
|
||||||
if (Platform.isWindows) {
|
|
||||||
inputs.insert(0, translate("System Sound"));
|
|
||||||
}
|
|
||||||
var inputList = inputs
|
|
||||||
.map((e) => PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Obx(() => Offstage(
|
|
||||||
offstage: defaultInput.value != e,
|
|
||||||
child: Icon(Icons.check))),
|
|
||||||
Expanded(
|
|
||||||
child: Tooltip(
|
|
||||||
message: e,
|
|
||||||
child: Text(
|
|
||||||
"$e",
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
value: e,
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
inputList.insert(
|
|
||||||
0,
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Obx(() => Offstage(
|
|
||||||
offstage: enabled.value, child: Icon(Icons.check))),
|
|
||||||
Expanded(child: Text(translate("Mute"))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
value: "Mute",
|
|
||||||
));
|
|
||||||
return PopupMenuButton<String>(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
child: Container(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(translate("Audio Input"))),
|
|
||||||
itemBuilder: (context) => inputList,
|
|
||||||
onSelected: (dev) async {
|
|
||||||
if (dev == "Mute") {
|
|
||||||
await bind.mainSetOption(
|
|
||||||
key: 'enable-audio', value: enabled.value ? '' : 'N');
|
|
||||||
enabled.value =
|
|
||||||
await bind.mainGetOption(key: 'enable-audio') != 'N';
|
|
||||||
} else if (dev != await gFFI.getDefaultAudioInput()) {
|
|
||||||
gFFI.setDefaultAudioInput(dev);
|
|
||||||
defaultInput.value = dev;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Text("...");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
value: 'audio-input',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void about() async {
|
|
||||||
final appName = await bind.mainGetAppName();
|
|
||||||
final license = await bind.mainGetLicense();
|
|
||||||
final version = await bind.mainGetVersion();
|
|
||||||
const linkStyle = TextStyle(decoration: TextDecoration.underline);
|
|
||||||
gFFI.dialogManager.show((setState, close) {
|
|
||||||
return CustomAlertDialog(
|
|
||||||
title: Text("About $appName"),
|
|
||||||
content: ConstrainedBox(
|
|
||||||
constraints: const BoxConstraints(minWidth: 500),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
height: 8.0,
|
|
||||||
),
|
|
||||||
Text("Version: $version").marginSymmetric(vertical: 4.0),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
launchUrlString("https://rustdesk.com/privacy");
|
|
||||||
},
|
|
||||||
child: const Text(
|
|
||||||
"Privacy Statement",
|
|
||||||
style: linkStyle,
|
|
||||||
).marginSymmetric(vertical: 4.0)),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
launchUrlString("https://rustdesk.com");
|
|
||||||
},
|
|
||||||
child: const Text(
|
|
||||||
"Website",
|
|
||||||
style: linkStyle,
|
|
||||||
).marginSymmetric(vertical: 4.0)),
|
|
||||||
Container(
|
|
||||||
decoration: const BoxDecoration(color: Color(0xFF2c8cff)),
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
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),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).marginSymmetric(vertical: 4.0)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(onPressed: close, child: Text(translate("OK"))),
|
|
||||||
],
|
|
||||||
onSubmit: close,
|
|
||||||
onCancel: close,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void login() {
|
|
||||||
loginDialog().then((success) {
|
|
||||||
if (success) {
|
|
||||||
// refresh frame
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void logOut() {
|
|
||||||
gFFI.userModel.logOut().then((_) => {setState(() {})});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// common login dialog for desktop
|
/// common login dialog for desktop
|
||||||
@ -874,120 +558,3 @@ void setPasswordDialog() async {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PasswordPopupMenu extends StatefulWidget {
|
|
||||||
const _PasswordPopupMenu({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<_PasswordPopupMenu> createState() => _PasswordPopupMenuState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PasswordPopupMenuState extends State<_PasswordPopupMenu> {
|
|
||||||
final RxBool _tempEnabled = true.obs;
|
|
||||||
final RxBool _permEnabled = true.obs;
|
|
||||||
|
|
||||||
List<MenuEntryBase<String>> _buildMenus() {
|
|
||||||
return <MenuEntryBase<String>>[
|
|
||||||
MenuEntryRadios<String>(
|
|
||||||
text: translate('Password type'),
|
|
||||||
optionsGetter: () => [
|
|
||||||
MenuEntryRadioOption(
|
|
||||||
text: translate('Use temporary password'),
|
|
||||||
value: kUseTemporaryPassword),
|
|
||||||
MenuEntryRadioOption(
|
|
||||||
text: translate('Use permanent password'),
|
|
||||||
value: kUsePermanentPassword),
|
|
||||||
MenuEntryRadioOption(
|
|
||||||
text: translate('Use both passwords'),
|
|
||||||
value: kUseBothPasswords),
|
|
||||||
],
|
|
||||||
curOptionGetter: () async {
|
|
||||||
return gFFI.serverModel.verificationMethod;
|
|
||||||
},
|
|
||||||
optionSetter: (String oldValue, String newValue) async {
|
|
||||||
await bind.mainSetOption(
|
|
||||||
key: "verification-method", value: newValue);
|
|
||||||
await gFFI.serverModel.updatePasswordModel();
|
|
||||||
setState(() {
|
|
||||||
_tempEnabled.value =
|
|
||||||
gFFI.serverModel.verificationMethod != kUsePermanentPassword;
|
|
||||||
_permEnabled.value =
|
|
||||||
gFFI.serverModel.verificationMethod != kUseTemporaryPassword;
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
MenuEntryDivider(),
|
|
||||||
MenuEntryButton<String>(
|
|
||||||
enabled: _permEnabled,
|
|
||||||
childBuilder: (TextStyle? style) => Text(
|
|
||||||
translate('Set permanent password'),
|
|
||||||
style: style,
|
|
||||||
),
|
|
||||||
proc: () {
|
|
||||||
setPasswordDialog();
|
|
||||||
},
|
|
||||||
dismissOnClicked: true,
|
|
||||||
),
|
|
||||||
MenuEntrySubMenu(
|
|
||||||
enabled: _tempEnabled,
|
|
||||||
text: translate('Set temporary password length'),
|
|
||||||
entries: [
|
|
||||||
MenuEntryRadios<String>(
|
|
||||||
enabled: _tempEnabled,
|
|
||||||
text: translate(''),
|
|
||||||
optionsGetter: () => [
|
|
||||||
MenuEntryRadioOption(
|
|
||||||
text: translate('6'),
|
|
||||||
value: '6',
|
|
||||||
enabled: _tempEnabled,
|
|
||||||
),
|
|
||||||
MenuEntryRadioOption(
|
|
||||||
text: translate('8'),
|
|
||||||
value: '8',
|
|
||||||
enabled: _tempEnabled,
|
|
||||||
),
|
|
||||||
MenuEntryRadioOption(
|
|
||||||
text: translate('10'),
|
|
||||||
value: '10',
|
|
||||||
enabled: _tempEnabled,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
curOptionGetter: () async {
|
|
||||||
return gFFI.serverModel.temporaryPasswordLength;
|
|
||||||
},
|
|
||||||
optionSetter: (String oldValue, String newValue) async {
|
|
||||||
if (oldValue != newValue) {
|
|
||||||
await gFFI.serverModel.setTemporaryPasswordLength(newValue);
|
|
||||||
await gFFI.serverModel.updatePasswordModel();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final editHover = false.obs;
|
|
||||||
return mod_menu.PopupMenuButton(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
onHover: (v) => editHover.value = v,
|
|
||||||
tooltip: translate(''),
|
|
||||||
position: mod_menu.PopupMenuPosition.overSide,
|
|
||||||
itemBuilder: (BuildContext context) => _buildMenus()
|
|
||||||
.map((entry) => entry.build(
|
|
||||||
context,
|
|
||||||
const MenuConfig(
|
|
||||||
commonColor: _MenubarTheme.commonColor,
|
|
||||||
height: _MenubarTheme.height,
|
|
||||||
dividerHeight: _MenubarTheme.dividerHeight,
|
|
||||||
)))
|
|
||||||
.expand((i) => i)
|
|
||||||
.toList(),
|
|
||||||
child: Obx(() => Icon(Icons.edit,
|
|
||||||
size: 22,
|
|
||||||
color: editHover.value
|
|
||||||
? MyTheme.color(context).text
|
|
||||||
: const Color(0xFFDDDDDD))
|
|
||||||
.marginOnly(bottom: 2)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -140,7 +140,7 @@ packages:
|
|||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.0"
|
||||||
charcode:
|
charcode:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -161,7 +161,7 @@ packages:
|
|||||||
name: clock
|
name: clock
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.0"
|
||||||
code_builder:
|
code_builder:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -367,6 +367,13 @@ packages:
|
|||||||
url: "https://github.com/Kingtous/rustdesk_flutter_custom_cursor"
|
url: "https://github.com/Kingtous/rustdesk_flutter_custom_cursor"
|
||||||
source: git
|
source: git
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
|
flutter_improved_scrolling:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_improved_scrolling
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.3"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -374,6 +381,11 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
|
flutter_localizations:
|
||||||
|
dependency: "direct main"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
flutter_parsed_text:
|
flutter_parsed_text:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -478,7 +490,7 @@ packages:
|
|||||||
name: icons_launcher
|
name: icons_launcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.5"
|
version: "2.0.4"
|
||||||
image:
|
image:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -576,7 +588,7 @@ packages:
|
|||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.5"
|
version: "0.1.4"
|
||||||
menu_base:
|
menu_base:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -590,7 +602,7 @@ packages:
|
|||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.7.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -667,7 +679,7 @@ packages:
|
|||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.2"
|
version: "1.8.1"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
// This is a basic Flutter widget test.
|
|
||||||
//
|
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
|
||||||
// utility that Flutter provides. For example, you can send tap and scroll
|
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
|
|
||||||
import 'package:flutter_hbb/main.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
|
||||||
// Build our app and trigger a frame.
|
|
||||||
await tester.pumpWidget(App());
|
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
|
||||||
expect(find.text('0'), findsOneWidget);
|
|
||||||
expect(find.text('1'), findsNothing);
|
|
||||||
|
|
||||||
// Tap the '+' icon and trigger a frame.
|
|
||||||
await tester.tap(find.byIcon(Icons.add));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
// Verify that our counter has incremented.
|
|
||||||
expect(find.text('0'), findsNothing);
|
|
||||||
expect(find.text('1'), findsOneWidget);
|
|
||||||
});
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user