diff --git a/src/components/ProfilePicture.js b/src/components/ProfilePicture.js
new file mode 100644
index 0000000..583315a
--- /dev/null
+++ b/src/components/ProfilePicture.js
@@ -0,0 +1,65 @@
+import { Image } from "expo-image";
+import { memo } from "react";
+import { Platform, StyleSheet, View } from "react-native";
+import { Palette } from "../styles";
+
+const DEFAULT_INTENSITY = Platform.select({ ios: 22, default: 14 });
+
+const ProfilePicture = ({
+ uri = null,
+ size = 48,
+ style,
+ blurIntensity = DEFAULT_INTENSITY,
+ blurTint = "dark",
+ imageProps = {},
+ transitionDuration = 120,
+ cachePolicy = "memory-disk",
+ contentFit = "cover",
+ accessibilityLabel,
+ ...rest
+}) => {
+ const dimensionStyle = {
+ width: size,
+ height: size,
+ borderRadius: size / 2,
+ };
+
+ return (
+
+ {uri ? (
+
+ ) : (
+ <>
+
+ >
+ )}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ overflow: "hidden",
+ backgroundColor: "transparent",
+ },
+ fallback: {
+ backgroundColor: Palette.glass,
+ borderColor: Palette.ultraLightWhite,
+ borderWidth: 2,
+ },
+});
+
+export default memo(ProfilePicture);
diff --git a/src/components/bottomsheets/CommentsBottomSheet.js b/src/components/bottomsheets/CommentsBottomSheet.js
index a8eed22..4377a1c 100644
--- a/src/components/bottomsheets/CommentsBottomSheet.js
+++ b/src/components/bottomsheets/CommentsBottomSheet.js
@@ -6,7 +6,6 @@ import {
BottomSheetTextInput,
} from '@gorhom/bottom-sheet';
import { BlurView } from 'expo-blur';
-import { Image as ExpoImage } from 'expo-image';
import React, {
useCallback,
useEffect,
@@ -30,7 +29,7 @@ import { useUser } from '../../providers/UserDataProvider';
import { getArtistDisplayName } from '../../utils/artistName';
import { Palette } from '../../styles';
import { FONT_FAMILY } from '../../styles/Fonts';
-import { size } from '../../styles/Style';
+import ProfilePicture from '../ProfilePicture';
let externalOpen;
let externalClose;
@@ -273,24 +272,7 @@ const CommentsBottomSheet = () => {
- {c?.profilePicture ? (
-
- ) : (
-
- )}
+
{
}, [handleDeleteProject, menuProject?.id]);
useEffect(() => {
- if (route?.params?.showLyricsCongrats) {
- Alert(
- "Céline",
- "Bravo ! Vous venez de terminer de créer les paroles de votre musique ! Maintenant vous pouvez passer à la prochaine étape : le Studio avec Malik. Dans cette étape vous allez pouvoir donner vie à votre chanson !"
- );
- navigation?.setParams?.({ showLyricsCongrats: false });
+ if (!route?.params?.showLyricsCongrats) {
+ return;
}
- }, [navigation, route?.params?.showLyricsCongrats]);
+ const beatmakerStage = currentProject
+ ? getStageAction("beatmaker", currentProject)
+ : null;
+ Alert(
+ "Céline",
+ "Bravo ! Vous venez de terminer de créer les paroles de votre musique ! Maintenant vous pouvez passer à la prochaine étape : le Studio avec Malik. Dans cette étape vous allez pouvoir donner vie à votre chanson !",
+ [
+ {
+ text: "Retour à l'accueil",
+ style: "cancel",
+ },
+ {
+ text: "Continuer avec Malik",
+ onPress: () => {
+ if (!currentProject?.id) {
+ return;
+ }
+ if (selectedProject?.id !== currentProject.id) {
+ selectProject(currentProject.id);
+ }
+ const targetRoute = beatmakerStage?.route || Routes.Compose;
+ navigate(targetRoute, beatmakerStage?.params);
+ },
+ },
+ ]
+ );
+ navigation?.setParams?.({ showLyricsCongrats: false });
+ }, [
+ currentProject,
+ navigation,
+ selectProject,
+ selectedProject?.id,
+ route?.params?.showLyricsCongrats,
+ ]);
const activeStage =
stageStates[activeStageIndex] || stageStates[preferredStageIndex];
diff --git a/src/screens/Library/components/SearchResultsList.js b/src/screens/Library/components/SearchResultsList.js
index abc3c7b..cff47ea 100644
--- a/src/screens/Library/components/SearchResultsList.js
+++ b/src/screens/Library/components/SearchResultsList.js
@@ -1,14 +1,12 @@
-import { Image as ExpoImage } from "expo-image";
import React, { useState } from "react";
import { Pressable, ScrollView, Text, View } from "react-native";
-import { img } from "../../../assets";
import MoreMenu from "../../../components/MoreMenu";
+import ProfilePicture from "../../../components/ProfilePicture";
import useNavigateToMusicDetails from "../../../hooks/useNavigateToMusicDetails";
import { Routes } from "../../../navigation";
import { navigate } from "../../../navigation/NavigationService";
import { Palette, Style } from "../../../styles";
import { FONT_FAMILY } from "../../../styles/Fonts";
-import { size } from "../../../styles/Style";
import { getArtistDisplayName } from "../../../utils/artistName";
import CreateLyricsHeader from "../../Writing/components/CreateLyricsHeader";
import MusicCard from "./MusicCard";
@@ -190,27 +188,15 @@ const SearchResultsList = ({
key={user.id}
onPress={() => handleProfilePress(user.id)}
>
-
{
navigate(Routes.SingerProfile, { userId: item?.userId });
}}
>
- {owner?.profilePictureURL ? (
-
- ) : (
-
- )}
+
{owner?.id && currentUID && owner.id !== currentUID && (
0 && styles.commentRowSpacing,
]}
>
- {c?.profilePicture ? (
-
- ) : (
-
- )}
+
@@ -315,14 +307,6 @@ const styles = StyleSheet.create({
marginTop: 16,
},
commentAvatar: {
- ...size({ size: 48 }),
- borderRadius: 100,
- marginRight: 12,
- },
- commentAvatarFallback: {
- ...size({ size: 48 }),
- borderRadius: 100,
- backgroundColor: "#FFFFFF33",
marginRight: 12,
},
commentBubble: {
diff --git a/src/screens/Profile/EditProfile.js b/src/screens/Profile/EditProfile.js
index 2cc4e3e..fce762c 100644
--- a/src/screens/Profile/EditProfile.js
+++ b/src/screens/Profile/EditProfile.js
@@ -1,12 +1,12 @@
import { BlurView } from "expo-blur";
-import { Image as ExpoImage } from "expo-image";
import * as ImagePicker from "expo-image-picker";
import React, { useEffect, useState } from "react";
import { Platform, Pressable, Text, View } from "react-native";
import { responsiveHeight } from "react-native-responsive-dimensions";
import { useGlobal } from "reactn";
-import { background, img } from "../../assets";
+import { background } from "../../assets";
import GradientButton from "../../components/GradientButton";
+import ProfilePicture from "../../components/ProfilePicture";
import firebase, { serverTimestamp, usersRef } from "../../config/firebase";
import { uploadFileToFirebase } from "../../helpers/uploadToFirebase";
import { isWeb } from "../../hooks/useLayoutType";
@@ -15,7 +15,6 @@ import { goBack } from "../../navigation/NavigationService";
import { useUser } from "../../providers/UserDataProvider";
import { gutters, Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
-import { size } from "../../styles/Style";
import EditInput from "./components/EditInput";
const EditProfile = () => {
@@ -147,22 +146,10 @@ const EditProfile = () => {
// }
>
-
{
const { params } = useRoute();
@@ -92,17 +91,10 @@ const Follows = () => {
style={{ gap: 14, ...Style.containerRow }}
onPress={() => navigate(Routes.SingerProfile, { userId: user?.id })}
>
-
{
-
{isSelf && (
{
@@ -264,17 +265,49 @@ const Lyrics = ({ navigation }) => {
if (!isSame) {
updateData.musicUrls = firebase.firestore.FieldValue.delete();
updateData.musicStatus = firebase.firestore.FieldValue.delete();
- await projectsRef
- .doc(selectedProjectId)
- .set(updateData, { merge: true });
}
- navigate(Routes.BottomTab, {
- screen: Routes.HomeStack,
- params: {
- screen: Routes.Home,
- params: { showLyricsCongrats: true },
- },
- });
+ await projectsRef
+ .doc(selectedProjectId)
+ .set(updateData, { merge: true });
+ const projectForStage = {
+ ...selectedProject,
+ title: titleTrimmed,
+ lyrics: normalizedNewLyrics,
+ config: sanitize(projectConfig),
+ selections: sanitize(projectSelections),
+ hasLyrics: true,
+ };
+ if (!isSame) {
+ projectForStage.musicUrls = undefined;
+ projectForStage.musicStatus = undefined;
+ }
+ const beatmakerStage = getStageAction("beatmaker", projectForStage);
+ await setIsLoading(false);
+ alert(
+ "Céline",
+ "Bravo ! Vous venez de terminer de créer les paroles de votre musique ! Maintenant vous pouvez passer à la prochaine étape : le Studio avec Malik. Dans cette étape vous allez pouvoir donner vie à votre chanson !",
+ [
+ {
+ text: "Retour à l'accueil",
+ style: "cancel",
+ onPress: () =>
+ navigate(Routes.BottomTab, {
+ screen: Routes.HomeStack,
+ params: {
+ screen: Routes.Home,
+ },
+ }),
+ },
+ {
+ text: "Continuer avec Malik",
+ onPress: () => {
+ const targetRoute = beatmakerStage?.route || Routes.Compose;
+ navigate(targetRoute, beatmakerStage?.params);
+ },
+ },
+ ]
+ );
+ return;
} catch (e) {
console.log(e);
alertMessage("Erreur", "Échec de l'enregistrement dans le projet.");
@@ -293,6 +326,7 @@ const Lyrics = ({ navigation }) => {
selectedProjectId,
projectHasLyrics,
projectLyrics,
+ selectedProject,
]);
const typeOccurrences = {};
diff --git a/src/screens/cover/ValidateCover.js b/src/screens/cover/ValidateCover.js
index 7dd441f..3b0496f 100644
--- a/src/screens/cover/ValidateCover.js
+++ b/src/screens/cover/ValidateCover.js
@@ -3,6 +3,7 @@ import React, { useCallback, useMemo, useState } from "react";
import { Pressable, Text, View } from "react-native";
import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
import { background } from "../../assets";
+import alert from "../../components/Alert";
import GradientButton from "../../components/GradientButton";
import MusicLandHeader from "../../components/MusicLandHeader";
import { isWeb } from "../../hooks/useLayoutType";
@@ -11,6 +12,7 @@ import { Routes } from "../../navigation";
import { goBack, navigate } from "../../navigation/NavigationService";
import { useUserData } from "../../providers/UserDataProvider";
import { gutters, Palette, Style } from "../../styles";
+import { getStageAction } from "../../utils/projectStages";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
const ValidateCover = () => {
@@ -95,18 +97,46 @@ const ValidateCover = () => {
const existingCover = selectedProject?.cover || {};
const finalUrl =
selectedOption.finalUrl || selectedOption.generatedUrl || null;
+ const nextCoverData = {
+ ...existingCover,
+ options: coverOptions,
+ selectedOptionId: selectedOption.id,
+ result: finalUrl,
+ generatedBackground:
+ selectedOption.generatedUrl || selectedOption.finalUrl || null,
+ };
await updateProjectData({
- cover: {
- ...existingCover,
- options: coverOptions,
- selectedOptionId: selectedOption.id,
- result: finalUrl,
- generatedBackground:
- selectedOption.generatedUrl || selectedOption.finalUrl || null,
- },
+ cover: nextCoverData,
coverUrl: finalUrl,
});
- navigate(Routes.Home);
+ const projectForStage = {
+ ...selectedProject,
+ cover: nextCoverData,
+ coverUrl: finalUrl,
+ };
+ const playbackStage = getStageAction("director", projectForStage);
+ await setIsLoading(false);
+ alert(
+ "Malik",
+ "Super ! Ta pochette est validée. Tu peux retourner à l'accueil ou continuer avec John pour produire ton playback.",
+ [
+ {
+ text: "Retour à l'accueil",
+ style: "cancel",
+ onPress: () => navigate(Routes.Home),
+ },
+ {
+ text: "Continuer avec John",
+ onPress: () => {
+ const targetRoute = playbackStage?.route || Routes.Playback;
+ const params =
+ playbackStage?.params || { project: projectForStage };
+ navigate(targetRoute, params);
+ },
+ },
+ ]
+ );
+ return;
} catch (e) {
console.log(e);
} finally {