diff --git a/data/waveforms/3f776e71-0c9c-44b5-bc9f-a796ec3159ef.svg b/data/waveforms/3f776e71-0c9c-44b5-bc9f-a796ec3159ef.svg new file mode 100644 index 0000000..e588d9e --- /dev/null +++ b/data/waveforms/3f776e71-0c9c-44b5-bc9f-a796ec3159ef.svg @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/components/Player.tsx b/frontend/src/components/Player.tsx index 8e36f6e..07f20e2 100644 --- a/frontend/src/components/Player.tsx +++ b/frontend/src/components/Player.tsx @@ -28,6 +28,7 @@ export default function Player({ clip, isPlaying, onTogglePlay, onStop, onClose const [volume, setVolume] = useState(1) const [isMuted, setIsMuted] = useState(false) const [isDragging, setIsDragging] = useState(false) + const [isRepeating, setIsRepeating] = useState(false) const progressRef = useRef(null) // Sync play/pause with audio element @@ -59,10 +60,23 @@ export default function Player({ clip, isPlaying, onTogglePlay, onStop, onClose // Track ended const handleEnded = () => { - onTogglePlay() + if (!isRepeating) { + onTogglePlay() + } setCurrentTime(0) } + // Toggle repeat + const toggleRepeat = () => { + setIsRepeating(prev => { + const next = !prev + if (audioRef.current) { + audioRef.current.loop = next + } + return next + }) + } + // Seek to position const handleSeek = useCallback((clientX: number) => { if (!progressRef.current || !audioRef.current) return @@ -181,13 +195,28 @@ export default function Player({ clip, isPlaying, onTogglePlay, onStop, onClose - {/* Restart */} + {/* Restart — ISO skip backwards to beginning */} + + {/* Repeat — ISO repeat indefinitely with glowing toggle */} +