dialog focus && deal with Enter/Esc key

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages
2022-09-03 18:19:50 +08:00
parent 1b56304d9a
commit a553334157
12 changed files with 959 additions and 859 deletions

View File

@@ -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();
// request focus if there is no focused FocusNode in the dialog
Future.delayed(Duration.zero, () {
if (!focusNode.hasFocus) focusNode.requestFocus();
});
return Focus(
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, scrollable: true,
title: title, title: title,
contentPadding: contentPadding: EdgeInsets.symmetric(
EdgeInsets.symmetric(horizontal: contentPadding ?? 25, vertical: 10), horizontal: contentPadding ?? 25, vertical: 10),
content: content, content: content,
actions: actions, actions: actions,
),
); );
} }
} }
@@ -429,26 +468,28 @@ void msgBox(
{bool? hasCancel}) { {bool? hasCancel}) {
dialogManager.dismissAll(); dialogManager.dismissAll();
List<Widget> buttons = []; List<Widget> buttons = [];
if (type != "connecting" && type != "success" && !type.contains("nook")) { bool hasOk = false;
buttons.insert( submit() {
0,
msgBoxButton(translate('OK'), () {
dialogManager.dismissAll(); dialogManager.dismissAll();
// https://github.com/fufesou/rustdesk/blob/5e9a31340b899822090a3731769ae79c6bf5f3e5/src/ui/common.tis#L263 // https://github.com/fufesou/rustdesk/blob/5e9a31340b899822090a3731769ae79c6bf5f3e5/src/ui/common.tis#L263
if (!type.contains("custom")) { if (!type.contains("custom")) {
closeConnection(); closeConnection();
} }
})); }
cancel() {
dialogManager.dismissAll();
}
if (type != "connecting" && type != "success" && !type.contains("nook")) {
hasOk = true;
buttons.insert(0, msgBoxButton(translate('OK'), submit));
} }
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")) {
@@ -460,8 +501,11 @@ 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]) {

View File

@@ -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,52 +668,15 @@ 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) {
return CustomAlertDialog( submit() async {
title: Text(translate("Add ID")),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("whitelist_sep")),
SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: TextField(
onChanged: (s) {
field = s;
},
maxLines: null,
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg),
),
controller: TextEditingController(text: field),
),
),
],
),
SizedBox(
height: 4.0,
),
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
],
),
actions: [
TextButton(
onPressed: () {
close();
},
child: Text(translate("Cancel"))),
TextButton(
onPressed: () async {
setState(() { setState(() {
msg = ""; msg = "";
isInProgress = true; isInProgress = true;
}); });
field = field.trim(); field = controller.text.trim();
if (field.isEmpty) { if (field.isEmpty) {
// pass // pass
} else { } else {
@@ -723,9 +693,44 @@ class _ConnectionPageState extends State<ConnectionPage> {
// final currentPeers // final currentPeers
} }
close(); close();
}, }
child: Text(translate("OK"))),
return CustomAlertDialog(
title: Text(translate("Add ID")),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("whitelist_sep")),
const SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: TextField(
maxLines: null,
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg),
),
controller: controller,
focusNode: FocusNode()..requestFocus()),
),
], ],
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, child: Text(translate("OK"))),
],
onSubmit: submit,
onCancel: close,
); );
}); });
} }
@@ -734,52 +739,14 @@ 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) {
return CustomAlertDialog( submit() async {
title: Text(translate("Add Tag")),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("whitelist_sep")),
SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: TextField(
onChanged: (s) {
field = s;
},
maxLines: null,
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg),
),
controller: TextEditingController(text: field),
),
),
],
),
SizedBox(
height: 4.0,
),
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
],
),
actions: [
TextButton(
onPressed: () {
close();
},
child: Text(translate("Cancel"))),
TextButton(
onPressed: () async {
setState(() { setState(() {
msg = ""; msg = "";
isInProgress = true; isInProgress = true;
}); });
field = field.trim(); field = controller.text.trim();
if (field.isEmpty) { if (field.isEmpty) {
// pass // pass
} else { } else {
@@ -792,9 +759,45 @@ class _ConnectionPageState extends State<ConnectionPage> {
// final currentPeers // final currentPeers
} }
close(); close();
}, }
child: Text(translate("OK"))),
return CustomAlertDialog(
title: Text(translate("Add Tag")),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("whitelist_sep")),
const SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: TextField(
maxLines: null,
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg),
),
controller: controller,
focusNode: FocusNode()..requestFocus(),
),
),
], ],
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, 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,
); );
}); });
} }

