Fix Task: #64
This commit is contained in:
@@ -3,13 +3,17 @@ import React from "react";
|
||||
import BorderGradient from "../BorderGradient/BorderGradient";
|
||||
import { BlurView } from "expo-blur";
|
||||
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||
import { useKeyboard } from "@react-native-community/hooks";
|
||||
|
||||
const ItemContainer = ({
|
||||
height = responsiveHeight(40),
|
||||
children,
|
||||
gradientProps,
|
||||
style,
|
||||
disableKeyboardHeight = false,
|
||||
}) => {
|
||||
const { keyboardShown } = useKeyboard();
|
||||
|
||||
return (
|
||||
<BorderGradient
|
||||
gradientProps={{
|
||||
@@ -20,7 +24,12 @@ const ItemContainer = ({
|
||||
}}
|
||||
style={{
|
||||
...styles.borderGradientStyle,
|
||||
height,
|
||||
height: !disableKeyboardHeight
|
||||
? keyboardShown
|
||||
? responsiveHeight(30)
|
||||
: height
|
||||
: height,
|
||||
|
||||
...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 Page from "../../layouts/Page";
|
||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||
@@ -73,7 +73,8 @@ const CreateLyricsWithAi = () => {
|
||||
setStyle(sel.style);
|
||||
if (!otherStyle && typeof sel.otherStyle === "string")
|
||||
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
|
||||
if (structure == null && typeof sel.structure === "string" && sel.structure)
|
||||
@@ -216,7 +217,11 @@ const CreateLyricsWithAi = () => {
|
||||
}, [selectedIndex, parentLayout?.height]);
|
||||
|
||||
return (
|
||||
<Page headerType="NONE">
|
||||
<Page
|
||||
headerType="NONE"
|
||||
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
||||
keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 100}
|
||||
>
|
||||
<MusicLandHeader onPressBack={onPressBack} progress={progress} />
|
||||
<View
|
||||
style={{
|
||||
|
||||
@@ -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 CreateLyricsHeader from "./components/CreateLyricsHeader";
|
||||
import { Palette, Style } from "../../styles";
|
||||
@@ -6,8 +14,15 @@ import { GOALS } from "../../data/data";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import CustomInput from "./components/CustomInput";
|
||||
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 selected = selectedProp ?? internalSelected;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
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 MusicLandHeader from "../../components/MusicLandHeader";
|
||||
import { navigate } from "../../navigation/NavigationService";
|
||||
@@ -14,9 +20,12 @@ import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
|
||||
const Lyrics = ({ navigation }) => {
|
||||
const scrollRef = useRef(null);
|
||||
const [containerLayout, setContainerLayout] = useState(null);
|
||||
const { setIsLoading } = useMinuit();
|
||||
const { selectedProjectId, selectedProject } = useUser();
|
||||
const [isFocus, setIsFocus] = useState(null);
|
||||
const [itemsContainerLayout, setItemsContainerLayout] = useState([]);
|
||||
|
||||
// Effective sources from provider only
|
||||
const projectTitle = selectedProject?.title || "";
|
||||
@@ -103,7 +112,7 @@ const Lyrics = ({ navigation }) => {
|
||||
if (invalid) {
|
||||
Alert.alert(
|
||||
"Champs incomplets",
|
||||
"Chaque couplet et refrain doit contenir du texte.",
|
||||
"Chaque couplet et refrain doit contenir du texte."
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -124,7 +133,7 @@ const Lyrics = ({ navigation }) => {
|
||||
normalizedOldLyrics.every(
|
||||
(s, i) =>
|
||||
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
|
||||
@@ -148,7 +157,7 @@ const Lyrics = ({ navigation }) => {
|
||||
: null;
|
||||
Alert.alert(
|
||||
"Contenu interdit",
|
||||
[data?.message, quotes].filter(Boolean).join("\n\n"),
|
||||
[data?.message, quotes].filter(Boolean).join("\n\n")
|
||||
);
|
||||
return; // stop here
|
||||
}
|
||||
@@ -156,7 +165,7 @@ const Lyrics = ({ navigation }) => {
|
||||
if (data?.errorCode === "ANALYSE_FAILED") {
|
||||
Alert.alert(
|
||||
"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;
|
||||
}
|
||||
@@ -191,11 +200,11 @@ const Lyrics = ({ navigation }) => {
|
||||
} catch (moderationError) {
|
||||
console.log(
|
||||
"Moderation call failed",
|
||||
moderationError?.message || moderationError,
|
||||
moderationError?.message || moderationError
|
||||
);
|
||||
Alert.alert(
|
||||
"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;
|
||||
}
|
||||
@@ -250,8 +259,12 @@ const Lyrics = ({ navigation }) => {
|
||||
}}
|
||||
onLayout={(e) => setContainerLayout(e.nativeEvent.layout)}
|
||||
>
|
||||
<ItemContainer height={containerLayout?.height}>
|
||||
<ItemContainer
|
||||
height={containerLayout?.height}
|
||||
disableKeyboardHeight={isFocus !== sections.length - 1 || !isFocus}
|
||||
>
|
||||
<ScrollView
|
||||
ref={scrollRef}
|
||||
contentContainerStyle={{
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
@@ -267,6 +280,13 @@ const Lyrics = ({ navigation }) => {
|
||||
setValue={setTitleValue}
|
||||
multiline={false}
|
||||
maxLength={60}
|
||||
onLayout={(e) => {
|
||||
e.persist();
|
||||
setItemsContainerLayout((prev) => [
|
||||
...prev,
|
||||
e?.nativeEvent?.layout,
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
{sections.map((s, idx) => {
|
||||
// Calculer l'index humain par type
|
||||
@@ -284,6 +304,19 @@ const Lyrics = ({ navigation }) => {
|
||||
height={type === "refrain" ? 170 : 225}
|
||||
value={s?.lyrics || ""}
|
||||
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,
|
||||
multiline = true,
|
||||
maxLength,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onLayout,
|
||||
}) => {
|
||||
return (
|
||||
<View style={{ gap: 8 }}>
|
||||
<View style={{ gap: 8 }} onLayout={onLayout}>
|
||||
{label && (
|
||||
<Text
|
||||
style={{
|
||||
@@ -48,6 +51,8 @@ const CustomInput = ({
|
||||
numberOfLines={multiline ? undefined : 1}
|
||||
maxLength={maxLength}
|
||||
textAlignVertical={multiline ? "top" : "center"}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user