fix slider

This commit is contained in:
2025-10-21 14:25:07 +02:00
parent 837a634997
commit d04855fb8d
4 changed files with 64 additions and 18 deletions
+20 -14
View File
@@ -215,7 +215,7 @@ const PlayerProvider = ({ children }) => {
const [error, setError] = useState(null); const [error, setError] = useState(null);
const autoPlayRef = useRef(false); const autoPlayRef = useRef(false);
const pendingSeekSecondsRef = useRef(null); const pendingSeekValueRef = useRef(null);
const source = useMemo(() => { const source = useMemo(() => {
if (!currentTrack?.source) return null; if (!currentTrack?.source) return null;
@@ -228,6 +228,11 @@ const PlayerProvider = ({ children }) => {
? HIDDEN_ROUTE_NAMES.has(activeRouteName) ? HIDDEN_ROUTE_NAMES.has(activeRouteName)
: false; : false;
const toPlayerSeekValue = useCallback((milliseconds) => {
const ms = Math.max(0, Number(milliseconds) || 0);
return Platform.OS === "web" ? ms : ms / 1000;
}, []);
useEffect(() => { useEffect(() => {
if (!status) return; if (!status) return;
@@ -269,8 +274,8 @@ const PlayerProvider = ({ children }) => {
const run = async () => { const run = async () => {
try { try {
const pendingSeek = pendingSeekSecondsRef.current; const pendingSeek = pendingSeekValueRef.current;
pendingSeekSecondsRef.current = null; pendingSeekValueRef.current = null;
if (typeof pendingSeek === "number" && pendingSeek >= 0) { if (typeof pendingSeek === "number" && pendingSeek >= 0) {
await player.seekTo?.(pendingSeek); await player.seekTo?.(pendingSeek);
@@ -305,7 +310,7 @@ const PlayerProvider = ({ children }) => {
: typeof options?.positionMs === "number" : typeof options?.positionMs === "number"
? options.positionMs ? options.positionMs
: 0; : 0;
const targetSeconds = Math.max(0, targetPositionMs) / 1000; const targetSeekValue = toPlayerSeekValue(targetPositionMs);
const shouldAutoPlay = options?.autoPlay !== false; const shouldAutoPlay = options?.autoPlay !== false;
setError(null); setError(null);
@@ -313,8 +318,8 @@ const PlayerProvider = ({ children }) => {
if (sameTrack) { if (sameTrack) {
setCurrentTrack((prev) => ({ ...prev, ...normalized })); setCurrentTrack((prev) => ({ ...prev, ...normalized }));
try { try {
if (targetSeconds > 0) { if (targetPositionMs > 0) {
await player?.seekTo?.(targetSeconds); await player?.seekTo?.(targetSeekValue);
} }
if (shouldAutoPlay) { if (shouldAutoPlay) {
await player?.play?.(); await player?.play?.();
@@ -342,7 +347,8 @@ const PlayerProvider = ({ children }) => {
} }
autoPlayRef.current = shouldAutoPlay; autoPlayRef.current = shouldAutoPlay;
pendingSeekSecondsRef.current = targetSeconds > 0 ? targetSeconds : null; pendingSeekValueRef.current =
targetPositionMs > 0 ? targetSeekValue : null;
setPlayback((prev) => ({ setPlayback((prev) => ({
...prev, ...prev,
@@ -352,7 +358,7 @@ const PlayerProvider = ({ children }) => {
})); }));
setCurrentTrack(normalized); setCurrentTrack(normalized);
}, },
[currentTrack?.id, player] [currentTrack?.id, player, toPlayerSeekValue]
); );
const resume = useCallback(async () => { const resume = useCallback(async () => {
@@ -367,7 +373,7 @@ const PlayerProvider = ({ children }) => {
const pause = useCallback(async () => { const pause = useCallback(async () => {
try { try {
autoPlayRef.current = false; autoPlayRef.current = false;
pendingSeekSecondsRef.current = null; pendingSeekValueRef.current = null;
await player?.pause?.(); await player?.pause?.();
} catch (err) { } catch (err) {
setError(err); setError(err);
@@ -405,19 +411,19 @@ const PlayerProvider = ({ children }) => {
async (positionMs) => { async (positionMs) => {
if (!player) return; if (!player) return;
const bounded = Math.max(0, Number(positionMs) || 0); const bounded = Math.max(0, Number(positionMs) || 0);
const seconds = bounded / 1000; const seekValue = toPlayerSeekValue(bounded);
try { try {
if (status?.isLoaded) { if (status?.isLoaded) {
await player.seekTo?.(seconds); await player.seekTo?.(seekValue);
} else { } else {
pendingSeekSecondsRef.current = seconds; pendingSeekValueRef.current = seekValue;
} }
} catch (err) { } catch (err) {
setError(err); setError(err);
} }
}, },
[player, status?.isLoaded] [player, status?.isLoaded, toPlayerSeekValue]
); );
const seekBy = useCallback( const seekBy = useCallback(
@@ -431,7 +437,7 @@ const PlayerProvider = ({ children }) => {
const stop = useCallback(async () => { const stop = useCallback(async () => {
try { try {
autoPlayRef.current = false; autoPlayRef.current = false;
pendingSeekSecondsRef.current = null; pendingSeekValueRef.current = null;
await player?.pause?.(); await player?.pause?.();
} catch (err) { } catch (err) {
setError(err); setError(err);
+42 -2
View File
@@ -55,6 +55,7 @@ const MusicDetails = ({ route }) => {
const [fav, setFav] = useState(false); const [fav, setFav] = useState(false);
const [currentUID] = useGlobal("currentUID"); const [currentUID] = useGlobal("currentUID");
const wasPlayingBeforeSeek = React.useRef(false); const wasPlayingBeforeSeek = React.useRef(false);
const lastSeekTargetMs = React.useRef(null);
const listenedMsRef = React.useRef(0); const listenedMsRef = React.useRef(0);
const incrementDoneRef = React.useRef(false); const incrementDoneRef = React.useRef(false);
const timerRef = React.useRef(null); const timerRef = React.useRef(null);
@@ -220,6 +221,13 @@ const MusicDetails = ({ route }) => {
const handleSliderSeekStart = useCallback(async () => { const handleSliderSeekStart = useCallback(async () => {
if (!trackDescriptor) return; if (!trackDescriptor) return;
try { try {
console.log("[MusicDetails.web] handleSliderSeekStart", {
isCurrentTrack,
isTrackPlaying,
positionMs,
durationMs,
});
lastSeekTargetMs.current = null;
wasPlayingBeforeSeek.current = isTrackPlaying; wasPlayingBeforeSeek.current = isTrackPlaying;
if (!isCurrentTrack) { if (!isCurrentTrack) {
await ensureLoaded({ await ensureLoaded({
@@ -240,6 +248,8 @@ const MusicDetails = ({ route }) => {
ensureLoaded, ensureLoaded,
positionMs, positionMs,
pauseTrack, pauseTrack,
lastSeekTargetMs,
durationMs,
]); ]);
const handleSliderSeek = useCallback( const handleSliderSeek = useCallback(
@@ -247,6 +257,13 @@ const MusicDetails = ({ route }) => {
const dur = durationMs || 0; const dur = durationMs || 0;
if (!trackDescriptor || dur <= 0) return; if (!trackDescriptor || dur <= 0) return;
const targetMs = Math.max(0, Math.floor(dur * ratio)); const targetMs = Math.max(0, Math.floor(dur * ratio));
lastSeekTargetMs.current = targetMs;
console.log("[MusicDetails.web] handleSliderSeek", {
ratio,
durationMs: dur,
targetMs,
isCurrentTrack,
});
try { try {
if (!isCurrentTrack) { if (!isCurrentTrack) {
await ensureLoaded({ startPositionMs: targetMs, autoPlay: false }); await ensureLoaded({ startPositionMs: targetMs, autoPlay: false });
@@ -261,14 +278,30 @@ const MusicDetails = ({ route }) => {
); );
const handleSliderSeekEnd = useCallback(async () => { 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 { try {
if (wasPlayingBeforeSeek.current) { if (wasPlayingBeforeSeek.current) {
if (!isCurrentTrack) { if (!isCurrentTrack) {
await ensureLoaded({ await ensureLoaded({
startPositionMs: positionMs, startPositionMs:
targetMs !== null && Number.isFinite(targetMs)
? targetMs
: positionMs,
autoPlay: true, autoPlay: true,
}); });
} else { } else {
if (targetMs !== null && Number.isFinite(targetMs)) {
await seekTrackTo(targetMs);
}
await resumeTrack(); await resumeTrack();
} }
} }
@@ -276,8 +309,15 @@ const MusicDetails = ({ route }) => {
console.log("MusicDetails seek end error", e?.message); console.log("MusicDetails seek end error", e?.message);
} finally { } finally {
wasPlayingBeforeSeek.current = false; wasPlayingBeforeSeek.current = false;
lastSeekTargetMs.current = null;
} }
}, [ensureLoaded, isCurrentTrack, positionMs, resumeTrack]); }, [
ensureLoaded,
isCurrentTrack,
positionMs,
resumeTrack,
seekTrackTo,
]);
const handleSeekBySeconds = useCallback( const handleSeekBySeconds = useCallback(
async (deltaSeconds) => { async (deltaSeconds) => {
+1 -1
View File
@@ -19,7 +19,7 @@ const EmotionConvey = ({
return ( return (
<View style={{ flex: 1, gap: 10, marginTop: 16 }}> <View style={{ flex: 1, gap: 10, marginTop: 16 }}>
<CreateLyricsHeader <CreateLyricsHeader
title={`Étape 3: Quelle émotion veux-tu\ntransmettre ?`} title={`Quelle émotion veux-tu\ntransmettre ?`}
subTitle="Sélectionne une seule intention émotionnelle." subTitle="Sélectionne une seule intention émotionnelle."
/> />
+1 -1
View File
@@ -39,7 +39,7 @@ const Goals = ({
<ScrollView contentContainerStyle={{ flex: 1, gap: 16, marginTop: 16 }}> <ScrollView contentContainerStyle={{ flex: 1, gap: 16, marginTop: 16 }}>
<View style={{ gap: 10 }}> <View style={{ gap: 10 }}>
<CreateLyricsHeader <CreateLyricsHeader
title="Étape 2: Quel est le contexte ?" title="Quel est le contexte ?"
subTitle="Besoin d'idées ? Pense à un anniversaire, une équipe de sport ou ton entreprise." subTitle="Besoin d'idées ? Pense à un anniversaire, une équipe de sport ou ton entreprise."
/> />
<ItemContainer> <ItemContainer>