get music timestamps
This commit is contained in:
@@ -42,12 +42,6 @@ jspm_packages/
|
|||||||
# Firebase
|
# Firebase
|
||||||
.firebase/
|
.firebase/
|
||||||
|
|
||||||
# Service account key
|
|
||||||
serviceAccountKey.json
|
|
||||||
|
|
||||||
# API keys
|
|
||||||
config/keys.js
|
|
||||||
|
|
||||||
# Build files
|
# Build files
|
||||||
dist/
|
dist/
|
||||||
build/
|
build/
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
exports.GEMINI_API_KEY = "AIzaSyBoPQC5ZaMKP73TlKGpZQp1mAw8ArHiH9Y";
|
||||||
|
// exports.SUNO_API_KEY = "543b5650b30d93e98d8046a830244c80"; client api key
|
||||||
|
exports.SUNO_API_KEY = "138bace8405b869f917156440acb6fed"; // perso api key
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"type": "service_account",
|
||||||
|
"project_id": "musicland-d33f9",
|
||||||
|
"private_key_id": "c1110a2aa31eb3ac7cf42d931249a2572bf68e37",
|
||||||
|
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZKlW0nTIg4Il2\nPtr/BYi247mWp8pxpCwS2ggwGBU7iO44jLQAgLWtZdHrQ7kpRfjVuceJDrkLrS82\ntkt8wQpytCFKfZjil9fdyS1hrVIQdfaPppovbRtzDpe0varA8XxgWXG8L+CQtCQd\nNhcixKONFhgOWTKB/tvEtGEExtpRRTb7y21o/EFbfpZqSbGEPcota2DPPvNh1r1y\nnhF7AcboGFTouDaTVL/oFIYYm3eWQP6nJRiM15xPqEhar+2z3lG9Y6HoRkkynFFj\nwvhQ6AUidA4A1ZW90HC33jsY5u7MAbzXY/QZ2MC82gaf26rda/7hThmk0RUSEaOv\n/G2f2lQBAgMBAAECggEAKnssdEDZQ3cjiTFbyjm9toQo2FlHdAeF1eC1PqmfUfjj\nobmcvzrzqNlBxM/uzjzDDHxPlHsJ5ewt2S3sd/iOrku5pBB70/UrgS8oMBxDU590\nOFmMEDVh1KKqfw3QC12vEoYcXoak8V2VWqjC9/i0KBCFsY0ZziZizAb/lbSVns52\nuJQhjvZURHQQOQmrZDm5mhklKCjE6qDxAMjL0yIhDQLAATzqeVPPeP8Rvq6u7yiB\noiB40OGiGHLdt28Q7IAXSQ+/Vqig7aw/qwrfZrFqgbgCYJKo1GiYFaDgRbH6GiaE\nhBJg7LtM0EaDR5G0raBWv5szqpfOb2DC6K802dcQRQKBgQDQm7HoJjmvEu9a6hxF\nVwS3rdJO67dTtxFMZM0HespQu659NT8f21QsRf/2JIcwktTnGzSeVTca0GZ4z8de\nkP9Wid0VPcA6Y3U7yplBf7Xh/5KW7/O6iSCEN03Y3/lH6vK6tBe5xCT3kfYKkrAd\n/xePLLBx++dAL5YFixMzBFfI5wKBgQC79i2S6Bcu6WQc0yykVHkAMStPz4gsAYA5\nqqCuWEwFcgEEY5AiP/oH056Hu2Z2HJHPp4OKYWSbqdxkNM214vysO0yhrF59BjQX\nyo+hwQfBqS0JfH7bJgUjNuDjP947qGtRXVo2i3FRJuZ4NmS2cGC9gT00p6rZRrbL\nJkaKSuVW1wKBgH3xsgxVn7fqd6Xs99qJOejnQbSyLUGWohP8O6jLYoAxf5xKXG0Q\nTxZXwLxLu28BBxbsXu1Ex3sh3OwNjfGzGuWVYGvllzvpNis+Gx7nStlCIq+L+Rti\nlMYeWZqZRng8CgXcmwJlwGfTsLcbbsb9bqzbLz/x9ODUmf+IwrOnaJR7AoGBALA7\nPjm6YFo8vAAGw5mEFjtm3owjMjLIaXgoEiXFZenJHUkHLNHgGEcUVFRBEe12FgST\ntFKfxFvrJFfT5ng+TdgSdWQ0oBcrJNaVtpvbx7D9NNvrHWnOOQzuXGbVsEFRROXx\n2C7CCUokZfyaS01/CkVEEqX2+spjceoBhiwN0v/bAoGBAK4sYw+3o3yjH26/M/Ni\nn5hwxofTktvAkYi7GlSFaRf2QwwxMBeA6qM/AJn7rer6pRzWwApbae/kOyfZfivq\nLnfpwloJMtds/Mm2egz0zoX7WIZ15uEx4vha2IUmi4Qz92kUzgaD1jTN8ZLUCypn\npR/zlJVkLv5BFqOtfX8shz1T\n-----END PRIVATE KEY-----\n",
|
||||||
|
"client_email": "firebase-adminsdk-fbsvc@musicland-d33f9.iam.gserviceaccount.com",
|
||||||
|
"client_id": "114560176426659117925",
|
||||||
|
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||||
|
"token_uri": "https://oauth2.googleapis.com/token",
|
||||||
|
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||||
|
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fbsvc%40musicland-d33f9.iam.gserviceaccount.com",
|
||||||
|
"universe_domain": "googleapis.com"
|
||||||
|
}
|
||||||
@@ -69,19 +69,19 @@ Pour chaque ` +
|
|||||||
.string()
|
.string()
|
||||||
.describe(
|
.describe(
|
||||||
'Type de section : "couplet" ou "refrain" ' +
|
'Type de section : "couplet" ou "refrain" ' +
|
||||||
"selon la structure",
|
"selon la structure"
|
||||||
),
|
),
|
||||||
lyrics: z
|
lyrics: z
|
||||||
.string()
|
.string()
|
||||||
.describe(
|
.describe(
|
||||||
"Paroles de la section, chaque ligne séparée " +
|
"Paroles de la section, chaque ligne séparée " +
|
||||||
"par un retour à la ligne",
|
"par un retour à la ligne"
|
||||||
),
|
),
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
.describe(
|
.describe(
|
||||||
"Paroles de la chanson sous forme de tableau de sections " +
|
"Paroles de la chanson sous forme de tableau de sections " +
|
||||||
"structurées.",
|
"structurées."
|
||||||
),
|
),
|
||||||
success: z.boolean().describe("Indique si la génération a réussi"),
|
success: z.boolean().describe("Indique si la génération a réussi"),
|
||||||
});
|
});
|
||||||
|
|||||||
+137
-12
@@ -13,6 +13,7 @@ const db = admin.firestore();
|
|||||||
const SUNO_API_BASE = "https://api.sunoapi.org";
|
const SUNO_API_BASE = "https://api.sunoapi.org";
|
||||||
const SUNO_API_PATH = "/api/v1/generate";
|
const SUNO_API_PATH = "/api/v1/generate";
|
||||||
const SUNO_STATUS_PATH = "/api/v1/generate/record-info";
|
const SUNO_STATUS_PATH = "/api/v1/generate/record-info";
|
||||||
|
const SUNO_TIMESTAMPED_LYRICS_PATH = "/api/v1/generate/get-timestamped-lyrics";
|
||||||
const SUNO_MODEL = "V4_5";
|
const SUNO_MODEL = "V4_5";
|
||||||
// const SUNO_MODEL = "V3_5";
|
// const SUNO_MODEL = "V3_5";
|
||||||
const SUNO_CALLBACK_URL =
|
const SUNO_CALLBACK_URL =
|
||||||
@@ -199,7 +200,7 @@ exports.generateMusic = onCall(async ({ data = {} }) => {
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${SUNO_API_KEY}`,
|
Authorization: `Bearer ${SUNO_API_KEY}`,
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const parsed = response.data;
|
const parsed = response.data;
|
||||||
@@ -218,7 +219,7 @@ exports.generateMusic = onCall(async ({ data = {} }) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("❌ Erreur lors de la génération de musique:", error);
|
console.error("❌ Erreur lors de la génération de musique:", error);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Erreur lors de la génération de musique: ${error.message}`,
|
`Erreur lors de la génération de musique: ${error.message}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -247,7 +248,7 @@ exports.getSunoStatus = onCall(async ({ data = {} }) => {
|
|||||||
Authorization: `Bearer ${SUNO_API_KEY}`,
|
Authorization: `Bearer ${SUNO_API_KEY}`,
|
||||||
},
|
},
|
||||||
timeout: 30000, // 30 secondes de timeout
|
timeout: 30000, // 30 secondes de timeout
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
parsed = response.data;
|
parsed = response.data;
|
||||||
|
|
||||||
@@ -324,6 +325,131 @@ exports.getSunoStatus = onCall(async ({ data = {} }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère les timestamps (aligned words) pour une génération Suno
|
||||||
|
* Attend: { taskId: string, musicIndex: number, projectId: string }
|
||||||
|
*/
|
||||||
|
exports.getSunoTimestamps = onCall(async ({ data = {} }) => {
|
||||||
|
try {
|
||||||
|
const { taskId, musicIndex, projectId } = data || {};
|
||||||
|
|
||||||
|
if (!taskId) {
|
||||||
|
throw new Error("TaskId manquant");
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = Number(musicIndex);
|
||||||
|
if (!Number.isFinite(index) || index < 0) {
|
||||||
|
throw new Error("musicIndex invalide");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!projectId || typeof projectId !== "string" || !projectId.trim()) {
|
||||||
|
throw new Error("projectId manquant ou invalide");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("🔎 Récupération des timestamps Suno", {
|
||||||
|
taskId,
|
||||||
|
musicIndex: index,
|
||||||
|
});
|
||||||
|
|
||||||
|
let response;
|
||||||
|
let parsed;
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = await axios.post(
|
||||||
|
`${SUNO_API_BASE}${SUNO_TIMESTAMPED_LYRICS_PATH}`,
|
||||||
|
{ taskId, musicIndex: index },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `Bearer ${SUNO_API_KEY}`,
|
||||||
|
},
|
||||||
|
timeout: 30000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
parsed = response.data;
|
||||||
|
console.log("📊 Réponse timestamps Suno API:", parsed?.code, parsed?.msg);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Erreur API Suno Timestamps:", {
|
||||||
|
message: error.message,
|
||||||
|
status: error.response?.status,
|
||||||
|
statusText: error.response?.statusText,
|
||||||
|
data: error.response?.data,
|
||||||
|
config: {
|
||||||
|
url: error.config?.url,
|
||||||
|
headers: error.config?.headers
|
||||||
|
? { ...error.config.headers, Authorization: "[redacted]" }
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const errorStatus = error.response?.status || "UNKNOWN";
|
||||||
|
const errorMessage =
|
||||||
|
error.response?.data?.msg ||
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.response?.statusText ||
|
||||||
|
error.message;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
taskId,
|
||||||
|
musicIndex: index,
|
||||||
|
error: {
|
||||||
|
status: errorStatus,
|
||||||
|
message: errorMessage,
|
||||||
|
type: "API_ERROR",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataToReturn = parsed?.data || parsed || {};
|
||||||
|
|
||||||
|
// Sauvegarde obligatoire dans le document projet
|
||||||
|
let saved = false;
|
||||||
|
try {
|
||||||
|
await db
|
||||||
|
.collection("projects")
|
||||||
|
.doc(projectId)
|
||||||
|
.set(
|
||||||
|
{
|
||||||
|
[`musicTimestamps.${index}`]: dataToReturn,
|
||||||
|
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||||
|
},
|
||||||
|
{ merge: true }
|
||||||
|
);
|
||||||
|
saved = true;
|
||||||
|
console.log("💾 Timestamps sauvegardés dans Firestore", {
|
||||||
|
projectId,
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
"❌ Échec sauvegarde timestamps Firestore:",
|
||||||
|
e?.message || e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
taskId,
|
||||||
|
musicIndex: index,
|
||||||
|
projectId,
|
||||||
|
saved,
|
||||||
|
musicTimestamps: dataToReturn,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Erreur interne getSunoTimestamps:", error);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
taskId: data?.taskId,
|
||||||
|
musicIndex: data?.musicIndex,
|
||||||
|
error: {
|
||||||
|
message: error.message,
|
||||||
|
type: "INTERNAL_ERROR",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cloud Function pour recevoir les callbacks de l'API Suno
|
* Cloud Function pour recevoir les callbacks de l'API Suno
|
||||||
* Cette fonction est appelée par l'API Suno lorsque la génération
|
* Cette fonction est appelée par l'API Suno lorsque la génération
|
||||||
@@ -340,7 +466,9 @@ exports.sunoCallback = onRequest({ methods: ["POST"] }, async (req, res) => {
|
|||||||
|
|
||||||
const body = req.body || {};
|
const body = req.body || {};
|
||||||
const code = body.code ?? body.statusCode ?? null;
|
const code = body.code ?? body.statusCode ?? null;
|
||||||
const callbackType = (body?.data?.callbackType || "").toString().toLowerCase();
|
const callbackType = (body?.data?.callbackType || "")
|
||||||
|
.toString()
|
||||||
|
.toLowerCase();
|
||||||
const status = (body.status || body.state || callbackType)
|
const status = (body.status || body.state || callbackType)
|
||||||
.toString()
|
.toString()
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
@@ -402,10 +530,7 @@ exports.sunoCallback = onRequest({ methods: ["POST"] }, async (req, res) => {
|
|||||||
const audioUrls = tracks
|
const audioUrls = tracks
|
||||||
.map(
|
.map(
|
||||||
(t) =>
|
(t) =>
|
||||||
t.audio_url ||
|
t.audio_url || t.audioUrl || t.stream_audio_url || t.streamAudioUrl
|
||||||
t.audioUrl ||
|
|
||||||
t.stream_audio_url ||
|
|
||||||
t.streamAudioUrl,
|
|
||||||
)
|
)
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.slice(0, 2);
|
.slice(0, 2);
|
||||||
@@ -420,7 +545,7 @@ exports.sunoCallback = onRequest({ methods: ["POST"] }, async (req, res) => {
|
|||||||
has_audio_url: !!t.audio_url,
|
has_audio_url: !!t.audio_url,
|
||||||
has_stream_audio_url: !!t.stream_audio_url,
|
has_stream_audio_url: !!t.stream_audio_url,
|
||||||
})),
|
})),
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,14 +570,14 @@ exports.sunoCallback = onRequest({ methods: ["POST"] }, async (req, res) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const downloadUrl = `https://firebasestorage.googleapis.com/v0/b/${bucket.name}/o/${encodeURIComponent(
|
const downloadUrl = `https://firebasestorage.googleapis.com/v0/b/${bucket.name}/o/${encodeURIComponent(
|
||||||
path,
|
path
|
||||||
)}?alt=media&token=${token}`;
|
)}?alt=media&token=${token}`;
|
||||||
console.log("✅ [SunoCallback] Sauvegardé:", path, "URL:", downloadUrl);
|
console.log("✅ [SunoCallback] Sauvegardé:", path, "URL:", downloadUrl);
|
||||||
return { path, url: downloadUrl };
|
return { path, url: downloadUrl };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
`❌ [SunoCallback] Échec save piste ${index + 1}:`,
|
`❌ [SunoCallback] Échec save piste ${index + 1}:`,
|
||||||
e.message,
|
e.message
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -472,7 +597,7 @@ exports.sunoCallback = onRequest({ methods: ["POST"] }, async (req, res) => {
|
|||||||
musicUrls,
|
musicUrls,
|
||||||
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||||
},
|
},
|
||||||
{ merge: true },
|
{ merge: true }
|
||||||
);
|
);
|
||||||
console.log("🏷️ [SunoCallback] Projet marqué GENERATED", {
|
console.log("🏷️ [SunoCallback] Projet marqué GENERATED", {
|
||||||
projectId,
|
projectId,
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import React from "react";
|
import React, { useCallback } from "react";
|
||||||
import { Image, StyleSheet, View } from "react-native";
|
import { Alert, Image, StyleSheet, View } from "react-native";
|
||||||
|
import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
|
||||||
import { ai, background } from "../../assets";
|
import { ai, background } from "../../assets";
|
||||||
import BorderGradientButton from "../../components/BorderGradientButton";
|
import BorderGradientButton from "../../components/BorderGradientButton";
|
||||||
import GradientButton from "../../components/GradientButton";
|
import GradientButton from "../../components/GradientButton";
|
||||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||||
|
import firebase from "../../config/firebase";
|
||||||
import Page from "../../layouts/Page";
|
import Page from "../../layouts/Page";
|
||||||
import { Routes } from "../../navigation";
|
import { Routes } from "../../navigation";
|
||||||
import { goBack, navigate } from "../../navigation/NavigationService";
|
import { goBack, navigate } from "../../navigation/NavigationService";
|
||||||
@@ -11,6 +13,53 @@ import { gutters } from "../../styles";
|
|||||||
|
|
||||||
const Playback = ({ route }) => {
|
const Playback = ({ route }) => {
|
||||||
const { project } = route.params;
|
const { project } = route.params;
|
||||||
|
const projectId = project?.id;
|
||||||
|
const songIndex = project?.songIndex;
|
||||||
|
const sunoTaskId = project?.sunoTaskId;
|
||||||
|
const { setIsLoading } = useMinuit();
|
||||||
|
|
||||||
|
const onPressRecord = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
// If we lack required fields, skip generation but continue UX
|
||||||
|
if (!projectId || songIndex === undefined || !sunoTaskId) {
|
||||||
|
console.log("Missing data for timestamp generation", {
|
||||||
|
projectId,
|
||||||
|
songIndex,
|
||||||
|
sunoTaskId,
|
||||||
|
});
|
||||||
|
// return navigate(Routes.RecordPlayback, { project });
|
||||||
|
}
|
||||||
|
|
||||||
|
await setIsLoading(true);
|
||||||
|
const callable = firebase
|
||||||
|
.functions()
|
||||||
|
.httpsCallable("music-getSunoTimestamps");
|
||||||
|
const { data } = await callable({
|
||||||
|
taskId: sunoTaskId,
|
||||||
|
musicIndex: Number(songIndex) || 0,
|
||||||
|
projectId: projectId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!data?.success) {
|
||||||
|
console.log("getSunoTimestamps failed", data?.error || data);
|
||||||
|
Alert.alert(
|
||||||
|
"Timestamps",
|
||||||
|
"Impossible de récupérer les timestamps pour ce playback pour le moment. Tu peux quand même continuer."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("getSunoTimestamps error", e?.message || e);
|
||||||
|
Alert.alert(
|
||||||
|
"Timestamps",
|
||||||
|
"Une erreur est survenue lors de la génération des timestamps. Tu peux quand même continuer."
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await setIsLoading(false);
|
||||||
|
navigate(Routes.RecordPlayback, { project });
|
||||||
|
}
|
||||||
|
}, [projectId, songIndex, sunoTaskId, project]);
|
||||||
|
|
||||||
|
console.log("Playback render", { projectId, songIndex, sunoTaskId });
|
||||||
return (
|
return (
|
||||||
<Page headerType="NONE" backgroundImg={background.playbackBG2}>
|
<Page headerType="NONE" backgroundImg={background.playbackBG2}>
|
||||||
<Image source={ai.john} style={styles.img} resizeMode="contain" />
|
<Image source={ai.john} style={styles.img} resizeMode="contain" />
|
||||||
@@ -27,7 +76,7 @@ const Playback = ({ route }) => {
|
|||||||
{/* <BorderGradientButton title="Importer une vidéo" /> */}
|
{/* <BorderGradientButton title="Importer une vidéo" /> */}
|
||||||
<GradientButton
|
<GradientButton
|
||||||
title="Enregistrer mon Playback"
|
title="Enregistrer mon Playback"
|
||||||
onPress={() => navigate(Routes.RecordPlayback, { project })}
|
onPress={onPressRecord}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ const Profile = () => {
|
|||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
{selected === "Playbacks" && (
|
{selected === "Playbacks" && (
|
||||||
<MusicListSection
|
<MusicàListàSection
|
||||||
data={userPlaybacks}
|
data={userPlaybacks}
|
||||||
emptyText="Aucun playback pour le moment"
|
emptyText="Aucun playback pour le moment"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import { useAudioPlayer } from "expo-audio";
|
||||||
import Page from "../../layouts/Page";
|
|
||||||
import { background, icons } from "../../assets";
|
|
||||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
|
||||||
import { goBack, navigate } from "../../navigation/NavigationService";
|
|
||||||
import Slider from "../../components/Slider";
|
|
||||||
import { Image, Platform, Pressable, View, Text } from "react-native";
|
|
||||||
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
|
|
||||||
import { BlurView } from "expo-blur";
|
import { BlurView } from "expo-blur";
|
||||||
import { Style } from "../../styles";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { gutters, size } from "../../styles/Style";
|
import { Image, Platform, Pressable, Text, View } from "react-native";
|
||||||
|
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||||
|
import { background, icons } from "../../assets";
|
||||||
import BorderGradientButton from "../../components/BorderGradientButton";
|
import BorderGradientButton from "../../components/BorderGradientButton";
|
||||||
import GradientButton from "../../components/GradientButton";
|
import GradientButton from "../../components/GradientButton";
|
||||||
import { Routes } from "../../navigation";
|
|
||||||
import ValidateModal from "../../components/modal/ValidateModal";
|
import ValidateModal from "../../components/modal/ValidateModal";
|
||||||
|
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||||
|
import Slider from "../../components/Slider";
|
||||||
import firebase, { projectsRef } from "../../config/firebase";
|
import firebase, { projectsRef } from "../../config/firebase";
|
||||||
import { useAudioPlayer } from "expo-audio";
|
import Page from "../../layouts/Page";
|
||||||
import { responsiveHeight } from "react-native-responsive-dimensions";
|
import { Routes } from "../../navigation";
|
||||||
|
import { goBack, navigate } from "../../navigation/NavigationService";
|
||||||
|
import { Style } from "../../styles";
|
||||||
|
import { gutters, size } from "../../styles/Style";
|
||||||
|
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
|
||||||
|
|
||||||
const SongReady = ({ route }) => {
|
const SongReady = ({ route }) => {
|
||||||
const { projectId = null } = route?.params || {};
|
const { projectId = null } = route?.params || {};
|
||||||
@@ -28,10 +28,10 @@ const SongReady = ({ route }) => {
|
|||||||
1: { pos: 0, dur: 0 },
|
1: { pos: 0, dur: 0 },
|
||||||
});
|
});
|
||||||
const player0 = useAudioPlayer(
|
const player0 = useAudioPlayer(
|
||||||
musicUrls[0] ? { uri: musicUrls[0] } : undefined,
|
musicUrls[0] ? { uri: musicUrls[0] } : undefined
|
||||||
);
|
);
|
||||||
const player1 = useAudioPlayer(
|
const player1 = useAudioPlayer(
|
||||||
musicUrls[1] ? { uri: musicUrls[1] } : undefined,
|
musicUrls[1] ? { uri: musicUrls[1] } : undefined
|
||||||
);
|
);
|
||||||
const wasPlayingBeforeSeek = useRef({ 0: false, 1: false });
|
const wasPlayingBeforeSeek = useRef({ 0: false, 1: false });
|
||||||
|
|
||||||
@@ -119,10 +119,11 @@ const SongReady = ({ route }) => {
|
|||||||
if (!projectId || !url) return;
|
if (!projectId || !url) return;
|
||||||
await projectsRef.doc(projectId).set(
|
await projectsRef.doc(projectId).set(
|
||||||
{
|
{
|
||||||
|
songIndex: selectedIndex,
|
||||||
songUrl: url,
|
songUrl: url,
|
||||||
updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
|
updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
|
||||||
},
|
},
|
||||||
{ merge: true },
|
{ merge: true }
|
||||||
);
|
);
|
||||||
navigate(Routes.FlowSelection, { projectId });
|
navigate(Routes.FlowSelection, { projectId });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -206,7 +207,7 @@ const SongReady = ({ route }) => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(
|
console.log(
|
||||||
"SongReady pause on seek start",
|
"SongReady pause on seek start",
|
||||||
e?.message,
|
e?.message
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user