feat: Add repeat button and fix skip-to-beginning icon

Player.tsx updates:
- Repeat button: ISO repeat indefinitely icon with glowing toggle state.
  When active: lyria-accent color, bg-lyria-accent/10, orange glow shadow.
  When inactive: muted gray, hover to white. Toggles audio.loop.
- Skip to beginning: Now uses ISO skip-backwards icon (filled, two bars
  pointing left) instead of circular arrow. Title: 'Skip to beginning'.
- Track end handler respects repeat state — if repeating, stays playing
  and loops; if not, pauses as before.
- New state: isRepeating (useState), toggleRepeat function sets both
  React state and audioRef.current.loop.
This commit is contained in:
rin.kagamine committed 2026-05-29 20:35:00 -04:00
1 parent 8218234eb9
commit b0755b9063
2 files changed
+236 -4

No files matched your search

+33 -4
View File
@@ -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<HTMLDivElement>(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
</svg>
</button>
{/* Restart */}
{/* Restart — ISO skip backwards to beginning */}
<button
onClick={handleRestart}
className="w-7 h-7 rounded flex items-center justify-center text-lyria-muted hover:text-white hover:bg-white/5 transition-colors shrink-0"
title="Play from beginning"
title="Skip to beginning"
>
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
<path d="M6 6h2v12H6V6zm3.5 6l8.5 6V6l-8.5 6z" />
</svg>
</button>
{/* Repeat — ISO repeat indefinitely with glowing toggle */}
<button
onClick={toggleRepeat}
className={`w-7 h-7 rounded flex items-center justify-center transition-colors shrink-0 ${
isRepeating
? 'text-lyria-accent bg-lyria-accent/10 shadow-[0_0_8px_rgba(255,107,53,0.4)]'
: 'text-lyria-muted hover:text-white hover:bg-white/5'
}`}
title={isRepeating ? 'Repeat on' : 'Repeat off'}
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</button>