diff --git a/mobile/lib/constants/enums.dart b/mobile/lib/constants/enums.dart index c4505137d2..284a7f1eb1 100644 --- a/mobile/lib/constants/enums.dart +++ b/mobile/lib/constants/enums.dart @@ -11,3 +11,5 @@ enum ActionSource { timeline, viewer } enum CleanupStep { selectDate, filterOptions, scan, delete } enum AssetFilterType { all, photosOnly, videosOnly } + +enum AssetDateAggregation { start, end } diff --git a/mobile/lib/domain/services/remote_album.service.dart b/mobile/lib/domain/services/remote_album.service.dart index 5c0bcd8338..0223a16feb 100644 --- a/mobile/lib/domain/services/remote_album.service.dart +++ b/mobile/lib/domain/services/remote_album.service.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:collection/collection.dart'; +import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; @@ -41,8 +42,8 @@ class RemoteAlbumService { AlbumSortMode.title => albums.sortedBy((album) => album.name), AlbumSortMode.lastModified => albums.sortedBy((album) => album.updatedAt), AlbumSortMode.assetCount => albums.sortedBy((album) => album.assetCount), - AlbumSortMode.mostRecent => await _sortByAssetDate(albums, useMin: false), - AlbumSortMode.mostOldest => await _sortByAssetDate(albums, useMin: true), + AlbumSortMode.mostRecent => await _sortByAssetDate(albums, aggregation: AssetDateAggregation.end), + AlbumSortMode.mostOldest => await _sortByAssetDate(albums, aggregation: AssetDateAggregation.start), }; return (isReverse ? sorted.reversed : sorted).toList(); @@ -169,20 +170,24 @@ class RemoteAlbumService { return _repository.getAlbumsContainingAsset(assetId); } - Future> _sortByAssetDate(List albums, {required bool useMin}) async { + Future> _sortByAssetDate( + List albums, { + required AssetDateAggregation aggregation, + }) async { if (albums.isEmpty) return []; final albumIds = albums.map((e) => e.id).toList(); + final sortedIds = await _repository.getSortedAlbumIds(albumIds, aggregation: aggregation); - final dateMap = await _repository.getAlbumAssetDateMap(albumIds, useMin: useMin); + final albumMap = Map.fromEntries(albums.map((a) => MapEntry(a.id, a))); - final sortedAlbums = List.from(albums); + final sortedAlbums = sortedIds.map((id) => albumMap[id]).whereType().toList(); - sortedAlbums.sort((a, b) { - final aDate = dateMap[a.id] ?? DateTime.fromMillisecondsSinceEpoch(0); - final bDate = dateMap[b.id] ?? DateTime.fromMillisecondsSinceEpoch(0); - return aDate.compareTo(bDate); - }); + if (sortedAlbums.length < albums.length) { + final returnedIdSet = sortedIds.toSet(); + final emptyAlbums = albums.where((a) => !returnedIdSet.contains(a.id)); + sortedAlbums.addAll(emptyAlbums); + } return sortedAlbums; } diff --git a/mobile/lib/infrastructure/repositories/remote_album.repository.dart b/mobile/lib/infrastructure/repositories/remote_album.repository.dart index c6b1bc671f..a594647f19 100644 --- a/mobile/lib/infrastructure/repositories/remote_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/remote_album.repository.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:drift/drift.dart'; +import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; @@ -322,36 +323,32 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { }).watchSingleOrNull(); } - Future> getAlbumAssetDateMap(List albumIds, {required bool useMin}) async { - if (albumIds.isEmpty) return {}; + Future> getSortedAlbumIds(List albumIds, {required AssetDateAggregation aggregation}) async { + if (albumIds.isEmpty) return []; final jsonIds = jsonEncode(albumIds); - final agg = useMin ? 'MIN' : 'MAX'; + final sqlAgg = aggregation == AssetDateAggregation.start ? 'MIN' : 'MAX'; final rows = await _db .customSelect( ''' SELECT raae.album_id, - $agg(rae.local_date_time) AS asset_date + $sqlAgg(rae.local_date_time) AS asset_date FROM json_each(?) ids INNER JOIN remote_album_asset_entity raae ON raae.album_id = ids.value INNER JOIN remote_asset_entity rae ON rae.id = raae.asset_id GROUP BY raae.album_id + ORDER BY asset_date ASC ''', variables: [Variable(jsonIds)], readsFrom: {_db.remoteAlbumAssetEntity, _db.remoteAssetEntity}, ) .get(); - final results = {}; - for (final row in rows) { - results[row.read('album_id')] = row.read('asset_date'); - } - - return results; + return rows.map((row) => row.read('album_id')).toList(); } Future getCount() {