Fix quality setting and device name display issues (#34)
- Clear both L1 memory and L2 disk caches when quality setting changes This ensures cached tracks at wrong quality are removed - Fix device name not showing in popup on first hover Now refreshes status on each hover instead of only when null - Add quality downgrade indicator when stream quality is lower than track's original quality (shows yellow arrow with tooltip) - Store original track quality values for comparison with actual stream
This commit is contained in:
1 parent
8b7e4dab27
commit
ae81b1c3c4
7 files changed
+78
-12
No files matched your search
Vendored
+8
-2
@@ -199,14 +199,20 @@ impl AudioCache {
|
||||
);
|
||||
}
|
||||
|
||||
/// Clear all cached data
|
||||
/// Clear all cached data (both L1 memory and L2 disk caches)
|
||||
pub fn clear(&self) {
|
||||
let mut state = self.state.lock().unwrap();
|
||||
state.tracks.clear();
|
||||
state.access_order.clear();
|
||||
state.current_size = 0;
|
||||
state.fetching.clear();
|
||||
log::info!("Cache cleared");
|
||||
log::info!("L1 memory cache cleared");
|
||||
|
||||
// Also clear L2 disk cache if present
|
||||
if let Some(ref playback_cache) = self.playback_cache {
|
||||
playback_cache.clear();
|
||||
log::info!("L2 playback cache cleared");
|
||||
}
|
||||
}
|
||||
|
||||
/// Get cache statistics
|
||||
|
||||
@@ -161,12 +161,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Update outputStatus when hovering to get fresh device name
|
||||
// Always refresh status when hovering to get fresh device name
|
||||
// The device name is only set when playback starts, so we need to re-fetch
|
||||
$effect(() => {
|
||||
if (isHovering && !outputStatus) {
|
||||
invoke<AudioOutputStatus>('get_audio_output_status')
|
||||
.then(status => outputStatus = status)
|
||||
.catch(() => {});
|
||||
if (isHovering) {
|
||||
loadStatus();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
qualityLevel: number;
|
||||
bitDepth?: number;
|
||||
samplingRate?: number;
|
||||
originalBitDepth?: number;
|
||||
originalSamplingRate?: number;
|
||||
format?: string;
|
||||
isPlaying: boolean;
|
||||
onTogglePlay: () => void;
|
||||
@@ -72,6 +74,8 @@
|
||||
qualityLevel,
|
||||
bitDepth,
|
||||
samplingRate,
|
||||
originalBitDepth,
|
||||
originalSamplingRate,
|
||||
format,
|
||||
isPlaying,
|
||||
onTogglePlay,
|
||||
@@ -257,7 +261,7 @@
|
||||
<h3 class="album">{album}</h3>
|
||||
</div>
|
||||
<div class="quality-info">
|
||||
<QualityBadge {quality} {bitDepth} samplingRate={displaySamplingRate} {format} />
|
||||
<QualityBadge {quality} {bitDepth} samplingRate={displaySamplingRate} {originalBitDepth} {originalSamplingRate} {format} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
qualityLevel?: number;
|
||||
bitDepth?: number;
|
||||
samplingRate?: number;
|
||||
originalBitDepth?: number;
|
||||
originalSamplingRate?: number;
|
||||
format?: string;
|
||||
isPlaying?: boolean;
|
||||
onTogglePlay?: () => void;
|
||||
@@ -76,6 +78,8 @@
|
||||
qualityLevel = 0,
|
||||
bitDepth,
|
||||
samplingRate,
|
||||
originalBitDepth,
|
||||
originalSamplingRate,
|
||||
format,
|
||||
isPlaying = false,
|
||||
onTogglePlay,
|
||||
@@ -320,7 +324,7 @@
|
||||
</div>
|
||||
|
||||
<div class="quality-indicator">
|
||||
<QualityBadge {quality} {bitDepth} {samplingRate} {format} />
|
||||
<QualityBadge {quality} {bitDepth} {samplingRate} {originalBitDepth} {originalSamplingRate} {format} />
|
||||
<div class="audio-badges-row">
|
||||
<AudioOutputBadges {samplingRate} />
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
quality?: string;
|
||||
bitDepth?: number;
|
||||
samplingRate?: number;
|
||||
originalBitDepth?: number;
|
||||
originalSamplingRate?: number;
|
||||
format?: string;
|
||||
compact?: boolean;
|
||||
}
|
||||
@@ -11,10 +13,27 @@
|
||||
quality = '',
|
||||
bitDepth,
|
||||
samplingRate,
|
||||
originalBitDepth,
|
||||
originalSamplingRate,
|
||||
format,
|
||||
compact = false
|
||||
}: Props = $props();
|
||||
|
||||
// Check if quality was downgraded due to settings
|
||||
const isDowngraded = $derived.by(() => {
|
||||
// Need both original and current values to compare
|
||||
if (!originalSamplingRate || !samplingRate) return false;
|
||||
// Significant difference (more than 10% lower)
|
||||
return samplingRate < originalSamplingRate * 0.9;
|
||||
});
|
||||
|
||||
// Format original quality for tooltip
|
||||
const originalQualityText = $derived.by(() => {
|
||||
if (!isDowngraded || !originalSamplingRate) return '';
|
||||
const depth = originalBitDepth || 24;
|
||||
return `${depth}-bit / ${originalSamplingRate} kHz`;
|
||||
});
|
||||
|
||||
// Determine quality tier
|
||||
const tier = $derived.by(() => {
|
||||
const fmt = (format || quality || '').toLowerCase();
|
||||
@@ -116,7 +135,11 @@
|
||||
{compactText}
|
||||
</span>
|
||||
{:else}
|
||||
<div class="quality-badge" title="{tierLabel}: {displayText}">
|
||||
<div
|
||||
class="quality-badge"
|
||||
class:downgraded={isDowngraded}
|
||||
title={isDowngraded ? `Playing at ${displayText} (original: ${originalQualityText})` : `${tierLabel}: ${displayText}`}
|
||||
>
|
||||
<!-- Icon -->
|
||||
<img
|
||||
src={iconPath}
|
||||
@@ -127,7 +150,12 @@
|
||||
|
||||
<!-- Text -->
|
||||
<div class="badge-text">
|
||||
<span class="tier-label">{tierLabel}</span>
|
||||
<span class="tier-label">
|
||||
{tierLabel}
|
||||
{#if isDowngraded}
|
||||
<span class="downgrade-indicator">↓</span>
|
||||
{/if}
|
||||
</span>
|
||||
<span class="quality-info">{displayText}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -210,4 +238,15 @@
|
||||
font-weight: 100;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
/* Downgrade indicator styles */
|
||||
.quality-badge.downgraded {
|
||||
border-color: rgba(234, 179, 8, 0.3);
|
||||
}
|
||||
|
||||
.downgrade-indicator {
|
||||
color: #eab308;
|
||||
font-weight: 600;
|
||||
margin-left: 2px;
|
||||
}
|
||||
</style>
|
||||
@@ -51,6 +51,9 @@ export interface PlayingTrack {
|
||||
artistId?: number;
|
||||
// ISRC for MusicBrainz/ListenBrainz enrichment
|
||||
isrc?: string;
|
||||
// Original track quality from metadata (for comparison with actual stream)
|
||||
originalBitDepth?: number;
|
||||
originalSamplingRate?: number;
|
||||
}
|
||||
|
||||
interface BackendPlaybackState {
|
||||
@@ -192,14 +195,21 @@ export function getPlayerState(): PlayerState {
|
||||
|
||||
/**
|
||||
* Set the current track (called when starting playback)
|
||||
* Preserves original quality values for comparison with actual stream
|
||||
*/
|
||||
export function setCurrentTrack(track: PlayingTrack | null): void {
|
||||
currentTrack = track;
|
||||
if (track) {
|
||||
// Store original quality values before they might be overwritten by stream events
|
||||
currentTrack = {
|
||||
...track,
|
||||
originalBitDepth: track.bitDepth,
|
||||
originalSamplingRate: track.samplingRate
|
||||
};
|
||||
duration = track.duration;
|
||||
currentTime = 0;
|
||||
queueEnded = false;
|
||||
} else {
|
||||
currentTrack = null;
|
||||
duration = 0;
|
||||
currentTime = 0;
|
||||
}
|
||||
|
||||
@@ -2993,6 +2993,8 @@
|
||||
quality={currentTrack.quality}
|
||||
bitDepth={currentTrack.bitDepth}
|
||||
samplingRate={currentTrack.samplingRate}
|
||||
originalBitDepth={currentTrack.originalBitDepth}
|
||||
originalSamplingRate={currentTrack.originalSamplingRate}
|
||||
format={currentTrack.format}
|
||||
{isPlaying}
|
||||
onTogglePlay={togglePlay}
|
||||
@@ -3078,6 +3080,8 @@
|
||||
qualityLevel={currentTrack.quality.includes('24') ? 5 : 3}
|
||||
bitDepth={currentTrack.bitDepth}
|
||||
samplingRate={currentTrack.samplingRate}
|
||||
originalBitDepth={currentTrack.originalBitDepth}
|
||||
originalSamplingRate={currentTrack.originalSamplingRate}
|
||||
format={currentTrack.format}
|
||||
{isPlaying}
|
||||
onTogglePlay={togglePlay}
|
||||
|
||||
Reference in new issue
Block a user