Initial scaffold: FastAPI backend + React frontend + Docker Compose
- Backend: FastAPI with SQLite, clip CRUD, health check - Frontend: React + Vite + TypeScript + Tailwind, dark theme - Components: Generator, Gallery, Player - Docker: Compose setup for backend + frontend - Architecture docs in Palace KB
This commit is contained in:
commit
a2bc785b14
23 files changed
+819
No files matched your search
@@ -0,0 +1,70 @@
|
||||
import { useRef, useEffect } from 'react'
|
||||
|
||||
interface Clip {
|
||||
id: string
|
||||
prompt: string
|
||||
duration_seconds: number
|
||||
}
|
||||
|
||||
interface Props {
|
||||
clip: Clip
|
||||
isPlaying: boolean
|
||||
onTogglePlay: () => void
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export default function Player({ clip, isPlaying, onTogglePlay, onClose }: Props) {
|
||||
const audioRef = useRef<HTMLAudioElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (audioRef.current) {
|
||||
if (isPlaying) {
|
||||
audioRef.current.play()
|
||||
} else {
|
||||
audioRef.current.pause()
|
||||
}
|
||||
}
|
||||
}, [isPlaying, clip.id])
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-lyria-panel border-t border-white/10 px-6 py-3">
|
||||
<div className="max-w-6xl mx-auto flex items-center gap-4">
|
||||
<button
|
||||
onClick={onTogglePlay}
|
||||
className="w-10 h-10 rounded-full bg-lyria-accent flex items-center justify-center text-white hover:bg-lyria-accent/90 transition-colors shrink-0"
|
||||
>
|
||||
{isPlaying ? (
|
||||
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M8 5v14l11-7z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm text-white truncate">{clip.prompt}</p>
|
||||
<p className="text-xs text-lyria-muted">{clip.duration_seconds}s</p>
|
||||
</div>
|
||||
|
||||
<audio
|
||||
ref={audioRef}
|
||||
src={`/api/clips/${clip.id}/audio`}
|
||||
onEnded={() => onTogglePlay()}
|
||||
className="hidden"
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-lyria-muted hover:text-white transition-colors shrink-0"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user