docs(admin): hash conflicts page — the duplicate-content queue
Sixth admin page. Documents what creates conflict groups (scanner at scan time + the hash backfill retroactively), the group card anatomy (count badge, library + short SHA-256, per-copy rows with usage summary highlighted when that copy holds reading data), and both resolutions with verified semantics: Keep this copy (reparents the other copies' children into the kept copy, deletes their catalog rows, records the resolver — files on disk never touched, consistent with platform-wide delete semantics) and Keep both (mark resolved, stop flagging, nothing merged). Glossary gains Keep both and Keep this copy.
This commit is contained in:
1 parent
3e55ddd88a
commit
aee1aafc74
2 files changed
+64
No files matched your search
@@ -0,0 +1,56 @@
|
|||||||
|
<!-- Ground truth: templates/admin_hash_conflicts.templ (cards, actions,
|
||||||
|
confirms), internal/handlers/hash_conflicts.go (ResolveHashConflict:
|
||||||
|
keep_all marks resolved; keep reparents children to the kept copy,
|
||||||
|
deletes the other catalog rows, records who resolved), internal/
|
||||||
|
services/media_scanner.go (recordHashConflictIfAny), internal/services/
|
||||||
|
hash_backfill.go (backfill-created conflicts). Re-verify against these
|
||||||
|
when the page changes. -->
|
||||||
|
|
||||||
|
# Hash Conflicts
|
||||||
|
|
||||||
|
Hash Conflicts is the duplicate-content queue: groups of catalog items
|
||||||
|
whose files are **byte-identical** (same SHA-256) but stored at more than
|
||||||
|
one path in the same library. The scanner flags these as it goes — and
|
||||||
|
the hash backfill job flags them retroactively for content that predates
|
||||||
|
hash tracking — so both fresh scans and old libraries surface their
|
||||||
|
duplicates here.
|
||||||
|
|
||||||
|
Duplicates usually mean the same book was copied into two folders, or a
|
||||||
|
library was reorganized and both the old and new copies got scanned. The
|
||||||
|
harm is quiet but real: split reading histories, double-counted library
|
||||||
|
stats, and two entries for one book.
|
||||||
|
|
||||||
|
## What a conflict looks like
|
||||||
|
|
||||||
|
One card per group: a **Duplicate content** heading, a badge with the
|
||||||
|
copy count, the library and a short fingerprint of the shared hash, and
|
||||||
|
one row per copy — title, author, full path, file size, and a usage
|
||||||
|
summary that's **highlighted when that copy holds reading data** (someone
|
||||||
|
has actually read it).
|
||||||
|
|
||||||
|
## Resolving a group
|
||||||
|
|
||||||
|
Two outcomes, both confirm-guarded:
|
||||||
|
|
||||||
|
### Keep this copy
|
||||||
|
|
||||||
|
Per-copy button. Keeps the copy you chose and folds the **other copies'
|
||||||
|
reading data into it** (their catalog rows are removed; the underlying
|
||||||
|
files on disk are never touched — this platform's deletes act on the
|
||||||
|
catalog, not your files). The row-level usage summaries exist precisely
|
||||||
|
so you can pick the copy that already carries the reading history.
|
||||||
|
|
||||||
|
### Keep both
|
||||||
|
|
||||||
|
The group-level button, for duplicates that are intentional. It records
|
||||||
|
the resolution and stops flagging this group — every copy stays in the
|
||||||
|
catalog exactly as it is, nothing merged, nothing removed.
|
||||||
|
|
||||||
|
After either choice the card is replaced with the outcome, and the group
|
||||||
|
never comes back (unless the same duplicate situation re-arises from a
|
||||||
|
*new* scan, which creates a fresh group).
|
||||||
|
|
||||||
|
## When the page is empty
|
||||||
|
|
||||||
|
"No content duplicates detected." — the queue drains from the top; groups
|
||||||
|
appear as scans and the backfill find them.
|
||||||
@@ -284,6 +284,14 @@ label: User Access
|
|||||||
where: Admin → Libraries → a library's panel → section heading
|
where: Admin → Libraries → a library's panel → section heading
|
||||||
does: Per-user visibility checkboxes — checked (default) shows the library to that user; unchecked hides it everywhere for them, enforced in the database.
|
does: Per-user visibility checkboxes — checked (default) shows the library to that user; unchecked hides it everywhere for them, enforced in the database.
|
||||||
|
|
||||||
|
label: Keep both
|
||||||
|
where: Admin → Hash Conflicts → a conflict group card
|
||||||
|
does: Records the resolution and stops flagging the group; every copy stays, nothing merged or removed. For intentional duplicates.
|
||||||
|
|
||||||
|
label: Keep this copy
|
||||||
|
where: Admin → Hash Conflicts → a copy row
|
||||||
|
does: Keeps that copy, folds the other copies' reading data into it, and removes their catalog rows. Files on disk are never touched.
|
||||||
|
|
||||||
label: Resume rewind
|
label: Resume rewind
|
||||||
where: audio player → player settings; profile settings
|
where: audio player → player settings; profile settings
|
||||||
does: Rewinds playback a configured few seconds when you resume.
|
does: Rewinds playback a configured few seconds when you resume.
|
||||||
|
|||||||
Reference in new issue
Block a user