feat(frontend): perbagus voice & audio playback UX
- Recordings: custom RecordingAudioPlayer (play/pause, buffering spinner, click-to-seek, time label, eq bars, single-playback antar kartu) + highlight kartu now-playing - Media: thumbnail di disc hero + queue row, equalizer saat playing, badge 'up next', label Paused vs Now playing - MiniPlayer global di AppFrame (fixed bottom-right, hidden on /media) menggantikan use-media-player.tsx dead provider (dihapus) - Voice: mic level meter live (AnalyserNode RMS) + slider mic/listen volume
This commit is contained in:
@@ -106,6 +106,7 @@ export function useMicTransmit(ws: {
|
||||
sendBinary: (data: ArrayBufferLike) => void;
|
||||
}) {
|
||||
const transmitterRef = useRef<MicTransmitter | null>(null);
|
||||
const [micLevel, setMicLevel] = useState(0);
|
||||
|
||||
const action = useAction(async (active: boolean) => {
|
||||
if (active) {
|
||||
@@ -116,6 +117,7 @@ export function useMicTransmit(ws: {
|
||||
} else {
|
||||
transmitterRef.current?.stop();
|
||||
transmitterRef.current = null;
|
||||
setMicLevel(0);
|
||||
await voiceApi.sendCommand("voice:transmit:stop");
|
||||
}
|
||||
});
|
||||
@@ -124,7 +126,15 @@ export function useMicTransmit(ws: {
|
||||
transmitterRef.current?.setVolume(volume / 100);
|
||||
}, []);
|
||||
|
||||
return { ...action, setVolume };
|
||||
// Poll the analyser RMS so the UI can render a live input meter.
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setMicLevel(transmitterRef.current?.getLevel() ?? 0);
|
||||
}, 120);
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
return { ...action, setVolume, micLevel };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user