View File

@@ -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,53 +642,10 @@ 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) {
return CustomAlertDialog( submit() async {
title: Text(translate("Change ID")), newId = controller.text.trim();
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("id_change_tip")),
SizedBox(
height: 8.0,
),
Row(
children: [
Text("ID:").marginOnly(bottom: 16.0),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
onChanged: (s) {
newId = s;
},
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg)),
inputFormatters: [
LengthLimitingTextInputFormatter(16),
// FilteringTextInputFormatter(RegExp(r"[a-zA-z][a-zA-z0-9\_]*"), allow: true)
],
maxLength: 16,
),
),
],
),
SizedBox(
height: 4.0,
),
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
],
),
actions: [
TextButton(
onPressed: () {
close();
},
child: Text(translate("Cancel"))),
TextButton(
onPressed: () async {
setState(() { setState(() {
msg = ""; msg = "";
isInProgress = true; isInProgress = true;
@@ -697,7 +654,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
var status = await bind.mainGetAsyncStatus(); var status = await bind.mainGetAsyncStatus();
while (status == " ") { while (status == " ") {
await Future.delayed(Duration(milliseconds: 100)); await Future.delayed(const Duration(milliseconds: 100));
status = await bind.mainGetAsyncStatus(); status = await bind.mainGetAsyncStatus();
} }
if (status.isEmpty) { if (status.isEmpty) {
@@ -709,9 +666,52 @@ class _DesktopHomePageState extends State<DesktopHomePage>
isInProgress = false; isInProgress = false;
msg = translate(status); msg = translate(status);
}); });
}, }
child: Text(translate("OK"))),
return CustomAlertDialog(
title: Text(translate("Change ID")),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("id_change_tip")),
const SizedBox(
height: 8.0,
),
Row(
children: [
const Text("ID:").marginOnly(bottom: 16.0),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg)),
inputFormatters: [
LengthLimitingTextInputFormatter(16),
// FilteringTextInputFormatter(RegExp(r"[a-zA-z][a-zA-z0-9\_]*"), allow: true)
], ],
maxLength: 16,
controller: controller,
focusNode: FocusNode()..requestFocus(),
),
),
],
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, 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 &copy; 2022 Purslane Ltd.\n$license", "Copyright &copy; 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,86 +814,18 @@ 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) {
return CustomAlertDialog( submit() async {
title: Text(translate("Login")),
content: ConstrainedBox(
constraints: BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text(
"${translate('Username')}:",
textAlign: TextAlign.start,
).marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: userNameMsg.isNotEmpty ? userNameMsg : null),
controller: userContontroller,
),
),
],
),
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text("${translate('Password')}:")
.marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: passMsg.isNotEmpty ? passMsg : null),
controller: pwdController,
),
),
],
),
SizedBox(
height: 4.0,
),
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
],
),
),
actions: [
TextButton(
onPressed: () {
completer.complete(false);
close();
},
child: Text(translate("Cancel"))),
TextButton(
onPressed: () async {
setState(() { setState(() {
userNameMsg = ""; userNameMsg = "";
passMsg = ""; passMsg = "";
isInProgress = true; isInProgress = true;
}); });
final cancel = () { cancel() {
setState(() { setState(() {
isInProgress = false; isInProgress = false;
}); });
}; }
userName = userContontroller.text; userName = userContontroller.text;
pass = pwdController.text; pass = pwdController.text;
if (userName.isEmpty) { if (userName.isEmpty) {
@@ -919,14 +850,88 @@ Future<bool> loginDialog() async {
debugPrint("$resp"); debugPrint("$resp");
completer.complete(true); completer.complete(true);
} catch (err) { } catch (err) {
// ignore: avoid_print
print(err.toString()); print(err.toString());
cancel(); cancel();
return; return;
} }
close(); close();
}, }
child: Text(translate("OK"))),
cancel() {
completer.complete(false);
close();
}
return CustomAlertDialog(
title: Text(translate("Login")),
content: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text(
"${translate('Username')}:",
textAlign: TextAlign.start,
).marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: userNameMsg.isNotEmpty ? userNameMsg : null),
controller: userContontroller,
focusNode: FocusNode()..requestFocus(),
),
),
], ],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('Password')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: passMsg.isNotEmpty ? passMsg : null),
controller: pwdController,
),
),
],
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
),
actions: [
TextButton(onPressed: cancel, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, child: Text(translate("OK"))),
],
onSubmit: submit,
onCancel: cancel,
); );
}); });
return completer.future; return completer.future;
@@ -940,72 +945,7 @@ void setPasswordDialog() async {
var errMsg1 = ""; var errMsg1 = "";
gFFI.dialogManager.show((setState, close) { gFFI.dialogManager.show((setState, close) {
return CustomAlertDialog( submit() {
title: Text(translate("Set Password")),
content: ConstrainedBox(
constraints: BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text(
"${translate('Password')}:",
textAlign: TextAlign.start,
).marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: errMsg0.isNotEmpty ? errMsg0 : null),
controller: p0,
),
),
],
),
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text("${translate('Confirmation')}:")
.marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: errMsg1.isNotEmpty ? errMsg1 : null),
controller: p1,
),
),
],
),
],
),
),
actions: [
TextButton(
onPressed: () {
close();
},
child: Text(translate("Cancel"))),
TextButton(
onPressed: () {
setState(() { setState(() {
errMsg0 = ""; errMsg0 = "";
errMsg1 = ""; errMsg1 = "";
@@ -1025,9 +965,73 @@ void setPasswordDialog() async {
} }
bind.mainSetPermanentPassword(password: pass); bind.mainSetPermanentPassword(password: pass);
close(); close();
}, }
child: Text(translate("OK"))),
return CustomAlertDialog(
title: Text(translate("Set Password")),
content: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text(
"${translate('Password')}:",
textAlign: TextAlign.start,
).marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: errMsg0.isNotEmpty ? errMsg0 : null),
controller: p0,
focusNode: FocusNode()..requestFocus(),
),
),
], ],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('Confirmation')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: errMsg1.isNotEmpty ? errMsg1 : null),
controller: p1,
),
),
],
),
],
),
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, child: Text(translate("OK"))),
],
onSubmit: submit,
onCancel: close,
); );
}); });
} }

