feat(mobile): add album asset sync (#19522)

* feat(mobile): add album asset sync

* add SyncAlbumToAssetDeleteV1 to openapi-spec

* update delete queries to use where in statements

* clear remote album when clear remote data

* fix: bad merge

* fix: bad merge

* fix: _SyncAckV1 return type

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: wuzihao051119 <wuzihao051119@outlook.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
shenlong
2025-06-26 19:20:39 +05:30
committed by GitHub
parent 24a4cba953
commit ea3a14ed25
39 changed files with 3059 additions and 100 deletions
@@ -6,6 +6,7 @@ import 'package:immich_mobile/constants/constants.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/timeline.model.dart';
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:stream_transform/stream_transform.dart';
@@ -139,6 +140,62 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
.map((row) => row.readTable(_db.localAssetEntity).toDto())
.get();
}
Stream<List<Bucket>> watchRemoteBucket(
String albumId, {
GroupAssetsBy groupBy = GroupAssetsBy.day,
}) {
if (groupBy == GroupAssetsBy.none) {
return _db.remoteAlbumAssetEntity
.count(where: (row) => row.albumId.equals(albumId))
.map(_generateBuckets)
.watchSingle();
}
final assetCountExp = _db.remoteAssetEntity.id.count();
final dateExp = _db.remoteAssetEntity.createdAt.dateFmt(groupBy);
final query = _db.remoteAssetEntity.selectOnly()
..addColumns([assetCountExp, dateExp])
..join([
innerJoin(
_db.remoteAlbumAssetEntity,
_db.remoteAlbumAssetEntity.assetId
.equalsExp(_db.remoteAssetEntity.id),
),
])
..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId))
..groupBy([dateExp])
..orderBy([OrderingTerm.desc(dateExp)]);
return query.map((row) {
final timeline = row.read(dateExp)!.dateFmt(groupBy);
final assetCount = row.read(assetCountExp)!;
return TimeBucket(date: timeline, assetCount: assetCount);
}).watch();
}
Future<List<BaseAsset>> getRemoteBucketAssets(
String albumId, {
required int offset,
required int count,
}) {
final query = _db.remoteAssetEntity.select().join(
[
innerJoin(
_db.remoteAlbumAssetEntity,
_db.remoteAlbumAssetEntity.assetId
.equalsExp(_db.remoteAssetEntity.id),
),
],
)
..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId))
..orderBy([OrderingTerm.desc(_db.remoteAssetEntity.createdAt)])
..limit(count, offset: offset);
return query
.map((row) => row.readTable(_db.remoteAssetEntity).toDto())
.get();
}
}
extension on Expression<DateTime> {