mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-15 08:21:28 +03:00
dialog focus && deal with Enter/Esc key
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import 'package:back_button_interceptor/back_button_interceptor.dart';
|
|||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
||||||
import 'package:flutter_hbb/models/peer_model.dart';
|
import 'package:flutter_hbb/models/peer_model.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -340,34 +341,41 @@ class OverlayDialogManager {
|
|||||||
{bool clickMaskDismiss = false,
|
{bool clickMaskDismiss = false,
|
||||||
bool showCancel = true,
|
bool showCancel = true,
|
||||||
VoidCallback? onCancel}) {
|
VoidCallback? onCancel}) {
|
||||||
show((setState, close) => CustomAlertDialog(
|
show((setState, close) {
|
||||||
|
cancel() {
|
||||||
|
dismissAll();
|
||||||
|
if (onCancel != null) {
|
||||||
|
onCancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CustomAlertDialog(
|
||||||
content: Container(
|
content: Container(
|
||||||
constraints: BoxConstraints(maxWidth: 240),
|
constraints: const BoxConstraints(maxWidth: 240),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
Center(child: CircularProgressIndicator()),
|
const Center(child: CircularProgressIndicator()),
|
||||||
SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Center(
|
Center(
|
||||||
child: Text(translate(text),
|
child: Text(translate(text),
|
||||||
style: TextStyle(fontSize: 15))),
|
style: const TextStyle(fontSize: 15))),
|
||||||
SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: !showCancel,
|
offstage: !showCancel,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
style: flatButtonStyle,
|
style: flatButtonStyle,
|
||||||
onPressed: () {
|
onPressed: cancel,
|
||||||
dismissAll();
|
|
||||||
if (onCancel != null) {
|
|
||||||
onCancel();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(translate('Cancel'),
|
child: Text(translate('Cancel'),
|
||||||
style: TextStyle(color: MyTheme.accent)))))
|
style:
|
||||||
]))));
|
const TextStyle(color: MyTheme.accent)))))
|
||||||
|
])),
|
||||||
|
onCancel: showCancel ? cancel : null,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,18 +385,18 @@ void showToast(String text, {Duration timeout = const Duration(seconds: 2)}) {
|
|||||||
final entry = OverlayEntry(builder: (_) {
|
final entry = OverlayEntry(builder: (_) {
|
||||||
return IgnorePointer(
|
return IgnorePointer(
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment(0.0, 0.8),
|
alignment: const Alignment(0.0, 0.8),
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black.withOpacity(0.6),
|
color: Colors.black.withOpacity(0.6),
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: const BorderRadius.all(
|
||||||
Radius.circular(20),
|
Radius.circular(20),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 5),
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
|
||||||
child: Text(
|
child: Text(
|
||||||
text,
|
text,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
decoration: TextDecoration.none,
|
decoration: TextDecoration.none,
|
||||||
fontWeight: FontWeight.w300,
|
fontWeight: FontWeight.w300,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
@@ -403,23 +411,54 @@ void showToast(String text, {Duration timeout = const Duration(seconds: 2)}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CustomAlertDialog extends StatelessWidget {
|
class CustomAlertDialog extends StatelessWidget {
|
||||||
CustomAlertDialog(
|
const CustomAlertDialog(
|
||||||
{this.title, required this.content, this.actions, this.contentPadding});
|
{Key? key,
|
||||||
|
this.title,
|
||||||
|
required this.content,
|
||||||
|
this.actions,
|
||||||
|
this.contentPadding,
|
||||||
|
this.onSubmit,
|
||||||
|
this.onCancel})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final Widget? title;
|
final Widget? title;
|
||||||
final Widget content;
|
final Widget content;
|
||||||
final List<Widget>? actions;
|
final List<Widget>? actions;
|
||||||
final double? contentPadding;
|
final double? contentPadding;
|
||||||
|
final Function()? onSubmit;
|
||||||
|
final Function()? onCancel;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
FocusNode focusNode = FocusNode();
|
||||||
scrollable: true,
|
// request focus if there is no focused FocusNode in the dialog
|
||||||
title: title,
|
Future.delayed(Duration.zero, () {
|
||||||
contentPadding:
|
if (!focusNode.hasFocus) focusNode.requestFocus();
|
||||||
EdgeInsets.symmetric(horizontal: contentPadding ?? 25, vertical: 10),
|
});
|
||||||
content: content,
|
return Focus(
|
||||||
actions: actions,
|
focusNode: focusNode,
|
||||||
|
autofocus: true,
|
||||||
|
onKey: (node, key) {
|
||||||
|
if (key.logicalKey == LogicalKeyboardKey.escape) {
|
||||||
|
if (key is RawKeyDownEvent) {
|
||||||
|
onCancel?.call();
|
||||||
|
}
|
||||||
|
return KeyEventResult.handled; // avoid TextField exception on escape
|
||||||
|
} else if (onSubmit != null &&
|
||||||
|
key.logicalKey == LogicalKeyboardKey.enter) {
|
||||||
|
if (key is RawKeyDownEvent) onSubmit?.call();
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
return KeyEventResult.ignored;
|
||||||
|
},
|
||||||
|
child: AlertDialog(
|
||||||
|
scrollable: true,
|
||||||
|
title: title,
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: contentPadding ?? 25, vertical: 10),
|
||||||
|
content: content,
|
||||||
|
actions: actions,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,26 +468,28 @@ void msgBox(
|
|||||||
{bool? hasCancel}) {
|
{bool? hasCancel}) {
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
List<Widget> buttons = [];
|
List<Widget> buttons = [];
|
||||||
|
bool hasOk = false;
|
||||||
|
submit() {
|
||||||
|
dialogManager.dismissAll();
|
||||||
|
// https://github.com/fufesou/rustdesk/blob/5e9a31340b899822090a3731769ae79c6bf5f3e5/src/ui/common.tis#L263
|
||||||
|
if (!type.contains("custom")) {
|
||||||
|
closeConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
dialogManager.dismissAll();
|
||||||
|
}
|
||||||
|
|
||||||
if (type != "connecting" && type != "success" && !type.contains("nook")) {
|
if (type != "connecting" && type != "success" && !type.contains("nook")) {
|
||||||
buttons.insert(
|
hasOk = true;
|
||||||
0,
|
buttons.insert(0, msgBoxButton(translate('OK'), submit));
|
||||||
msgBoxButton(translate('OK'), () {
|
|
||||||
dialogManager.dismissAll();
|
|
||||||
// https://github.com/fufesou/rustdesk/blob/5e9a31340b899822090a3731769ae79c6bf5f3e5/src/ui/common.tis#L263
|
|
||||||
if (!type.contains("custom")) {
|
|
||||||
closeConnection();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
hasCancel ??= !type.contains("error") &&
|
hasCancel ??= !type.contains("error") &&
|
||||||
!type.contains("nocancel") &&
|
!type.contains("nocancel") &&
|
||||||
type != "restarting";
|
type != "restarting";
|
||||||
if (hasCancel) {
|
if (hasCancel) {
|
||||||
buttons.insert(
|
buttons.insert(0, msgBoxButton(translate('Cancel'), cancel));
|
||||||
0,
|
|
||||||
msgBoxButton(translate('Cancel'), () {
|
|
||||||
dialogManager.dismissAll();
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
// TODO: test this button
|
// TODO: test this button
|
||||||
if (type.contains("hasclose")) {
|
if (type.contains("hasclose")) {
|
||||||
@@ -459,9 +500,12 @@ void msgBox(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
dialogManager.show((setState, close) => CustomAlertDialog(
|
dialogManager.show((setState, close) => CustomAlertDialog(
|
||||||
title: _msgBoxTitle(title),
|
title: _msgBoxTitle(title),
|
||||||
content: Text(translate(text), style: TextStyle(fontSize: 15)),
|
content: Text(translate(text), style: const TextStyle(fontSize: 15)),
|
||||||
actions: buttons));
|
actions: buttons,
|
||||||
|
onSubmit: hasOk ? submit : null,
|
||||||
|
onCancel: hasCancel == true ? cancel : null,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget msgBoxButton(String text, void Function() onPressed) {
|
Widget msgBoxButton(String text, void Function() onPressed) {
|
||||||
@@ -479,15 +523,19 @@ Widget msgBoxButton(String text, void Function() onPressed) {
|
|||||||
Text(translate(text), style: TextStyle(color: MyTheme.accent))));
|
Text(translate(text), style: TextStyle(color: MyTheme.accent))));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _msgBoxTitle(String title) => Text(translate(title), style: TextStyle(fontSize: 21));
|
Widget _msgBoxTitle(String title) =>
|
||||||
|
Text(translate(title), style: TextStyle(fontSize: 21));
|
||||||
|
|
||||||
void msgBoxCommon(OverlayDialogManager dialogManager, String title,
|
void msgBoxCommon(OverlayDialogManager dialogManager, String title,
|
||||||
Widget content, List<Widget> buttons) {
|
Widget content, List<Widget> buttons,
|
||||||
|
{bool hasCancel = true}) {
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show((setState, close) => CustomAlertDialog(
|
dialogManager.show((setState, close) => CustomAlertDialog(
|
||||||
title: _msgBoxTitle(title),
|
title: _msgBoxTitle(title),
|
||||||
content: content,
|
content: content,
|
||||||
actions: buttons));
|
actions: buttons,
|
||||||
|
onCancel: hasCancel ? close : null,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Color str2color(String str, [alpha = 0xFF]) {
|
Color str2color(String str, [alpha = 0xFF]) {
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
});
|
});
|
||||||
var w = Container(
|
var w = Container(
|
||||||
width: 320 + 20 * 2,
|
width: 320 + 20 * 2,
|
||||||
padding: EdgeInsets.fromLTRB(20, 24, 20, 22),
|
padding: const EdgeInsets.fromLTRB(20, 24, 20, 22),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: MyTheme.color(context).bg,
|
color: MyTheme.color(context).bg,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(13)),
|
borderRadius: const BorderRadius.all(Radius.circular(13)),
|
||||||
@@ -179,7 +179,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
translate('Control Remote Desktop'),
|
translate('Control Remote Desktop'),
|
||||||
style: TextStyle(fontSize: 19, height: 1),
|
style: const TextStyle(fontSize: 19, height: 1),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).marginOnly(bottom: 15),
|
).marginOnly(bottom: 15),
|
||||||
@@ -192,11 +192,13 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
enableSuggestions: false,
|
enableSuggestions: false,
|
||||||
keyboardType: TextInputType.visiblePassword,
|
keyboardType: TextInputType.visiblePassword,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontFamily: 'WorkSans',
|
fontFamily: 'WorkSans',
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
height: 1,
|
height: 1,
|
||||||
),
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
cursorColor: MyTheme.color(context).text!,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: inputFocused.value
|
hintText: inputFocused.value
|
||||||
? null
|
? null
|
||||||
@@ -206,14 +208,18 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.zero,
|
borderRadius: BorderRadius.zero,
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: MyTheme.color(context).placeholder!)),
|
color: MyTheme.color(context).border!)),
|
||||||
focusedBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.zero,
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: MyTheme.color(context).border!)),
|
||||||
|
focusedBorder: const OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.zero,
|
borderRadius: BorderRadius.zero,
|
||||||
borderSide:
|
borderSide:
|
||||||
BorderSide(color: MyTheme.button, width: 3),
|
BorderSide(color: MyTheme.button, width: 3),
|
||||||
),
|
),
|
||||||
isDense: true,
|
isDense: true,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
horizontal: 10, vertical: 12)),
|
horizontal: 10, vertical: 12)),
|
||||||
controller: _idController,
|
controller: _idController,
|
||||||
inputFormatters: [IDTextInputFormatter()],
|
inputFormatters: [IDTextInputFormatter()],
|
||||||
@@ -266,7 +272,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
).marginSymmetric(horizontal: 12),
|
).marginSymmetric(horizontal: 12),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 17,
|
width: 17,
|
||||||
),
|
),
|
||||||
Obx(
|
Obx(
|
||||||
@@ -311,7 +317,8 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(constraints: BoxConstraints(maxWidth: 600), child: w));
|
child: Container(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 600), child: w));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -661,71 +668,69 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
var field = "";
|
var field = "";
|
||||||
var msg = "";
|
var msg = "";
|
||||||
var isInProgress = false;
|
var isInProgress = false;
|
||||||
|
TextEditingController controller = TextEditingController(text: field);
|
||||||
|
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
setState(() {
|
||||||
|
msg = "";
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
field = controller.text.trim();
|
||||||
|
if (field.isEmpty) {
|
||||||
|
// pass
|
||||||
|
} else {
|
||||||
|
final ids = field.trim().split(RegExp(r"[\s,;\n]+"));
|
||||||
|
field = ids.join(',');
|
||||||
|
for (final newId in ids) {
|
||||||
|
if (gFFI.abModel.idContainBy(newId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gFFI.abModel.addId(newId);
|
||||||
|
}
|
||||||
|
await gFFI.abModel.updateAb();
|
||||||
|
this.setState(() {});
|
||||||
|
// final currentPeers
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Add ID")),
|
title: Text(translate("Add ID")),
|
||||||
content: Column(
|
content: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(translate("whitelist_sep")),
|
Text(translate("whitelist_sep")),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
onChanged: (s) {
|
maxLines: null,
|
||||||
field = s;
|
decoration: InputDecoration(
|
||||||
},
|
border: const OutlineInputBorder(),
|
||||||
maxLines: null,
|
errorText: msg.isEmpty ? null : translate(msg),
|
||||||
decoration: InputDecoration(
|
),
|
||||||
border: OutlineInputBorder(),
|
controller: controller,
|
||||||
errorText: msg.isEmpty ? null : translate(msg),
|
focusNode: FocusNode()..requestFocus()),
|
||||||
),
|
|
||||||
controller: TextEditingController(text: field),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 4.0,
|
height: 4.0,
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
msg = "";
|
|
||||||
isInProgress = true;
|
|
||||||
});
|
|
||||||
field = field.trim();
|
|
||||||
if (field.isEmpty) {
|
|
||||||
// pass
|
|
||||||
} else {
|
|
||||||
final ids = field.trim().split(RegExp(r"[\s,;\n]+"));
|
|
||||||
field = ids.join(',');
|
|
||||||
for (final newId in ids) {
|
|
||||||
if (gFFI.abModel.idContainBy(newId)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
gFFI.abModel.addId(newId);
|
|
||||||
}
|
|
||||||
await gFFI.abModel.updateAb();
|
|
||||||
this.setState(() {});
|
|
||||||
// final currentPeers
|
|
||||||
}
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -734,67 +739,65 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
var field = "";
|
var field = "";
|
||||||
var msg = "";
|
var msg = "";
|
||||||
var isInProgress = false;
|
var isInProgress = false;
|
||||||
|
TextEditingController controller = TextEditingController(text: field);
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
setState(() {
|
||||||
|
msg = "";
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
field = controller.text.trim();
|
||||||
|
if (field.isEmpty) {
|
||||||
|
// pass
|
||||||
|
} else {
|
||||||
|
final tags = field.trim().split(RegExp(r"[\s,;\n]+"));
|
||||||
|
field = tags.join(',');
|
||||||
|
for (final tag in tags) {
|
||||||
|
gFFI.abModel.addTag(tag);
|
||||||
|
}
|
||||||
|
await gFFI.abModel.updateAb();
|
||||||
|
// final currentPeers
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Add Tag")),
|
title: Text(translate("Add Tag")),
|
||||||
content: Column(
|
content: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(translate("whitelist_sep")),
|
Text(translate("whitelist_sep")),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
onChanged: (s) {
|
|
||||||
field = s;
|
|
||||||
},
|
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: msg.isEmpty ? null : translate(msg),
|
errorText: msg.isEmpty ? null : translate(msg),
|
||||||
),
|
),
|
||||||
controller: TextEditingController(text: field),
|
controller: controller,
|
||||||
|
focusNode: FocusNode()..requestFocus(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 4.0,
|
height: 4.0,
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
msg = "";
|
|
||||||
isInProgress = true;
|
|
||||||
});
|
|
||||||
field = field.trim();
|
|
||||||
if (field.isEmpty) {
|
|
||||||
// pass
|
|
||||||
} else {
|
|
||||||
final tags = field.trim().split(RegExp(r"[\s,;\n]+"));
|
|
||||||
field = tags.join(',');
|
|
||||||
for (final tag in tags) {
|
|
||||||
gFFI.abModel.addTag(tag);
|
|
||||||
}
|
|
||||||
await gFFI.abModel.updateAb();
|
|
||||||
// final currentPeers
|
|
||||||
}
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -806,13 +809,23 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
var selectedTag = gFFI.abModel.getPeerTags(id).obs;
|
var selectedTag = gFFI.abModel.getPeerTags(id).obs;
|
||||||
|
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
setState(() {
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
gFFI.abModel.changeTagForPeer(id, selectedTag);
|
||||||
|
await gFFI.abModel.updateAb();
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Edit Tag")),
|
title: Text(translate("Edit Tag")),
|
||||||
content: Column(
|
content: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: tags
|
children: tags
|
||||||
.map((e) => buildTag(e, selectedTag, onTap: () {
|
.map((e) => buildTag(e, selectedTag, onTap: () {
|
||||||
@@ -825,26 +838,16 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
.toList(growable: false),
|
.toList(growable: false),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
isInProgress = true;
|
|
||||||
});
|
|
||||||
gFFI.abModel.changeTagForPeer(id, selectedTag);
|
|
||||||
await gFFI.abModel.updateAb();
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
buildServerInfo(context),
|
buildServerInfo(context),
|
||||||
VerticalDivider(
|
const VerticalDivider(
|
||||||
width: 1,
|
width: 1,
|
||||||
thickness: 1,
|
thickness: 1,
|
||||||
),
|
),
|
||||||
@@ -93,7 +93,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
buildIDBoard(BuildContext context) {
|
buildIDBoard(BuildContext context) {
|
||||||
final model = gFFI.serverModel;
|
final model = gFFI.serverModel;
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.only(left: 20, right: 16),
|
margin: const EdgeInsets.only(left: 20, right: 16),
|
||||||
height: 52,
|
height: 52,
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||||
@@ -101,7 +101,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
width: 2,
|
width: 2,
|
||||||
decoration: BoxDecoration(color: MyTheme.accent),
|
decoration: const BoxDecoration(color: MyTheme.accent),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -109,7 +109,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
SizedBox(
|
||||||
height: 25,
|
height: 25,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -135,11 +135,11 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: model.serverId,
|
controller: model.serverId,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.only(bottom: 18),
|
contentPadding: EdgeInsets.only(bottom: 18),
|
||||||
),
|
),
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -642,76 +642,76 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
var newId = "";
|
var newId = "";
|
||||||
var msg = "";
|
var msg = "";
|
||||||
var isInProgress = false;
|
var isInProgress = false;
|
||||||
|
TextEditingController controller = TextEditingController();
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
newId = controller.text.trim();
|
||||||
|
setState(() {
|
||||||
|
msg = "";
|
||||||
|
isInProgress = true;
|
||||||
|
bind.mainChangeId(newId: newId);
|
||||||
|
});
|
||||||
|
|
||||||
|
var status = await bind.mainGetAsyncStatus();
|
||||||
|
while (status == " ") {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
status = await bind.mainGetAsyncStatus();
|
||||||
|
}
|
||||||
|
if (status.isEmpty) {
|
||||||
|
// ok
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
isInProgress = false;
|
||||||
|
msg = translate(status);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Change ID")),
|
title: Text(translate("Change ID")),
|
||||||
content: Column(
|
content: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(translate("id_change_tip")),
|
Text(translate("id_change_tip")),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text("ID:").marginOnly(bottom: 16.0),
|
const Text("ID:").marginOnly(bottom: 16.0),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
onChanged: (s) {
|
|
||||||
newId = s;
|
|
||||||
},
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: msg.isEmpty ? null : translate(msg)),
|
errorText: msg.isEmpty ? null : translate(msg)),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
LengthLimitingTextInputFormatter(16),
|
LengthLimitingTextInputFormatter(16),
|
||||||
// FilteringTextInputFormatter(RegExp(r"[a-zA-z][a-zA-z0-9\_]*"), allow: true)
|
// FilteringTextInputFormatter(RegExp(r"[a-zA-z][a-zA-z0-9\_]*"), allow: true)
|
||||||
],
|
],
|
||||||
maxLength: 16,
|
maxLength: 16,
|
||||||
|
controller: controller,
|
||||||
|
focusNode: FocusNode()..requestFocus(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 4.0,
|
height: 4.0,
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
msg = "";
|
|
||||||
isInProgress = true;
|
|
||||||
bind.mainChangeId(newId: newId);
|
|
||||||
});
|
|
||||||
|
|
||||||
var status = await bind.mainGetAsyncStatus();
|
|
||||||
while (status == " ") {
|
|
||||||
await Future.delayed(Duration(milliseconds: 100));
|
|
||||||
status = await bind.mainGetAsyncStatus();
|
|
||||||
}
|
|
||||||
if (status.isEmpty) {
|
|
||||||
// ok
|
|
||||||
close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
isInProgress = false;
|
|
||||||
msg = translate(status);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -720,16 +720,16 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
final appName = await bind.mainGetAppName();
|
final appName = await bind.mainGetAppName();
|
||||||
final license = await bind.mainGetLicense();
|
final license = await bind.mainGetLicense();
|
||||||
final version = await bind.mainGetVersion();
|
final version = await bind.mainGetVersion();
|
||||||
final linkStyle = TextStyle(decoration: TextDecoration.underline);
|
const linkStyle = TextStyle(decoration: TextDecoration.underline);
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text("About $appName"),
|
title: Text("About $appName"),
|
||||||
content: ConstrainedBox(
|
content: ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 500),
|
constraints: const BoxConstraints(minWidth: 500),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Text("Version: $version").marginSymmetric(vertical: 4.0),
|
Text("Version: $version").marginSymmetric(vertical: 4.0),
|
||||||
@@ -737,7 +737,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
launchUrlString("https://rustdesk.com/privacy");
|
launchUrlString("https://rustdesk.com/privacy");
|
||||||
},
|
},
|
||||||
child: Text(
|
child: const Text(
|
||||||
"Privacy Statement",
|
"Privacy Statement",
|
||||||
style: linkStyle,
|
style: linkStyle,
|
||||||
).marginSymmetric(vertical: 4.0)),
|
).marginSymmetric(vertical: 4.0)),
|
||||||
@@ -745,13 +745,14 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
launchUrlString("https://rustdesk.com");
|
launchUrlString("https://rustdesk.com");
|
||||||
},
|
},
|
||||||
child: Text(
|
child: const Text(
|
||||||
"Website",
|
"Website",
|
||||||
style: linkStyle,
|
style: linkStyle,
|
||||||
).marginSymmetric(vertical: 4.0)),
|
).marginSymmetric(vertical: 4.0)),
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(color: Color(0xFF2c8cff)),
|
decoration: const BoxDecoration(color: Color(0xFF2c8cff)),
|
||||||
padding: EdgeInsets.symmetric(vertical: 24, horizontal: 8),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -760,9 +761,9 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Copyright © 2022 Purslane Ltd.\n$license",
|
"Copyright © 2022 Purslane Ltd.\n$license",
|
||||||
style: TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
Text(
|
const Text(
|
||||||
"Made with heart in this chaotic world!",
|
"Made with heart in this chaotic world!",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w800,
|
fontWeight: FontWeight.w800,
|
||||||
@@ -778,12 +779,10 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("OK"))),
|
||||||
onPressed: () async {
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: close,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -815,118 +814,124 @@ Future<bool> loginDialog() async {
|
|||||||
var isInProgress = false;
|
var isInProgress = false;
|
||||||
var completer = Completer<bool>();
|
var completer = Completer<bool>();
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
setState(() {
|
||||||
|
userNameMsg = "";
|
||||||
|
passMsg = "";
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
cancel() {
|
||||||
|
setState(() {
|
||||||
|
isInProgress = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
userName = userContontroller.text;
|
||||||
|
pass = pwdController.text;
|
||||||
|
if (userName.isEmpty) {
|
||||||
|
userNameMsg = translate("Username missed");
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pass.isEmpty) {
|
||||||
|
passMsg = translate("Password missed");
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final resp = await gFFI.userModel.login(userName, pass);
|
||||||
|
if (resp.containsKey('error')) {
|
||||||
|
passMsg = resp['error'];
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// {access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJndWlkIjoiMDFkZjQ2ZjgtZjg3OS00MDE0LTk5Y2QtMGMwYzM2MmViZGJlIiwiZXhwIjoxNjYxNDg2NzYwfQ.GZpe1oI8TfM5yTYNrpcwbI599P4Z_-b2GmnwNl2Lr-w,
|
||||||
|
// token_type: Bearer, user: {id: , name: admin, email: null, note: null, status: null, grp: null, is_admin: true}}
|
||||||
|
debugPrint("$resp");
|
||||||
|
completer.complete(true);
|
||||||
|
} catch (err) {
|
||||||
|
// ignore: avoid_print
|
||||||
|
print(err.toString());
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
completer.complete(false);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Login")),
|
title: Text(translate("Login")),
|
||||||
content: ConstrainedBox(
|
content: ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 500),
|
constraints: const BoxConstraints(minWidth: 500),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text(
|
child: Text(
|
||||||
"${translate('Username')}:",
|
"${translate('Username')}:",
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
).marginOnly(bottom: 16.0)),
|
).marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: userNameMsg.isNotEmpty ? userNameMsg : null),
|
errorText: userNameMsg.isNotEmpty ? userNameMsg : null),
|
||||||
controller: userContontroller,
|
controller: userContontroller,
|
||||||
|
focusNode: FocusNode()..requestFocus(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('Password')}:")
|
child: Text("${translate('Password')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: passMsg.isNotEmpty ? passMsg : null),
|
errorText: passMsg.isNotEmpty ? passMsg : null),
|
||||||
controller: pwdController,
|
controller: pwdController,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 4.0,
|
height: 4.0,
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: cancel, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
completer.complete(false);
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
userNameMsg = "";
|
|
||||||
passMsg = "";
|
|
||||||
isInProgress = true;
|
|
||||||
});
|
|
||||||
final cancel = () {
|
|
||||||
setState(() {
|
|
||||||
isInProgress = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
userName = userContontroller.text;
|
|
||||||
pass = pwdController.text;
|
|
||||||
if (userName.isEmpty) {
|
|
||||||
userNameMsg = translate("Username missed");
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pass.isEmpty) {
|
|
||||||
passMsg = translate("Password missed");
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
final resp = await gFFI.userModel.login(userName, pass);
|
|
||||||
if (resp.containsKey('error')) {
|
|
||||||
passMsg = resp['error'];
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// {access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJndWlkIjoiMDFkZjQ2ZjgtZjg3OS00MDE0LTk5Y2QtMGMwYzM2MmViZGJlIiwiZXhwIjoxNjYxNDg2NzYwfQ.GZpe1oI8TfM5yTYNrpcwbI599P4Z_-b2GmnwNl2Lr-w,
|
|
||||||
// token_type: Bearer, user: {id: , name: admin, email: null, note: null, status: null, grp: null, is_admin: true}}
|
|
||||||
debugPrint("$resp");
|
|
||||||
completer.complete(true);
|
|
||||||
} catch (err) {
|
|
||||||
print(err.toString());
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: cancel,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return completer.future;
|
return completer.future;
|
||||||
@@ -940,55 +945,78 @@ void setPasswordDialog() async {
|
|||||||
var errMsg1 = "";
|
var errMsg1 = "";
|
||||||
|
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() {
|
||||||
|
setState(() {
|
||||||
|
errMsg0 = "";
|
||||||
|
errMsg1 = "";
|
||||||
|
});
|
||||||
|
final pass = p0.text.trim();
|
||||||
|
if (pass.length < 6) {
|
||||||
|
setState(() {
|
||||||
|
errMsg0 = translate("Too short, at least 6 characters.");
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p1.text.trim() != pass) {
|
||||||
|
setState(() {
|
||||||
|
errMsg1 = translate("The confirmation is not identical.");
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bind.mainSetPermanentPassword(password: pass);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Set Password")),
|
title: Text(translate("Set Password")),
|
||||||
content: ConstrainedBox(
|
content: ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 500),
|
constraints: const BoxConstraints(minWidth: 500),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text(
|
child: Text(
|
||||||
"${translate('Password')}:",
|
"${translate('Password')}:",
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
).marginOnly(bottom: 16.0)),
|
).marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: errMsg0.isNotEmpty ? errMsg0 : null),
|
errorText: errMsg0.isNotEmpty ? errMsg0 : null),
|
||||||
controller: p0,
|
controller: p0,
|
||||||
|
focusNode: FocusNode()..requestFocus(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('Confirmation')}:")
|
child: Text("${translate('Confirmation')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: errMsg1.isNotEmpty ? errMsg1 : null),
|
errorText: errMsg1.isNotEmpty ? errMsg1 : null),
|
||||||
controller: p1,
|
controller: p1,
|
||||||
),
|
),
|
||||||
@@ -999,35 +1027,11 @@ void setPasswordDialog() async {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
errMsg0 = "";
|
|
||||||
errMsg1 = "";
|
|
||||||
});
|
|
||||||
final pass = p0.text.trim();
|
|
||||||
if (pass.length < 6) {
|
|
||||||
setState(() {
|
|
||||||
errMsg0 = translate("Too short, at least 6 characters.");
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (p1.text.trim() != pass) {
|
|
||||||
setState(() {
|
|
||||||
errMsg1 = translate("The confirmation is not identical.");
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bind.mainSetPermanentPassword(password: pass);
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1038,52 +1038,117 @@ void changeServer() async {
|
|||||||
var keyController = TextEditingController(text: key);
|
var keyController = TextEditingController(text: key);
|
||||||
|
|
||||||
var isInProgress = false;
|
var isInProgress = false;
|
||||||
|
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
setState(() {
|
||||||
|
[idServerMsg, relayServerMsg, apiServerMsg].forEach((element) {
|
||||||
|
element = "";
|
||||||
|
});
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
cancel() {
|
||||||
|
setState(() {
|
||||||
|
isInProgress = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
idServer = idController.text.trim();
|
||||||
|
relayServer = relayController.text.trim();
|
||||||
|
apiServer = apiController.text.trim().toLowerCase();
|
||||||
|
key = keyController.text.trim();
|
||||||
|
|
||||||
|
if (idServer.isNotEmpty) {
|
||||||
|
idServerMsg =
|
||||||
|
translate(await bind.mainTestIfValidServer(server: idServer));
|
||||||
|
if (idServerMsg.isEmpty) {
|
||||||
|
oldOptions['custom-rendezvous-server'] = idServer;
|
||||||
|
} else {
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oldOptions['custom-rendezvous-server'] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relayServer.isNotEmpty) {
|
||||||
|
relayServerMsg =
|
||||||
|
translate(await bind.mainTestIfValidServer(server: relayServer));
|
||||||
|
if (relayServerMsg.isEmpty) {
|
||||||
|
oldOptions['relay-server'] = relayServer;
|
||||||
|
} else {
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oldOptions['relay-server'] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apiServer.isNotEmpty) {
|
||||||
|
if (apiServer.startsWith('http://') ||
|
||||||
|
apiServer.startsWith("https://")) {
|
||||||
|
oldOptions['api-server'] = apiServer;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
apiServerMsg = translate("invalid_http");
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oldOptions['api-server'] = "";
|
||||||
|
}
|
||||||
|
// ok
|
||||||
|
oldOptions['key'] = key;
|
||||||
|
await bind.mainSetOptions(json: jsonEncode(oldOptions));
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("ID/Relay Server")),
|
title: Text(translate("ID/Relay Server")),
|
||||||
content: ConstrainedBox(
|
content: ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 500),
|
constraints: const BoxConstraints(minWidth: 500),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('ID Server')}:")
|
child: Text("${translate('ID Server')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: idServerMsg.isNotEmpty ? idServerMsg : null),
|
errorText: idServerMsg.isNotEmpty ? idServerMsg : null),
|
||||||
controller: idController,
|
controller: idController,
|
||||||
|
focusNode: FocusNode()..requestFocus(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('Relay Server')}:")
|
child: Text("${translate('Relay Server')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText:
|
errorText:
|
||||||
relayServerMsg.isNotEmpty ? relayServerMsg : null),
|
relayServerMsg.isNotEmpty ? relayServerMsg : null),
|
||||||
controller: relayController,
|
controller: relayController,
|
||||||
@@ -1091,22 +1156,22 @@ void changeServer() async {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('API Server')}:")
|
child: Text("${translate('API Server')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText:
|
errorText:
|
||||||
apiServerMsg.isNotEmpty ? apiServerMsg : null),
|
apiServerMsg.isNotEmpty ? apiServerMsg : null),
|
||||||
controller: apiController,
|
controller: apiController,
|
||||||
@@ -1114,21 +1179,21 @@ void changeServer() async {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child:
|
child:
|
||||||
Text("${translate('Key')}:").marginOnly(bottom: 16.0)),
|
Text("${translate('Key')}:").marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
controller: keyController,
|
controller: keyController,
|
||||||
@@ -1136,83 +1201,20 @@ void changeServer() async {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 4.0,
|
height: 4.0,
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
[idServerMsg, relayServerMsg, apiServerMsg].forEach((element) {
|
|
||||||
element = "";
|
|
||||||
});
|
|
||||||
isInProgress = true;
|
|
||||||
});
|
|
||||||
final cancel = () {
|
|
||||||
setState(() {
|
|
||||||
isInProgress = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
idServer = idController.text.trim();
|
|
||||||
relayServer = relayController.text.trim();
|
|
||||||
apiServer = apiController.text.trim().toLowerCase();
|
|
||||||
key = keyController.text.trim();
|
|
||||||
|
|
||||||
if (idServer.isNotEmpty) {
|
|
||||||
idServerMsg = translate(
|
|
||||||
await bind.mainTestIfValidServer(server: idServer));
|
|
||||||
if (idServerMsg.isEmpty) {
|
|
||||||
oldOptions['custom-rendezvous-server'] = idServer;
|
|
||||||
} else {
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oldOptions['custom-rendezvous-server'] = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (relayServer.isNotEmpty) {
|
|
||||||
relayServerMsg = translate(
|
|
||||||
await bind.mainTestIfValidServer(server: relayServer));
|
|
||||||
if (relayServerMsg.isEmpty) {
|
|
||||||
oldOptions['relay-server'] = relayServer;
|
|
||||||
} else {
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oldOptions['relay-server'] = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apiServer.isNotEmpty) {
|
|
||||||
if (apiServer.startsWith('http://') ||
|
|
||||||
apiServer.startsWith("https://")) {
|
|
||||||
oldOptions['api-server'] = apiServer;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
apiServerMsg = translate("invalid_http");
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oldOptions['api-server'] = "";
|
|
||||||
}
|
|
||||||
// ok
|
|
||||||
oldOptions['key'] = key;
|
|
||||||
await bind.mainSetOptions(json: jsonEncode(oldOptions));
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1231,27 +1233,28 @@ void changeWhiteList() async {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(translate("whitelist_sep")),
|
Text(translate("whitelist_sep")),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: msg.isEmpty ? null : translate(msg),
|
errorText: msg.isEmpty ? null : translate(msg),
|
||||||
),
|
),
|
||||||
controller: controller,
|
controller: controller,
|
||||||
),
|
focusNode: FocusNode()..requestFocus()),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 4.0,
|
height: 4.0,
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
@@ -1277,7 +1280,7 @@ void changeWhiteList() async {
|
|||||||
final ipMatch = RegExp(r"^\d+\.\d+\.\d+\.\d+$");
|
final ipMatch = RegExp(r"^\d+\.\d+\.\d+\.\d+$");
|
||||||
for (final ip in ips) {
|
for (final ip in ips) {
|
||||||
if (!ipMatch.hasMatch(ip)) {
|
if (!ipMatch.hasMatch(ip)) {
|
||||||
msg = translate("Invalid IP") + " $ip";
|
msg = "${translate("Invalid IP")} $ip";
|
||||||
setState(() {
|
setState(() {
|
||||||
isInProgress = false;
|
isInProgress = false;
|
||||||
});
|
});
|
||||||
@@ -1292,6 +1295,7 @@ void changeWhiteList() async {
|
|||||||
},
|
},
|
||||||
child: Text(translate("OK"))),
|
child: Text(translate("OK"))),
|
||||||
],
|
],
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1314,50 +1318,80 @@ void changeSocks5Proxy() async {
|
|||||||
|
|
||||||
var isInProgress = false;
|
var isInProgress = false;
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
setState(() {
|
||||||
|
proxyMsg = "";
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
cancel() {
|
||||||
|
setState(() {
|
||||||
|
isInProgress = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy = proxyController.text.trim();
|
||||||
|
username = userController.text.trim();
|
||||||
|
password = pwdController.text.trim();
|
||||||
|
|
||||||
|
if (proxy.isNotEmpty) {
|
||||||
|
proxyMsg = translate(await bind.mainTestIfValidServer(server: proxy));
|
||||||
|
if (proxyMsg.isEmpty) {
|
||||||
|
// ignore
|
||||||
|
} else {
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await bind.mainSetSocks(
|
||||||
|
proxy: proxy, username: username, password: password);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Socks5 Proxy")),
|
title: Text(translate("Socks5 Proxy")),
|
||||||
content: ConstrainedBox(
|
content: ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 500),
|
constraints: const BoxConstraints(minWidth: 500),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('Hostname')}:")
|
child: Text("${translate('Hostname')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
errorText: proxyMsg.isNotEmpty ? proxyMsg : null),
|
errorText: proxyMsg.isNotEmpty ? proxyMsg : null),
|
||||||
controller: proxyController,
|
controller: proxyController,
|
||||||
|
focusNode: FocusNode()..requestFocus(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('Username')}:")
|
child: Text("${translate('Username')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
controller: userController,
|
controller: userController,
|
||||||
@@ -1365,21 +1399,21 @@ void changeSocks5Proxy() async {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('Password')}:")
|
child: Text("${translate('Password')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
controller: pwdController,
|
controller: pwdController,
|
||||||
@@ -1387,50 +1421,20 @@ void changeSocks5Proxy() async {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
proxyMsg = "";
|
|
||||||
isInProgress = true;
|
|
||||||
});
|
|
||||||
final cancel = () {
|
|
||||||
setState(() {
|
|
||||||
isInProgress = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
proxy = proxyController.text.trim();
|
|
||||||
username = userController.text.trim();
|
|
||||||
password = pwdController.text.trim();
|
|
||||||
|
|
||||||
if (proxy.isNotEmpty) {
|
|
||||||
proxyMsg =
|
|
||||||
translate(await bind.mainTestIfValidServer(server: proxy));
|
|
||||||
if (proxyMsg.isEmpty) {
|
|
||||||
// ignore
|
|
||||||
} else {
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await bind.mainSetSocks(
|
|
||||||
proxy: proxy, username: username, password: password);
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,25 +37,33 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
|
|||||||
RxBool fullscreen = false.obs;
|
RxBool fullscreen = false.obs;
|
||||||
Get.put(fullscreen, tag: 'fullscreen');
|
Get.put(fullscreen, tag: 'fullscreen');
|
||||||
return Obx(() => DragToResizeArea(
|
return Obx(() => DragToResizeArea(
|
||||||
resizeEdgeSize: fullscreen.value ? 1.0 : 8.0,
|
resizeEdgeSize: fullscreen.value ? 1.0 : 8.0,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: MyTheme.color(context).border!)),
|
border: Border.all(color: MyTheme.color(context).border!)),
|
||||||
child: Scaffold(
|
child: Overlay(initialEntries: [
|
||||||
backgroundColor: MyTheme.color(context).bg,
|
OverlayEntry(builder: (context) {
|
||||||
body: DesktopTab(
|
gFFI.dialogManager.setOverlayState(Overlay.of(context));
|
||||||
controller: tabController,
|
return Scaffold(
|
||||||
theme: dark ? TarBarTheme.dark() : TarBarTheme.light(),
|
backgroundColor: MyTheme.color(context).bg,
|
||||||
tail: ActionIcon(
|
body: DesktopTab(
|
||||||
message: 'Settings',
|
controller: tabController,
|
||||||
icon: IconFont.menu,
|
theme: dark
|
||||||
theme: dark ? TarBarTheme.dark() : TarBarTheme.light(),
|
? const TarBarTheme.dark()
|
||||||
onTap: onAddSetting,
|
: const TarBarTheme.light(),
|
||||||
is_close: false,
|
tail: ActionIcon(
|
||||||
),
|
message: 'Settings',
|
||||||
)),
|
icon: IconFont.menu,
|
||||||
),
|
theme: dark
|
||||||
));
|
? const TarBarTheme.dark()
|
||||||
|
: const TarBarTheme.light(),
|
||||||
|
onTap: onAddSetting,
|
||||||
|
is_close: false,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void onAddSetting() {
|
void onAddSetting() {
|
||||||
|
|||||||
@@ -642,47 +642,51 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final name = TextEditingController();
|
final name = TextEditingController();
|
||||||
_ffi.dialogManager
|
_ffi.dialogManager.show((setState, close) {
|
||||||
.show((setState, close) => CustomAlertDialog(
|
submit() {
|
||||||
title: Text(translate("Create Folder")),
|
if (name.value.text.isNotEmpty) {
|
||||||
content: Column(
|
model.createDir(
|
||||||
mainAxisSize: MainAxisSize.min,
|
PathUtil.join(
|
||||||
children: [
|
model.getCurrentDir(isLocal).path,
|
||||||
TextFormField(
|
name.value.text,
|
||||||
decoration: InputDecoration(
|
model.getCurrentIsWindows(isLocal)),
|
||||||
labelText: translate(
|
isLocal: isLocal);
|
||||||
"Please enter the folder name"),
|
close();
|
||||||
),
|
}
|
||||||
controller: name,
|
}
|
||||||
),
|
|
||||||
],
|
cancel() => close(false);
|
||||||
),
|
return CustomAlertDialog(
|
||||||
actions: [
|
title: Text(translate("Create Folder")),
|
||||||
TextButton(
|
content: Column(
|
||||||
style: flatButtonStyle,
|
mainAxisSize: MainAxisSize.min,
|
||||||
onPressed: () => close(false),
|
children: [
|
||||||
child: Text(translate("Cancel"))),
|
TextFormField(
|
||||||
ElevatedButton(
|
decoration: InputDecoration(
|
||||||
style: flatButtonStyle,
|
labelText: translate(
|
||||||
onPressed: () {
|
"Please enter the folder name"),
|
||||||
if (name.value.text.isNotEmpty) {
|
),
|
||||||
model.createDir(
|
controller: name,
|
||||||
PathUtil.join(
|
focusNode: FocusNode()..requestFocus(),
|
||||||
model
|
),
|
||||||
.getCurrentDir(
|
],
|
||||||
isLocal)
|
),
|
||||||
.path,
|
actions: [
|
||||||
name.value.text,
|
TextButton(
|
||||||
model.getCurrentIsWindows(
|
style: flatButtonStyle,
|
||||||
isLocal)),
|
onPressed: cancel,
|
||||||
isLocal: isLocal);
|
child: Text(translate("Cancel"))),
|
||||||
close();
|
ElevatedButton(
|
||||||
}
|
style: flatButtonStyle,
|
||||||
},
|
onPressed: submit,
|
||||||
child: Text(translate("OK")))
|
child: Text(translate("OK")))
|
||||||
]));
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: cancel,
|
||||||
|
);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.create_new_folder_outlined)),
|
icon: const Icon(Icons.create_new_folder_outlined)),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final items = isLocal
|
final items = isLocal
|
||||||
|
|||||||
@@ -70,38 +70,45 @@ class _PortForwardPageState extends State<PortForwardPage>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
return Scaffold(
|
return Overlay(initialEntries: [
|
||||||
backgroundColor: MyTheme.color(context).grayBg,
|
OverlayEntry(builder: (context) {
|
||||||
body: FutureBuilder(future: () async {
|
_ffi.dialogManager.setOverlayState(Overlay.of(context));
|
||||||
if (!isRdp) {
|
return Scaffold(
|
||||||
refreshTunnelConfig();
|
backgroundColor: MyTheme.color(context).grayBg,
|
||||||
}
|
body: FutureBuilder(future: () async {
|
||||||
}(), builder: (context, snapshot) {
|
if (!isRdp) {
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
refreshTunnelConfig();
|
||||||
return Container(
|
}
|
||||||
decoration: BoxDecoration(
|
}(), builder: (context, snapshot) {
|
||||||
border: Border.all(
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
width: 20, color: MyTheme.color(context).grayBg!)),
|
return Container(
|
||||||
child: Column(
|
decoration: BoxDecoration(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
border: Border.all(
|
||||||
children: [
|
width: 20, color: MyTheme.color(context).grayBg!)),
|
||||||
buildPrompt(context),
|
child: Column(
|
||||||
Flexible(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
child: Container(
|
children: [
|
||||||
decoration: BoxDecoration(
|
buildPrompt(context),
|
||||||
color: MyTheme.color(context).bg,
|
Flexible(
|
||||||
border: Border.all(width: 1, color: MyTheme.border)),
|
child: Container(
|
||||||
child:
|
decoration: BoxDecoration(
|
||||||
widget.isRDP ? buildRdp(context) : buildTunnel(context),
|
color: MyTheme.color(context).bg,
|
||||||
),
|
border:
|
||||||
|
Border.all(width: 1, color: MyTheme.border)),
|
||||||
|
child: widget.isRDP
|
||||||
|
? buildRdp(context)
|
||||||
|
: buildTunnel(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
),
|
}
|
||||||
);
|
return const Offstage();
|
||||||
}
|
}),
|
||||||
return const Offstage();
|
);
|
||||||
}),
|
})
|
||||||
);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildPrompt(BuildContext context) {
|
buildPrompt(BuildContext context) {
|
||||||
|
|||||||
@@ -563,47 +563,47 @@ abstract class BasePeerCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
isInProgress.value = true;
|
||||||
|
name = controller.text;
|
||||||
|
await bind.mainSetPeerOption(id: id, key: 'alias', value: name);
|
||||||
|
if (isAddressBook) {
|
||||||
|
gFFI.abModel.setPeerOption(id, 'alias', name);
|
||||||
|
await gFFI.abModel.updateAb();
|
||||||
|
}
|
||||||
|
alias.value = await bind.mainGetPeerOption(id: peer.id, key: 'alias');
|
||||||
|
close();
|
||||||
|
isInProgress.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate('Rename')),
|
title: Text(translate('Rename')),
|
||||||
content: Column(
|
content: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
child: Form(
|
child: Form(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
decoration: InputDecoration(border: OutlineInputBorder()),
|
focusNode: FocusNode()..requestFocus(),
|
||||||
|
decoration:
|
||||||
|
const InputDecoration(border: OutlineInputBorder()),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Obx(() => Offstage(
|
Obx(() => Offstage(
|
||||||
offstage: isInProgress.isFalse,
|
offstage: isInProgress.isFalse,
|
||||||
child: LinearProgressIndicator())),
|
child: const LinearProgressIndicator())),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
isInProgress.value = true;
|
|
||||||
name = controller.text;
|
|
||||||
await bind.mainSetPeerOption(id: id, key: 'alias', value: name);
|
|
||||||
if (isAddressBook) {
|
|
||||||
gFFI.abModel.setPeerOption(id, 'alias', name);
|
|
||||||
await gFFI.abModel.updateAb();
|
|
||||||
}
|
|
||||||
alias.value =
|
|
||||||
await bind.mainGetPeerOption(id: peer.id, key: 'alias');
|
|
||||||
close();
|
|
||||||
isInProgress.value = false;
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -750,13 +750,23 @@ class AddressBookPeerCard extends BasePeerCard {
|
|||||||
var selectedTag = gFFI.abModel.getPeerTags(id).obs;
|
var selectedTag = gFFI.abModel.getPeerTags(id).obs;
|
||||||
|
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
setState(() {
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
gFFI.abModel.changeTagForPeer(id, selectedTag);
|
||||||
|
await gFFI.abModel.updateAb();
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Edit Tag")),
|
title: Text(translate("Edit Tag")),
|
||||||
content: Column(
|
content: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: tags
|
children: tags
|
||||||
.map((e) => _buildTag(e, selectedTag, onTap: () {
|
.map((e) => _buildTag(e, selectedTag, onTap: () {
|
||||||
@@ -769,26 +779,16 @@ class AddressBookPeerCard extends BasePeerCard {
|
|||||||
.toList(growable: false),
|
.toList(growable: false),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
|
Offstage(
|
||||||
|
offstage: !isInProgress, child: const LinearProgressIndicator())
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
isInProgress = true;
|
|
||||||
});
|
|
||||||
gFFI.abModel.changeTagForPeer(id, selectedTag);
|
|
||||||
await gFFI.abModel.updateAb();
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -871,25 +871,35 @@ void _rdpDialog(String id) async {
|
|||||||
RxBool secure = true.obs;
|
RxBool secure = true.obs;
|
||||||
|
|
||||||
gFFI.dialogManager.show((setState, close) {
|
gFFI.dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
await bind.mainSetPeerOption(
|
||||||
|
id: id, key: 'rdp_port', value: portController.text.trim());
|
||||||
|
await bind.mainSetPeerOption(
|
||||||
|
id: id, key: 'rdp_username', value: userController.text);
|
||||||
|
await bind.mainSetPeerOption(
|
||||||
|
id: id, key: 'rdp_password', value: passwordContorller.text);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text('RDP ' + translate('Settings')),
|
title: Text('RDP ${translate('Settings')}'),
|
||||||
content: ConstrainedBox(
|
content: ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 500),
|
constraints: const BoxConstraints(minWidth: 500),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text(
|
child: Text(
|
||||||
"${translate('Port')}:",
|
"${translate('Port')}:",
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
).marginOnly(bottom: 16.0)),
|
).marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -898,52 +908,54 @@ void _rdpDialog(String id) async {
|
|||||||
FilteringTextInputFormatter.allow(RegExp(
|
FilteringTextInputFormatter.allow(RegExp(
|
||||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$'))
|
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$'))
|
||||||
],
|
],
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(), hintText: '3389'),
|
border: OutlineInputBorder(), hintText: '3389'),
|
||||||
controller: portController,
|
controller: portController,
|
||||||
|
focusNode: FocusNode()..requestFocus(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text(
|
child: Text(
|
||||||
"${translate('Username')}:",
|
"${translate('Username')}:",
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
).marginOnly(bottom: 16.0)),
|
).marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
decoration: InputDecoration(border: OutlineInputBorder()),
|
decoration:
|
||||||
|
const InputDecoration(border: OutlineInputBorder()),
|
||||||
controller: userController,
|
controller: userController,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 8.0,
|
height: 8.0,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: 100),
|
constraints: const BoxConstraints(minWidth: 100),
|
||||||
child: Text("${translate('Password')}:")
|
child: Text("${translate('Password')}:")
|
||||||
.marginOnly(bottom: 16.0)),
|
.marginOnly(bottom: 16.0)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 24.0,
|
width: 24.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Obx(() => TextField(
|
child: Obx(() => TextField(
|
||||||
obscureText: secure.value,
|
obscureText: secure.value,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
onPressed: () => secure.value = !secure.value,
|
onPressed: () => secure.value = !secure.value,
|
||||||
icon: Icon(secure.value
|
icon: Icon(secure.value
|
||||||
@@ -958,23 +970,11 @@ void _rdpDialog(String id) async {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
onPressed: () {
|
TextButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await bind.mainSetPeerOption(
|
|
||||||
id: id, key: 'rdp_port', value: portController.text.trim());
|
|
||||||
await bind.mainSetPeerOption(
|
|
||||||
id: id, key: 'rdp_username', value: userController.text);
|
|
||||||
await bind.mainSetPeerOption(
|
|
||||||
id: id, key: 'rdp_password', value: passwordContorller.text);
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
child: Text(translate("OK"))),
|
|
||||||
],
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -596,46 +596,49 @@ void showSetOSPassword(
|
|||||||
var autoLogin = await bind.sessionGetOption(id: id, arg: "auto-login") != "";
|
var autoLogin = await bind.sessionGetOption(id: id, arg: "auto-login") != "";
|
||||||
controller.text = password;
|
controller.text = password;
|
||||||
dialogManager.show((setState, close) {
|
dialogManager.show((setState, close) {
|
||||||
|
submit() {
|
||||||
|
var text = controller.text.trim();
|
||||||
|
bind.sessionPeerOption(id: id, name: "os-password", value: text);
|
||||||
|
bind.sessionPeerOption(
|
||||||
|
id: id, name: "auto-login", value: autoLogin ? 'Y' : '');
|
||||||
|
if (text != "" && login) {
|
||||||
|
bind.sessionInputOsPassword(id: id, value: text);
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate('OS Password')),
|
title: Text(translate('OS Password')),
|
||||||
content: Column(mainAxisSize: MainAxisSize.min, children: [
|
content: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
PasswordWidget(controller: controller),
|
PasswordWidget(controller: controller),
|
||||||
CheckboxListTile(
|
CheckboxListTile(
|
||||||
contentPadding: const EdgeInsets.all(0),
|
contentPadding: const EdgeInsets.all(0),
|
||||||
dense: true,
|
dense: true,
|
||||||
controlAffinity: ListTileControlAffinity.leading,
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
title: Text(
|
title: Text(
|
||||||
translate('Auto Login'),
|
translate('Auto Login'),
|
||||||
),
|
|
||||||
value: autoLogin,
|
|
||||||
onChanged: (v) {
|
|
||||||
if (v == null) return;
|
|
||||||
setState(() => autoLogin = v);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
]),
|
value: autoLogin,
|
||||||
actions: [
|
onChanged: (v) {
|
||||||
TextButton(
|
if (v == null) return;
|
||||||
style: flatButtonStyle,
|
setState(() => autoLogin = v);
|
||||||
onPressed: () {
|
},
|
||||||
close();
|
),
|
||||||
},
|
]),
|
||||||
child: Text(translate('Cancel')),
|
actions: [
|
||||||
),
|
TextButton(
|
||||||
TextButton(
|
style: flatButtonStyle,
|
||||||
style: flatButtonStyle,
|
onPressed: close,
|
||||||
onPressed: () {
|
child: Text(translate('Cancel')),
|
||||||
var text = controller.text.trim();
|
),
|
||||||
bind.sessionPeerOption(id: id, name: "os-password", value: text);
|
TextButton(
|
||||||
bind.sessionPeerOption(
|
style: flatButtonStyle,
|
||||||
id: id, name: "auto-login", value: autoLogin ? 'Y' : '');
|
onPressed: submit,
|
||||||
if (text != "" && login) {
|
child: Text(translate('OK')),
|
||||||
bind.sessionInputOsPassword(id: id, value: text);
|
),
|
||||||
}
|
],
|
||||||
close();
|
onSubmit: submit,
|
||||||
},
|
onCancel: close,
|
||||||
child: Text(translate('OK')),
|
);
|
||||||
),
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -462,22 +462,24 @@ class WindowActionPanel extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
closeConfirmDialog(Function() callback) async {
|
closeConfirmDialog(Function() callback) async {
|
||||||
final res = await gFFI.dialogManager
|
final res = await gFFI.dialogManager.show<bool>((setState, close) {
|
||||||
.show<bool>((setState, close) => CustomAlertDialog(
|
submit() => close(true);
|
||||||
title: Row(children: [
|
return CustomAlertDialog(
|
||||||
Icon(Icons.warning_amber_sharp,
|
title: Row(children: [
|
||||||
color: Colors.redAccent, size: 28),
|
const Icon(Icons.warning_amber_sharp,
|
||||||
SizedBox(width: 10),
|
color: Colors.redAccent, size: 28),
|
||||||
Text(translate("Warning")),
|
const SizedBox(width: 10),
|
||||||
]),
|
Text(translate("Warning")),
|
||||||
content: Text(translate("Disconnect all devices?")),
|
]),
|
||||||
actions: [
|
content: Text(translate("Disconnect all devices?")),
|
||||||
TextButton(
|
actions: [
|
||||||
onPressed: () => close(), child: Text(translate("Cancel"))),
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
ElevatedButton(
|
ElevatedButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
onPressed: () => close(true), child: Text(translate("OK"))),
|
],
|
||||||
],
|
onSubmit: submit,
|
||||||
));
|
onCancel: close,
|
||||||
|
);
|
||||||
|
});
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -559,49 +559,55 @@ class FileModel extends ChangeNotifier {
|
|||||||
Future<bool?> showRemoveDialog(
|
Future<bool?> showRemoveDialog(
|
||||||
String title, String content, bool showCheckbox) async {
|
String title, String content, bool showCheckbox) async {
|
||||||
return await parent.target?.dialogManager.show<bool>(
|
return await parent.target?.dialogManager.show<bool>(
|
||||||
(setState, Function(bool v) close) => CustomAlertDialog(
|
(setState, Function(bool v) close) {
|
||||||
title: Row(
|
cancel() => close(false);
|
||||||
children: [
|
submit() => close(true);
|
||||||
Icon(Icons.warning, color: Colors.red),
|
return CustomAlertDialog(
|
||||||
SizedBox(width: 20),
|
title: Row(
|
||||||
Text(title)
|
children: [
|
||||||
],
|
const Icon(Icons.warning, color: Colors.red),
|
||||||
),
|
const SizedBox(width: 20),
|
||||||
content: Column(
|
Text(title)
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
),
|
||||||
children: [
|
content: Column(
|
||||||
Text(content),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
SizedBox(height: 5),
|
mainAxisSize: MainAxisSize.min,
|
||||||
Text(translate("This is irreversible!"),
|
children: [
|
||||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
Text(content),
|
||||||
showCheckbox
|
const SizedBox(height: 5),
|
||||||
? CheckboxListTile(
|
Text(translate("This is irreversible!"),
|
||||||
contentPadding: const EdgeInsets.all(0),
|
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||||
dense: true,
|
showCheckbox
|
||||||
controlAffinity: ListTileControlAffinity.leading,
|
? CheckboxListTile(
|
||||||
title: Text(
|
contentPadding: const EdgeInsets.all(0),
|
||||||
translate("Do this for all conflicts"),
|
dense: true,
|
||||||
),
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
value: removeCheckboxRemember,
|
title: Text(
|
||||||
onChanged: (v) {
|
translate("Do this for all conflicts"),
|
||||||
if (v == null) return;
|
),
|
||||||
setState(() => removeCheckboxRemember = v);
|
value: removeCheckboxRemember,
|
||||||
},
|
onChanged: (v) {
|
||||||
)
|
if (v == null) return;
|
||||||
: SizedBox.shrink()
|
setState(() => removeCheckboxRemember = v);
|
||||||
]),
|
},
|
||||||
actions: [
|
)
|
||||||
TextButton(
|
: const SizedBox.shrink()
|
||||||
style: flatButtonStyle,
|
]),
|
||||||
onPressed: () => close(false),
|
actions: [
|
||||||
child: Text(translate("Cancel"))),
|
TextButton(
|
||||||
TextButton(
|
style: flatButtonStyle,
|
||||||
style: flatButtonStyle,
|
onPressed: cancel,
|
||||||
onPressed: () => close(true),
|
child: Text(translate("Cancel"))),
|
||||||
child: Text(translate("OK"))),
|
TextButton(
|
||||||
]),
|
style: flatButtonStyle,
|
||||||
useAnimation: false);
|
onPressed: submit,
|
||||||
|
child: Text(translate("OK"))),
|
||||||
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: cancel,
|
||||||
|
);
|
||||||
|
}, useAnimation: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fileConfirmCheckboxRemember = false;
|
bool fileConfirmCheckboxRemember = false;
|
||||||
@@ -610,55 +616,59 @@ class FileModel extends ChangeNotifier {
|
|||||||
String title, String content, bool showCheckbox) async {
|
String title, String content, bool showCheckbox) async {
|
||||||
fileConfirmCheckboxRemember = false;
|
fileConfirmCheckboxRemember = false;
|
||||||
return await parent.target?.dialogManager.show<bool?>(
|
return await parent.target?.dialogManager.show<bool?>(
|
||||||
(setState, Function(bool? v) close) => CustomAlertDialog(
|
(setState, Function(bool? v) close) {
|
||||||
title: Row(
|
cancel() => close(false);
|
||||||
children: [
|
submit() => close(true);
|
||||||
Icon(Icons.warning, color: Colors.red),
|
return CustomAlertDialog(
|
||||||
SizedBox(width: 20),
|
title: Row(
|
||||||
Text(title)
|
children: [
|
||||||
],
|
const Icon(Icons.warning, color: Colors.red),
|
||||||
),
|
const SizedBox(width: 20),
|
||||||
content: Column(
|
Text(title)
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
),
|
||||||
children: [
|
content: Column(
|
||||||
Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
translate(
|
mainAxisSize: MainAxisSize.min,
|
||||||
"This file exists, skip or overwrite this file?"),
|
children: [
|
||||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
Text(translate("This file exists, skip or overwrite this file?"),
|
||||||
SizedBox(height: 5),
|
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||||
Text(content),
|
const SizedBox(height: 5),
|
||||||
showCheckbox
|
Text(content),
|
||||||
? CheckboxListTile(
|
showCheckbox
|
||||||
contentPadding: const EdgeInsets.all(0),
|
? CheckboxListTile(
|
||||||
dense: true,
|
contentPadding: const EdgeInsets.all(0),
|
||||||
controlAffinity: ListTileControlAffinity.leading,
|
dense: true,
|
||||||
title: Text(
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
translate("Do this for all conflicts"),
|
title: Text(
|
||||||
),
|
translate("Do this for all conflicts"),
|
||||||
value: fileConfirmCheckboxRemember,
|
),
|
||||||
onChanged: (v) {
|
value: fileConfirmCheckboxRemember,
|
||||||
if (v == null) return;
|
onChanged: (v) {
|
||||||
setState(() => fileConfirmCheckboxRemember = v);
|
if (v == null) return;
|
||||||
},
|
setState(() => fileConfirmCheckboxRemember = v);
|
||||||
)
|
},
|
||||||
: SizedBox.shrink()
|
)
|
||||||
]),
|
: const SizedBox.shrink()
|
||||||
actions: [
|
]),
|
||||||
TextButton(
|
actions: [
|
||||||
style: flatButtonStyle,
|
TextButton(
|
||||||
onPressed: () => close(false),
|
style: flatButtonStyle,
|
||||||
child: Text(translate("Cancel"))),
|
onPressed: cancel,
|
||||||
TextButton(
|
child: Text(translate("Cancel"))),
|
||||||
style: flatButtonStyle,
|
TextButton(
|
||||||
onPressed: () => close(null),
|
style: flatButtonStyle,
|
||||||
child: Text(translate("Skip"))),
|
onPressed: () => close(null),
|
||||||
TextButton(
|
child: Text(translate("Skip"))),
|
||||||
style: flatButtonStyle,
|
TextButton(
|
||||||
onPressed: () => close(true),
|
style: flatButtonStyle,
|
||||||
child: Text(translate("OK"))),
|
onPressed: submit,
|
||||||
]),
|
child: Text(translate("OK"))),
|
||||||
useAnimation: false);
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: cancel,
|
||||||
|
);
|
||||||
|
}, useAnimation: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendRemoveFile(String path, int fileNum, bool isLocal) {
|
sendRemoveFile(String path, int fileNum, bool isLocal) {
|
||||||
|
|||||||
@@ -209,46 +209,48 @@ class ServerModel with ChangeNotifier {
|
|||||||
/// Toggle the screen sharing service.
|
/// Toggle the screen sharing service.
|
||||||
toggleService() async {
|
toggleService() async {
|
||||||
if (_isStart) {
|
if (_isStart) {
|
||||||
final res = await parent.target?.dialogManager
|
final res =
|
||||||
.show<bool>((setState, close) => CustomAlertDialog(
|
await parent.target?.dialogManager.show<bool>((setState, close) {
|
||||||
title: Row(children: [
|
submit() => close(true);
|
||||||
Icon(Icons.warning_amber_sharp,
|
return CustomAlertDialog(
|
||||||
color: Colors.redAccent, size: 28),
|
title: Row(children: [
|
||||||
SizedBox(width: 10),
|
const Icon(Icons.warning_amber_sharp,
|
||||||
Text(translate("Warning")),
|
color: Colors.redAccent, size: 28),
|
||||||
]),
|
const SizedBox(width: 10),
|
||||||
content: Text(translate("android_stop_service_tip")),
|
Text(translate("Warning")),
|
||||||
actions: [
|
]),
|
||||||
TextButton(
|
content: Text(translate("android_stop_service_tip")),
|
||||||
onPressed: () => close(),
|
actions: [
|
||||||
child: Text(translate("Cancel"))),
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
ElevatedButton(
|
ElevatedButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
onPressed: () => close(true),
|
],
|
||||||
child: Text(translate("OK"))),
|
onSubmit: submit,
|
||||||
],
|
onCancel: close,
|
||||||
));
|
);
|
||||||
|
});
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
stopService();
|
stopService();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final res = await parent.target?.dialogManager
|
final res =
|
||||||
.show<bool>((setState, close) => CustomAlertDialog(
|
await parent.target?.dialogManager.show<bool>((setState, close) {
|
||||||
title: Row(children: [
|
submit() => close(true);
|
||||||
Icon(Icons.warning_amber_sharp,
|
return CustomAlertDialog(
|
||||||
color: Colors.redAccent, size: 28),
|
title: Row(children: [
|
||||||
SizedBox(width: 10),
|
const Icon(Icons.warning_amber_sharp,
|
||||||
Text(translate("Warning")),
|
color: Colors.redAccent, size: 28),
|
||||||
]),
|
const SizedBox(width: 10),
|
||||||
content: Text(translate("android_service_will_start_tip")),
|
Text(translate("Warning")),
|
||||||
actions: [
|
]),
|
||||||
TextButton(
|
content: Text(translate("android_service_will_start_tip")),
|
||||||
onPressed: () => close(),
|
actions: [
|
||||||
child: Text(translate("Cancel"))),
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
ElevatedButton(
|
ElevatedButton(onPressed: submit, child: Text(translate("OK"))),
|
||||||
onPressed: () => close(true),
|
],
|
||||||
child: Text(translate("OK"))),
|
onSubmit: submit,
|
||||||
],
|
onCancel: close,
|
||||||
));
|
);
|
||||||
|
});
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
startService();
|
startService();
|
||||||
}
|
}
|
||||||
@@ -388,49 +390,49 @@ class ServerModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showLoginDialog(Client client) {
|
void showLoginDialog(Client client) {
|
||||||
parent.target?.dialogManager.show(
|
parent.target?.dialogManager.show((setState, close) {
|
||||||
(setState, close) => CustomAlertDialog(
|
cancel() {
|
||||||
title: Row(
|
sendLoginResponse(client, false);
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
close();
|
||||||
children: [
|
}
|
||||||
Text(translate(client.isFileTransfer
|
|
||||||
? "File Connection"
|
submit() {
|
||||||
: "Screen Connection")),
|
sendLoginResponse(client, true);
|
||||||
IconButton(
|
close();
|
||||||
onPressed: () {
|
}
|
||||||
close();
|
|
||||||
},
|
return CustomAlertDialog(
|
||||||
icon: Icon(Icons.close))
|
title:
|
||||||
]),
|
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
content: Column(
|
Text(translate(
|
||||||
mainAxisSize: MainAxisSize.min,
|
client.isFileTransfer ? "File Connection" : "Screen Connection")),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
IconButton(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
onPressed: () {
|
||||||
children: [
|
close();
|
||||||
Text(translate("Do you accept?")),
|
},
|
||||||
clientInfo(client),
|
icon: const Icon(Icons.close))
|
||||||
Text(
|
]),
|
||||||
translate("android_new_connection_tip"),
|
content: Column(
|
||||||
style: TextStyle(color: Colors.black54),
|
mainAxisSize: MainAxisSize.min,
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
],
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
),
|
children: [
|
||||||
actions: [
|
Text(translate("Do you accept?")),
|
||||||
TextButton(
|
clientInfo(client),
|
||||||
child: Text(translate("Dismiss")),
|
Text(
|
||||||
onPressed: () {
|
translate("android_new_connection_tip"),
|
||||||
sendLoginResponse(client, false);
|
style: const TextStyle(color: Colors.black54),
|
||||||
close();
|
|
||||||
}),
|
|
||||||
ElevatedButton(
|
|
||||||
child: Text(translate("Accept")),
|
|
||||||
onPressed: () {
|
|
||||||
sendLoginResponse(client, true);
|
|
||||||
close();
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
tag: getLoginDialogTag(client.id));
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(onPressed: cancel, child: Text(translate("Dismiss"))),
|
||||||
|
ElevatedButton(onPressed: submit, child: Text(translate("Accept"))),
|
||||||
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: cancel,
|
||||||
|
);
|
||||||
|
}, tag: getLoginDialogTag(client.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollToBottom() {
|
scrollToBottom() {
|
||||||
@@ -563,24 +565,29 @@ String getLoginDialogTag(int id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showInputWarnAlert(FFI ffi) {
|
showInputWarnAlert(FFI ffi) {
|
||||||
ffi.dialogManager.show((setState, close) => CustomAlertDialog(
|
ffi.dialogManager.show((setState, close) {
|
||||||
title: Text(translate("How to get Android input permission?")),
|
submit() {
|
||||||
content: Column(
|
ffi.serverModel.initInput();
|
||||||
mainAxisSize: MainAxisSize.min,
|
close();
|
||||||
children: [
|
}
|
||||||
Text(translate("android_input_permission_tip1")),
|
|
||||||
SizedBox(height: 10),
|
return CustomAlertDialog(
|
||||||
Text(translate("android_input_permission_tip2")),
|
title: Text(translate("How to get Android input permission?")),
|
||||||
],
|
content: Column(
|
||||||
),
|
mainAxisSize: MainAxisSize.min,
|
||||||
actions: [
|
children: [
|
||||||
TextButton(child: Text(translate("Cancel")), onPressed: close),
|
Text(translate("android_input_permission_tip1")),
|
||||||
ElevatedButton(
|
const SizedBox(height: 10),
|
||||||
child: Text(translate("Open System Setting")),
|
Text(translate("android_input_permission_tip2")),
|
||||||
onPressed: () {
|
|
||||||
ffi.serverModel.initInput();
|
|
||||||
close();
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
));
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(onPressed: close, child: Text(translate("Cancel"))),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: submit, child: Text(translate("Open System Setting"))),
|
||||||
|
],
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: close,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user