View File

@@ -1038,138 +1038,29 @@ 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) {
return CustomAlertDialog( submit() async {
title: Text(translate("ID/Relay Server")),
content: ConstrainedBox(
constraints: BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text("${translate('ID Server')}:")
.marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: idServerMsg.isNotEmpty ? idServerMsg : null),
controller: idController,
),
),
],
),
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text("${translate('Relay Server')}:")
.marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText:
relayServerMsg.isNotEmpty ? relayServerMsg : null),
controller: relayController,
),
),
],
),
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text("${translate('API Server')}:")
.marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText:
apiServerMsg.isNotEmpty ? apiServerMsg : null),
controller: apiController,
),
),
],
),
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child:
Text("${translate('Key')}:").marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
),
controller: keyController,
),
),
],
),
SizedBox(
height: 4.0,
),
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
],
),
),
actions: [
TextButton(
onPressed: () {
close();
},
child: Text(translate("Cancel"))),
TextButton(
onPressed: () async {
setState(() { setState(() {
[idServerMsg, relayServerMsg, apiServerMsg].forEach((element) { [idServerMsg, relayServerMsg, apiServerMsg].forEach((element) {
element = ""; element = "";
}); });
isInProgress = true; isInProgress = true;
}); });
final cancel = () { cancel() {
setState(() { setState(() {
isInProgress = false; isInProgress = false;
}); });
}; }
idServer = idController.text.trim(); idServer = idController.text.trim();
relayServer = relayController.text.trim(); relayServer = relayController.text.trim();
apiServer = apiController.text.trim().toLowerCase(); apiServer = apiController.text.trim().toLowerCase();
key = keyController.text.trim(); key = keyController.text.trim();
if (idServer.isNotEmpty) { if (idServer.isNotEmpty) {
idServerMsg = translate( idServerMsg =
await bind.mainTestIfValidServer(server: idServer)); translate(await bind.mainTestIfValidServer(server: idServer));
if (idServerMsg.isEmpty) { if (idServerMsg.isEmpty) {
oldOptions['custom-rendezvous-server'] = idServer; oldOptions['custom-rendezvous-server'] = idServer;
} else { } else {
@@ -1181,8 +1072,8 @@ void changeServer() async {
} }
if (relayServer.isNotEmpty) { if (relayServer.isNotEmpty) {
relayServerMsg = translate( relayServerMsg =
await bind.mainTestIfValidServer(server: relayServer)); translate(await bind.mainTestIfValidServer(server: relayServer));
if (relayServerMsg.isEmpty) { if (relayServerMsg.isEmpty) {
oldOptions['relay-server'] = relayServer; oldOptions['relay-server'] = relayServer;
} else { } else {
@@ -1210,9 +1101,120 @@ void changeServer() async {
oldOptions['key'] = key; oldOptions['key'] = key;
await bind.mainSetOptions(json: jsonEncode(oldOptions)); await bind.mainSetOptions(json: jsonEncode(oldOptions));
close(); close();
}, }
child: Text(translate("OK"))),
return CustomAlertDialog(
title: Text(translate("ID/Relay Server")),
content: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('ID Server')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: idServerMsg.isNotEmpty ? idServerMsg : null),
controller: idController,
focusNode: FocusNode()..requestFocus(),
),
),
], ],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('Relay Server')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText:
relayServerMsg.isNotEmpty ? relayServerMsg : null),
controller: relayController,
),
),
],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('API Server')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText:
apiServerMsg.isNotEmpty ? apiServerMsg : null),
controller: apiController,
),
),
],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child:
Text("${translate('Key')}:").marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
controller: keyController,
),
),
],
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, child: Text(translate("OK"))),
],
onSubmit: submit,
onCancel: close,
); );
}); });
} }
@@ -1231,7 +1233,7 @@ 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(
@@ -1240,18 +1242,19 @@ void changeWhiteList() async {
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,110 +1318,23 @@ void changeSocks5Proxy() async {
var isInProgress = false; var isInProgress = false;
gFFI.dialogManager.show((setState, close) { gFFI.dialogManager.show((setState, close) {
return CustomAlertDialog( submit() async {
title: Text(translate("Socks5 Proxy")),
content: ConstrainedBox(
constraints: BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text("${translate('Hostname')}:")
.marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
errorText: proxyMsg.isNotEmpty ? proxyMsg : null),
controller: proxyController,
),
),
],
),
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text("${translate('Username')}:")
.marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
),
controller: userController,
),
),
],
),
SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints(minWidth: 100),
child: Text("${translate('Password')}:")
.marginOnly(bottom: 16.0)),
SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
),
controller: pwdController,
),
),
],
),
SizedBox(
height: 8.0,
),
Offstage(offstage: !isInProgress, child: LinearProgressIndicator())
],
),
),
actions: [
TextButton(
onPressed: () {
close();
},
child: Text(translate("Cancel"))),
TextButton(
onPressed: () async {
setState(() { setState(() {
proxyMsg = ""; proxyMsg = "";
isInProgress = true; isInProgress = true;
}); });
final cancel = () { cancel() {
setState(() { setState(() {
isInProgress = false; isInProgress = false;
}); });
}; }
proxy = proxyController.text.trim(); proxy = proxyController.text.trim();
username = userController.text.trim(); username = userController.text.trim();
password = pwdController.text.trim(); password = pwdController.text.trim();
if (proxy.isNotEmpty) { if (proxy.isNotEmpty) {
proxyMsg = proxyMsg = translate(await bind.mainTestIfValidServer(server: proxy));
translate(await bind.mainTestIfValidServer(server: proxy));
if (proxyMsg.isEmpty) { if (proxyMsg.isEmpty) {
// ignore // ignore
} else { } else {
@@ -1428,9 +1345,96 @@ void changeSocks5Proxy() async {
await bind.mainSetSocks( await bind.mainSetSocks(
proxy: proxy, username: username, password: password); proxy: proxy, username: username, password: password);
close(); close();
}, }
child: Text(translate("OK"))),
return CustomAlertDialog(
title: Text(translate("Socks5 Proxy")),
content: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('Hostname')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: proxyMsg.isNotEmpty ? proxyMsg : null),
controller: proxyController,
focusNode: FocusNode()..requestFocus(),
),
),
], ],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('Username')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
controller: userController,
),
),
],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('Password')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
controller: pwdController,
),
),
],
),
const SizedBox(
height: 8.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, child: Text(translate("OK"))),
],
onSubmit: submit,
onCancel: close,
); );
}); });
} }

