WIP: Fix play behaviour in track view

- Added wasPlayingRef to preserve playback state across version changes
- Auto-play new waveform if previous version was playing
- Ensure play/pause buttons work correctly after version switch
- Added WebSocket proxy configuration for real-time features

Fixes: Version switching now preserves playback state
Todo: Test edge cases and finalize implementation
This commit is contained in:
Mistral Vibe
2026-03-29 20:37:25 +02:00
parent 02fd556372
commit 1179d9f063
2 changed files with 41 additions and 5 deletions

View File

@@ -31,6 +31,22 @@ server {
proxy_send_timeout 300s; proxy_send_timeout 300s;
} }
# WebSocket proxy for real-time version room events
location /ws/ {
proxy_pass http://api:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket specific headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
# SPA routing — all other paths fall back to index.html # SPA routing — all other paths fall back to index.html
location / { location / {
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;

View File

@@ -16,6 +16,7 @@ export function useWaveform(
const [isPlaying, setIsPlaying] = useState(false); const [isPlaying, setIsPlaying] = useState(false);
const [isReady, setIsReady] = useState(false); const [isReady, setIsReady] = useState(false);
const [currentTime, setCurrentTime] = useState(0); const [currentTime, setCurrentTime] = useState(0);
const wasPlayingRef = useRef(false);
useEffect(() => { useEffect(() => {
if (!containerRef.current || !options.url) return; if (!containerRef.current || !options.url) return;
@@ -38,6 +39,10 @@ export function useWaveform(
ws.on("ready", () => { ws.on("ready", () => {
setIsReady(true); setIsReady(true);
options.onReady?.(ws.getDuration()); options.onReady?.(ws.getDuration());
// Auto-play if previous version was playing
if (wasPlayingRef.current) {
ws.play();
}
}); });
ws.on("audioprocess", (time) => { ws.on("audioprocess", (time) => {
@@ -45,9 +50,18 @@ export function useWaveform(
options.onTimeUpdate?.(time); options.onTimeUpdate?.(time);
}); });
ws.on("play", () => setIsPlaying(true)); ws.on("play", () => {
ws.on("pause", () => setIsPlaying(false)); setIsPlaying(true);
ws.on("finish", () => setIsPlaying(false)); wasPlayingRef.current = true;
});
ws.on("pause", () => {
setIsPlaying(false);
wasPlayingRef.current = false;
});
ws.on("finish", () => {
setIsPlaying(false);
wasPlayingRef.current = false;
});
wsRef.current = ws; wsRef.current = ws;
return () => { return () => {
@@ -57,8 +71,14 @@ export function useWaveform(
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [options.url]); }, [options.url]);
const play = () => wsRef.current?.play(); const play = () => {
const pause = () => wsRef.current?.pause(); wsRef.current?.play();
wasPlayingRef.current = true;
};
const pause = () => {
wsRef.current?.pause();
wasPlayingRef.current = false;
};
const seekTo = (time: number) => { const seekTo = (time: number) => {
if (wsRef.current && isReady) { if (wsRef.current && isReady) {
wsRef.current.setTime(time); wsRef.current.setTime(time);