Ver código fonte

Add support for trashing collections

Neeraj Gupta 2 anos atrás
pai
commit
06e619e9b3

+ 37 - 0
lib/services/collections_service.dart

@@ -1,5 +1,6 @@
 // @dart=2.9
 
+import 'dart:async';
 import 'dart:convert';
 import 'dart:math';
 import 'dart:typed_data';
@@ -13,6 +14,7 @@ import 'package:photos/core/errors.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/network.dart';
 import 'package:photos/db/collections_db.dart';
+import 'package:photos/db/device_files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/trash_db.dart';
 import 'package:photos/events/collection_updated_event.dart';
@@ -25,6 +27,7 @@ import 'package:photos/models/file.dart';
 import 'package:photos/models/magic_metadata.dart';
 import 'package:photos/services/app_lifecycle_service.dart';
 import 'package:photos/services/file_magic_service.dart';
+import 'package:photos/services/local_sync_service.dart';
 import 'package:photos/services/remote_sync_service.dart';
 import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/file_download_util.dart';
@@ -241,6 +244,40 @@ class CollectionsService {
     RemoteSyncService.instance.sync(silently: true);
   }
 
+  Future<void> trashCollection(Collection collection) async {
+    try {
+      final deviceCollections = await _filesDB.getDeviceCollections();
+      final Map<String, bool> deivcePathIDsToUnsync = Map.fromEntries(
+        deviceCollections
+            .where((e) => e.shouldBackup && e.collectionID == collection.id)
+            .map((e) => MapEntry(e.id, false)),
+      );
+
+      if (deivcePathIDsToUnsync.isNotEmpty) {
+        _logger.info(
+          'turning off backup status for folders $deivcePathIDsToUnsync',
+        );
+        await RemoteSyncService.instance
+            .updateDeviceFolderSyncStatus(deivcePathIDsToUnsync);
+      }
+      await _dio.delete(
+        Configuration.instance.getHttpEndpoint() +
+            "/collections/v2/${collection.id}",
+        options: Options(
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
+      );
+      await _filesDB.deleteCollection(collection.id);
+      final deletedCollection = collection.copyWith(isDeleted: true);
+      _collectionIDToCollections[collection.id] = deletedCollection;
+      _db.insert([deletedCollection]);
+      unawaited(LocalSyncService.instance.syncAll());
+    } catch (e) {
+      _logger.severe('failed to trash collection', e);
+      rethrow;
+    }
+  }
+
   Uint8List getCollectionKey(int collectionID) {
     if (!_cachedKeys.containsKey(collectionID)) {
       final collection = _collectionIDToCollections[collectionID];

+ 2 - 0
lib/services/remote_sync_service.dart

@@ -13,6 +13,7 @@ import 'package:photos/core/event_bus.dart';
 import 'package:photos/db/device_files_db.dart';
 import 'package:photos/db/file_updation_db.dart';
 import 'package:photos/db/files_db.dart';
+import 'package:photos/events/backup_folders_updated_event.dart';
 import 'package:photos/events/collection_updated_event.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/force_reload_home_gallery_event.dart';
@@ -322,6 +323,7 @@ class RemoteSyncService {
     oldCollectionIDsForAutoSync.removeAll(newCollectionIDsForAutoSync);
     await removeFilesQueuedForUpload(oldCollectionIDsForAutoSync.toList());
     Bus.instance.fire(LocalPhotosUpdatedEvent(<File>[]));
+    Bus.instance.fire(BackupFoldersUpdatedEvent());
   }
 
   Future<void> removeFilesQueuedForUpload(List<int> collectionIDs) async {

+ 0 - 3
lib/ui/backup_folder_selection_page.dart

@@ -9,11 +9,9 @@ import 'package:implicitly_animated_reorderable_list/implicitly_animated_reorder
 import 'package:implicitly_animated_reorderable_list/transitions.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/configuration.dart';
-import 'package:photos/core/event_bus.dart';
 import 'package:photos/db/device_files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/ente_theme_data.dart';
-import 'package:photos/events/backup_folders_updated_event.dart';
 import 'package:photos/models/device_collection.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/services/remote_sync_service.dart';
@@ -193,7 +191,6 @@ class _BackupFolderSelectionPageState extends State<BackupFolderSelectionPage> {
                               _allDevicePathIDs.length ==
                                   _selectedDevicePathIDs.length,
                             );
-                            Bus.instance.fire(BackupFoldersUpdatedEvent());
                             Navigator.of(context).pop();
                           },
                     child: Text(widget.buttonText),

+ 0 - 2
lib/ui/viewer/gallery/device_folder_page.dart

@@ -6,7 +6,6 @@ import 'package:photos/core/event_bus.dart';
 import 'package:photos/db/device_files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/ente_theme_data.dart';
-import 'package:photos/events/backup_folders_updated_event.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/local_photos_updated_event.dart';
 import 'package:photos/models/device_collection.dart';
@@ -120,7 +119,6 @@ class _BackupConfigurationHeaderWidgetState
               );
               _isBackedUp = value;
               setState(() {});
-              Bus.instance.fire(BackupFoldersUpdatedEvent());
             },
           ),
         ],

+ 50 - 2
lib/ui/viewer/gallery/gallery_app_bar_widget.dart

@@ -21,6 +21,7 @@ import 'package:photos/ui/common/rename_dialog.dart';
 import 'package:photos/ui/sharing/share_collection_widget.dart';
 import 'package:photos/utils/dialog_util.dart';
 import 'package:photos/utils/magic_util.dart';
+import 'package:photos/utils/toast_util.dart';
 
 class GalleryAppBarWidget extends StatefulWidget {
   final GalleryType type;
@@ -193,13 +194,26 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
                 ),
               ),
             );
+            items.add(
+              PopupMenuItem(
+                value: 3,
+                child: Row(
+                  children: const [
+                    Icon(Icons.delete_sweep_outlined),
+                    Padding(
+                      padding: EdgeInsets.all(8),
+                    ),
+                    Text("Delete Album"),
+                  ],
+                ),
+              ),
+            );
             return items;
           },
           onSelected: (value) async {
             if (value == 1) {
               await _renameAlbum(context);
-            }
-            if (value == 2) {
+            } else if (value == 2) {
               await changeCollectionVisibility(
                 context,
                 widget.collection,
@@ -207,6 +221,8 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
                     ? kVisibilityVisible
                     : kVisibilityArchive,
               );
+            } else if (value == 3) {
+              await _trashCollection();
             }
           },
         ),
@@ -215,6 +231,38 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
     return actions;
   }
 
+  Future<void> _trashCollection() async {
+    final result = await showChoiceDialog(
+      context,
+      "Delete album?",
+      "Files that are unique to this album "
+          "will be moved to trash, and this album would be deleted.",
+      firstAction: "Cancel",
+      secondAction: "Delete album",
+      secondActionColor: Colors.red,
+    );
+    if (result != DialogUserChoice.secondChoice) {
+      return;
+    }
+    final dialog = createProgressDialog(
+      context,
+      "Please wait, deleting album",
+    );
+    await dialog.show();
+    try {
+      await CollectionsService.instance.trashCollection(widget.collection);
+
+      showShortToast(context, "Successfully deleted album");
+      await dialog.hide();
+      Navigator.of(context).pop();
+    } catch (e, s) {
+      _logger.severe("failed to trash collection", e, s);
+      await dialog.hide();
+      showGenericErrorDialog(context);
+      rethrow;
+    }
+  }
+
   Future<void> _showShareCollectionDialog() async {
     var collection = widget.collection;
     final dialog = createProgressDialog(context, "Please wait...");