generate two covers
This commit is contained in:
+165
-125
@@ -1,6 +1,5 @@
|
||||
import { useIsFocused } from "@react-navigation/native";
|
||||
import { Image as ExpoImage } from "expo-image";
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { ActivityIndicator, Text, View } from "react-native";
|
||||
import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
|
||||
import { background, icons } from "../../assets";
|
||||
@@ -17,20 +16,48 @@ import { goBack, navigate } from "../../navigation/NavigationService";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { gutters, Palette, Style } from "../../styles";
|
||||
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
|
||||
import CustomInput from "../Writing/components/CustomInput";
|
||||
|
||||
const PouchReady = () => {
|
||||
const { selectedProjectId, selectedProject } = useUser();
|
||||
const { selectedProjectId, selectedProject, updateProjectData } = useUser();
|
||||
const { setIsLoading } = useMinuit();
|
||||
const isGenerating = selectedProject?.coverStatus === "GENERATING";
|
||||
const isFocused = useIsFocused();
|
||||
const coverOptions = Array.isArray(selectedProject?.cover?.options)
|
||||
? selectedProject.cover.options
|
||||
: [];
|
||||
const hasGeneratedOptions = coverOptions.length > 0;
|
||||
const coverBackgroundMessage = isWeb
|
||||
? loaderMessages.pouchReadyGenerationWeb
|
||||
: "";
|
||||
|
||||
const generateCover = useCallback(async () => {
|
||||
const [coverStyle, setCoverStyle] = useState(
|
||||
selectedProject?.coverStyle || ""
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setCoverStyle(selectedProject?.coverStyle || "");
|
||||
}, [selectedProject?.coverStyle]);
|
||||
|
||||
const generateCover = useCallback(async (styleValue) => {
|
||||
if (!selectedProjectId) return;
|
||||
if (hasGeneratedOptions) {
|
||||
return;
|
||||
}
|
||||
const trimmedStyle = String(styleValue || "").trim();
|
||||
if (!trimmedStyle) {
|
||||
alert("Attention", "Merci de renseigner un style pour la pochette.", [
|
||||
{ text: "OK" },
|
||||
]);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await setIsLoading(true);
|
||||
await updateProjectData(
|
||||
{
|
||||
coverStyle: trimmedStyle,
|
||||
},
|
||||
{ merge: true }
|
||||
);
|
||||
await tasksRef.add({
|
||||
type: "cover",
|
||||
projectId: selectedProjectId,
|
||||
@@ -42,40 +69,49 @@ const PouchReady = () => {
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [selectedProjectId, setIsLoading]);
|
||||
}, [hasGeneratedOptions, selectedProjectId, setIsLoading, updateProjectData]);
|
||||
|
||||
const requestCoverGeneration = useCallback(() => {
|
||||
const trimmedStyle = (coverStyle || "").trim();
|
||||
if (!trimmedStyle) {
|
||||
alert("Attention", "Merci de renseigner un style pour la pochette.", [
|
||||
{ text: "OK" },
|
||||
]);
|
||||
return;
|
||||
}
|
||||
alert("Attention", "Générer une pochette ?", [
|
||||
{
|
||||
text: "Annuler",
|
||||
style: "cancel",
|
||||
},
|
||||
{
|
||||
text: "Oui",
|
||||
onPress: () => generateCover(trimmedStyle),
|
||||
},
|
||||
]);
|
||||
}, [coverStyle, generateCover]);
|
||||
|
||||
const validateCover = () => {
|
||||
navigate(Routes.ValidateCover);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isFocused &&
|
||||
!selectedProject?.cover?.generatedBackground &&
|
||||
selectedProject?.coverStatus !== "GENERATING"
|
||||
) {
|
||||
alert(
|
||||
"Attention",
|
||||
"Générer une pochette ?",
|
||||
[
|
||||
{
|
||||
text: "Oui",
|
||||
onPress: generateCover,
|
||||
},
|
||||
{
|
||||
text: "Non",
|
||||
},
|
||||
],
|
||||
{ cancelable: true }
|
||||
);
|
||||
}
|
||||
}, [generateCover, isFocused, selectedProject]);
|
||||
|
||||
const coverPreviewUrl =
|
||||
selectedProject?.cover?.result ||
|
||||
selectedProject?.cover?.generatedBackground ||
|
||||
null;
|
||||
|
||||
const displayOptions = hasGeneratedOptions
|
||||
? coverOptions
|
||||
: coverPreviewUrl
|
||||
? [
|
||||
{
|
||||
id: "preview",
|
||||
finalUrl: selectedProject?.cover?.result || null,
|
||||
generatedUrl: coverPreviewUrl,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
return (
|
||||
<Page backgroundImg={background.studioBG2} headerType="NONE">
|
||||
<MusicLandHeader onPressBack={goBack} progress={72} />
|
||||
@@ -89,37 +125,82 @@ const PouchReady = () => {
|
||||
// subTitle="Qu’en penses-tu ?"
|
||||
/>
|
||||
<View style={{ flex: 1, ...Style.containerCenter }}>
|
||||
<View style={{ width: "80%", position: "relative" }}>
|
||||
{coverPreviewUrl && !isGenerating ? (
|
||||
<ExpoImage
|
||||
source={{ uri: coverPreviewUrl }}
|
||||
cachePolicy="memory-disk"
|
||||
priority="high"
|
||||
contentFit="cover"
|
||||
transition={120}
|
||||
style={{
|
||||
width: isWeb ? 300 : "100%",
|
||||
height: 300,
|
||||
borderRadius: 20,
|
||||
alignSelf: "center",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<View
|
||||
style={{
|
||||
width: isWeb ? 300 : "100%",
|
||||
height: 300,
|
||||
borderRadius: 20,
|
||||
backgroundColor: "#00000040",
|
||||
alignSelf: "center",
|
||||
...Style.containerCenter,
|
||||
}}
|
||||
>
|
||||
{isGenerating && (
|
||||
<View style={{ alignItems: "center", gap: 8 }}>
|
||||
<ActivityIndicator color={Palette.white} />
|
||||
{isWeb ? (
|
||||
coverBackgroundMessage ? (
|
||||
<View style={{ width: "80%", gap: 24 }}>
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
flexDirection: isWeb ? "row" : "column",
|
||||
gap: 16,
|
||||
justifyContent: "center",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
{displayOptions.length > 0 ? (
|
||||
displayOptions.map((option, index) => {
|
||||
const optionUri = option?.finalUrl || option?.generatedUrl || "";
|
||||
if (!optionUri) return null;
|
||||
return (
|
||||
<View
|
||||
key={option?.id || index}
|
||||
style={{
|
||||
width: isWeb ? 280 : "100%",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
<ExpoImage
|
||||
source={{ uri: optionUri }}
|
||||
cachePolicy="memory-disk"
|
||||
priority="high"
|
||||
contentFit="cover"
|
||||
transition={120}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 260,
|
||||
borderRadius: 20,
|
||||
}}
|
||||
/>
|
||||
{hasGeneratedOptions && (
|
||||
<Text
|
||||
style={{
|
||||
color: Palette.white,
|
||||
opacity: 0.7,
|
||||
}}
|
||||
>
|
||||
Pochette {index + 1}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<View
|
||||
style={{
|
||||
width: isWeb ? 300 : "100%",
|
||||
height: 300,
|
||||
borderRadius: 20,
|
||||
backgroundColor: "#00000040",
|
||||
alignSelf: "center",
|
||||
...Style.containerCenter,
|
||||
}}
|
||||
>
|
||||
{isGenerating && (
|
||||
<View style={{ alignItems: "center", gap: 8 }}>
|
||||
<ActivityIndicator color={Palette.white} />
|
||||
{isWeb ? (
|
||||
coverBackgroundMessage ? (
|
||||
<Text
|
||||
style={{
|
||||
color: Palette.white,
|
||||
marginTop: 6,
|
||||
textAlign: "center",
|
||||
opacity: 0.9,
|
||||
}}
|
||||
>
|
||||
{coverBackgroundMessage}
|
||||
</Text>
|
||||
) : null
|
||||
) : (
|
||||
<Text
|
||||
style={{
|
||||
color: Palette.white,
|
||||
@@ -128,66 +209,23 @@ const PouchReady = () => {
|
||||
opacity: 0.9,
|
||||
}}
|
||||
>
|
||||
{coverBackgroundMessage}
|
||||
Génération en cours.
|
||||
</Text>
|
||||
) : null
|
||||
) : (
|
||||
<Text
|
||||
style={{
|
||||
color: Palette.white,
|
||||
marginTop: 6,
|
||||
textAlign: "center",
|
||||
opacity: 0.9,
|
||||
}}
|
||||
>
|
||||
Génération en cours.
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
{/*<View*/}
|
||||
{/* style={{*/}
|
||||
{/* position: "absolute",*/}
|
||||
{/* alignSelf: "center",*/}
|
||||
{/* alignItems: "center",*/}
|
||||
{/* top: 10,*/}
|
||||
{/* }}*/}
|
||||
{/*>*/}
|
||||
{/* <Text*/}
|
||||
{/* style={{*/}
|
||||
{/* fontSize: 22,*/}
|
||||
{/* color: Palette.white,*/}
|
||||
{/* fontFamily: FONT_FAMILY.InterSemiBold,*/}
|
||||
{/* }}*/}
|
||||
{/* >*/}
|
||||
{/* {title || "Titre"}*/}
|
||||
{/* </Text>*/}
|
||||
{/* <Text*/}
|
||||
{/* style={{*/}
|
||||
{/* fontSize: 14,*/}
|
||||
{/* color: Palette.gray,*/}
|
||||
{/* fontFamily: FONT_FAMILY.InterRegular,*/}
|
||||
{/* }}*/}
|
||||
{/* >*/}
|
||||
{/* MusicLand*/}
|
||||
{/* </Text>*/}
|
||||
{/*</View>*/}
|
||||
{/*<View*/}
|
||||
{/* style={{*/}
|
||||
{/* position: "absolute",*/}
|
||||
{/* alignItems: "center",*/}
|
||||
{/* bottom: 10,*/}
|
||||
{/* width: "100%",*/}
|
||||
{/* }}*/}
|
||||
{/*>*/}
|
||||
{/* <Image*/}
|
||||
{/* source={icons.musicLandLogo}*/}
|
||||
{/* style={{ width: "100%", height: 30 }}*/}
|
||||
{/* resizeMode="contain"*/}
|
||||
{/* />*/}
|
||||
{/*</View>*/}
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<CustomInput
|
||||
label="Style de la pochette"
|
||||
placeholder="Exemple : Collage rétro futuriste lumineux"
|
||||
value={coverStyle}
|
||||
setValue={setCoverStyle}
|
||||
multiline={false}
|
||||
height={55}
|
||||
maxLength={120}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@@ -199,12 +237,14 @@ const PouchReady = () => {
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<BorderGradientButton
|
||||
title={isGenerating ? "Génération en cours..." : "Regénérer"}
|
||||
icon={icons.stars}
|
||||
onPress={generateCover}
|
||||
disabled={isGenerating}
|
||||
/>
|
||||
{!hasGeneratedOptions && (
|
||||
<BorderGradientButton
|
||||
title={isGenerating ? "Génération en cours..." : "Générer la pochette"}
|
||||
icon={icons.stars}
|
||||
onPress={requestCoverGeneration}
|
||||
disabled={isGenerating}
|
||||
/>
|
||||
)}
|
||||
<GradientButton
|
||||
title={isGenerating ? "Veuillez patienter..." : "Valider"}
|
||||
disabled={isGenerating || !coverPreviewUrl}
|
||||
|
||||
Reference in New Issue
Block a user