minuit ticket

This commit is contained in:
2025-10-01 16:02:27 +02:00
parent c6041e81ab
commit 9a2c0428e0
3 changed files with 177 additions and 12 deletions
+21 -1
View File
@@ -89,6 +89,27 @@ const App = () => {
return subscriber; return subscriber;
}, []); }, []);
useEffect(() => {
if (Platform.OS === "web") {
const s = document.createElement("script");
s.src = "https://minuit.app/embed/report-a-problem.js";
s.async = true;
s.setAttribute("data-project-id", "playbackproduction");
s.setAttribute("data-position", "right");
s.setAttribute("data-offset", "16");
s.setAttribute("data-primary-color", "#FB68A8");
s.setAttribute("data-bg-primary-color", "#0E0E12");
s.setAttribute("data-bg-secondary-color", "#1D1825");
s.setAttribute("data-text-color", "#F3F0F5");
document.body.appendChild(s);
return () => {
try {
s.remove();
} catch (_) {}
};
}
}, []);
const onAuthStateChanged = async (user) => { const onAuthStateChanged = async (user) => {
if (isInitializing) { if (isInitializing) {
setInitializing(false); setInitializing(false);
@@ -112,7 +133,6 @@ const App = () => {
if (!loaded || isInitializing) { if (!loaded || isInitializing) {
return null; return null;
} }
return ( return (
<> <>
<StatusBar style="light" /> <StatusBar style="light" />
@@ -0,0 +1,145 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Image, StyleSheet, View, Text } from "react-native";
import Animated, { useAnimatedRef } from "react-native-reanimated";
import Sortable from "react-native-sortables";
import CreateLyricsHeader from "./components/CreateLyricsHeader";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { icons } from "../../assets";
const VALID_SEGMENTS = ["couplet", "refrain"];
const sanitizeStructure = (structure = []) =>
structure
.map((segment) => `${segment}`.trim().toLowerCase())
.filter((segment) => VALID_SEGMENTS.includes(segment));
const buildItems = (structure = []) => {
const counters = { couplet: 0, refrain: 0 };
return structure.map((segment, index) => {
counters[segment] += 1;
const label = `${segment === "couplet" ? "Couplet" : "Refrain"} ${counters[segment]}`;
return {
id: `${segment}-${index}-${counters[segment]}`,
value: segment,
label,
};
});
};
const CustomizeSongStructure = ({ baseStructure = [], onChange }) => {
const sanitized = useMemo(() => sanitizeStructure(baseStructure), [baseStructure]);
const [items, setItems] = useState(() => buildItems(sanitized));
const scrollRef = useAnimatedRef();
useEffect(() => {
setItems((prev) => {
if (
prev.length === sanitized.length &&
prev.every((item, index) => item.value === sanitized[index])
) {
return prev;
}
return buildItems(sanitized);
});
}, [sanitized]);
useEffect(() => {
onChange?.(items.map((item) => item.value));
}, [items, onChange]);
const renderItem = useCallback(({ item }) => {
return (
<View style={styles.itemContainer}>
<View style={styles.row}>
<Text style={styles.rowText}>{item.label}</Text>
<Sortable.Handle>
<Image source={icons.dragDots} style={styles.handleIcon} />
</Sortable.Handle>
</View>
</View>
);
}, []);
if (!items.length) {
return (
<View style={{ flex: 1, gap: 10, marginTop: 16 }}>
<CreateLyricsHeader
title="Personnalise la structure de ta chanson"
subTitle="Sélectionne une structure pour commencer"
/>
</View>
);
}
return (
<View style={{ flex: 1, gap: 10, marginTop: 16 }}>
<CreateLyricsHeader
title="Personnalise la structure de ta chanson"
subTitle="Glisse-dépose pour réorganiser"
/>
<View style={styles.listContainer}>
<Animated.ScrollView
ref={scrollRef}
contentContainerStyle={styles.scrollContent}
showsVerticalScrollIndicator={false}
>
<Sortable.Grid
columns={1}
data={items}
keyExtractor={(item) => item.id}
renderItem={renderItem}
rowGap={12}
customHandle
scrollableRef={scrollRef}
onDragEnd={({ data: nextItems }) => {
const nextOrder = nextItems.map((item) => item.value);
setItems(buildItems(nextOrder));
}}
/>
</Animated.ScrollView>
</View>
</View>
);
};
export default CustomizeSongStructure;
const styles = StyleSheet.create({
listContainer: {
flex: 1,
},
scrollContent: {
paddingVertical: 4,
paddingBottom: 24,
},
itemContainer: {
height: 54,
borderRadius: 14,
backgroundColor: Palette.glass,
shadowColor: "#00000040",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
overflow: "hidden",
},
row: {
flex: 1,
paddingHorizontal: 16,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
},
rowText: {
fontSize: 16,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
},
handleIcon: {
width: 22,
height: 22,
tintColor: Palette.white,
cursor: "grab",
},
});
+11 -11
View File
@@ -1,16 +1,16 @@
import { View, Image, StyleSheet } from "react-native";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Page from "../../layouts/Page"; import { Image, StyleSheet, View } from "react-native";
import { ai } from "../../assets";
import GradientButton from "../../components/GradientButton";
import { gutters } from "../../styles";
import BorderGradientButton from "../../components/BorderGradientButton";
import MusicLandHeader from "../../components/MusicLandHeader";
import { goBack, navigate } from "../../navigation/NavigationService";
import { Routes } from "../../navigation";
import { useUserData } from "../../providers/UserDataProvider";
import useMinuit from "react-native-minuit/src/hooks/useMinuit.js"; import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
import FullscreenIntroVideo from "../../components/FullscreenIntroVideo"; import { ai } from "../../assets";
import BorderGradientButton from "../../components/BorderGradientButton";
import FullscreenIntroVideo from "../../components/FullscreenIntroVideo.web";
import GradientButton from "../../components/GradientButton";
import MusicLandHeader from "../../components/MusicLandHeader";
import Page from "../../layouts/Page";
import { Routes } from "../../navigation";
import { goBack, navigate } from "../../navigation/NavigationService";
import { useUserData } from "../../providers/UserDataProvider";
import { gutters } from "../../styles";
const WritingLyrics = () => { const WritingLyrics = () => {
const { createNewProject, selectedProject, updateProjectData } = const { createNewProject, selectedProject, updateProjectData } =