fix(qconnect): unify queue replacement through shared helper
cx
This commit is contained in:
15 files changed
+255
-35
No files matched your search
@@ -19,6 +19,7 @@
|
||||
import TrackMenu from '../TrackMenu.svelte';
|
||||
import BulkActionBar from '../BulkActionBar.svelte';
|
||||
import QualityBadge from '../QualityBadge.svelte';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { consumeContextTrackFocus, setPlaybackContext, getPlaybackContext } from '$lib/stores/playbackContextStore';
|
||||
import { saveScrollPosition, getSavedScrollPosition } from '$lib/stores/navigationStore';
|
||||
import { togglePlay } from '$lib/stores/playerStore';
|
||||
@@ -1185,7 +1186,9 @@
|
||||
console.log(`[Artist] Context created: "${artist.name}" top tracks, ${trackIds.length} tracks, starting at ${index}`);
|
||||
try {
|
||||
const queueTracks = buildTopTracksQueue(topTracks);
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: index });
|
||||
await replacePlaybackQueue(queueTracks, index, {
|
||||
debugLabel: 'artist-detail:top-tracks'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to set queue:', err);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import { formatDuration, getQobuzImage } from '$lib/adapters/qobuzAdapters';
|
||||
import { getDynamicSuggest } from '$lib/services/dynamicSuggest';
|
||||
import { getHomeSeeds, getHomeSeedsML } from '$lib/services/recoService';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { showToast } from '$lib/stores/toastStore';
|
||||
import { setPlaybackContext } from '$lib/stores/playbackContextStore';
|
||||
import { isBlacklisted as isArtistBlacklisted } from '$lib/stores/artistBlacklistStore';
|
||||
@@ -362,7 +363,9 @@
|
||||
);
|
||||
|
||||
try {
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: queueIndex });
|
||||
await replacePlaybackQueue(queueTracks, queueIndex, {
|
||||
debugLabel: 'dynamic-suggest'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to set queue:', err);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import BulkActionBar from '$lib/components/BulkActionBar.svelte';
|
||||
import { t } from '$lib/i18n';
|
||||
import { formatDuration, getQobuzImage } from '$lib/adapters/qobuzAdapters';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { showToast } from '$lib/stores/toastStore';
|
||||
import { setPlaybackContext } from '$lib/stores/playbackContextStore';
|
||||
import { isBlacklisted as isArtistBlacklisted } from '$lib/stores/artistBlacklistStore';
|
||||
@@ -304,7 +305,9 @@
|
||||
}
|
||||
|
||||
try {
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: queueIndex });
|
||||
await replacePlaybackQueue(queueTracks, queueIndex, {
|
||||
debugLabel: 'fav-q'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to set queue:', err);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
import { syncCache as syncAlbumCache } from '$lib/stores/albumFavoritesStore';
|
||||
import { syncCache as syncArtistCache } from '$lib/stores/artistFavoritesStore';
|
||||
import { categorizeAlbum, getQobuzImage, formatQuality } from '$lib/adapters/qobuzAdapters';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { getUserItem, setUserItem } from '$lib/utils/userStorage';
|
||||
import GenreFilterButton from '../GenreFilterButton.svelte';
|
||||
import {
|
||||
@@ -1179,7 +1180,9 @@
|
||||
async function setFavoritesQueue(startIndex: number) {
|
||||
if (filteredTracks.length === 0) return;
|
||||
const queueTracks = buildFavoritesQueueTracks(filteredTracks);
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex });
|
||||
await replacePlaybackQueue(queueTracks, startIndex, {
|
||||
debugLabel: 'favorites:tracks'
|
||||
});
|
||||
}
|
||||
|
||||
async function handleTrackClick(track: FavoriteTrack, index: number) {
|
||||
@@ -1216,7 +1219,9 @@
|
||||
// Shuffle the tracks
|
||||
const shuffled = [...filteredTracks].sort(() => Math.random() - 0.5);
|
||||
const queueTracks = buildFavoritesQueueTracks(shuffled);
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: 0 });
|
||||
await replacePlaybackQueue(queueTracks, 0, {
|
||||
debugLabel: 'favorites:shuffle'
|
||||
});
|
||||
await setFavoritesContext(shuffled.map(trk => trk.id), 0);
|
||||
onTrackPlay(buildDisplayTrack(shuffled[0], 0));
|
||||
} catch (err) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import AlbumCard from '../AlbumCard.svelte';
|
||||
import TrackRow from '../TrackRow.svelte';
|
||||
import { formatQuality, getQobuzImageForSize } from '$lib/adapters/qobuzAdapters';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { playTrack } from '$lib/services/playbackService';
|
||||
import { playQueueIndex } from '$lib/stores/queueStore';
|
||||
import { resolveArtistImage } from '$lib/stores/customArtistImageStore';
|
||||
@@ -629,7 +630,9 @@
|
||||
album_id: track.album?.id || null,
|
||||
artist_id: track.artist?.id || spotlightData!.artistId,
|
||||
}));
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: 0 });
|
||||
await replacePlaybackQueue(queueTracks, 0, {
|
||||
debugLabel: 'for-you:spotlight-top-tracks'
|
||||
});
|
||||
await startRadioPlayback();
|
||||
} catch (err) {
|
||||
console.error('Failed to play spotlight top tracks:', err);
|
||||
@@ -769,7 +772,13 @@
|
||||
|
||||
try {
|
||||
const queueTracks = buildContinueQueueTracks(continueTracks);
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: trackIndex });
|
||||
const localTrackIds = continueTracks
|
||||
.filter((trk) => trk.isLocal)
|
||||
.map((trk) => trk.id);
|
||||
await replacePlaybackQueue(queueTracks, trackIndex, {
|
||||
localTrackIds,
|
||||
debugLabel: 'for-you:continue-listening'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to set queue:', err);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
hasActiveFilter as hasGenreFilter
|
||||
} from '$lib/stores/genreFilterStore';
|
||||
import { setPlaybackContext } from '$lib/stores/playbackContextStore';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import {
|
||||
getCachedArtist,
|
||||
setCachedArtist,
|
||||
@@ -666,7 +667,13 @@
|
||||
if (continueTracks.length > 0) {
|
||||
try {
|
||||
const queueTracks = buildContinueQueueTracks(continueTracks);
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: trackIndex });
|
||||
const localTrackIds = continueTracks
|
||||
.filter((track) => track.isLocal)
|
||||
.map((track) => track.id);
|
||||
await replacePlaybackQueue(queueTracks, trackIndex, {
|
||||
localTrackIds,
|
||||
debugLabel: 'home:continue-listening'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to set queue:', err);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import QobuzPlaylistCard from '../QobuzPlaylistCard.svelte';
|
||||
import TrackMenu from '../TrackMenu.svelte';
|
||||
import QualityBadge from '../QualityBadge.svelte';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { setPlaybackContext } from '$lib/stores/playbackContextStore';
|
||||
import { togglePlay } from '$lib/stores/playerStore';
|
||||
import {
|
||||
@@ -459,7 +460,9 @@
|
||||
console.log(`[LabelView] Context set: "${pageData?.name}" top tracks, ${trackIds.length} tracks, index ${index}`);
|
||||
|
||||
const queueTracks = buildTopTracksQueue(topTracks);
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: index });
|
||||
await replacePlaybackQueue(queueTracks, index, {
|
||||
debugLabel: 'label-view:top-tracks'
|
||||
});
|
||||
console.log('[LabelView] Queue set successfully');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
import {
|
||||
setPlaybackContext
|
||||
} from '$lib/stores/playbackContextStore';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
|
||||
// Backend types matching Rust models
|
||||
interface LocalTrack {
|
||||
@@ -2182,8 +2183,10 @@
|
||||
console.log('[LocalLibrary Queue] Mapped to', queueTracks.length, 'queue tracks');
|
||||
console.log('[LocalLibrary Queue] Track IDs:', queueTracks.map(track => track.id));
|
||||
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex });
|
||||
onSetLocalQueue?.(tracks.filter(track => track.source !== 'plex').map(track => track.id));
|
||||
await replacePlaybackQueue(queueTracks, startIndex, {
|
||||
localTrackIds: tracks.filter(track => track.source !== 'plex').map(track => track.id),
|
||||
debugLabel: 'local-library:set-queue'
|
||||
});
|
||||
|
||||
console.log('[LocalLibrary Queue] Queue set successfully');
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
import { t } from '$lib/i18n';
|
||||
import { onMount, tick } from 'svelte';
|
||||
import { getUserItem, setUserItem } from '$lib/utils/userStorage';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
|
||||
interface PlaylistTrack {
|
||||
id: number;
|
||||
@@ -1556,10 +1557,10 @@
|
||||
const allTracks = displayTracks;
|
||||
if (allTracks.length === 0) return;
|
||||
const { queueTracks, localIds } = buildQueueTracks(allTracks);
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex });
|
||||
if (localIds.length > 0) {
|
||||
onSetLocalQueue?.(localIds);
|
||||
}
|
||||
await replacePlaybackQueue(queueTracks, startIndex, {
|
||||
localTrackIds: localIds,
|
||||
debugLabel: 'playlist-detail:set-queue'
|
||||
});
|
||||
}
|
||||
|
||||
async function handleTrackClick(track: DisplayTrack, trackIndex: number) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import ViewTransition from '../ViewTransition.svelte';
|
||||
import TrackMenu from '../TrackMenu.svelte';
|
||||
import QualityBadge from '../QualityBadge.svelte';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { getSearchState, setSearchState, subscribeSearchFocus, subscribeSearchQuery, setSearchQuery, type SearchResults, type SearchAllResults, type SearchTab, type SearchFilterType, type Playlist } from '$lib/stores/searchState';
|
||||
import { setPlaybackContext } from '$lib/stores/playbackContextStore';
|
||||
import { togglePlay } from '$lib/stores/playerStore';
|
||||
@@ -731,7 +732,9 @@
|
||||
if (trackResults && trackResults.items.length > 0) {
|
||||
try {
|
||||
const queueTracks = buildSearchQueueTracks(trackResults.items);
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: trackIndex });
|
||||
await replacePlaybackQueue(queueTracks, trackIndex, {
|
||||
debugLabel: 'search:results'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to set queue:', err);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { t } from '$lib/i18n';
|
||||
import { formatDuration, getQobuzImage } from '$lib/adapters/qobuzAdapters';
|
||||
import { getDynamicSuggest } from '$lib/services/dynamicSuggest';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { showToast } from '$lib/stores/toastStore';
|
||||
import { setPlaybackContext } from '$lib/stores/playbackContextStore';
|
||||
import { isBlacklisted as isArtistBlacklisted } from '$lib/stores/artistBlacklistStore';
|
||||
@@ -417,7 +418,9 @@
|
||||
}
|
||||
|
||||
try {
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: queueIndex });
|
||||
await replacePlaybackQueue(queueTracks, queueIndex, {
|
||||
debugLabel: 'top-q'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to set queue:', err);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import { formatDuration, getQobuzImage } from '$lib/adapters/qobuzAdapters';
|
||||
import { getDynamicSuggest } from '$lib/services/dynamicSuggest';
|
||||
import { getHomeSeeds, getHomeSeedsML } from '$lib/services/recoService';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import { showToast } from '$lib/stores/toastStore';
|
||||
import { setPlaybackContext } from '$lib/stores/playbackContextStore';
|
||||
import { isBlacklisted as isArtistBlacklisted } from '$lib/stores/artistBlacklistStore';
|
||||
@@ -360,7 +361,9 @@
|
||||
);
|
||||
|
||||
try {
|
||||
await invoke('v2_set_queue', { tracks: queueTracks, startIndex: queueIndex });
|
||||
await replacePlaybackQueue(queueTracks, queueIndex, {
|
||||
debugLabel: 'weekly-q'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to set queue:', err);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
assessQconnectQueueSync
|
||||
} from './queuePlaybackService';
|
||||
import type { BackendQueueTrack } from '$lib/stores/queueStore';
|
||||
|
||||
function buildTrack(id: number, overrides: Partial<BackendQueueTrack> = {}): BackendQueueTrack {
|
||||
return {
|
||||
id,
|
||||
title: `Track ${id}`,
|
||||
artist: 'Artist',
|
||||
album: 'Album',
|
||||
duration_secs: 180,
|
||||
artwork_url: null,
|
||||
hires: false,
|
||||
bit_depth: null,
|
||||
sample_rate: null,
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
|
||||
describe('assessQconnectQueueSync', () => {
|
||||
it('accepts a pure Qobuz queue', () => {
|
||||
expect(assessQconnectQueueSync([
|
||||
buildTrack(101),
|
||||
buildTrack(102),
|
||||
buildTrack(103)
|
||||
])).toEqual({
|
||||
syncable: true,
|
||||
reason: 'ok',
|
||||
trackIds: [101, 102, 103],
|
||||
blockedTrackIds: []
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects local tracks so remote queue is not desynced', () => {
|
||||
expect(assessQconnectQueueSync([
|
||||
buildTrack(101),
|
||||
buildTrack(9001, { is_local: true, source: 'local' })
|
||||
])).toEqual({
|
||||
syncable: false,
|
||||
reason: 'queue_contains_non_qobuz_tracks',
|
||||
trackIds: [],
|
||||
blockedTrackIds: [9001]
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects Plex tracks', () => {
|
||||
expect(assessQconnectQueueSync([
|
||||
buildTrack(7001, { source: 'plex', is_local: false })
|
||||
])).toEqual({
|
||||
syncable: false,
|
||||
reason: 'queue_contains_non_qobuz_tracks',
|
||||
trackIds: [],
|
||||
blockedTrackIds: [7001]
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects an empty queue', () => {
|
||||
expect(assessQconnectQueueSync([])).toEqual({
|
||||
syncable: false,
|
||||
reason: 'empty_queue',
|
||||
trackIds: [],
|
||||
blockedTrackIds: []
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,113 @@
|
||||
import {
|
||||
setLocalTrackIds,
|
||||
setQueue,
|
||||
type BackendQueueTrack
|
||||
} from '$lib/stores/queueStore';
|
||||
import { loadQconnectQueue } from '$lib/services/trackActions';
|
||||
|
||||
export type QconnectQueueSyncAssessment = {
|
||||
syncable: boolean;
|
||||
reason: 'ok' | 'empty_queue' | 'queue_contains_non_qobuz_tracks';
|
||||
trackIds: number[];
|
||||
blockedTrackIds: number[];
|
||||
};
|
||||
|
||||
export type ReplacePlaybackQueueOptions = {
|
||||
clearLocal?: boolean;
|
||||
localTrackIds?: number[];
|
||||
syncQconnect?: boolean;
|
||||
debugLabel?: string;
|
||||
};
|
||||
|
||||
function isQconnectSyncEligibleTrack(track: BackendQueueTrack): boolean {
|
||||
if (track.is_local) return false;
|
||||
|
||||
const source = (track.source ?? '').toLowerCase();
|
||||
if (source === 'local' || source === 'plex' || source === 'qobuz_download') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Number.isFinite(track.id) && track.id > 0;
|
||||
}
|
||||
|
||||
export function assessQconnectQueueSync(tracks: BackendQueueTrack[]): QconnectQueueSyncAssessment {
|
||||
if (tracks.length === 0) {
|
||||
return {
|
||||
syncable: false,
|
||||
reason: 'empty_queue',
|
||||
trackIds: [],
|
||||
blockedTrackIds: []
|
||||
};
|
||||
}
|
||||
|
||||
const trackIds: number[] = [];
|
||||
const blockedTrackIds: number[] = [];
|
||||
|
||||
for (const track of tracks) {
|
||||
if (isQconnectSyncEligibleTrack(track)) {
|
||||
trackIds.push(track.id);
|
||||
} else {
|
||||
blockedTrackIds.push(track.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (blockedTrackIds.length > 0) {
|
||||
return {
|
||||
syncable: false,
|
||||
reason: 'queue_contains_non_qobuz_tracks',
|
||||
trackIds: [],
|
||||
blockedTrackIds
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
syncable: true,
|
||||
reason: 'ok',
|
||||
trackIds,
|
||||
blockedTrackIds: []
|
||||
};
|
||||
}
|
||||
|
||||
export async function syncQconnectQueueFromTracks(
|
||||
tracks: BackendQueueTrack[],
|
||||
startIndex: number,
|
||||
debugLabel: string = 'queue-replace'
|
||||
): Promise<boolean> {
|
||||
const assessment = assessQconnectQueueSync(tracks);
|
||||
|
||||
if (!assessment.syncable) {
|
||||
console.log('[QConnect/QueueSync] skipped %s: reason=%s blockedTrackIds=%o', debugLabel, assessment.reason, assessment.blockedTrackIds);
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('[QConnect/QueueSync] syncing %s: trackCount=%d startIndex=%d', debugLabel, assessment.trackIds.length, startIndex);
|
||||
return loadQconnectQueue(assessment.trackIds, startIndex);
|
||||
}
|
||||
|
||||
export async function replacePlaybackQueue(
|
||||
tracks: BackendQueueTrack[],
|
||||
startIndex: number,
|
||||
options: ReplacePlaybackQueueOptions = {}
|
||||
): Promise<boolean> {
|
||||
const {
|
||||
clearLocal = true,
|
||||
localTrackIds = [],
|
||||
syncQconnect = true,
|
||||
debugLabel = 'queue-replace'
|
||||
} = options;
|
||||
|
||||
const success = await setQueue(tracks, startIndex, clearLocal);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (localTrackIds.length > 0) {
|
||||
setLocalTrackIds(localTrackIds);
|
||||
}
|
||||
|
||||
if (syncQconnect) {
|
||||
await syncQconnectQueueFromTracks(tracks, startIndex, debugLabel);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
+10
-17
@@ -301,6 +301,7 @@
|
||||
shareSonglinkTrack,
|
||||
loadQconnectQueue
|
||||
} from '$lib/services/trackActions';
|
||||
import { replacePlaybackQueue } from '$lib/services/queuePlaybackService';
|
||||
import type {
|
||||
QconnectDiagnosticsPayload,
|
||||
QconnectQueueSnapshot,
|
||||
@@ -1559,14 +1560,9 @@
|
||||
artist_id: trk.artistId ?? album.artistId
|
||||
}));
|
||||
|
||||
await setQueue(queueTracks, 0, true);
|
||||
|
||||
// Sync the full queue to QConnect remote so controllers see the album
|
||||
const trackIds = album.tracks.map(trk => trk.id);
|
||||
loadQconnectQueue(trackIds, 0).then(ok => {
|
||||
if (ok) console.log('[QConnect] Album queue synced to remote (%d tracks)', trackIds.length);
|
||||
else console.warn('[QConnect] Album queue NOT synced to remote (not connected or rejected)');
|
||||
}).catch(err => console.error('[QConnect] Album queue sync error:', err));
|
||||
await replacePlaybackQueue(queueTracks, 0, {
|
||||
debugLabel: 'page:play-album'
|
||||
});
|
||||
|
||||
const firstTrack = album.tracks[0];
|
||||
const quality = firstTrack.hires && firstTrack.bitDepth && firstTrack.samplingRate
|
||||
@@ -1784,14 +1780,9 @@
|
||||
artist_id: trk.performer?.id
|
||||
}));
|
||||
|
||||
await setQueue(queueTracks, 0);
|
||||
|
||||
// Sync the full queue to QConnect remote so controllers see the playlist
|
||||
const trackIds = tracks.map(trk => trk.id);
|
||||
loadQconnectQueue(trackIds, 0).then(ok => {
|
||||
if (ok) console.log('[QConnect] Playlist queue synced to remote (%d tracks)', trackIds.length);
|
||||
else console.warn('[QConnect] Playlist queue NOT synced to remote (not connected or rejected)');
|
||||
}).catch(err => console.error('[QConnect] Playlist queue sync error:', err));
|
||||
await replacePlaybackQueue(queueTracks, 0, {
|
||||
debugLabel: 'page:play-playlist'
|
||||
});
|
||||
|
||||
const firstTrack = tracks[0];
|
||||
const artwork = firstTrack.album?.image?.large || firstTrack.album?.image?.thumbnail || firstTrack.album?.image?.small || '';
|
||||
@@ -2013,7 +2004,9 @@
|
||||
console.log('[Album Queue] Track IDs:', queueTracks.map(trk => trk.id));
|
||||
|
||||
// Set the queue starting at the clicked track
|
||||
await setQueue(queueTracks, trackIndex >= 0 ? trackIndex : 0, true);
|
||||
await replacePlaybackQueue(queueTracks, trackIndex >= 0 ? trackIndex : 0, {
|
||||
debugLabel: 'page:album-track-play'
|
||||
});
|
||||
|
||||
console.log('[Album Queue] Queue set successfully');
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user