Skip to content

feat: Tell the user when an artwork is already in the gallery - #80

Merged
mrtncode merged 2 commits into
mrtncode:mainfrom
SirTerrific:pr-duplicate-uploads
Aug 13, 2026
Merged

feat: Tell the user when an artwork is already in the gallery#80
mrtncode merged 2 commits into
mrtncode:mainfrom
SirTerrific:pr-duplicate-uploads

Conversation

@SirTerrific

Copy link
Copy Markdown
Contributor

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:

  • Rows that predate the column have no hash and never match, so nothing has to be backfilled for this to work. Upload a file again and it picks one up.
  • A twin whose file has since been deleted is ignored — pointing at something that is no longer there helps nobody.

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 empty alembic_version; adding it again would abort the upgrade.

Verified in a container both ways: a database created by current main then upgraded, and a fresh install.

⚠️ This migration and the one in #72 both descend from 601a7cee3cbb. Whichever merges second needs its down_revision repointed 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

@SirTerrific

Copy link
Copy Markdown
Contributor Author

Pushed a second commit that belongs with this one: POST /api/images/reconcile, plus a Check the library button in settings.

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.

@mrtncode mrtncode added the enhancement New feature or request label Aug 11, 2026
SirTerrific and others added 2 commits August 12, 2026 19:16
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>
@SirTerrific
SirTerrific force-pushed the pr-duplicate-uploads branch from 16b0698 to 2c5649f Compare August 12, 2026 23:31
@SirTerrific

Copy link
Copy Markdown
Contributor Author

Rebased on main — conflicts gone, and the two loose ends from the description are tied off now that the slideshow and backup PRs have landed:

  • The migration now descends from b7c3d1e9f204 (the slideshow one) instead of 601a7cee3cbb, so there is a single head. Verified in a container: a database created by current main upgrades to d3f1a7c25b90 (head), and a fresh install stamps clean.
  • The two settings cards are merged into one, as offered — "Library" now holds both Download a backup and Check the library, rather than two adjacent cards saying similar things.

70 tests pass, frontend typechecks and builds.

@mrtncode
mrtncode merged commit 9d8ac64 into mrtncode:main Aug 13, 2026
2 checks passed
@mrtncode

Copy link
Copy Markdown
Owner

Thank you! Nice stuff!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants