Merge branch 'main' of gitlab.com:agenceminuit/musicland
This commit is contained in:
@@ -18,3 +18,4 @@ exports.cover = require("./src/cover");
|
|||||||
exports.projects = require("./src/project");
|
exports.projects = require("./src/project");
|
||||||
exports.thumbnail = require("./src/thumbnail");
|
exports.thumbnail = require("./src/thumbnail");
|
||||||
exports.upload = require("./src/upload");
|
exports.upload = require("./src/upload");
|
||||||
|
exports.algolia = require("./src/algolia");
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
const { onRequest } = require("firebase-functions/v2/https");
|
||||||
|
|
||||||
|
exports.algoliaTransformProjectData = onRequest(
|
||||||
|
{ region: "europe-west1" },
|
||||||
|
(req, res) => {
|
||||||
|
const payload = req.body.data;
|
||||||
|
const objectID = payload.objectID;
|
||||||
|
try {
|
||||||
|
const flat = { ...payload };
|
||||||
|
delete flat["musicTimestamps"];
|
||||||
|
|
||||||
|
console.log(`Change in ${payload.objectID}`);
|
||||||
|
console.log(flat);
|
||||||
|
// Ton object final doit contenir "objectID"
|
||||||
|
const result = {
|
||||||
|
objectID,
|
||||||
|
...flat,
|
||||||
|
};
|
||||||
|
|
||||||
|
res.send({ result });
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`Error ${objectID}:`, e.message);
|
||||||
|
res.status(500).end();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -33,6 +33,20 @@ exports.onProjectUpdate = onDocumentWritten(
|
|||||||
batch.delete(doc.ref);
|
batch.delete(doc.ref);
|
||||||
});
|
});
|
||||||
await batch.commit();
|
await batch.commit();
|
||||||
|
} else {
|
||||||
|
if (previousData) {
|
||||||
|
// edit
|
||||||
|
if (!previousData?.songUrl && currentData?.songUrl) {
|
||||||
|
await refList.projects.doc(projectId).update({
|
||||||
|
hasSong: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!previousData?.playbackUrl && currentData?.playbackUrl) {
|
||||||
|
await refList.projects.doc(projectId).update({
|
||||||
|
hasPlayback: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|||||||
@@ -19,3 +19,17 @@ export const GOOGLE_IOS_CLIENT_ID =
|
|||||||
// Android client ID (client_type 1 from google-services.json)
|
// Android client ID (client_type 1 from google-services.json)
|
||||||
export const GOOGLE_ANDROID_CLIENT_ID =
|
export const GOOGLE_ANDROID_CLIENT_ID =
|
||||||
"305598753437-qck73beo37mi04qlautgafbpdl3ccaoh.apps.googleusercontent.com";
|
"305598753437-qck73beo37mi04qlautgafbpdl3ccaoh.apps.googleusercontent.com";
|
||||||
|
|
||||||
|
const AlgoliaAppId = "38AHXYR8S1";
|
||||||
|
const AlgoliaSearchKey = "2ac15d7b8b5e6490b53821067e4a0f03";
|
||||||
|
|
||||||
|
export const AlgoliaUserConfig = {
|
||||||
|
index: "users",
|
||||||
|
projectID: AlgoliaAppId,
|
||||||
|
publicKey: AlgoliaSearchKey,
|
||||||
|
};
|
||||||
|
export const AlgoliaProjectConfig = {
|
||||||
|
index: "projects",
|
||||||
|
projectID: AlgoliaAppId,
|
||||||
|
publicKey: AlgoliaSearchKey,
|
||||||
|
};
|
||||||
|
|||||||
+30
-209
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useState } from "react";
|
||||||
import { useGlobal } from "reactn";
|
import useAlgoliaSearch from "react-native-minuit/src/hooks/useAlgoliaSearch";
|
||||||
import { usersRef, projectsRef } from "../config/firebase";
|
import { AlgoliaUserConfig, AlgoliaProjectConfig } from "../data/keys";
|
||||||
import useDataFromRef from "./useDataFromRef";
|
import { useUserData } from "../providers/UserDataProvider";
|
||||||
|
|
||||||
const batchSizes = {
|
const batchSizes = {
|
||||||
users: 5,
|
users: 5,
|
||||||
@@ -11,221 +11,42 @@ const batchSizes = {
|
|||||||
const useSearch = () => {
|
const useSearch = () => {
|
||||||
const [selected, setSelected] = useState(null);
|
const [selected, setSelected] = useState(null);
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const queryText = useMemo(() => search.trim(), [search]);
|
const { currentUID } = useUserData();
|
||||||
const queryLower = useMemo(
|
|
||||||
() => (search || "").toLowerCase().trim(),
|
|
||||||
[search],
|
|
||||||
);
|
|
||||||
const [currentUID] = useGlobal("currentUID");
|
|
||||||
const [autoLoads, setAutoLoads] = useState(0);
|
|
||||||
|
|
||||||
const usersQueryRef = useMemo(() => {
|
const { hits: users, loading: userLoading } = useAlgoliaSearch({
|
||||||
try {
|
query: search,
|
||||||
const lower = queryLower;
|
algoliaObject: AlgoliaUserConfig,
|
||||||
if (lower) {
|
batch: batchSizes.users,
|
||||||
return usersRef
|
searchParams: {
|
||||||
.orderBy("userNameLower")
|
filters: `NOT objectID:${currentUID}`,
|
||||||
.startAt(lower)
|
},
|
||||||
.endAt(lower + "\uf8ff");
|
|
||||||
}
|
|
||||||
return usersRef.orderBy("userNameLower");
|
|
||||||
} catch (_error) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}, [queryLower]);
|
|
||||||
|
|
||||||
const projectsQueryRefLower = useMemo(() => {
|
|
||||||
try {
|
|
||||||
const lower = queryText ? queryText.toLowerCase() : "";
|
|
||||||
if (lower) {
|
|
||||||
return projectsRef
|
|
||||||
.orderBy("titleLower")
|
|
||||||
.startAt(lower)
|
|
||||||
.endAt(lower + "\uf8ff");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (_error) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}, [queryText]);
|
|
||||||
|
|
||||||
const projectsQueryRefCase = useMemo(() => {
|
|
||||||
try {
|
|
||||||
const raw = queryText || "";
|
|
||||||
if (raw) {
|
|
||||||
return projectsRef
|
|
||||||
.orderBy("title")
|
|
||||||
.startAt(raw)
|
|
||||||
.endAt(raw + "\uf8ff");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (_error) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}, [queryText]);
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: userResults = [],
|
|
||||||
loading: usersLoading,
|
|
||||||
loadMore: loadMoreUsers,
|
|
||||||
} = useDataFromRef({
|
|
||||||
ref: usersQueryRef,
|
|
||||||
simpleRef: false,
|
|
||||||
listener: false,
|
|
||||||
condition: !!usersQueryRef,
|
|
||||||
refreshArray: [queryLower],
|
|
||||||
usePagination: true,
|
|
||||||
batchSize: batchSizes.users,
|
|
||||||
});
|
});
|
||||||
|
const { hits: playbacks, loading: playbackLoading } = useAlgoliaSearch({
|
||||||
const filteredUsers = useMemo(() => {
|
query: search,
|
||||||
const arr = Array.isArray(userResults) ? userResults : [];
|
algoliaObject: AlgoliaProjectConfig,
|
||||||
const matchingUsers = queryLower
|
batch: batchSizes.projects,
|
||||||
? arr.filter((user) => {
|
searchParams: {
|
||||||
const nameLower = (
|
filters: `hasPlayback:true AND hasSong:true`,
|
||||||
user?.userNameLower ||
|
},
|
||||||
user?.userName ||
|
|
||||||
""
|
|
||||||
).toLowerCase();
|
|
||||||
return nameLower.includes(queryLower);
|
|
||||||
})
|
|
||||||
: arr;
|
|
||||||
const seen = new Set();
|
|
||||||
const unique = [];
|
|
||||||
for (const user of matchingUsers) {
|
|
||||||
const id = user?.id;
|
|
||||||
if (!id || seen.has(id)) continue;
|
|
||||||
if (id === currentUID || user?.userID === currentUID) continue;
|
|
||||||
seen.add(id);
|
|
||||||
unique.push(user);
|
|
||||||
}
|
|
||||||
return unique;
|
|
||||||
}, [userResults, queryLower, currentUID]);
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: projectResultsLower = [],
|
|
||||||
loading: projectsLoadingLower,
|
|
||||||
loadMore: loadMoreProjectsLower,
|
|
||||||
} = useDataFromRef({
|
|
||||||
ref: projectsQueryRefLower,
|
|
||||||
simpleRef: false,
|
|
||||||
listener: false,
|
|
||||||
condition: !!projectsQueryRefLower,
|
|
||||||
refreshArray: [queryText],
|
|
||||||
usePagination: true,
|
|
||||||
batchSize: batchSizes.projects,
|
|
||||||
});
|
});
|
||||||
|
const { hits: musics, loading: musicLoading } = useAlgoliaSearch({
|
||||||
const {
|
query: search,
|
||||||
data: projectResultsCase = [],
|
algoliaObject: AlgoliaProjectConfig,
|
||||||
loading: projectsLoadingCase,
|
batch: batchSizes.projects,
|
||||||
loadMore: loadMoreProjectsCase,
|
searchParams: {
|
||||||
} = useDataFromRef({
|
filters: `hasPlayback:false AND hasSong:true`,
|
||||||
ref: projectsQueryRefCase,
|
},
|
||||||
simpleRef: false,
|
|
||||||
listener: false,
|
|
||||||
condition: !!projectsQueryRefCase,
|
|
||||||
refreshArray: [queryText],
|
|
||||||
usePagination: true,
|
|
||||||
batchSize: batchSizes.projects,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
|
||||||
data: projectResultsDefault = [],
|
|
||||||
loading: projectsLoadingDefault,
|
|
||||||
loadMore: loadMoreProjectsDefault,
|
|
||||||
} = useDataFromRef({
|
|
||||||
ref: !queryText ? projectsRef.orderBy("updatedAt", "desc") : null,
|
|
||||||
simpleRef: false,
|
|
||||||
listener: false,
|
|
||||||
condition: !queryText,
|
|
||||||
refreshArray: [queryText],
|
|
||||||
usePagination: true,
|
|
||||||
batchSize: batchSizes.projects,
|
|
||||||
});
|
|
||||||
|
|
||||||
const projectsLoading = queryText
|
|
||||||
? projectsLoadingLower || projectsLoadingCase
|
|
||||||
: projectsLoadingDefault;
|
|
||||||
|
|
||||||
const loadMoreProjects = () => {
|
|
||||||
if (queryText) {
|
|
||||||
loadMoreProjectsLower?.();
|
|
||||||
loadMoreProjectsCase?.();
|
|
||||||
} else {
|
|
||||||
loadMoreProjectsDefault?.();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const filteredProjects = useMemo(() => {
|
|
||||||
const lowerMatches = Array.isArray(projectResultsLower)
|
|
||||||
? projectResultsLower
|
|
||||||
: [];
|
|
||||||
const caseMatches = Array.isArray(projectResultsCase)
|
|
||||||
? projectResultsCase
|
|
||||||
: [];
|
|
||||||
const defaultProjects = Array.isArray(projectResultsDefault)
|
|
||||||
? projectResultsDefault
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const arr = queryText ? [...lowerMatches, ...caseMatches] : defaultProjects;
|
|
||||||
const seen = new Set();
|
|
||||||
const unique = [];
|
|
||||||
for (const project of arr) {
|
|
||||||
const id = project?.id;
|
|
||||||
if (!id || seen.has(id)) continue;
|
|
||||||
seen.add(id);
|
|
||||||
unique.push(project);
|
|
||||||
}
|
|
||||||
return unique;
|
|
||||||
}, [
|
|
||||||
queryText,
|
|
||||||
projectResultsLower,
|
|
||||||
projectResultsCase,
|
|
||||||
projectResultsDefault,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setAutoLoads(0);
|
|
||||||
}, [queryText]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (
|
|
||||||
filteredUsers.length < batchSizes.users &&
|
|
||||||
usersQueryRef &&
|
|
||||||
!usersLoading
|
|
||||||
) {
|
|
||||||
if (autoLoads < 3) {
|
|
||||||
setAutoLoads((previous) => previous + 1);
|
|
||||||
loadMoreUsers?.();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
filteredUsers.length,
|
|
||||||
usersLoading,
|
|
||||||
usersQueryRef,
|
|
||||||
autoLoads,
|
|
||||||
loadMoreUsers,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const toggleSelected = (item) => {
|
|
||||||
setSelected((prev) => (prev === item ? null : item));
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
search,
|
search,
|
||||||
setSearch,
|
setSearch,
|
||||||
queryText,
|
|
||||||
queryLower,
|
|
||||||
selected,
|
selected,
|
||||||
setSelected,
|
setSelected,
|
||||||
toggleSelected,
|
users,
|
||||||
filteredUsers,
|
musics,
|
||||||
usersLoading,
|
playbacks,
|
||||||
loadMoreUsers,
|
loading: userLoading || musicLoading || playbackLoading,
|
||||||
filteredProjects,
|
|
||||||
projectsLoading,
|
|
||||||
loadMoreProjects,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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 { Image, Platform, ScrollView, Text, View } from "react-native";
|
||||||
import { responsiveHeight } from "react-native-responsive-dimensions";
|
import { responsiveHeight } from "react-native-responsive-dimensions";
|
||||||
import { background, icons } from "../../assets";
|
import { background, icons } from "../../assets";
|
||||||
@@ -50,15 +50,38 @@ const Library = () => {
|
|||||||
setSearch,
|
setSearch,
|
||||||
selected,
|
selected,
|
||||||
setSelected,
|
setSelected,
|
||||||
toggleSelected,
|
users = [],
|
||||||
filteredProjects,
|
musics = [],
|
||||||
projectsLoading,
|
playbacks = [],
|
||||||
loadMoreProjects,
|
loading,
|
||||||
filteredUsers,
|
|
||||||
usersLoading,
|
|
||||||
loadMoreUsers,
|
|
||||||
} = useSearch();
|
} = 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 [dropdownVisible, setDropdownVisible] = useState(false);
|
||||||
const searchWrapperRef = useRef(null);
|
const searchWrapperRef = useRef(null);
|
||||||
|
|
||||||
@@ -152,12 +175,12 @@ const Library = () => {
|
|||||||
/>
|
/>
|
||||||
<SearchResultsList
|
<SearchResultsList
|
||||||
selected={selected}
|
selected={selected}
|
||||||
filteredProjects={filteredProjects}
|
musics={musicResults}
|
||||||
projectsLoading={projectsLoading}
|
musicsLoading={musicsLoading}
|
||||||
loadMoreProjects={loadMoreProjects}
|
playbacks={playbackResults}
|
||||||
filteredUsers={filteredUsers}
|
playbacksLoading={playbacksLoading}
|
||||||
|
users={userResults}
|
||||||
usersLoading={usersLoading}
|
usersLoading={usersLoading}
|
||||||
loadMoreUsers={loadMoreUsers}
|
|
||||||
onResultSelected={closeDropdown}
|
onResultSelected={closeDropdown}
|
||||||
style={{ flex: 0, maxHeight: 420 }}
|
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 { View } from "react-native";
|
||||||
import { background } from "../../assets";
|
import { background } from "../../assets";
|
||||||
import useSearch from "../../hooks/useSearch";
|
import useSearch from "../../hooks/useSearch";
|
||||||
@@ -12,15 +12,39 @@ const Research = () => {
|
|||||||
search,
|
search,
|
||||||
setSearch,
|
setSearch,
|
||||||
selected,
|
selected,
|
||||||
toggleSelected,
|
setSelected,
|
||||||
filteredProjects,
|
users = [],
|
||||||
projectsLoading,
|
musics = [],
|
||||||
loadMoreProjects,
|
playbacks = [],
|
||||||
filteredUsers,
|
loading,
|
||||||
usersLoading,
|
|
||||||
loadMoreUsers,
|
|
||||||
} = useSearch();
|
} = 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 (
|
return (
|
||||||
<Page
|
<Page
|
||||||
headerType="NAVIGATION"
|
headerType="NAVIGATION"
|
||||||
@@ -39,12 +63,12 @@ const Research = () => {
|
|||||||
/>
|
/>
|
||||||
<SearchResultsList
|
<SearchResultsList
|
||||||
selected={selected}
|
selected={selected}
|
||||||
filteredProjects={filteredProjects}
|
musics={musicResults}
|
||||||
projectsLoading={projectsLoading}
|
musicsLoading={musicsLoading}
|
||||||
loadMoreProjects={loadMoreProjects}
|
playbacks={playbackResults}
|
||||||
filteredUsers={filteredUsers}
|
playbacksLoading={playbacksLoading}
|
||||||
|
users={userResults}
|
||||||
usersLoading={usersLoading}
|
usersLoading={usersLoading}
|
||||||
loadMoreUsers={loadMoreUsers}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Image as ExpoImage } from "expo-image";
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Pressable, ScrollView, Text, View } from "react-native";
|
import { Pressable, ScrollView, Text, View } from "react-native";
|
||||||
|
import { Image as ExpoImage } from "expo-image";
|
||||||
import { img } from "../../../assets";
|
import { img } from "../../../assets";
|
||||||
import MoreMenu from "../../../components/MoreMenu";
|
import MoreMenu from "../../../components/MoreMenu";
|
||||||
import { Routes } from "../../../navigation";
|
import { Routes } from "../../../navigation";
|
||||||
@@ -28,12 +28,12 @@ const EmptyText = ({ text }) => (
|
|||||||
|
|
||||||
const SearchResultsList = ({
|
const SearchResultsList = ({
|
||||||
selected,
|
selected,
|
||||||
filteredProjects,
|
musics = [],
|
||||||
projectsLoading,
|
musicsLoading = false,
|
||||||
loadMoreProjects,
|
playbacks = [],
|
||||||
filteredUsers,
|
playbacksLoading = false,
|
||||||
usersLoading,
|
users = [],
|
||||||
loadMoreUsers,
|
usersLoading = false,
|
||||||
onResultSelected,
|
onResultSelected,
|
||||||
contentContainerStyle,
|
contentContainerStyle,
|
||||||
style,
|
style,
|
||||||
@@ -52,14 +52,23 @@ const SearchResultsList = ({
|
|||||||
onResultSelected?.();
|
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 (
|
return (
|
||||||
<View style={[{ flex: 1 }, style]}>
|
<View style={[{ flex: 1 }, style]}>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
contentContainerStyle={{ paddingTop: 2, ...contentContainerStyle }}
|
contentContainerStyle={{ paddingTop: 2, ...contentContainerStyle }}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
>
|
>
|
||||||
{((!selected && (filteredProjects.length > 0 || projectsLoading)) ||
|
{shouldShowMusics && (
|
||||||
selected === "Musiques") && (
|
|
||||||
<View style={{ paddingHorizontal: 2 }}>
|
<View style={{ paddingHorizontal: 2 }}>
|
||||||
<CreateLyricsHeader
|
<CreateLyricsHeader
|
||||||
gradientProps={{
|
gradientProps={{
|
||||||
@@ -67,10 +76,10 @@ const SearchResultsList = ({
|
|||||||
end: { x: 0, y: 1 },
|
end: { x: 0, y: 1 },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{filteredProjects.length > 0 && (
|
{musics.length > 0 && (
|
||||||
<View style={{ gap: 10 }}>
|
<View style={{ gap: 10 }}>
|
||||||
{Array.isArray(filteredProjects) &&
|
{Array.isArray(musics) &&
|
||||||
filteredProjects.slice(0, 6).map((project) => (
|
musics.slice(0, 6).map((project) => (
|
||||||
<MusicCard
|
<MusicCard
|
||||||
key={project.id}
|
key={project.id}
|
||||||
title={project?.title || "Sans titre"}
|
title={project?.title || "Sans titre"}
|
||||||
@@ -85,46 +94,91 @@ const SearchResultsList = ({
|
|||||||
setShowMenu(
|
setShowMenu(
|
||||||
(previous) =>
|
(previous) =>
|
||||||
!previous ||
|
!previous ||
|
||||||
positionTop?.top !== (menuPosition?.top ?? null)
|
positionTop?.top !== (menuPosition?.top ?? null),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{/* {(filteredProjects.length >= 6 || projectsLoading) && (
|
{musicsLoading && (
|
||||||
<Pressable
|
<Text
|
||||||
onPress={loadMoreProjects}
|
style={{
|
||||||
style={{ alignSelf: "center", marginTop: 6 }}
|
fontSize: 12,
|
||||||
|
color: Palette.white,
|
||||||
|
fontFamily: FONT_FAMILY.InterRegular,
|
||||||
|
alignSelf: "center",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Text
|
{"Chargement…"}
|
||||||
style={{
|
</Text>
|
||||||
fontSize: 12,
|
)}
|
||||||
color: Palette.white,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
opacity: projectsLoading ? 0.6 : 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{projectsLoading ? "Chargement…" : "Charger plus"}
|
|
||||||
</Text>
|
|
||||||
</Pressable>
|
|
||||||
)} */}
|
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{filteredProjects.length === 0 && !projectsLoading && (
|
{musics.length === 0 && !musicsLoading && (
|
||||||
<EmptyText text={"Aucune musique trouvée"} />
|
<EmptyText text={"Aucune musique trouvée"} />
|
||||||
)}
|
)}
|
||||||
</CreateLyricsHeader>
|
</CreateLyricsHeader>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{((!selected && (filteredUsers.length > 0 || usersLoading)) ||
|
{shouldShowPlaybacks && (
|
||||||
selected === "Profils") && (
|
<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 }}>
|
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
||||||
<CreateLyricsHeader
|
<CreateLyricsHeader
|
||||||
gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}
|
gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}
|
||||||
>
|
>
|
||||||
{filteredUsers.length > 0 && (
|
{users.length > 0 && (
|
||||||
<View style={{ gap: 8 }}>
|
<View style={{ gap: 8 }}>
|
||||||
{Array.isArray(filteredUsers) &&
|
{Array.isArray(users) &&
|
||||||
filteredUsers.slice(0, 5).map((user) => (
|
users.slice(0, 5).map((user) => (
|
||||||
<Pressable
|
<Pressable
|
||||||
style={{ gap: 14, ...Style.containerRow }}
|
style={{ gap: 14, ...Style.containerRow }}
|
||||||
key={user.id}
|
key={user.id}
|
||||||
@@ -163,40 +217,26 @@ const SearchResultsList = ({
|
|||||||
</Text>
|
</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
))}
|
))}
|
||||||
{/* {(filteredUsers.length >= 5 || usersLoading) && (
|
{usersLoading && (
|
||||||
<Pressable
|
<Text
|
||||||
onPress={loadMoreUsers}
|
style={{
|
||||||
style={{ alignSelf: "center", marginTop: 6 }}
|
fontSize: 12,
|
||||||
|
color: Palette.white,
|
||||||
|
fontFamily: FONT_FAMILY.InterRegular,
|
||||||
|
alignSelf: "center",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Text
|
{"Chargement…"}
|
||||||
style={{
|
</Text>
|
||||||
fontSize: 12,
|
)}
|
||||||
color: Palette.white,
|
|
||||||
fontFamily: FONT_FAMILY.InterRegular,
|
|
||||||
opacity: usersLoading ? 0.6 : 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{usersLoading ? "Chargement…" : "Charger plus"}
|
|
||||||
</Text>
|
|
||||||
</Pressable>
|
|
||||||
)} */}
|
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{filteredUsers.length === 0 && !usersLoading && (
|
{users.length === 0 && !usersLoading && (
|
||||||
<EmptyText text={"Aucun profil trouvé"} />
|
<EmptyText text={"Aucun profil trouvé"} />
|
||||||
)}
|
)}
|
||||||
</CreateLyricsHeader>
|
</CreateLyricsHeader>
|
||||||
</View>
|
</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" && (
|
{selected === "Clips" && (
|
||||||
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
||||||
<CreateLyricsHeader
|
<CreateLyricsHeader
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ const CreatingLyrics = ({ active, config, selections }) => {
|
|||||||
await setIsLoading(true);
|
await setIsLoading(true);
|
||||||
await updateProjectData({
|
await updateProjectData({
|
||||||
title: result?.title || "",
|
title: result?.title || "",
|
||||||
titleLower: (result?.title || "").toLowerCase(),
|
|
||||||
lyrics: Array.isArray(result?.lyrics) ? result.lyrics : [],
|
lyrics: Array.isArray(result?.lyrics) ? result.lyrics : [],
|
||||||
description: result?.lyricsDescription,
|
description: result?.lyricsDescription,
|
||||||
config: config || null,
|
config: config || null,
|
||||||
@@ -198,7 +197,6 @@ const CreatingLyrics = ({ active, config, selections }) => {
|
|||||||
await setIsLoading(true);
|
await setIsLoading(true);
|
||||||
await updateProjectData({
|
await updateProjectData({
|
||||||
title: result?.title || "",
|
title: result?.title || "",
|
||||||
titleLower: (result?.title || "").toLowerCase(),
|
|
||||||
lyrics: Array.isArray(result?.lyrics)
|
lyrics: Array.isArray(result?.lyrics)
|
||||||
? result.lyrics
|
? result.lyrics
|
||||||
: [],
|
: [],
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
if (invalid) {
|
if (invalid) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
"Champs incomplets",
|
"Champs incomplets",
|
||||||
"Chaque couplet et refrain doit contenir du texte."
|
"Chaque couplet et refrain doit contenir du texte.",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
normalizedOldLyrics.every(
|
normalizedOldLyrics.every(
|
||||||
(s, i) =>
|
(s, i) =>
|
||||||
s.type === normalizedNewLyrics[i]?.type &&
|
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
|
// 1) Appel de la Cloud Function de modération avant tout enregistrement
|
||||||
@@ -157,7 +157,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
: null;
|
: null;
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
"Contenu interdit",
|
"Contenu interdit",
|
||||||
[data?.message, quotes].filter(Boolean).join("\n\n")
|
[data?.message, quotes].filter(Boolean).join("\n\n"),
|
||||||
);
|
);
|
||||||
return; // stop here
|
return; // stop here
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
if (data?.errorCode === "ANALYSE_FAILED") {
|
if (data?.errorCode === "ANALYSE_FAILED") {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
"Analyse indisponible",
|
"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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -200,18 +200,17 @@ const Lyrics = ({ navigation }) => {
|
|||||||
} catch (moderationError) {
|
} catch (moderationError) {
|
||||||
console.log(
|
console.log(
|
||||||
"Moderation call failed",
|
"Moderation call failed",
|
||||||
moderationError?.message || moderationError
|
moderationError?.message || moderationError,
|
||||||
);
|
);
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
"Analyse indisponible",
|
"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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseData = {
|
const baseData = {
|
||||||
title: titleTrimmed,
|
title: titleTrimmed,
|
||||||
titleLower: titleTrimmed.toLowerCase(),
|
|
||||||
lyrics: normalizedNewLyrics,
|
lyrics: normalizedNewLyrics,
|
||||||
config: sanitize(projectConfig),
|
config: sanitize(projectConfig),
|
||||||
selections: sanitize(projectSelections),
|
selections: sanitize(projectSelections),
|
||||||
|
|||||||
Reference in New Issue
Block a user