new options
This commit is contained in:
@@ -40,7 +40,11 @@ const MusicLandHeader = ({
|
||||
<View style={{ alignItems: "center", gap: 16 }}>
|
||||
<Image
|
||||
source={logo || icons.musicLandLogo}
|
||||
style={{ alignSelf: "center", height: 150, resizeMode: "contain" }}
|
||||
style={{
|
||||
alignSelf: "center",
|
||||
height: isWeb ? 150 : 100,
|
||||
resizeMode: "contain",
|
||||
}}
|
||||
/>
|
||||
<View style={{ width: "100%", ...Style.containerRow, gap: 16 }}>
|
||||
<Pressable style={backButtonStyle} onPress={onPressBack}>
|
||||
|
||||
@@ -250,13 +250,7 @@ const MusicDetails = ({ route }) => {
|
||||
console.log("MusicDetails seek error", e?.message);
|
||||
}
|
||||
},
|
||||
[
|
||||
trackDescriptor,
|
||||
durationMs,
|
||||
isCurrentTrack,
|
||||
ensureLoaded,
|
||||
seekTrackTo,
|
||||
]
|
||||
[trackDescriptor, durationMs, isCurrentTrack, ensureLoaded, seekTrackTo]
|
||||
);
|
||||
|
||||
const handleSliderSeekEnd = useCallback(async () => {
|
||||
@@ -293,13 +287,7 @@ const MusicDetails = ({ route }) => {
|
||||
console.log("MusicDetails seekBy error", e?.message);
|
||||
}
|
||||
},
|
||||
[
|
||||
trackDescriptor,
|
||||
positionMs,
|
||||
isCurrentTrack,
|
||||
ensureLoaded,
|
||||
seekTrackBy,
|
||||
]
|
||||
[trackDescriptor, positionMs, isCurrentTrack, ensureLoaded, seekTrackBy]
|
||||
);
|
||||
|
||||
const handleLyricsSeek = useCallback(
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { Image, Platform, StyleSheet, Text, View } from "react-native";
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
import {
|
||||
FlatList,
|
||||
Image,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import Animated, { useAnimatedRef } from "react-native-reanimated";
|
||||
import Sortable from "react-native-sortables";
|
||||
import { icons } from "../../assets";
|
||||
@@ -11,7 +18,6 @@ import CreateLyricsHeader from "./components/CreateLyricsHeader";
|
||||
// baseStructure: array like ['couplet','refrain',...]
|
||||
// onChange: callback that receives array like ['couplet','refrain',...]
|
||||
const CustomizeSongStructure = ({ baseStructure = [], onChange }) => {
|
||||
const [containerLayout, setContainerLayout] = useState(null);
|
||||
const scrollRef = useAnimatedRef();
|
||||
|
||||
// Build stable keyed data like { 'couplet-1': { label, value }, ... }
|
||||
@@ -34,6 +40,23 @@ const CustomizeSongStructure = ({ baseStructure = [], onChange }) => {
|
||||
|
||||
const items = useMemo(() => Object.values(data), [data]);
|
||||
|
||||
const newItems = [
|
||||
{
|
||||
id: "short_intro",
|
||||
label: "Introduction instrumentale courte",
|
||||
value: "short_intro",
|
||||
},
|
||||
{
|
||||
id: "long_intro",
|
||||
label: "Introduction instrumentale longue",
|
||||
value: "long_intro",
|
||||
},
|
||||
{
|
||||
id: "pre_chorus",
|
||||
label: "Pré-refrain",
|
||||
value: "pre_chorus",
|
||||
},
|
||||
];
|
||||
// Initialize parent with current order (so it's saved even without drag)
|
||||
useEffect(() => {
|
||||
const initialValues = (items || []).map((it) => it?.value).filter(Boolean);
|
||||
@@ -65,9 +88,12 @@ const CustomizeSongStructure = ({ baseStructure = [], onChange }) => {
|
||||
<Text style={styles.rowText}>{rowData?.label || ""}</Text>
|
||||
</View>
|
||||
</View>
|
||||
{/* Render handle only for items that come from the sortable data (have an id like 'couplet-1') */}
|
||||
{String(rowData?.id || "").includes("-") ? (
|
||||
<Sortable.Handle>
|
||||
<Image source={icons.dragDots} style={styles.handleIcon} />
|
||||
</Sortable.Handle>
|
||||
) : null}
|
||||
</View>
|
||||
</BlurView>
|
||||
</View>
|
||||
@@ -79,15 +105,13 @@ const CustomizeSongStructure = ({ baseStructure = [], onChange }) => {
|
||||
title="Personnalise la structure de ta chanson"
|
||||
subTitle="Réorganise par glisser-déposer"
|
||||
/>
|
||||
<View
|
||||
style={{ flex: 1 }}
|
||||
onLayout={(e) => setContainerLayout(e.nativeEvent.layout)}
|
||||
>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Animated.ScrollView
|
||||
ref={scrollRef}
|
||||
contentContainerStyle={{ paddingVertical: 4, paddingBottom: 24 }}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<>
|
||||
<Sortable.Grid
|
||||
columns={1}
|
||||
rowGap={12}
|
||||
@@ -103,6 +127,21 @@ const CustomizeSongStructure = ({ baseStructure = [], onChange }) => {
|
||||
onChange?.(values);
|
||||
}}
|
||||
/>
|
||||
<FlatList
|
||||
data={newItems}
|
||||
gap={12}
|
||||
renderItem={({ item }) => (
|
||||
<View style={{ marginTop: 12 }}>
|
||||
<Row item={item} />
|
||||
</View>
|
||||
)}
|
||||
keyExtractor={(item) => item.id}
|
||||
contentContainerStyle={{ paddingBottom: 24 }}
|
||||
// Prevent FlatList from capturing scroll gestures so Sortable can handle drags
|
||||
scrollEnabled={false}
|
||||
nestedScrollEnabled={false}
|
||||
/>
|
||||
</>
|
||||
</Animated.ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user