View File

@@ -41,21 +41,29 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
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: [
OverlayEntry(builder: (context) {
gFFI.dialogManager.setOverlayState(Overlay.of(context));
return Scaffold(
backgroundColor: MyTheme.color(context).bg, backgroundColor: MyTheme.color(context).bg,
body: DesktopTab( body: DesktopTab(
controller: tabController, controller: tabController,
theme: dark ? TarBarTheme.dark() : TarBarTheme.light(), theme: dark
? const TarBarTheme.dark()
: const TarBarTheme.light(),
tail: ActionIcon( tail: ActionIcon(
message: 'Settings', message: 'Settings',
icon: IconFont.menu, icon: IconFont.menu,
theme: dark ? TarBarTheme.dark() : TarBarTheme.light(), theme: dark
? const TarBarTheme.dark()
: const TarBarTheme.light(),
onTap: onAddSetting, onTap: onAddSetting,
is_close: false, is_close: false,
), ),
)),
),
)); ));
})
]),
)));
} }
void onAddSetting() { void onAddSetting() {

View File

@@ -642,8 +642,21 @@ 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() {
if (name.value.text.isNotEmpty) {
model.createDir(
PathUtil.join(
model.getCurrentDir(isLocal).path,
name.value.text,
model.getCurrentIsWindows(isLocal)),
isLocal: isLocal);
close();
}
}
cancel() => close(false);
return CustomAlertDialog(
title: Text(translate("Create Folder")), title: Text(translate("Create Folder")),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -654,35 +667,26 @@ class _FileManagerPageState extends State<FileManagerPage>
"Please enter the folder name"), "Please enter the folder name"),
), ),
controller: name, controller: name,
focusNode: FocusNode()..requestFocus(),
), ),
], ],
), ),
actions: [ actions: [
TextButton( TextButton(
style: flatButtonStyle, style: flatButtonStyle,
onPressed: () => close(false), onPressed: cancel,
child: Text(translate("Cancel"))), child: Text(translate("Cancel"))),
ElevatedButton( ElevatedButton(
style: flatButtonStyle, style: flatButtonStyle,
onPressed: () { onPressed: submit,
if (name.value.text.isNotEmpty) {
model.createDir(
PathUtil.join(
model
.getCurrentDir(
isLocal)
.path,
name.value.text,
model.getCurrentIsWindows(
isLocal)),
isLocal: isLocal);
close();
}
},
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

View File

@@ -70,6 +70,9 @@ class _PortForwardPageState extends State<PortForwardPage>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
return Overlay(initialEntries: [
OverlayEntry(builder: (context) {
_ffi.dialogManager.setOverlayState(Overlay.of(context));
return Scaffold( return Scaffold(
backgroundColor: MyTheme.color(context).grayBg, backgroundColor: MyTheme.color(context).grayBg,
body: FutureBuilder(future: () async { body: FutureBuilder(future: () async {
@@ -90,9 +93,11 @@ class _PortForwardPageState extends State<PortForwardPage>
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: MyTheme.color(context).bg, color: MyTheme.color(context).bg,
border: Border.all(width: 1, color: MyTheme.border)), border:
child: Border.all(width: 1, color: MyTheme.border)),
widget.isRDP ? buildRdp(context) : buildTunnel(context), child: widget.isRDP
? buildRdp(context)
: buildTunnel(context),
), ),
), ),
], ],
@@ -102,6 +107,8 @@ class _PortForwardPageState extends State<PortForwardPage>
return const Offstage(); return const Offstage();
}), }),
); );
})
]);
} }
buildPrompt(BuildContext context) { buildPrompt(BuildContext context) {

View File

@@ -563,33 +563,7 @@ abstract class BasePeerCard extends StatelessWidget {
} }
} }
gFFI.dialogManager.show((setState, close) { gFFI.dialogManager.show((setState, close) {
return CustomAlertDialog( submit() async {
title: Text(translate('Rename')),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Form(
child: TextFormField(
controller: controller,
decoration: InputDecoration(border: OutlineInputBorder()),
),
),
),
Obx(() => Offstage(
offstage: isInProgress.isFalse,
child: LinearProgressIndicator())),
],
),
actions: [
TextButton(
onPressed: () {
close();
},
child: Text(translate("Cancel"))),
TextButton(
onPressed: () async {
isInProgress.value = true; isInProgress.value = true;
name = controller.text; name = controller.text;
await bind.mainSetPeerOption(id: id, key: 'alias', value: name); await bind.mainSetPeerOption(id: id, key: 'alias', value: name);
@@ -597,13 +571,39 @@ abstract class BasePeerCard extends StatelessWidget {
gFFI.abModel.setPeerOption(id, 'alias', name); gFFI.abModel.setPeerOption(id, 'alias', name);
await gFFI.abModel.updateAb(); await gFFI.abModel.updateAb();
} }
alias.value = alias.value = await bind.mainGetPeerOption(id: peer.id, key: 'alias');
await bind.mainGetPeerOption(id: peer.id, key: 'alias');
close(); close();
isInProgress.value = false; isInProgress.value = false;
}, }
child: Text(translate("OK"))),
return CustomAlertDialog(
title: Text(translate('Rename')),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Form(
child: TextFormField(
controller: controller,
focusNode: FocusNode()..requestFocus(),
decoration:
const InputDecoration(border: OutlineInputBorder()),
),
),
),
Obx(() => Offstage(
offstage: isInProgress.isFalse,
child: const LinearProgressIndicator())),
], ],
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, 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,
); );
}); });
} }

