Переглянути джерело

Feature: Add support for deleting empty albums

Neeraj Gupta 2 роки тому
батько
коміт
9877af76e7

+ 11 - 3
lib/ui/collections_gallery_widget.dart

@@ -1,5 +1,3 @@
-
-
 import 'dart:async';
 
 import 'package:collection/collection.dart';
@@ -22,6 +20,7 @@ import 'package:photos/ui/collections/remote_collections_grid_view_widget.dart';
 import 'package:photos/ui/collections/section_title.dart';
 import 'package:photos/ui/collections/trash_button_widget.dart';
 import 'package:photos/ui/common/loading_widget.dart';
+import 'package:photos/ui/viewer/actions/delete_empty_albums.dart';
 import 'package:photos/ui/viewer/gallery/empty_state.dart';
 import 'package:photos/utils/local_settings.dart';
 
@@ -37,7 +36,8 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
     with AutomaticKeepAliveClientMixin {
   final _logger = Logger((_CollectionsGalleryWidgetState).toString());
   late StreamSubscription<LocalPhotosUpdatedEvent> _localFilesSubscription;
-  late StreamSubscription<CollectionUpdatedEvent> _collectionUpdatesSubscription;
+  late StreamSubscription<CollectionUpdatedEvent>
+      _collectionUpdatesSubscription;
   late StreamSubscription<UserLoggedOutEvent> _loggedOutEvent;
   AlbumSortKey? sortKey;
   String _loadReason = "init";
@@ -123,6 +123,8 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
   Widget _getCollectionsGalleryWidget(
     List<CollectionWithThumbnail>? collections,
   ) {
+    final bool showDeleteAlbumsButton =
+        collections!.where((c) => c.thumbnail == null).length > 4;
     final TextStyle trashAndHiddenTextStyle = Theme.of(context)
         .textTheme
         .subtitle1!
@@ -149,6 +151,12 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
                 _sortMenu(),
               ],
             ),
+            showDeleteAlbumsButton
+                ? const Padding(
+                    padding: EdgeInsets.only(top: 2, left: 8.5, right: 48),
+                    child: DeleteEmptyAlbums(),
+                  )
+                : const SizedBox.shrink(),
             const SizedBox(height: 12),
             Configuration.instance.hasConfiguredAccount()
                 ? RemoteCollectionsGridViewWidget(collections)

+ 106 - 0
lib/ui/viewer/actions/delete_empty_albums.dart

@@ -0,0 +1,106 @@
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:photos/core/event_bus.dart';
+import 'package:photos/events/collection_updated_event.dart';
+import 'package:photos/models/file.dart';
+import 'package:photos/services/collections_service.dart';
+import 'package:photos/ui/components/action_sheet_widget.dart';
+import 'package:photos/ui/components/button_widget.dart';
+import 'package:photos/ui/components/models/button_type.dart';
+
+class DeleteEmptyAlbums extends StatefulWidget {
+  const DeleteEmptyAlbums({Key? key}) : super(key: key);
+
+  @override
+  State<DeleteEmptyAlbums> createState() => _DeleteEmptyAlbumsState();
+}
+
+class _DeleteEmptyAlbumsState extends State<DeleteEmptyAlbums> {
+  final ValueNotifier<String> _deleteProgress = ValueNotifier("");
+  bool _isCancelled = false;
+
+  @override
+  Widget build(BuildContext context) {
+    return Align(
+      alignment: Alignment.centerLeft,
+      child: ButtonWidget(
+        buttonSize: ButtonSize.small,
+        buttonType: ButtonType.secondary,
+        labelText: "Delete empty albums",
+        icon: Icons.delete_sweep_outlined,
+        shouldSurfaceExecutionStates: false,
+        onTap: () async {
+          await showActionSheet(
+            context: context,
+            isDismissible: false,
+            buttons: [
+              ButtonWidget(
+                labelText: "Yes",
+                buttonType: ButtonType.neutral,
+                buttonSize: ButtonSize.large,
+                shouldStickToDarkTheme: true,
+                shouldSurfaceExecutionStates: true,
+                progressStatus: _deleteProgress,
+                onTap: () async {
+                  await _deleteEmptyAlbums();
+                  if (!_isCancelled) {
+                    Navigator.of(context, rootNavigator: true).pop();
+                  }
+                  Bus.instance.fire(
+                    CollectionUpdatedEvent(
+                      0,
+                      <File>[],
+                      "empty_albums_deleted",
+                    ),
+                  );
+                  CollectionsService.instance.sync().ignore();
+                  _isCancelled = false;
+                },
+              ),
+              ButtonWidget(
+                labelText: "Cancel",
+                buttonType: ButtonType.secondary,
+                buttonSize: ButtonSize.large,
+                shouldStickToDarkTheme: true,
+                onTap: () async {
+                  _isCancelled = true;
+                  Navigator.of(context, rootNavigator: true).pop();
+                },
+              )
+            ],
+            title: "Delete empty albums",
+            body:
+                "This will delete all empty albums. This is useful when you want to reduce the clutter in your album list.",
+            actionSheetType: ActionSheetType.defaultActionSheet,
+          );
+        },
+      ),
+    );
+  }
+
+  Future<bool> _deleteEmptyAlbums() async {
+    final collections =
+        await CollectionsService.instance.getCollectionsWithThumbnails();
+    collections.removeWhere((element) => element.thumbnail != null);
+    int failedCount = 0;
+    for (int i = 0; i < collections.length; i++) {
+      if (mounted && !_isCancelled) {
+        _deleteProgress.value =
+            "Deleting ${(i + 1).toString().padLeft(collections.length.toString().length, '0')}/ "
+            "${collections.length} ";
+        try {
+          await CollectionsService.instance
+              .trashEmptyCollections(collections[i].collection);
+        } catch (_) {
+          failedCount++;
+        }
+      } else {
+        return false;
+      }
+    }
+    if (failedCount > 0) {
+      debugPrint("Delete ops failed for $failedCount collections");
+    }
+    return true;
+  }
+}