feat(player): disable metadata actions for ephemeral tracks

Library-bound actions (favorite, add-to-playlist, track info) require a
DB row to operate; ephemeral tracks live only in memory and would 404
on use. Surface them disabled rather than removed so the affordance
stays discoverable in the chrome — users still see the icon, the
tooltip explains why it's inert.

Surfaces wired
- NowPlayingBar: + and ♥ disabled when active track id >= 2^48.
- QueuePanel: now-playing ♥ + per-track Add to Playlist + Track Info
  in both queue and history menus disabled per-row by id range.
- ImmersiveControls + PlayerControlsCompact: ♥ disabled.
- ImmersivePlayer: passthrough prop to PlayerControlsCompact.
- MiniPlayerFooter / MiniPlayerWindowControls: no metadata actions in
  these surfaces, nothing to gate.

Detection is by id range (>= EPHEMERAL_ID_FLOOR), not by source string.
The setQueueForLocalTracks mapping rewrites `source: 'ephemeral'` to
`'local'` before the track reaches the queue, so a string-equality
check would never fire — id range matches the rest of the ephemeral
codebase (gapless carve-out, CUE boundary, seek offset, queue/now-
playing wipe).

Tooltip on the disabled state uses the new
`actions.unavailableForEphemeral` key, translated for en, es, de, fr, pt.

cc
This commit is contained in:
vicrodh committed 2026-05-09 09:24:37 -06:00
1 parent 0fe19dd460
commit 2d33d7cb42
11 files changed
+112 -29

No files matched your search

+2
View File
@@ -6727,6 +6727,7 @@
{isFavorite}
onToggleFavorite={toggleFavorite}
onAddToPlaylist={openAddToPlaylistModal}
metadataActionsDisabled={currentTrack != null && currentTrack.id >= (1 << 48)}
onOpenQueue={toggleQueue}
onOpenMiniPlayer={() => {
void enterMiniplayerMode();
@@ -6832,6 +6833,7 @@
onToggleRepeat={toggleRepeat}
{isFavorite}
onToggleFavorite={toggleFavorite}
metadataActionsDisabled={currentTrack != null && currentTrack.id >= (1 << 48)}
lyricsLines={lyricsLines}
lyricsActiveIndex={lyricsActiveIndex}
lyricsActiveProgress={lyricsActiveProgress}