docs(17-02): complete track details save flow & cover art editing plan
- SUMMARY.md with 5 commits (1 feat + 4 fixes during verification) - STATE.md updated: Phase 17 complete, decisions added - ROADMAP.md updated: Phase 17 2/2 Complete - REQUIREMENTS.md updated: EDIT-02, EDIT-03, EDIT-04 all complete
This commit is contained in:
@@ -31,8 +31,8 @@ Requirements for v1.2 Tag Editing milestone. Each maps to roadmap phases.
|
||||
### Single Track Edit
|
||||
|
||||
- [x] **EDIT-01**: User can open tag editor for a single track from context menu or detail view
|
||||
- [ ] **EDIT-02**: Editor shows all 8 editable fields with current values pre-populated
|
||||
- [ ] **EDIT-03**: Editor shows current cover art with option to replace from image file
|
||||
- [x] **EDIT-02**: Editor shows all 8 editable fields with current values pre-populated
|
||||
- [x] **EDIT-03**: Editor shows current cover art with option to replace from image file
|
||||
- [x] **EDIT-04**: Saving writes tags to file, updates DB, updates FTS5, and refreshes all views immediately
|
||||
|
||||
### Batch Edit
|
||||
@@ -104,8 +104,8 @@ Which phases cover which requirements. Updated during roadmap creation.
|
||||
| SYNC-03 | Phase 16 | Complete |
|
||||
| SYNC-04 | Phase 16 | Complete |
|
||||
| EDIT-01 | Phase 17 | Complete |
|
||||
| EDIT-02 | Phase 17 | Pending |
|
||||
| EDIT-03 | Phase 17 | Pending |
|
||||
| EDIT-02 | Phase 17 | Complete |
|
||||
| EDIT-03 | Phase 17 | Complete |
|
||||
| EDIT-04 | Phase 17 | Complete |
|
||||
| BATCH-01 | Phase 18 | Pending |
|
||||
| BATCH-02 | Phase 18 | Pending |
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
- [x] **Phase 15: Schema Migration & Write Safety** — FTS5 contentless_delete migration and atomic file write utility (completed 2026-03-16)
|
||||
- [x] **Phase 16: Tag Writing & Database Sync** — Format-specific tag writers (MP3, FLAC, cover art) with inline DB + FTS5 update pipeline (3 plans) (completed 2026-03-17)
|
||||
- [ ] **Phase 17: Single Track Edit** — End-to-end single track editing: UI → file write → DB sync → view refresh
|
||||
- [x] **Phase 17: Single Track Edit** — End-to-end single track editing: UI → file write → DB sync → view refresh (completed 2026-03-18)
|
||||
- [ ] **Phase 18: Batch Edit** — Multi-select batch editing with three-state field model, progress, and batch cover art
|
||||
- [ ] **Phase 19: OGG Vorbis Tag Writing** — Custom OGG page rewriter for Vorbis Comment tag writing (stretch)
|
||||
|
||||
@@ -87,7 +87,7 @@ Plans:
|
||||
2. The editor displays all 8 editable fields (title, artist, album, genre, year, track number, disc number, composer) pre-populated with the track's current values — empty fields show as empty, not "Unknown"
|
||||
3. The editor displays the track's current cover art (or a placeholder if none) with a button to select a replacement image file from disk
|
||||
4. Clicking "Save" writes the changes to the audio file, updates the database and search index, and refreshes all visible views (track list, album view, artist view, genre view, queue, now-playing bar) — the user sees the new metadata everywhere without restarting or rescanning
|
||||
**Plans:** 1/2 plans executed
|
||||
**Plans:** 2/2 plans complete
|
||||
Plans:
|
||||
- [ ] 17-01-PLAN.md — Backend wiring (WriteTrackTagsByPath, ImageFilePicker) + library store event handler + context menu fix
|
||||
- [ ] 17-02-PLAN.md — Track details dialog save flow, cover art editing, error handling, human verification
|
||||
@@ -133,7 +133,7 @@ Plans:
|
||||
| 14. Performance Optimization | v1.1 | 4/4 | Complete | 2026-03-15 |
|
||||
| 15. Schema Migration & Write Safety | 2/2 | Complete | 2026-03-16 | - |
|
||||
| 16. Tag Writing & Database Sync | 3/3 | Complete | 2026-03-17 | - |
|
||||
| 17. Single Track Edit | 1/2 | In Progress| | - |
|
||||
| 17. Single Track Edit | 2/2 | Complete | 2026-03-18 | - |
|
||||
| 18. Batch Edit | v1.2 | 0/? | Not started | - |
|
||||
| 19. OGG Vorbis Tag Writing | v1.2 | 0/? | Not started | - |
|
||||
|
||||
|
||||
+17
-13
@@ -3,12 +3,12 @@ gsd_state_version: 1.0
|
||||
milestone: v1.2
|
||||
milestone_name: Tag Editing
|
||||
status: in-progress
|
||||
last_updated: "2026-03-18T01:05:17Z"
|
||||
last_updated: "2026-03-18T15:18:33Z"
|
||||
progress:
|
||||
total_phases: 5
|
||||
completed_phases: 2
|
||||
total_plans: 6
|
||||
completed_plans: 6
|
||||
completed_phases: 3
|
||||
total_plans: 7
|
||||
completed_plans: 7
|
||||
---
|
||||
|
||||
# YellowJacket — Project State
|
||||
@@ -22,10 +22,10 @@ See: .planning/PROJECT.md (updated 2026-03-16)
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: Phase 17 — Single Track Edit (in progress)
|
||||
Plan: 1 of 3 complete
|
||||
Status: Completed 17-01 (backend bridge & frontend plumbing)
|
||||
Last activity: 2026-03-18 — Completed 17-01 (WriteTrackTagsByPath, ImageFilePicker, TrackMetadataChanged handler, context menu fix)
|
||||
Phase: Phase 17 — Single Track Edit (complete)
|
||||
Plan: 2 of 2 complete
|
||||
Status: Phase 17 complete — all single-track edit requirements fulfilled
|
||||
Last activity: 2026-03-18 — Completed 17-02 (save flow, cover art editing, error handling, Wails deserialization fixes)
|
||||
|
||||
### Phase Overview
|
||||
|
||||
@@ -33,7 +33,7 @@ Last activity: 2026-03-18 — Completed 17-01 (WriteTrackTagsByPath, ImageFilePi
|
||||
|-------|--------|
|
||||
| 15. Schema Migration & Write Safety | Complete (2/2 plans) |
|
||||
| 16. Tag Writing & Database Sync | Complete (3/3 plans) |
|
||||
| 17. Single Track Edit | In Progress (1/3 plans) |
|
||||
| 17. Single Track Edit | Complete (2/2 plans) |
|
||||
| 18. Batch Edit | Not started |
|
||||
| 19. OGG Vorbis Tag Writing | Not started |
|
||||
|
||||
@@ -63,6 +63,7 @@ Last activity: 2026-03-18 — Completed 17-01 (WriteTrackTagsByPath, ImageFilePi
|
||||
| 16 | 02 | 20min | 2 | 6 |
|
||||
| 16 | 03 | 9min | 2 | 7 |
|
||||
| 17 | 01 | 11min | 2 | 11 |
|
||||
| 17 | 02 | 25min | 2 | 8 |
|
||||
|
||||
## Accumulated Context
|
||||
|
||||
@@ -96,6 +97,9 @@ Decisions from v1.0 and v1.1 are archived in PROJECT.md Key Decisions table. Key
|
||||
| Global genre orphan cleanup via DELETE WHERE id NOT IN | Simpler than tracking old genre IDs; safe because genres only referenced via recording_genres |
|
||||
| Manually added Wails TypeScript bindings for new Go methods | Wails binding generator runs at `wails dev`/`wails build` time, not via `go generate`; manual addition matches existing pattern exactly |
|
||||
| Track Details opens for first selected track in multi-select | `filePaths[0]` is consistent across all 4 views; avoids blocking the menu item unnecessarily |
|
||||
| ReadFile Go method on FrontendUtil for cover art bytes | Native file dialog returns path; frontend needs bytes for blob preview + save payload |
|
||||
| asInt/asBytes helpers for Wails JSON deserialization | Wails sends JS numbers as float64 and []byte as base64; direct type assertions silently fail |
|
||||
| Cover art DB sync with content-hash dedup + thumbnail generation | Saves to covers cache dir, upserts cover_art row, updates release_groups.cover_art_id |
|
||||
|
||||
### v1.2 Roadmap Decisions
|
||||
|
||||
@@ -136,9 +140,9 @@ Decisions from v1.0 and v1.1 are archived in PROJECT.md Key Decisions table. Key
|
||||
### Last Session
|
||||
|
||||
**Date:** 2026-03-18
|
||||
**What happened:** Executed Phase 17 Plan 01 — Backend bridge methods (WriteTrackTagsByPath, ImageFilePicker), TrackMetadataChanged handler in LibraryStore, removed selection gate on Track Details context menu in all 4 views.
|
||||
**Where we stopped:** Completed 17-01-PLAN.md
|
||||
**Next action:** Execute 17-02 (track-details dialog edit mode wiring)
|
||||
**What happened:** Completed Phase 17 Plan 02 — Save flow with diff-only TagChanges, cover art replace/remove via native file picker, inline error handling. Fixed 4 bugs during verification: stale dialog data, Wails float64 deserialization, cover art DB sync, cover art URL refresh.
|
||||
**Where we stopped:** Completed 17-02-PLAN.md — Phase 17 complete
|
||||
**Next action:** Plan or execute Phase 18 (Batch Edit)
|
||||
|
||||
---
|
||||
*State initialized: 2026-02-27*
|
||||
@@ -152,4 +156,4 @@ Decisions from v1.0 and v1.1 are archived in PROJECT.md Key Decisions table. Key
|
||||
| 19 | fix phantom playlist tracks with multi-root path resolution | 2026-03-16 | 9144ded | [19-fix-phantom-playlist-tracks](./quick/19-fix-phantom-playlist-tracks/) |
|
||||
|
||||
Last activity: 2026-03-16 - Completed quick task 19: fix phantom playlist tracks with multi-root path resolution
|
||||
*Last updated: 2026-03-18 — Completed 17-01 (backend bridge & frontend plumbing)*
|
||||
*Last updated: 2026-03-18 — Completed 17-02 (save flow, cover art editing, Phase 17 complete)*
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
---
|
||||
phase: 17-single-track-edit
|
||||
plan: 02
|
||||
subsystem: ui
|
||||
tags: [tag-editing, cover-art, wails-bindings, lit-element, dialog, file-picker]
|
||||
|
||||
# Dependency graph
|
||||
requires:
|
||||
- phase: 17-single-track-edit
|
||||
provides: WriteTrackTagsByPath, ImageFilePicker, TrackMetadataChanged handler, Track Details context menu
|
||||
provides:
|
||||
- Complete single-track tag editor with save flow, cover art editing, and error handling
|
||||
- ReadFile Go method on FrontendUtil for reading cover art image bytes
|
||||
- DB sync for cover art (save to cache, thumbnail generation, release_group update)
|
||||
- Dialog data refresh after save (track + cover art URLs)
|
||||
affects: [18-batch-edit]
|
||||
|
||||
# Tech tracking
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "Diff-only TagChanges map — only changed fields sent to backend, reducing unnecessary writes"
|
||||
- "Blob URL preview for cover art — instant client-side preview without server round-trip"
|
||||
- "Base64 decode for Go []byte return values — Wails serializes []byte as base64 JSON strings"
|
||||
- "asInt/asBytes helpers for Wails JSON deserialization — JavaScript numbers arrive as float64, arrays as []interface{}"
|
||||
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- frontend/src/components/track-details/track-details.ts
|
||||
- backend/frontendutil/frontendutil.go
|
||||
- backend/tagwriter/tagwriter.go
|
||||
- backend/tagwriter/dbsync.go
|
||||
- backend/tagwriter/mp3.go
|
||||
- backend/tagwriter/flac.go
|
||||
- frontend/wailsjs/go/frontendutil/FrontendUtil.js
|
||||
- frontend/wailsjs/go/frontendutil/FrontendUtil.d.ts
|
||||
|
||||
key-decisions:
|
||||
- "ReadFile Go method on FrontendUtil to return file bytes to frontend — needed because Wails native file dialog returns path, but frontend needs bytes for preview + save"
|
||||
- "asInt/asBytes type coercion helpers in tagwriter — Wails JSON deserialization sends all numbers as float64 and byte arrays as base64 strings"
|
||||
- "Cover art DB sync saves to covers cache directory with content-hash dedup and thumbnail generation"
|
||||
|
||||
patterns-established:
|
||||
- "Wails float64 coercion: always use asInt() helper for numeric TagChanges values, never direct .(int) assertion"
|
||||
- "Wails []byte handling: Go []byte serializes as base64 JSON string; frontend must atob() decode before use"
|
||||
|
||||
requirements-completed: [EDIT-02, EDIT-03, EDIT-04]
|
||||
|
||||
# Metrics
|
||||
duration: 25min
|
||||
completed: 2026-03-18
|
||||
---
|
||||
|
||||
# Phase 17 Plan 02: Track Details Save Flow & Cover Art Editing Summary
|
||||
|
||||
**Diff-only tag save with cover art replace/remove via native file picker, inline error handling, and automatic dialog + view refresh after write**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** ~25 min (implementation) + verification session with bug fixes
|
||||
- **Started:** 2026-03-18T01:08:53Z
|
||||
- **Completed:** 2026-03-18T14:54:17Z
|
||||
- **Tasks:** 2 (1 auto + 1 human-verify)
|
||||
- **Files modified:** 8
|
||||
|
||||
## Accomplishments
|
||||
- Complete save flow: `saveEdit()` builds diff-only TagChanges map and calls `WriteTrackTagsByPath` — unchanged fields are never sent
|
||||
- Cover art editing: native file picker for JPEG/PNG with instant blob preview via object URL; remove button (×) clears embedded art
|
||||
- Inline error handling: errors display in the dialog action bar, edit mode stays active for retry or cancel
|
||||
- Saving state indicator: Save button shows "Saving…" and both buttons disabled during write
|
||||
- Dialog data refresh: after save, track data and cover art URLs are re-fetched from the library store
|
||||
- Cover art DB sync: image saved to covers cache with content-hash dedup + thumbnail generation, release_group updated
|
||||
- Wails JSON deserialization fixes: asInt/asBytes helpers handle float64 numbers and base64 byte arrays
|
||||
|
||||
## Task Commits
|
||||
|
||||
Each task was committed atomically:
|
||||
|
||||
1. **Task 1: Implement saveEdit, cover art editing, error handling, and saving state** - `265a9ea` (feat)
|
||||
2. **Task 2: Verify complete single-track edit flow** — human-verify checkpoint, APPROVED
|
||||
|
||||
**Bug fixes during verification (committed by orchestrator):**
|
||||
3. **Fix: refresh track-details dialog data after save** - `ffcdc41` (fix)
|
||||
4. **Fix: handle float64 numeric values from Wails JSON deserialization** - `900db2e` (fix)
|
||||
5. **Fix: cover art replace and remove (asBytes, DB sync, base64 decode)** - `d7c2965` (fix)
|
||||
6. **Fix: refresh cover art URLs after save** - `8cd4914` (fix)
|
||||
|
||||
## Files Created/Modified
|
||||
- `frontend/src/components/track-details/track-details.ts` - Complete save flow, cover art editing UI, error handling, saving state, dialog refresh
|
||||
- `backend/frontendutil/frontendutil.go` - Added ReadFile method for reading cover art bytes
|
||||
- `backend/tagwriter/tagwriter.go` - Added asInt/asBytes helpers for Wails JSON deserialization
|
||||
- `backend/tagwriter/dbsync.go` - Cover art DB sync (save image, update release_group, orphan cleanup)
|
||||
- `backend/tagwriter/mp3.go` - Use asInt/asBytes helpers for type coercion
|
||||
- `backend/tagwriter/flac.go` - Use asInt/asBytes helpers for type coercion
|
||||
- `frontend/wailsjs/go/frontendutil/FrontendUtil.js` - Wails binding for ReadFile
|
||||
- `frontend/wailsjs/go/frontendutil/FrontendUtil.d.ts` - TypeScript declaration for ReadFile
|
||||
|
||||
## Decisions Made
|
||||
- Added `ReadFile` Go method on FrontendUtil to bridge the gap between native file dialog (returns path) and frontend need for bytes (preview + save). Simplest approach that avoids additional Go-side image processing.
|
||||
- Created `asInt()` and `asBytes()` type coercion helpers in tagwriter package — Wails JSON deserialization always sends JavaScript numbers as Go `float64` and `[]byte` as base64 strings. Direct `.(int)` assertions silently failed.
|
||||
- Cover art DB sync saves the image to the covers cache directory using content-hash dedup with thumbnail generation, then updates `release_groups.cover_art_id`. Clear sets `cover_art_id` to NULL.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues (by orchestrator during verification)
|
||||
|
||||
**1. [Rule 1 - Bug] Dialog showed stale track data after save**
|
||||
- **Found during:** Task 2 (human verification)
|
||||
- **Issue:** After save, dialog returned to read-only mode but showed pre-edit values because `this.track` was the original snapshot passed via `show()`
|
||||
- **Fix:** After successful `WriteTrackTagsByPath`, re-fetch tracks from library store and update `this.track` with fresh data
|
||||
- **Files modified:** `frontend/src/components/track-details/track-details.ts`
|
||||
- **Committed in:** `ffcdc41`
|
||||
|
||||
**2. [Rule 1 - Bug] Numeric fields silently ignored during save**
|
||||
- **Found during:** Task 2 (human verification)
|
||||
- **Issue:** Wails JSON deserialization sends all JavaScript numbers as Go `float64`. All `.(int)` type assertions on year, track_number, and disc_number silently failed (returned zero-value + false), meaning numeric edits were dropped
|
||||
- **Fix:** Added `asInt()` helper that handles both `float64` and `int` types; replaced all direct `.(int)` assertions across tagwriter package
|
||||
- **Files modified:** `backend/tagwriter/tagwriter.go`, `backend/tagwriter/dbsync.go`, `backend/tagwriter/mp3.go`, `backend/tagwriter/flac.go`
|
||||
- **Committed in:** `900db2e`
|
||||
|
||||
**3. [Rule 1 - Bug] Cover art replace and remove did not work**
|
||||
- **Found during:** Task 2 (human verification)
|
||||
- **Issue:** Three related issues: (a) Cover art bytes from frontend arrived as `[]interface{}` of `float64` — same deserialization issue as numerics. (b) DB sync for cover art was a placeholder no-op — didn't save image to cache or update release_group. (c) Frontend `ReadFile` returns base64 string (Go `[]byte` JSON encoding), not `number[]` — preview blob was corrupted.
|
||||
- **Fix:** Added `asBytes()` helper for `[]interface{}` → `[]byte` conversion. Implemented full cover art DB sync (save to covers cache with content-hash dedup + thumbnail generation, upsert cover_art row, update release_groups). Fixed frontend to decode base64 with `atob()` before creating `Uint8Array`.
|
||||
- **Files modified:** `backend/tagwriter/tagwriter.go`, `backend/tagwriter/dbsync.go`, `backend/tagwriter/flac.go`, `backend/tagwriter/mp3.go`, `frontend/src/components/track-details/track-details.ts`
|
||||
- **Committed in:** `d7c2965`
|
||||
|
||||
**4. [Rule 1 - Bug] Cover art image reverted to old after save**
|
||||
- **Found during:** Task 2 (human verification)
|
||||
- **Issue:** After save, dialog refreshed `this.track` but kept stale `this.coverArt` URLs pointing to old content-hash files. The image visually reverted until the dialog was closed and reopened.
|
||||
- **Fix:** After save, re-fetch albums alongside tracks and re-resolve cover art URLs from updated album data
|
||||
- **Files modified:** `frontend/src/components/track-details/track-details.ts`
|
||||
- **Committed in:** `8cd4914`
|
||||
|
||||
---
|
||||
|
||||
**Total deviations:** 4 auto-fixed (all Rule 1 bugs discovered during human verification)
|
||||
**Impact on plan:** All fixes were necessary for correct end-to-end functionality. The Wails JSON deserialization issues (float64 numbers, base64 bytes) were a systemic pattern not visible until real runtime testing. No scope creep — all fixes are within the plan's boundary.
|
||||
|
||||
## Issues Encountered
|
||||
None beyond the deviations documented above. All issues were discovered and resolved during the human verification checkpoint.
|
||||
|
||||
## User Setup Required
|
||||
|
||||
None - no external service configuration required.
|
||||
|
||||
## Next Phase Readiness
|
||||
- Phase 17 is now complete (2/2 plans done)
|
||||
- Single-track editing works end-to-end: tag writes, cover art replacement/removal, error handling, view refresh
|
||||
- Ready for Phase 18 (Batch Edit) which builds on this foundation
|
||||
- The `asInt()`/`asBytes()` Wails deserialization helpers established in this plan will be essential for Phase 18
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
All 6 key files verified on disk. All 5 commits verified in git history.
|
||||
|
||||
---
|
||||
*Phase: 17-single-track-edit*
|
||||
*Completed: 2026-03-18*
|
||||
Reference in New Issue
Block a user