Commit Graph
407 Commits
Author SHA1 Message Date
yonlu 8a0b16a4ec feat(quick-15): insert BufferedStreamer into player pipeline and increase speaker buffer
- BufferedStreamer wraps resampled streamer with 2s read-ahead buffer
- Speaker buffer increased from 100ms to 200ms for secondary protection
- Close old BufferedStreamer on track change and unload to prevent goroutine leaks
- Streamer chain: decode -> resample -> BufferedStreamer -> ctrl -> volume -> speaker
2026-03-05 15:28:28 -05:00
yonlu 85b23acb24 feat(quick-15): add BufferedStreamer with goroutine read-ahead
- Ring-buffer streamer decouples source I/O from speaker callback
- Read-ahead goroutine pre-fills buffer in 512-sample chunks
- Returns silence when buffer temporarily empty (prevents glitches)
- Close() signals goroutine shutdown via channel
- 5 unit tests: basic stream, small reads, drain, silence, close
2026-03-05 15:27:24 -05:00
yonlu 8f16463fdd docs(quick-14): fix queue/player desync after hot reload 2026-03-05 15:05:17 -05:00
yonlu 97c135766b docs(quick-14): complete queue/player desync fix plan 2026-03-05 15:04:39 -05:00
yonlu 2820de2510 fix(quick-14): add roll-back-on-failure to queue index advancement
- Next() rolls back currentIndex and skips emitIndexChanged on load failure
- Previous() applies same pattern to all three branches (RepeatOne, restart, navigate)
- OnPlaybackFinished() rolls back currentIndex on playCurrentTrack failure
- PlayIndex() and playFromStart() also guard against load failures
- RepeatOne paths guard emitIndexChanged with the bool return value
2026-03-05 15:03:29 -05:00
yonlu 6eeddda976 refactor(quick-14): make playOrLoadCurrentTrack and playCurrentTrack return bool
- playCurrentTrack returns false on load failure or play error
- playOrLoadCurrentTrack propagates bool from load/play helpers
- loadCurrentTrack already returned bool — no change needed
2026-03-05 15:02:11 -05:00
yonlu e743294406 docs(quick-13): complete fix linting issues plan
- Add 13-SUMMARY.md with execution details
- Update STATE.md with quick task 13 entry
2026-03-05 14:09:48 -05:00
yonlu e1a95e65a9 fix(quick-13): resolve lint issues in main source files
- Fix errcheck for db.Close() in testhelper.go
- Fix errcheck, nlreturn, wsl, gofumpt issues in genevents/main.go
- Fix gofumpt and wsl issues in library.go
2026-03-05 14:07:50 -05:00
yonlu 97f256d67f fix: include full track metadata in GetAudioFilesByReleaseGroup query
The GetAudioFilesByReleaseGroup SQL query only selected 6 columns,
missing audio properties (sample_rate, bit_depth, channels, bitrate,
file_size) and metadata (album, genre, year, composer, file_type).
This caused track details opened from the album view to show dashes
instead of actual values. Expanded the query to match
GetAllTracksWithFullMetadata and updated GetAlbumTracks to use the
shared mapTrackRow helper.
2026-03-05 13:34:03 -05:00
yonlu 3e9c143a6e docs(quick-12): Add favorite icon to album grid track list dropdown 2026-03-05 11:44:52 -05:00
yonlu 06d2c4702e docs(quick-12): complete add favorite icon to album dropdown plan 2026-03-05 11:44:28 -05:00
yonlu 12a0bbc89c feat(quick-12): add favorite icon to album dropdown track rows
- Add FavoritesController and classMap imports
- Add .fav-icon CSS with compact sizing (18px/11px) for dropdown context
- Insert heart/star icon between track number and title
- Click toggles favorite with stopPropagation to avoid track selection
2026-03-05 11:43:31 -05:00
yonlu a28b4d1e06 feat: add scan progress bar with phase indicator
Add live progress reporting during library scans:

- Pre-walk count: fast WalkDir to count audio files upfront for
  percentage calculation (~1-2s overhead)
- Progress ticker: emits ScanProgress events every 300ms with
  phase, file counts (added/skipped/updated), and total
