Commit Graph
99 Commits
Author SHA1 Message Date
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 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 7dfe003e63 docs(06-03): add SAFETY comments to all 12 hand-crafted SQL statements
- 7 SAFETY comments in search.go (FTS5 MATCH/INSERT/DELETE operations)
- 3 SAFETY comments in library.go (FTS5 INSERT/DELETE in commitNewAudioFile, updateAudioFileMetadata)
- 1 SAFETY comment in rescan.go (FTS5 DELETE in clearAllLibraryData)
- 1 SAFETY comment in persistence.go (variable-count multi-row INSERT)
- Cross-references link library.go/rescan.go back to search.go
- Two-part format: why sqlc can't handle it + what makes it safe
2026-03-04 19:33:55 -05:00
yonlu 2221a68459 feat(06-03): migrate lookupChunk to sqlc-generated LookupTrackMetaByPaths query
- Add LookupTrackMetaByPaths sqlc query using track_metadata VIEW with sqlc.slice()
- Replace hand-crafted fmt.Sprintf IN clause in lookupChunk with sqlc-generated call
- Preserve lookupTrackMetaBatch chunking at maxSQLiteVars (900)
- All queue tests pass with -race
2026-03-04 19:31:52 -05:00
yonlu 9159b409dc refactor(06-01): consolidate search queries to use track_metadata VIEW
- SearchFTS uses JOIN track_metadata instead of 5-table inline JOIN
- SearchFTSByFilename uses JOIN track_metadata instead of 5-table inline JOIN
- SearchFTSTracks uses JOIN track_metadata instead of 6-table inline JOIN
- RebuildSearchIndex selects from track_metadata instead of inline JOIN
- All 15 database tests pass with -race
2026-03-04 19:23:11 -05:00
yonlu 3e9edd05e8 feat(06-02): create Go→TypeScript event constant codegen tool
- Add backend/events/cmd/genevents/main.go using go/ast for deterministic output
- Add //go:generate directive to backend/events/events.go
- Generate frontend/src/events.ts with all 21 constants including LibraryConfigChanged
- Atomic file writes via temp file + rename
- Comment groups preserved with trailing period stripping
2026-03-04 19:22:11 -05:00
yonlu 9c7e5a9634 feat(06-01): create track_metadata VIEW schema and migration 4
- Add track_metadata_view.sql for sqlc VIEW awareness
- Add migration4TrackMetadataView for existing databases
- sqlc generate produces TrackMetadatum model from VIEW
- migration2 inline JOIN preserved (runs before VIEW exists)
2026-03-04 19:21:58 -05:00
yonlu dd34569ac0 test(05-01): add FTS5 search tests for database package
- seedSearchData helper creates full entity graph (7 tracks, 4 artists, 7 albums)
- Pure helper tests: tokeniseForFTS, buildFTSQuery, stripExtForSearch
- FTS5 search tests: basic term, empty query, special characters (AC/DC),
  multi-word, diacritics (Beyonce→Beyoncé), ranking, filename search
- SearchFTSTracks verifies all 16 columns populated
- Index ops: insert, delete (documents contentless FTS5 limitation),
  rebuild, clear (documents contentless limitation)
