Merge branch 'main' of gitlab.com:agenceminuit/musicland
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Image, Platform, ScrollView, Text, View } from "react-native";
|
||||
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||
import { background, icons } from "../../assets";
|
||||
@@ -50,15 +50,38 @@ const Library = () => {
|
||||
setSearch,
|
||||
selected,
|
||||
setSelected,
|
||||
toggleSelected,
|
||||
filteredProjects,
|
||||
projectsLoading,
|
||||
loadMoreProjects,
|
||||
filteredUsers,
|
||||
usersLoading,
|
||||
loadMoreUsers,
|
||||
users = [],
|
||||
musics = [],
|
||||
playbacks = [],
|
||||
loading,
|
||||
} = useSearch();
|
||||
|
||||
const toggleSelected = useCallback(
|
||||
(value) => {
|
||||
setSelected((previous) => (previous === value ? null : value));
|
||||
},
|
||||
[setSelected],
|
||||
);
|
||||
|
||||
const musicResults = useMemo(
|
||||
() => (Array.isArray(musics) ? musics : []),
|
||||
[musics],
|
||||
);
|
||||
|
||||
const playbackResults = useMemo(
|
||||
() => (Array.isArray(playbacks) ? playbacks : []),
|
||||
[playbacks],
|
||||
);
|
||||
|
||||
const userResults = useMemo(
|
||||
() => (Array.isArray(users) ? users : []),
|
||||
[users],
|
||||
);
|
||||
|
||||
const musicsLoading = loading;
|
||||
const playbacksLoading = loading;
|
||||
const usersLoading = loading;
|
||||
|
||||
const [dropdownVisible, setDropdownVisible] = useState(false);
|
||||
const searchWrapperRef = useRef(null);
|
||||
|
||||
@@ -152,12 +175,12 @@ const Library = () => {
|
||||
/>
|
||||
<SearchResultsList
|
||||
selected={selected}
|
||||
filteredProjects={filteredProjects}
|
||||
projectsLoading={projectsLoading}
|
||||
loadMoreProjects={loadMoreProjects}
|
||||
filteredUsers={filteredUsers}
|
||||
musics={musicResults}
|
||||
musicsLoading={musicsLoading}
|
||||
playbacks={playbackResults}
|
||||
playbacksLoading={playbacksLoading}
|
||||
users={userResults}
|
||||
usersLoading={usersLoading}
|
||||
loadMoreUsers={loadMoreUsers}
|
||||
onResultSelected={closeDropdown}
|
||||
style={{ flex: 0, maxHeight: 420 }}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useCallback, useMemo } from "react";
|
||||
import { View } from "react-native";
|
||||
import { background } from "../../assets";
|
||||
import useSearch from "../../hooks/useSearch";
|
||||
@@ -12,15 +12,39 @@ const Research = () => {
|
||||
search,
|
||||
setSearch,
|
||||
selected,
|
||||
toggleSelected,
|
||||
filteredProjects,
|
||||
projectsLoading,
|
||||
loadMoreProjects,
|
||||
filteredUsers,
|
||||
usersLoading,
|
||||
loadMoreUsers,
|
||||
setSelected,
|
||||
users = [],
|
||||
musics = [],
|
||||
playbacks = [],
|
||||
loading,
|
||||
} = useSearch();
|
||||
|
||||
const toggleSelected = useCallback(
|
||||
(value) => {
|
||||
setSelected((previous) => (previous === value ? null : value));
|
||||
},
|
||||
[setSelected],
|
||||
);
|
||||
|
||||
const musicResults = useMemo(
|
||||
() => (Array.isArray(musics) ? musics : []),
|
||||
[musics],
|
||||
);
|
||||
|
||||
const playbackResults = useMemo(
|
||||
() => (Array.isArray(playbacks) ? playbacks : []),
|
||||
[playbacks],
|
||||
);
|
||||
|
||||
const userResults = useMemo(
|
||||
() => (Array.isArray(users) ? users : []),
|
||||
[users],
|
||||
);
|
||||
|
||||
const musicsLoading = loading;
|
||||
const playbacksLoading = loading;
|
||||
const usersLoading = loading;
|
||||
|
||||
return (
|
||||
<Page
|
||||
headerType="NAVIGATION"
|
||||
@@ -39,12 +63,12 @@ const Research = () => {
|
||||
/>
|
||||
<SearchResultsList
|
||||
selected={selected}
|
||||
filteredProjects={filteredProjects}
|
||||
projectsLoading={projectsLoading}
|
||||
loadMoreProjects={loadMoreProjects}
|
||||
filteredUsers={filteredUsers}
|
||||
musics={musicResults}
|
||||
musicsLoading={musicsLoading}
|
||||
playbacks={playbackResults}
|
||||
playbacksLoading={playbacksLoading}
|
||||
users={userResults}
|
||||
usersLoading={usersLoading}
|
||||
loadMoreUsers={loadMoreUsers}
|
||||
/>
|
||||
</View>
|
||||
</Page>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Image as ExpoImage } from "expo-image";
|
||||
import React, { useState } from "react";
|
||||
import { Pressable, ScrollView, Text, View } from "react-native";
|
||||
import { Image as ExpoImage } from "expo-image";
|
||||
import { img } from "../../../assets";
|
||||
import MoreMenu from "../../../components/MoreMenu";
|
||||
import { Routes } from "../../../navigation";
|
||||
@@ -28,12 +28,12 @@ const EmptyText = ({ text }) => (
|
||||
|
||||
const SearchResultsList = ({
|
||||
selected,
|
||||
filteredProjects,
|
||||
projectsLoading,
|
||||
loadMoreProjects,
|
||||
filteredUsers,
|
||||
usersLoading,
|
||||
loadMoreUsers,
|
||||
musics = [],
|
||||
musicsLoading = false,
|
||||
playbacks = [],
|
||||
playbacksLoading = false,
|
||||
users = [],
|
||||
usersLoading = false,
|
||||
onResultSelected,
|
||||
contentContainerStyle,
|
||||
style,
|
||||
@@ -52,14 +52,23 @@ const SearchResultsList = ({
|
||||
onResultSelected?.();
|
||||
};
|
||||
|
||||
const shouldShowMusics =
|
||||
(!selected && (musics.length > 0 || musicsLoading)) || selected === "Musiques";
|
||||
|
||||
const shouldShowPlaybacks =
|
||||
(!selected && (playbacks.length > 0 || playbacksLoading)) ||
|
||||
selected === "Playbacks";
|
||||
|
||||
const shouldShowUsers =
|
||||
(!selected && (users.length > 0 || usersLoading)) || selected === "Profils";
|
||||
|
||||
return (
|
||||
<View style={[{ flex: 1 }, style]}>
|
||||
<ScrollView
|
||||
contentContainerStyle={{ paddingTop: 2, ...contentContainerStyle }}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{((!selected && (filteredProjects.length > 0 || projectsLoading)) ||
|
||||
selected === "Musiques") && (
|
||||
{shouldShowMusics && (
|
||||
<View style={{ paddingHorizontal: 2 }}>
|
||||
<CreateLyricsHeader
|
||||
gradientProps={{
|
||||
@@ -67,10 +76,10 @@ const SearchResultsList = ({
|
||||
end: { x: 0, y: 1 },
|
||||
}}
|
||||
>
|
||||
{filteredProjects.length > 0 && (
|
||||
{musics.length > 0 && (
|
||||
<View style={{ gap: 10 }}>
|
||||
{Array.isArray(filteredProjects) &&
|
||||
filteredProjects.slice(0, 6).map((project) => (
|
||||
{Array.isArray(musics) &&
|
||||
musics.slice(0, 6).map((project) => (
|
||||
<MusicCard
|
||||
key={project.id}
|
||||
title={project?.title || "Sans titre"}
|
||||
@@ -85,46 +94,91 @@ const SearchResultsList = ({
|
||||
setShowMenu(
|
||||
(previous) =>
|
||||
!previous ||
|
||||
positionTop?.top !== (menuPosition?.top ?? null)
|
||||
positionTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{/* {(filteredProjects.length >= 6 || projectsLoading) && (
|
||||
<Pressable
|
||||
onPress={loadMoreProjects}
|
||||
style={{ alignSelf: "center", marginTop: 6 }}
|
||||
{musicsLoading && (
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
alignSelf: "center",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
opacity: projectsLoading ? 0.6 : 1,
|
||||
}}
|
||||
>
|
||||
{projectsLoading ? "Chargement…" : "Charger plus"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
)} */}
|
||||
{"Chargement…"}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
{filteredProjects.length === 0 && !projectsLoading && (
|
||||
{musics.length === 0 && !musicsLoading && (
|
||||
<EmptyText text={"Aucune musique trouvée"} />
|
||||
)}
|
||||
</CreateLyricsHeader>
|
||||
</View>
|
||||
)}
|
||||
{((!selected && (filteredUsers.length > 0 || usersLoading)) ||
|
||||
selected === "Profils") && (
|
||||
{shouldShowPlaybacks && (
|
||||
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
||||
<CreateLyricsHeader
|
||||
gradientProps={{
|
||||
start: { x: 0, y: 0 },
|
||||
end: { x: 0, y: 1 },
|
||||
}}
|
||||
>
|
||||
{playbacks.length > 0 && (
|
||||
<View style={{ gap: 10 }}>
|
||||
{Array.isArray(playbacks) &&
|
||||
playbacks.slice(0, 6).map((project) => (
|
||||
<MusicCard
|
||||
key={project.id}
|
||||
title={project?.title || "Sans titre"}
|
||||
subtitle={"MusicLand"}
|
||||
imageUri={project?.coverUrl || null}
|
||||
projectId={project?.id}
|
||||
likedBy={project?.likedBy || []}
|
||||
onPress={() => handleProjectPress(project.id)}
|
||||
onPressMore={(positionTop) => {
|
||||
setSelectedProjectId(project.id);
|
||||
setMenuPosition(positionTop);
|
||||
setShowMenu(
|
||||
(previous) =>
|
||||
!previous ||
|
||||
positionTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{playbacksLoading && (
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
alignSelf: "center",
|
||||
}}
|
||||
>
|
||||
{"Chargement…"}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
{playbacks.length === 0 && !playbacksLoading && (
|
||||
<EmptyText text={"Aucun playback trouvé"} />
|
||||
)}
|
||||
</CreateLyricsHeader>
|
||||
</View>
|
||||
)}
|
||||
{shouldShowUsers && (
|
||||
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
||||
<CreateLyricsHeader
|
||||
gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}
|
||||
>
|
||||
{filteredUsers.length > 0 && (
|
||||
{users.length > 0 && (
|
||||
<View style={{ gap: 8 }}>
|
||||
{Array.isArray(filteredUsers) &&
|
||||
filteredUsers.slice(0, 5).map((user) => (
|
||||
{Array.isArray(users) &&
|
||||
users.slice(0, 5).map((user) => (
|
||||
<Pressable
|
||||
style={{ gap: 14, ...Style.containerRow }}
|
||||
key={user.id}
|
||||
@@ -163,40 +217,26 @@ const SearchResultsList = ({
|
||||
</Text>
|
||||
</Pressable>
|
||||
))}
|
||||
{/* {(filteredUsers.length >= 5 || usersLoading) && (
|
||||
<Pressable
|
||||
onPress={loadMoreUsers}
|
||||
style={{ alignSelf: "center", marginTop: 6 }}
|
||||
{usersLoading && (
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
alignSelf: "center",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
opacity: usersLoading ? 0.6 : 1,
|
||||
}}
|
||||
>
|
||||
{usersLoading ? "Chargement…" : "Charger plus"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
)} */}
|
||||
{"Chargement…"}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
{filteredUsers.length === 0 && !usersLoading && (
|
||||
{users.length === 0 && !usersLoading && (
|
||||
<EmptyText text={"Aucun profil trouvé"} />
|
||||
)}
|
||||
</CreateLyricsHeader>
|
||||
</View>
|
||||
)}
|
||||
{selected === "Playbacks" && (
|
||||
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
||||
<CreateLyricsHeader
|
||||
gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}
|
||||
>
|
||||
<EmptyText text={"Aucun playback trouvé"} />
|
||||
</CreateLyricsHeader>
|
||||
</View>
|
||||
)}
|
||||
{selected === "Clips" && (
|
||||
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
||||
<CreateLyricsHeader
|
||||
|
||||
@@ -87,7 +87,6 @@ const CreatingLyrics = ({ active, config, selections }) => {
|
||||
await setIsLoading(true);
|
||||
await updateProjectData({
|
||||
title: result?.title || "",
|
||||
titleLower: (result?.title || "").toLowerCase(),
|
||||
lyrics: Array.isArray(result?.lyrics) ? result.lyrics : [],
|
||||
description: result?.lyricsDescription,
|
||||
config: config || null,
|
||||
@@ -198,7 +197,6 @@ const CreatingLyrics = ({ active, config, selections }) => {
|
||||
await setIsLoading(true);
|
||||
await updateProjectData({
|
||||
title: result?.title || "",
|
||||
titleLower: (result?.title || "").toLowerCase(),
|
||||
lyrics: Array.isArray(result?.lyrics)
|
||||
? result.lyrics
|
||||
: [],
|
||||
|
||||
@@ -112,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;
|
||||
}
|
||||
@@ -133,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
|
||||
@@ -157,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
|
||||
}
|
||||
@@ -165,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;
|
||||
}
|
||||
@@ -200,18 +200,17 @@ 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;
|
||||
}
|
||||
|
||||
const baseData = {
|
||||
title: titleTrimmed,
|
||||
titleLower: titleTrimmed.toLowerCase(),
|
||||
lyrics: normalizedNewLyrics,
|
||||
config: sanitize(projectConfig),
|
||||
selections: sanitize(projectSelections),
|
||||
|
||||
Reference in New Issue
Block a user