feat: Tell the user when an artwork is already in the gallery - #80
Conversation
|
Pushed a second commit that belongs with this one: It fills in the hashes of images uploaded before the column existed — which is what makes duplicate detection cover an existing library rather than only new uploads — and while it is walking the folder it also picks up files added or removed outside the app and reports the groups that turn out to be the same artwork. Album membership is never touched. Happy to split it back out if you would rather review it separately. 7 tests, 32 pass. |
The same image under two names became two entries with no sign they were the same, which shows up after a few rounds of importing from a phone. Uploads are hashed with sha256 and matched against the existing rows. The file is still stored — silently dropping something someone asked to upload would be worse — but the response carries `duplicate_of`, and the gallery says which existing image it matches. Rows that predate the column simply have no hash and never match, so nothing has to be backfilled for the feature to work; a file uploaded again picks one up. A twin whose file has since been deleted is ignored, since pointing at something that is no longer there helps nobody. The migration adds one nullable column and its index, checking first: the app calls create_all() at startup, so on a fresh install the column is already there by the time alembic runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Files get added or removed underneath the app — copied in over a share, cleaned up by hand — and the database drifts. Rows whose file is gone make the gallery offer images that cannot be served; files with no row are invisible to anything that reads the database. `POST /api/images/reconcile` adds rows for untracked files, drops rows whose file is gone, fills in the hashes of images uploaded before there was a hash column, and reports the groups of files that turn out to be the same artwork. Album membership is never touched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
16b0698 to
2c5649f
Compare
|
Rebased on
70 tests pass, frontend typechecks and builds. |
|
Thank you! Nice stuff! |
The same image under two names becomes two entries with no sign they are the same. That shows up quickly after a few rounds of importing from a phone, where filenames differ but the content does not.
What this does
Uploads are hashed with sha256 and matched against existing rows. The file is still stored — silently dropping something someone asked to upload would be worse — but the response carries
duplicate_of, and the gallery says which existing image it matches.Two deliberate non-cases:
Migration
One nullable column plus its index, each checked before it is added. The app calls
create_all()at startup, so on a fresh install the column is already present by the time alembic runs against an emptyalembic_version; adding it again would abort the upgrade.Verified in a container both ways: a database created by current
mainthen upgraded, and a fresh install.601a7cee3cbb. Whichever merges second needs itsdown_revisionrepointed at the other — one line. Happy to do that on whichever you take last.4 tests added, 29 pass. Frontend typechecks and builds.
🤖 Generated with Claude Code