Commit Graph

2 Commits

Author SHA1 Message Date
320107841b refactor: config-driven libraries; drop folder-add UI
The frontend AddSourceFolderDialog let users register source roots
from inside the app, but with the bootstrap auto-creating one for
the /photos mount on first boot, the dialog was redundant in the
common case and confusing in every other (users had to know which
container path corresponded to their host directory). Going
config-driven matches Plex/Photoprism/Immich and matches the
mental model "the docker mount IS the library".

Frontend
- Deleted components/dialogs/AddSourceFolderDialog.tsx entirely.
- LeftSidebar drops the "+ Add Source Folder" button + bottom-bar
  layout, the addFolderMutation, the dead Plus action button on
  the (no-longer-existing) folders/heaps tree headers, and the
  Plus icon import.
- api.ts: removed sourceFolders.add(), library.browse(), and the
  BrowseChild / BrowseResponse types. The remaining sourceFolders
  surface is read-only (list + manual scan).
- LeftSidebar bottom strip is now just the "Scan all folders"
  button when there's at least one source root.

Backend
- Dropped POST /folders (no consumers) along with FolderCreate /
  FolderResponse pydantic models. The folders router header now
  documents the config-driven approach.
- Dropped GET /library/browse (no consumers). Removed the unused
  os/HTTPException/SourceRoot imports it brought in.
- cleanup_data_integrity now also walks the source roots and logs
  a warning for any whose path is missing on disk. Doesn't auto-
  delete (a missing path could be a temporarily unmounted drive)
  but surfaces enough hint to fix it. Returns the count in the
  summary dict alongside merged-duplicates.

Docs
- README "How libraries are managed" section rewritten to spell
  out that mounts ARE source roots, edit .env + restart, no UI for
  managing source roots. New "Changing or adding libraries"
  section walks through the typical edit-restart loop including
  the optional volume-nuke for a clean slate.
- "Adding more libraries" subsection covers multi-mount via
  edited compose with a note that auto-registration is roadmap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 00:44:48 +02:00
cf7c72d437 fix: deduplicate scanner-created source_roots and folders
Two related fixes:

1. Prevention — scanner now normalizes paths before lookup/insert
   in get_or_create_source_root and get_or_create_folder. Trailing
   slashes, redundant separators, and `.` segments all collapse to
   the same row. _normalize_path uses os.path.normpath; symlinks
   are intentionally NOT resolved so mount paths stay intact for
   cross-machine portability.

2. Cleanup — new app/services/cleanup.py runs on backend startup
   (idempotent) and merges any pre-existing duplicates left over
   from older scanner versions:
   - Groups source_roots by normalized path. Picks the canonical
     row (preferring one with a non-empty name and the earliest
     added_at), re-points child Folder rows via UPDATE, and
     deletes the duplicates.
   - Same for folders, with photo_count as the tiebreaker. Photos
     get re-pointed to the canonical folder via UPDATE.
   - Recomputes folder.photo_count from the actual non-discarded
     photo membership so the sidebar count matches reality.

Wired into main.py's lifespan handler. On the dev DB this merged
the empty-name "/host/Pictures/MulitaTest/" duplicate that was
showing up alongside the canonical MulitaTest source root.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 23:43:53 +02:00