fix(playback): pin queue playback to source server when browsing another library (#717)

* fix(playback): pin queue streams, cover art, and library links to queue server

When the active server changes while a queue from another server is playing,
keep streams and UI on queueServerId; switch back for artist/album links and
queue or player-bar context menus.

* fix(playback): switch to queue server when opening Now Playing

Ensure active server matches queueServerId before Subsonic fetches on the
Now Playing page, mobile player route, and queue info panel; scope caches
by server id.

* docs(credits): mention Now Playing in PR #717 contribution line

* fix(playback): route scrobble and queue sync to queue server

Address PR review: apiForServer for scrobble/now-playing/savePlayQueue,
clear queueServerId on server removal, mini-player queueServerId sync,
block cross-server enqueue with toast, and regression tests.
This commit is contained in:
cucadmuh
2026-05-15 16:08:41 +03:00
committed by GitHub
parent a9b50b9244
commit 45e0e1206f
58 changed files with 701 additions and 178 deletions
+18 -1
View File
@@ -15,6 +15,8 @@ import {
} from '../utils/componentHelpers/contextMenuActions';
import { useContextMenuKeyboardNav } from '../hooks/useContextMenuKeyboardNav';
import { useContextMenuRating } from '../hooks/useContextMenuRating';
import { usePlaybackLibraryNavigate } from '../hooks/usePlaybackLibraryNavigate';
import { useNavigate } from 'react-router-dom';
import ContextMenuItems from './contextMenu/ContextMenuItems';
export { AddToPlaylistSubmenu };
@@ -22,6 +24,8 @@ export { AddToPlaylistSubmenu };
export default function ContextMenu() {
const { t } = useTranslation();
const navigate = useNavigate();
const navigatePlaybackLibrary = usePlaybackLibraryNavigate();
const orbitRole = useOrbitStore(s => s.role);
const { contextMenu, closeContextMenu, playTrack, enqueue, playNext, queue, currentTrack, removeTrack, lastfmLovedCache, setLastfmLovedForSong, starredOverrides, setStarredOverride, openSongInfo, userRatingOverrides, setUserRatingOverride } = usePlayerStore(
useShallow(s => ({
@@ -125,7 +129,18 @@ export default function ContextMenu() {
}, [contextMenu.isOpen, closeContextMenu, cancelPlaylistSubmenuCloseTimer]);
const { type, item, queueIndex, playlistId, playlistSongIndex, shareKindOverride } = contextMenu;
const {
type,
item,
queueIndex,
playlistId,
playlistSongIndex,
shareKindOverride,
pinToPlaybackServer = false,
} = contextMenu;
const navigateLibrary = pinToPlaybackServer
? navigatePlaybackLibrary
: (path: string) => { navigate(path); };
const isStarred = (id: string, itemStarred?: string) =>
id in starredOverrides ? starredOverrides[id] : !!itemStarred;
@@ -216,6 +231,8 @@ export default function ContextMenu() {
downloadAlbum={downloadAlbum}
copyShareLink={copyShareLink}
isStarred={isStarred}
pinToPlaybackServer={pinToPlaybackServer}
navigateLibrary={navigateLibrary}
/>
</div>
</>