Design Prot Merge #1

Merged
NotS1mp merged 217 commits from design-prot into master 2026-09-21 15:48:16 +00:00
3 changed files with 33 additions and 8 deletions
Showing only changes of commit 4069b36202 - Show all commits
+5 -1
View File
@@ -45,6 +45,10 @@ export function queueIdForTrack(track: ApiTrackLike): string | number {
return isPendingYouTubeTrack(track) && track.externalId ? track.externalId : track.id;
}
export function youTubeThumbnailUrl(videoId: string): string {
return `https://i.ytimg.com/vi/${videoId}/mqdefault.jpg`;
}
export function toQueueItems(tracks: ApiTrackLike[]): QueueItem[] {
return tracks.map((track) => {
const pendingYouTube = isPendingYouTubeTrack(track);
@@ -53,7 +57,7 @@ export function toQueueItems(tracks: ApiTrackLike[]): QueueItem[] {
title: track.title,
artist: track.artist,
source: pendingYouTube ? 'youtube' : 'local',
coverUrl: pendingYouTube ? `/api/tracks/${track.id}/cover?size=small` : undefined
coverUrl: pendingYouTube && track.externalId ? youTubeThumbnailUrl(track.externalId) : undefined
};
});
}
@@ -16,7 +16,8 @@
player,
isPendingYouTubeTrack,
queueIdForTrack,
toQueueItems
toQueueItems,
youTubeThumbnailUrl
} from '$lib/player/player.svelte';
import { HUES, fmtTime } from '$lib/theme/color';
import Cover from '$lib/components/ui/Cover.svelte';
@@ -179,6 +180,7 @@
<button type="button" onclick={() => playFrom(i)} class="flex min-w-0 items-center gap-3.5 text-left">
<Cover
trackId={track.id}
src={isPendingYouTubeTrack(track) ? youTubeThumbnailUrl(track.externalId) : undefined}
hue={hueFor(track.id)}
size="small"
alt={track.title}
+25 -6
View File
@@ -11,19 +11,34 @@
const latest = $derived(data.latest);
const playlists = $derived(data.playlists);
const trackIds = $derived(data.trackIds);
interface RecentItem {
id: string;
title: string;
artist?: string;
source: 'local' | 'youtube';
coverUrl?: string;
}
const recentlyPlayed = $derived.by(() => {
const seen = new Set<string>();
const merged: { id: string; title: string }[] = [];
const merged: RecentItem[] = [];
for (const t of player.recentlyPlayed) {
const id = String(t.id);
if (seen.has(id)) continue;
seen.add(id);
merged.push({ id, title: t.title });
merged.push({ id, title: t.title, artist: t.artist, source: t.source, coverUrl: t.coverUrl });
}
for (const t of data.recentlyPlayed) {
if (seen.has(t.id)) continue;
seen.add(t.id);
merged.push({ id: t.id, title: t.title });
for (const item of toQueueItems(data.recentlyPlayed)) {
const id = String(item.id);
if (seen.has(id)) continue;
seen.add(id);
merged.push({
id,
title: item.title,
artist: item.artist,
source: item.source ?? 'local',
coverUrl: item.coverUrl
});
}
return merged.slice(0, 15);
});
@@ -98,6 +113,7 @@
>
<Cover
trackId={track.id}
src={track.coverUrl}
hue={hueFor(track.id)}
size="small"
alt={track.title}
@@ -109,6 +125,9 @@
</Cover>
<div class="min-w-0">
<div class="truncate text-sm font-semibold text-[var(--mf-text)]">{track.title}</div>
{#if track.artist}
<div class="truncate text-xs text-neutral-500">{track.artist}</div>
{/if}
</div>
</button>
{/each}