fix(ephemeral): replace 1 << 48 with 2 ** 48 for ephemeral track id floor
JavaScript bitwise shift operates on 32-bit signed integers, so
`1 << 48` is `1 << (48 % 32)` = `1 << 16` = 65536. Every Qobuz track
id sits above that, so the existing `id >= EPHEMERAL_ID_FLOOR` checks
were classifying every Qobuz track as ephemeral and disabling the
favorite / playlist / mixtape / collection actions for them — most
visibly in the immersive player favorite button, but also silently
stripping Qobuz tracks from the persisted session queue.
Five places shared the same broken constant, all now use `2 ** 48`
(281474976710656) — the actual ephemeral id floor defined in
src-tauri/src/ephemeral_library/mod.rs:
- src/routes/+page.svelte (two metadataActionsDisabled checks for
the immersive player and now-playing bar, plus the session-save
EPHEMERAL_ID_FLOOR filter).
- src/lib/components/QueuePanel.svelte (isEphemeralQueueTrack guard
that hides favorite / playlist / track-info actions for queue
rows).
- src/lib/stores/playerStore.ts (isEphemeralTransition flag in the
gapless carve-out and CUE virtual-track position translation).
- src/lib/components/views/LocalLibraryView.svelte (close-folder
cleanup check — only ephemeral folders should wipe the queue +
now-playing slot when closed).
Each call site keeps a short comment naming the trap so future edits
don't reach for the same bitwise expression.
cc
This commit is contained in:
4 files changed
+17
-7
No files matched your search
@@ -29,13 +29,15 @@
|
||||
parental_warning?: boolean;
|
||||
}
|
||||
|
||||
// Mirrors EPHEMERAL_ID_FLOOR (1 << 48) in src-tauri/src/ephemeral_library.
|
||||
// Mirrors EPHEMERAL_ID_FLOOR (2^48) in src-tauri/src/ephemeral_library.
|
||||
// Track ids at or above this threshold come from the in-memory ephemeral
|
||||
// cache, not the library DB. Favorites / playlists / track-info actions
|
||||
// require a DB row and don't make sense for ephemeral tracks; the
|
||||
// helper below gates the corresponding UI off so users don't get
|
||||
// dead-end clicks.
|
||||
const EPHEMERAL_ID_FLOOR = 1 << 48;
|
||||
// 2 ** 48 (NOT 1 << 48 — JS bitwise shift is 32-bit, 1 << 48 silently
|
||||
// becomes 65536 and every Qobuz track ends up "ephemeral").
|
||||
const EPHEMERAL_ID_FLOOR = 2 ** 48;
|
||||
function isEphemeralQueueTrack(id: string | number | null | undefined): boolean {
|
||||
if (id == null) return false;
|
||||
return Number(id) >= EPHEMERAL_ID_FLOOR;
|
||||
|
||||
@@ -1330,7 +1330,9 @@
|
||||
// not a DB row. Used for "did the user just close a folder whose
|
||||
// tracks are still playing?" checks so we know whether to wipe the
|
||||
// queue + now-playing slot when an ephemeral session ends.
|
||||
const EPHEMERAL_ID_FLOOR = 1 << 48;
|
||||
// 2 ** 48 (NOT 1 << 48 — JS bitwise shift is 32-bit, 1 << 48 silently
|
||||
// becomes 65536 and every Qobuz track gets mis-classified).
|
||||
const EPHEMERAL_ID_FLOOR = 2 ** 48;
|
||||
const EPHEMERAL_PATH_STORAGE_KEY = 'qbz-ephemeral-folder-path';
|
||||
let ephemeralFolder = $state<EphemeralFolderState | null>(null);
|
||||
let openingEphemeralFolder = $state(false);
|
||||
|
||||
@@ -87,7 +87,10 @@ interface BackendPlaybackState {
|
||||
// ephemeral cache, not DB rows; the playback logic special-cases them
|
||||
// in a couple of places (gapless transition is_playing carve-out, CUE
|
||||
// virtual-track position translation).
|
||||
const EPHEMERAL_ID_FLOOR = 1 << 48;
|
||||
// 2 ** 48 (NOT 1 << 48 — JavaScript bitwise shift is 32-bit, 1 << 48
|
||||
// silently truncates to 65536 and every Qobuz track ends up classified
|
||||
// as ephemeral, suppressing favorites and breaking session save).
|
||||
const EPHEMERAL_ID_FLOOR = 2 ** 48;
|
||||
|
||||
/**
|
||||
* Bit-perfect mode of the active audio stream, reported by the Rust backend.
|
||||
|
||||
@@ -4474,7 +4474,10 @@
|
||||
// Strip them from the persisted queue and clear the current-index
|
||||
// pointer if it was sitting on one — the ephemeral pane comes back
|
||||
// via folder-path persistence and the user re-clicks play.
|
||||
const EPHEMERAL_ID_FLOOR = 1 << 48;
|
||||
// 2 ** 48 (NOT 1 << 48 — JavaScript bitwise shift operates on
|
||||
// 32-bit ints so 1 << 48 silently truncates to 65536, which
|
||||
// mis-classified every Qobuz track as ephemeral).
|
||||
const EPHEMERAL_ID_FLOOR = 2 ** 48;
|
||||
const persistedTracks: PersistedQueueTrack[] = [];
|
||||
let persistedCurrentIndex: number | null = null;
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
@@ -6884,7 +6887,7 @@
|
||||
{isFavorite}
|
||||
onToggleFavorite={toggleFavorite}
|
||||
onAddToPlaylist={openAddToPlaylistModal}
|
||||
metadataActionsDisabled={currentTrack != null && currentTrack.id >= (1 << 48)}
|
||||
metadataActionsDisabled={currentTrack != null && currentTrack.id >= 2 ** 48}
|
||||
onOpenQueue={toggleQueue}
|
||||
onOpenMiniPlayer={() => {
|
||||
void enterMiniplayerMode();
|
||||
@@ -6990,7 +6993,7 @@
|
||||
onToggleRepeat={toggleRepeat}
|
||||
{isFavorite}
|
||||
onToggleFavorite={toggleFavorite}
|
||||
metadataActionsDisabled={currentTrack != null && currentTrack.id >= (1 << 48)}
|
||||
metadataActionsDisabled={currentTrack != null && currentTrack.id >= 2 ** 48}
|
||||
lyricsLines={lyricsLines}
|
||||
lyricsActiveIndex={lyricsActiveIndex}
|
||||
lyricsActiveProgress={lyricsActiveProgress}
|
||||
|
||||
Reference in new issue
Block a user