Commit Graph
5 Commits
Author SHA1 Message Date
vicrodh 6d8c951a38 chore(deps): rusqlite 0.40 (u64 casts; a latent two-statement execute fixed)
rusqlite 0.40 removed ToSql/FromSql for u64 (SQLite integers are i64):
every u64 column now reads/writes through an explicit i64 cast. It also
rejects a multi-statement execute() instead of silently running only the
first statement — which is what catalog.rs's editions/logical_albums
prune had been doing all along; it is an execute_batch now, so the
logical_albums prune finally runs.

cc
2026-08-29 08:36:21 -06:00
vicrodh 378afb9c9a feat(lyrics): map and cache embedded translations
LyricsRequest carries an optional translation target that threads
through the LyricsProviders::qobuz boundary to the client; the external
fallback chain is untouched. LyricsDoc gains translation
(Option<Box<TranslatedLyrics>> with a LyricsKind dispatch mirroring the
Android v10 mapper: wsync->WordSynced, lsync->LineSynced, plain->Plain)
plus a client-derived has_translation (requested lang in
translation_langs, false when none requested). QobuzWsync stores the
translation verbatim in the existing cache JSON (serde default, no DB
migration) with its lang recorded: a synced cache hit only serves a
language request when the stored translation matches it, otherwise the
chain refetches; original-only requests keep today's behavior.

km
2026-07-22 19:12:07 -06:00
vicrodh 999ded11ff feat(slint): post-lyrics UI polish sweep + correctness fixes
- TrackRow: Korean/CJK titles render via layout-assigned width+height
  (SongCard parity, never femtovg-measured); explicit "E" badge hugs the
  title text; duration + position number dropped to 13px so they read
  smaller than the 14px title.
- AlbumView: label/awards rail 214->160px with smaller card/icon/padding
  and centered headings in the compact rail; removed the dark right gutter
  (full-width Flickable, content clears the scrollbar via the 32px page
  padding); column headers homologated to Playlist casing (Title/Duration/
  Quality), same in LocalAlbumView.
- ArtistView: network sidebar auto-collapses on ShellState.content-
  constrained (the AlbumView signal) and no longer re-opens on artist->
  artist navigation (reset_network_sidebar respects the constraint).
- Hero titles homologated to Typography.section (18px) across MyQBZ detail,
  Musician, Label releases, Artists-by-location, Offline Manager.
- Lyrics: Qobuz || LRCLIB parallel fetch, next-track prefetch, source
  footer, asymmetric line fade.

cc
2026-06-11 22:03:46 -06:00
vicrodh 5f9fd5bdd6 feat(slint): lyrics sync engine with karaoke fill and auto-center scroll
S4 of the lyrics epic: ms-precision position source, 30Hz sync engine,
word-anchored karaoke fill, auto-centered ladder scroll, QConnect peer
following.

- qbz-player: read-only SharedState::current_position_ms() derived from
  the existing playback_start_millis/position_at_start anchors (Q1; no
  stream/seek/format path touched) + unit test
- qbz-lyrics: new sync module porting the Tauri active-line math (binary
  search active index, per-line progress with the 0.99 snap) plus the
  word-anchored clip fraction for Qobuz wsync lines (char-proportional
  word width approximation, Q2); unit tests
- qbz-slint: lyrics_sync engine - adaptive slint::Timer (33ms while
  panel open + synced + playing, 250ms gate polling otherwise),
  equality-guarded pushes, fill animation zeroed across discontinuities
  (line change / backward seek); kick() on doc commit and panel open
- QConnect (Q7): the poll loop controller branch publishes the raw
  renderer anchor; the engine extrapolates it per tick so lyrics follow
  the peer (Tauri freezes); local fallthrough clears the anchor
- LyricsLinesView: karaoke fill via clipped bright overlay text over the
  dim base (rect-clip approximation, D5); auto-center scroll from
  layout-relative active-row geometry, smooth for <=2-line moves and
  instant for jumps/initial sync, animated via a separate scroll-target
  property so user wheel input is never animated
- LyricsState: line-progress + fill-anim-ms properties

cc
2026-06-10 17:14:37 -06:00
vicrodh d12039371b feat(lyrics): qbz-lyrics engine crate with Qobuz-first chain, LRC parse/emit, providers, cache
S2 of the Lyrics epic: new shared crate crates/qbz-lyrics (headless,
frontend-agnostic per ADR-006), the whole fetch/parse/cache engine in one
testable home for Slint, Tauri and the TUI.

- Domain model: LyricsDoc/LyricsLine/Word (native Qobuz wsync word stamps
  preserved) + the Tauri-wire-compatible LyricsPayload (camelCase serde);
  LyricsProvider gains the qobuz variant and round-trips it.
- LRC parser ported from the Tauri TS semantics (gap markers as end-of-vocal,
  8s MAX_SUNG cap, median last-line end) with the F5 defects fixed forward:
  multi-stamp lines split per stamp, [offset:] honored. Emitter renders wsync
  line bounds as LRC-with-gap-markers (Q5 persistence form, lossy at word
  level only).
- Providers ported verbatim from src-tauri/src/lyrics/providers.rs: LRCLIB
  search-first + scorer and lyrics.ovh, request shapes byte-identical.
- Cache: same per-user SQLite schema/path Tauri uses (WAL per ADR-002,
  no TTL) plus the additive qobuz_wsync_json column (amended Q5) with an
  idempotent in-place migration for Tauri-era DBs; readers prefer wsync.
  Stats read entries AND size from the per-user path (F1 fix).
- Orchestrator LyricsService: cache probe with uniform plain-only soft miss
  (Q4) -> Qobuz primary (wsync authoritative; plain held while LRCLIB is
  probed for synced, the no-sync-regression rule) -> LRCLIB with one retry
  on transport error -> lyrics.ovh; offline = cache-only with typed
  NotAvailableOffline (F3); in-flight dedupe via shared futures (F6);
  request-key echo on every response for the caller stale guard (F2).
- 55 unit tests: parser/emitter round-trips, scorer matrix, cache lifecycle
  + schema migration, chain priority/offline/dedupe with mocked providers.

cc
2026-06-10 16:22:57 -06:00