diff --git a/furumi-node-player/client/src/FurumiPlayer.tsx b/furumi-node-player/client/src/FurumiPlayer.tsx index 2633975..6c058f7 100644 --- a/furumi-node-player/client/src/FurumiPlayer.tsx +++ b/furumi-node-player/client/src/FurumiPlayer.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef, useState, type MouseEvent as ReactMouseEvent } from 'react' import './furumi-player.css' -import { API_ROOT, searchTracks, recordPlay } from './furumiApi' +import { furumiApi, searchTracks, recordPlay } from './furumiApi' import { store, useAppDispatch, useAppSelector } from './store' import { fetchArtists } from './store/slices/artistsSlice' import { fetchArtistAlbums } from './store/slices/albumsSlice' @@ -88,13 +88,17 @@ export function FurumiPlayer({ user }: { user: UserProfile }) { document.title = `${nowPlayingTrack.title} — Furumi` if ('mediaSession' in navigator) { try { - const coverUrl = `${API_ROOT}/tracks/${nowPlayingTrack.slug}/cover` - navigator.mediaSession.metadata = new window.MediaMetadata({ + const meta = new window.MediaMetadata({ title: nowPlayingTrack.title, artist: nowPlayingTrack.artist || '', album: '', - artwork: [{ src: coverUrl, sizes: '512x512' }], }) + navigator.mediaSession.metadata = meta + furumiApi.get(`/tracks/${nowPlayingTrack.slug}/cover`, { responseType: 'blob' }) + .then((res) => { + meta.artwork = [{ src: URL.createObjectURL(res.data), sizes: '512x512' }] + }) + .catch(() => {}) } catch { // ignore } diff --git a/furumi-node-player/client/src/components/AuthImg.tsx b/furumi-node-player/client/src/components/AuthImg.tsx new file mode 100644 index 0000000..fadfedf --- /dev/null +++ b/furumi-node-player/client/src/components/AuthImg.tsx @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react' +import { furumiApi } from '../furumiApi' + +export function AuthImg({ src, alt, ...props }: React.ImgHTMLAttributes) { + const [blobUrl, setBlobUrl] = useState(null) + + useEffect(() => { + if (!src) return + let revoked = false + furumiApi.get(src, { responseType: 'blob' }) + .then((res) => { + if (!revoked) setBlobUrl(URL.createObjectURL(res.data)) + }) + .catch(() => {}) + return () => { + revoked = true + if (blobUrl) URL.revokeObjectURL(blobUrl) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [src]) + + if (!blobUrl) return null + return {alt +} diff --git a/furumi-node-player/client/src/components/NowPlaying.tsx b/furumi-node-player/client/src/components/NowPlaying.tsx index ac323bc..8adf61a 100644 --- a/furumi-node-player/client/src/components/NowPlaying.tsx +++ b/furumi-node-player/client/src/components/NowPlaying.tsx @@ -1,16 +1,14 @@ -import { useEffect, useState } from 'react' +import { useState } from 'react' import { API_ROOT } from '../furumiApi' +import { AuthImg } from './AuthImg' import type { QueueItem } from './QueueList' -function Cover({ src }: { src: string }) { +function Cover({ slug }: { slug: string }) { const [errored, setErrored] = useState(false) - - useEffect(() => { - setErrored(false) - }, [src]) + const src = `/tracks/${slug}/cover` if (errored) return <>🎵 - return setErrored(true)} /> + return setErrored(true)} /> } export function NowPlaying({ track }: { track: QueueItem | null }) { @@ -32,12 +30,10 @@ export function NowPlaying({ track }: { track: QueueItem | null }) { ) } - const coverUrl = `${API_ROOT}/tracks/${track.slug}/cover` - return (
- +
diff --git a/furumi-node-player/client/src/components/QueueList.tsx b/furumi-node-player/client/src/components/QueueList.tsx index d2877d3..57865de 100644 --- a/furumi-node-player/client/src/components/QueueList.tsx +++ b/furumi-node-player/client/src/components/QueueList.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react' -import { API_ROOT } from '../furumiApi' +import { AuthImg } from './AuthImg' export type QueueItem = { slug: string @@ -32,11 +32,10 @@ function fmt(secs: number) { return `${m}:${pad(s % 60)}` } -function Cover({ src }: { src: string }) { +function Cover({ slug }: { slug: string }) { const [errored, setErrored] = useState(false) - useEffect(() => { setErrored(false) }, [src]) if (errored) return <>🎵 - return setErrored(true)} /> + return setErrored(true)} /> } export function QueueList({ @@ -74,7 +73,7 @@ export function QueueList({ if (!t) return null const isPlaying = origIdx === playingOrigIdx - const coverSrc = t.album_slug ? `${API_ROOT}/tracks/${t.slug}/cover` : '' + const hasAlbum = !!t.album_slug const dur = t.duration ? fmt(t.duration) : '' const isDragging = draggingPos === pos const isDragOver = dragOverPos === pos @@ -115,7 +114,7 @@ export function QueueList({ > {isPlaying ? '' : pos + 1}
- {coverSrc ? : <>🎵} + {hasAlbum ? : <>🎵}
{t.title}