소스 검색

Merge pull request #824 from ente-io/dialog-fixes

Dialog fixes
Neeraj Gupta 2 년 전
부모
커밋
ad9733b08c

+ 7 - 5
lib/services/user_service.dart

@@ -197,21 +197,23 @@ class UserService {
   }
 
   Future<void> logout(BuildContext context) async {
-    final dialog = createProgressDialog(context, "Logging out...");
-    await dialog.show();
     try {
       final response = await _enteDio.post("/users/logout");
       if (response.statusCode == 200) {
         await Configuration.instance.logout();
-        await dialog.hide();
         Navigator.of(context).popUntil((route) => route.isFirst);
       } else {
         throw Exception("Log out action failed");
       }
     } catch (e) {
       _logger.severe(e);
-      await dialog.hide();
-      showGenericErrorDialog(context: context);
+      //This future is for waiting for the dialog from which logout() is called
+      //to close and only then to show the error dialog.
+      Future.delayed(
+        const Duration(milliseconds: 150),
+        () => showGenericErrorDialog(context: context),
+      );
+      rethrow;
     }
   }
 

+ 1 - 1
lib/ui/account/delete_account_page.dart

@@ -131,7 +131,7 @@ class DeleteAccountPage extends StatelessWidget {
     );
 
     if (hasAuthenticated) {
-      final choice = await showNewChoiceDialog(
+      final choice = await showChoiceDialog(
         context,
         title: 'Are you sure you want to delete your account?',
         body:

+ 2 - 2
lib/ui/account/password_reentry_page.dart

@@ -80,7 +80,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
           } on KeyDerivationError catch (e, s) {
             _logger.severe("Password verification failed", e, s);
             await dialog.hide();
-            final dialogChoice = await showNewChoiceDialog(
+            final dialogChoice = await showChoiceDialog(
               context,
               title: "Recreate password",
               body: "The current device is not powerful enough to verify your "
@@ -102,7 +102,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
           } catch (e, s) {
             _logger.severe("Password verification failed", e, s);
             await dialog.hide();
-            final dialogChoice = await showNewChoiceDialog(
+            final dialogChoice = await showChoiceDialog(
               context,
               title: "Incorrect password",
               body: "Please try again",

+ 1 - 1
lib/ui/account/verify_recovery_page.dart

@@ -74,7 +74,7 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
           "The recovery key you entered is not valid. Please make sure it "
           "contains 24 words, and check the spelling of each.\n\nIf you "
           "entered an older recovery code, make sure it is 64 characters long, and check each of them.";
-      final result = await showNewChoiceDialog(
+      final result = await showChoiceDialog(
         context,
         title: "Invalid key",
         body: errMessage,

+ 1 - 1
lib/ui/actions/collection/collection_sharing_actions.dart

@@ -142,7 +142,7 @@ class CollectionActions {
     Collection collection,
     User user,
   ) async {
-    final result = await showNewChoiceDialog(
+    final result = await showChoiceDialog(
       context,
       title: "Remove",
       body: "${user.email} will be removed",

+ 0 - 76
lib/ui/common/dialogs.dart

@@ -1,76 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:photos/ente_theme_data.dart';
-
-enum DialogUserChoice { firstChoice, secondChoice }
-
-enum ActionType {
-  confirm,
-  critical,
-}
-
-// if dialog is dismissed by tapping outside, this will return null
-Future<DialogUserChoice?> showChoiceDialog<T>(
-  BuildContext context,
-  String title,
-  String content, {
-  String firstAction = 'Ok',
-  Color? firstActionColor,
-  String secondAction = 'Cancel',
-  Color? secondActionColor,
-  ActionType actionType = ActionType.confirm,
-}) {
-  final AlertDialog alert = AlertDialog(
-    title: Text(
-      title,
-      style: TextStyle(
-        color: actionType == ActionType.critical
-            ? Colors.red
-            : Theme.of(context).colorScheme.primary,
-      ),
-    ),
-    content: Text(
-      content,
-      style: const TextStyle(
-        height: 1.4,
-      ),
-    ),
-    actions: [
-      TextButton(
-        child: Text(
-          firstAction,
-          style: TextStyle(
-            color: firstActionColor ??
-                (actionType == ActionType.critical
-                    ? Colors.red
-                    : Theme.of(context).colorScheme.onSurface),
-          ),
-        ),
-        onPressed: () {
-          Navigator.of(context, rootNavigator: true)
-              .pop(DialogUserChoice.firstChoice);
-        },
-      ),
-      TextButton(
-        child: Text(
-          secondAction,
-          style: TextStyle(
-            color: secondActionColor ??
-                Theme.of(context).colorScheme.greenAlternative,
-          ),
-        ),
-        onPressed: () {
-          Navigator.of(context, rootNavigator: true)
-              .pop(DialogUserChoice.secondChoice);
-        },
-      ),
-    ],
-  );
-
-  return showDialog(
-    context: context,
-    builder: (BuildContext context) {
-      return alert;
-    },
-    barrierColor: Colors.black87,
-  );
-}

+ 1 - 1
lib/ui/payment/child_subscription_widget.dart

@@ -118,7 +118,7 @@ class ChildSubscriptionWidget extends StatelessWidget {
   }
 
   Future<void> _leaveFamilyPlan(BuildContext context) async {
-    final choice = await showNewChoiceDialog(
+    final choice = await showChoiceDialog(
       context,
       title: "Leave family",
       body: "Are you sure that you want to leave the family plan?",

+ 3 - 3
lib/ui/payment/stripe_subscription_page.dart

@@ -344,7 +344,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
       onPressed: () async {
         bool confirmAction = false;
         if (isRenewCancelled) {
-          final choice = await showNewChoiceDialog(
+          final choice = await showChoiceDialog(
             context,
             title: title,
             body: "Are you sure you want to renew?",
@@ -352,7 +352,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
           );
           confirmAction = choice == ButtonAction.first;
         } else {
-          final choice = await showNewChoiceDialog(
+          final choice = await showChoiceDialog(
             context,
             title: title,
             body: "Are you sure you want to cancel?",
@@ -429,7 +429,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
               String stripPurChaseAction = 'buy';
               if (_isStripeSubscriber && _hasActiveSubscription) {
                 // confirm if user wants to change plan or not
-                final result = await showNewChoiceDialog(
+                final result = await showChoiceDialog(
                   context,
                   title: "Confirm plan change",
                   body: "Are you sure you want to change your plan?",

+ 8 - 41
lib/ui/settings/account_section_widget.dart

@@ -2,7 +2,6 @@ import 'dart:async';
 
 import 'package:flutter/material.dart';
 import 'package:flutter_sodium/flutter_sodium.dart';
-import 'package:photos/ente_theme_data.dart';
 import 'package:photos/services/local_authentication_service.dart';
 import 'package:photos/services/user_service.dart';
 import 'package:photos/theme/ente_theme.dart';
@@ -156,46 +155,14 @@ class AccountSectionWidget extends StatelessWidget {
     );
   }
 
-  Future<void> _onLogoutTapped(BuildContext context) async {
-    final AlertDialog alert = AlertDialog(
-      title: const Text(
-        "Logout",
-        style: TextStyle(
-          color: Colors.red,
-        ),
-      ),
-      content: const Text("Are you sure you want to logout?"),
-      actions: [
-        TextButton(
-          child: const Text(
-            "Yes, logout",
-            style: TextStyle(
-              color: Colors.red,
-            ),
-          ),
-          onPressed: () async {
-            Navigator.of(context, rootNavigator: true).pop('dialog');
-            await UserService.instance.logout(context);
-          },
-        ),
-        TextButton(
-          child: Text(
-            "No",
-            style: TextStyle(
-              color: Theme.of(context).colorScheme.greenAlternative,
-            ),
-          ),
-          onPressed: () {
-            Navigator.of(context, rootNavigator: true).pop('dialog');
-          },
-        ),
-      ],
-    );
-
-    await showDialog(
-      context: context,
-      builder: (BuildContext context) {
-        return alert;
+  void _onLogoutTapped(BuildContext context) {
+    showChoiceActionSheet(
+      context,
+      title: "Are you sure you want to logout?",
+      firstButtonLabel: "Yes, logout",
+      isCritical: true,
+      firstButtonOnTap: () async {
+        await UserService.instance.logout(context);
       },
     );
   }

+ 1 - 1
lib/ui/viewer/gallery/gallery_app_bar_widget.dart

@@ -138,7 +138,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
   }
 
   Future<dynamic> _leaveAlbum(BuildContext context) async {
-    final result = await showNewChoiceDialog(
+    final result = await showChoiceDialog(
       context,
       title: "Leave shared album",
       body: "You will leave the album, and it will stop being visible to you",

+ 12 - 25
lib/utils/delete_file_util.dart

@@ -20,7 +20,6 @@ import 'package:photos/models/trash_item_request.dart';
 import 'package:photos/services/remote_sync_service.dart';
 import 'package:photos/services/sync_service.dart';
 import 'package:photos/services/trash_sync_service.dart';
-import 'package:photos/ui/common/dialogs.dart';
 import 'package:photos/ui/common/linear_progress_dialog.dart';
 import 'package:photos/ui/components/action_sheet_widget.dart';
 import 'package:photos/ui/components/button_widget.dart';
@@ -35,8 +34,6 @@ Future<void> deleteFilesFromEverywhere(
   BuildContext context,
   List<File> files,
 ) async {
-  final dialog = createProgressDialog(context, "Deleting...");
-  await dialog.show();
   _logger.info("Trying to deleteFilesFromEverywhere " + files.toString());
   final List<String> localAssetIDs = [];
   final List<String> localSharedMediaIDs = [];
@@ -60,7 +57,6 @@ Future<void> deleteFilesFromEverywhere(
   if (hasLocalOnlyFiles && Platform.isAndroid) {
     final shouldProceed = await shouldProceedWithDeletion(context);
     if (!shouldProceed) {
-      await dialog.hide();
       return;
     }
   }
@@ -102,12 +98,9 @@ Future<void> deleteFilesFromEverywhere(
           uploadedFilesToBeTrashed.map((item) => item.fileID).toList();
       await TrashSyncService.instance
           .trashFilesOnServer(uploadedFilesToBeTrashed);
-      // await SyncService.instance
-      //     .deleteFilesOnServer(fileIDs);
       await FilesDB.instance.deleteMultipleUploadedFiles(fileIDs);
     } catch (e) {
       _logger.severe(e);
-      await dialog.hide();
       showGenericErrorDialog(context: context);
       rethrow;
     }
@@ -138,7 +131,6 @@ Future<void> deleteFilesFromEverywhere(
       showShortToast(context, "Moved to trash");
     }
   }
-  await dialog.hide();
   if (uploadedFilesToBeTrashed.isNotEmpty) {
     RemoteSyncService.instance.sync(silently: true);
   }
@@ -153,8 +145,6 @@ Future<void> deleteFilesFromRemoteOnly(
     showToast(context, "Selected files are not on ente");
     return;
   }
-  final dialog = createProgressDialog(context, "Deleting...");
-  await dialog.show();
   _logger.info(
     "Trying to deleteFilesFromRemoteOnly " +
         files.map((f) => f.uploadedFileID).toString(),
@@ -172,7 +162,6 @@ Future<void> deleteFilesFromRemoteOnly(
     await FilesDB.instance.deleteMultipleUploadedFiles(uploadedFileIDs);
   } catch (e, s) {
     _logger.severe("Failed to delete files from remote", e, s);
-    await dialog.hide();
     showGenericErrorDialog(context: context);
     rethrow;
   }
@@ -194,7 +183,6 @@ Future<void> deleteFilesFromRemoteOnly(
     ),
   );
   SyncService.instance.sync();
-  await dialog.hide();
   RemoteSyncService.instance.sync(silently: true);
 }
 
@@ -202,8 +190,6 @@ Future<void> deleteFilesOnDeviceOnly(
   BuildContext context,
   List<File> files,
 ) async {
-  final dialog = createProgressDialog(context, "Deleting...");
-  await dialog.show();
   _logger.info("Trying to deleteFilesOnDeviceOnly" + files.toString());
   final List<String> localAssetIDs = [];
   final List<String> localSharedMediaIDs = [];
@@ -227,7 +213,6 @@ Future<void> deleteFilesOnDeviceOnly(
   if (hasLocalOnlyFiles && Platform.isAndroid) {
     final shouldProceed = await shouldProceedWithDeletion(context);
     if (!shouldProceed) {
-      await dialog.hide();
       return;
     }
   }
@@ -258,12 +243,11 @@ Future<void> deleteFilesOnDeviceOnly(
       ),
     );
   }
-  await dialog.hide();
 }
 
 Future<bool> deleteFromTrash(BuildContext context, List<File> files) async {
   bool didDeletionStart = false;
-  final result = await showNewChoiceDialog(
+  final result = await showChoiceDialog(
     context,
     title: "Permanently delete?",
     body: "This action cannot be undone",
@@ -298,7 +282,7 @@ Future<bool> deleteFromTrash(BuildContext context, List<File> files) async {
 }
 
 Future<bool> emptyTrash(BuildContext context) async {
-  final result = await showNewChoiceDialog(
+  final result = await showChoiceDialog(
     context,
     title: "Empty trash?",
     body:
@@ -485,20 +469,23 @@ Future<List<String>> _tryDeleteSharedMediaFiles(List<String> localIDs) {
 Future<bool> shouldProceedWithDeletion(BuildContext context) async {
   final choice = await showChoiceDialog(
     context,
-    "Are you sure?",
-    "Some of the files you are trying to delete are only available on your device and cannot be recovered if deleted",
-    firstAction: "Cancel",
-    secondAction: "Delete",
-    secondActionColor: Colors.red,
+    title: "Are you sure?",
+    body:
+        "Some of the files you are trying to delete are only available on your device and cannot be recovered if deleted",
+    firstButtonLabel: "Delete",
+    isCritical: true,
   );
-  return choice == DialogUserChoice.secondChoice;
+  if (choice == null) {
+    return false;
+  } else {
+    return choice == ButtonAction.first;
+  }
 }
 
 Future<void> showDeleteSheet(
   BuildContext context,
   SelectedFiles selectedFiles,
 ) async {
-  final count = selectedFiles.files.length;
   bool containsUploadedFile = false, containsLocalFile = false;
   for (final file in selectedFiles.files) {
     if (file.uploadedFileID != null) {

+ 44 - 1
lib/utils/dialog_util.dart

@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/ui/common/loading_widget.dart';
 import 'package:photos/ui/common/progress_dialog.dart';
+import 'package:photos/ui/components/action_sheet_widget.dart';
 import 'package:photos/ui/components/button_widget.dart';
 import 'package:photos/ui/components/dialog_widget.dart';
 import 'package:photos/ui/components/models/button_type.dart';
@@ -90,7 +91,7 @@ DialogWidget choiceDialog({
 }
 
 ///Will return null if dismissed by tapping outside
-Future<ButtonAction?> showNewChoiceDialog(
+Future<ButtonAction?> showChoiceDialog(
   BuildContext context, {
   required String title,
   String? body,
@@ -132,6 +133,48 @@ Future<ButtonAction?> showNewChoiceDialog(
   );
 }
 
+///Will return null if dismissed by tapping outside
+Future<ButtonAction?> showChoiceActionSheet(
+  BuildContext context, {
+  required String title,
+  String? body,
+  required String firstButtonLabel,
+  String secondButtonLabel = "Cancel",
+  ButtonType firstButtonType = ButtonType.neutral,
+  ButtonType secondButtonType = ButtonType.secondary,
+  ButtonAction firstButtonAction = ButtonAction.first,
+  ButtonAction secondButtonAction = ButtonAction.cancel,
+  FutureVoidCallback? firstButtonOnTap,
+  FutureVoidCallback? secondButtonOnTap,
+  bool isCritical = false,
+  IconData? icon,
+  bool isDismissible = true,
+}) async {
+  final buttons = [
+    ButtonWidget(
+      buttonType: isCritical ? ButtonType.critical : firstButtonType,
+      labelText: firstButtonLabel,
+      isInAlert: true,
+      onTap: firstButtonOnTap,
+      buttonAction: firstButtonAction,
+    ),
+    ButtonWidget(
+      buttonType: secondButtonType,
+      labelText: secondButtonLabel,
+      isInAlert: true,
+      onTap: secondButtonOnTap,
+      buttonAction: secondButtonAction,
+    ),
+  ];
+  return showActionSheet(
+    context: context,
+    title: title,
+    body: body,
+    buttons: buttons,
+    isDismissible: isDismissible,
+  );
+}
+
 ProgressDialog createProgressDialog(
   BuildContext context,
   String message, {

+ 1 - 1
lib/utils/email_util.dart

@@ -253,7 +253,7 @@ Future<String> _clientInfo() async {
 }
 
 void _showNoMailAppsDialog(BuildContext context, String toEmail) {
-  showNewChoiceDialog(
+  showChoiceDialog(
     context,
     icon: Icons.email_outlined,
     title: 'Please email us at $toEmail',