mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
fix(queue): pin queueServerId on auto-add paths so infinite + radio top-up refs resolve (#930)
* fix(queue): extend server-pin contract to auto-add paths The infinite-queue top-up and radio top-up paths in nextAction.ts read state.queueServerId directly inside their set callbacks. When the queue was populated without a queue-replacing playTrack (single- track enqueue from a SongRow + button, AdvancedSearch row, etc), queueServerId stayed null, seedQueueResolver skipped its store-write under the if (serverId) guard, and the auto-added refs landed with an empty server key. Every auto-added row rendered as the resolver placeholder (… / 0:00) until the next time something happened to bind the server. Same symptom PR #892 fixed for the manual enqueue surface, just on the auto-add paths. Extract ensureQueueServerPinned() from the private helper in queueMutationActions.ts into playbackServer.ts so it can be shared. Call it before every set callback that appends or splices refs in nextAction.ts — appendTracksAndPlayFirst, proactive infinite top-up, proactive radio top-up. Helper returns the pinned canonical key so the caller does not need a second store read. Regression coverage in ensureQueueServerPinned.test.ts: pin on null + active server, idempotent on already-bound, empty-string fallback when no active server, canonical-key return value matches what toQueueItemRefs expects (not the raw auth uuid). Existing b1QueueServerIdentity.test.ts continues to cover the manual enqueue surface unchanged. * docs(release): CHANGELOG for queue auto-top-up placeholder fix (PR #930)
This commit is contained in:
committed by
GitHub
parent
ae1572f370
commit
2a88ca3248
+12
-3
@@ -2,6 +2,7 @@ import { getSimilarSongs2, getTopSongs } from '../api/subsonicArtists';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { buildInfiniteQueueCandidates } from '../utils/playback/buildInfiniteQueueCandidates';
|
||||
import { songToTrack } from '../utils/playback/songToTrack';
|
||||
import { ensureQueueServerPinned } from '../utils/playback/playbackServer';
|
||||
import { useAuthStore } from './authStore';
|
||||
import { setIsAudioPaused } from './engineState';
|
||||
import {
|
||||
@@ -35,8 +36,11 @@ type GetState = () => PlayerState;
|
||||
*/
|
||||
function appendTracksAndPlayFirst(set: SetState, get: GetState, fresh: Track[]): void {
|
||||
if (fresh.length === 0) return;
|
||||
// Pin the server *before* reading state so the appended refs (and the
|
||||
// resolver seed) carry the canonical server key — otherwise queue rows for
|
||||
// the appended tracks render as the resolver placeholder. See PR #892.
|
||||
const serverId = ensureQueueServerPinned();
|
||||
const state = get();
|
||||
const serverId = state.queueServerId ?? '';
|
||||
if (serverId) seedQueueResolver(serverId, fresh);
|
||||
const incoming: QueueItemRef[] = toQueueItemRefs(serverId, fresh);
|
||||
const playAt = state.queueItems.length;
|
||||
@@ -93,8 +97,12 @@ export function runNext(set: SetState, get: GetState, manual: boolean): void {
|
||||
// an Orbit session between scheduling and resolving.
|
||||
if (isInOrbitSession()) return;
|
||||
if (newTracks.length > 0) {
|
||||
// Pin before set so the appended refs carry the canonical server
|
||||
// key; without this the auto-added rows render as '…' / 0:00
|
||||
// when the queue was populated without a queue-replacing playTrack
|
||||
// (see PR #892).
|
||||
const serverId = ensureQueueServerPinned();
|
||||
set(state => {
|
||||
const serverId = state.queueServerId ?? '';
|
||||
if (serverId) seedQueueResolver(serverId, newTracks);
|
||||
const newItems = [...state.queueItems, ...toQueueItemRefs(serverId, newTracks)];
|
||||
return { queueItems: newItems };
|
||||
@@ -146,8 +154,9 @@ export function runNext(set: SetState, get: GetState, manual: boolean): void {
|
||||
// Keep the last HISTORY_KEEP played tracks so the user can still
|
||||
// navigate backwards a few songs. Trimmed ids stay in the seen-set.
|
||||
const HISTORY_KEEP = 5;
|
||||
// Pin before set; same reasoning as the infinite top-up above.
|
||||
const serverId = ensureQueueServerPinned();
|
||||
set(state => {
|
||||
const serverId = state.queueServerId ?? '';
|
||||
if (serverId) seedQueueResolver(serverId, fresh);
|
||||
const trimStart = Math.max(0, state.queueIndex - HISTORY_KEEP);
|
||||
const newItems = [
|
||||
|
||||
Reference in New Issue
Block a user