110 lines
4.2 KiB
Dart
110 lines
4.2 KiB
Dart
import 'package:collection/collection.dart';
|
|
import 'package:drift/drift.dart';
|
|
import 'package:immich_mobile/constants/constants.dart';
|
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|
import 'package:immich_mobile/infrastructure/entities/trash_sync.entity.drift.dart';
|
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
|
|
|
class DriftTrashSyncRepository extends DriftDatabaseRepository {
|
|
final Drift _db;
|
|
|
|
const DriftTrashSyncRepository(this._db) : super(_db);
|
|
|
|
Future<void> upsertReviewCandidates(Iterable<LocalAsset> itemsToReview) async {
|
|
if (itemsToReview.isEmpty) {
|
|
return Future.value();
|
|
}
|
|
|
|
final existingEntities = <TrashSyncEntityData>[];
|
|
final checksums = itemsToReview.map((e) => e.checksum).nonNulls;
|
|
for (final slice in checksums.slices(kDriftMaxChunk)) {
|
|
final sliceResult = await (_db.trashSyncEntity.select()..where((tbl) => tbl.checksum.isIn(slice))).get();
|
|
existingEntities.addAll(sliceResult);
|
|
}
|
|
|
|
final existingMap = {for (var e in existingEntities) e.checksum: e};
|
|
return _db.batch((batch) {
|
|
for (var item in itemsToReview) {
|
|
final existing = existingMap[item.checksum];
|
|
if (existing == null || (existing.isSyncApproved == false && item.deletedAt!.isAfter(existing.updatedAt))) {
|
|
batch.insert(
|
|
_db.trashSyncEntity,
|
|
TrashSyncEntityCompanion.insert(checksum: item.checksum!, updatedAt: Value(item.deletedAt!)),
|
|
onConflict: DoUpdate(
|
|
(_) => TrashSyncEntityCompanion.custom(
|
|
updatedAt: Variable(item.deletedAt),
|
|
isSyncApproved: const Variable(null),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
Future<void> updateApproves(Iterable<String> checksums, bool isSyncApproved) {
|
|
if (checksums.isEmpty) {
|
|
return Future.value();
|
|
}
|
|
return _db.batch((batch) {
|
|
batch.update(
|
|
_db.trashSyncEntity,
|
|
TrashSyncEntityCompanion(isSyncApproved: Value(isSyncApproved)),
|
|
where: (tbl) => tbl.checksum.isIn(checksums),
|
|
);
|
|
});
|
|
}
|
|
|
|
Future<int> deleteOutdated() async {
|
|
final remoteAliveSelect = _db.selectOnly(_db.remoteAssetEntity)
|
|
..addColumns([_db.remoteAssetEntity.checksum])
|
|
..where(_db.remoteAssetEntity.deletedAt.isNull());
|
|
|
|
final localTrashedSelect = _db.selectOnly(_db.trashedLocalAssetEntity)
|
|
..addColumns([_db.trashedLocalAssetEntity.checksum]);
|
|
|
|
final query = _db.delete(_db.trashSyncEntity)
|
|
..where((row) => row.isSyncApproved.isNull() | row.isSyncApproved.equals(false))
|
|
..where((row) => row.checksum.isInQuery(remoteAliveSelect) | row.checksum.isInQuery(localTrashedSelect));
|
|
|
|
final deletedMatched = await query.go();
|
|
|
|
final localTrashedChecksums = _db.selectOnly(_db.trashedLocalAssetEntity)
|
|
..addColumns([_db.trashedLocalAssetEntity.checksum])
|
|
..where(_db.trashedLocalAssetEntity.checksum.isNotNull());
|
|
|
|
final localAssetChecksums = _db.selectOnly(_db.localAssetEntity)
|
|
..addColumns([_db.localAssetEntity.checksum])
|
|
..where(_db.localAssetEntity.checksum.isNotNull());
|
|
|
|
final orphanQuery = _db.delete(_db.trashSyncEntity)
|
|
..where(
|
|
(row) =>
|
|
(row.isSyncApproved.equals(false) & row.checksum.isNotInQuery(localAssetChecksums)) |
|
|
(row.isSyncApproved.equals(true) & row.checksum.isNotInQuery(localTrashedChecksums)),
|
|
);
|
|
|
|
final deletedOrphans = await orphanQuery.go();
|
|
|
|
return deletedMatched + deletedOrphans;
|
|
}
|
|
|
|
Stream<int> watchPendingApprovalCount() {
|
|
final countExpr = _db.trashSyncEntity.checksum.count(distinct: true);
|
|
|
|
final q = _db.selectOnly(_db.trashSyncEntity)
|
|
..addColumns([countExpr])
|
|
..where(_db.trashSyncEntity.isSyncApproved.isNull());
|
|
|
|
return q.watchSingle().map((row) => row.read(countExpr) ?? 0).distinct();
|
|
}
|
|
|
|
Stream<bool> watchIsApprovalPending(String checksum) {
|
|
final query = _db.selectOnly(_db.trashSyncEntity)
|
|
..addColumns([_db.trashSyncEntity.checksum])
|
|
..where((_db.trashSyncEntity.checksum.equals(checksum) & _db.trashSyncEntity.isSyncApproved.isNull()))
|
|
..limit(1);
|
|
return query.watchSingleOrNull().map((row) => row != null).distinct();
|
|
}
|
|
}
|