feat(track): icon-based status badges, detect locally-cached tracks
Replace the labelled availability/metadata badges in track rows with small icon+tooltip indicators (cloud/hard-drives/warning/etc, derived from TrackAvailability and MetadataStatus). Add a `connection` slice fed by a single status poller (Sidebar) so other components can cheaply check backend reachability. TrackRow uses this plus the offline audio cache to show "Local" instead of a stale "On server" when the backend is down but the track is already cached.
This commit is contained in:
@@ -7,6 +7,8 @@ import { Icon } from '../common/Icon';
|
||||
import { PlayingIndicator } from '../common/PlayingIndicator';
|
||||
import { formatDuration } from '../../lib/format';
|
||||
import { useAppDispatch, useAppSelector } from '../../hooks/useAppDispatch';
|
||||
import { useIsOffline } from '../../hooks/useConnectionStatus';
|
||||
import { useStreamCached } from '../../hooks/useStreamCached';
|
||||
import { playNow } from '../../store/slices/queue';
|
||||
import type { Track } from '../../api/types';
|
||||
import { getCoverUrl, getTrackCoverUrl } from '../../api/endpoints/streaming';
|
||||
@@ -45,6 +47,15 @@ export function TrackRow({
|
||||
getCoverUrl(track.albumArtUrl) ??
|
||||
(token ? getTrackCoverUrl(track.id, token, track.hasCover) : undefined);
|
||||
|
||||
// The backend reports `server`, but if it's unreachable and this track's
|
||||
// audio is already in the offline cache, show "Local" instead.
|
||||
const offline = useIsOffline();
|
||||
const cached = useStreamCached(offline ? track.id : undefined);
|
||||
const displayAvailability =
|
||||
track.availability === 'server' && offline && cached
|
||||
? 'local'
|
||||
: track.availability;
|
||||
|
||||
const handlePlayNow = () => {
|
||||
dispatch(
|
||||
playNow({
|
||||
@@ -161,8 +172,9 @@ export function TrackRow({
|
||||
<MetadataStatusBadge
|
||||
status={track.metadataStatus}
|
||||
error={track.metadataError}
|
||||
iconOnly
|
||||
/>
|
||||
<AvailabilityBadge availability={track.availability} />
|
||||
<AvailabilityBadge availability={displayAvailability} iconOnly />
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
<span
|
||||
|
||||
Reference in New Issue
Block a user