refactor(mobile): simplify local sync and hash service (#18970)

* Hash service review changes

* local album repo test

* simplify local album repo method names

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong
2025-06-09 08:26:44 +05:30
committed by GitHub
parent 5574b2dd39
commit 84024f6cdc
8 changed files with 198 additions and 77 deletions
@@ -3,11 +3,11 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/local_album.model.dart';
abstract interface class ILocalAlbumRepository implements IDatabaseRepository {
Future<List<LocalAlbum>> getAll({SortLocalAlbumsBy? sortBy});
Future<List<LocalAlbum>> getAll({Set<SortLocalAlbumsBy> sortBy = const {}});
Future<List<LocalAsset>> getAssetsForAlbum(String albumId);
Future<List<LocalAsset>> getAssets(String albumId);
Future<List<String>> getAssetIdsForAlbum(String albumId);
Future<List<String>> getAssetIds(String albumId);
Future<void> upsert(
LocalAlbum album, {
@@ -25,12 +25,9 @@ abstract interface class ILocalAlbumRepository implements IDatabaseRepository {
required Map<String, List<String>> assetAlbums,
});
Future<void> syncAlbumDeletes(
String albumId,
Iterable<String> assetIdsToKeep,
);
Future<void> syncDeletes(String albumId, Iterable<String> assetIdsToKeep);
Future<List<LocalAsset>> getAssetsToHash(String albumId);
}
enum SortLocalAlbumsBy { id }
enum SortLocalAlbumsBy { id, backupSelection, isIosSharedAlbum }
@@ -1,12 +1,10 @@
enum BackupSelection {
none._(1),
selected._(0),
excluded._(2);
// Used to sort albums based on the backupSelection
// selected -> none -> excluded
final int sortOrder;
const BackupSelection._(this.sortOrder);
// Do not change the order of these values
selected,
none,
excluded,
}
class LocalAlbum {
+14 -15
View File
@@ -33,18 +33,12 @@ class HashService {
Future<void> hashAssets() async {
final Stopwatch stopwatch = Stopwatch()..start();
// Sorted by backupSelection followed by isCloud
final localAlbums = await _localAlbumRepository.getAll();
localAlbums.sort((a, b) {
final backupComparison =
a.backupSelection.sortOrder.compareTo(b.backupSelection.sortOrder);
if (backupComparison != 0) {
return backupComparison;
}
// Local albums come before iCloud albums
return (a.isIosSharedAlbum ? 1 : 0).compareTo(b.isIosSharedAlbum ? 1 : 0);
});
final localAlbums = await _localAlbumRepository.getAll(
sortBy: {
SortLocalAlbumsBy.backupSelection,
SortLocalAlbumsBy.isIosSharedAlbum,
},
);
for (final album in localAlbums) {
final assetsToHash =
@@ -96,13 +90,18 @@ class HashService {
final hashed = <LocalAsset>[];
final hashes =
await _nativeSyncApi.hashPaths(toHash.map((e) => e.path).toList());
assert(
hashes.length == toHash.length,
"Hashes length does not match toHash length: ${hashes.length} != ${toHash.length}",
);
for (final (index, hash) in hashes.indexed) {
final asset = toHash[index].asset;
for (int i = 0; i < hashes.length; i++) {
final hash = hashes[i];
final asset = toHash[i].asset;
if (hash?.length == 20) {
hashed.add(asset.copyWith(checksum: base64.encode(hash!)));
} else {
_log.warning("Failed to hash file ${asset.id}");
_log.warning("Failed to hash file for ${asset.id}");
}
}
@@ -66,7 +66,7 @@ class LocalSyncService {
if (_platform.isAndroid) {
for (final album in dbAlbums) {
final deviceIds = await _nativeSyncApi.getAssetIdsForAlbum(album.id);
await _localAlbumRepository.syncAlbumDeletes(album.id, deviceIds);
await _localAlbumRepository.syncDeletes(album.id, deviceIds);
}
}
@@ -113,7 +113,7 @@ class LocalSyncService {
}
final dbAlbums =
await _localAlbumRepository.getAll(sortBy: SortLocalAlbumsBy.id);
await _localAlbumRepository.getAll(sortBy: {SortLocalAlbumsBy.id});
await diffSortedLists(
dbAlbums,
@@ -252,7 +252,7 @@ class LocalSyncService {
.then((a) => a.toLocalAssets())
: <LocalAsset>[];
final assetsInDb = dbAlbum.assetCount > 0
? await _localAlbumRepository.getAssetsForAlbum(dbAlbum.id)
? await _localAlbumRepository.getAssets(dbAlbum.id)
: <LocalAsset>[];
if (deviceAlbum.assetCount == 0) {