diff --git a/mobile/lib/ui/viewer/gallery/component/group/lazy_group_gallery.dart b/mobile/lib/ui/viewer/gallery/component/group/lazy_group_gallery.dart index b7d9e96fb..299d84d7d 100644 --- a/mobile/lib/ui/viewer/gallery/component/group/lazy_group_gallery.dart +++ b/mobile/lib/ui/viewer/gallery/component/group/lazy_group_gallery.dart @@ -105,32 +105,30 @@ class _LazyGroupGalleryState extends State { if (_filesInGroup.isEmpty) { return; } - final DateTime groupDate = - DateTime.fromMicrosecondsSinceEpoch(_filesInGroup[0].creationTime!); + final galleryState = context.findAncestorStateOfType(); + final groupType = GalleryContextState.of(context)!.type; + // iterate over files and check if any of the belongs to this group - final anyCandidateForGroup = event.updatedFiles.any((file) { - final fileDate = DateTime.fromMicrosecondsSinceEpoch(file.creationTime!); - return fileDate.year == groupDate.year && - fileDate.month == groupDate.month && - fileDate.day == groupDate.day; - }); + final anyCandidateForGroup = groupType.areModifiedFilesPartOfGroup( + event.updatedFiles, + _filesInGroup[0], + lastFile: _filesInGroup.last, + ); if (anyCandidateForGroup) { + late int startRange, endRange; + (startRange, endRange) = groupType.getGroupRange(_filesInGroup[0]); if (kDebugMode) { _logger.info( - " files were updated due to ${event.reason} on " + - DateTime.fromMicrosecondsSinceEpoch( - groupDate.microsecondsSinceEpoch, - ).toIso8601String(), + " files were updated due to ${event.reason} on type ${groupType.name} from ${DateTime.fromMicrosecondsSinceEpoch(startRange).toIso8601String()}" + " to ${DateTime.fromMicrosecondsSinceEpoch(endRange).toIso8601String()}", ); } if (event.type == EventType.addedOrUpdated || widget.removalEventTypes.contains(event.type)) { // We are reloading the whole group - final dayStartTime = - DateTime(groupDate.year, groupDate.month, groupDate.day); final result = await widget.asyncLoader( - dayStartTime.microsecondsSinceEpoch, - dayStartTime.microsecondsSinceEpoch + microSecondsInDay - 1, + startRange, + endRange, asc: GalleryContextState.of(context)!.sortOrderAsc, ); @@ -145,7 +143,7 @@ class _LazyGroupGalleryState extends State { //[galleryState] will never be null except when LazyLoadingGallery is //used without Gallery as an ancestor. - final galleryState = context.findAncestorStateOfType(); + if (galleryState?.mounted ?? false) { galleryState!.setState(() {}); _filesInGroup = result.files; diff --git a/mobile/lib/ui/viewer/gallery/component/group/type.dart b/mobile/lib/ui/viewer/gallery/component/group/type.dart index 755124143..f47156591 100644 --- a/mobile/lib/ui/viewer/gallery/component/group/type.dart +++ b/mobile/lib/ui/viewer/gallery/component/group/type.dart @@ -1,5 +1,6 @@ import "package:flutter/widgets.dart"; import "package:intl/intl.dart"; +import "package:photos/core/constants.dart"; import "package:photos/generated/l10n.dart"; import "package:photos/models/file/file.dart"; import "package:photos/utils/date_time_util.dart"; @@ -44,6 +45,91 @@ extension GroupTypeExtension on GroupType { } } + // returns true if the group should be refreshed. + // If groupType is day, it should return true if the list of modified files contains a file that was created on the same day as the first file. + // If groupType is week, it should return true if the list of modified files contains a file that was created in the same week as the first file. + // If groupType is month, it should return true if the list of modified files contains a file that was created in the same month as the first file. + // If groupType is year, it should return true if the list of modified files contains a file that was created in the same year as the first file. + bool areModifiedFilesPartOfGroup( + List modifiedFiles, + EnteFile fistFile, { + EnteFile? lastFile, + }) { + switch (this) { + case GroupType.day: + return modifiedFiles.any( + (file) => areFromSameDay(fistFile.creationTime!, file.creationTime!), + ); + case GroupType.week: + return modifiedFiles.any((file) { + final firstDate = + DateTime.fromMicrosecondsSinceEpoch(fistFile.creationTime!); + final fileDate = + DateTime.fromMicrosecondsSinceEpoch(file.creationTime!); + return areDatesInSameWeek(firstDate, fileDate); + }); + case GroupType.month: + return modifiedFiles.any((file) { + final firstDate = + DateTime.fromMicrosecondsSinceEpoch(fistFile.creationTime!); + final fileDate = + DateTime.fromMicrosecondsSinceEpoch(file.creationTime!); + return firstDate.year == fileDate.year && + firstDate.month == fileDate.month; + }); + case GroupType.year: + return modifiedFiles.any((file) { + final firstDate = + DateTime.fromMicrosecondsSinceEpoch(fistFile.creationTime!); + final fileDate = + DateTime.fromMicrosecondsSinceEpoch(file.creationTime!); + return firstDate.year == fileDate.year; + }); + default: + throw UnimplementedError("not implemented for $this"); + } + } + + // for day, year, month, year type, return the microsecond range of the group + (int, int) getGroupRange(EnteFile file) { + switch (this) { + case GroupType.day: + final date = DateTime.fromMicrosecondsSinceEpoch(file.creationTime!); + final startOfDay = DateTime(date.year, date.month, date.day); + return ( + startOfDay.microsecondsSinceEpoch, + (startOfDay.microsecondsSinceEpoch + microSecondsInDay - 1), + ); + case GroupType.week: + final date = DateTime.fromMicrosecondsSinceEpoch(file.creationTime!); + final startOfWeek = DateTime(date.year, date.month, date.day) + .subtract(Duration(days: date.weekday - 1)); + final endOfWeek = startOfWeek.add(const Duration(days: 7)); + return ( + startOfWeek.microsecondsSinceEpoch, + endOfWeek.microsecondsSinceEpoch - 1 + ); + case GroupType.month: + final date = DateTime.fromMicrosecondsSinceEpoch(file.creationTime!); + final startOfMonth = DateTime(date.year, date.month); + final endOfMonth = DateTime(date.year, date.month + 1); + return ( + startOfMonth.microsecondsSinceEpoch, + endOfMonth.microsecondsSinceEpoch - 1 + ); + case GroupType.year: + final date = DateTime.fromMicrosecondsSinceEpoch(file.creationTime!); + final startOfYear = DateTime(date.year); + final endOfYear = DateTime(date.year + 1); + return ( + startOfYear.microsecondsSinceEpoch, + endOfYear.microsecondsSinceEpoch - 1 + ); + default: + throw UnimplementedError("not implemented for $this"); + } + } + bool areFromSameGroup(EnteFile first, EnteFile second) { switch (this) { case GroupType.day: