frontend: Finish interactivity

This commit is contained in:
2025-02-15 16:28:47 -08:00
parent 9c4981b9cb
commit 79f53bbffe
9 changed files with 247 additions and 35 deletions

View File

@@ -1,30 +1,103 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import SongTable from './SongTable';
import NowPlaying from './NowPlaying';
import AddSongPanel from './AddSongPanel';
import { API, PlaylistItem } from '../api/player';
const App: React.FC = () => {
const [isPlaying, setIsPlaying] = useState(false);
const [nowPlayingSong, setNowPlayingSong] = useState<string | null>(null);
const [nowPlayingFileName, setNowPlayingFileName] = useState<string | null>(null);
const [songs, setSongs] = useState<string[]>([]);
const [songs, setSongs] = useState<PlaylistItem[]>([]);
const [ws, setWs] = useState<WebSocket | null>(null);
const fetchPlaylist = async () => {
const playlist = await API.getPlaylist();
setSongs(playlist);
};
const fetchNowPlaying = async () => {
const nowPlaying = await API.getNowPlaying();
setNowPlayingSong(nowPlaying.nowPlaying);
setNowPlayingFileName(nowPlaying.currentFile);
setIsPlaying(!nowPlaying.isPaused);
};
const handleAddURL = (url: string) => {
const urlToAdd = url.trim();
if (urlToAdd) {
setSongs([...songs, urlToAdd]);
API.addToPlaylist(urlToAdd);
fetchPlaylist();
}
};
const handleDelete = (index: number) => {
setSongs(songs.filter((_, i) => i !== index));
API.removeFromPlaylist(index);
fetchPlaylist();
fetchNowPlaying();
};
const handleSkipTo = (index: number) => {
setNowPlayingSong(songs[index]);
setNowPlayingFileName(songs[index].split('/').pop() || null);
setIsPlaying(true);
const handleSkipTo = async (index: number) => {
const song = songs[index];
if (song.playing) {
togglePlayPause();
} else {
await API.skipTo(index);
await API.play();
}
fetchNowPlaying();
fetchPlaylist();
};
const togglePlayPause = async () => {
if (isPlaying) {
await API.pause();
} else {
await API.play();
}
fetchNowPlaying();
};
const handleSkip = async () => {
await API.skip();
fetchNowPlaying();
};
const handlePrevious = async () => {
await API.previous();
fetchNowPlaying();
};
const watchForEvents = () => {
const ws = API.subscribeToEvents((event) => {
switch (event.event) {
case 'user_modify':
case 'end-file':
case 'playback-restart':
fetchPlaylist();
fetchNowPlaying();
break;
}
});
return ws;
};
useEffect(() => {
fetchPlaylist();
fetchNowPlaying();
setWs(watchForEvents());
return () => {
if (ws) {
ws.close();
}
};
}, []);
return (
<div className="flex items-center justify-center h-screen w-screen bg-black py-10">
<div className="bg-violet-900 w-full md:max-w-xl h-full md:max-h-xl md:border md:rounded-2xl flex flex-col">
@@ -33,14 +106,15 @@ const App: React.FC = () => {
songName={nowPlayingSong || "(Not Playing)"}
fileName={nowPlayingFileName || ""}
isPlaying={isPlaying}
onPlayPause={() => setIsPlaying(!isPlaying)}
onStepForward={() => {}}
onStepBackward={() => {}}
onPlayPause={togglePlayPause}
onSkip={handleSkip}
onPrevious={handlePrevious}
/>
{songs.length > 0 ? (
<SongTable
songs={songs}
isPlaying={isPlaying}
onDelete={handleDelete}
onSkipTo={handleSkipTo}
/>