Skip to content

Make SearchWindow manual picks sticky + add 'Reset lyrics for this track' menu item#192

Open
koto9x wants to merge 5 commits into
aviwad:mainfrom
koto9x:upstream-pr-b-sticky-picks
Open

Make SearchWindow manual picks sticky + add 'Reset lyrics for this track' menu item#192
koto9x wants to merge 5 commits into
aviwad:mainfrom
koto9x:upstream-pr-b-sticky-picks

Conversation

@koto9x

@koto9x koto9x commented Jun 1, 2026

Copy link
Copy Markdown

Summary

Two universal UX improvements that are independent of any Apple Music or player-specific work:

  1. Sticky manual picks: When the user opens the search window (magnifying glass) and applies a specific lyric source, that choice is now persisted with userPicked = true. On subsequent plays of the same track, LyricFever skips the entire network chain and returns the cached lyrics directly — no unnecessary re-fetching.

  2. Reset button: A new arrow.counterclockwise icon in the menubar button row lets the user bust the sticky cache for the currently-playing track. LyricFever deletes the CoreData entry and re-runs the full lyric chain on next play. Useful when lyrics were auto-cached incorrectly and then manually fixed, or after a new release updates official sync.

What's included

  • SongObject schema v2 — adds two fields via lightweight Core Data migration:
    • userPicked: Bool (default false) — true when lyrics came from a user's explicit search-window selection
    • sourceProvider: String? — which provider succeeded ("spotify", "lrclib", "user_picked", etc.)
  • SearchWindow.swift — sets userPicked = true and sourceProvider = "user_picked" when user applies lyrics
  • ViewModel.resetLyricsForCurrentTrack() — deletes the CoreData entry by track ID, cancels in-flight fetch, and re-triggers setCurrentProperties()
  • MenubarWindowView.swift — new arrow.counterclockwise SmallMenubarButton wired to the reset method; tooltip: "Reset lyrics for this track (clears cache, re-runs chain)"
  • ViewModel.fetchAllNetworkLyrics() — writes sourceProvider on every successful chain result and userPicked = false
  • ViewModel.fetchLyrics() — sticky fast-path: if existing CoreData entry has userPicked = true, return immediately without hitting the network

What's NOT included (intentional)

  • Apple Music integration (separate PR)
  • Album prefetch (separate PR)
  • No schema dependency on Apple Music fields — this PR's migration adds only userPicked + sourceProvider

Note on MediaController() fix

The upstream repo's ViewModel.swift still calls MediaController(bundleIdentifier:), but ejbills/mediaremote-adapter removed that parameter in commit b8ce5d1. This PR quietly fixes that call to MediaController() so the upstream builds cleanly.

Test plan

  • Play a track → lyrics auto-fetch via chain → userPicked remains false in CoreData
  • Open search window → apply LRClib result → replay same track → no network fetch fires (console: "CoreData Fetch (userPicked sticky)")
  • Use the arrow.counterclockwise reset button → CoreData entry deleted → replay → full chain fires again
  • Tooltip visible on hover: "Reset lyrics for this track (clears cache, re-runs chain)"

koto9x and others added 5 commits June 2, 2026 08:40
Lightweight CoreData migration. Adds two fields to SongObject:
- userPicked: Bool (default false) — true when the user manually
  selected lyrics via the search window; sticky flag that bypasses
  the network chain on subsequent plays.
- sourceProvider: String? — which provider succeeded ("spotify",
  "lrclib", "user_picked", etc.); used by the reset button.
…nd cache

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds resetLyricsForCurrentTrack() to ViewModel (deletes CoreData entry
by track ID, cancels in-flight fetch, re-triggers setCurrentProperties)
and wires it to a new arrow.counterclockwise SmallMenubarButton placed
between the search (magnifyingglass) and translate buttons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…use correct method names

- SearchWindow.swift: drop song.appleMusicID + song.albumID (those fields
  are added by the separate Apple Music PR; this PR only adds userPicked +
  sourceProvider to the schema)
- ViewModel: MediaController() call no longer takes bundleIdentifier param
  (ejbills/mediaremote-adapter removed it in b8ce5d1); call setCurrentProperties()
  not setCurrentPropertiesPublic() which doesn't exist upstream
koto9x added a commit to koto9x/LyricFever that referenced this pull request Jul 4, 2026
Upstream PRs:
- A: koto9x:upstream-pr-a-applemusic → aviwad#191
  Title: Add Apple Music as a first-class lyric source via MusicKit
  Commits: TTMLParser, AppleMusicAuthManager, AppleMusicAuthView,
           schema v2 (appleMusicID only), catalog ID capture (Task 6),
           AppleMusicLyricProvider, ViewModel chain reorder,
           auth sheet trigger + Window scene fix

- B: koto9x:upstream-pr-b-sticky-picks → aviwad#192
  Title: Make SearchWindow manual picks sticky + add 'Reset lyrics' menu item
  Commits: schema v2 (userPicked+sourceProvider only),
           ViewModel sticky read path, SearchWindow apply,
           resetLyricsForCurrentTrack + menubar button

- C: koto9x:upstream-pr-c-album-prefetch → aviwad#193
  Title: Optional: prefetch lyrics for every track on the currently-playing album
  Commits: schema v3 (albumID), AppleMusicPrefetcher.warmAlbum,
           prefetchAlbumLyrics toggle (DEFAULT OFF), ViewModel gating

Adapter dependency: ejbills/mediaremote-adapter#4 (koto9x/mediaremote-adapter
feat/expose-adam-ids temporarily pinned in PR-A pbxproj until upstream merges).

Stays in fork (not upstreamed): Lyrics9x provider, 3-tier romanization+translation,
Plexamp player + smart routing, MediaRemote adapter callback fork-specific bits,
Tailscale ATS exception, warmQueueWindow, sandbox fix for Plexamp,
Kotopia Inc team/bundle ID.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant