music: per-device now-playing (browser vs phone)

Key music_now_playing on (user_id, device) instead of user_id alone so the
browser ('web') and phone ('' default) each keep their own resume snapshot
instead of sharing one row. Sidecar /now-playing threads device (?device=,
default '') through get/set/clearNowPlaying; the web client tags its calls
?device=web. Phone unchanged → '' bucket, inherits the existing row.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 03:13:16 +00:00
co-authored by Claude Opus 4.8
parent 91ed03d514
commit f3dc4415bb
4 changed files with 47 additions and 36 deletions
@@ -76,7 +76,7 @@ export const MusicPlayerHost = () => {
const persist = () => {
if (!current) return;
put('/music/now-playing', {
put('/music/now-playing?device=web', {
homePath: trackHomePath(current.albumRel, current.file),
dir: `Music/${current.albumRel}`,
title: current.title ?? '',
@@ -126,7 +126,7 @@ export const MusicPlayerHost = () => {
restoredRef.current = true;
if (queue.length) return;
(async () => {
const snap = await get<NowPlaying | null>('/music/now-playing').catch(() => null);
const snap = await get<NowPlaying | null>('/music/now-playing?device=web').catch(() => null);
if (!snap?.homePath) return;
const albumRel = (snap.dir || snap.homePath.split('/').slice(0, -1).join('/')).replace(/^Music\//, '');
const file = snap.homePath.split('/').pop() ?? '';
@@ -236,7 +236,7 @@ export const MusicPlayerHost = () => {
// Closing the dock also clears the saved "currently playing" snapshot, so it doesn't get restored on
// the next load. (Merely close()-ing the local queue would leave the server snapshot to bring it back.)
const handleClose = () => {
del('/music/now-playing').catch(() => {});
del('/music/now-playing?device=web').catch(() => {});
close();
};