Files
yellowjacket/.planning/plans/completed/002-v1.1-multi-library.md
T
2026-05-01 11:52:50 -04:00

24 lines
2.3 KiB
Markdown

# 002 — v1.1 Multi-Library Support
> Lets users register and manage multiple music library directories with per-library scanning, filtered views, cross-library playlists, and phantom-track preservation when a library is removed.
**Shipped:** 2026-03-16 · **Phases:** 9-14
## What landed
- **Phase 9 — Scan cancellation & keyboard shortcuts.** Cancellable/pausable library scans via per-scan context; configurable shortcuts with record-style capture, scope-aware dispatch, conflict detection.
- **Phase 10 — Schema & migration.** New `libraries` table, `library_id` FK on `audio_files`, phantom columns on `playlist_tracks`, seamless single-directory → named-library migration on first launch.
- **Phase 11 — Per-library scan pipeline.** Sequential scan-queue coordinator (single writer is the SQLite reality); per-library progress UI with library name; cancel scope respects the active library.
- **Phase 12 — Library CRUD & data integrity.** Add/rename/remove library through UI; atomic orphan cleanup (shared artists/albums/genres survive); FTS5 entries removed; queue tracks from a removed library cascade-deleted with playback continuing.
- **Phase 13 — Library views & phantom tracks.** Library filter dropdown across all views; tracks/albums/artists/genres/search respect the active filter; cross-library playlists work naturally; removed-library tracks become greyed-out phantoms with preserved metadata, auto-resolved on rescan via `ScanHooks` + M3U8 matching.
- **Phase 14 — Performance optimization.** CSS containment + GPU promotion on scroll containers; view caching (display toggle, no DOM destruction); event delegation on virtualizer; `queueMicrotask` notification batching; pprof profiling guide.
## Key decisions retained
- **Hybrid model — `library_id` only on `audio_files`.** Physical files belong to a library; logical entities (artist/album/genre) are shared.
- **Libraries live in DB, not TOML.** UI-driven CRUD shouldn't require TOML manipulation.
- **`SET NULL` on `playlist_tracks` FK.** Phantom rows preserve playlist structure when a library is removed.
- **Backend filters, frontend doesn't.** `ByLibrary` SQL variants keep the UI responsive at 150k tracks.
- **Sequential scanning.** SQLite single-writer makes parallel scans pointless.
- **`ScanHooks` callback pattern.** Breaks the library → playlist circular dep needed for phantom resolution.