View File

@@ -596,6 +596,17 @@ 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: [
@@ -617,25 +628,17 @@ void showSetOSPassword(
actions: [ actions: [
TextButton( TextButton(
style: flatButtonStyle, style: flatButtonStyle,
onPressed: () { onPressed: close,
close();
},
child: Text(translate('Cancel')), child: Text(translate('Cancel')),
), ),
TextButton( TextButton(
style: flatButtonStyle, style: flatButtonStyle,
onPressed: () { onPressed: 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();
},
child: Text(translate('OK')), child: Text(translate('OK')),
), ),
]); ],
onSubmit: submit,
onCancel: close,
);
}); });
} }

View File

@@ -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);
return CustomAlertDialog(
title: Row(children: [ title: Row(children: [
Icon(Icons.warning_amber_sharp, const Icon(Icons.warning_amber_sharp,
color: Colors.redAccent, size: 28), color: Colors.redAccent, size: 28),
SizedBox(width: 10), const SizedBox(width: 10),
Text(translate("Warning")), Text(translate("Warning")),
]), ]),
content: Text(translate("Disconnect all devices?")), content: Text(translate("Disconnect all devices?")),
actions: [ actions: [
TextButton( TextButton(onPressed: close, child: Text(translate("Cancel"))),
onPressed: () => close(), child: Text(translate("Cancel"))), ElevatedButton(onPressed: submit, child: Text(translate("OK"))),
ElevatedButton(
onPressed: () => close(true), child: Text(translate("OK"))),
], ],
)); onSubmit: submit,
onCancel: close,
);
});
if (res == true) { if (res == true) {
callback(); callback();
} }

