clear last tickets
This commit is contained in:
@@ -67,7 +67,7 @@ const SongReady = () => {
|
||||
} catch (error) {
|
||||
console.log("SongReady pause error", error?.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
await Promise.all(tasks);
|
||||
}, []);
|
||||
@@ -95,15 +95,15 @@ const SongReady = () => {
|
||||
console.log("SongReady play error", error?.message);
|
||||
}
|
||||
},
|
||||
[pauseAllExcept]
|
||||
[pauseAllExcept],
|
||||
);
|
||||
|
||||
// Sync URLs from provider's selectedProject
|
||||
useEffect(() => {
|
||||
const urls = Array.isArray(selectedProject?.musicUrls)
|
||||
? selectedProject.musicUrls
|
||||
.filter((url) => typeof url === "string" && url.trim())
|
||||
.map((url) => url.trim())
|
||||
.filter((url) => typeof url === "string" && url.trim())
|
||||
.map((url) => url.trim())
|
||||
: [];
|
||||
setMusicUrls(urls);
|
||||
setSelectedIndex((prev) => {
|
||||
@@ -150,7 +150,7 @@ const SongReady = () => {
|
||||
return () => {
|
||||
pauseAllPlayers();
|
||||
};
|
||||
}, [pauseAllPlayers])
|
||||
}, [pauseAllPlayers]),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -177,7 +177,7 @@ const SongReady = () => {
|
||||
},
|
||||
},
|
||||
],
|
||||
{ cancelable: false }
|
||||
{ cancelable: false },
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ const SongReady = () => {
|
||||
setShowRegenerateModal(false);
|
||||
try {
|
||||
await pauseAllPlayers();
|
||||
} catch {}
|
||||
} catch { }
|
||||
navigate(Routes.Lyrics);
|
||||
};
|
||||
|
||||
@@ -207,38 +207,36 @@ const SongReady = () => {
|
||||
|
||||
alert(
|
||||
"Re-générer le morceau",
|
||||
(
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
alignItems: "center",
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<Text style={descriptionTextStyle}>
|
||||
{`Tu vas pouvoir modifier tes choix pour re-générer ${SONG_OPTIONS_PER_GENERATION} nouveaux morceaux.`}
|
||||
</Text>
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: 12,
|
||||
justifyContent: "center",
|
||||
flexWrap: "wrap",
|
||||
gap: 6,
|
||||
}}
|
||||
>
|
||||
<Text style={descriptionTextStyle}>
|
||||
{`Tu vas pouvoir modifier tes choix pour re-générer ${SONG_OPTIONS_PER_GENERATION} nouveaux morceaux.`}
|
||||
</Text>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexWrap: "wrap",
|
||||
gap: 6,
|
||||
}}
|
||||
>
|
||||
<Text style={descriptionTextStyle}>Cette action coûte</Text>
|
||||
<CreditAmount
|
||||
value={MUSIC_GENERATION_COIN_COST}
|
||||
iconSize={18}
|
||||
textStyle={amountTextStyle}
|
||||
/>
|
||||
</View>
|
||||
<Text style={descriptionTextStyle}>
|
||||
Les crédits seront utilisés lors de l'étape de génération.
|
||||
</Text>
|
||||
<Text style={descriptionTextStyle}>Cette action coûte</Text>
|
||||
<CreditAmount
|
||||
value={MUSIC_GENERATION_COIN_COST}
|
||||
iconSize={18}
|
||||
textStyle={amountTextStyle}
|
||||
/>
|
||||
</View>
|
||||
),
|
||||
<Text style={descriptionTextStyle}>
|
||||
Les crédits seront utilisés lors de l'étape de génération.
|
||||
</Text>
|
||||
</View>,
|
||||
[
|
||||
{
|
||||
text: "Annuler",
|
||||
@@ -250,7 +248,7 @@ const SongReady = () => {
|
||||
onPress: () => handleConfirmRegenerate(),
|
||||
},
|
||||
],
|
||||
{ cancelable: true }
|
||||
{ cancelable: true },
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -263,7 +261,7 @@ const SongReady = () => {
|
||||
onPressBack={async () => {
|
||||
try {
|
||||
await pauseAllPlayers();
|
||||
} catch {}
|
||||
} catch { }
|
||||
navigate(Routes.Home);
|
||||
}}
|
||||
progress={63}
|
||||
@@ -360,6 +358,7 @@ const SongOptionCard = ({
|
||||
|
||||
const [progressInfo, setProgressInfo] = useState({ pos: 0, dur: 0 });
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
const shouldResumeAfterSeekRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
registerPlayer(index, player);
|
||||
@@ -387,11 +386,11 @@ const SongOptionCard = ({
|
||||
const id = setInterval(() => {
|
||||
const durationMs = Math.max(
|
||||
0,
|
||||
Math.round((Number(player.duration) || 0) * 1000)
|
||||
Math.round((Number(player.duration) || 0) * 1000),
|
||||
);
|
||||
const positionMs = Math.max(
|
||||
0,
|
||||
Math.round((Number(player.currentTime) || 0) * 1000)
|
||||
Math.round((Number(player.currentTime) || 0) * 1000),
|
||||
);
|
||||
setProgressInfo((prev) => {
|
||||
if (
|
||||
@@ -413,35 +412,16 @@ const SongOptionCard = ({
|
||||
return () => clearInterval(id);
|
||||
}, [player]);
|
||||
|
||||
const handleSeek = async (targetMs) => {
|
||||
if (!player || !progressInfo?.dur) return;
|
||||
const dur = progressInfo.dur || 0;
|
||||
const pos = Math.max(0, Math.min(dur, Math.floor(targetMs)));
|
||||
try {
|
||||
await player.seekTo?.(Math.floor(pos / 1000));
|
||||
setProgressInfo((prev) => ({ ...prev, pos }));
|
||||
} catch (error) {
|
||||
console.log("SongReady seek error", error?.message);
|
||||
}
|
||||
};
|
||||
const hasCapturedSeekStateRef = useRef(false);
|
||||
|
||||
const handleSeekStart = () => {
|
||||
onSelect(index);
|
||||
};
|
||||
|
||||
const pauseDuringSeek = async () => {
|
||||
const resumePlaybackIfNeeded = useCallback(async () => {
|
||||
if (!player) return;
|
||||
try {
|
||||
if (player.playing) {
|
||||
await player.pause?.();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("SongReady pause on seek start", error?.message);
|
||||
}
|
||||
};
|
||||
const shouldResume = shouldResumeAfterSeekRef.current;
|
||||
shouldResumeAfterSeekRef.current = false;
|
||||
hasCapturedSeekStateRef.current = false; // Reset capture flag
|
||||
|
||||
if (!shouldResume) return;
|
||||
|
||||
const resumeAfterSeek = async () => {
|
||||
if (!player) return;
|
||||
try {
|
||||
if (player.resume) {
|
||||
await player.resume?.();
|
||||
@@ -451,7 +431,48 @@ const SongOptionCard = ({
|
||||
} catch (error) {
|
||||
console.log("SongReady resume after seek", error?.message);
|
||||
}
|
||||
};
|
||||
}, [player]);
|
||||
|
||||
const handleSeek = useCallback(
|
||||
async (targetMs) => {
|
||||
if (!player || !progressInfo?.dur) {
|
||||
return;
|
||||
}
|
||||
const dur = progressInfo.dur || 0;
|
||||
const pos = Math.max(0, Math.min(dur, Math.floor(targetMs)));
|
||||
|
||||
// Mise à jour visuelle immédiate
|
||||
setProgressInfo((prev) => ({ ...prev, pos }));
|
||||
|
||||
try {
|
||||
await player.seekTo?.(Math.floor(pos / 1000));
|
||||
} catch (error) {
|
||||
console.log("SongReady seek error", error?.message);
|
||||
}
|
||||
},
|
||||
[player, progressInfo?.dur],
|
||||
);
|
||||
|
||||
const handleSeekStart = useCallback(async () => {
|
||||
onSelect(index);
|
||||
if (!player) return;
|
||||
|
||||
const isCurrentlyPlaying = !!player.playing || isPlaying;
|
||||
|
||||
// Only capture state if we haven't already for this drag interaction
|
||||
if (!hasCapturedSeekStateRef.current) {
|
||||
hasCapturedSeekStateRef.current = true;
|
||||
shouldResumeAfterSeekRef.current = isCurrentlyPlaying;
|
||||
}
|
||||
|
||||
try {
|
||||
if (isCurrentlyPlaying) {
|
||||
await player.pause?.();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("SongReady pause on seek start", error?.message);
|
||||
}
|
||||
}, [index, isPlaying, onSelect, player]);
|
||||
|
||||
const handleToggle = () => {
|
||||
onSelect(index);
|
||||
@@ -510,8 +531,7 @@ const SongOptionCard = ({
|
||||
isPlaying={isPlaying}
|
||||
onSeekStart={handleSeekStart}
|
||||
onSeek={handleSeek}
|
||||
onPause={pauseDuringSeek}
|
||||
onPlay={resumeAfterSeek}
|
||||
onSeekEnd={resumePlaybackIfNeeded}
|
||||
disabled={!url}
|
||||
/>
|
||||
</View>
|
||||
@@ -557,7 +577,7 @@ const RegenerateModal = ({ visible, onClose, onConfirm }) => {
|
||||
const horizontalPadding = Math.max(isCompactWidth ? 16 : gutters, 12);
|
||||
const verticalPadding = Math.max(
|
||||
isCompactWidth ? gutters : gutters * 1.5,
|
||||
12
|
||||
12,
|
||||
);
|
||||
const availableWidth = Math.max(width - horizontalPadding * 2, 0);
|
||||
const contentWidth =
|
||||
|
||||
Reference in New Issue
Block a user