mirror of
https://github.com/immich-app/immich.git
synced 2026-05-21 07:06:31 -04:00
653c4db355
Adds a "Review remote deletions" mode for trash-sync: when the server marks a remote asset as deleted, the local copy is queued for user review before being moved to the device trash. The existing auto-sync mode (Android-only, requires MANAGE_MEDIA) keeps the silent-mirror behavior. iOS gets the review surface only — auto-sync is hidden because PhotoKit prompts on every batch, defeating the silent intent. State lives on a single trash_sync_entity table keyed by local_asset_id with three decisions (pendingReview / kept / appTrashed) and two trigger sources (remoteSync / localUser). Both review-mode decisions and auto-mode transitions are single-row column updates on the same table, so the cross-repo atomicity bug from the original draft cannot recur structurally. Other shape choices: - UI subscribes to watchPendingReviewCount() to surface a review-badge notification — no event-stream needed. - recheckRemoteTrashCandidates() closes the durability gap from acked assetDeleteV1 events arriving before the local was hashed. - Auto-restore is gated on TrashSyncMode.autoSync; review mode never fires OS-level trash or restore on its own. - Predicates query backup-album selection dynamically via existsQuery, so assets in multiple selected albums aren't dropped during dedup. - getAppTrashedRemotelyRestored joins trashed_local_asset_entity for album reconciliation (the asset leaves local_album_asset_entity after auto-trash but stays in the OS-trash mirror). - Bucket queries use SQL GROUP BY date instead of Dart-side reduce; shared predicate subquery between bucket and asset paths. Co-authored-by: Peter Ombodi <peter.ombodi@gmail.com>