From 2b4fbe5173b26f18243c897a27c503e5c0a82628 Mon Sep 17 00:00:00 2001 From: Jamie Pine Date: Wed, 28 Jan 2026 22:27:37 -0800 Subject: [PATCH] Refactor AudioPlayer and related components to support conditional auto-play functionality - Updated AudioPlayer to auto-play only if the shouldAutoPlay flag is set, enhancing user control over playback. - Refactored HistoryTable, SampleList, and useGenerationForm to utilize setAudioWithAutoPlay for consistent audio loading and playback behavior. - Improved user experience by ensuring audio is only played when explicitly intended, reducing unexpected playback. --- .../components/AudioPlayer/AudioPlayer.tsx | 24 ++++++++++++------- app/src/components/History/HistoryTable.tsx | 13 ++++++---- .../components/VoiceProfiles/SampleList.tsx | 4 ++-- app/src/lib/hooks/useGenerationForm.ts | 4 ++-- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/app/src/components/AudioPlayer/AudioPlayer.tsx b/app/src/components/AudioPlayer/AudioPlayer.tsx index a03224c9..10323450 100644 --- a/app/src/components/AudioPlayer/AudioPlayer.tsx +++ b/app/src/components/AudioPlayer/AudioPlayer.tsx @@ -357,14 +357,22 @@ export function AudioPlayer() { } } - // Standard WaveSurfer auto-play - // Use a small delay to ensure audio element is fully ready - setTimeout(() => { - wavesurfer.play().catch((error) => { - debug.error('Failed to autoplay:', error); - // Don't show error for autoplay failures (browser restrictions) - }); - }, 100); + // Only auto-play if shouldAutoPlay flag is set (user explicitly clicked to play) + const shouldAutoPlayNow = usePlayerStore.getState().shouldAutoPlay; + if (shouldAutoPlayNow) { + // Clear the flag first + usePlayerStore.getState().clearAutoPlayFlag(); + + // Use a small delay to ensure audio element is fully ready + setTimeout(() => { + wavesurfer.play().catch((error) => { + debug.error('Failed to autoplay:', error); + // Don't show error for autoplay failures (browser restrictions) + }); + }, 100); + } else { + debug.log('Skipping auto-play - shouldAutoPlay is false'); + } }); // Handle play/pause diff --git a/app/src/components/History/HistoryTable.tsx b/app/src/components/History/HistoryTable.tsx index 85c7a8e4..418546b5 100644 --- a/app/src/components/History/HistoryTable.tsx +++ b/app/src/components/History/HistoryTable.tsx @@ -53,7 +53,7 @@ export function HistoryTable() { const exportGeneration = useExportGeneration(); const exportGenerationAudio = useExportGenerationAudio(); const importGeneration = useImportGeneration(); - const setAudio = usePlayerStore((state) => state.setAudio); + const setAudioWithAutoPlay = usePlayerStore((state) => state.setAudioWithAutoPlay); const restartCurrentAudio = usePlayerStore((state) => state.restartCurrentAudio); const currentAudioId = usePlayerStore((state) => state.audioId); const isPlaying = usePlayerStore((state) => state.isPlaying); @@ -77,9 +77,9 @@ export function HistoryTable() { if (currentAudioId === audioId) { restartCurrentAudio(); } else { - // Otherwise, load the new audio + // Otherwise, load the new audio and auto-play it const audioUrl = apiClient.getAudioUrl(audioId); - setAudio(audioUrl, audioId, profileId, text.substring(0, 50)); + setAudioWithAutoPlay(audioUrl, audioId, profileId, text.substring(0, 50)); } }; @@ -233,7 +233,11 @@ export function HistoryTable() { {/* Far right - Ellipsis actions */} -
+
e.stopPropagation()} + onClick={(e) => e.stopPropagation()} + > diff --git a/app/src/components/VoiceProfiles/SampleList.tsx b/app/src/components/VoiceProfiles/SampleList.tsx index e116462e..6dad3325 100644 --- a/app/src/components/VoiceProfiles/SampleList.tsx +++ b/app/src/components/VoiceProfiles/SampleList.tsx @@ -14,7 +14,7 @@ export function SampleList({ profileId }: SampleListProps) { const { data: samples, isLoading } = useProfileSamples(profileId); const deleteSample = useDeleteSample(); const [uploadOpen, setUploadOpen] = useState(false); - const setAudio = usePlayerStore((state) => state.setAudio); + const setAudioWithAutoPlay = usePlayerStore((state) => state.setAudioWithAutoPlay); const currentAudioId = usePlayerStore((state) => state.audioId); const isPlaying = usePlayerStore((state) => state.isPlaying); @@ -26,7 +26,7 @@ export function SampleList({ profileId }: SampleListProps) { const handlePlay = (referenceText: string, sampleId: string) => { const audioUrl = apiClient.getSampleUrl(sampleId); - setAudio(audioUrl, sampleId, referenceText.substring(0, 50)); + setAudioWithAutoPlay(audioUrl, sampleId, null, referenceText.substring(0, 50)); }; if (isLoading) { diff --git a/app/src/lib/hooks/useGenerationForm.ts b/app/src/lib/hooks/useGenerationForm.ts index b0c87b4a..c6fdba50 100644 --- a/app/src/lib/hooks/useGenerationForm.ts +++ b/app/src/lib/hooks/useGenerationForm.ts @@ -28,7 +28,7 @@ interface UseGenerationFormOptions { export function useGenerationForm(options: UseGenerationFormOptions = {}) { const { toast } = useToast(); const generation = useGeneration(); - const setAudio = usePlayerStore((state) => state.setAudio); + const setAudioWithAutoPlay = usePlayerStore((state) => state.setAudioWithAutoPlay); const setIsGenerating = useGenerationStore((state) => state.setIsGenerating); const [downloadingModelName, setDownloadingModelName] = useState(null); const [downloadingDisplayName, setDownloadingDisplayName] = useState(null); @@ -97,7 +97,7 @@ export function useGenerationForm(options: UseGenerationFormOptions = {}) { }); const audioUrl = apiClient.getAudioUrl(result.id); - setAudio(audioUrl, result.id, selectedProfileId, data.text.substring(0, 50)); + setAudioWithAutoPlay(audioUrl, result.id, selectedProfileId, data.text.substring(0, 50)); form.reset(); options.onSuccess?.(result.id);