Merge pull request from NicKoehler/modern-dialog

Modernize dialogs
This commit is contained in:
RustDesk 2023-03-02 17:19:14 +08:00 committed by GitHub
commit b9e5576cd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 445 additions and 169 deletions

@ -174,6 +174,27 @@ class MyTheme {
brightness: Brightness.light, brightness: Brightness.light,
hoverColor: Color.fromARGB(255, 224, 224, 224), hoverColor: Color.fromARGB(255, 224, 224, 224),
scaffoldBackgroundColor: Color(0xFFFFFFFF), scaffoldBackgroundColor: Color(0xFFFFFFFF),
dialogBackgroundColor: Color(0xFFFFFFFF),
dialogTheme: DialogTheme(
elevation: 15,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(
width: 1,
color: Color(0xFFEEEEEE),
),
),
),
inputDecorationTheme: InputDecorationTheme(
fillColor: Color(0xFFEEEEEE),
filled: true,
isDense: true,
contentPadding: EdgeInsets.all(15),
border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(18),
borderSide: BorderSide.none,
),
),
textTheme: const TextTheme( textTheme: const TextTheme(
titleLarge: TextStyle(fontSize: 19, color: Colors.black87), titleLarge: TextStyle(fontSize: 19, color: Colors.black87),
titleSmall: TextStyle(fontSize: 14, color: Colors.black87), titleSmall: TextStyle(fontSize: 14, color: Colors.black87),
@ -192,9 +213,48 @@ class MyTheme {
splashFactory: isDesktop ? NoSplash.splashFactory : null, splashFactory: isDesktop ? NoSplash.splashFactory : null,
textButtonTheme: isDesktop textButtonTheme: isDesktop
? TextButtonThemeData( ? TextButtonThemeData(
style: ButtonStyle(splashFactory: NoSplash.splashFactory), style: TextButton.styleFrom(
splashFactory: NoSplash.splashFactory,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
) )
: null, : null,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: MyTheme.accent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
backgroundColor: Color(
0xFFEEEEEE,
),
foregroundColor: Colors.black87,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
checkboxTheme: const CheckboxThemeData(
splashRadius: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
),
listTileTheme: ListTileThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
),
colorScheme: ColorScheme.fromSwatch( colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
).copyWith( ).copyWith(
@ -211,6 +271,27 @@ class MyTheme {
brightness: Brightness.dark, brightness: Brightness.dark,
hoverColor: Color.fromARGB(255, 45, 46, 53), hoverColor: Color.fromARGB(255, 45, 46, 53),
scaffoldBackgroundColor: Color(0xFF18191E), scaffoldBackgroundColor: Color(0xFF18191E),
dialogBackgroundColor: Color(0xFF18191E),
dialogTheme: DialogTheme(
elevation: 15,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(
width: 1,
color: Color(0xFF24252B),
),
),
),
inputDecorationTheme: InputDecorationTheme(
fillColor: Color(0xFF24252B),
filled: true,
isDense: true,
contentPadding: EdgeInsets.all(15),
border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(18),
borderSide: BorderSide.none,
),
),
textTheme: const TextTheme( textTheme: const TextTheme(
titleLarge: TextStyle(fontSize: 19), titleLarge: TextStyle(fontSize: 19),
titleSmall: TextStyle(fontSize: 14), titleSmall: TextStyle(fontSize: 14),
@ -229,27 +310,55 @@ class MyTheme {
splashColor: Colors.transparent, splashColor: Colors.transparent,
highlightColor: Colors.transparent, highlightColor: Colors.transparent,
splashFactory: isDesktop ? NoSplash.splashFactory : null, splashFactory: isDesktop ? NoSplash.splashFactory : null,
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
side: BorderSide(color: Colors.white38),
disabledForegroundColor: Colors.white70,
),
),
textButtonTheme: isDesktop textButtonTheme: isDesktop
? TextButtonThemeData( ? TextButtonThemeData(
style: TextButton.styleFrom( style: TextButton.styleFrom(
splashFactory: NoSplash.splashFactory, splashFactory: NoSplash.splashFactory,
disabledForegroundColor: Colors.white70, disabledForegroundColor: Colors.white70,
)) foregroundColor: Colors.white70,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
)
: null, : null,
elevatedButtonTheme: ElevatedButtonThemeData( elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: MyTheme.accent,
disabledForegroundColor: Colors.white70, disabledForegroundColor: Colors.white70,
disabledBackgroundColor: Colors.white10, disabledBackgroundColor: Colors.white10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
backgroundColor: Color(0xFF24252B),
side: BorderSide(color: Colors.white12, width: 0.5),
disabledForegroundColor: Colors.white70,
foregroundColor: Colors.white70,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
checkboxTheme: const CheckboxThemeData(
checkColor: MaterialStatePropertyAll(dark),
splashRadius: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
),
listTileTheme: ListTileThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
), ),
), ),
checkboxTheme:
const CheckboxThemeData(checkColor: MaterialStatePropertyAll(dark)),
colorScheme: ColorScheme.fromSwatch( colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
).copyWith( ).copyWith(
@ -480,7 +589,7 @@ class OverlayDialogManager {
BackButtonInterceptor.removeByName(dialogTag); BackButtonInterceptor.removeByName(dialogTag);
} }
dialog.entry = OverlayEntry(builder: (_) { dialog.entry = OverlayEntry(builder: (context) {
bool innerClicked = false; bool innerClicked = false;
return Listener( return Listener(
onPointerUp: (_) { onPointerUp: (_) {
@ -490,7 +599,9 @@ class OverlayDialogManager {
innerClicked = false; innerClicked = false;
}, },
child: Container( child: Container(
color: Colors.black12, color: Theme.of(context).brightness == Brightness.light
? Colors.black12
: Colors.black45,
child: StatefulBuilder(builder: (context, setState) { child: StatefulBuilder(builder: (context, setState) {
return Listener( return Listener(
onPointerUp: (_) => innerClicked = true, onPointerUp: (_) => innerClicked = true,
@ -672,7 +783,7 @@ class CustomAlertDialog extends StatelessWidget {
Future.delayed(Duration.zero, () { Future.delayed(Duration.zero, () {
if (!scopeNode.hasFocus) scopeNode.requestFocus(); if (!scopeNode.hasFocus) scopeNode.requestFocus();
}); });
const double padding = 16; const double padding = 30;
bool tabTapped = false; bool tabTapped = false;
return FocusScope( return FocusScope(
node: scopeNode, node: scopeNode,
@ -701,18 +812,19 @@ class CustomAlertDialog extends StatelessWidget {
scrollable: true, scrollable: true,
title: title, title: title,
titlePadding: EdgeInsets.fromLTRB(padding, 24, padding, 0), titlePadding: EdgeInsets.fromLTRB(padding, 24, padding, 0),
contentPadding: EdgeInsets.fromLTRB(contentPadding ?? padding, 25, contentPadding: EdgeInsets.fromLTRB(
contentPadding ?? padding, actions is List ? 10 : padding), contentPadding ?? padding,
25,
contentPadding ?? padding,
actions is List ? 10 : padding,
),
content: ConstrainedBox( content: ConstrainedBox(
constraints: contentBoxConstraints, constraints: contentBoxConstraints,
child: Theme( child: content,
data: Theme.of(context).copyWith(
inputDecorationTheme: InputDecorationTheme(
isDense: true, contentPadding: EdgeInsets.all(15))),
child: content),
), ),
actions: actions, actions: actions,
actionsPadding: EdgeInsets.fromLTRB(padding, 0, padding, padding), actionsPadding: EdgeInsets.fromLTRB(padding, 0, padding, padding),
actionsAlignment: MainAxisAlignment.center,
), ),
); );
} }
@ -1727,19 +1839,33 @@ class ServerConfig {
Widget dialogButton(String text, Widget dialogButton(String text,
{required VoidCallback? onPressed, {required VoidCallback? onPressed,
bool isOutline = false, bool isOutline = false,
Widget? icon,
TextStyle? style, TextStyle? style,
ButtonStyle? buttonStyle}) { ButtonStyle? buttonStyle}) {
if (isDesktop) { if (isDesktop) {
if (isOutline) { if (isOutline) {
return OutlinedButton( return icon == null
? OutlinedButton(
onPressed: onPressed, onPressed: onPressed,
child: Text(translate(text), style: style), child: Text(translate(text), style: style),
)
: OutlinedButton.icon(
icon: icon,
onPressed: onPressed,
label: Text(translate(text), style: style),
); );
} else { } else {
return ElevatedButton( return icon == null
? ElevatedButton(
style: ElevatedButton.styleFrom(elevation: 0).merge(buttonStyle), style: ElevatedButton.styleFrom(elevation: 0).merge(buttonStyle),
onPressed: onPressed, onPressed: onPressed,
child: Text(translate(text), style: style), child: Text(translate(text), style: style),
)
: ElevatedButton.icon(
icon: icon,
style: ElevatedButton.styleFrom(elevation: 0).merge(buttonStyle),
onPressed: onPressed,
label: Text(translate(text), style: style),
); );
} }
} else { } else {
@ -1748,7 +1874,8 @@ Widget dialogButton(String text,
child: Text( child: Text(
translate(text), translate(text),
style: style, style: style,
)); ),
);
} }
} }

@ -532,19 +532,7 @@ abstract class BasePeerCard extends StatelessWidget {
], ],
), ),
proc: () { proc: () {
() async { _delete(id, isLan, reloadFunc);
if (isLan) {
bind.mainRemoveDiscovered(id: id);
} else {
final favs = (await bind.mainGetFav()).toList();
if (favs.remove(id)) {
await bind.mainStoreFav(favs: favs);
}
await bind.mainRemovePeer(id: id);
}
removePreference(id);
await reloadFunc();
}();
}, },
padding: menuPadding, padding: menuPadding,
dismissOnClicked: true, dismissOnClicked: true,
@ -673,7 +661,13 @@ abstract class BasePeerCard extends StatelessWidget {
} }
return CustomAlertDialog( return CustomAlertDialog(
title: Text(translate('Rename')), title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.edit_rounded, color: MyTheme.accent),
Text(translate('Rename')).paddingOnly(left: 10),
],
),
content: Column( content: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -682,9 +676,7 @@ abstract class BasePeerCard extends StatelessWidget {
child: TextFormField( child: TextFormField(
controller: controller, controller: controller,
autofocus: true, autofocus: true,
decoration: InputDecoration( decoration: InputDecoration(labelText: translate('Name')),
border: OutlineInputBorder(),
labelText: translate('Name')),
), ),
), ),
), ),
@ -694,8 +686,17 @@ abstract class BasePeerCard extends StatelessWidget {
], ],
), ),
actions: [ actions: [
dialogButton("Cancel", onPressed: close, isOutline: true), dialogButton(
dialogButton("OK", onPressed: submit), "Cancel",
icon: Icon(Icons.close_rounded),
onPressed: close,
isOutline: true,
),
dialogButton(
"OK",
icon: Icon(Icons.done_rounded),
onPressed: submit,
),
], ],
onSubmit: submit, onSubmit: submit,
onCancel: close, onCancel: close,
@ -705,6 +706,58 @@ abstract class BasePeerCard extends StatelessWidget {
@protected @protected
void _update(); void _update();
void _delete(String id, bool isLan, Function reloadFunc) async {
gFFI.dialogManager.show(
(setState, close) {
submit() async {
if (isLan) {
bind.mainRemoveDiscovered(id: id);
} else {
final favs = (await bind.mainGetFav()).toList();
if (favs.remove(id)) {
await bind.mainStoreFav(favs: favs);
}
await bind.mainRemovePeer(id: id);
}
removePreference(id);
await reloadFunc();
close();
}
return CustomAlertDialog(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.delete_rounded,
color: Colors.red,
),
Text(translate('Delete')).paddingOnly(
left: 10,
),
],
),
content: SizedBox.shrink(),
actions: [
dialogButton(
"Cancel",
icon: Icon(Icons.close_rounded),
onPressed: close,
isOutline: true,
),
dialogButton(
"OK",
icon: Icon(Icons.done_rounded),
onPressed: submit,
),
],
onSubmit: submit,
onCancel: close,
);
},
);
}
} }
class RecentPeerCard extends BasePeerCard { class RecentPeerCard extends BasePeerCard {

@ -300,14 +300,13 @@ class _FileManagerPageState extends State<FileManagerPage>
} }
skipCount = index + 1; skipCount = index + 1;
} }
var searchResult = entries var searchResult = entries.skip(skipCount).where(
.skip(skipCount) (element) => element.name.toLowerCase().startsWith(buffer));
.where((element) => element.name.toLowerCase().startsWith(buffer));
if (searchResult.isEmpty) { if (searchResult.isEmpty) {
// cannot find next, lets restart search from head // cannot find next, lets restart search from head
debugPrint("restart search from head"); debugPrint("restart search from head");
searchResult = searchResult = entries.where(
entries.where((element) => element.name.toLowerCase().startsWith(buffer)); (element) => element.name.toLowerCase().startsWith(buffer));
} }
if (searchResult.isEmpty) { if (searchResult.isEmpty) {
setState(() { setState(() {
@ -321,8 +320,8 @@ class _FileManagerPageState extends State<FileManagerPage>
onSearch: (buffer) { onSearch: (buffer) {
debugPrint("searching for $buffer"); debugPrint("searching for $buffer");
final selectedEntries = getSelectedItems(isLocal); final selectedEntries = getSelectedItems(isLocal);
final searchResult = final searchResult = entries.where(
entries.where((element) => element.name.toLowerCase().startsWith(buffer)); (element) => element.name.toLowerCase().startsWith(buffer));
selectedEntries.clear(); selectedEntries.clear();
if (searchResult.isEmpty) { if (searchResult.isEmpty) {
setState(() { setState(() {
@ -504,8 +503,7 @@ class _FileManagerPageState extends State<FileManagerPage>
debugPrint("entry is not valid: ${entry.path}"); debugPrint("entry is not valid: ${entry.path}");
} }
final selectedEntries = getSelectedItems(isLocal); final selectedEntries = getSelectedItems(isLocal);
final searchResult = final searchResult = entries.where((element) => element == entry);
entries.where((element) => element == entry);
selectedEntries.clear(); selectedEntries.clear();
if (searchResult.isEmpty) { if (searchResult.isEmpty) {
return; return;
@ -976,14 +974,26 @@ class _FileManagerPageState extends State<FileManagerPage>
cancel() => close(false); cancel() => close(false);
return CustomAlertDialog( return CustomAlertDialog(
title: Text(translate("Create Folder")), title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset("assets/folder_new.svg",
color: MyTheme.accent),
Text(
translate("Create Folder"),
).paddingOnly(
left: 10,
),
],
),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
TextFormField( TextFormField(
decoration: InputDecoration( decoration: InputDecoration(
labelText: translate( labelText: translate(
"Please enter the folder name"), "Please enter the folder name",
),
), ),
controller: name, controller: name,
autofocus: true, autofocus: true,
@ -991,9 +1001,17 @@ class _FileManagerPageState extends State<FileManagerPage>
], ],
), ),
actions: [ actions: [
dialogButton("Cancel", dialogButton(
onPressed: cancel, isOutline: true), "Cancel",
dialogButton("OK", onPressed: submit) icon: Icon(Icons.close_rounded),
onPressed: cancel,
isOutline: true,
),
dialogButton(
"Ok",
icon: Icon(Icons.done_rounded),
onPressed: submit,
),
], ],
onSubmit: submit, onSubmit: submit,
onCancel: cancel, onCancel: cancel,
@ -1036,11 +1054,6 @@ class _FileManagerPageState extends State<FileManagerPage>
? MyTheme.accent80 ? MyTheme.accent80
: MyTheme.accent, : MyTheme.accent,
), ),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
), ),
onPressed: validItems(selectedItems) onPressed: validItems(selectedItems)
? () { ? () {
@ -1467,10 +1480,8 @@ class _FileManagerPageState extends State<FileManagerPage>
axis: Axis.vertical, axis: Axis.vertical,
onPointerMove: (dx) { onPointerMove: (dx) {
nameColWidth.value += dx; nameColWidth.value += dx;
nameColWidth.value = min( nameColWidth.value = min(kDesktopFileTransferMaximumWidth,
kDesktopFileTransferMaximumWidth, max(kDesktopFileTransferMinimumWidth, nameColWidth.value));
max(kDesktopFileTransferMinimumWidth,
nameColWidth.value));
}, },
padding: padding, padding: padding,
), ),

@ -421,7 +421,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
SizedBox(width: _MenubarTheme.buttonHMargin) SizedBox(width: _MenubarTheme.buttonHMargin)
], ],
), ),
)), ),
),
), ),
_buildDraggableShowHide(context), _buildDraggableShowHide(context),
], ],
@ -434,7 +435,10 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
style: ButtonStyle( style: ButtonStyle(
minimumSize: MaterialStatePropertyAll(Size(64, 36)), minimumSize: MaterialStatePropertyAll(Size(64, 36)),
textStyle: MaterialStatePropertyAll( textStyle: MaterialStatePropertyAll(
TextStyle(fontWeight: FontWeight.normal)))), TextStyle(fontWeight: FontWeight.normal),
),
),
),
dividerTheme: DividerThemeData(space: 4), dividerTheme: DividerThemeData(space: 4),
); );
} }
@ -655,8 +659,16 @@ class _ControlMenu extends StatelessWidget {
} }
return CustomAlertDialog( return CustomAlertDialog(
title: Text(translate('OS Password')), title: Row(
content: Column(mainAxisSize: MainAxisSize.min, children: [ mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.password_rounded, color: MyTheme.accent),
Text(translate('OS Password')).paddingOnly(left: 10),
],
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
PasswordWidget(controller: controller), PasswordWidget(controller: controller),
CheckboxListTile( CheckboxListTile(
contentPadding: const EdgeInsets.all(0), contentPadding: const EdgeInsets.all(0),
@ -671,10 +683,20 @@ class _ControlMenu extends StatelessWidget {
setState(() => autoLogin = v); setState(() => autoLogin = v);
}, },
), ),
]), ],
),
actions: [ actions: [
dialogButton('Cancel', onPressed: close, isOutline: true), dialogButton(
dialogButton('OK', onPressed: submit), "Cancel",
icon: Icon(Icons.close_rounded),
onPressed: close,
isOutline: true,
),
dialogButton(
"OK",
icon: Icon(Icons.done_rounded),
onPressed: submit,
),
], ],
onSubmit: submit, onSubmit: submit,
onCancel: close, onCancel: close,

