Files
musicland/src/screens/Studio/ComposeSong.js
T
2025-09-03 15:43:22 +02:00

188 lines
6.1 KiB
JavaScript

import { View, Dimensions } from "react-native";
import React, { useMemo, useRef, useState } from "react";
import Page from "../../layouts/Page";
import { background } from "../../assets";
import MusicLandHeader from "../../components/MusicLandHeader";
import GradientButton from "../../components/GradientButton";
import { goBack, navigate } from "../../navigation/NavigationService";
import { gutters } from "../../styles";
import SwiperFlatList from "react-native-swiper-flatlist";
import ChooseGenre from "./ChooseGenre";
import CustomizeVoice from "./CustomizeVoice";
import ChooseInstruments from "./ChooseInstruments";
import ChooseRhythm from "./ChooseRhythm";
import { projectsRef } from "../../config/firebase";
import { useUser } from "../../providers/UserDataProvider";
import { Routes } from "../../navigation";
const { width } = Dimensions.get("window");
const ComposeSong = () => {
const scrollRef = useRef(null);
const [selectedIndex, setSelectedIndex] = useState(0);
const [progress, setProgress] = useState(18);
const [containerLayout, setContainerLayout] = useState(null);
const { selectedProjectId, selectedProject, updateProjectData } = useUser();
// Selections state
const [genres, setGenres] = useState([]);
const [voice, setVoice] = useState(null);
const [instruments, setInstruments] = useState([]);
const [rhythm, setRhythm] = useState(null);
const isStepValid = useMemo(() => {
switch (selectedIndex) {
case 0:
return Array.isArray(genres) && genres.length > 0;
case 1:
return !!voice;
case 2:
return Array.isArray(instruments) && instruments.length > 0;
case 3:
return !!rhythm;
default:
return true;
}
}, [selectedIndex, genres, voice, instruments, rhythm]);
const musicConfig = useMemo(() => {
let lyricsArr = [];
if (Array.isArray(selectedProject?.lyrics)) {
lyricsArr = selectedProject.lyrics.map((s) => ({
type: (s?.type || "").toLowerCase(),
lyrics: s?.lyrics || "",
}));
} else {
const c = selectedProject?.lyrics?.couplet;
const r = selectedProject?.lyrics?.refrain;
if (c) lyricsArr.push({ type: "couplet", lyrics: c });
if (r) lyricsArr.push({ type: "refrain", lyrics: r });
}
return {
title: selectedProject?.title || "",
lyrics: lyricsArr,
genres: Array.isArray(genres) ? genres : [],
voice: voice || undefined,
instruments: Array.isArray(instruments) ? instruments : [],
tempo: rhythm || undefined,
projectId: selectedProjectId || undefined,
};
}, [selectedProject, genres, voice, instruments, rhythm, selectedProjectId]);
const onPressNext = async () => {
if (selectedIndex === 3) {
try {
// Persist config on the selected selectedProject so GeneratingSong can pick it up
if (selectedProjectId) {
await updateProjectData({
musicConfig: {
title: musicConfig?.title || "",
lyrics: Array.isArray(musicConfig?.lyrics)
? musicConfig.lyrics
: [],
genres: Array.isArray(musicConfig?.genres)
? musicConfig.genres
: [],
voice: musicConfig?.voice || "",
instruments: Array.isArray(musicConfig?.instruments)
? musicConfig.instruments
: [],
tempo: musicConfig?.tempo || "",
},
musicStatus: null,
});
}
} catch (e) {}
// Also pass the config to the screen to avoid any race condition
navigate(Routes.GeneratingSong, { config: musicConfig });
return;
}
setSelectedIndex(selectedIndex + 1);
setProgress(progress + 9);
scrollRef.current.scrollToIndex({
index: selectedIndex + 1,
animated: true,
});
};
const onPressBack = () => {
if (selectedIndex > 0) {
setSelectedIndex(selectedIndex - 1);
setProgress(progress - 9);
scrollRef.current.scrollToIndex({
index: selectedIndex - 1,
animated: true,
});
} else {
goBack();
}
};
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<MusicLandHeader onPressBack={onPressBack} progress={progress} />
<View style={{ flex: 1, paddingBottom: gutters, gap: 48 }}>
<View
style={{ flex: 1 }}
onLayout={(event) => setContainerLayout(event.nativeEvent.layout)}
>
<SwiperFlatList
style={{ width, left: -gutters }}
ref={scrollRef}
disableGesture
>
<View
style={{
width: width,
height: containerLayout?.height,
paddingHorizontal: gutters,
}}
>
<ChooseGenre selected={genres} setSelected={setGenres} />
</View>
<View
style={{
width: width,
height: containerLayout?.height,
paddingHorizontal: gutters,
}}
>
<CustomizeVoice selected={voice} setSelected={setVoice} />
</View>
<View
style={{
width: width,
height: containerLayout?.height,
paddingHorizontal: gutters,
}}
>
<ChooseInstruments
selected={instruments}
setSelected={setInstruments}
/>
</View>
<View
style={{
width: width,
height: containerLayout?.height,
paddingHorizontal: gutters,
}}
>
<ChooseRhythm selected={rhythm} setSelected={setRhythm} />
</View>
</SwiperFlatList>
</View>
{selectedIndex !== 4 && (
<GradientButton
title={selectedIndex === 3 ? "Générer" : "Suivant"}
onPress={onPressNext}
disabled={!isStepValid}
/>
)}
</View>
</Page>
);
};
export default ComposeSong;