This commit is contained in:
2025-09-03 11:00:46 +02:00
parent 50dba49808
commit ade2d6ef9d
2 changed files with 95 additions and 39 deletions
+1 -14
View File
@@ -15,24 +15,11 @@ const Playback = ({ route }) => {
const { project } = route.params;
const projectId = project?.id;
const songIndex = project?.songIndex;
console.log("sonindex", songIndex);
const sunoTaskId = project?.sunoTaskId;
const { setIsLoading } = useMinuit();
// console.log("musicTimestamps avec songIndex:", {
// // Accès avec la clé dot notation
// musicTimeStamps: project?.[`musicTimestamps.${songIndex}`],
// // Toutes les clés qui commencent par musicTimestamps
// });
const onPressRecord = useCallback(async () => {
try {
console.log(
"project",
songIndex,
"project id",
projectId,
"sunoTaskId",
sunoTaskId
);
if (!projectId || songIndex === undefined || !sunoTaskId) {
return;
// return navigate(Routes.RecordPlayback, { project });
+84 -15
View File
@@ -1,7 +1,13 @@
import { useFocusEffect } from "@react-navigation/native";
import { useAudioPlayer } from "expo-audio";
import { CameraView, useCameraPermissions } from "expo-camera";
import React, { useCallback, useEffect, useRef, useState } from "react";
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { Text, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import Svg, { Circle } from "react-native-svg";
@@ -14,20 +20,13 @@ import { gutters, Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
/**
* RecordPlayback — refactor robuste du compteur
*
* Correction de l'auto-start : on garde un flag countdownActiveRef pour
* empêcher l'effet de se déclencher tant que le timer n'a pas réellement démarré.
* On affiche 5→1 puis on bascule (pas de 0 visible) pour éviter le "bloqué sur 1".
*/
const TIME_BEFORE_INCREMENT_MS = 20000; // 20s
const RecordPlayback = ({ route }) => {
const { top, bottom } = useSafeAreaInsets();
const { project } = route.params || {};
const projectId = project?.id;
const songIndex = project?.songIndex;
// Permissions
const [cameraPermission, requestCameraPermission] = useCameraPermissions();
@@ -55,6 +54,22 @@ const RecordPlayback = ({ route }) => {
const songUrl = project?.songUrl || null;
const player = useAudioPlayer(songUrl ? { uri: songUrl } : undefined);
const musicIndex = useMemo(() => {
const i = Number(songIndex);
return Number.isFinite(i) && i >= 0 ? i : 0;
}, [songIndex]);
const alignedWords = useMemo(() => {
const ts = project?.[`musicTimestamps.${songIndex}`];
null;
const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : [];
return arr.map((w) => ({
word: String(w?.word ?? "").replace(/\n/g, " "),
startS: Number(w?.startS ?? 0),
endS: Number(w?.endS ?? 0),
}));
}, [project?.musicTimestamps, musicIndex]);
// console.log("alignedWords:", alignedWords);
useEffect(() => {
listenedMsRef.current = 0;
incrementDoneRef.current = false;
@@ -73,6 +88,19 @@ const RecordPlayback = ({ route }) => {
return () => clearInterval(id);
}, [player]);
// Compute current word index from playback time
const currentTimeS = (progressInfo?.pos || 0) / 1000;
const currentIdx = useMemo(() => {
if (!alignedWords || alignedWords.length === 0) return -1;
for (let i = 0; i < alignedWords.length; i++) {
const w = alignedWords[i];
if (currentTimeS >= w.startS && currentTimeS <= w.endS) return i;
}
if (currentTimeS > (alignedWords[alignedWords.length - 1]?.endS || 0))
return alignedWords.length - 1;
return -1;
}, [alignedWords, currentTimeS]);
// Permissions au mount + cleanup
useEffect(() => {
(async () => {
@@ -408,14 +436,14 @@ const RecordPlayback = ({ route }) => {
position: "absolute",
left: 0,
right: 0,
bottom: bottom + 100,
bottom: bottom + 130,
paddingHorizontal: gutters,
}}
>
<CreateLyricsHeader
// disableBlur={Platform.OS !== "ios"}
// containerStyle={{ backgroundColor: Palette.ultraLightBlack }}
>
<CreateLyricsHeader>
{(isRecording || showProgress) && alignedWords?.length > 0 ? (
<KaraokeLine words={alignedWords} currentIdx={currentIdx} />
) : (
<Text
style={{
fontSize: 16,
@@ -426,6 +454,7 @@ const RecordPlayback = ({ route }) => {
L'enregistrement de ta vidéo commencera lorsque tu lanceras ta
musique, et s'arrêtera à la fin du morceau.
</Text>
)}
</CreateLyricsHeader>
</View>
</View>
@@ -464,3 +493,43 @@ const ProgressRing = ({ size = 50, strokeWidth = 12, progress = 0 }) => {
};
export default RecordPlayback;
// Simple karaoke line renderer
const KaraokeLine = ({ words = [], currentIdx = -1 }) => {
const windowSize = 8;
const start = Math.max(0, currentIdx - 2);
const end = Math.min(
words.length,
currentIdx >= 0 ? currentIdx + windowSize : windowSize
);
const slice = words.slice(start, end);
return (
<Text
style={{
color: Palette.white,
fontSize: 18,
lineHeight: 24,
textAlign: "center",
}}
>
{slice.map((w, i) => {
const idx = start + i;
const text = String(w.word || "").replace(/\s+/g, " ");
const isCurrent = idx === currentIdx;
return (
<Text
key={`${idx}-${text}`}
style={{
color: isCurrent ? Palette.white : "#FFFFFFAA",
fontFamily: isCurrent
? FONT_FAMILY.InterSemiBold
: FONT_FAMILY.InterMedium,
}}
>
{text + " "}
</Text>
);
})}
</Text>
);
};