From f47fc2c27cabeb696bd2fc0514d563f43830160f Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 4 Jun 2024 17:39:44 +0530 Subject: [PATCH] Add view large file option --- mobile/lib/generated/intl/messages_en.dart | 3 + mobile/lib/generated/l10n.dart | 20 +++ mobile/lib/l10n/intl_en.arb | 2 + .../settings/backup/free_space_options.dart | 137 +++++++++++------- .../ui/viewer/gallery/large_files_page.dart | 90 ++++++++++++ 5 files changed, 198 insertions(+), 54 deletions(-) create mode 100644 mobile/lib/ui/viewer/gallery/large_files_page.dart diff --git a/mobile/lib/generated/intl/messages_en.dart b/mobile/lib/generated/intl/messages_en.dart index 7bb46b787e..d60f7a94c6 100644 --- a/mobile/lib/generated/intl/messages_en.dart +++ b/mobile/lib/generated/intl/messages_en.dart @@ -1533,6 +1533,9 @@ class MessageLookup extends MessageLookupByLibrary { "viewAll": MessageLookupByLibrary.simpleMessage("View all"), "viewAllExifData": MessageLookupByLibrary.simpleMessage("View all EXIF data"), + "viewLargeFiles": MessageLookupByLibrary.simpleMessage("Large files"), + "viewLargeFilesDesc": MessageLookupByLibrary.simpleMessage( + "View files that are consuming the most amount of storage"), "viewLogs": MessageLookupByLibrary.simpleMessage("View logs"), "viewRecoveryKey": MessageLookupByLibrary.simpleMessage("View recovery key"), diff --git a/mobile/lib/generated/l10n.dart b/mobile/lib/generated/l10n.dart index e9925a5eb9..2c7b0a2c38 100644 --- a/mobile/lib/generated/l10n.dart +++ b/mobile/lib/generated/l10n.dart @@ -3482,6 +3482,26 @@ class S { ); } + /// `Large files` + String get viewLargeFiles { + return Intl.message( + 'Large files', + name: 'viewLargeFiles', + desc: '', + args: [], + ); + } + + /// `View files that are consuming the most amount of storage` + String get viewLargeFilesDesc { + return Intl.message( + 'View files that are consuming the most amount of storage', + name: 'viewLargeFilesDesc', + desc: '', + args: [], + ); + } + /// `✨ No duplicates` String get noDuplicates { return Intl.message( diff --git a/mobile/lib/l10n/intl_en.arb b/mobile/lib/l10n/intl_en.arb index 8fca573f86..0830d89759 100644 --- a/mobile/lib/l10n/intl_en.arb +++ b/mobile/lib/l10n/intl_en.arb @@ -483,6 +483,8 @@ "noDeviceThatCanBeDeleted": "You've no files on this device that can be deleted", "removeDuplicates": "Remove duplicates", "removeDuplicatesDesc": "Review and remove files that are exact duplicates.", + "viewLargeFiles": "Large files", + "viewLargeFilesDesc": "View files that are consuming the most amount of storage", "noDuplicates": "✨ No duplicates", "youveNoDuplicateFilesThatCanBeCleared": "You've no duplicate files that can be cleared", "success": "Success", diff --git a/mobile/lib/ui/settings/backup/free_space_options.dart b/mobile/lib/ui/settings/backup/free_space_options.dart index 3619393ee0..1479dfdba8 100644 --- a/mobile/lib/ui/settings/backup/free_space_options.dart +++ b/mobile/lib/ui/settings/backup/free_space_options.dart @@ -20,6 +20,7 @@ import 'package:photos/ui/components/title_bar_title_widget.dart'; import 'package:photos/ui/components/title_bar_widget.dart'; import "package:photos/ui/tools/deduplicate_page.dart"; import "package:photos/ui/tools/free_space_page.dart"; +import "package:photos/ui/viewer/gallery/large_files_page.dart"; import "package:photos/utils/data_util.dart"; import "package:photos/utils/dialog_util.dart"; import 'package:photos/utils/local_settings.dart'; @@ -125,62 +126,90 @@ class _FreeUpSpaceOptionsScreenState extends State { const SizedBox( height: 24, ), - ], - ), - MenuItemWidget( - captionedTextWidget: CaptionedTextWidget( - title: S.of(context).removeDuplicates, - ), - menuItemColor: colorScheme.fillFaint, - trailingWidget: Icon( - Icons.chevron_right_outlined, - color: colorScheme.strokeBase, - ), - singleBorderRadius: 8, - alignCaptionedTextToLeft: true, - trailingIconIsMuted: true, - showOnlyLoadingState: true, - onTap: () async { - List duplicates; - try { - duplicates = await DeduplicationService - .instance - .getDuplicateFiles(); - } catch (e) { - await showGenericErrorDialog( - context: context, - error: e, - ); - return; - } + MenuItemWidget( + captionedTextWidget: CaptionedTextWidget( + title: S.of(context).removeDuplicates, + ), + menuItemColor: colorScheme.fillFaint, + trailingWidget: Icon( + Icons.chevron_right_outlined, + color: colorScheme.strokeBase, + ), + singleBorderRadius: 8, + alignCaptionedTextToLeft: true, + trailingIconIsMuted: true, + showOnlyLoadingState: true, + onTap: () async { + List duplicates; + try { + duplicates = await DeduplicationService + .instance + .getDuplicateFiles(); + } catch (e) { + await showGenericErrorDialog( + context: context, + error: e, + ); + return; + } - if (duplicates.isEmpty) { - unawaited( - showErrorDialog( + if (duplicates.isEmpty) { + unawaited( + showErrorDialog( + context, + S.of(context).noDuplicates, + S + .of(context) + .youveNoDuplicateFilesThatCanBeCleared, + ), + ); + } else { + final DeduplicationResult? result = + await routeToPage( + context, + DeduplicatePage(duplicates), + ); + if (result != null) { + _showDuplicateFilesDeletedDialog( + result, + ); + } + } + }, + ), + Align( + alignment: Alignment.centerLeft, + child: MenuSectionDescriptionWidget( + content: S.of(context).removeDuplicatesDesc, + ), + ), + const SizedBox( + height: 24, + ), + MenuItemWidget( + captionedTextWidget: CaptionedTextWidget( + title: S.of(context).viewLargeFiles, + ), + menuItemColor: colorScheme.fillFaint, + trailingWidget: Icon( + Icons.chevron_right_outlined, + color: colorScheme.strokeBase, + ), + singleBorderRadius: 8, + alignCaptionedTextToLeft: true, + trailingIconIsMuted: true, + showOnlyLoadingState: true, + onTap: () async { + await routeToPage( context, - S.of(context).noDuplicates, - S - .of(context) - .youveNoDuplicateFilesThatCanBeCleared, - ), - ); - } else { - final DeduplicationResult? result = - await routeToPage( - context, - DeduplicatePage(duplicates), - ); - if (result != null) { - _showDuplicateFilesDeletedDialog(result); - } - } - }, - ), - MenuSectionDescriptionWidget( - content: S.of(context).removeDuplicatesDesc, - ), - const SizedBox( - height: 24, + LargeFilesPagePage(), + ); + }, + ), + MenuSectionDescriptionWidget( + content: S.of(context).viewLargeFilesDesc, + ), + ], ), ], ), diff --git a/mobile/lib/ui/viewer/gallery/large_files_page.dart b/mobile/lib/ui/viewer/gallery/large_files_page.dart new file mode 100644 index 0000000000..28c9cfeeb5 --- /dev/null +++ b/mobile/lib/ui/viewer/gallery/large_files_page.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:photos/core/event_bus.dart'; +import 'package:photos/events/collection_meta_event.dart'; +import 'package:photos/events/collection_updated_event.dart'; +import 'package:photos/events/files_updated_event.dart'; +import "package:photos/generated/l10n.dart"; +import "package:photos/models/file/file.dart"; +import 'package:photos/models/file_load_result.dart'; +import 'package:photos/models/gallery_type.dart'; +import 'package:photos/models/selected_files.dart'; +import "package:photos/services/search_service.dart"; +import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.dart'; +import "package:photos/ui/viewer/gallery/component/group/type.dart"; +import 'package:photos/ui/viewer/gallery/gallery.dart'; + +class LargeFilesPagePage extends StatelessWidget { + final String tagPrefix; + final GalleryType appBarType; + final GalleryType overlayType; + final _selectedFiles = SelectedFiles(); + static const int minLargeFileSize = 50 * 1024 * 1024; + + LargeFilesPagePage({ + this.tagPrefix = "Uncategorized_page", + this.appBarType = GalleryType.homepage, + this.overlayType = GalleryType.homepage, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final gallery = Gallery( + asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) async { + final List allFiles = + await SearchService.instance.getAllFiles(); + final filesWithSize = []; + for (final file in allFiles) { + if (file.fileSize != null && file.fileSize! > minLargeFileSize) { + filesWithSize.add(file); + } + } + final FileLoadResult result = FileLoadResult(filesWithSize, false); + return result; + }, + reloadEvent: Bus.instance.on(), + removalEventTypes: const { + EventType.deletedFromRemote, + EventType.deletedFromEverywhere, + EventType.hide, + }, + forceReloadEvents: [ + Bus.instance.on(), + ], + tagPrefix: tagPrefix, + selectedFiles: _selectedFiles, + sortAsyncFn: () => false, + groupType: GroupType.size, + initialFiles: null, + albumName: S.of(context).viewLargeFiles, + ); + return Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(50.0), + child: AppBar( + elevation: 0, + centerTitle: false, + title: Text( + S.of(context).viewLargeFiles, + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 16), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + ), + body: Stack( + alignment: Alignment.bottomCenter, + children: [ + gallery, + FileSelectionOverlayBar( + overlayType, + _selectedFiles, + ), + ], + ), + ); + } +}