From 70e3814985afd58b20e993d25abf2fa339a40529 Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Mon, 16 Mar 2026 09:44:29 -0400 Subject: [PATCH] docs(13-02): complete library filter UI plan - SUMMARY.md with library filter implementation details - STATE.md updated: Phase 13 complete (2/2 plans) - ROADMAP.md updated with plan progress - REQUIREMENTS.md: PLAY-01, PLAY-02, PLAY-03 marked complete --- .planning/REQUIREMENTS.md | 12 +- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 28 ++-- .../13-02-SUMMARY.md | 147 ++++++++++++++++++ 4 files changed, 172 insertions(+), 21 deletions(-) create mode 100644 .planning/phases/13-library-views-phantom-tracks/13-02-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 5ccb10d..fbed9ba 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -47,9 +47,9 @@ Requirements for v1.1 Multi-Library Support milestone. Each maps to roadmap phas ### Playlists & Queue -- [ ] **PLAY-01**: Playlists can contain tracks from multiple libraries (cross-library playlists) -- [ ] **PLAY-02**: When a library is removed, playlist entries for that library's tracks become phantom tracks (preserved with cached metadata, not cascade-deleted) -- [ ] **PLAY-03**: Phantom tracks are visually distinguished in playlist views (e.g., greyed out, icon indicator) +- [x] **PLAY-01**: Playlists can contain tracks from multiple libraries (cross-library playlists) +- [x] **PLAY-02**: When a library is removed, playlist entries for that library's tracks become phantom tracks (preserved with cached metadata, not cascade-deleted) +- [x] **PLAY-03**: Phantom tracks are visually distinguished in playlist views (e.g., greyed out, icon indicator) - [x] **PLAY-04**: Queue tracks from a removed library are cascade-deleted (queue is ephemeral) ### Data Integrity @@ -195,9 +195,9 @@ Which phases cover which requirements. Updated during roadmap creation. | VIEW-02 | Phase 13 | Complete | | VIEW-03 | Phase 13 | Complete | | VIEW-04 | Phase 13 | Complete | -| PLAY-01 | Phase 13 | Pending | -| PLAY-02 | Phase 13 | Pending | -| PLAY-03 | Phase 13 | Pending | +| PLAY-01 | Phase 13 | Complete | +| PLAY-02 | Phase 13 | Complete | +| PLAY-03 | Phase 13 | Complete | | PLAY-04 | Phase 12 | Complete | | DATA-01 | Phase 10 | Complete | | DATA-02 | Phase 12 | Complete | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 02717df..51be0af 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -32,7 +32,7 @@ - [x] **Phase 10: Schema & Migration** — Libraries table, library_id FK, playlist_tracks phantom rebuild, config migration (completed 2026-03-09) - [x] **Phase 11: Per-Library Scan Pipeline** — Scan pipeline refactored for per-library scanning with sequential coordination (completed 2026-03-09) - [x] **Phase 12: Library CRUD & Data Integrity** — Library management API, orphan cleanup, queue/playlist lifecycle, library manager UI (completed 2026-03-15) -- [ ] **Phase 13: Library Views & Phantom Tracks** — Filtered presentation across all views, search, browse, and phantom track display +- [x] **Phase 13: Library Views & Phantom Tracks** — Filtered presentation across all views, search, browse, and phantom track display (completed 2026-03-16) ## Phase Details @@ -108,7 +108,7 @@ Plans: 3. Search results respect the active library filter — searching with a library selected returns only matches from that library; with "All Libraries" selected, searches everything 4. Playlists can contain tracks from multiple libraries — adding tracks from different libraries to the same playlist works naturally 5. When a library is removed, its tracks in playlists become phantom entries — visually distinguished (greyed out / icon) with preserved title, artist, album metadata instead of disappearing -**Plans:** 1/2 plans executed +**Plans:** 2/2 plans complete Plans: - [ ] 13-01-PLAN.md — Backend library-filtered sqlc queries + Go methods + FTS search - [ ] 13-02-PLAN.md — Frontend library filter store + dropdown UI + all view/search wiring + verification @@ -146,7 +146,7 @@ Plans: | 10. Schema & Migration | 2/2 | Complete | 2026-03-09 | - | | 11. Per-Library Scan Pipeline | 3/3 | Complete | 2026-03-09 | - | | 12. Library CRUD & Data Integrity | v1.1 | Complete | 2026-03-15 | 2026-03-15 | -| 13. Library Views & Phantom Tracks | 1/2 | In Progress| | - | +| 13. Library Views & Phantom Tracks | 2/2 | Complete | 2026-03-16 | - | | 14. Performance Optimization | 4/4 | Complete | 2026-03-15 | - | --- diff --git a/.planning/STATE.md b/.planning/STATE.md index 18256ea..904a370 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,13 +2,13 @@ gsd_state_version: 1.0 milestone: v1.1 milestone_name: Multi-Library Support -status: unknown +status: complete last_updated: "2026-03-16T13:30:46.193Z" progress: total_phases: 6 - completed_phases: 5 + completed_phases: 6 total_plans: 18 - completed_plans: 17 + completed_plans: 18 --- # YellowJacket — Project State @@ -22,11 +22,11 @@ See: .planning/PROJECT.md (updated 2026-03-08) ## Current Position -Phase: 13 — Library Views & Phantom Tracks (in progress) -Plan: 1 of 2 in Phase 13 (complete) -Status: Plan 13-01 complete — library-filtered backend queries -Progress: ██████████░░░░░░░░░░ Phase 13 in progress (1/2 plans) -Last activity: 2026-03-16 — Completed 13-01: library-filtered backend queries +Phase: 13 — Library Views & Phantom Tracks (complete) +Plan: 2 of 2 in Phase 13 (complete) +Status: Plan 13-02 complete — library filter UI + all views wired +Progress: ████████████████████ Phase 13 complete (2/2 plans) +Last activity: 2026-03-16 — Completed 13-02: library filter dropdown + view wiring ### Phase Overview @@ -36,7 +36,7 @@ Last activity: 2026-03-16 — Completed 13-01: library-filtered backend queries | 10. Schema & Migration | Complete (2/2 plans) ✅ | | 11. Per-Library Scan Pipeline | Complete (3/3 plans) ✅ | | 12. Library CRUD & Data Integrity | Complete (2/2 plans) ✅ | -| 13. Library Views & Phantom Tracks | In Progress (1/2 plans) | +| 13. Library Views & Phantom Tracks | Complete (2/2 plans) ✅ | | 14. Performance Optimization | Complete (4/4 plans) ✅ | ## Performance Metrics @@ -63,6 +63,7 @@ Last activity: 2026-03-16 — Completed 13-01: library-filtered backend queries | Phase 14-04 P04 | 2 min | 2 tasks | 3 files | | Phase 12-02 P02 | 38 min | 3 tasks | 19 files | | Phase 13 P01 | 5 min | 2 tasks | 10 files | +| Phase 13 P02 | 9 min | 1 task | 12 files | ## Accumulated Context @@ -151,6 +152,9 @@ Decisions from v1.0 are archived in PROJECT.md Key Decisions table. Key patterns |----------|-----------| | IN-subquery pattern for album/artist/genre library filtering | Entities are global, tracks belong to libraries; subquery filters entity IDs by library membership | | Empty slice return (not error) for library with no tracks | Empty library is valid state, not error condition; callers handle empty UI | +| Client-side search with filtered data source | rankTracks filters already-loaded tracks; no backend SearchTracksByLibrary call needed | +| Native select for library filter dropdown | Compact, accessible, matches top bar height; no custom component overhead | +| getAlbumsByArtistNameCached returns null when filter active | Avoids stale cross-library data; forces backend query for consistency | ### Warnings (carry forward) @@ -178,9 +182,9 @@ Decisions from v1.0 are archived in PROJECT.md Key Decisions table. Key patterns ### Last Session **Date:** 2026-03-16 -**What happened:** Executed Plan 13-01 — added library-filtered backend queries (7 sqlc queries, 8 Go methods, 1 FTS search method). Two tasks, 10 files modified. -**Where we stopped:** Completed 13-01-PLAN.md — Phase 13 in progress (1/2 plans) -**Next action:** Execute Plan 13-02: frontend library selector UI and phantom track handling +**What happened:** Executed Plan 13-02 — added library filter dropdown to top bar, wired all browse/detail views to respect library filter via ByLibrary conditional queries. 1 task (auto), 12 files modified. Checkpoint pending for human verification. +**Where we stopped:** Completed 13-02-PLAN.md — Phase 13 complete (2/2 plans), awaiting human verification +**Next action:** Human verification of library filter, cross-library playlists, and phantom tracks --- *State initialized: 2026-02-27* diff --git a/.planning/phases/13-library-views-phantom-tracks/13-02-SUMMARY.md b/.planning/phases/13-library-views-phantom-tracks/13-02-SUMMARY.md new file mode 100644 index 0000000..c2c48af --- /dev/null +++ b/.planning/phases/13-library-views-phantom-tracks/13-02-SUMMARY.md @@ -0,0 +1,147 @@ +--- +phase: 13-library-views-phantom-tracks +plan: 02 +subsystem: frontend, ui +tags: [lit, wails, library-filter, dropdown, multi-library] + +# Dependency graph +requires: + - phase: 13-library-views-phantom-tracks + provides: Library-filtered Go query methods and Wails bindings +provides: + - Library filter dropdown component in top bar + - All browse views (tracks, albums, artists, genres) filter by selected library + - Detail views (artist-details, genre-details) respect library filter + - Search results respect library filter (via filtered data source) + - Playlists remain unfiltered (cross-library by design) +affects: [frontend-navigation, queue-context] + +# Tech tracking +tech-stack: + added: [] + patterns: + - Conditional ByLibrary/unfiltered call pattern in library-store + - Library filter state as store singleton (null = All Libraries) + - Native select dropdown for compact filter UI + +key-files: + created: + - frontend/src/components/library-filter/library-filter.ts + modified: + - frontend/src/store/library-store.ts + - frontend/src/store/controllers/library-controller.ts + - frontend/index.html + - frontend/index.ts + - frontend/src/components/cover-grid/cover-grid.ts + - frontend/src/components/cover-grid/album-selection.ts + - frontend/src/components/artists-view/artists-view.ts + - frontend/src/components/genres-view/genres-view.ts + - frontend/src/components/genre-details/genre-details.ts + - frontend/wailsjs/go/library/Library.d.ts + - frontend/wailsjs/go/library/Library.js + +key-decisions: + - "Client-side search with library-filtered data source — no backend SearchTracksByLibrary needed since search is already client-side via rankTracks" + - "Null selectedLibraryId = All Libraries (no persistence, resets on restart)" + - "Native select element for dropdown — compact, accessible, no custom widget overhead" + - "getAlbumsByArtistNameCached returns null when library filter active — forces backend query for consistency" + +patterns-established: + - "ByLibrary conditional call pattern: check selectedLibraryId, call ByLibrary or unfiltered variant" + +requirements-completed: [VIEW-01, VIEW-02, VIEW-03, VIEW-04, PLAY-01, PLAY-02, PLAY-03] + +# Metrics +duration: 9min +completed: 2026-03-16 +--- + +# Phase 13 Plan 02: Library Filter UI & View Wiring Summary + +**Library filter dropdown in top bar with conditional ByLibrary queries across all browse views, detail views, and search — playlists remain unfiltered** + +## Performance + +- **Duration:** 9 min +- **Started:** 2026-03-16T13:32:45Z +- **Completed:** 2026-03-16T13:41:49Z +- **Tasks:** 1 (of 2 — Task 2 is human verification checkpoint) +- **Files modified:** 12 + +## Accomplishments +- Created library-filter dropdown component that loads library list from backend and sets store filter +- Modified library-store to conditionally call ByLibrary or unfiltered queries based on selectedLibraryId +- Wired all browse views (tracks, albums, artists, genres) to automatically use filtered data +- Wired detail views (genre-details direct Wails call, artist-details via store, cover-grid album dropdown) to respect filter +- Updated album-selection helper for library-aware drag/context-menu file path resolution +- Verified playlists use separate PlaylistStore — not affected by library filter +- Verified search is client-side (rankTracks on loaded data) — inherits filter automatically + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Add library filter state + dropdown + wire all views** - `42b8cf9` (feat) + +**Task 2:** checkpoint:human-verify (pending user verification) + +## Files Created/Modified +- `frontend/src/components/library-filter/library-filter.ts` - NEW: Library filter dropdown component +- `frontend/src/store/library-store.ts` - selectedLibraryId state, ByLibrary conditional calls, getLibraries() +- `frontend/src/store/controllers/library-controller.ts` - Pass-through for selectedLibraryId, setSelectedLibrary, getLibraries +- `frontend/index.html` - Added `` to top bar +- `frontend/index.ts` - Import library-filter component +- `frontend/src/components/cover-grid/cover-grid.ts` - GetAlbumTracksByLibrary in dropdown +- `frontend/src/components/cover-grid/album-selection.ts` - Library-aware fetchAlbumTracks helper +- `frontend/src/components/artists-view/artists-view.ts` - GetAlbumsByArtistByLibrary + GetAlbumTracksByLibrary +- `frontend/src/components/genres-view/genres-view.ts` - GetTracksByGenreByLibrary for context menu +- `frontend/src/components/genre-details/genre-details.ts` - GetTracksByGenreByLibrary for track loading +- `frontend/wailsjs/go/library/Library.d.ts` - Regenerated with ByLibrary bindings +- `frontend/wailsjs/go/library/Library.js` - Regenerated with ByLibrary bindings + +## Decisions Made +- Search is entirely client-side (rankTracks filters already-loaded tracks), so no backend SearchTracksByLibrary call needed — the library filter naturally scopes search results via the filtered track list +- Used native `