diff --git a/src/pages/SoundboardPage.tsx b/src/pages/SoundboardPage.tsx index e587e34..89b398c 100644 --- a/src/pages/SoundboardPage.tsx +++ b/src/pages/SoundboardPage.tsx @@ -1,12 +1,46 @@ import React, { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; -import { Play, Square, Volume2, Plus } from 'lucide-react'; +import { Play, Square, Volume2, Plus, Clock, Weight } from 'lucide-react'; import { toast } from 'sonner'; import { apiService } from '@/services/api'; import { AddUrlDialog } from '@/components/AddUrlDialog'; import { useAddUrlShortcut } from '@/hooks/use-keyboard-shortcuts'; import { formatDuration } from '@/lib/format-duration'; +import { cn } from '@/lib/utils'; +import NumberFlow from '@number-flow/react'; +import { formatSize } from '@/lib/format-size'; +import { useTheme } from 'next-themes'; + +const lightModeColors = [ + 'bg-red-600/30 hover:bg-red-600/40 text-red-900 border-red-600/20', + 'bg-blue-700/30 hover:bg-blue-700/40 text-blue-900 border-blue-700/20', + 'bg-yellow-400/30 hover:bg-yellow-400/40 text-yellow-800 border-yellow-400/20', + 'bg-purple-700/30 hover:bg-purple-700/40 text-purple-900 border-purple-700/20', + 'bg-green-600/30 hover:bg-green-600/40 text-green-900 border-green-600/20', + 'bg-pink-500/30 hover:bg-pink-500/40 text-pink-900 border-pink-500/20', + 'bg-cyan-500/30 hover:bg-cyan-500/40 text-cyan-900 border-cyan-500/20', + 'bg-amber-500/30 hover:bg-amber-500/40 text-amber-900 border-amber-500/20', + 'bg-indigo-800/30 hover:bg-indigo-800/40 text-indigo-900 border-indigo-800/20', + 'bg-lime-500/30 hover:bg-lime-500/40 text-lime-900 border-lime-500/20', + 'bg-fuchsia-600/30 hover:bg-fuchsia-600/40 text-fuchsia-900 border-fuchsia-600/20', + 'bg-orange-600/30 hover:bg-orange-600/40 text-orange-900 border-orange-600/20', +] + +const darkModeColors = [ + 'bg-red-700/40 hover:bg-red-700/50 text-red-100 border border-red-500/50', + 'bg-blue-800/40 hover:bg-blue-800/50 text-blue-100 border border-blue-600/50', + 'bg-yellow-600/40 hover:bg-yellow-600/50 text-yellow-100 border border-yellow-400/50', + 'bg-purple-800/40 hover:bg-purple-800/50 text-purple-100 border border-purple-600/50', + 'bg-green-700/40 hover:bg-green-700/50 text-green-100 border border-green-500/50', + 'bg-pink-700/40 hover:bg-pink-700/50 text-pink-100 border border-pink-500/50', + 'bg-cyan-700/40 hover:bg-cyan-700/50 text-cyan-100 border border-cyan-500/50', + 'bg-amber-700/40 hover:bg-amber-700/50 text-amber-100 border border-amber-500/50', + 'bg-indigo-900/40 hover:bg-indigo-900/50 text-indigo-100 border border-indigo-700/50', + 'bg-lime-700/40 hover:bg-lime-700/50 text-lime-100 border border-lime-500/50', + 'bg-fuchsia-800/40 hover:bg-fuchsia-800/50 text-fuchsia-100 border border-fuchsia-600/50', + 'bg-orange-700/40 hover:bg-orange-700/50 text-orange-100 border border-orange-500/50', +] interface Sound { id: number; @@ -14,6 +48,7 @@ interface Sound { filename: string; type: string; duration: number; + size: number; play_count: number; is_normalized: boolean; normalized_filename?: string; @@ -22,45 +57,38 @@ interface Sound { interface SoundCardProps { sound: Sound; onPlay: (soundId: number) => void; - isPlaying: boolean; + colorClasses: string; } -const SoundCard: React.FC = ({ sound, onPlay, isPlaying }) => { +const SoundCard: React.FC = ({ sound, onPlay, colorClasses }) => { const handlePlay = () => { onPlay(sound.id); }; return ( - - - - {sound.name} - - - -
-
- + + +

{sound.name}

+
+
+ {formatDuration(sound.duration)}
-
- {sound.play_count} plays +
+ + {formatSize(sound.size)} +
+
+ +
- - {sound.is_normalized && ( -
- Normalized -
- )} ); @@ -70,9 +98,9 @@ export function SoundboardPage() { const [sounds, setSounds] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [playingSound, setPlayingSound] = useState(null); const [searchTerm, setSearchTerm] = useState(''); const [addUrlDialogOpen, setAddUrlDialogOpen] = useState(false); + const [currentColors, setCurrentColors] = useState(lightModeColors) // Setup keyboard shortcut for CTRL+U useAddUrlShortcut(() => setAddUrlDialogOpen(true)); @@ -81,6 +109,21 @@ export function SoundboardPage() { fetchSounds(); }, []); + const { resolvedTheme } = useTheme() + + useEffect(() => { + if (resolvedTheme === 'dark') { + setCurrentColors(darkModeColors) + } else { + setCurrentColors(lightModeColors) + } + }, [resolvedTheme]) + + const getSoundColor = (soundIdx: number) => { + const index = soundIdx % currentColors.length + return currentColors[index] + } + const fetchSounds = async () => { try { setLoading(true); @@ -90,7 +133,6 @@ export function SoundboardPage() { } catch (err) { setError('Failed to load sounds'); toast.error('Failed to load sounds'); - console.error('Error fetching sounds:', err); } finally { setLoading(false); } @@ -98,30 +140,20 @@ export function SoundboardPage() { const handlePlaySound = async (soundId: number) => { try { - setPlayingSound(soundId); await apiService.post(`/api/soundboard/sounds/${soundId}/play`); - - // Reset playing state after a short delay - setTimeout(() => { - setPlayingSound(null); - }, 1000); } catch (err) { setError('Failed to play sound'); toast.error('Failed to play sound'); - console.error('Error playing sound:', err); - setPlayingSound(null); } }; const handleStopAll = async () => { try { await apiService.post('/api/soundboard/stop-all'); - setPlayingSound(null); toast.success('All sounds stopped'); } catch (err) { setError('Failed to stop sounds'); toast.error('Failed to stop sounds'); - console.error('Error stopping sounds:', err); } }; @@ -129,12 +161,10 @@ export function SoundboardPage() { try { const response = await apiService.post('/api/soundboard/force-stop'); const data = await response.json(); - setPlayingSound(null); toast.success(`Force stopped ${data.stopped_count} sound instances`); } catch (err) { setError('Failed to force stop sounds'); toast.error('Failed to force stop sounds'); - console.error('Error force stopping sounds:', err); } }; @@ -199,12 +229,12 @@ export function SoundboardPage() {
- {filteredSounds.map((sound) => ( + {filteredSounds.map((sound, idx) => ( ))}