All checks were successful
Deploy / build-and-deploy (push) Successful in 1m43s
43 lines
1.4 KiB
TypeScript
43 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
import { subscribe, getPlaybackState, stopCurrent, PlaybackState } from "@/lib/player";
|
|
|
|
export function SoundPlayerBar() {
|
|
const [s, setS] = useState<PlaybackState>(getPlaybackState());
|
|
|
|
useEffect(() => {
|
|
const unsub = subscribe(setS);
|
|
return unsub;
|
|
}, []);
|
|
|
|
if (!s.isPlaying) return null;
|
|
|
|
const pct = Math.min((s.elapsed / s.duration) * 100, 100);
|
|
|
|
return (
|
|
<div className="border-t border-slate-700/30 bg-slate-950/95 px-3 py-2">
|
|
<div className="flex items-center gap-2 text-[10px] font-mono max-w-2xl mx-auto">
|
|
<span className="text-cyan-400 shrink-0">🔊</span>
|
|
<span className="text-slate-300 truncate max-w-[200px]">{s.name}</span>
|
|
<div className="flex-1 h-1.5 bg-slate-800 rounded-full overflow-hidden min-w-[80px]">
|
|
<div
|
|
className="h-full bg-cyan-500 transition-all duration-100 rounded-full"
|
|
style={{ width: `${pct}%` }}
|
|
/>
|
|
</div>
|
|
<span className="text-slate-500 shrink-0 w-16 text-right tabular-nums">
|
|
{s.elapsed.toFixed(1)}s / {s.duration.toFixed(0)}s
|
|
</span>
|
|
<button
|
|
type="button"
|
|
onClick={stopCurrent}
|
|
className="px-2 py-0.5 rounded bg-slate-800 hover:bg-red-800/60 text-slate-400 hover:text-red-300 cursor-pointer shrink-0"
|
|
>
|
|
■
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|