diff --git a/src/workspaces/officerdev/src/apps/Music/MusicBrowser.tsx b/src/workspaces/officerdev/src/apps/Music/MusicBrowser.tsx index bbd1d2e7..da506926 100644 --- a/src/workspaces/officerdev/src/apps/Music/MusicBrowser.tsx +++ b/src/workspaces/officerdev/src/apps/Music/MusicBrowser.tsx @@ -1,21 +1,42 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, type ReactNode } from 'react'; import { useClient } from 'hooks/useClient'; import { usePanelChannel } from 'hooks/usePanelChannel'; import { Library, Music2, ChevronLeft, Folder } from 'lucide-react'; import { MUSIC_ROOT, MUSIC_CWD_CHANNEL, + coverUrl, toRel, type LsResult, type Manifest, type ManifestAlbum, } from './shared'; +// A row's leading thumbnail: the folder's indexed cover (its folder.jpg/cover.jpg, server-compressed), +// falling back to an icon when it has none or the image fails to load. +const RowThumb = ({ src, fallback }: { src: string | null; fallback: ReactNode }) => { + const [failed, setFailed] = useState(false); + useEffect(() => setFailed(false), [src]); + return ( +