View File

@@ -559,11 +559,14 @@ 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) {
cancel() => close(false);
submit() => close(true);
return CustomAlertDialog(
title: Row( title: Row(
children: [ children: [
Icon(Icons.warning, color: Colors.red), const Icon(Icons.warning, color: Colors.red),
SizedBox(width: 20), const SizedBox(width: 20),
Text(title) Text(title)
], ],
), ),
@@ -572,9 +575,9 @@ class FileModel extends ChangeNotifier {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text(content), Text(content),
SizedBox(height: 5), const SizedBox(height: 5),
Text(translate("This is irreversible!"), Text(translate("This is irreversible!"),
style: TextStyle(fontWeight: FontWeight.bold)), style: const TextStyle(fontWeight: FontWeight.bold)),
showCheckbox showCheckbox
? CheckboxListTile( ? CheckboxListTile(
contentPadding: const EdgeInsets.all(0), contentPadding: const EdgeInsets.all(0),
@@ -589,19 +592,22 @@ class FileModel extends ChangeNotifier {
setState(() => removeCheckboxRemember = v); setState(() => removeCheckboxRemember = v);
}, },
) )
: SizedBox.shrink() : const SizedBox.shrink()
]), ]),
actions: [ actions: [
TextButton( TextButton(
style: flatButtonStyle, style: flatButtonStyle,
onPressed: () => close(false), onPressed: cancel,
child: Text(translate("Cancel"))), child: Text(translate("Cancel"))),
TextButton( TextButton(
style: flatButtonStyle, style: flatButtonStyle,
onPressed: () => close(true), onPressed: submit,
child: Text(translate("OK"))), child: Text(translate("OK"))),
]), ],
useAnimation: false); onSubmit: submit,
onCancel: cancel,
);
}, useAnimation: false);
} }
bool fileConfirmCheckboxRemember = false; bool fileConfirmCheckboxRemember = false;
@@ -610,11 +616,14 @@ 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) {
cancel() => close(false);
submit() => close(true);
return CustomAlertDialog(
title: Row( title: Row(
children: [ children: [
Icon(Icons.warning, color: Colors.red), const Icon(Icons.warning, color: Colors.red),
SizedBox(width: 20), const SizedBox(width: 20),
Text(title) Text(title)
], ],
), ),
@@ -622,11 +631,9 @@ class FileModel extends ChangeNotifier {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(translate("This file exists, skip or overwrite this file?"),
translate( style: const TextStyle(fontWeight: FontWeight.bold)),
"This file exists, skip or overwrite this file?"), const SizedBox(height: 5),
style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(height: 5),
Text(content), Text(content),
showCheckbox showCheckbox
? CheckboxListTile( ? CheckboxListTile(
@@ -642,12 +649,12 @@ class FileModel extends ChangeNotifier {
setState(() => fileConfirmCheckboxRemember = v); setState(() => fileConfirmCheckboxRemember = v);
}, },
) )
: SizedBox.shrink() : const SizedBox.shrink()
]), ]),
actions: [ actions: [
TextButton( TextButton(
style: flatButtonStyle, style: flatButtonStyle,
onPressed: () => close(false), onPressed: cancel,
child: Text(translate("Cancel"))), child: Text(translate("Cancel"))),
TextButton( TextButton(
style: flatButtonStyle, style: flatButtonStyle,
@@ -655,10 +662,13 @@ class FileModel extends ChangeNotifier {
child: Text(translate("Skip"))), child: Text(translate("Skip"))),
TextButton( TextButton(
style: flatButtonStyle, style: flatButtonStyle,
onPressed: () => close(true), onPressed: submit,
child: Text(translate("OK"))), 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) {

View File

@@ -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) {
submit() => close(true);
return CustomAlertDialog(
title: Row(children: [ title: Row(children: [
Icon(Icons.warning_amber_sharp, const Icon(Icons.warning_amber_sharp,
color: Colors.redAccent, size: 28), color: Colors.redAccent, size: 28),
SizedBox(width: 10), const SizedBox(width: 10),
Text(translate("Warning")), Text(translate("Warning")),
]), ]),
content: Text(translate("android_stop_service_tip")), content: Text(translate("android_stop_service_tip")),
actions: [ actions: [
TextButton( TextButton(onPressed: close, child: Text(translate("Cancel"))),
onPressed: () => close(), ElevatedButton(onPressed: submit, child: Text(translate("OK"))),
child: Text(translate("Cancel"))),
ElevatedButton(
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) {
submit() => close(true);
return CustomAlertDialog(
title: Row(children: [ title: Row(children: [
Icon(Icons.warning_amber_sharp, const Icon(Icons.warning_amber_sharp,
color: Colors.redAccent, size: 28), color: Colors.redAccent, size: 28),
SizedBox(width: 10), const SizedBox(width: 10),
Text(translate("Warning")), Text(translate("Warning")),
]), ]),
content: Text(translate("android_service_will_start_tip")), content: Text(translate("android_service_will_start_tip")),
actions: [ actions: [
TextButton( TextButton(onPressed: close, child: Text(translate("Cancel"))),
onPressed: () => close(), ElevatedButton(onPressed: submit, child: Text(translate("OK"))),
child: Text(translate("Cancel"))),
ElevatedButton(
onPressed: () => close(true),
child: Text(translate("OK"))),
], ],
)); onSubmit: submit,
onCancel: close,
);
});
if (res == true) { if (res == true) {
startService(); startService();
} }
@@ -388,19 +390,27 @@ 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);
close();
}
return CustomAlertDialog(
title:
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(translate(
client.isFileTransfer ? "File Connection" : "Screen Connection")),
IconButton( IconButton(
onPressed: () { onPressed: () {
close(); close();
}, },
icon: Icon(Icons.close)) icon: const Icon(Icons.close))
]), ]),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -411,26 +421,18 @@ class ServerModel with ChangeNotifier {
clientInfo(client), clientInfo(client),
Text( Text(
translate("android_new_connection_tip"), translate("android_new_connection_tip"),
style: TextStyle(color: Colors.black54), style: const TextStyle(color: Colors.black54),
), ),
], ],
), ),
actions: [ actions: [
TextButton( TextButton(onPressed: cancel, child: Text(translate("Dismiss"))),
child: Text(translate("Dismiss")), ElevatedButton(onPressed: submit, child: Text(translate("Accept"))),
onPressed: () {
sendLoginResponse(client, false);
close();
}),
ElevatedButton(
child: Text(translate("Accept")),
onPressed: () {
sendLoginResponse(client, true);
close();
}),
], ],
), onSubmit: submit,
tag: getLoginDialogTag(client.id)); 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) {
submit() {
ffi.serverModel.initInput();
close();
}
return CustomAlertDialog(
title: Text(translate("How to get Android input permission?")), title: Text(translate("How to get Android input permission?")),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text(translate("android_input_permission_tip1")), Text(translate("android_input_permission_tip1")),
SizedBox(height: 10), const SizedBox(height: 10),
Text(translate("android_input_permission_tip2")), Text(translate("android_input_permission_tip2")),
], ],
), ),
actions: [ actions: [
TextButton(child: Text(translate("Cancel")), onPressed: close), TextButton(onPressed: close, child: Text(translate("Cancel"))),
ElevatedButton( ElevatedButton(
child: Text(translate("Open System Setting")), onPressed: submit, child: Text(translate("Open System Setting"))),
onPressed: () {
ffi.serverModel.initInput();
close();
}),
], ],
)); onSubmit: submit,
onCancel: close,
);
});
} }