diff --git a/.envrc b/.envrc deleted file mode 100644 index 0a722d7..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use nix; diff --git a/index.html b/index.html index 17c3bd5..d17bf2c 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,6 @@
- + diff --git a/src/App.tsx b/src/App.tsx index e8cb2ff..77c2262 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react' +import { useState, useEffect } from 'react' import { MusicBrainzApi, type ITrack } from 'musicbrainz-api'; import Album from "./components/Album/Album"; import AlbumArt from "./components/AlbumArt/AlbumArt"; @@ -28,7 +28,7 @@ async function getCoverArtSrcURL(releaseId: string, releaseGroupId: string): Pro continue; } const data = await res.json(); - const front = (data.images || []).find((img: any) => img.front) || data.images?.[0]; + const front = (data.images || []).find(img => img.front) || data.images?.[0]; if (front) { return front.thumbnails?.["1200"]|| front.image; } @@ -55,65 +55,11 @@ function navidromeURL(path: string, params: Record): string { function App() { const [album, setAlbum] = useState(null); const [buffer, setBuffer] = useState([]); - const [nowPlaying, play] = useState(0); + const [nowPlaying, play] = useState(null); const [searching, setSearching] = useState(false); - const [paused, setPaused] = useState(true); - const [currentTime, setCurrentTime] = useState(0); - const [duration, setDuration] = useState(0); - const audioRef = useRef(null); + const [paused, setPaused] = useState(false); - const handleTimeUpdate = () => { - const audio = audioRef.current; - if (!audio) { - return; - } - setCurrentTime(audio.currentTime || 0); - }; - - const handleLoadedMetadata = () => { - const audio = audioRef.current; - if (!audio) { - return; - } - setDuration(audio.duration); - setCurrentTime(audio.currentTime || 0); - }; - - const handleEnded = () => { - if ((album?.tracks?.length ?? 0) > nowPlaying + 1) { // if there's a next track - play(nowPlaying + 1); - setPaused(false); - } - }; - - // When a track ends or is skipped, play the new track - useEffect(() => { - const audio = audioRef.current; - if (!audio) { - return; - } - audio.currentTime = 0; - audio.load(); - setCurrentTime(0); - setDuration(0); - audio.play().catch(() => setPaused(true)); - }, [nowPlaying]); - - // Handle play/pause - useEffect(() => { - const audio = audioRef.current; - if (!audio) { - return; - } - if (paused) { - audio.pause(); - } else { - audio.play().catch(() => setPaused(true)); - } - }, [paused]); - - - // Handle keyboard/scanner input + // Handle input useEffect(() => { const handleKeyDown = (ev: KeyboardEvent) => { if (ev.key === "s") { // TODO: remove @@ -173,7 +119,7 @@ function App() { const ndRes = await fetch(navidromeURL('/rest/getAlbum.view', { id: ndFoundAlbum.id })).then(res => res.json()); const ndAlbum = ndRes["subsonic-response"].album; console.log("Found album in Navidrome:", ndAlbum); - let tracks: Track[] = ndAlbum.song?.map((t: any) => ({ + let tracks: PlayableTrack[] = ndAlbum.song?.map((t: any) => ({ title: t.title, duration: t.duration, id: t.id, @@ -186,10 +132,10 @@ function App() { releaseDate: ndAlbum.originalReleaseDate??'', tracks, coverArtLink: navidromeURL('/rest/getCoverArt.view', { id: ndAlbum.coverArt }), - }); + }) // # …and play! - play(0); - setPaused(false); + // play(album.tracks[0]); + // TODO setSearching(false); } else { // Not found in Navidrome; populate with MusicBrainz data instead const fullMbRelease = await mbApi.lookup('release', mbRelease.id, ['recordings', 'artist-credits', 'release-groups']); @@ -204,7 +150,7 @@ function App() { artistName: fullMbRelease['artist-credit']?.[0].name || '', // TODO releaseDate: fullMbRelease.date || '', tracks, - coverArtLink: await getCoverArtSrcURL(fullMbRelease.id, fullMbRelease['release-group']?.id || '') || '', + coverArtLink: await getCoverArtSrcURL(fullMbRelease.id, fullMbRelease['release-group'].id) || '', }) console.log(album); setSearching(false); @@ -214,30 +160,13 @@ function App() { if (album) { // If the Album is a PlayableAlbum const player = album.tracks[0]?.source ? ( - + ) : (

