Fix session restore and audio badges visibility

Session restore:
- Add pendingSessionRestore state to playerStore
- When restored track is played, load from Qobuz first
- Seek to saved position after track loads

Audio badges:
- Always show DAC/EXC badges (very muted when off)
- Adjust margins and sizing for better alignment
This commit is contained in:
vicrodh committed 2026-01-11 11:19:34 -06:00
1 parent 3fd3d25bdc
commit dd758d3523
3 files changed
+93 -56

No files matched your search

+41 -50
View File
@@ -67,79 +67,70 @@
});
</script>
{#if shouldShowBadges}
<div
class="audio-badges"
onmouseenter={() => isHovering = true}
onmouseleave={() => isHovering = false}
>
<!-- DAC Badge -->
<div
class="audio-badges"
onmouseenter={() => isHovering = true}
onmouseleave={() => isHovering = false}
class="badge"
class:active={dacPassthroughActive}
title={showTooltips ? (dacPassthroughActive ? 'DAC Passthrough active' : 'DAC Passthrough inactive') : undefined}
>
<!-- DAC Badge -->
<div
class="badge"
class:active={dacPassthroughActive}
class:external={isExternal}
title={showTooltips ? (dacPassthroughActive ? 'DAC Passthrough active' : 'DAC Passthrough inactive') : undefined}
>
<span class="badge-label">DAC</span>
</div>
<!-- Exclusive Mode Badge -->
<div
class="badge"
class:active={exclusiveModeActive}
title={showTooltips ? (exclusiveModeActive ? 'Exclusive Mode active' : 'Exclusive Mode inactive') : undefined}
>
<span class="badge-label">EXC</span>
</div>
<!-- Device Tooltip on hover -->
{#if isHovering && showTooltips}
<div class="device-tooltip">
<div class="tooltip-label">Output Device</div>
<div class="tooltip-device">{prettyDeviceName}</div>
{#if currentDevice && currentDevice !== prettyDeviceName}
<div class="tooltip-raw">{currentDevice}</div>
{/if}
</div>
{/if}
<span class="badge-label">DAC</span>
</div>
{/if}
<!-- Exclusive Mode Badge -->
<div
class="badge"
class:active={exclusiveModeActive}
title={showTooltips ? (exclusiveModeActive ? 'Exclusive Mode active' : 'Exclusive Mode inactive') : undefined}
>
<span class="badge-label">EXC</span>
</div>
<!-- Device Tooltip on hover -->
{#if isHovering && showTooltips}
<div class="device-tooltip">
<div class="tooltip-label">Output Device</div>
<div class="tooltip-device">{prettyDeviceName}</div>
{#if currentDevice && currentDevice !== prettyDeviceName}
<div class="tooltip-raw">{currentDevice}</div>
{/if}
</div>
{/if}
</div>
<style>
.audio-badges {
display: flex;
align-items: center;
gap: 4px;
gap: 3px;
position: relative;
margin-left: 8px;
margin-left: 4px;
}
.badge {
display: flex;
align-items: center;
justify-content: center;
padding: 2px 6px;
padding: 2px 5px;
border-radius: 3px;
font-size: 8px;
font-size: 7px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
background: rgba(255, 255, 255, 0.05);
color: rgba(255, 255, 255, 0.25);
border: 1px solid rgba(255, 255, 255, 0.08);
letter-spacing: 0.3px;
background: transparent;
color: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(255, 255, 255, 0.06);
transition: all 200ms ease;
}
.badge.active {
background: rgba(34, 197, 94, 0.15);
background: rgba(34, 197, 94, 0.2);
color: #22c55e;
border-color: rgba(34, 197, 94, 0.3);
}
.badge.external:not(.active) {
background: rgba(99, 102, 241, 0.1);
color: rgba(99, 102, 241, 0.5);
border-color: rgba(99, 102, 241, 0.2);
border-color: rgba(34, 197, 94, 0.4);
}
.badge-label {
+48 -1
View File
@@ -61,6 +61,9 @@ let queueEnded = false;
// Callbacks for track advancement (set by consumer)
let onTrackEnded: (() => Promise<void>) | null = null;
// Session restore state - when set, next play will load the track first
let pendingSessionRestore: { trackId: number; position: number } | null = null;
// Listeners
const listeners = new Set<() => void>();
@@ -176,6 +179,28 @@ export function setQueueEnded(ended: boolean): void {
// ============ Playback Controls ============
/**
* Set pending session restore - will load track on next play
*/
export function setPendingSessionRestore(trackId: number, position: number): void {
pendingSessionRestore = { trackId, position };
console.log('[Player] Set pending session restore:', { trackId, position });
}
/**
* Clear pending session restore
*/
export function clearPendingSessionRestore(): void {
pendingSessionRestore = null;
}
/**
* Check if there's a pending session restore
*/
export function hasPendingSessionRestore(): boolean {
return pendingSessionRestore !== null;
}
/**
* Toggle play/pause
*/
@@ -188,7 +213,29 @@ export async function togglePlay(): Promise<void> {
try {
if (newIsPlaying) {
await invoke('resume_playback');
// Check if we need to load the track first (session restore)
if (pendingSessionRestore && pendingSessionRestore.trackId === currentTrack.id) {
console.log('[Player] Loading restored track:', pendingSessionRestore.trackId);
const savedPosition = pendingSessionRestore.position;
pendingSessionRestore = null; // Clear before loading
// Load the track from Qobuz
await invoke('play_track', { trackId: currentTrack.id });
// Seek to saved position after a short delay to let audio load
if (savedPosition > 0) {
setTimeout(async () => {
try {
await invoke('seek', { position: savedPosition });
console.log('[Player] Seeked to restored position:', savedPosition);
} catch (seekErr) {
console.error('[Player] Failed to seek to restored position:', seekErr);
}
}, 500);
}
} else {
await invoke('resume_playback');
}
} else {
await invoke('pause_playback');
}
+4 -5
View File
@@ -80,6 +80,7 @@
togglePlay,
seek as playerSeek,
setVolume as playerSetVolume,
setPendingSessionRestore,
startPolling,
stopPolling,
reset as resetPlayer,
@@ -851,11 +852,9 @@
quality: 'Restored',
});
// Seek to saved position if > 0
if (session.current_position_secs > 0) {
// Note: actual seek will happen when user presses play
console.log(`[Session] Will resume at ${session.current_position_secs}s`);
}
// Mark that this track needs to be loaded when user presses play
setPendingSessionRestore(track.id, session.current_position_secs);
console.log(`[Session] Track ${track.id} pending load, will resume at ${session.current_position_secs}s`);
}
console.log('[Session] Session restored successfully');