From c4db036cac31e4c2ae2b2eb113de7aaa2d3b1993 Mon Sep 17 00:00:00 2001 From: Greg Trihus Date: Tue, 5 May 2026 16:57:30 -0500 Subject: [PATCH 1/2] TT-7145 Enhance useWaveSurfer to improve playhead behavior - Introduced a constant FINISH_END_EPSILON_SEC to nudge the playhead slightly before the true duration, ensuring the custom cursor remains visible at the end. - Updated the playhead logic to clamp the current time within valid duration bounds. - Modified the 'finish' event handler to safely navigate to the adjusted end time before stopping playback, enhancing user experience. --- src/renderer/src/crud/useWaveSurfer.tsx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/crud/useWaveSurfer.tsx b/src/renderer/src/crud/useWaveSurfer.tsx index 90a933ea..519c9452 100644 --- a/src/renderer/src/crud/useWaveSurfer.tsx +++ b/src/renderer/src/crud/useWaveSurfer.tsx @@ -21,6 +21,9 @@ import { NamedRegions, useMobile } from '../utils'; const noop = () => {}; +/** Nudge playhead slightly before true duration so the custom cursor (CSS) stays visible at end. */ +const FINISH_END_EPSILON_SEC = 0.005; + export interface IMarker { time: number; label?: string; @@ -169,9 +172,15 @@ export function useWaveSurfer( if (loadingRef.current) return; const ws = wavesurferRef.current; - const t = + let t = ws != null ? roundTime(ws.getCurrentTime()) : roundTime(currentTime); + const duration = durationRef.current || 0; + if (duration > 0) { + if (t < 0) t = 0; + else if (t > duration) t = duration; + } + setProgress(t); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -339,7 +348,17 @@ export function useWaveSurfer( }); wavesurfer.on('finish', function () { - if (playingRef.current && !loopingRef.current) setPlaying(false); + if (playingRef.current && !loopingRef.current) { + const duration = durationRef.current || 0; + if (duration > 0) { + const safeEnd = Math.max( + 0, + roundTime(duration - FINISH_END_EPSILON_SEC) + ); + void wsGoto(safeEnd); + } + setPlaying(false); + } }); wavesurfer.on('interaction', function (/*newTime: number*/) { onInteraction(); From 3bb0e2ddcbc14f6a87a69624abcd7a5ce989241d Mon Sep 17 00:00:00 2001 From: Greg Trihus Date: Tue, 5 May 2026 17:56:13 -0500 Subject: [PATCH 2/2] clamp seek [0, duration] and nudge play back so it is visible. proposed by devin --- src/renderer/src/crud/useWaveSurfer.tsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/renderer/src/crud/useWaveSurfer.tsx b/src/renderer/src/crud/useWaveSurfer.tsx index 519c9452..1363bb64 100644 --- a/src/renderer/src/crud/useWaveSurfer.tsx +++ b/src/renderer/src/crud/useWaveSurfer.tsx @@ -164,6 +164,8 @@ export function useWaveSurfer( }; const roundTime = (n: number) => Math.round(n * 100000) / 100000; + const clamp = (n: number, min: number, max: number) => + Math.min(Math.max(n, min), max); useEffect(() => { // Ignore updates while loading (previous clip). Prefer getCurrentTime() over @@ -176,10 +178,7 @@ export function useWaveSurfer( ws != null ? roundTime(ws.getCurrentTime()) : roundTime(currentTime); const duration = durationRef.current || 0; - if (duration > 0) { - if (t < 0) t = 0; - else if (t > duration) t = duration; - } + if (duration > 0) t = clamp(t, 0, duration); setProgress(t); @@ -194,10 +193,9 @@ export function useWaveSurfer( const wsGoto = async (position: number, keepPlayRegion: boolean = false) => { if (!keepPlayRegion) resetPlayingRegion(); - let pos = position; const duration = wsDuration(); - if (pos > duration) pos = duration; - if (pos < 0) pos = 0; + const pos = + duration > 0 ? clamp(position, 0, duration) : Math.max(position, 0); onRegionGoTo(pos); if (pos === duration && isPlayingRef.current) { //if playing, position messages come in after this one that set it back to previously playing position. Turn this off first in hopes that all messages are done before we set the position... @@ -347,7 +345,7 @@ export function useWaveSurfer( wavesurferRef.current = null; }); - wavesurfer.on('finish', function () { + wavesurfer.on('finish', async function () { if (playingRef.current && !loopingRef.current) { const duration = durationRef.current || 0; if (duration > 0) { @@ -355,7 +353,11 @@ export function useWaveSurfer( 0, roundTime(duration - FINISH_END_EPSILON_SEC) ); - void wsGoto(safeEnd); + try { + await wsGoto(safeEnd); + } catch (error: any) { + logError(Severity.error, errorReporter, error); + } } setPlaying(false); }