@ -429,7 +429,7 @@ class ConnectionManager extends StatelessWidget {
? ElevatedButton.icon( ? ElevatedButton.icon(
style: ButtonStyle( style: ButtonStyle(
backgroundColor: backgroundColor:
MaterialStateProperty.all(Colors.red)), MaterialStatePropertyAll(Colors.red)),
icon: const Icon(Icons.close), icon: const Icon(Icons.close),
onPressed: () { onPressed: () {
bind.cmCloseConnection(connId: client.id); bind.cmCloseConnection(connId: client.id);

@ -25,19 +25,26 @@ void showRestartRemoteDevice(
final res = final res =
await dialogManager.show<bool>((setState, close) => CustomAlertDialog( await dialogManager.show<bool>((setState, close) => CustomAlertDialog(
title: Row(children: [ title: Row(children: [
Icon(Icons.warning_amber_sharp, Icon(Icons.warning_rounded, color: Colors.redAccent, size: 28),
color: Colors.redAccent, size: 28), Text(translate("Restart Remote Device")).paddingOnly(left: 10),
SizedBox(width: 10),
Text(translate("Restart Remote Device")),
]), ]),
content: Text( content: Text(
"${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"), "${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"),
actions: [
dialogButton(
"Cancel",
icon: Icon(Icons.close_rounded),
onPressed: close,
isOutline: true,
),
dialogButton(
"OK",
icon: Icon(Icons.done_rounded),
onPressed: () => close(true),
),
],
onCancel: close, onCancel: close,
onSubmit: () => close(true), onSubmit: () => close(true),
actions: [
dialogButton("Cancel", onPressed: close, isOutline: true),
dialogButton("OK", onPressed: () => close(true)),
],
)); ));
if (res == true) bind.sessionRestartRemoteDevice(id: id); if (res == true) bind.sessionRestartRemoteDevice(id: id);
} }
@ -62,7 +69,13 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async {
} }
return CustomAlertDialog( return CustomAlertDialog(
title: Text(translate('Set your own password')), title: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.password_rounded, color: MyTheme.accent),
Text(translate('Set your own password')).paddingOnly(left: 10),
],
),
content: Form( content: Form(
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(mainAxisSize: MainAxisSize.min, children: [ child: Column(mainAxisSize: MainAxisSize.min, children: [
@ -112,11 +125,13 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async {
actions: [ actions: [
dialogButton( dialogButton(
'Cancel', 'Cancel',
icon: Icon(Icons.close_rounded),
onPressed: close, onPressed: close,
isOutline: true, isOutline: true,
), ),
dialogButton( dialogButton(
'OK', 'OK',
icon: Icon(Icons.done_rounded),
onPressed: (validateLength && validateSame) ? submit : null, onPressed: (validateLength && validateSame) ? submit : null,
), ),
], ],
@ -178,7 +193,13 @@ void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async {
} }
return CustomAlertDialog( return CustomAlertDialog(
title: Text(translate('Password Required')), title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.password_rounded, color: MyTheme.accent),
Text(translate('Password Required')).paddingOnly(left: 10),
],
),
content: Column(mainAxisSize: MainAxisSize.min, children: [ content: Column(mainAxisSize: MainAxisSize.min, children: [
PasswordWidget(controller: controller), PasswordWidget(controller: controller),
CheckboxListTile( CheckboxListTile(
@ -197,8 +218,17 @@ void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async {
), ),
]), ]),
actions: [ actions: [
dialogButton('Cancel', onPressed: cancel, isOutline: true), dialogButton(
dialogButton('OK', onPressed: submit), 'Cancel',
icon: Icon(Icons.close_rounded),
onPressed: cancel,
isOutline: true,
),
dialogButton(
'OK',
icon: Icon(Icons.done_rounded),
onPressed: submit,
),
], ],
onSubmit: submit, onSubmit: submit,
onCancel: cancel, onCancel: cancel,

@ -593,9 +593,12 @@ class FileModel extends ChangeNotifier {
? "${translate("Are you sure you want to delete the file of this directory?")}\n" ? "${translate("Are you sure you want to delete the file of this directory?")}\n"
: ""; : "";
final count = entries.length > 1 ? "${i + 1}/${entries.length}" : ""; final count = entries.length > 1 ? "${i + 1}/${entries.length}" : "";
content = "$dirShow$count \n${entries[i].path}"; content = "$dirShow\n\n${entries[i].path}".trim();
final confirm = final confirm = await showRemoveDialog(
await showRemoveDialog(title, content, item.isDirectory); count.isEmpty ? title : "$title ($count)",
content,
item.isDirectory,
);
try { try {
if (confirm == true) { if (confirm == true) {
sendRemoveFile(entries[i].path, i, items.isLocal!); sendRemoveFile(entries[i].path, i, items.isLocal!);
@ -636,22 +639,27 @@ class FileModel extends ChangeNotifier {
submit() => close(true); submit() => close(true);
return CustomAlertDialog( return CustomAlertDialog(
title: Row( title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon(Icons.warning, color: Colors.red), const Icon(Icons.warning_rounded, color: Colors.red),
const SizedBox(width: 20), Text(title).paddingOnly(
Text(title) left: 10,
),
], ],
), ),
contentBoxConstraints: contentBoxConstraints:
BoxConstraints(minHeight: 100, minWidth: 400, maxWidth: 400), BoxConstraints(minHeight: 100, minWidth: 400, maxWidth: 400),
content: Column( content: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [ children: [
Text(content), Text(content),
const SizedBox(height: 5), Text(
Text(translate("This is irreversible!"), translate("This is irreversible!"),
style: const TextStyle(fontWeight: FontWeight.bold)), style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
).paddingOnly(top: 20),
showCheckbox showCheckbox
? CheckboxListTile( ? CheckboxListTile(
contentPadding: const EdgeInsets.all(0), contentPadding: const EdgeInsets.all(0),
@ -667,10 +675,20 @@ class FileModel extends ChangeNotifier {
}, },
) )
: const SizedBox.shrink() : const SizedBox.shrink()
]), ],
),
actions: [ actions: [
dialogButton("Cancel", onPressed: cancel, isOutline: true), dialogButton(
dialogButton("OK", onPressed: submit), "Cancel",
icon: Icon(Icons.close_rounded),
onPressed: cancel,
isOutline: true,
),
dialogButton(
"OK",
icon: Icon(Icons.done_rounded),
onPressed: submit,
),
], ],
onSubmit: submit, onSubmit: submit,
onCancel: cancel, onCancel: cancel,
@ -690,9 +708,10 @@ class FileModel extends ChangeNotifier {
return CustomAlertDialog( return CustomAlertDialog(
title: Row( title: Row(
children: [ children: [
const Icon(Icons.warning, color: Colors.red), const Icon(Icons.warning_rounded, color: Colors.red),
const SizedBox(width: 20), Text(title).paddingOnly(
Text(title) left: 10,
),
], ],
), ),
contentBoxConstraints: contentBoxConstraints:
@ -722,9 +741,23 @@ class FileModel extends ChangeNotifier {
: const SizedBox.shrink() : const SizedBox.shrink()
]), ]),
actions: [ actions: [
dialogButton("Cancel", onPressed: cancel, isOutline: true), dialogButton(
dialogButton("Skip", onPressed: () => close(null), isOutline: true), "Cancel",
dialogButton("OK", onPressed: submit), icon: Icon(Icons.close_rounded),
onPressed: cancel,
isOutline: true,
),
dialogButton(
"Skip",
icon: Icon(Icons.navigate_next_rounded),
onPressed: () => close(null),
isOutline: true,
),
dialogButton(
"OK",
icon: Icon(Icons.done_rounded),
onPressed: submit,
),
], ],
onSubmit: submit, onSubmit: submit,
onCancel: cancel, onCancel: cancel,