refactor(web): playlistTrackToRef helper to dedupe TrackRef
reconstruction (#375) PlaylistTrackRow.svelte and PlaylistCard.toTrackRefs both rebuilt TrackRef from PlaylistTrack with the same field-by-field literal. Server adding a new TrackRef field would have needed both sites updated; now one helper owns the mapping. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
import type { Playlist, PlaylistTrack, TrackRef } from '$lib/api/types';
|
import type { Playlist, PlaylistTrack, TrackRef } from '$lib/api/types';
|
||||||
import { user } from '$lib/auth/store.svelte';
|
import { user } from '$lib/auth/store.svelte';
|
||||||
import { getPlaylist, refreshDiscover, refreshForYou } from '$lib/api/playlists';
|
import { getPlaylist, refreshDiscover, refreshForYou } from '$lib/api/playlists';
|
||||||
|
import { playlistTrackToRef } from '$lib/playlists/playlistTrackToRef';
|
||||||
import { errCode } from '$lib/api/errors';
|
import { errCode } from '$lib/api/errors';
|
||||||
import { qk } from '$lib/api/queries';
|
import { qk } from '$lib/api/queries';
|
||||||
import { playQueue } from '$lib/player/store.svelte';
|
import { playQueue } from '$lib/player/store.svelte';
|
||||||
@@ -25,25 +26,12 @@
|
|||||||
menuOpen = !menuOpen;
|
menuOpen = !menuOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map PlaylistTrack rows to TrackRef shape and drop tracks whose upstream
|
// Map PlaylistTrack rows to TrackRef shape and drop tracks whose
|
||||||
// file has been removed (track_id is null). Mirrors PlaylistTrackRow's
|
// upstream file has been removed (track_id null).
|
||||||
// liveTrack derivation.
|
|
||||||
function toTrackRefs(rows: PlaylistTrack[]): TrackRef[] {
|
function toTrackRefs(rows: PlaylistTrack[]): TrackRef[] {
|
||||||
const out: TrackRef[] = [];
|
return rows
|
||||||
for (const r of rows) {
|
.map((r) => playlistTrackToRef(r))
|
||||||
if (!r.track_id) continue;
|
.filter((t): t is TrackRef => t !== null);
|
||||||
out.push({
|
|
||||||
id: r.track_id,
|
|
||||||
title: r.title,
|
|
||||||
album_id: r.album_id ?? '',
|
|
||||||
album_title: r.album_title,
|
|
||||||
artist_id: r.artist_id ?? '',
|
|
||||||
artist_name: r.artist_name,
|
|
||||||
duration_sec: r.duration_sec,
|
|
||||||
stream_url: r.stream_url ?? ''
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onPlayClick(e: MouseEvent) {
|
async function onPlayClick(e: MouseEvent) {
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
import { draggable, type DragEventData } from '@neodrag/svelte';
|
import { draggable, type DragEventData } from '@neodrag/svelte';
|
||||||
import LikeButton from './LikeButton.svelte';
|
import LikeButton from './LikeButton.svelte';
|
||||||
import TrackMenu from './TrackMenu.svelte';
|
import TrackMenu from './TrackMenu.svelte';
|
||||||
import type { PlaylistTrack, TrackRef } from '$lib/api/types';
|
import type { PlaylistTrack } from '$lib/api/types';
|
||||||
|
import { playlistTrackToRef } from '$lib/playlists/playlistTrackToRef';
|
||||||
import { offsetToDelta } from './queue-row-math';
|
import { offsetToDelta } from './queue-row-math';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
@@ -22,22 +23,9 @@
|
|||||||
|
|
||||||
const isUnavailable = $derived(row.track_id === null);
|
const isUnavailable = $derived(row.track_id === null);
|
||||||
|
|
||||||
// Construct a minimal TrackRef for the kebab menu when the upstream
|
// Reconstruct a minimal TrackRef for the kebab menu when the
|
||||||
// track still exists. When unavailable, the menu is hidden.
|
// upstream track still exists. When unavailable, the menu is hidden.
|
||||||
const liveTrack = $derived<TrackRef | null>(
|
const liveTrack = $derived(playlistTrackToRef(row));
|
||||||
row.track_id
|
|
||||||
? ({
|
|
||||||
id: row.track_id,
|
|
||||||
title: row.title,
|
|
||||||
album_id: row.album_id ?? '',
|
|
||||||
album_title: row.album_title,
|
|
||||||
artist_id: row.artist_id ?? '',
|
|
||||||
artist_name: row.artist_name,
|
|
||||||
duration_sec: row.duration_sec,
|
|
||||||
stream_url: row.stream_url ?? ''
|
|
||||||
} as TrackRef)
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
|
|
||||||
let measuredRowHeight = 56; // sensible default; replaced on dragStart
|
let measuredRowHeight = 56; // sensible default; replaced on dragStart
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Converts a PlaylistTrack row into the minimal TrackRef shape used
|
||||||
|
// by play queues + track menus. Centralizes the mapping so server
|
||||||
|
// additions (new TrackRef fields) only update one site.
|
||||||
|
//
|
||||||
|
// Returns null when the upstream track has been removed (track_id
|
||||||
|
// is null on the playlist row); callers should filter nulls.
|
||||||
|
|
||||||
|
import type { PlaylistTrack, TrackRef } from '$lib/api/types';
|
||||||
|
|
||||||
|
export function playlistTrackToRef(row: PlaylistTrack): TrackRef | null {
|
||||||
|
if (!row.track_id) return null;
|
||||||
|
return {
|
||||||
|
id: row.track_id,
|
||||||
|
title: row.title,
|
||||||
|
album_id: row.album_id ?? '',
|
||||||
|
album_title: row.album_title,
|
||||||
|
artist_id: row.artist_id ?? '',
|
||||||
|
artist_name: row.artist_name,
|
||||||
|
duration_sec: row.duration_sec,
|
||||||
|
stream_url: row.stream_url ?? ''
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user