Fix Task: #64
This commit is contained in:
@@ -3,13 +3,17 @@ import React from "react";
|
|||||||
import BorderGradient from "../BorderGradient/BorderGradient";
|
import BorderGradient from "../BorderGradient/BorderGradient";
|
||||||
import { BlurView } from "expo-blur";
|
import { BlurView } from "expo-blur";
|
||||||
import { responsiveHeight } from "react-native-responsive-dimensions";
|
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||||
|
import { useKeyboard } from "@react-native-community/hooks";
|
||||||
|
|
||||||
const ItemContainer = ({
|
const ItemContainer = ({
|
||||||
height = responsiveHeight(40),
|
height = responsiveHeight(40),
|
||||||
children,
|
children,
|
||||||
gradientProps,
|
gradientProps,
|
||||||
style,
|
style,
|
||||||
|
disableKeyboardHeight = false,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { keyboardShown } = useKeyboard();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BorderGradient
|
<BorderGradient
|
||||||
gradientProps={{
|
gradientProps={{
|
||||||
@@ -20,7 +24,12 @@ const ItemContainer = ({
|
|||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
...styles.borderGradientStyle,
|
...styles.borderGradientStyle,
|
||||||
height,
|
height: !disableKeyboardHeight
|
||||||
|
? keyboardShown
|
||||||
|
? responsiveHeight(30)
|
||||||
|
: height
|
||||||
|
: height,
|
||||||
|
|
||||||
...style,
|
...style,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { View, Dimensions } from "react-native";
|
import { View, Dimensions, Platform } from "react-native";
|
||||||
import React, { useMemo, useRef, useState } from "react";
|
import React, { useMemo, useRef, useState } from "react";
|
||||||
import Page from "../../layouts/Page";
|
import Page from "../../layouts/Page";
|
||||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||||
@@ -73,7 +73,8 @@ const CreateLyricsWithAi = () => {
|
|||||||
setStyle(sel.style);
|
setStyle(sel.style);
|
||||||
if (!otherStyle && typeof sel.otherStyle === "string")
|
if (!otherStyle && typeof sel.otherStyle === "string")
|
||||||
setOtherStyle(sel.otherStyle);
|
setOtherStyle(sel.otherStyle);
|
||||||
if (!audience && typeof sel.audience === "string") setAudience(sel.audience);
|
if (!audience && typeof sel.audience === "string")
|
||||||
|
setAudience(sel.audience);
|
||||||
|
|
||||||
// Structure choisie (string) si déjà enregistrée dans selections
|
// Structure choisie (string) si déjà enregistrée dans selections
|
||||||
if (structure == null && typeof sel.structure === "string" && sel.structure)
|
if (structure == null && typeof sel.structure === "string" && sel.structure)
|
||||||
@@ -216,7 +217,11 @@ const CreateLyricsWithAi = () => {
|
|||||||
}, [selectedIndex, parentLayout?.height]);
|
}, [selectedIndex, parentLayout?.height]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page headerType="NONE">
|
<Page
|
||||||
|
headerType="NONE"
|
||||||
|
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
||||||
|
keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 100}
|
||||||
|
>
|
||||||
<MusicLandHeader onPressBack={onPressBack} progress={progress} />
|
<MusicLandHeader onPressBack={onPressBack} progress={progress} />
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@@ -312,8 +317,8 @@ const CreateLyricsWithAi = () => {
|
|||||||
(Array.isArray(customStructure)
|
(Array.isArray(customStructure)
|
||||||
? customStructure
|
? customStructure
|
||||||
: Array.isArray(selectedProject?.config?.structure)
|
: Array.isArray(selectedProject?.config?.structure)
|
||||||
? selectedProject.config.structure
|
? selectedProject.config.structure
|
||||||
: [])
|
: [])
|
||||||
}
|
}
|
||||||
onChange={setCustomStructure}
|
onChange={setCustomStructure}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
import { View, Text, FlatList, StyleSheet, Pressable } from "react-native";
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
FlatList,
|
||||||
|
StyleSheet,
|
||||||
|
Pressable,
|
||||||
|
KeyboardAvoidingView,
|
||||||
|
Platform,
|
||||||
|
} from "react-native";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import CreateLyricsHeader from "./components/CreateLyricsHeader";
|
import CreateLyricsHeader from "./components/CreateLyricsHeader";
|
||||||
import { Palette, Style } from "../../styles";
|
import { Palette, Style } from "../../styles";
|
||||||
@@ -6,8 +14,15 @@ import { GOALS } from "../../data/data";
|
|||||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||||
import CustomInput from "./components/CustomInput";
|
import CustomInput from "./components/CustomInput";
|
||||||
import ItemContainer from "../../components/ItemContainer/ItemContainer";
|
import ItemContainer from "../../components/ItemContainer/ItemContainer";
|
||||||
|
import { useKeyboard } from "@react-native-community/hooks";
|
||||||
|
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||||
|
|
||||||
const Goals = ({ selected: selectedProp, setSelected: setSelectedProp, otherObjective, setOtherObjective }) => {
|
const Goals = ({
|
||||||
|
selected: selectedProp,
|
||||||
|
setSelected: setSelectedProp,
|
||||||
|
otherObjective,
|
||||||
|
setOtherObjective,
|
||||||
|
}) => {
|
||||||
const [internalSelected, setInternalSelected] = useState(null);
|
const [internalSelected, setInternalSelected] = useState(null);
|
||||||
|
|
||||||
const selected = selectedProp ?? internalSelected;
|
const selected = selectedProp ?? internalSelected;
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { View, ScrollView, Alert } from "react-native";
|
import { View, ScrollView, Alert } from "react-native";
|
||||||
import React, { useMemo, useState, useCallback, useEffect } from "react";
|
import React, {
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
} from "react";
|
||||||
import Page from "../../layouts/Page";
|
import Page from "../../layouts/Page";
|
||||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||||
import { navigate } from "../../navigation/NavigationService";
|
import { navigate } from "../../navigation/NavigationService";
|
||||||
@@ -14,9 +20,12 @@ import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
|
|||||||
import { useUser } from "../../providers/UserDataProvider";
|
import { useUser } from "../../providers/UserDataProvider";
|
||||||
|
|
||||||
const Lyrics = ({ navigation }) => {
|
const Lyrics = ({ navigation }) => {
|
||||||
|
const scrollRef = useRef(null);
|
||||||
const [containerLayout, setContainerLayout] = useState(null);
|
const [containerLayout, setContainerLayout] = useState(null);
|
||||||
const { setIsLoading } = useMinuit();
|
const { setIsLoading } = useMinuit();
|
||||||
const { selectedProjectId, selectedProject } = useUser();
|
const { selectedProjectId, selectedProject } = useUser();
|
||||||
|
const [isFocus, setIsFocus] = useState(null);
|
||||||
|
const [itemsContainerLayout, setItemsContainerLayout] = useState([]);
|
||||||
|
|
||||||
// Effective sources from provider only
|
// Effective sources from provider only
|
||||||
const projectTitle = selectedProject?.title || "";
|
const projectTitle = selectedProject?.title || "";
|
||||||
@@ -103,7 +112,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
if (invalid) {
|
if (invalid) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
"Champs incomplets",
|
"Champs incomplets",
|
||||||
"Chaque couplet et refrain doit contenir du texte.",
|
"Chaque couplet et refrain doit contenir du texte."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -124,7 +133,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
normalizedOldLyrics.every(
|
normalizedOldLyrics.every(
|
||||||
(s, i) =>
|
(s, i) =>
|
||||||
s.type === normalizedNewLyrics[i]?.type &&
|
s.type === normalizedNewLyrics[i]?.type &&
|
||||||
s.lyrics === normalizedNewLyrics[i]?.lyrics,
|
s.lyrics === normalizedNewLyrics[i]?.lyrics
|
||||||
);
|
);
|
||||||
|
|
||||||
// 1) Appel de la Cloud Function de modération avant tout enregistrement
|
// 1) Appel de la Cloud Function de modération avant tout enregistrement
|
||||||
@@ -148,7 +157,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
: null;
|
: null;
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
"Contenu interdit",
|
"Contenu interdit",
|
||||||
[data?.message, quotes].filter(Boolean).join("\n\n"),
|
[data?.message, quotes].filter(Boolean).join("\n\n")
|
||||||
);
|
);
|
||||||
return; // stop here
|
return; // stop here
|
||||||
}
|
}
|
||||||
@@ -156,7 +165,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
if (data?.errorCode === "ANALYSE_FAILED") {
|
if (data?.errorCode === "ANALYSE_FAILED") {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
"Analyse indisponible",
|
"Analyse indisponible",
|
||||||
"Impossible de vérifier la toxicité pour le moment. Réessayez plus tard.",
|
"Impossible de vérifier la toxicité pour le moment. Réessayez plus tard."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -191,11 +200,11 @@ const Lyrics = ({ navigation }) => {
|
|||||||
} catch (moderationError) {
|
} catch (moderationError) {
|
||||||
console.log(
|
console.log(
|
||||||
"Moderation call failed",
|
"Moderation call failed",
|
||||||
moderationError?.message || moderationError,
|
moderationError?.message || moderationError
|
||||||
);
|
);
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
"Analyse indisponible",
|
"Analyse indisponible",
|
||||||
"Impossible de vérifier la toxicité pour le moment. Réessayez plus tard.",
|
"Impossible de vérifier la toxicité pour le moment. Réessayez plus tard."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -250,8 +259,12 @@ const Lyrics = ({ navigation }) => {
|
|||||||
}}
|
}}
|
||||||
onLayout={(e) => setContainerLayout(e.nativeEvent.layout)}
|
onLayout={(e) => setContainerLayout(e.nativeEvent.layout)}
|
||||||
>
|
>
|
||||||
<ItemContainer height={containerLayout?.height}>
|
<ItemContainer
|
||||||
|
height={containerLayout?.height}
|
||||||
|
disableKeyboardHeight={isFocus !== sections.length - 1 || !isFocus}
|
||||||
|
>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
ref={scrollRef}
|
||||||
contentContainerStyle={{
|
contentContainerStyle={{
|
||||||
paddingHorizontal: 14,
|
paddingHorizontal: 14,
|
||||||
paddingVertical: 10,
|
paddingVertical: 10,
|
||||||
@@ -267,6 +280,13 @@ const Lyrics = ({ navigation }) => {
|
|||||||
setValue={setTitleValue}
|
setValue={setTitleValue}
|
||||||
multiline={false}
|
multiline={false}
|
||||||
maxLength={60}
|
maxLength={60}
|
||||||
|
onLayout={(e) => {
|
||||||
|
e.persist();
|
||||||
|
setItemsContainerLayout((prev) => [
|
||||||
|
...prev,
|
||||||
|
e?.nativeEvent?.layout,
|
||||||
|
]);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{sections.map((s, idx) => {
|
{sections.map((s, idx) => {
|
||||||
// Calculer l'index humain par type
|
// Calculer l'index humain par type
|
||||||
@@ -284,6 +304,19 @@ const Lyrics = ({ navigation }) => {
|
|||||||
height={type === "refrain" ? 170 : 225}
|
height={type === "refrain" ? 170 : 225}
|
||||||
value={s?.lyrics || ""}
|
value={s?.lyrics || ""}
|
||||||
setValue={(val) => setSectionAt(idx, val)}
|
setValue={(val) => setSectionAt(idx, val)}
|
||||||
|
onFocus={() => {
|
||||||
|
setIsFocus(idx);
|
||||||
|
scrollRef?.current?.scrollTo({
|
||||||
|
y: itemsContainerLayout[idx + 1]?.y,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onLayout={(e) => {
|
||||||
|
e.persist();
|
||||||
|
setItemsContainerLayout((prev) => [
|
||||||
|
...prev,
|
||||||
|
e?.nativeEvent?.layout,
|
||||||
|
]);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ const CustomInput = ({
|
|||||||
height = 65,
|
height = 65,
|
||||||
multiline = true,
|
multiline = true,
|
||||||
maxLength,
|
maxLength,
|
||||||
|
onFocus,
|
||||||
|
onBlur,
|
||||||
|
onLayout,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<View style={{ gap: 8 }}>
|
<View style={{ gap: 8 }} onLayout={onLayout}>
|
||||||
{label && (
|
{label && (
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
@@ -48,6 +51,8 @@ const CustomInput = ({
|
|||||||
numberOfLines={multiline ? undefined : 1}
|
numberOfLines={multiline ? undefined : 1}
|
||||||
maxLength={maxLength}
|
maxLength={maxLength}
|
||||||
textAlignVertical={multiline ? "top" : "center"}
|
textAlignVertical={multiline ? "top" : "center"}
|
||||||
|
onFocus={onFocus}
|
||||||
|
onBlur={onBlur}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user