- Add blank lines before cuddled expressions in wav_test.go
- Fix cuddled copy expression in wav.go writeRIFF
- All WAV lint issues resolved (remaining are pre-existing in other files)
- createTestWAV: builds minimal valid WAV with optional ID3v2 tag
- readWavID3Tags: extracts ID3v2 from RIFF via parseRIFF + dhowden/tag
- createTestWAVWithExtraChunks: adds LIST INFO and bext chunks for preservation tests
- makePCMFmtData: generates 16-byte PCM format data
Archive v1.2 milestone: ROADMAP + REQUIREMENTS + phases to milestones/.
Evolve PROJECT.md with v1.2 validated requirements and key decisions.
Update RETROSPECTIVE.md with v1.2 lessons and cross-milestone trends.
Clean STATE.md for next milestone.
- track-list: branch on selection count, resolve tracks from this.tracks
- cover-grid: branch on selection count, resolve from expandedTracks
- queue-panel: branch on indices count, resolve via libraryStore.getCachedTracks
- playlist-details: branch on selection count, resolve via libraryStore
- Each view determines coverArt/coverArtMixed state and calls showBatch()
- showBatch() API for multi-track entry with merged field values
- Three-state field model: keep/set/clear via dirty tracking in editValues
- Confirmation dialog showing field changes before batch save
- Progress bar with live counter wired to BatchWriteProgress events
- Cancel button calling CancelBatchWrite during batch write
- Results view with success/failure counts and expandable failure details
- Batch cover art: pick, preview, or clear for all selected tracks
- Post-save data refresh returning to updated summary view
- Single-track show() path unchanged (batchMode = false)
- Add BatchFailure and BatchResult types for structured batch outcomes
- Add cancelBatch channel and suppressEvents flag to TagWriter struct
- Add CancelBatchWrite method for mid-batch cancellation from frontend
- Add BatchWriteTrackTags method processing tracks sequentially
- Emit BatchWriteProgress event per-track with current/total/succeeded/failed
- Suppress per-track TrackMetadataChanged; emit single event after batch
- Wails bindings auto-generated for BatchWriteTrackTags and CancelBatchWrite
- tagwriter namespace with BatchResult/BatchFailure in models.ts
After a successful save, re-fetch albums alongside tracks and re-resolve
cover art URLs from the updated album data. Previously the dialog only
refreshed this.track but kept stale this.coverArt URLs pointing to the
old content-hash files, causing the image to revert until reopen.
Three issues fixed:
1. asBytes() helper for []interface{} → []byte conversion — same
float64 deserialization issue as numeric fields. Cover art data
from the frontend arrives as []interface{} of float64, not []byte.
2. DB sync for cover art — was a placeholder no-op. Now saves image
to covers cache dir (content-hash dedup + thumbnail generation),
upserts cover_art row, and updates release_groups.cover_art_id.
Clear sets cover_art_id to NULL on linked release groups.
3. Frontend ReadFile returns base64 string (Go []byte JSON encoding),
not number[]. Decode with atob() before creating Uint8Array for
preview blob URL.
Wails deserializes JSON numbers from JavaScript as float64, not int.
All .(int) type assertions on year, track_number, and disc_number
silently failed. Add asInt() helper, replace all assertions.
After saveEdit() succeeds, re-fetch tracks from library store and update
this.track with the fresh data so the dialog shows updated values instead
of the stale snapshot passed via show().
- Wire saveEdit() to WriteTrackTagsByPath with diff-only TagChanges map
- Add cover art selection via ImageFilePicker with instant blob preview
- Add cover art removal (× button) with clearCoverArt state
- Show saving indicator and disable buttons during save
- Display errors inline in action bar; edit mode stays active on error
- Add ReadFile Go method on FrontendUtil to read cover art bytes
- Add Wails binding for ReadFile
- Clean up all edit state (editValues, pendingCoverArt, errorMessage) on close/cancel
- Created 17-01-SUMMARY.md
- Updated STATE.md with position, decisions, metrics
- Updated ROADMAP.md with plan progress
- Marked EDIT-01 and EDIT-04 complete in REQUIREMENTS.md
- LibraryStore now listens for TrackMetadataChanged and invalidates all caches
- Track Details context menu item visible for any right-clicked track in all 4 views
- Removed selectionCount === 1 gate from track-list, queue-panel, cover-grid, playlist-details
- WriteTrackTagsByPath resolves filePath to trackID via GetAudioFileByPath
- ImageFilePicker opens native file dialog filtered to JPEG/PNG
- Added Wails TypeScript bindings for both new methods