diff --git a/mobile/lib/ui/viewer/gallery/component/group/type.dart b/mobile/lib/ui/viewer/gallery/component/group/type.dart index f47156591..19b1224de 100644 --- a/mobile/lib/ui/viewer/gallery/component/group/type.dart +++ b/mobile/lib/ui/viewer/gallery/component/group/type.dart @@ -5,7 +5,14 @@ import "package:photos/generated/l10n.dart"; import "package:photos/models/file/file.dart"; import "package:photos/utils/date_time_util.dart"; -enum GroupType { day, week, month, size, year } +enum GroupType { + day, + week, + month, + size, + year, + none, +} extension GroupTypeExtension on GroupType { String get name { @@ -20,9 +27,25 @@ extension GroupTypeExtension on GroupType { return "size"; case GroupType.year: return "year"; + case GroupType.none: + return "none"; } } + bool timeGrouping() { + return this == GroupType.day || + this == GroupType.week || + this == GroupType.month || + this == GroupType.year; + } + + bool showGroupHeader() { + if (this == GroupType.size || this == GroupType.none) { + return false; + } + return true; + } + String getTitle(BuildContext context, EnteFile file, {EnteFile? lastFile}) { if (this == GroupType.day) { return _getDayTitle(context, file.creationTime!); @@ -41,7 +64,7 @@ extension GroupTypeExtension on GroupType { return DateFormat.yMMM(Localizations.localeOf(context).languageCode) .format(date); } else { - throw UnimplementedError("not implemented for $this"); + throw UnimplementedError("getTitle not implemented for $this"); } } diff --git a/mobile/lib/ui/viewer/gallery/component/multiple_groups_gallery_view.dart b/mobile/lib/ui/viewer/gallery/component/multiple_groups_gallery_view.dart index 094f915d3..e7ad53f46 100644 --- a/mobile/lib/ui/viewer/gallery/component/multiple_groups_gallery_view.dart +++ b/mobile/lib/ui/viewer/gallery/component/multiple_groups_gallery_view.dart @@ -9,7 +9,10 @@ import "package:photos/models/selected_files.dart"; import "package:photos/ui/common/loading_widget.dart"; import "package:photos/ui/huge_listview/huge_listview.dart"; import 'package:photos/ui/viewer/gallery/component/group/lazy_group_gallery.dart'; +import "package:photos/ui/viewer/gallery/component/group/type.dart"; import "package:photos/ui/viewer/gallery/gallery.dart"; +import "package:photos/ui/viewer/gallery/state/gallery_context_state.dart"; +import "package:photos/utils/data_util.dart"; import "package:photos/utils/local_settings.dart"; import "package:scrollable_positioned_list/scrollable_positioned_list.dart"; @@ -65,6 +68,7 @@ class MultipleGroupsGalleryView extends StatelessWidget { @override Widget build(BuildContext context) { + final gType = GalleryContextState.of(context)!.type; return HugeListView>( controller: itemScroller, startIndex: 0, @@ -123,10 +127,17 @@ class MultipleGroupsGalleryView extends StatelessWidget { }, labelTextBuilder: (int index) { try { + final EnteFile file = groupedFiles[index][0]; + if (gType == GroupType.size) { + return file.fileSize != null + ? convertBytesToReadableFormat(file.fileSize!) + : ""; + } + return DateFormat.yMMM(Localizations.localeOf(context).languageCode) .format( DateTime.fromMicrosecondsSinceEpoch( - groupedFiles[index][0].creationTime!, + file.creationTime!, ), ); } catch (e) { diff --git a/mobile/lib/ui/viewer/gallery/gallery.dart b/mobile/lib/ui/viewer/gallery/gallery.dart index 45a732ad0..b7edda271 100644 --- a/mobile/lib/ui/viewer/gallery/gallery.dart +++ b/mobile/lib/ui/viewer/gallery/gallery.dart @@ -214,7 +214,9 @@ class GalleryState extends State { // gallery reload bool _onFilesLoaded(List files) { final updatedGroupedFiles = - widget.enableFileGrouping ? _groupFiles(files) : [files]; + widget.enableFileGrouping && widget.groupType.timeGrouping() + ? _groupBasedOnTime(files) + : _genericGroupForPerf(files); if (currentGroupedFiles.length != updatedGroupedFiles.length || currentGroupedFiles.isEmpty) { if (mounted) { @@ -261,20 +263,52 @@ class GalleryState extends State { tagPrefix: widget.tagPrefix, scrollBottomSafeArea: widget.scrollBottomSafeArea, limitSelectionToOne: widget.limitSelectionToOne, - enableFileGrouping: widget.enableFileGrouping, + enableFileGrouping: + widget.enableFileGrouping && widget.groupType.showGroupHeader(), logTag: _logTag, logger: _logger, reloadEvent: widget.reloadEvent, header: widget.header, footer: widget.footer, selectedFiles: widget.selectedFiles, - showSelectAllByDefault: widget.showSelectAllByDefault, + showSelectAllByDefault: + widget.showSelectAllByDefault && widget.groupType.showGroupHeader(), isScrollablePositionedList: widget.isScrollablePositionedList, ), ); } - List> _groupFiles(List files) { + // create groups of 200 files for performance + List> _genericGroupForPerf(List files) { + if (widget.groupType == GroupType.size) { + // sort files by fileSize on the bases of _sortOrderAsc + files.sort((a, b) { + if (_sortOrderAsc) { + return a.fileSize!.compareTo(b.fileSize!); + } else { + return b.fileSize!.compareTo(a.fileSize!); + } + }); + } + + final List> resultGroupedFiles = []; + List singleGroupFile = []; + const int groupSize = 40; + for (int i = 0; i < files.length; i += 1) { + singleGroupFile.add(files[i]); + if (singleGroupFile.length == groupSize) { + resultGroupedFiles.add(singleGroupFile); + singleGroupFile = []; + } + } + if (singleGroupFile.isNotEmpty) { + resultGroupedFiles.add(singleGroupFile); + } + _logger.info('Grouped files into ${resultGroupedFiles.length} groups'); + return resultGroupedFiles; + } + + List> _groupBasedOnTime(List files) { List dailyFiles = []; final List> resultGroupedFiles = [];