covers with logo

This commit is contained in:
2025-10-22 17:06:49 +02:00
parent 40e10d1692
commit b4375d04be
9 changed files with 643 additions and 228 deletions
+52 -61
View File
@@ -1,30 +1,21 @@
import * as ImagePicker from "expo-image-picker";
import { BlurView } from "expo-blur";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
Image,
Modal,
Pressable,
StyleSheet,
Text,
View,
} from "react-native";
import { Image, Modal, Pressable, StyleSheet, Text, View } from "react-native";
import useMinuit from "react-native-minuit/src/hooks/useMinuit";
import { ai, background } from "../../assets";
import BorderGradientButton from "../../components/BorderGradientButton";
import FullscreenIntroVideo from "../../components/FullscreenIntroVideo";
import GradientButton from "../../components/GradientButton";
import MusicLandHeader from "../../components/MusicLandHeader";
import { Input } from "../../components/Input";
import MusicLandHeader from "../../components/MusicLandHeader";
import firebase, { projectsRef, usersRef } from "../../config/firebase";
import { uploadFileToFirebase } from "../../helpers/uploadToFirebase";
import Page from "../../layouts/Page";
import { Routes } from "../../navigation";
import { goBack, navigate } from "../../navigation/NavigationService";
import { useUserData } from "../../providers/UserDataProvider";
import { buildFullName } from "../../utils/artistName";
import { gutters, Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { buildFullName } from "../../utils/artistName";
export const ChooseCoverType = () => {
const [showIntro, setShowIntro] = useState(true);
@@ -52,11 +43,14 @@ export const ChooseCoverType = () => {
return pref === "REAL_NAME" || pref === "CUSTOM";
}, [currentUserData?.artistNamePreference, currentUserData?.userName]);
const realName = useMemo(() => buildFullName(currentUserData), [
currentUserData?.firstName,
currentUserData?.lastName,
currentUserData?.displayName,
]);
const realName = useMemo(
() => buildFullName(currentUserData),
[
currentUserData?.firstName,
currentUserData?.lastName,
currentUserData?.displayName,
]
);
useEffect(() => {
if (pseudoVisible) {
@@ -122,48 +116,48 @@ export const ChooseCoverType = () => {
[currentUID, projectId]
);
const pickUserImage = useCallback(async () => {
try {
await setIsLoading(true);
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ["images"],
allowsEditing: true,
aspect: [1, 1],
quality: 1,
});
// const pickUserImage = useCallback(async () => {
// try {
// await setIsLoading(true);
// const result = await ImagePicker.launchImageLibraryAsync({
// mediaTypes: ["images"],
// allowsEditing: true,
// aspect: [1, 1],
// quality: 1,
// });
const uri = result?.assets?.[0]?.uri || null;
if (!uri) return;
// const uri = result?.assets?.[0]?.uri || null;
// if (!uri) return;
if (!projectId) return;
const path = `musics/${projectId}/userSelectedCover.png`;
// if (!projectId) return;
// const path = `musics/${projectId}/userSelectedCover.png`;
const { resultURI } = await uploadFileToFirebase({
uri,
path,
shouldCompress: true,
fileType: "IMAGE",
});
// const { resultURI } = await uploadFileToFirebase({
// uri,
// path,
// shouldCompress: true,
// fileType: "IMAGE",
// });
if (!resultURI) {
throw new Error("Erreur lors de l'upload");
}
await updateProjectData({
cover: {
result: resultURI,
},
});
navigate(Routes.ValidateCover);
} catch (e) {
console.log("onPickUserImage error", e?.message);
} finally {
await setIsLoading(false);
}
}, [projectId, setIsLoading, updateProjectData]);
// if (!resultURI) {
// throw new Error("Erreur lors de l'upload");
// }
// await updateProjectData({
// cover: {
// result: resultURI,
// },
// });
// navigate(Routes.ValidateCover);
// } catch (e) {
// console.log("onPickUserImage error", e?.message);
// } finally {
// await setIsLoading(false);
// }
// }, [projectId, setIsLoading, updateProjectData]);
const handlePickUserImage = useCallback(() => {
ensureArtistPreference(pickUserImage);
}, [ensureArtistPreference, pickUserImage]);
// const handlePickUserImage = useCallback(() => {
// ensureArtistPreference(pickUserImage);
// }, [ensureArtistPreference, pickUserImage]);
const handleGenerateCover = useCallback(() => {
ensureArtistPreference(() => navigate(Routes.PouchReady));
@@ -184,8 +178,7 @@ export const ChooseCoverType = () => {
if (!realName) {
setTooltip({
type: "error",
text:
"Renseigne ton prénom et nom dans ton profil ou crée un nom d'artiste.",
text: "Renseigne ton prénom et nom dans ton profil ou crée un nom d'artiste.",
});
setChoiceVisible(false);
setPseudoVisible(true);
@@ -298,10 +291,10 @@ export const ChooseCoverType = () => {
gap: 12,
}}
>
<BorderGradientButton
{/* <BorderGradientButton
title="Choisir une image"
onPress={handlePickUserImage}
/>
/> */}
<GradientButton
title="Générer une pochette"
onPress={handleGenerateCover}
@@ -333,9 +326,7 @@ export const ChooseCoverType = () => {
</Text>
<View style={styles.modalButtons}>
<BorderGradientButton
title={
savingChoice ? "Chargement..." : "Utiliser prénom/nom"
}
title={savingChoice ? "Chargement..." : "Utiliser prénom/nom"}
onPress={handleUseRealName}
disabled={savingChoice}
/>
+48 -83
View File
@@ -1,15 +1,11 @@
import { Image as ExpoImage } from "expo-image";
import * as ImagePicker from "expo-image-picker";
import React from "react";
import { ActivityIndicator, Text, View } from "react-native";
import useMinuit from "react-native-minuit/src/hooks/useMinuit";
import { background } from "../../assets";
import BorderGradientButton from "../../components/BorderGradientButton";
import GradientButton from "../../components/GradientButton";
import MusicLandHeader from "../../components/MusicLandHeader";
import firebase, { tasksRef } from "../../config/firebase";
import loaderMessages from "../../config/loaderMessages";
import { uploadFileToFirebase } from "../../helpers/uploadToFirebase";
import { isWeb } from "../../hooks/useLayoutType";
import Page from "../../layouts/Page";
import { Routes } from "../../navigation";
@@ -19,69 +15,30 @@ import { gutters, Palette, Style } from "../../styles";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
const PhotoCover = () => {
const { selectedProject, selectedProjectId, updateProjectData } =
useUserData();
const { setIsLoading } = useMinuit();
const { selectedProject } = useUserData();
const isGenerating = selectedProject?.coverStatus === "GENERATING";
const coverGenerationMessage = isWeb
? loaderMessages.photoCoverGenerationWeb
: "";
const onChooseForegroundImage = async () => {
try {
await setIsLoading(true);
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ["images"],
allowsEditing: true,
aspect: [1, 1],
quality: 1,
});
const uri = result?.assets?.[0]?.uri || null;
if (!uri) return;
const projectId = selectedProject?.id || selectedProjectId;
const path = `musics/${projectId}/userForeground.png`;
const { resultURI } = await uploadFileToFirebase({
uri,
path,
shouldCompress: true,
fileType: "IMAGE",
});
if (!resultURI) {
throw new Error("Erreur lors de l'upload");
}
await updateProjectData({
cover: {
...selectedProject.cover,
userForeground: resultURI,
},
});
await tasksRef.add({
type: "combine",
projectId: selectedProjectId,
status: "PENDING",
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
});
} catch (e) {
console.log("onPickUserImage error", e?.message);
} finally {
await setIsLoading(false);
}
};
const coverUrl =
selectedProject?.cover?.result ||
selectedProject?.cover?.generatedBackground ||
null;
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<MusicLandHeader onPressBack={goBack} progress={81} />
<View style={{ flex: 1, marginTop: 16 }}>
<CreateLyricsHeader title="Souhaites-tu rajouter une photo de toi sur la pochette?" />
<CreateLyricsHeader
title="Ta pochette MusicLand Production"
subTitle="Le logo est automatiquement ajouté en bas à droite."
/>
<View style={{ flex: 1, ...Style.containerCenter }}>
<View style={{ width: "80%", position: "relative" }}>
{selectedProject?.cover?.result && !isGenerating ? (
{coverUrl && !isGenerating ? (
<ExpoImage
source={{ uri: selectedProject?.cover?.result }}
source={{ uri: coverUrl }}
cachePolicy="memory-disk"
priority="high"
contentFit="cover"
@@ -103,11 +60,11 @@ const PhotoCover = () => {
...Style.containerCenter,
}}
>
{isGenerating && (
<View style={{ alignItems: "center", gap: 8 }}>
<ActivityIndicator color={Palette.white} />
{isWeb ? (
coverGenerationMessage ? (
<View style={{ alignItems: "center", gap: 8 }}>
{isGenerating ? (
<>
<ActivityIndicator color={Palette.white} />
{isWeb && coverGenerationMessage ? (
<Text
style={{
color: Palette.white,
@@ -118,21 +75,33 @@ const PhotoCover = () => {
>
{coverGenerationMessage}
</Text>
) : null
) : (
<Text
style={{
color: Palette.white,
marginTop: 6,
textAlign: "center",
opacity: 0.9,
}}
>
Génération en cours.
</Text>
)}
</View>
)}
) : (
<Text
style={{
color: Palette.white,
marginTop: 6,
textAlign: "center",
opacity: 0.9,
}}
>
Génération en cours.
</Text>
)}
</>
) : (
<Text
style={{
color: Palette.white,
marginTop: 6,
textAlign: "center",
opacity: 0.9,
}}
>
La pochette sera disponible une fois la génération
terminée.
</Text>
)}
</View>
</View>
)}
</View>
@@ -147,18 +116,14 @@ const PhotoCover = () => {
}}
>
<BorderGradientButton
onPress={() => navigate(Routes.ValidateCover)}
title={
isGenerating ? "Génération en cours..." : "Valider la pochette"
}
onPress={() => navigate(Routes.PouchReady)}
title="Regénérer la pochette"
disabled={isGenerating}
/>
<GradientButton
title={
isGenerating ? "Génération en cours..." : "Oui choisir une image"
}
onPress={() => onChooseForegroundImage()}
disabled={isGenerating}
title="Valider la pochette"
onPress={() => navigate(Routes.ValidateCover)}
disabled={isGenerating || !coverUrl}
/>
</View>
</Page>
+12 -20
View File
@@ -19,7 +19,7 @@ import { gutters, Palette, Style } from "../../styles";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
const PouchReady = () => {
const { selectedProjectId, selectedProject, updateProjectData } = useUser();
const { selectedProjectId, selectedProject } = useUser();
const { setIsLoading } = useMinuit();
const isGenerating = selectedProject?.coverStatus === "GENERATING";
const isFocused = useIsFocused();
@@ -44,22 +44,9 @@ const PouchReady = () => {
}
}, [selectedProjectId, setIsLoading]);
async function validateCover() {
try {
await setIsLoading(true);
await updateProjectData({
cover: {
...selectedProject.cover,
result: selectedProject.cover.generatedBackground,
},
});
navigate(Routes.PhotoCover);
} catch (e) {
console.log(e);
} finally {
await setIsLoading(false);
}
}
const validateCover = () => {
navigate(Routes.ValidateCover);
};
useEffect(() => {
if (
@@ -84,6 +71,11 @@ const PouchReady = () => {
}
}, [generateCover, isFocused, selectedProject]);
const coverPreviewUrl =
selectedProject?.cover?.result ||
selectedProject?.cover?.generatedBackground ||
null;
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<MusicLandHeader onPressBack={goBack} progress={72} />
@@ -98,9 +90,9 @@ const PouchReady = () => {
/>
<View style={{ flex: 1, ...Style.containerCenter }}>
<View style={{ width: "80%", position: "relative" }}>
{selectedProject?.cover?.generatedBackground && !isGenerating ? (
{coverPreviewUrl && !isGenerating ? (
<ExpoImage
source={{ uri: selectedProject?.cover?.generatedBackground }}
source={{ uri: coverPreviewUrl }}
cachePolicy="memory-disk"
priority="high"
contentFit="cover"
@@ -215,7 +207,7 @@ const PouchReady = () => {
/>
<GradientButton
title={isGenerating ? "Veuillez patienter..." : "Valider"}
disabled={isGenerating}
disabled={isGenerating || !coverPreviewUrl}
onPress={() => validateCover()}
/>
</View>
+1 -1
View File
@@ -205,7 +205,7 @@ export const getStageAction = (key, project) => {
}
if (!hasFinalCover) {
return { route: Routes.PhotoCover };
return { route: Routes.ValidateCover };
}
return { route: Routes.ChooseCoverType };