303 lines
10 KiB
JavaScript
303 lines
10 KiB
JavaScript
import React, { useEffect, useMemo, useState } from "react";
|
|
import { Image, Pressable, ScrollView, Text, View } from "react-native";
|
|
import { background, img } from "../../assets";
|
|
import MoreMenu from "../../components/MoreMenu";
|
|
import { usersRef, projectsRef } from "../../config/firebase";
|
|
import useDataFromRef from "../../hooks/useDataFromRef";
|
|
import { useGlobal } from "reactn";
|
|
import Page from "../../layouts/Page";
|
|
import { Routes } from "../../navigation";
|
|
import { navigate } from "../../navigation/NavigationService";
|
|
import { gutters, Palette, Style } from "../../styles";
|
|
import { FONT_FAMILY } from "../../styles/Fonts";
|
|
import { size } from "../../styles/Style";
|
|
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
|
|
import MusicCard from "./components/MusicCard";
|
|
import ResearchHeader from "./components/ResearchHeader";
|
|
|
|
const Research = () => {
|
|
const [selected, setSelected] = useState(null);
|
|
const [search, setSearch] = useState("");
|
|
const queryText = useMemo(() => search.trim(), [search]);
|
|
const [currentUID] = useGlobal("currentUID");
|
|
const [autoLoads, setAutoLoads] = useState(0);
|
|
|
|
const usersQueryRef = useMemo(() => {
|
|
try {
|
|
if (queryText) {
|
|
return usersRef
|
|
.orderBy("userName")
|
|
.startAt(queryText)
|
|
.endAt(queryText + "\uf8ff");
|
|
}
|
|
return usersRef.orderBy("userName");
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}, [queryText]);
|
|
|
|
const projectsQueryRef = useMemo(() => {
|
|
try {
|
|
if (queryText) {
|
|
return projectsRef
|
|
.orderBy("title")
|
|
.startAt(queryText)
|
|
.endAt(queryText + "\uf8ff");
|
|
}
|
|
return projectsRef.orderBy("updatedAt", "desc");
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}, [queryText]);
|
|
|
|
const {
|
|
data: userResults = [],
|
|
loading: usersLoading,
|
|
loadMore: loadMoreUsers,
|
|
} = useDataFromRef({
|
|
ref: usersQueryRef,
|
|
simpleRef: false,
|
|
listener: false,
|
|
condition: !!usersQueryRef,
|
|
refreshArray: [queryText],
|
|
usePagination: true,
|
|
batchSize: 5,
|
|
});
|
|
const filteredUsers = useMemo(() => {
|
|
const arr = Array.isArray(userResults) ? userResults : [];
|
|
const seen = new Set();
|
|
const unique = [];
|
|
for (const u of arr) {
|
|
const id = u?.id;
|
|
if (!id || seen.has(id)) continue;
|
|
if (id === currentUID || u?.userID === currentUID) continue;
|
|
seen.add(id);
|
|
unique.push(u);
|
|
}
|
|
return unique;
|
|
}, [JSON.stringify(userResults), currentUID]);
|
|
|
|
const {
|
|
data: projectResults = [],
|
|
loading: projectsLoading,
|
|
loadMore: loadMoreProjects,
|
|
} = useDataFromRef({
|
|
ref: projectsQueryRef,
|
|
simpleRef: false,
|
|
listener: false,
|
|
condition: !!projectsQueryRef,
|
|
refreshArray: [queryText],
|
|
usePagination: true,
|
|
batchSize: 6,
|
|
});
|
|
const filteredProjects = useMemo(() => {
|
|
return Array.isArray(projectResults) ? projectResults : [];
|
|
}, [JSON.stringify(projectResults)]);
|
|
|
|
useEffect(() => {
|
|
setAutoLoads(0);
|
|
}, [queryText]);
|
|
|
|
useEffect(() => {
|
|
if (filteredUsers.length < 5 && usersQueryRef && !usersLoading) {
|
|
if (autoLoads < 3) {
|
|
setAutoLoads((n) => n + 1);
|
|
loadMoreUsers();
|
|
}
|
|
}
|
|
}, [
|
|
filteredUsers.length,
|
|
usersLoading,
|
|
usersQueryRef,
|
|
autoLoads,
|
|
loadMoreUsers,
|
|
]);
|
|
const [menuTop, setMenuTop] = useState(0);
|
|
const [showMenu, setShowMenu] = useState(false);
|
|
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
|
|
|
const onPressMenu = (item) => {
|
|
if (selected === item) {
|
|
setSelected(null);
|
|
} else {
|
|
setSelected(item);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Page
|
|
headerType="NAVIGATION"
|
|
backgroundImg={background.libraryBG2}
|
|
title="Recherche"
|
|
contentContainerStyle={{
|
|
paddingBottom: gutters * 2,
|
|
}}
|
|
>
|
|
<View style={{ flex: 1, gap: 10 }}>
|
|
<ResearchHeader
|
|
onPress={(item) => onPressMenu(item)}
|
|
selected={selected}
|
|
searchValue={search}
|
|
onChangeSearch={setSearch}
|
|
/>
|
|
<View style={{ flex: 1 }}>
|
|
<ScrollView contentContainerStyle={{ paddingTop: 2 }}>
|
|
{(!selected || selected === "Musiques") && (
|
|
<View style={{ paddingHorizontal: 2 }}>
|
|
<CreateLyricsHeader
|
|
gradientProps={{
|
|
start: { x: 0, y: 0 },
|
|
end: { x: 0, y: 1 },
|
|
}}
|
|
>
|
|
<View style={{ gap: 10 }}>
|
|
{Array.isArray(filteredProjects) &&
|
|
filteredProjects.slice(0, 6).map((p) => (
|
|
<MusicCard
|
|
key={p.id}
|
|
title={p?.title || "Sans titre"}
|
|
subtitle={"MusicLand"}
|
|
imageUri={p?.coverUrl || null}
|
|
projectId={p?.id}
|
|
likedBy={p?.likedBy || []}
|
|
onPress={() =>
|
|
navigate(Routes.MusicDetails, { projectId: p.id })
|
|
}
|
|
onPressMore={(posTop) => {
|
|
setSelectedProjectId(p.id);
|
|
setMenuTop(posTop);
|
|
setShowMenu((prev) => !prev || posTop !== menuTop);
|
|
}}
|
|
/>
|
|
))}
|
|
{(filteredProjects.length >= 6 || projectsLoading) && (
|
|
<Pressable
|
|
onPress={loadMoreProjects}
|
|
style={{ alignSelf: "center", marginTop: 6 }}
|
|
>
|
|
<Text
|
|
style={{
|
|
fontSize: 12,
|
|
color: Palette.white,
|
|
fontFamily: FONT_FAMILY.InterRegular,
|
|
opacity: projectsLoading ? 0.6 : 1,
|
|
}}
|
|
>
|
|
{projectsLoading ? "Chargement…" : "Charger plus"}
|
|
</Text>
|
|
</Pressable>
|
|
)}
|
|
</View>
|
|
</CreateLyricsHeader>
|
|
</View>
|
|
)}
|
|
{(!selected || selected === "Clips") && (
|
|
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
|
<CreateLyricsHeader
|
|
gradientProps={{
|
|
start: { x: 0, y: 0 },
|
|
end: { x: 0, y: 1 },
|
|
}}
|
|
>
|
|
<View style={{ gap: 6, ...Style.containerRow }}>
|
|
{Array.from({ length: 3 }).map((_, index) => (
|
|
<View style={{ flex: 1, gap: 6 }} key={index}>
|
|
<Image
|
|
source={img.placeholder3}
|
|
style={{
|
|
width: "100%",
|
|
height: 147,
|
|
borderRadius: 10,
|
|
}}
|
|
/>
|
|
<Text
|
|
style={{
|
|
fontSize: 12,
|
|
color: Palette.white,
|
|
fontFamily: FONT_FAMILY.InterRegular,
|
|
}}
|
|
>
|
|
Pour Lili
|
|
</Text>
|
|
</View>
|
|
))}
|
|
</View>
|
|
</CreateLyricsHeader>
|
|
</View>
|
|
)}
|
|
{(!selected || selected === "Profils") && (
|
|
<View style={{ paddingHorizontal: 2, paddingTop: 10 }}>
|
|
<CreateLyricsHeader
|
|
gradientProps={{ start: { x: 0, y: 0 }, end: { x: 0, y: 1 } }}
|
|
>
|
|
<View style={{ gap: 8 }}>
|
|
{Array.isArray(filteredUsers) &&
|
|
filteredUsers.slice(0, 5).map((u) => (
|
|
<Pressable
|
|
style={{ gap: 14, ...Style.containerRow }}
|
|
key={u.id}
|
|
onPress={() =>
|
|
navigate(Routes.SingerProfile, { userId: u.id })
|
|
}
|
|
>
|
|
<Image
|
|
source={
|
|
u?.pictureUrl || u?.profilePictureURL || u?.photoURL
|
|
? {
|
|
uri:
|
|
u?.pictureUrl ||
|
|
u?.profilePictureURL ||
|
|
u?.photoURL,
|
|
}
|
|
: img.profile
|
|
}
|
|
style={{ ...size({ size: 60 }), borderRadius: 100 }}
|
|
/>
|
|
<Text
|
|
style={{
|
|
fontSize: 12,
|
|
color: Palette.white,
|
|
fontFamily: FONT_FAMILY.InterRegular,
|
|
}}
|
|
>
|
|
{u?.userName || "Utilisateur"}
|
|
</Text>
|
|
</Pressable>
|
|
))}
|
|
{(filteredUsers.length >= 5 || usersLoading) && (
|
|
<Pressable
|
|
onPress={loadMoreUsers}
|
|
style={{ alignSelf: "center", marginTop: 6 }}
|
|
>
|
|
<Text
|
|
style={{
|
|
fontSize: 12,
|
|
color: Palette.white,
|
|
fontFamily: FONT_FAMILY.InterRegular,
|
|
opacity: usersLoading ? 0.6 : 1,
|
|
}}
|
|
>
|
|
{usersLoading ? "Chargement…" : "Charger plus"}
|
|
</Text>
|
|
</Pressable>
|
|
)}
|
|
</View>
|
|
</CreateLyricsHeader>
|
|
</View>
|
|
)}
|
|
<MoreMenu
|
|
visible={showMenu}
|
|
top={menuTop}
|
|
onClose={() => setShowMenu(false)}
|
|
inPlaylist={false}
|
|
projectId={selectedProjectId}
|
|
/>
|
|
</ScrollView>
|
|
</View>
|
|
</View>
|
|
</Page>
|
|
);
|
|
};
|
|
|
|
export default Research;
|