- Migration test: user_version >= 3, UNIQUE index enforcement
- 15 tests, all passing with -race
2026-03-04 16:43:06 -05:00
yonlu fa6c378e25 test(05-02): add entity cache and orphan cleanup tests with DB backing
- TestCachedUpsertArtistCredit: cache hit returns same ID on second call
- TestCachedLinkArtist: skips duplicate INSERT via linkedCredits cache
- TestCachedLinkArtist_MultiCredit: same artist linked to different credits
- TestCachedUpsertGenre: genre cache returns same ID on repeated calls
- TestResolveReleaseGroup: creates release group, updates cover art on cache hit
- TestResolveReleaseGroup_CacheHit: pre-populated cache returns cached ID
- TestOrphanDeletion: DeleteAudioFile removes row, documents contentless FTS5 limitation
- TestEntityCache_EmptyFields: empty artist name, empty album, AlbumArtist reuse
2026-03-04 16:37:48 -05:00
yonlu 6f96a9411f test(05-02): add pure helper tests for scan utility functions
- TestGetRecordingName: title present, fallback to filename sans extension
- TestToNullInt64: zero as null, positive/negative as valid
- TestToNullString: empty as null, non-empty as valid
- TestSplitGenres: empty/single/multiple genre splitting on || delimiter
- TestMapTrackRow: all 16 columns including string TrackLength, NullInt64 fields
2026-03-04 16:35:00 -05:00
yonlu 294b629877 test(04-02): add player volume conversion and state mapping tests
- ToVolume/ToUserVolume at all boundary values (0, 25, 50, 75, 100)
- Out-of-range behavior for both conversion directions
- Full roundtrip characterization (0-100) with ±1 tolerance
- clampVolume at and beyond both boundaries
- stateToMediaControls for all states including unknown fallback
2026-03-03 17:01:40 -05:00
yonlu 77cc993fec test(04-01): add queue persistence round-trip tests
- Full roundtrip: SaveState/RestoreState preserves all fields (tracks, index, shuffle, repeat, shuffleOrder)
- Edge cases: empty queue, single track, no prior save state
- Track order: 10-track order preservation verification
- Overwrite: second SaveState replaces first
- 6 tests all passing with -race
2026-03-03 17:00:38 -05:00
yonlu f9b2ad95b7 test(04-02): add config and sub-config validation tests
- Theme: hex color regex + background shade enum validation
- Tracklist: column ID recognition + duplicate detection
- Favorites: icon style enum validation
- Library: directory existence + scan concurrency mode validation
- Config: load/save roundtrip, missing file handling, composed errors, defaults
2026-03-03 17:00:12 -05:00
yonlu 8d60dc05ce test(04-01): add queue core operations and navigation tests
- Queue operations: SetQueue, AddTrack, InsertTracksAt, MoveQueueTracks, RemoveTrack, Clear, ToggleShuffle, CycleRepeat
- Navigation: nextIndex/previousIndex in all repeat modes (off/all/one)
- Shuffle: generateShuffleOrder properties (no duplicates, current at [0]), shuffle navigation
- Mock TrackLoader and seedAudioFiles helper for DB-backed tests
- 23 tests total (14 core + 9 navigation) all passing with -race
2026-03-03 16:59:45 -05:00
yonlu bae9d70d23 feat(03-01): create NewTestDB helper for in-memory SQLite test databases
- Add testhelper.go with exported NewTestDB(t *testing.T) *DB
- Opens :memory: SQLite with same connection params as production
- Shares applyPRAGMAs, schema application loop, and runMigrations
- Registers t.Cleanup for automatic DB close
- No orphan cleanup, no functional options, no error return
2026-03-02 22:05:39 -05:00
yonlu d34881530a feat(03-01): extract shared applyPRAGMAs and add production PRAGMAs to NewDB
- Extract inline foreign_keys PRAGMA into shared applyPRAGMAs function
- Add synchronous=NORMAL, cache_size=-8000, mmap_size=67108864 PRAGMAs
- NewDB now calls applyPRAGMAs instead of inline PRAGMA exec
- applyPRAGMAs will be reused by NewTestDB for production-mirroring tests
2026-03-02 22:04:49 -05:00
yonlu e6866ded9d feat(02-02): add ScanWarning type and reclassify scan errors as warnings
- Add ScanWarning struct with FilePath/Phase/Err to ScanMetrics
- Add mutex-protected addWarning method for concurrent use
- Reclassify walk, extraction, commit, orphan, variant, FTS failures as warnings
- Update commitBatch to return only fatal tx.Commit errors
- Update cachedLinkArtist to check errors via database.IsUniqueViolation
- Update handleConfigUpdate to capture and log scan warning count
2026-03-02 19:18:11 -05:00
yonlu 0860b2fd4b fix(02-01): log MPRIS callback errors instead of discarding them
- OnPause, OnPlayPause, OnStop, OnSeek now check errors and log at Warn level
- All four MPRIS closures use yj.logger.Warn for non-fatal error reporting
- No more silently discarded player.Pause() / player.Seek() errors
2026-03-02 18:39:54 -05:00
yonlu 2a86408201 fix(02-01): eliminate package-level startupErr and fix config file permissions
- Move startupErr from package-level var to YellowJacketApp struct field
- Update OnStartup and OnDomReady to reference yj.startupErr
- Change config.Save() file permissions from 0o666 to 0o644
- Fix nlreturn lint in database/errors.go (pre-existing, blocking commit hook)
2026-03-02 18:39:15 -05:00
yonlu 83de934c39 feat(quick-8): add FindDuplicateTracksInPlaylist backend method
- Add DuplicateTrackInfo and DuplicateCheckResult types
- Implement FindDuplicateTracksInPlaylist on playlist Service
- Regenerate Wails TypeScript bindings
2026-03-01 11:12:04 -05:00
yonlu 6e123bd47f feat(quick-7): add PinDefault config field with backend getter/setter
- Add PinDefault bool to favorites.Config struct with TOML tag
- Add GetPinDefaultPlaylist() and SetPinDefaultPlaylist() methods
- Include PinDefault in emitFavoritesChanged event payload
- Default to true (pinned) for new config installations
2026-03-01 10:05:22 -05:00
yonlu bdaff478e8 feat(quick-5): add CreatedAt/UpdatedAt to playlist Summary struct
- Add CreatedAt and UpdatedAt string fields to Summary struct
- Format as RFC3339 at all construction sites in playlist.go and favorites.go
- Update TypeScript bindings with new fields in models.ts
2026-03-01 08:51:00 -05:00
yonlu 8ba8bbe7be feat(quick-002): add uniquePlaylistName helper and wire into ImportPlaylist
- Add uniquePlaylistName method to auto-rename duplicate names with (1), (2), etc.
- Call uniquePlaylistName only from ImportPlaylist, not CreatePlaylist
2026-02-28 13:53:21 -05:00
yonlu 04b2088b28 feat(quick-002): add CountPlaylistsByName SQL query and regenerate sqlc
- Add CountPlaylistsByName :one query to playlists.sql
- Regenerate sqlc to produce Go function
2026-02-28 13:52:21 -05:00
yonlu c34e4ad029 feat(quick-001): add multi-file picker and batch import support
- Update PlaylistFilePicker to return []string via OpenMultipleFilesDialog
- Add ImportPlaylists method for sequential batch import with partial success
2026-02-28 13:30:36 -05:00
yonlu 3abaeba3af fix(01-01): collapse Player.SetContext double-lock into single acquisition
- Replaced two separate Lock/Unlock pairs with single Lock/defer Unlock
- Both p.ctx assignment and p.restoreStateLocked() now run under same lock hold
- Prevents observing partially-initialized state between the two operations
2026-02-28 12:09:34 -05:00
yonlu daaa6b7f97 fix(01-01): add mutex protection to Queue, Library, and Playlist SetContext methods
- Queue.SetContext acquires existing q.mu before writing q.ctx
- Library struct gets new mu sync.Mutex; SetContext and SetRescanHooks acquire it
- Playlist Service struct gets new mu sync.Mutex; SetContext and SetFavoritesConfig acquire it
- Library and Playlist release lock before calling post-init methods (registerEventHandlers, migrateExistingPlaylists)
2026-02-28 12:09:14 -05:00
yonlu d01f5e5d14 added "default playlist"/ favorites system 2026-02-25 22:53:57 -05:00
yonlu 51da5cfb07 no longer using forked beep 2026-02-25 21:16:29 -05:00
yonlu 4f3244c992 added mpris (linux media player controls) support 2026-02-25 20:51:29 -05:00
yonlu d5010e6fa8 default user volume is 50 now 2026-02-25 19:32:44 -05:00
yonlu 012131283c fixed startup ondomready call to use wails bindings and call when complete 2026-02-25 19:10:37 -05:00
yonlu cf144bf0dd refactored many events to use wails bindings, reducing boilerplate 2026-02-25 18:51:07 -05:00
yonlu baa4644ece extracted cover art handling from library package 2026-02-25 15:31:05 -05:00
yonlu e192d4625e playlist phantom track matching added, updated search queries for efficiency 2026-02-24 21:23:25 -05:00
yonlu ff7649600b refactored full rescan to use hook/lifecycle pattern and added rescan package 2026-02-24 16:11:41 -05:00
yonlu 768a8cf1f2 replaced track info string map with a struct 2026-02-24 15:39:54 -05:00
yonlu d764fefb10 fixed library scan using event listeners instead of store pattern 2026-02-24 15:04:35 -05:00
yonlu 352fa9da61 split queue package into multiple files. other minor fixes 2026-02-24 08:34:28 -05:00
yonlu 153cd0eae0 added refactoring catalog, fixed context menu freezing tracklist 2026-02-23 20:54:50 -05:00
yonlu d925e3d659 added mutex to player to prevent simultaneous access 2026-02-23 20:06:41 -05:00
yonlu 16060023bb audio file info added, fixed right click selecting. 2026-02-23 19:05:57 -05:00
yonlu 3349e785d7 playing a new queue with shuffle enabled now starts at a random track. 2026-02-23 12:13:40 -05:00
yonlu 9dabfb81c5 beginnings of artist grid and artist details view 2026-02-22 19:17:27 -05:00
yonlu 9cb1c6674a changed genre scanning to parse multiple genres, updated db to accommodate. 2026-02-22 13:59:28 -05:00
yonlu b5e70a8ce6 user can configure visible columns in track-list 2026-02-22 11:24:19 -05:00
yonlu 9d84a11543 drag and drop enhancements, fixed playlist creation using old db entries, added icons-only sidebar when small width 2026-02-21 14:16:37 -05:00
logan 2a3a79652c add dev-only profiling with pprof, runtime/trace, and operation timing
Wire up Go's standard profiling toolkit so it's automatically available
in dev builds and completely absent from production. The profiling
package uses build tags (dev/!dev) to eliminate all pprof, trace, and
timing code from release binaries with zero new dependencies.

- backend/profiling: pprof HTTP server on :6060, /debug/trace endpoint,
  block/mutex profiling, and TimeOp helper for structured operation timing
- scripts/profile.sh: interactive menu-driven script that auto-selects
  free ports (8080-8089) so multiple profiles can be open simultaneously
- Instrumented key operations: app init, database init, player load/restore,
  queue set/restore
- Makefile targets: profile, profile-cpu, profile-heap, profile-trace
- .gitignore: exclude trace-*.out and *.pprof artifacts
2026-02-20 18:27:25 -06:00