From d69577b4ce3220c73a5c9ce09585600e9742592d Mon Sep 17 00:00:00 2001 From: Leon Date: Thu, 12 Feb 2026 11:53:36 +0100 Subject: [PATCH] global loading for lyrics --- src/screens/Writing/Lyrics.js | 49 +++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/screens/Writing/Lyrics.js b/src/screens/Writing/Lyrics.js index 986dbb2..e77f12f 100644 --- a/src/screens/Writing/Lyrics.js +++ b/src/screens/Writing/Lyrics.js @@ -1,6 +1,5 @@ import React, { useCallback, useMemo, useRef, useState } from 'react' import { ScrollView, StyleSheet, Text, View } from 'react-native' -import useMinuit from 'react-native-minuit/src/hooks/useMinuit.js' import { background, icons } from '../../assets' import alert from '../../components/Alert' import AppCheckbox from '../../components/AppCheckbox' @@ -15,6 +14,7 @@ import { isWeb } from '../../hooks/useLayoutType' import Page from '../../layouts/Page' import { Routes } from '../../navigation' import { navigate } from '../../navigation/NavigationService' +import { LoaderIndicator } from '../../providers/LoadingProvider' import { useUser } from '../../providers/UserDataProvider' import { Palette, gutters } from '../../styles' import { FONT_FAMILY } from '../../styles/Fonts' @@ -35,7 +35,6 @@ const RESPONSIBILITY_CHECKBOX_LABEL = const Lyrics = ({ navigation }) => { const scrollRef = useRef(null) const [containerLayout, setContainerLayout] = useState(null) - const { setIsLoading } = useMinuit() const { selectedProjectId, selectedProject } = useUser() const hasExistingMusicDraft = useMemo(() => { if (!Array.isArray(selectedProject?.musicUrls)) return false @@ -43,6 +42,9 @@ const Lyrics = ({ navigation }) => { }, [selectedProject?.musicUrls]) const [isFocus, setIsFocus] = useState(null) const [itemsContainerLayout, setItemsContainerLayout] = useState([]) + const [isSubmitting, setIsSubmitting] = useState(false) + const [isBlockingUI, setIsBlockingUI] = useState(false) + const isSubmittingRef = useRef(false) const [sensitiveContentModal, setSensitiveContentModal] = useState({ visible: false, title: '', @@ -194,10 +196,14 @@ const Lyrics = ({ navigation }) => { }, [closeSensitiveContentModal, isSensitiveContentAcknowledged]) const onValidate = useCallback(async () => { + if (isSubmittingRef.current) return + isSubmittingRef.current = true + setIsSubmitting(true) + setIsBlockingUI(true) try { - await setIsLoading(true) const titleTrimmed = (titleValue || '').trim() if (!titleTrimmed) { + setIsBlockingUI(false) alertMessage('Titre manquant', 'Veuillez renseigner un titre.') return } @@ -207,6 +213,7 @@ const Lyrics = ({ navigation }) => { return !(s?.lyrics || '').trim() }) if (invalid) { + setIsBlockingUI(false) alertMessage('Champs incomplets', 'Chaque section doit contenir du texte.') return } @@ -247,11 +254,13 @@ const Lyrics = ({ navigation }) => { .map((e) => `• ${e.quote}`) .join('\n') : null + setIsBlockingUI(false) alertMessage('Contenu interdit', [data?.message, quotes].filter(Boolean).join('\n\n')) return // stop here } // Erreur d'analyse: informer et arrêter if (data?.errorCode === 'ANALYSE_FAILED') { + setIsBlockingUI(false) alertMessage( 'Analyse indisponible', 'Impossible de vérifier la toxicité pour le moment. Réessayez plus tard.' @@ -270,11 +279,14 @@ const Lyrics = ({ navigation }) => { : null const msg = [data?.message, quotes].filter(Boolean).join('\n\n') + setIsBlockingUI(false) const proceed = await confirmSensitiveContent('Contenu potentiellement sensible', msg) if (!proceed) return + setIsBlockingUI(true) } } catch (moderationError) { console.log('Moderation call failed', moderationError?.message || moderationError) + setIsBlockingUI(false) alertMessage( 'Analyse indisponible', 'Impossible de vérifier la toxicité pour le moment. Réessayez plus tard.' @@ -310,7 +322,7 @@ const Lyrics = ({ navigation }) => { projectForStage.musicStatus = undefined } const beatmakerStage = getStageAction('beatmaker', projectForStage) - await setIsLoading(false) + setIsBlockingUI(false) if (hasExistingMusicDraft) { navigate(Routes.ComposeSong, { isRegeneration: true }) return @@ -343,9 +355,12 @@ const Lyrics = ({ navigation }) => { return } catch (e) { console.log(e) + setIsBlockingUI(false) alertMessage('Erreur', "Échec de l'enregistrement dans le projet.") } finally { - await setIsLoading(false) + isSubmittingRef.current = false + setIsSubmitting(false) + setIsBlockingUI(false) } }, [ titleValue, @@ -355,7 +370,6 @@ const Lyrics = ({ navigation }) => { alertMessage, confirmSensitiveContent, sanitize, - setIsLoading, selectedProjectId, projectHasLyrics, projectLyrics, @@ -461,10 +475,22 @@ const Lyrics = ({ navigation }) => { }} > {!projectHasLyrics && ( - + )} - + + {isBlockingUI ? ( + + + + ) : null} { @@ -578,4 +604,11 @@ const styles = StyleSheet.create({ flexDirection: 'row', gap: 12, }, + loadingOverlay: { + ...StyleSheet.absoluteFillObject, + zIndex: 10000, + backgroundColor: Palette.transparentBlack, + justifyContent: 'center', + alignItems: 'center', + }, })