From 1179d9f0630469839a76db212cc2983174aa1fe2 Mon Sep 17 00:00:00 2001 From: Mistral Vibe Date: Sun, 29 Mar 2026 20:37:25 +0200 Subject: [PATCH 1/2] 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 --- web/nginx.conf | 16 ++++++++++++++++ web/src/hooks/useWaveform.ts | 30 +++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/web/nginx.conf b/web/nginx.conf index b054424..cd1f909 100644 --- a/web/nginx.conf +++ b/web/nginx.conf @@ -31,6 +31,22 @@ server { 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 location / { try_files $uri $uri/ /index.html; diff --git a/web/src/hooks/useWaveform.ts b/web/src/hooks/useWaveform.ts index 0023fcb..06f812b 100644 --- a/web/src/hooks/useWaveform.ts +++ b/web/src/hooks/useWaveform.ts @@ -16,6 +16,7 @@ export function useWaveform( const [isPlaying, setIsPlaying] = useState(false); const [isReady, setIsReady] = useState(false); const [currentTime, setCurrentTime] = useState(0); + const wasPlayingRef = useRef(false); useEffect(() => { if (!containerRef.current || !options.url) return; @@ -38,6 +39,10 @@ export function useWaveform( ws.on("ready", () => { setIsReady(true); options.onReady?.(ws.getDuration()); + // Auto-play if previous version was playing + if (wasPlayingRef.current) { + ws.play(); + } }); ws.on("audioprocess", (time) => { @@ -45,9 +50,18 @@ export function useWaveform( options.onTimeUpdate?.(time); }); - ws.on("play", () => setIsPlaying(true)); - ws.on("pause", () => setIsPlaying(false)); - ws.on("finish", () => setIsPlaying(false)); + ws.on("play", () => { + setIsPlaying(true); + wasPlayingRef.current = true; + }); + ws.on("pause", () => { + setIsPlaying(false); + wasPlayingRef.current = false; + }); + ws.on("finish", () => { + setIsPlaying(false); + wasPlayingRef.current = false; + }); wsRef.current = ws; return () => { @@ -57,8 +71,14 @@ export function useWaveform( // eslint-disable-next-line react-hooks/exhaustive-deps }, [options.url]); - const play = () => wsRef.current?.play(); - const pause = () => wsRef.current?.pause(); + const play = () => { + wsRef.current?.play(); + wasPlayingRef.current = true; + }; + const pause = () => { + wsRef.current?.pause(); + wasPlayingRef.current = false; + }; const seekTo = (time: number) => { if (wsRef.current && isReady) { wsRef.current.setTime(time); From e71c7fc3adc31e8a181d3530b7a85a878d9abb2a Mon Sep 17 00:00:00 2001 From: Mistral Vibe Date: Sun, 29 Mar 2026 20:39:15 +0200 Subject: [PATCH 2/2] Fix play behaviour in track view - Version switching now stops playback and resets UI state - Playback must be started manually after version switch - Added space key shortcut for play/pause toggle - UI elements correctly reflect playback state Fixes: Play/pause controls work correctly after version switching Improves: User experience with keyboard shortcuts --- web/src/hooks/useWaveform.ts | 7 +++---- web/src/pages/SongPage.tsx | 19 ++++++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/web/src/hooks/useWaveform.ts b/web/src/hooks/useWaveform.ts index 06f812b..45b713d 100644 --- a/web/src/hooks/useWaveform.ts +++ b/web/src/hooks/useWaveform.ts @@ -39,10 +39,9 @@ export function useWaveform( ws.on("ready", () => { setIsReady(true); options.onReady?.(ws.getDuration()); - // Auto-play if previous version was playing - if (wasPlayingRef.current) { - ws.play(); - } + // Reset playing state when switching versions + setIsPlaying(false); + wasPlayingRef.current = false; }); ws.on("audioprocess", (time) => { diff --git a/web/src/pages/SongPage.tsx b/web/src/pages/SongPage.tsx index dd163df..b96071f 100644 --- a/web/src/pages/SongPage.tsx +++ b/web/src/pages/SongPage.tsx @@ -1,4 +1,4 @@ -import { useRef, useState, useCallback } from "react"; +import { useRef, useState, useCallback, useEffect } from "react"; import { useParams, Link } from "react-router-dom"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { api } from "../api/client"; @@ -42,6 +42,23 @@ export function SongPage() { peaksUrl: activeVersion ? `/api/v1/versions/${activeVersion}/waveform` : null, }); + // Add space key shortcut for play/pause + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.code === "Space") { + e.preventDefault(); + if (isPlaying) { + pause(); + } else { + play(); + } + } + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [isPlaying, play, pause]); + const { data: comments } = useQuery({ queryKey: ["comments", songId], queryFn: () => api.get(`/songs/${songId}/comments`),