fix slider
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user