- Phase labels: counting → scanning → thumbnails → orphans
- Frontend: progress bar with percentage, file counts breakdown,
  and phase indicator in both config-page and library-manager

Replaces the static 'Scanning...' text with a live progress bar
showing e.g. '62% — Scanning... 1,247 / 2,013 files (891 new,
356 skipped)'
2026-03-05 11:21:53 -05:00
yonlu a2975531f4 docs(quick-11): Investigate and fix neovim crash during library scan 2026-03-05 11:10:34 -05:00
yonlu fd367de80e docs(quick-11): complete fix neovim crash during library scan plan
- Add 11-SUMMARY.md with execution results
- Update STATE.md with quick task 11 entry and session info
2026-03-05 11:10:15 -05:00
yonlu c45bca411b feat(quick-11): add make dev-debug target for verbose logging
- New dev-debug target sets YJ_LOG_LEVEL=debug for full debug output
- Existing dev target unchanged (now quieter by default due to Info level)
2026-03-05 11:08:49 -05:00
yonlu 55b4902fac feat(quick-11): add configurable log level via YJ_LOG_LEVEL env var
- Change dev mode default from Debug to Info to prevent stdout flooding
- Add resolveLogLevel() function with YJ_LOG_LEVEL env var support
- Accept debug/info/warn/error values (case-insensitive)
- Prevents neovim display corruption during library scans
2026-03-05 11:08:30 -05:00
yonlu fe7cba86b4 docs: update STATE.md for FTS5 contentless fix 2026-03-05 10:42:12 -05:00
yonlu 8e9a616037 fix: drop+recreate contentless FTS5 index instead of DELETE
The search_index is a contentless FTS5 table (content=''), which
SQLite does not support DELETE on. ClearSearchIndex now drops and
recreates the virtual table. Single-row DeleteSearchIndex becomes
a no-op since contentless FTS5 also cannot delete individual rows;
stale entries are harmless (search JOINs filter them out) and the
index is fully rebuilt during FullRescan.
2026-03-05 10:41:55 -05:00
yonlu 2439c2a728 docs(quick-10): diagnose duplicate album merging bug - albums with same name but different artists shown as single entry 2026-03-05 10:27:25 -05:00
yonlu 1b33923980 docs(quick-10): complete fix duplicate album merging bug plan
- Add 10-SUMMARY.md with full execution details
- Update STATE.md with quick task 10 entry and session info
2026-03-05 10:26:57 -05:00
yonlu d43ba7bd0c fix(quick-10): add migration 5 and fix entity cache for composite album key
- Migration 5 rebuilds release_groups with UNIQUE(name, album_artist_credit_id)
- Drops and recreates track_metadata VIEW during table rebuild
- Temporarily disables FK checks for safe table rebuild
- Entity cache now keys by album name + artist credit ID
- Update tests to use composite cache keys
2026-03-05 10:25:53 -05:00
yonlu 999ab967be fix(quick-10): update release_groups schema and queries for composite uniqueness
- Change UNIQUE(name) to UNIQUE(name, album_artist_credit_id) in schema
- Update UpsertReleaseGroup ON CONFLICT to match composite key
- Rename GetReleaseGroupByName to GetReleaseGroupByNameAndArtist with two params
- Regenerate sqlc code
2026-03-05 10:23:25 -05:00
yonlu dff625a568 docs(quick-9): complete fix queue panel scroll bar plan
- Add 9-SUMMARY.md with execution results
- Update STATE.md with quick task 9 entry
2026-03-05 09:41:18 -05:00
yonlu ebde5e5a8b fix(quick-9): set fixed height on queue track items for stable virtualizer scroll
- Add height: 49px and overflow: hidden to .track-item CSS
- Add overflow: hidden to .track-details CSS
- Fixed height ensures lit-virtualizer _scrollSize is stable from first render
- Prevents scrollbar lag on large queues (20k+ tracks) caused by dynamic item size averaging
2026-03-05 09:40:10 -05:00
yonlu 6ce0661fca chore: complete v1.0 Consolidation milestone
Archive milestone artifacts:
- milestones/v1.0-ROADMAP.md (full roadmap archive)
- milestones/v1.0-REQUIREMENTS.md (26/26 requirements complete)
- milestones/v1.0-phases/ (8 phase directories with plans, summaries, verifications)

