mirror of
https://github.com/immich-app/immich
synced 2026-08-22 13:13:05 +00:00
fix(mobile): update trash sync review markers instead of skipping already-reviewed rows
This commit is contained in:
parent
0a699d0d0e
commit
6da802d22e
3 changed files with 25 additions and 12 deletions
|
|
@ -135,15 +135,6 @@ class DriftTrashSyncRepository extends DriftDatabaseRepository {
|
|||
Future<void> _recordReviewAssets(Expression<bool> contentExists, {Expression<DateTime>? remoteDeletedAt}) async {
|
||||
final pending = Constant(TrashSyncStatus.pending.index);
|
||||
final selectedAssetsQuery = _selectedAssetsQuery();
|
||||
final reviewDecisionsQuery = _db.selectOnly(_db.trashSyncEntity)
|
||||
..addColumns([_db.trashSyncEntity.assetId])
|
||||
..where(
|
||||
_db.trashSyncEntity.assetId.equalsExp(_db.localAssetEntity.id) &
|
||||
_db.trashSyncEntity.status.isIn([
|
||||
TrashSyncStatus.reviewRejected.index,
|
||||
TrashSyncStatus.reviewApproved.index,
|
||||
]),
|
||||
);
|
||||
final nonPendingMarkerQuery = _db.selectOnly(_db.trashSyncEntity)
|
||||
..addColumns([_db.trashSyncEntity.assetId])
|
||||
..where(
|
||||
|
|
@ -156,7 +147,6 @@ class DriftTrashSyncRepository extends DriftDatabaseRepository {
|
|||
_db.localAssetEntity.checksum.isNotNull() &
|
||||
contentExists &
|
||||
existsQuery(selectedAssetsQuery) &
|
||||
notExistsQuery(reviewDecisionsQuery) &
|
||||
notExistsQuery(nonPendingMarkerQuery),
|
||||
);
|
||||
if (remoteDeletedAt != null) {
|
||||
|
|
@ -184,7 +174,15 @@ class DriftTrashSyncRepository extends DriftDatabaseRepository {
|
|||
_db.trashSyncEntity.assetUpdatedAt: _db.localAssetEntity.updatedAt,
|
||||
if (remoteDeletedAt != null) _db.trashSyncEntity.remoteDeletedAt: remoteDeletedAt,
|
||||
},
|
||||
mode: .insertOrReplace,
|
||||
onConflict: DoUpdate.withExcluded(
|
||||
(old, excluded) => remoteDeletedAt != null
|
||||
? TrashSyncEntityCompanion.custom(
|
||||
status: excluded.status,
|
||||
assetUpdatedAt: excluded.assetUpdatedAt,
|
||||
remoteDeletedAt: excluded.remoteDeletedAt,
|
||||
)
|
||||
: TrashSyncEntityCompanion.custom(status: excluded.status, assetUpdatedAt: excluded.assetUpdatedAt),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
|||
|
||||
ActionIconButtonWidget(action: FavoriteAction(assets: assetForAction)),
|
||||
|
||||
ViewerKebabMenu(originalTheme: originalTheme),
|
||||
ImmichColorOverride(color: null, child: ViewerKebabMenu(originalTheme: originalTheme)),
|
||||
];
|
||||
|
||||
final lockedViewActions = <Widget>[ViewerKebabMenu(originalTheme: originalTheme)];
|
||||
|
|
|
|||
|
|
@ -195,6 +195,21 @@ void main() {
|
|||
expect(rows.single.assetUpdatedAt, existingUpdatedAt);
|
||||
});
|
||||
|
||||
test('preserves remoteDeletedAt when a hard-delete pass matches an already pending review marker', () async {
|
||||
final existingDeletedAt = DateTime(2026, 1, 1);
|
||||
final asset = await backedUpAsset(ownerId: userId, remoteDeletedAt: existingDeletedAt);
|
||||
|
||||
await sut.recordSoftDeleteReviewAssets();
|
||||
// Simulates the same checksum also being recorded as hard-deleted (e.g. reused content),
|
||||
// without the remote row being removed first, so the pending marker stays matchable by both passes.
|
||||
await sut.recordHardDeletedChecksums([asset.remoteId]);
|
||||
await sut.recordHardDeletedReviewAssets();
|
||||
|
||||
final rows = await ctx.db.select(ctx.db.trashSyncEntity).get();
|
||||
expect(rows.single.status, TrashSyncStatus.pending);
|
||||
expect(rows.single.remoteDeletedAt, existingDeletedAt.toUtc());
|
||||
});
|
||||
|
||||
test('rejecting an asset without a pending marker does not create a review decision', () async {
|
||||
final asset = await backedUpAsset(ownerId: userId, remoteDeletedAt: DateTime(2026, 1, 1));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue