diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index aa5666e86..dd48cefea 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -136,7 +136,6 @@ class OverlayDialogManager { BackButtonInterceptor.removeByName(tag); } - // TODO clickMaskDismiss Future show(DialogBuilder builder, {bool clickMaskDismiss = false, bool backDismiss = false, @@ -168,10 +167,22 @@ class OverlayDialogManager { BackButtonInterceptor.removeByName(_tag); }; dialog.entry = OverlayEntry(builder: (_) { - return Container( - color: Colors.transparent, - child: StatefulBuilder( - builder: (_, setState) => builder(setState, close))); + bool innerClicked = false; + return Listener( + onPointerUp: (_) { + if (!innerClicked && clickMaskDismiss) { + close(); + } + innerClicked = false; + }, + child: Container( + color: Colors.black12, + child: StatefulBuilder(builder: (context, setState) { + return Listener( + onPointerUp: (_) => innerClicked = true, + child: builder(setState, close), + ); + }))); }); overlayState.insert(dialog.entry!); BackButtonInterceptor.add((stopDefaultButtonEvent, routeInfo) { @@ -184,7 +195,9 @@ class OverlayDialogManager { } void showLoading(String text, - {bool clickMaskDismiss = false, bool cancelToClose = false}) { + {bool clickMaskDismiss = false, + bool showCancel = true, + VoidCallback? onCancel}) { show((setState, close) => CustomAlertDialog( content: Container( color: MyTheme.white, @@ -200,21 +213,52 @@ class OverlayDialogManager { child: Text(translate(text), style: TextStyle(fontSize: 15))), SizedBox(height: 20), - Center( - child: TextButton( - style: flatButtonStyle, - onPressed: () { - dismissAll(); - if (cancelToClose) backToHomePage(); - }, - child: Text(translate('Cancel'), - style: TextStyle(color: MyTheme.accent)))) + Offstage( + offstage: !showCancel, + child: Center( + child: TextButton( + style: flatButtonStyle, + onPressed: () { + dismissAll(); + if (onCancel != null) { + onCancel(); + } + }, + child: Text(translate('Cancel'), + style: TextStyle(color: MyTheme.accent))))) ])))); } +} - void showToast(String text) { - // TODO - } +void showToast(String text, {Duration timeout = const Duration(seconds: 2)}) { + final overlayState = globalKey.currentState?.overlay; + if (overlayState == null) return; + final entry = OverlayEntry(builder: (_) { + return IgnorePointer( + child: Align( + alignment: Alignment(0.0, 0.8), + child: Container( + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.6), + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 5), + child: Text( + text, + style: TextStyle( + decoration: TextDecoration.none, + fontWeight: FontWeight.w300, + fontSize: 18, + color: Colors.white), + ), + ))); + }); + overlayState.insert(entry); + Future.delayed(timeout, () { + entry.remove(); + }); } class CustomAlertDialog extends StatelessWidget { diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 627c5b2e4..407d38958 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart' hide MenuItem; @@ -120,7 +119,7 @@ class _DesktopHomePageState extends State onDoubleTap: () { Clipboard.setData( ClipboardData(text: model.serverId.text)); - gFFI.dialogManager.showToast(translate("Copied")); + showToast(translate("Copied")); }, child: TextFormField( controller: model.serverId, @@ -257,7 +256,7 @@ class _DesktopHomePageState extends State kUsePermanentPassword) { Clipboard.setData( ClipboardData(text: model.serverPasswd.text)); - gFFI.dialogManager.showToast(translate("Copied")); + showToast(translate("Copied")); } }, child: TextFormField( diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index ceeb96049..02060dee5 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -62,7 +62,7 @@ class _RemotePageState extends State WidgetsBinding.instance.addPostFrameCallback((_) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); _ffi.dialogManager - .showLoading(translate('Connecting...'), cancelToClose: true); + .showLoading(translate('Connecting...'), onCancel: backToHomePage); _interval = Timer.periodic(Duration(milliseconds: 30), (timer) => interval()); }); diff --git a/flutter/lib/mobile/pages/file_manager_page.dart b/flutter/lib/mobile/pages/file_manager_page.dart index 9c8fd92c4..c361e7b7c 100644 --- a/flutter/lib/mobile/pages/file_manager_page.dart +++ b/flutter/lib/mobile/pages/file_manager_page.dart @@ -29,7 +29,7 @@ class _FileManagerPageState extends State { gFFI.connect(widget.id, isFileTransfer: true); WidgetsBinding.instance.addPostFrameCallback((_) { gFFI.dialogManager - .showLoading(translate('Connecting...'), cancelToClose: true); + .showLoading(translate('Connecting...'), onCancel: backToHomePage); }); gFFI.ffiModel.updateEventListener(widget.id); Wakelock.enable(); diff --git a/flutter/lib/mobile/pages/remote_page.dart b/flutter/lib/mobile/pages/remote_page.dart index 3e826705f..d64c83707 100644 --- a/flutter/lib/mobile/pages/remote_page.dart +++ b/flutter/lib/mobile/pages/remote_page.dart @@ -51,7 +51,7 @@ class _RemotePageState extends State { WidgetsBinding.instance.addPostFrameCallback((_) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); gFFI.dialogManager - .showLoading(translate('Connecting...'), cancelToClose: true); + .showLoading(translate('Connecting...'), onCancel: backToHomePage); _interval = Timer.periodic(Duration(milliseconds: 30), (timer) => interval()); }); diff --git a/flutter/lib/mobile/pages/scan_page.dart b/flutter/lib/mobile/pages/scan_page.dart index 4325d0570..9f6c36ca8 100644 --- a/flutter/lib/mobile/pages/scan_page.dart +++ b/flutter/lib/mobile/pages/scan_page.dart @@ -63,7 +63,7 @@ class _ScanPageState extends State { var result = reader.decode(bitmap); showServerSettingFromQr(result.text); } catch (e) { - gFFI.dialogManager.showToast('No QR code found'); + showToast('No QR code found'); } } }), @@ -121,7 +121,7 @@ class _ScanPageState extends State { void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) { if (!p) { - gFFI.dialogManager.showToast('No permisssion'); + showToast('No permission'); } } @@ -135,7 +135,7 @@ class _ScanPageState extends State { backToHomePage(); await controller?.pauseCamera(); if (!data.startsWith('config=')) { - gFFI.dialogManager.showToast('Invalid QR code'); + showToast('Invalid QR code'); return; } try { @@ -147,7 +147,7 @@ class _ScanPageState extends State { showServerSettingsWithValue(host, '', key, api, gFFI.dialogManager); }); } catch (e) { - gFFI.dialogManager.showToast('Invalid QR code'); + showToast('Invalid QR code'); } } } diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index 3a1f8b352..be8403427 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -363,7 +363,7 @@ void logout(OverlayDialogManager dialogManager) async { }, body: json.encode(body)); } catch (e) { - dialogManager.showToast('Failed to access $url'); + showToast('Failed to access $url'); } resetToken(); } diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 075fa5bd9..6f3428805 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -8,15 +8,12 @@ void clientClose(OverlayDialogManager dialogManager) { msgBox('', 'Close', 'Are you sure to close the connection?', dialogManager); } -const SEC1 = Duration(seconds: 1); -void showSuccess({Duration duration = SEC1}) { - // TODO - // showToast(translate("Successful"), duration: SEC1); +void showSuccess() { + showToast(translate("Successful")); } -void showError({Duration duration = SEC1}) { - // TODO - // showToast(translate("Error"), duration: SEC1); +void showError() { + showToast(translate("Error")); } void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async { @@ -174,7 +171,7 @@ void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async { gFFI.login(id, text, remember); close(); dialogManager.showLoading(translate('Logging in...'), - cancelToClose: true); + onCancel: backToHomePage); }, child: Text(translate('OK')), ), diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index c297141de..c4b10b377 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -287,7 +287,7 @@ class FfiModel with ChangeNotifier { bind.sessionReconnect(id: id); clearPermissions(); dialogManager.showLoading(translate('Connecting...'), - cancelToClose: true); + onCancel: backToHomePage); }); _reconnects *= 2; } else { @@ -335,7 +335,7 @@ class FfiModel with ChangeNotifier { if (displays.length > 0) { parent.target?.dialogManager.showLoading( translate('Connected, waiting for image...'), - cancelToClose: true); + onCancel: backToHomePage); _waitForImage = true; _reconnects = 1; }