Updated:
- PROJECT.md: full evolution review, all consolidation requirements validated
- ROADMAP.md: collapsed to milestone summary with archive link
- STATE.md: reset for next milestone
- MILESTONES.md: created with stats and accomplishments
- RETROSPECTIVE.md: created with lessons learned

Deleted:
- REQUIREMENTS.md (archived, fresh for next milestone)

8 phases, 17 plans, 34 tasks, 84 tests added, 6 days
2026-03-05 09:34:43 -05:00
yonlu 5ef45f91ed docs(phase-08): complete phase execution 2026-03-05 09:22:14 -05:00
yonlu 9943ae381c docs(08-04): complete visual consistency audit & design token application plan
- SUMMARY.md documents 15-component design token rollout
- STATE.md updated: all 8 phases complete, 26/26 requirements delivered
- ROADMAP.md updated: Phase 8 4/4 plans complete
- Includes hotfix documentation for repeat() virtualizer regression (72ef719)
2026-03-05 09:16:22 -05:00
yonlu 72ef719ba7 fix(08-02): revert repeat() inside lit-virtualizer, restore .renderItem + .keyFunction
repeat() as child content of lit-virtualizer bypasses virtualization,
rendering ALL items instead of only visible ones. This caused 2+ minute
loading times and UI freezing with large libraries.

