Merge branch 'master' into video_queue
This commit is contained in:
commit
bbaecb6b7f
7
.github/workflows/flutter-nightly.yml
vendored
7
.github/workflows/flutter-nightly.yml
vendored
@ -44,7 +44,7 @@ jobs:
|
|||||||
# - { target: i686-pc-windows-msvc , os: windows-2019 }
|
# - { target: i686-pc-windows-msvc , os: windows-2019 }
|
||||||
# - { target: x86_64-pc-windows-gnu , os: windows-2019 }
|
# - { target: x86_64-pc-windows-gnu , os: windows-2019 }
|
||||||
- { target: x86_64-pc-windows-msvc, os: windows-2019 }
|
- { target: x86_64-pc-windows-msvc, os: windows-2019 }
|
||||||
# - { target: aarch64-pc-windows-msvc, os: windows-2019 }
|
# - { target: aarch64-pc-windows-msvc, os: windows-2019, arch: aarch64 }
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@ -264,11 +264,6 @@ jobs:
|
|||||||
os: macos-latest,
|
os: macos-latest,
|
||||||
extra-build-args: "",
|
extra-build-args: "",
|
||||||
}
|
}
|
||||||
- {
|
|
||||||
target: aarch64-apple-darwin,
|
|
||||||
os: macos-latest,
|
|
||||||
extra-build-args: "",
|
|
||||||
}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
1022
Cargo.lock
generated
1022
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
19
Cargo.toml
@ -57,19 +57,18 @@ rpassword = "7.0"
|
|||||||
base64 = "0.21"
|
base64 = "0.21"
|
||||||
num_cpus = "1.13"
|
num_cpus = "1.13"
|
||||||
bytes = { version = "1.2", features = ["serde"] }
|
bytes = { version = "1.2", features = ["serde"] }
|
||||||
default-net = "0.12.0"
|
default-net = "0.14"
|
||||||
wol-rs = "1.0"
|
wol-rs = "1.0"
|
||||||
flutter_rust_bridge = { version = "1.61.1", optional = true }
|
flutter_rust_bridge = { version = "1.61.1", optional = true }
|
||||||
errno = "0.3"
|
errno = "0.3"
|
||||||
rdev = { git = "https://github.com/fufesou/rdev" }
|
rdev = { git = "https://github.com/fufesou/rdev" }
|
||||||
url = { version = "2.1", features = ["serde"] }
|
url = { version = "2.1", features = ["serde"] }
|
||||||
dlopen = "0.1"
|
dlopen = "0.1"
|
||||||
hex = "0.4.3"
|
|
||||||
crossbeam-queue = "0.3"
|
crossbeam-queue = "0.3"
|
||||||
|
hex = "0.4"
|
||||||
reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false }
|
reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false }
|
||||||
chrono = "0.4.23"
|
chrono = "0.4"
|
||||||
cidr-utils = "0.5.9"
|
cidr-utils = "0.5"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies]
|
||||||
cpal = "0.14"
|
cpal = "0.14"
|
||||||
@ -95,8 +94,8 @@ winreg = "0.10"
|
|||||||
windows-service = "0.4"
|
windows-service = "0.4"
|
||||||
virtual_display = { path = "libs/virtual_display" }
|
virtual_display = { path = "libs/virtual_display" }
|
||||||
impersonate_system = { git = "https://github.com/21pages/impersonate-system" }
|
impersonate_system = { git = "https://github.com/21pages/impersonate-system" }
|
||||||
shared_memory = "0.12.4"
|
shared_memory = "0.12"
|
||||||
shutdown_hooks = "0.1.0"
|
shutdown_hooks = "0.1"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
objc = "0.2"
|
objc = "0.2"
|
||||||
@ -104,10 +103,10 @@ cocoa = "0.24"
|
|||||||
dispatch = "0.2"
|
dispatch = "0.2"
|
||||||
core-foundation = "0.9"
|
core-foundation = "0.9"
|
||||||
core-graphics = "0.22"
|
core-graphics = "0.22"
|
||||||
include_dir = "0.7.2"
|
include_dir = "0.7"
|
||||||
dark-light = "1.0"
|
dark-light = "1.0"
|
||||||
fruitbasket = "0.10.0"
|
fruitbasket = "0.10"
|
||||||
objc_id = "0.1.1"
|
objc_id = "0.1"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies]
|
[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies]
|
||||||
tray-icon = "0.4"
|
tray-icon = "0.4"
|
||||||
|
@ -186,6 +186,71 @@ class MyTheme {
|
|||||||
static const Color button = Color(0xFF2C8CFF);
|
static const Color button = Color(0xFF2C8CFF);
|
||||||
static const Color hoverBorder = Color(0xFF999999);
|
static const Color hoverBorder = Color(0xFF999999);
|
||||||
|
|
||||||
|
// ListTile
|
||||||
|
static const ListTileThemeData listTileTheme = ListTileThemeData(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Checkbox
|
||||||
|
static const CheckboxThemeData checkboxTheme = CheckboxThemeData(
|
||||||
|
splashRadius: 0,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// TextButton
|
||||||
|
// Value is used to calculate "dialog.actionsPadding"
|
||||||
|
static const double mobileTextButtonPaddingLR = 20;
|
||||||
|
|
||||||
|
// TextButton on mobile needs a fixed padding, otherwise small buttons
|
||||||
|
// like "OK" has a larger left/right padding.
|
||||||
|
static TextButtonThemeData mobileTextButtonTheme = TextButtonThemeData(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: mobileTextButtonPaddingLR),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Dialogs
|
||||||
|
static const double dialogPadding = 24;
|
||||||
|
|
||||||
|
// padding bottom depends on content (some dialogs has no content)
|
||||||
|
static EdgeInsets dialogTitlePadding({bool content = true}) {
|
||||||
|
final double p = dialogPadding;
|
||||||
|
|
||||||
|
return EdgeInsets.fromLTRB(p, p, p, content ? 0 : p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// padding bottom depends on actions (mobile has dialogs without actions)
|
||||||
|
static EdgeInsets dialogContentPadding({bool actions = true}) {
|
||||||
|
final double p = dialogPadding;
|
||||||
|
|
||||||
|
return isDesktop
|
||||||
|
? EdgeInsets.fromLTRB(p, p, p, actions ? (p - 4) : p)
|
||||||
|
: EdgeInsets.fromLTRB(p, p, p, actions ? (p / 2) : p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EdgeInsets dialogActionsPadding() {
|
||||||
|
final double p = dialogPadding;
|
||||||
|
|
||||||
|
return isDesktop
|
||||||
|
? EdgeInsets.fromLTRB(p, 0, p, (p - 4))
|
||||||
|
: EdgeInsets.fromLTRB(p, 0, (p - mobileTextButtonPaddingLR), (p / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static EdgeInsets dialogButtonPadding = isDesktop
|
||||||
|
? EdgeInsets.only(left: dialogPadding)
|
||||||
|
: EdgeInsets.only(left: dialogPadding / 3);
|
||||||
|
|
||||||
static ThemeData lightTheme = ThemeData(
|
static ThemeData lightTheme = ThemeData(
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
hoverColor: Color.fromARGB(255, 224, 224, 224),
|
hoverColor: Color.fromARGB(255, 224, 224, 224),
|
||||||
@ -236,7 +301,7 @@ class MyTheme {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: mobileTextButtonTheme,
|
||||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: MyTheme.accent,
|
backgroundColor: MyTheme.accent,
|
||||||
@ -254,21 +319,8 @@ class MyTheme {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
checkboxTheme: const CheckboxThemeData(
|
checkboxTheme: checkboxTheme,
|
||||||
splashRadius: 0,
|
listTileTheme: listTileTheme,
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(5),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
listTileTheme: ListTileThemeData(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(5),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
menuBarTheme: MenuBarThemeData(
|
menuBarTheme: MenuBarThemeData(
|
||||||
style:
|
style:
|
||||||
MenuStyle(backgroundColor: MaterialStatePropertyAll(Colors.white))),
|
MenuStyle(backgroundColor: MaterialStatePropertyAll(Colors.white))),
|
||||||
@ -334,7 +386,7 @@ class MyTheme {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: mobileTextButtonTheme,
|
||||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: MyTheme.accent,
|
backgroundColor: MyTheme.accent,
|
||||||
@ -357,21 +409,8 @@ class MyTheme {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
checkboxTheme: const CheckboxThemeData(
|
checkboxTheme: checkboxTheme,
|
||||||
splashRadius: 0,
|
listTileTheme: listTileTheme,
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(5),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
listTileTheme: ListTileThemeData(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(5),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
menuBarTheme: MenuBarThemeData(
|
menuBarTheme: MenuBarThemeData(
|
||||||
style: MenuStyle(
|
style: MenuStyle(
|
||||||
backgroundColor: MaterialStatePropertyAll(Color(0xFF121212)))),
|
backgroundColor: MaterialStatePropertyAll(Color(0xFF121212)))),
|
||||||
@ -771,6 +810,10 @@ void showToast(String text, {Duration timeout = const Duration(seconds: 2)}) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// - Remove argument "contentPadding", no need for it, all should look the same.
|
||||||
|
// - Remove "required" for argument "content". See simple confirm dialog "delete peer", only title and actions are used. No need to "content: SizedBox.shrink()".
|
||||||
|
// - Make dead code alive, transform arguments "onSubmit" and "onCancel" into correspondenting buttons "ConfirmOkButton", "CancelButton".
|
||||||
class CustomAlertDialog extends StatelessWidget {
|
class CustomAlertDialog extends StatelessWidget {
|
||||||
const CustomAlertDialog(
|
const CustomAlertDialog(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
@ -798,8 +841,8 @@ class CustomAlertDialog extends StatelessWidget {
|
|||||||
Future.delayed(Duration.zero, () {
|
Future.delayed(Duration.zero, () {
|
||||||
if (!scopeNode.hasFocus) scopeNode.requestFocus();
|
if (!scopeNode.hasFocus) scopeNode.requestFocus();
|
||||||
});
|
});
|
||||||
const double padding = 30;
|
|
||||||
bool tabTapped = false;
|
bool tabTapped = false;
|
||||||
|
|
||||||
return FocusScope(
|
return FocusScope(
|
||||||
node: scopeNode,
|
node: scopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
@ -824,22 +867,18 @@ class CustomAlertDialog extends StatelessWidget {
|
|||||||
return KeyEventResult.ignored;
|
return KeyEventResult.ignored;
|
||||||
},
|
},
|
||||||
child: AlertDialog(
|
child: AlertDialog(
|
||||||
scrollable: true,
|
scrollable: true,
|
||||||
title: title,
|
title: title,
|
||||||
titlePadding: EdgeInsets.fromLTRB(padding, 24, padding, 0),
|
content: ConstrainedBox(
|
||||||
contentPadding: EdgeInsets.fromLTRB(
|
constraints: contentBoxConstraints,
|
||||||
contentPadding ?? padding,
|
child: content,
|
||||||
25,
|
),
|
||||||
contentPadding ?? padding,
|
actions: actions,
|
||||||
actions is List ? 10 : padding,
|
titlePadding: MyTheme.dialogTitlePadding(content: content != null),
|
||||||
),
|
contentPadding:
|
||||||
content: ConstrainedBox(
|
MyTheme.dialogContentPadding(actions: actions is List),
|
||||||
constraints: contentBoxConstraints,
|
actionsPadding: MyTheme.dialogActionsPadding(),
|
||||||
child: content,
|
buttonPadding: MyTheme.dialogButtonPadding),
|
||||||
),
|
|
||||||
actions: actions,
|
|
||||||
actionsPadding: EdgeInsets.fromLTRB(padding, 0, padding, padding),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1115,25 +1154,32 @@ class AndroidPermissionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO move this to mobile/widgets.
|
||||||
|
// Used only for mobile, pages remote, settings, dialog
|
||||||
|
// TODO remove argument contentPadding, it’s not used, getToggle() has not
|
||||||
RadioListTile<T> getRadio<T>(
|
RadioListTile<T> getRadio<T>(
|
||||||
String name, T toValue, T curValue, void Function(T?) onChange,
|
String name, T toValue, T curValue, void Function(T?) onChange,
|
||||||
{EdgeInsetsGeometry? contentPadding}) {
|
{EdgeInsetsGeometry? contentPadding}) {
|
||||||
return RadioListTile<T>(
|
return RadioListTile<T>(
|
||||||
contentPadding: contentPadding,
|
contentPadding: contentPadding ?? EdgeInsets.zero,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
controlAffinity: ListTileControlAffinity.trailing,
|
controlAffinity: ListTileControlAffinity.trailing,
|
||||||
title: Text(translate(name)),
|
title: Text(translate(name)),
|
||||||
value: toValue,
|
value: toValue,
|
||||||
groupValue: curValue,
|
groupValue: curValue,
|
||||||
onChanged: onChange,
|
onChanged: onChange,
|
||||||
dense: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO move this to mobile/widgets.
|
||||||
|
// Used only for mobile, pages remote, settings, dialog
|
||||||
CheckboxListTile getToggle(
|
CheckboxListTile getToggle(
|
||||||
String id, void Function(void Function()) setState, option, name,
|
String id, void Function(void Function()) setState, option, name,
|
||||||
{FFI? ffi}) {
|
{FFI? ffi}) {
|
||||||
final opt = bind.sessionGetToggleOptionSync(id: id, arg: option);
|
final opt = bind.sessionGetToggleOptionSync(id: id, arg: option);
|
||||||
return CheckboxListTile(
|
return CheckboxListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
value: opt,
|
value: opt,
|
||||||
onChanged: (v) {
|
onChanged: (v) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -1143,7 +1189,6 @@ CheckboxListTile getToggle(
|
|||||||
(ffi ?? gFFI).qualityMonitorModel.checkShowQualityMonitor(id);
|
(ffi ?? gFFI).qualityMonitorModel.checkShowQualityMonitor(id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dense: true,
|
|
||||||
title: Text(translate(name)));
|
title: Text(translate(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,7 +802,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
|||||||
switchType: SwitchType.scheckbox,
|
switchType: SwitchType.scheckbox,
|
||||||
text: translate("Show Hidden Files"),
|
text: translate("Show Hidden Files"),
|
||||||
getter: () async {
|
getter: () async {
|
||||||
return controller.options.value.isWindows;
|
return controller.options.value.showHidden;
|
||||||
},
|
},
|
||||||
setter: (bool v) async {
|
setter: (bool v) async {
|
||||||
controller.toggleShowHidden();
|
controller.toggleShowHidden();
|
||||||
|
@ -696,10 +696,8 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
// return CustomAlertDialog(
|
// return CustomAlertDialog(
|
||||||
// title: Text(translate('Physical Keyboard Input Mode')),
|
// title: Text(translate('Physical Keyboard Input Mode')),
|
||||||
// content: Column(mainAxisSize: MainAxisSize.min, children: [
|
// content: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
// getRadio('Legacy mode', 'legacy', current, setMode,
|
// getRadio('Legacy mode', 'legacy', current, setMode),
|
||||||
// contentPadding: EdgeInsets.zero),
|
// getRadio('Map mode', 'map', current, setMode),
|
||||||
// getRadio('Map mode', 'map', current, setMode,
|
|
||||||
// contentPadding: EdgeInsets.zero),
|
|
||||||
// ]));
|
// ]));
|
||||||
// }, clickMaskDismiss: true);
|
// }, clickMaskDismiss: true);
|
||||||
// }
|
// }
|
||||||
@ -1069,7 +1067,6 @@ void showOptions(
|
|||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: displays + radios + toggles + more),
|
children: displays + radios + toggles + more),
|
||||||
contentPadding: 0,
|
|
||||||
);
|
);
|
||||||
}, clickMaskDismiss: true, backDismiss: true);
|
}, clickMaskDismiss: true, backDismiss: true);
|
||||||
}
|
}
|
||||||
|
@ -502,19 +502,18 @@ void showLanguageSettings(OverlayDialogManager dialogManager) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: SizedBox.shrink(),
|
content: Column(
|
||||||
content: Column(
|
children: [
|
||||||
children: [
|
getRadio('Default', '', lang, setLang),
|
||||||
getRadio('Default', '', lang, setLang),
|
Divider(color: MyTheme.border),
|
||||||
Divider(color: MyTheme.border),
|
] +
|
||||||
] +
|
langs.map((e) {
|
||||||
langs.map((e) {
|
final key = e[0] as String;
|
||||||
final key = e[0] as String;
|
final name = e[1] as String;
|
||||||
final name = e[1] as String;
|
return getRadio(name, key, lang, setLang);
|
||||||
return getRadio(name, key, lang, setLang);
|
}).toList(),
|
||||||
}).toList(),
|
),
|
||||||
),
|
);
|
||||||
actions: []);
|
|
||||||
}, backDismiss: true, clickMaskDismiss: true);
|
}, backDismiss: true, clickMaskDismiss: true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//
|
//
|
||||||
@ -536,14 +535,12 @@ void showThemeSettings(OverlayDialogManager dialogManager) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: SizedBox.shrink(),
|
content: Column(children: [
|
||||||
contentPadding: 10,
|
getRadio('Light', ThemeMode.light, themeMode, setTheme),
|
||||||
content: Column(children: [
|
getRadio('Dark', ThemeMode.dark, themeMode, setTheme),
|
||||||
getRadio('Light', ThemeMode.light, themeMode, setTheme),
|
getRadio('Follow System', ThemeMode.system, themeMode, setTheme)
|
||||||
getRadio('Dark', ThemeMode.dark, themeMode, setTheme),
|
]),
|
||||||
getRadio('Follow System', ThemeMode.system, themeMode, setTheme)
|
);
|
||||||
]),
|
|
||||||
actions: []);
|
|
||||||
}, backDismiss: true, clickMaskDismiss: true);
|
}, backDismiss: true, clickMaskDismiss: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,12 +128,19 @@ void setTemporaryPasswordLengthDialog(
|
|||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Set one-time password length")),
|
title: Text(translate("Set one-time password length")),
|
||||||
content: Column(
|
content: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children:
|
children: lengths
|
||||||
lengths.map((e) => getRadio(e, e, length, setLength)).toList()),
|
.map(
|
||||||
actions: [],
|
(value) => Row(
|
||||||
contentPadding: 14,
|
children: [
|
||||||
|
Text(value),
|
||||||
|
Radio(
|
||||||
|
value: value, groupValue: length, onChanged: setLength),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList()),
|
||||||
);
|
);
|
||||||
}, backDismiss: true, clickMaskDismiss: true);
|
}, backDismiss: true, clickMaskDismiss: true);
|
||||||
}
|
}
|
||||||
|
BIN
res/icon.ico
BIN
res/icon.ico
Binary file not shown.
Before Width: | Height: | Size: 48 B After Width: | Height: | Size: 1.9 KiB |
@ -1193,7 +1193,9 @@ fn is_function_key(ck: &EnumOrUnknown<ControlKey>) -> bool {
|
|||||||
});
|
});
|
||||||
res = true;
|
res = true;
|
||||||
} else if ck.value() == ControlKey::LockScreen.value() {
|
} else if ck.value() == ControlKey::LockScreen.value() {
|
||||||
lock_screen_2();
|
std::thread::spawn(|| {
|
||||||
|
lock_screen_2();
|
||||||
|
});
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user