fix web flow
This commit is contained in:
@@ -12,9 +12,9 @@ import {
|
|||||||
View,
|
View,
|
||||||
useWindowDimensions,
|
useWindowDimensions,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import PersonaCard from "../cards/PersonaCard/PersonaCard";
|
|
||||||
import { ai } from "../../assets";
|
import { ai } from "../../assets";
|
||||||
import { getCreationStageStates } from "../../utils/projectStages";
|
import { getCreationStageStates } from "../../utils/projectStages";
|
||||||
|
import PersonaCard from "../cards/PersonaCard/PersonaCard";
|
||||||
|
|
||||||
const STAGE_CARD_CONTENT = [
|
const STAGE_CARD_CONTENT = [
|
||||||
{
|
{
|
||||||
@@ -43,6 +43,8 @@ const STAGE_CARD_CONTENT = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const WEB_SCROLL_INACTIVE_DELTA = 0.05;
|
||||||
|
|
||||||
const FeatureCarousel = ({
|
const FeatureCarousel = ({
|
||||||
style,
|
style,
|
||||||
selectedProject,
|
selectedProject,
|
||||||
@@ -63,14 +65,14 @@ const FeatureCarousel = ({
|
|||||||
...item,
|
...item,
|
||||||
isLocked: stageStates[index]?.isLocked ?? true,
|
isLocked: stageStates[index]?.isLocked ?? true,
|
||||||
})),
|
})),
|
||||||
[stageStates],
|
[stageStates]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { height: windowHeight } = useWindowDimensions();
|
const { height: windowHeight } = useWindowDimensions();
|
||||||
const isWeb = Platform.OS === "web";
|
const isWeb = Platform.OS === "web";
|
||||||
|
|
||||||
const [viewportHeight, setViewportHeight] = useState(() =>
|
const [viewportHeight, setViewportHeight] = useState(() =>
|
||||||
Math.max(windowHeight, 1),
|
Math.max(windowHeight, 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateSnapHeight = useCallback((height) => {
|
const updateSnapHeight = useCallback((height) => {
|
||||||
@@ -95,7 +97,7 @@ const FeatureCarousel = ({
|
|||||||
const pendingScrollRef = useRef(false);
|
const pendingScrollRef = useRef(false);
|
||||||
const alignTimeoutRef = useRef(null);
|
const alignTimeoutRef = useRef(null);
|
||||||
const activeIndexRef = useRef(
|
const activeIndexRef = useRef(
|
||||||
typeof activeIndex === "number" ? activeIndex : 0,
|
typeof activeIndex === "number" ? activeIndex : 0
|
||||||
);
|
);
|
||||||
const onActiveIndexChangeRef = useRef(onActiveIndexChange);
|
const onActiveIndexChangeRef = useRef(onActiveIndexChange);
|
||||||
|
|
||||||
@@ -122,12 +124,12 @@ const FeatureCarousel = ({
|
|||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
},
|
},
|
||||||
[carouselItems.length],
|
[carouselItems.length]
|
||||||
);
|
);
|
||||||
|
|
||||||
const clearPendingAlignment = useCallback(() => {
|
const clearPendingAlignment = useCallback(() => {
|
||||||
if (alignTimeoutRef.current != null) {
|
if (alignTimeoutRef.current != null) {
|
||||||
clearTimeout(alignTimeoutRef.current);
|
globalThis.clearTimeout(alignTimeoutRef.current);
|
||||||
alignTimeoutRef.current = null;
|
alignTimeoutRef.current = null;
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
@@ -151,7 +153,7 @@ const FeatureCarousel = ({
|
|||||||
}
|
}
|
||||||
updateSnapHeight(height);
|
updateSnapHeight(height);
|
||||||
try {
|
try {
|
||||||
ref.scrollToOffset({ offset: clamped * height, animated: false });
|
ref.scrollToOffset({ offset: clamped * height, animated });
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
// Ignore scroll errors when list is not ready yet.
|
// Ignore scroll errors when list is not ready yet.
|
||||||
}
|
}
|
||||||
@@ -167,7 +169,7 @@ const FeatureCarousel = ({
|
|||||||
pendingScrollRef.current = false;
|
pendingScrollRef.current = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[clampIndex, isWeb, itemHeight, updateSnapHeight],
|
[clampIndex, isWeb, itemHeight, updateSnapHeight]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -200,7 +202,23 @@ const FeatureCarousel = ({
|
|||||||
|
|
||||||
updateSnapHeight(height);
|
updateSnapHeight(height);
|
||||||
|
|
||||||
const nextIndex = clampIndex(Math.round(offset / height));
|
const currentIndex = activeIndexRef.current;
|
||||||
|
const rawIndex = height ? offset / height : currentIndex;
|
||||||
|
|
||||||
|
let nextIndex = currentIndex;
|
||||||
|
if (isWeb) {
|
||||||
|
const delta = rawIndex - currentIndex;
|
||||||
|
if (Math.abs(delta) > WEB_SCROLL_INACTIVE_DELTA) {
|
||||||
|
if (Math.abs(delta) <= 1) {
|
||||||
|
nextIndex = clampIndex(currentIndex + (delta > 0 ? 1 : -1));
|
||||||
|
} else {
|
||||||
|
nextIndex = clampIndex(currentIndex + Math.round(delta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextIndex = clampIndex(Math.round(rawIndex));
|
||||||
|
}
|
||||||
|
|
||||||
const hasChanged = nextIndex !== activeIndexRef.current;
|
const hasChanged = nextIndex !== activeIndexRef.current;
|
||||||
|
|
||||||
if (hasChanged) {
|
if (hasChanged) {
|
||||||
@@ -212,10 +230,11 @@ const FeatureCarousel = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isWeb || hasChanged) {
|
if (isWeb || hasChanged) {
|
||||||
scrollToIndex(nextIndex, !isWeb, height);
|
const shouldAnimate = isWeb ? true : !isWeb;
|
||||||
|
scrollToIndex(nextIndex, shouldAnimate, height);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[clampIndex, isWeb, itemHeight, scrollToIndex, updateSnapHeight],
|
[clampIndex, isWeb, itemHeight, scrollToIndex, updateSnapHeight]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleScrollEnd = useCallback(
|
const handleScrollEnd = useCallback(
|
||||||
@@ -225,7 +244,7 @@ const FeatureCarousel = ({
|
|||||||
const layoutHeight = event?.nativeEvent?.layoutMeasurement?.height;
|
const layoutHeight = event?.nativeEvent?.layoutMeasurement?.height;
|
||||||
alignToOffset(offsetY, layoutHeight);
|
alignToOffset(offsetY, layoutHeight);
|
||||||
},
|
},
|
||||||
[alignToOffset, clearPendingAlignment],
|
[alignToOffset, clearPendingAlignment]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleScroll = useCallback(
|
const handleScroll = useCallback(
|
||||||
@@ -236,12 +255,12 @@ const FeatureCarousel = ({
|
|||||||
const offsetY = event?.nativeEvent?.contentOffset?.y ?? 0;
|
const offsetY = event?.nativeEvent?.contentOffset?.y ?? 0;
|
||||||
const layoutHeight = event?.nativeEvent?.layoutMeasurement?.height;
|
const layoutHeight = event?.nativeEvent?.layoutMeasurement?.height;
|
||||||
clearPendingAlignment();
|
clearPendingAlignment();
|
||||||
alignTimeoutRef.current = setTimeout(() => {
|
alignTimeoutRef.current = globalThis.setTimeout(() => {
|
||||||
alignToOffset(offsetY, layoutHeight);
|
alignToOffset(offsetY, layoutHeight);
|
||||||
alignTimeoutRef.current = null;
|
alignTimeoutRef.current = null;
|
||||||
}, 80);
|
}, 80);
|
||||||
},
|
},
|
||||||
[alignToOffset, clearPendingAlignment, isWeb],
|
[alignToOffset, clearPendingAlignment, isWeb]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleLayout = useCallback(
|
const handleLayout = useCallback(
|
||||||
@@ -251,7 +270,7 @@ const FeatureCarousel = ({
|
|||||||
updateSnapHeight(layoutHeight);
|
updateSnapHeight(layoutHeight);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[updateSnapHeight],
|
[updateSnapHeight]
|
||||||
);
|
);
|
||||||
|
|
||||||
const keyExtractor = useCallback((item) => item.key, []);
|
const keyExtractor = useCallback((item) => item.key, []);
|
||||||
@@ -265,7 +284,7 @@ const FeatureCarousel = ({
|
|||||||
height={itemHeight}
|
height={itemHeight}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[itemHeight],
|
[itemHeight]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getItemLayout = useCallback(
|
const getItemLayout = useCallback(
|
||||||
@@ -274,7 +293,7 @@ const FeatureCarousel = ({
|
|||||||
offset: itemHeight * index,
|
offset: itemHeight * index,
|
||||||
index,
|
index,
|
||||||
}),
|
}),
|
||||||
[itemHeight],
|
[itemHeight]
|
||||||
);
|
);
|
||||||
|
|
||||||
const viewabilityConfig = useRef({ viewAreaCoveragePercentThreshold: 60 });
|
const viewabilityConfig = useRef({ viewAreaCoveragePercentThreshold: 60 });
|
||||||
@@ -303,7 +322,7 @@ const FeatureCarousel = ({
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return carouselItems.map((_, index) => index * itemHeight);
|
return carouselItems.map((_, index) => index * itemHeight);
|
||||||
}, [carouselItems.length, isWeb, itemHeight]);
|
}, [carouselItems, isWeb, itemHeight]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, style]} onLayout={handleLayout}>
|
<View style={[styles.container, style]} onLayout={handleLayout}>
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
export const OTHER_OBJECTIVE_OPTION = "Autre objectif";
|
||||||
|
export const OTHER_STYLE_OPTION = "Autre style";
|
||||||
|
|
||||||
export const GOALS = [
|
export const GOALS = [
|
||||||
"Envoyer un message universel",
|
"Envoyer un message universel",
|
||||||
"Souhaiter un joyeux anniversaire à un ami",
|
"Souhaiter un joyeux anniversaire à un ami",
|
||||||
@@ -6,6 +9,7 @@ export const GOALS = [
|
|||||||
"Pour un mariage",
|
"Pour un mariage",
|
||||||
"Pour mon entreprise",
|
"Pour mon entreprise",
|
||||||
"Envoyer un message politique",
|
"Envoyer un message politique",
|
||||||
|
OTHER_OBJECTIVE_OPTION,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const EMOTION_CONVEY = [
|
export const EMOTION_CONVEY = [
|
||||||
@@ -182,6 +186,10 @@ export const SONG_STYLE = [
|
|||||||
title: "Melancholic",
|
title: "Melancholic",
|
||||||
description: "ambiance mélancolique",
|
description: "ambiance mélancolique",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: OTHER_STYLE_OPTION,
|
||||||
|
description: "Décris ton style personnalisé",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CUSTOM_SONG_STRUCTURE = [
|
export const CUSTOM_SONG_STRUCTURE = [
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { SwiperFlatList } from "react-native-swiper-flatlist";
|
|||||||
import { background } from "../../assets";
|
import { background } from "../../assets";
|
||||||
import GradientButton from "../../components/GradientButton";
|
import GradientButton from "../../components/GradientButton";
|
||||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||||
|
import { OTHER_OBJECTIVE_OPTION, OTHER_STYLE_OPTION } from "../../data/data";
|
||||||
import useLayoutType from "../../hooks/useLayoutType";
|
import useLayoutType from "../../hooks/useLayoutType";
|
||||||
import Page from "../../layouts/Page";
|
import Page from "../../layouts/Page";
|
||||||
import { Routes } from "../../navigation";
|
import { Routes } from "../../navigation";
|
||||||
@@ -44,6 +45,18 @@ const CreateLyricsWithAi = () => {
|
|||||||
const [rhymes, setRhymes] = useState(null);
|
const [rhymes, setRhymes] = useState(null);
|
||||||
const [customStructure, setCustomStructure] = useState(null); // array like ['couplet','refrain']
|
const [customStructure, setCustomStructure] = useState(null); // array like ['couplet','refrain']
|
||||||
|
|
||||||
|
const trimmedOtherObjective =
|
||||||
|
typeof otherObjective === "string" ? otherObjective.trim() : "";
|
||||||
|
const shouldUseOtherObjective = objective === OTHER_OBJECTIVE_OPTION;
|
||||||
|
const persistedOtherObjective = shouldUseOtherObjective
|
||||||
|
? trimmedOtherObjective
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const trimmedOtherStyle =
|
||||||
|
typeof otherStyle === "string" ? otherStyle.trim() : "";
|
||||||
|
const shouldUseOtherStyle = style === OTHER_STYLE_OPTION;
|
||||||
|
const persistedOtherStyle = shouldUseOtherStyle ? trimmedOtherStyle : "";
|
||||||
|
|
||||||
// Pré-remplir les états depuis le projet sélectionné si disponibles
|
// Pré-remplir les états depuis le projet sélectionné si disponibles
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!selectedProject) return;
|
if (!selectedProject) return;
|
||||||
@@ -52,19 +65,28 @@ const CreateLyricsWithAi = () => {
|
|||||||
|
|
||||||
const rawOtherObjective =
|
const rawOtherObjective =
|
||||||
typeof sel.otherObjective === "string" ? sel.otherObjective : "";
|
typeof sel.otherObjective === "string" ? sel.otherObjective : "";
|
||||||
const hasSavedOtherObjective = rawOtherObjective.trim().length > 0;
|
const trimmedSavedOtherObjective = rawOtherObjective.trim();
|
||||||
|
const hasSavedOtherObjective = trimmedSavedOtherObjective.length > 0;
|
||||||
const savedObjective =
|
const savedObjective =
|
||||||
typeof sel.objective === "string" && sel.objective.trim().length > 0
|
typeof sel.objective === "string" && sel.objective.trim().length > 0
|
||||||
? sel.objective
|
? sel.objective.trim()
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!otherObjective && hasSavedOtherObjective) {
|
if (!otherObjective && hasSavedOtherObjective) {
|
||||||
setOtherObjective(rawOtherObjective);
|
setOtherObjective(rawOtherObjective);
|
||||||
if (objective !== null) {
|
}
|
||||||
setObjective(null);
|
|
||||||
}
|
const shouldSelectOtherObjective =
|
||||||
} else if (!hasSavedOtherObjective && objective == null && savedObjective) {
|
hasSavedOtherObjective &&
|
||||||
setObjective(savedObjective);
|
(!savedObjective || savedObjective === OTHER_OBJECTIVE_OPTION);
|
||||||
|
const resolvedSavedObjective = shouldSelectOtherObjective
|
||||||
|
? OTHER_OBJECTIVE_OPTION
|
||||||
|
: savedObjective;
|
||||||
|
|
||||||
|
if (resolvedSavedObjective && objective !== resolvedSavedObjective) {
|
||||||
|
setObjective(resolvedSavedObjective);
|
||||||
|
} else if (!resolvedSavedObjective && objective !== null) {
|
||||||
|
setObjective(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context && typeof sel.context === "string") setContext(sel.context);
|
if (!context && typeof sel.context === "string") setContext(sel.context);
|
||||||
@@ -86,19 +108,24 @@ const CreateLyricsWithAi = () => {
|
|||||||
|
|
||||||
const rawOtherStyle =
|
const rawOtherStyle =
|
||||||
typeof sel.otherStyle === "string" ? sel.otherStyle : "";
|
typeof sel.otherStyle === "string" ? sel.otherStyle : "";
|
||||||
const hasSavedOtherStyle = rawOtherStyle.trim().length > 0;
|
const trimmedSavedOtherStyle = rawOtherStyle.trim();
|
||||||
|
const hasSavedOtherStyle = trimmedSavedOtherStyle.length > 0;
|
||||||
const savedStyle =
|
const savedStyle =
|
||||||
typeof sel.style === "string" && sel.style.trim().length > 0
|
typeof sel.style === "string" && sel.style.trim().length > 0
|
||||||
? sel.style
|
? sel.style.trim()
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!otherStyle && hasSavedOtherStyle) {
|
if (!otherStyle && hasSavedOtherStyle) {
|
||||||
setOtherStyle(rawOtherStyle);
|
setOtherStyle(rawOtherStyle);
|
||||||
if (style !== null) {
|
}
|
||||||
setStyle(null);
|
const shouldSelectOtherStyle =
|
||||||
}
|
hasSavedOtherStyle && (!savedStyle || savedStyle === OTHER_STYLE_OPTION);
|
||||||
} else if (!hasSavedOtherStyle && style == null && savedStyle) {
|
const resolvedSavedStyle = shouldSelectOtherStyle
|
||||||
setStyle(savedStyle);
|
? OTHER_STYLE_OPTION
|
||||||
|
: savedStyle;
|
||||||
|
if (resolvedSavedStyle && style !== resolvedSavedStyle) {
|
||||||
|
setStyle(resolvedSavedStyle);
|
||||||
|
} else if (!resolvedSavedStyle && style !== null) {
|
||||||
|
setStyle(null);
|
||||||
}
|
}
|
||||||
if (!audience && typeof sel.audience === "string")
|
if (!audience && typeof sel.audience === "string")
|
||||||
setAudience(sel.audience);
|
setAudience(sel.audience);
|
||||||
@@ -154,16 +181,21 @@ const CreateLyricsWithAi = () => {
|
|||||||
}, [hasLyrics]);
|
}, [hasLyrics]);
|
||||||
|
|
||||||
const lyricsConfig = useMemo(() => {
|
const lyricsConfig = useMemo(() => {
|
||||||
|
const resolvedObjective = shouldUseOtherObjective
|
||||||
|
? persistedOtherObjective || undefined
|
||||||
|
: objective || undefined;
|
||||||
|
const resolvedStyle = shouldUseOtherStyle
|
||||||
|
? persistedOtherStyle || undefined
|
||||||
|
: style || undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
objective: otherObjective?.trim()
|
objective: resolvedObjective,
|
||||||
? otherObjective.trim()
|
|
||||||
: objective || undefined,
|
|
||||||
context: context?.trim() ? context.trim() : undefined,
|
context: context?.trim() ? context.trim() : undefined,
|
||||||
emotion:
|
emotion:
|
||||||
emotion?.title && emotion?.description
|
emotion?.title && emotion?.description
|
||||||
? `${emotion.title} : ${emotion.description}`
|
? `${emotion.title} : ${emotion.description}`
|
||||||
: undefined,
|
: undefined,
|
||||||
style: otherStyle?.trim() ? otherStyle.trim() : style || undefined,
|
style: resolvedStyle,
|
||||||
audience: audience?.trim() ? audience.trim() : undefined,
|
audience: audience?.trim() ? audience.trim() : undefined,
|
||||||
structure:
|
structure:
|
||||||
(customStructure &&
|
(customStructure &&
|
||||||
@@ -174,12 +206,14 @@ const CreateLyricsWithAi = () => {
|
|||||||
rhymes: rhymes || undefined,
|
rhymes: rhymes || undefined,
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
|
shouldUseOtherObjective,
|
||||||
|
persistedOtherObjective,
|
||||||
objective,
|
objective,
|
||||||
otherObjective,
|
shouldUseOtherStyle,
|
||||||
|
persistedOtherStyle,
|
||||||
context,
|
context,
|
||||||
emotion,
|
emotion,
|
||||||
style,
|
style,
|
||||||
otherStyle,
|
|
||||||
audience,
|
audience,
|
||||||
parsedStructure,
|
parsedStructure,
|
||||||
rhymes,
|
rhymes,
|
||||||
@@ -191,9 +225,7 @@ const CreateLyricsWithAi = () => {
|
|||||||
case 0: {
|
case 0: {
|
||||||
const hasObjective =
|
const hasObjective =
|
||||||
typeof objective === "string" && objective.length > 0;
|
typeof objective === "string" && objective.length > 0;
|
||||||
const hasOther =
|
const hasOther = trimmedOtherObjective.length > 0;
|
||||||
typeof otherObjective === "string" &&
|
|
||||||
otherObjective.trim().length > 0;
|
|
||||||
return !(hasObjective || hasOther);
|
return !(hasObjective || hasOther);
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
@@ -209,8 +241,7 @@ const CreateLyricsWithAi = () => {
|
|||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
const hasStyle = typeof style === "string" && style.length > 0;
|
const hasStyle = typeof style === "string" && style.length > 0;
|
||||||
const hasOther =
|
const hasOther = trimmedOtherStyle.length > 0;
|
||||||
typeof otherStyle === "string" && otherStyle.trim().length > 0;
|
|
||||||
return !(hasStyle || hasOther);
|
return !(hasStyle || hasOther);
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
@@ -233,11 +264,11 @@ const CreateLyricsWithAi = () => {
|
|||||||
}, [
|
}, [
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
objective,
|
objective,
|
||||||
otherObjective,
|
trimmedOtherObjective,
|
||||||
context,
|
context,
|
||||||
emotion,
|
emotion,
|
||||||
style,
|
style,
|
||||||
otherStyle,
|
trimmedOtherStyle,
|
||||||
audience,
|
audience,
|
||||||
structure,
|
structure,
|
||||||
rhymes,
|
rhymes,
|
||||||
@@ -257,11 +288,11 @@ const CreateLyricsWithAi = () => {
|
|||||||
config: { structure: chosenStructure },
|
config: { structure: chosenStructure },
|
||||||
selections: {
|
selections: {
|
||||||
objective,
|
objective,
|
||||||
otherObjective,
|
otherObjective: persistedOtherObjective,
|
||||||
context,
|
context,
|
||||||
emotion,
|
emotion,
|
||||||
style,
|
style,
|
||||||
otherStyle,
|
otherStyle: persistedOtherStyle,
|
||||||
audience,
|
audience,
|
||||||
structure,
|
structure,
|
||||||
parsedStructure,
|
parsedStructure,
|
||||||
@@ -433,11 +464,11 @@ const CreateLyricsWithAi = () => {
|
|||||||
config={lyricsConfig}
|
config={lyricsConfig}
|
||||||
selections={{
|
selections={{
|
||||||
objective,
|
objective,
|
||||||
otherObjective,
|
otherObjective: persistedOtherObjective,
|
||||||
context,
|
context,
|
||||||
emotion,
|
emotion,
|
||||||
style,
|
style,
|
||||||
otherStyle,
|
otherStyle: persistedOtherStyle,
|
||||||
audience,
|
audience,
|
||||||
structure,
|
structure,
|
||||||
parsedStructure,
|
parsedStructure,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { responsiveHeight } from "react-native-responsive-dimensions";
|
|||||||
import { background } from "../../assets";
|
import { background } from "../../assets";
|
||||||
import GradientButton from "../../components/GradientButton";
|
import GradientButton from "../../components/GradientButton";
|
||||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||||
|
import { OTHER_OBJECTIVE_OPTION, OTHER_STYLE_OPTION } from "../../data/data";
|
||||||
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";
|
||||||
@@ -42,6 +43,18 @@ const CreateLyricsWithAi = () => {
|
|||||||
const [rhymes, setRhymes] = useState(null);
|
const [rhymes, setRhymes] = useState(null);
|
||||||
const [customStructure, setCustomStructure] = useState(null); // array like ['couplet','refrain']
|
const [customStructure, setCustomStructure] = useState(null); // array like ['couplet','refrain']
|
||||||
|
|
||||||
|
const trimmedOtherObjective =
|
||||||
|
typeof otherObjective === "string" ? otherObjective.trim() : "";
|
||||||
|
const shouldUseOtherObjective = objective === OTHER_OBJECTIVE_OPTION;
|
||||||
|
const persistedOtherObjective = shouldUseOtherObjective
|
||||||
|
? trimmedOtherObjective
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const trimmedOtherStyle =
|
||||||
|
typeof otherStyle === "string" ? otherStyle.trim() : "";
|
||||||
|
const shouldUseOtherStyle = style === OTHER_STYLE_OPTION;
|
||||||
|
const persistedOtherStyle = shouldUseOtherStyle ? trimmedOtherStyle : "";
|
||||||
|
|
||||||
// Pré-remplir les états depuis le projet sélectionné si disponibles
|
// Pré-remplir les états depuis le projet sélectionné si disponibles
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!selectedProject) return;
|
if (!selectedProject) return;
|
||||||
@@ -50,19 +63,28 @@ const CreateLyricsWithAi = () => {
|
|||||||
|
|
||||||
const rawOtherObjective =
|
const rawOtherObjective =
|
||||||
typeof sel.otherObjective === "string" ? sel.otherObjective : "";
|
typeof sel.otherObjective === "string" ? sel.otherObjective : "";
|
||||||
const hasSavedOtherObjective = rawOtherObjective.trim().length > 0;
|
const trimmedSavedOtherObjective = rawOtherObjective.trim();
|
||||||
|
const hasSavedOtherObjective = trimmedSavedOtherObjective.length > 0;
|
||||||
const savedObjective =
|
const savedObjective =
|
||||||
typeof sel.objective === "string" && sel.objective.trim().length > 0
|
typeof sel.objective === "string" && sel.objective.trim().length > 0
|
||||||
? sel.objective
|
? sel.objective.trim()
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!otherObjective && hasSavedOtherObjective) {
|
if (!otherObjective && hasSavedOtherObjective) {
|
||||||
setOtherObjective(rawOtherObjective);
|
setOtherObjective(rawOtherObjective);
|
||||||
if (objective !== null) {
|
}
|
||||||
setObjective(null);
|
|
||||||
}
|
const shouldSelectOtherObjective =
|
||||||
} else if (!hasSavedOtherObjective && objective == null && savedObjective) {
|
hasSavedOtherObjective &&
|
||||||
setObjective(savedObjective);
|
(!savedObjective || savedObjective === OTHER_OBJECTIVE_OPTION);
|
||||||
|
const resolvedSavedObjective = shouldSelectOtherObjective
|
||||||
|
? OTHER_OBJECTIVE_OPTION
|
||||||
|
: savedObjective;
|
||||||
|
|
||||||
|
if (resolvedSavedObjective && objective !== resolvedSavedObjective) {
|
||||||
|
setObjective(resolvedSavedObjective);
|
||||||
|
} else if (!resolvedSavedObjective && objective !== null) {
|
||||||
|
setObjective(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context && typeof sel.context === "string") setContext(sel.context);
|
if (!context && typeof sel.context === "string") setContext(sel.context);
|
||||||
@@ -84,19 +106,24 @@ const CreateLyricsWithAi = () => {
|
|||||||
|
|
||||||
const rawOtherStyle =
|
const rawOtherStyle =
|
||||||
typeof sel.otherStyle === "string" ? sel.otherStyle : "";
|
typeof sel.otherStyle === "string" ? sel.otherStyle : "";
|
||||||
const hasSavedOtherStyle = rawOtherStyle.trim().length > 0;
|
const trimmedSavedOtherStyle = rawOtherStyle.trim();
|
||||||
|
const hasSavedOtherStyle = trimmedSavedOtherStyle.length > 0;
|
||||||
const savedStyle =
|
const savedStyle =
|
||||||
typeof sel.style === "string" && sel.style.trim().length > 0
|
typeof sel.style === "string" && sel.style.trim().length > 0
|
||||||
? sel.style
|
? sel.style.trim()
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!otherStyle && hasSavedOtherStyle) {
|
if (!otherStyle && hasSavedOtherStyle) {
|
||||||
setOtherStyle(rawOtherStyle);
|
setOtherStyle(rawOtherStyle);
|
||||||
if (style !== null) {
|
}
|
||||||
setStyle(null);
|
const shouldSelectOtherStyle =
|
||||||
}
|
hasSavedOtherStyle && (!savedStyle || savedStyle === OTHER_STYLE_OPTION);
|
||||||
} else if (!hasSavedOtherStyle && style == null && savedStyle) {
|
const resolvedSavedStyle = shouldSelectOtherStyle
|
||||||
setStyle(savedStyle);
|
? OTHER_STYLE_OPTION
|
||||||
|
: savedStyle;
|
||||||
|
if (resolvedSavedStyle && style !== resolvedSavedStyle) {
|
||||||
|
setStyle(resolvedSavedStyle);
|
||||||
|
} else if (!resolvedSavedStyle && style !== null) {
|
||||||
|
setStyle(null);
|
||||||
}
|
}
|
||||||
if (!audience && typeof sel.audience === "string")
|
if (!audience && typeof sel.audience === "string")
|
||||||
setAudience(sel.audience);
|
setAudience(sel.audience);
|
||||||
@@ -159,16 +186,21 @@ const CreateLyricsWithAi = () => {
|
|||||||
}, [hasLyrics]);
|
}, [hasLyrics]);
|
||||||
|
|
||||||
const lyricsConfig = useMemo(() => {
|
const lyricsConfig = useMemo(() => {
|
||||||
|
const resolvedObjective = shouldUseOtherObjective
|
||||||
|
? persistedOtherObjective || undefined
|
||||||
|
: objective || undefined;
|
||||||
|
const resolvedStyle = shouldUseOtherStyle
|
||||||
|
? persistedOtherStyle || undefined
|
||||||
|
: style || undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
objective: otherObjective?.trim()
|
objective: resolvedObjective,
|
||||||
? otherObjective.trim()
|
|
||||||
: objective || undefined,
|
|
||||||
context: context?.trim() ? context.trim() : undefined,
|
context: context?.trim() ? context.trim() : undefined,
|
||||||
emotion:
|
emotion:
|
||||||
emotion?.title && emotion?.description
|
emotion?.title && emotion?.description
|
||||||
? `${emotion.title} : ${emotion.description}`
|
? `${emotion.title} : ${emotion.description}`
|
||||||
: undefined,
|
: undefined,
|
||||||
style: otherStyle?.trim() ? otherStyle.trim() : style || undefined,
|
style: resolvedStyle,
|
||||||
audience: audience?.trim() ? audience.trim() : undefined,
|
audience: audience?.trim() ? audience.trim() : undefined,
|
||||||
structure:
|
structure:
|
||||||
(customStructure &&
|
(customStructure &&
|
||||||
@@ -179,12 +211,14 @@ const CreateLyricsWithAi = () => {
|
|||||||
rhymes: rhymes || undefined,
|
rhymes: rhymes || undefined,
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
|
shouldUseOtherObjective,
|
||||||
|
persistedOtherObjective,
|
||||||
objective,
|
objective,
|
||||||
otherObjective,
|
shouldUseOtherStyle,
|
||||||
|
persistedOtherStyle,
|
||||||
context,
|
context,
|
||||||
emotion,
|
emotion,
|
||||||
style,
|
style,
|
||||||
otherStyle,
|
|
||||||
audience,
|
audience,
|
||||||
parsedStructure,
|
parsedStructure,
|
||||||
rhymes,
|
rhymes,
|
||||||
@@ -196,9 +230,7 @@ const CreateLyricsWithAi = () => {
|
|||||||
case 0: {
|
case 0: {
|
||||||
const hasObjective =
|
const hasObjective =
|
||||||
typeof objective === "string" && objective.length > 0;
|
typeof objective === "string" && objective.length > 0;
|
||||||
const hasOther =
|
const hasOther = trimmedOtherObjective.length > 0;
|
||||||
typeof otherObjective === "string" &&
|
|
||||||
otherObjective.trim().length > 0;
|
|
||||||
return !(hasObjective || hasOther);
|
return !(hasObjective || hasOther);
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
@@ -214,8 +246,7 @@ const CreateLyricsWithAi = () => {
|
|||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
const hasStyle = typeof style === "string" && style.length > 0;
|
const hasStyle = typeof style === "string" && style.length > 0;
|
||||||
const hasOther =
|
const hasOther = trimmedOtherStyle.length > 0;
|
||||||
typeof otherStyle === "string" && otherStyle.trim().length > 0;
|
|
||||||
return !(hasStyle || hasOther);
|
return !(hasStyle || hasOther);
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
@@ -238,11 +269,11 @@ const CreateLyricsWithAi = () => {
|
|||||||
}, [
|
}, [
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
objective,
|
objective,
|
||||||
otherObjective,
|
trimmedOtherObjective,
|
||||||
context,
|
context,
|
||||||
emotion,
|
emotion,
|
||||||
style,
|
style,
|
||||||
otherStyle,
|
trimmedOtherStyle,
|
||||||
audience,
|
audience,
|
||||||
structure,
|
structure,
|
||||||
rhymes,
|
rhymes,
|
||||||
@@ -262,11 +293,11 @@ const CreateLyricsWithAi = () => {
|
|||||||
config: { structure: chosenStructure },
|
config: { structure: chosenStructure },
|
||||||
selections: {
|
selections: {
|
||||||
objective,
|
objective,
|
||||||
otherObjective,
|
otherObjective: persistedOtherObjective,
|
||||||
context,
|
context,
|
||||||
emotion,
|
emotion,
|
||||||
style,
|
style,
|
||||||
otherStyle,
|
otherStyle: persistedOtherStyle,
|
||||||
audience,
|
audience,
|
||||||
structure,
|
structure,
|
||||||
parsedStructure,
|
parsedStructure,
|
||||||
@@ -365,11 +396,11 @@ const CreateLyricsWithAi = () => {
|
|||||||
config={lyricsConfig}
|
config={lyricsConfig}
|
||||||
selections={{
|
selections={{
|
||||||
objective,
|
objective,
|
||||||
otherObjective,
|
otherObjective: persistedOtherObjective,
|
||||||
context,
|
context,
|
||||||
emotion,
|
emotion,
|
||||||
style,
|
style,
|
||||||
otherStyle,
|
otherStyle: persistedOtherStyle,
|
||||||
audience,
|
audience,
|
||||||
structure,
|
structure,
|
||||||
parsedStructure,
|
parsedStructure,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useMemo, useState } from "react";
|
||||||
import { StyleSheet, View } from "react-native";
|
import { StyleSheet, View } from "react-native";
|
||||||
import ItemContainer from "../../components/ItemContainer/ItemContainer";
|
import ItemContainer from "../../components/ItemContainer/ItemContainer";
|
||||||
import ListSelection from "../../components/ListSelection/ListSelection";
|
import ListSelection from "../../components/ListSelection/ListSelection";
|
||||||
import { GOALS } from "../../data/data";
|
import { GOALS, OTHER_OBJECTIVE_OPTION } from "../../data/data";
|
||||||
import { Palette } from "../../styles";
|
import { Palette } from "../../styles";
|
||||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||||
import CreateLyricsHeader from "./components/CreateLyricsHeader";
|
import CreateLyricsHeader from "./components/CreateLyricsHeader";
|
||||||
@@ -19,9 +19,16 @@ const Goals = ({
|
|||||||
const selected = selectedProp ?? internalSelected;
|
const selected = selectedProp ?? internalSelected;
|
||||||
const setSelected = setSelectedProp ?? setInternalSelected;
|
const setSelected = setSelectedProp ?? setInternalSelected;
|
||||||
|
|
||||||
|
const goalsOptions = useMemo(() => GOALS ?? [], []);
|
||||||
|
|
||||||
const handleOtherObjectiveChange = (value) => {
|
const handleOtherObjectiveChange = (value) => {
|
||||||
setOtherObjective?.(value);
|
setOtherObjective?.(value);
|
||||||
if (value?.trim()?.length && selected != null) {
|
const trimmed = value?.trim() ?? "";
|
||||||
|
if (trimmed.length) {
|
||||||
|
if (selected !== OTHER_OBJECTIVE_OPTION) {
|
||||||
|
setSelected(OTHER_OBJECTIVE_OPTION);
|
||||||
|
}
|
||||||
|
} else if (selected === OTHER_OBJECTIVE_OPTION) {
|
||||||
setSelected(null);
|
setSelected(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -34,7 +41,7 @@ const Goals = ({
|
|||||||
<CreateLyricsHeader title="Quel est ton objectif ?" />
|
<CreateLyricsHeader title="Quel est ton objectif ?" />
|
||||||
<ItemContainer>
|
<ItemContainer>
|
||||||
<ListSelection
|
<ListSelection
|
||||||
options={GOALS}
|
options={goalsOptions}
|
||||||
variant="simple"
|
variant="simple"
|
||||||
selected={selected}
|
selected={selected}
|
||||||
setSelected={setSelected}
|
setSelected={setSelected}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { View, StyleSheet } from "react-native";
|
import { View, StyleSheet } from "react-native";
|
||||||
import React, { useState } from "react";
|
import React, { useMemo, useState } from "react";
|
||||||
import CreateLyricsHeader from "./components/CreateLyricsHeader";
|
import CreateLyricsHeader from "./components/CreateLyricsHeader";
|
||||||
import { SONG_STYLE } from "../../data/data";
|
import { OTHER_STYLE_OPTION, SONG_STYLE } from "../../data/data";
|
||||||
import { Palette } from "../../styles";
|
import { Palette } from "../../styles";
|
||||||
import CustomInput from "./components/CustomInput";
|
import CustomInput from "./components/CustomInput";
|
||||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||||
@@ -18,9 +18,16 @@ const SongStyle = ({
|
|||||||
const selected = selectedProp ?? internalSelected;
|
const selected = selectedProp ?? internalSelected;
|
||||||
const setSelected = setSelectedProp ?? setInternalSelected;
|
const setSelected = setSelectedProp ?? setInternalSelected;
|
||||||
|
|
||||||
|
const songStyleOptions = useMemo(() => SONG_STYLE ?? [], []);
|
||||||
|
|
||||||
const handleOtherStyleChange = (value) => {
|
const handleOtherStyleChange = (value) => {
|
||||||
setOtherStyle?.(value);
|
setOtherStyle?.(value);
|
||||||
if (value?.trim()?.length && selected != null) {
|
const trimmed = value?.trim() ?? "";
|
||||||
|
if (trimmed.length) {
|
||||||
|
if (selected !== OTHER_STYLE_OPTION) {
|
||||||
|
setSelected(OTHER_STYLE_OPTION);
|
||||||
|
}
|
||||||
|
} else if (selected === OTHER_STYLE_OPTION) {
|
||||||
setSelected(null);
|
setSelected(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -36,7 +43,7 @@ const SongStyle = ({
|
|||||||
/>
|
/>
|
||||||
<ItemContainer>
|
<ItemContainer>
|
||||||
<ListSelection
|
<ListSelection
|
||||||
options={SONG_STYLE}
|
options={songStyleOptions}
|
||||||
variant="titleDescription"
|
variant="titleDescription"
|
||||||
selected={selected}
|
selected={selected}
|
||||||
setSelected={setSelected}
|
setSelected={setSelected}
|
||||||
@@ -47,7 +54,7 @@ const SongStyle = ({
|
|||||||
</View>
|
</View>
|
||||||
<CustomInput
|
<CustomInput
|
||||||
label="Tu as un autre style de chanson ?"
|
label="Tu as un autre style de chanson ?"
|
||||||
placeholder="Décrire l’objectif"
|
placeholder="Décrire le style"
|
||||||
value={otherStyle}
|
value={otherStyle}
|
||||||
setValue={handleOtherStyleChange}
|
setValue={handleOtherStyleChange}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user