The correct approach: use lit-virtualizer's native .renderItem and
.keyFunction properties which integrate with its scroll-based viewport
management.
2026-03-05 08:46:01 -05:00
yonlu 1303422e69 feat(08-04): apply design tokens to cover-grid, track-list, queue-panel, and detail components
- cover-grid dynamic text tiers use --yj-text-xs/sm/md/lg tokens
- track-list sort toolbar, row text, and fav icon use design tokens
- queue-panel header and track text use type scale tokens
- track-details, track-info, artist-details, genre-details use tokens
- designTokens imported and prepended to static styles in all 8 files
2026-03-04 23:30:29 -05:00
yonlu bc487cd715 docs(08-03): complete renderTrackRow optimization plan
- SUMMARY.md with classMap directive migration results
- STATE.md updated: 3/4 plans complete, decisions recorded
- ROADMAP.md updated with plan progress
2026-03-04 23:24:15 -05:00
yonlu aed90d7b17 feat(08-04): convert sidebar em-based spacing to px and apply icon/type tokens
- Sidebar: convert all em-based padding/gap to px values, icon sizes to --yj-icon-md
- Now-playing: cover placeholder icon to --yj-icon-lg, text sizes to type tokens
- Search-bar: search icon to --yj-icon-sm, input font to --yj-text-md
- Audio-player: convert em-based gap/padding/margin to px values
- Seek-bar: tooltip font to --yj-text-lg, margin from em to px
- Volume-control: padding/margin from em to px, thumb sizes from em to px
- All components import designTokens and include in static styles
2026-03-04 23:23:25 -05:00
yonlu 62f41c2491 perf(08-03): optimize column rendering and apply classMap to queue-panel renderTrackItem
- Hoist searchCtrl.term lookup outside per-column loop in renderTrackRow
- Search highlighting already short-circuits when search term is empty
- Import classMap in queue-panel.ts
- Replace array filter/join class construction with classMap in renderTrackItem
- Eliminates per-row array allocation in queue panel render hot path
2026-03-04 23:21:56 -05:00
yonlu ad210278fc perf(08-03): replace class string construction with classMap directive in renderTrackRow
- Import classMap from lit/directives/class-map.js
- Replace array filter/join class construction with classMap for track-row
- Convert fav-icon conditional class to classMap
- Convert cell alignment classes to classMap
- Eliminates per-row array allocation and string join in render hot path
2026-03-04 23:21:04 -05:00
yonlu e9410e5019 docs(08-02): complete virtualizer repeat() directive migration plan 2026-03-04 23:18:41 -05:00
yonlu 2ad301c297 docs(08-01): complete performance plumbing and design tokens plan 2026-03-04 23:17:00 -05:00
yonlu 1c3514da1d perf(08-02): migrate cover-grid, artists-view, and genres-view virtualizers to repeat() directive
- cover-grid: all 3 virtualizers (single, before-split, after-split) use repeat() with album.ID key
- artists-view uses repeat() with artist.ID key
- genres-view uses repeat() with genre.name key
- Removed gridKeyFunction (now inlined in repeat calls)
- Removed .renderItem and .keyFunction properties from all virtualizers
2026-03-04 23:16:55 -05:00
yonlu d2d7d8c6ce perf(08-02): migrate track-list and queue-panel virtualizers to repeat() directive
- track-list uses repeat() with FilePath key for efficient DOM reuse
- queue-panel uses repeat() with QueueTrack.id key
- Removed .renderItem property, kept .items for virtualization sizing
2026-03-04 23:15:09 -05:00
yonlu 1444a66bb2 feat(08-01): define design token CSS custom properties for icon sizes and type scale
- New tokens.css.ts exports designTokens with --yj-icon-sm/md/lg and --yj-text-xs/sm/md/lg/xl
- Values derived from existing pixel sizes scattered across codebase
- :host scoped for component-level adoption via static styles array
2026-03-04 23:14:43 -05:00
yonlu 3bf66ed125 perf(08-01): add queueMicrotask coalescing to library store and debounce search input
- Library store notify() coalesces multiple calls per microtask tick into one subscriber notification
- Search input debounces store propagation by 150ms while keeping instant visual feedback
- Empty search input clears immediately for responsive UX
2026-03-04 23:14:16 -05:00
yonlu 08793bf60d docs(08-frontend-performance-ux): create phase plan 2026-03-04 21:34:48 -05:00
yonlu 568a9aa090 docs(08): capture phase context 2026-03-04 21:26:58 -05:00
yonlu fbaa72da8f docs(phase-07): complete phase execution 2026-03-04 21:04:13 -05:00
yonlu 6f79c77b58 docs(07-01): complete queue persistence optimization plan
- SUMMARY.md with incremental persistence + Phase 2 dedup details
- STATE.md updated: Phase 7 complete (2/2 plans), decisions recorded
- ROADMAP.md updated: Phase 7 marked complete
- REQUIREMENTS.md: PERF-01, PERF-02 marked complete
2026-03-04 21:00:31 -05:00
yonlu ced58fe6a9 perf(07-01): eliminate redundant lookups in SetQueue Phase 2
- Add phase1Meta parameter to resolveRemainingTracks
- Filter out already-resolved paths before lookupTrackMetaBatch call
- Merge Phase 1 results into Phase 2 lookup map
- Pass batchMeta from SetQueue call site to resolveRemainingTracks
- For 1000-track queue with Phase 1 resolving 50, Phase 2 now queries 950 instead of 1000
2026-03-04 20:58:22 -05:00
yonlu cdd17db275 perf(07-01): add incremental persistence helpers for queue mutations
- Add persistAddTrack/persistAddTracks for O(1) append operations
- Add persistInsertTracks with variable-N position shift for insert-at operations
- Add persistRemoveTrack with single DELETE + position shift
- Wire AddTrack/AddTracks to use incremental INSERT (no full table rewrite)
- Wire InsertNext/InsertNextTracks/InsertTracksAt to use position shift + INSERT
- Wire RemoveTrack to use single DELETE + shift (no full table rewrite)
- RemoveTracks keeps full persistTracks rewrite (bulk operation per design)
- Preserve shuffle order regeneration in all mutation paths
2026-03-04 20:57:47 -05:00
yonlu cd98ad6dc8 perf(07-02): defer eagerFetch to after DOM ready for instant app shell
- Remove eagerFetch() call from LibraryStore constructor
- Add deferEagerFetch() that waits for DOMContentLoaded event
- App shell renders before backend data roundtrips begin
- All 4 data types (tracks, albums, artists, genres) still loaded eagerly
- invalidate() still calls eagerFetch() directly for post-scan refresh
2026-03-04 20:54:38 -05:00
yonlu 9f381e2a03 docs(07): create phase plan 2026-03-04 20:49:38 -05:00
yonlu 2ffcd6ea0e docs(07): capture phase context 2026-03-04 20:41:39 -05:00
yonlu c9626f4c9f docs(phase-06): complete phase execution 2026-03-04 19:38:35 -05:00