This album cannot be played, as Chandler doesn't own a copy.

); return (
-
diff --git a/src/album.tsx b/src/album.tsx index 7cf5e8c..27754de 100644 --- a/src/album.tsx +++ b/src/album.tsx @@ -1,8 +1,8 @@ -export interface Album { +export interface Album { title: string; artistName: string; releaseDate: any; // TODO: Date; - tracks: Track[]; + tracks: TTrack[]; coverArtLink: string; } diff --git a/src/components/Album/Album.tsx b/src/components/Album/Album.tsx index 2b84aed..4c9c1eb 100644 --- a/src/components/Album/Album.tsx +++ b/src/components/Album/Album.tsx @@ -2,7 +2,7 @@ import Track from "./Track"; import "./Album.css"; import type { Album, Track as TrackType } from "../../album"; -export default function Album({ album, dismissAlbum, play, nowPlaying }: { album: Album; dismissAlbum: () => void, play: (i: number) => void, nowPlaying: TrackType }) { +export default function Album({ album, dismissAlbum, play, nowPlaying }: { album: Album; dismissAlbum: () => void, play: (track: TrackType) => void, nowPlaying: any }) { return (
@@ -14,8 +14,8 @@ export default function Album({ album, dismissAlbum, play, nowPlaying }: { album {album.artistName} {album.releaseDate.year ? ' • ' + album.releaseDate.year : ''} {/* TODO: .toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" }) */}

- {album.tracks.map((t, i) => ( - + {album.tracks.map(t => ( + ))}
diff --git a/src/components/Album/Track.tsx b/src/components/Album/Track.tsx index aa4f126..a838f61 100644 --- a/src/components/Album/Track.tsx +++ b/src/components/Album/Track.tsx @@ -1,18 +1,8 @@ import type { Track } from "../../album"; import css from "./Track.module.css"; -export default function Track({ - track, - idx, - play, - nowPlaying, -}: { - track: Track; - idx: number; - play: (i: number) => void; - nowPlaying: Track | null; -}) { - const handler = track.source ? () => play(idx) : undefined; +export default function Track({track, play, nowPlaying}:{track:any, play: (track:Track) => void, nowPlaying:any}) { + const handler = track.source ? () => play(track) : undefined; return ( <>
diff --git a/src/components/NowPlaying/NowPlaying.tsx b/src/components/NowPlaying/NowPlaying.tsx index 55d1ec6..be88126 100644 --- a/src/components/NowPlaying/NowPlaying.tsx +++ b/src/components/NowPlaying/NowPlaying.tsx @@ -1,39 +1,17 @@ import type { Track } from '../../album'; import './NowPlaying.css'; -const formatTime = (value: number) => { - const minutes = Math.floor(value / 60); - const seconds = Math.round(value) % 60; - return `${minutes}:${seconds.toString().padStart(2, "0")}`; -}; - -export default function NowPlaying({ - currentTrack, - paused, - currentTime, - duration, - setPaused, -}: { - currentTrack: Track; - paused: boolean; - currentTime: number; - duration: number; - setPaused: (p: boolean) => void; -}) { +export default function NowPlaying({ nowPlaying, paused, setPaused }: { nowPlaying: Track|null; paused: boolean; setPaused: (paused: boolean) => void }) { return (
- +
- {currentTrack?.title??"—"} - {formatTime(currentTime)} / {formatTime(duration)} + {nowPlaying?.title??"—"} + 0:00 / 0:00
-
0 ? Math.min(1, Math.max(0, currentTime / duration)) : 0) * 100}%` }} - >
+