From d04855fb8df2c749e0e9e30359b7bd5e50af1ffb Mon Sep 17 00:00:00 2001 From: leon-morival Date: Tue, 21 Oct 2025 14:25:07 +0200 Subject: [PATCH] fix slider --- src/providers/PlayerProvider.js | 34 +++++++++++-------- src/screens/Library/MusicDetails.web.js | 44 +++++++++++++++++++++++-- src/screens/Writing/EmotionConvey.js | 2 +- src/screens/Writing/Goals.js | 2 +- 4 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/providers/PlayerProvider.js b/src/providers/PlayerProvider.js index e9d7687..8d802e2 100644 --- a/src/providers/PlayerProvider.js +++ b/src/providers/PlayerProvider.js @@ -215,7 +215,7 @@ const PlayerProvider = ({ children }) => { const [error, setError] = useState(null); const autoPlayRef = useRef(false); - const pendingSeekSecondsRef = useRef(null); + const pendingSeekValueRef = useRef(null); const source = useMemo(() => { if (!currentTrack?.source) return null; @@ -228,6 +228,11 @@ const PlayerProvider = ({ children }) => { ? HIDDEN_ROUTE_NAMES.has(activeRouteName) : false; + const toPlayerSeekValue = useCallback((milliseconds) => { + const ms = Math.max(0, Number(milliseconds) || 0); + return Platform.OS === "web" ? ms : ms / 1000; + }, []); + useEffect(() => { if (!status) return; @@ -269,8 +274,8 @@ const PlayerProvider = ({ children }) => { const run = async () => { try { - const pendingSeek = pendingSeekSecondsRef.current; - pendingSeekSecondsRef.current = null; + const pendingSeek = pendingSeekValueRef.current; + pendingSeekValueRef.current = null; if (typeof pendingSeek === "number" && pendingSeek >= 0) { await player.seekTo?.(pendingSeek); @@ -305,7 +310,7 @@ const PlayerProvider = ({ children }) => { : typeof options?.positionMs === "number" ? options.positionMs : 0; - const targetSeconds = Math.max(0, targetPositionMs) / 1000; + const targetSeekValue = toPlayerSeekValue(targetPositionMs); const shouldAutoPlay = options?.autoPlay !== false; setError(null); @@ -313,8 +318,8 @@ const PlayerProvider = ({ children }) => { if (sameTrack) { setCurrentTrack((prev) => ({ ...prev, ...normalized })); try { - if (targetSeconds > 0) { - await player?.seekTo?.(targetSeconds); + if (targetPositionMs > 0) { + await player?.seekTo?.(targetSeekValue); } if (shouldAutoPlay) { await player?.play?.(); @@ -342,7 +347,8 @@ const PlayerProvider = ({ children }) => { } autoPlayRef.current = shouldAutoPlay; - pendingSeekSecondsRef.current = targetSeconds > 0 ? targetSeconds : null; + pendingSeekValueRef.current = + targetPositionMs > 0 ? targetSeekValue : null; setPlayback((prev) => ({ ...prev, @@ -352,7 +358,7 @@ const PlayerProvider = ({ children }) => { })); setCurrentTrack(normalized); }, - [currentTrack?.id, player] + [currentTrack?.id, player, toPlayerSeekValue] ); const resume = useCallback(async () => { @@ -367,7 +373,7 @@ const PlayerProvider = ({ children }) => { const pause = useCallback(async () => { try { autoPlayRef.current = false; - pendingSeekSecondsRef.current = null; + pendingSeekValueRef.current = null; await player?.pause?.(); } catch (err) { setError(err); @@ -405,19 +411,19 @@ const PlayerProvider = ({ children }) => { async (positionMs) => { if (!player) return; const bounded = Math.max(0, Number(positionMs) || 0); - const seconds = bounded / 1000; + const seekValue = toPlayerSeekValue(bounded); try { if (status?.isLoaded) { - await player.seekTo?.(seconds); + await player.seekTo?.(seekValue); } else { - pendingSeekSecondsRef.current = seconds; + pendingSeekValueRef.current = seekValue; } } catch (err) { setError(err); } }, - [player, status?.isLoaded] + [player, status?.isLoaded, toPlayerSeekValue] ); const seekBy = useCallback( @@ -431,7 +437,7 @@ const PlayerProvider = ({ children }) => { const stop = useCallback(async () => { try { autoPlayRef.current = false; - pendingSeekSecondsRef.current = null; + pendingSeekValueRef.current = null; await player?.pause?.(); } catch (err) { setError(err); diff --git a/src/screens/Library/MusicDetails.web.js b/src/screens/Library/MusicDetails.web.js index b1a6435..ca486f1 100644 --- a/src/screens/Library/MusicDetails.web.js +++ b/src/screens/Library/MusicDetails.web.js @@ -55,6 +55,7 @@ const MusicDetails = ({ route }) => { const [fav, setFav] = useState(false); const [currentUID] = useGlobal("currentUID"); const wasPlayingBeforeSeek = React.useRef(false); + const lastSeekTargetMs = React.useRef(null); const listenedMsRef = React.useRef(0); const incrementDoneRef = React.useRef(false); const timerRef = React.useRef(null); @@ -220,6 +221,13 @@ const MusicDetails = ({ route }) => { const handleSliderSeekStart = useCallback(async () => { if (!trackDescriptor) return; try { + console.log("[MusicDetails.web] handleSliderSeekStart", { + isCurrentTrack, + isTrackPlaying, + positionMs, + durationMs, + }); + lastSeekTargetMs.current = null; wasPlayingBeforeSeek.current = isTrackPlaying; if (!isCurrentTrack) { await ensureLoaded({ @@ -240,6 +248,8 @@ const MusicDetails = ({ route }) => { ensureLoaded, positionMs, pauseTrack, + lastSeekTargetMs, + durationMs, ]); const handleSliderSeek = useCallback( @@ -247,6 +257,13 @@ const MusicDetails = ({ route }) => { const dur = durationMs || 0; if (!trackDescriptor || dur <= 0) return; const targetMs = Math.max(0, Math.floor(dur * ratio)); + lastSeekTargetMs.current = targetMs; + console.log("[MusicDetails.web] handleSliderSeek", { + ratio, + durationMs: dur, + targetMs, + isCurrentTrack, + }); try { if (!isCurrentTrack) { await ensureLoaded({ startPositionMs: targetMs, autoPlay: false }); @@ -261,14 +278,30 @@ const MusicDetails = ({ route }) => { ); const handleSliderSeekEnd = useCallback(async () => { + const targetMs = + typeof lastSeekTargetMs.current === "number" + ? Math.max(0, lastSeekTargetMs.current) + : null; + console.log("[MusicDetails.web] handleSliderSeekEnd", { + targetMs, + wasPlayingBeforeSeek: wasPlayingBeforeSeek.current, + isCurrentTrack, + positionMs, + }); try { if (wasPlayingBeforeSeek.current) { if (!isCurrentTrack) { await ensureLoaded({ - startPositionMs: positionMs, + startPositionMs: + targetMs !== null && Number.isFinite(targetMs) + ? targetMs + : positionMs, autoPlay: true, }); } else { + if (targetMs !== null && Number.isFinite(targetMs)) { + await seekTrackTo(targetMs); + } await resumeTrack(); } } @@ -276,8 +309,15 @@ const MusicDetails = ({ route }) => { console.log("MusicDetails seek end error", e?.message); } finally { wasPlayingBeforeSeek.current = false; + lastSeekTargetMs.current = null; } - }, [ensureLoaded, isCurrentTrack, positionMs, resumeTrack]); + }, [ + ensureLoaded, + isCurrentTrack, + positionMs, + resumeTrack, + seekTrackTo, + ]); const handleSeekBySeconds = useCallback( async (deltaSeconds) => { diff --git a/src/screens/Writing/EmotionConvey.js b/src/screens/Writing/EmotionConvey.js index 0aa593c..86b2b63 100644 --- a/src/screens/Writing/EmotionConvey.js +++ b/src/screens/Writing/EmotionConvey.js @@ -19,7 +19,7 @@ const EmotionConvey = ({ return ( diff --git a/src/screens/Writing/Goals.js b/src/screens/Writing/Goals.js index 16164a9..1357015 100644 --- a/src/screens/Writing/Goals.js +++ b/src/screens/Writing/Goals.js @@ -39,7 +39,7 @@ const Goals = ({