playlists
This commit is contained in:
@@ -1,31 +1,34 @@
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
FlatList,
|
||||
Pressable,
|
||||
Image,
|
||||
Dimensions,
|
||||
TextInput,
|
||||
} from "react-native";
|
||||
import React, { useRef, useState } from "react";
|
||||
import AppActionSheet from "../AppActionSheet";
|
||||
import AppCheckbox from "../AppCheckbox";
|
||||
import {
|
||||
Dimensions,
|
||||
FlatList,
|
||||
Image,
|
||||
Pressable,
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import SwiperFlatList from "react-native-swiper-flatlist";
|
||||
import { icons } from "../../assets";
|
||||
import { useUserData } from "../../providers/UserDataProvider";
|
||||
import { createPlaylist } from "../../screens/Library/Playlists/playlist";
|
||||
import { Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { icons } from "../../assets";
|
||||
import Style, { size } from "../../styles/Style";
|
||||
import SwiperFlatList from "react-native-swiper-flatlist";
|
||||
import AppActionSheet from "../AppActionSheet";
|
||||
import AppCheckbox from "../AppCheckbox";
|
||||
import GradientButton from "../GradientButton";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
|
||||
const PLAYLIST = ["Ménage", "Voiture", "Roadtrip"];
|
||||
|
||||
const { width } = Dimensions.get("window");
|
||||
|
||||
const PlaylistModal = () => {
|
||||
const PlaylistModal = (props) => {
|
||||
const scrollRef = useRef(null);
|
||||
const [selected, setSelected] = useState("");
|
||||
const [selectedId, setSelectedId] = useState("");
|
||||
const [playlist, setPlaylist] = useState("");
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const { currentUID, userPlaylists = [] } = useUserData();
|
||||
const startAtCreate = props?.payload?.startAtCreate || false;
|
||||
|
||||
return (
|
||||
<AppActionSheet id="Playlist">
|
||||
@@ -33,6 +36,7 @@ const PlaylistModal = () => {
|
||||
style={{ width, left: -14 }}
|
||||
ref={scrollRef}
|
||||
disableGesture
|
||||
index={startAtCreate ? 1 : 0}
|
||||
>
|
||||
<View style={{ width, paddingHorizontal: 14 }}>
|
||||
<View style={{ gap: 20 }}>
|
||||
@@ -47,7 +51,7 @@ const PlaylistModal = () => {
|
||||
Ajouter ce titre à une playlist
|
||||
</Text>
|
||||
<FlatList
|
||||
data={PLAYLIST}
|
||||
data={Array.isArray(userPlaylists) ? userPlaylists : []}
|
||||
contentContainerStyle={{ gap: 20 }}
|
||||
ListHeaderComponent={
|
||||
<Pressable
|
||||
@@ -76,9 +80,9 @@ const PlaylistModal = () => {
|
||||
}
|
||||
renderItem={({ item }) => (
|
||||
<AppCheckbox
|
||||
label={item}
|
||||
onPress={() => setSelected(item)}
|
||||
selected={selected === item}
|
||||
label={item?.name || "Sans nom"}
|
||||
onPress={() => setSelectedId(item?.id)}
|
||||
selected={selectedId === item?.id}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@@ -94,25 +98,27 @@ const PlaylistModal = () => {
|
||||
</View>
|
||||
<View style={{ width, paddingHorizontal: 14 }}>
|
||||
<View style={{ gap: 20 }}>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
scrollRef.current.scrollToIndex({
|
||||
index: 0,
|
||||
animated: true,
|
||||
});
|
||||
setPlaylist("");
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: Palette.gray,
|
||||
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
||||
{!startAtCreate && (
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
scrollRef.current.scrollToIndex({
|
||||
index: 0,
|
||||
animated: true,
|
||||
});
|
||||
setPlaylist("");
|
||||
}}
|
||||
>
|
||||
Annuler
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: Palette.gray,
|
||||
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
||||
}}
|
||||
>
|
||||
Annuler
|
||||
</Text>
|
||||
</Pressable>
|
||||
)}
|
||||
<View style={{ ...Style.containerCenter, gap: 14 }}>
|
||||
<Text
|
||||
style={{
|
||||
@@ -140,17 +146,32 @@ const PlaylistModal = () => {
|
||||
/>
|
||||
</View>
|
||||
<GradientButton
|
||||
title="Créer la playlist"
|
||||
title={isCreating ? "Création..." : "Créer la playlist"}
|
||||
containerStyle={{
|
||||
width: "80%",
|
||||
alignSelf: "center",
|
||||
opacity: playlist?.trim()?.length ? 1 : 0.5,
|
||||
}}
|
||||
onPress={() => {
|
||||
scrollRef.current.scrollToIndex({
|
||||
index: 0,
|
||||
animated: true,
|
||||
});
|
||||
setPlaylist("");
|
||||
disabled={!playlist?.trim()?.length || isCreating}
|
||||
onPress={async () => {
|
||||
if (!playlist?.trim()?.length || !currentUID) return;
|
||||
try {
|
||||
setIsCreating(true);
|
||||
await createPlaylist({
|
||||
createdBy: currentUID,
|
||||
name: playlist.trim(),
|
||||
musics: [],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
});
|
||||
setPlaylist("");
|
||||
SheetManager.hide("Playlist");
|
||||
scrollRef.current.scrollToIndex({ index: 0, animated: true });
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
setIsCreating(false);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import firebase from "firebase/compat/app";
|
||||
import {
|
||||
initializeAuth,
|
||||
getReactNativePersistence,
|
||||
} from "firebase/auth/react-native";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import {
|
||||
getReactNativePersistence,
|
||||
initializeAuth,
|
||||
} from "firebase/auth/react-native";
|
||||
import firebase from "firebase/compat/app";
|
||||
|
||||
import "firebase/compat/auth";
|
||||
import "firebase/compat/storage";
|
||||
import "firebase/compat/functions";
|
||||
import "firebase/compat/firestore";
|
||||
import "firebase/compat/functions";
|
||||
import "firebase/compat/storage";
|
||||
|
||||
export const firebaseConfig = {
|
||||
apiKey: "AIzaSyCuHJHdwVN_F-VmUG4Hd7bGiMRqj6rPlLo",
|
||||
@@ -48,6 +48,7 @@ try {
|
||||
|
||||
export const usersRef = firestore.collection("users");
|
||||
export const projectsRef = firestore.collection("projects");
|
||||
export const playlistsRef = firestore.collection("playlists");
|
||||
export const notificationsRef = firestore.collection("notifications");
|
||||
export const documentsRef = firestore.collection("documents");
|
||||
export const chatsRef = firestore.collection("chats");
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function useDataFromArrayDocId({
|
||||
ref,
|
||||
format = null,
|
||||
arrayId = [],
|
||||
refreshArray = [],
|
||||
condition = true,
|
||||
pagination = false,
|
||||
batchSize = 20,
|
||||
}) {
|
||||
const [data, setData] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
|
||||
async function getAllDocs(arrayToGet) {
|
||||
try {
|
||||
setLoading(true);
|
||||
const promises = arrayToGet.map(async (id) => {
|
||||
return new Promise(async (resolve) => {
|
||||
const doc = await ref.doc(id).get();
|
||||
if (doc.exists) {
|
||||
resolve({ ...doc.data(), id: doc.id });
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
await Promise.all(promises).then(async (values) => {
|
||||
const validData = values.filter((value) => value !== null);
|
||||
const newData = format ? await format(validData) : validData;
|
||||
if (currentPage > 0) {
|
||||
setData((prev) => [...prev, ...newData]);
|
||||
} else {
|
||||
setData(newData);
|
||||
}
|
||||
if (pagination && newData.length > 0) {
|
||||
setCurrentPage((prev) => prev + 1);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
function getNewArrayToGet(currPage = 0) {
|
||||
const start = currPage * batchSize;
|
||||
const end = (currPage + 1) * batchSize;
|
||||
const newArray = arrayId.slice(start, end);
|
||||
return newArray.filter(Boolean);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (ref && arrayId?.length > 0 && !!condition && !loading) {
|
||||
if (pagination) {
|
||||
setCurrentPage(0);
|
||||
getAllDocs(getNewArrayToGet(0));
|
||||
} else {
|
||||
getAllDocs(arrayId);
|
||||
}
|
||||
} else {
|
||||
if (data.length > 0) {
|
||||
setData([]);
|
||||
}
|
||||
}
|
||||
}, [ref, arrayId?.length, condition, ...refreshArray]);
|
||||
|
||||
async function loadMore() {
|
||||
if (ref && arrayId?.length > 0 && !!condition && !loading) {
|
||||
getAllDocs(getNewArrayToGet(currentPage));
|
||||
}
|
||||
}
|
||||
|
||||
return { data, setData, loading, loadMore };
|
||||
}
|
||||
@@ -5,7 +5,11 @@ import { createContext, useContext, useGlobal } from "reactn";
|
||||
|
||||
import { useState } from "react";
|
||||
import { checkIfEmailIsValid } from "../actions/signupActions";
|
||||
import firebase, { usersRef } from "../config/firebase";
|
||||
import firebase, {
|
||||
playlistsRef,
|
||||
projectsRef,
|
||||
usersRef,
|
||||
} from "../config/firebase";
|
||||
|
||||
export const UserDataContext = createContext();
|
||||
|
||||
@@ -21,7 +25,8 @@ export default ({ children }) => {
|
||||
const [currentUserRoles] = useGlobal("currentUserRoles");
|
||||
const [userProjects, setUserProjects] = useState([]);
|
||||
const [userLikedProjects, setUserLikedProjects] = useState([]);
|
||||
const [userLikedMusic, setUserLikedMusic] = useState([]);
|
||||
const [userPlaylists, setUserPlaylists] = useState([]);
|
||||
|
||||
useDataFromRef({
|
||||
ref: currentUID ? usersRef.doc(currentUID) : null,
|
||||
simpleRef: true,
|
||||
@@ -40,9 +45,7 @@ export default ({ children }) => {
|
||||
// Subscribe to user's projects (musics)
|
||||
useDataFromRef({
|
||||
ref: currentUID
|
||||
? firebase
|
||||
.firestore()
|
||||
.collection("projects")
|
||||
? projectsRef
|
||||
.where("userId", "==", currentUID)
|
||||
.orderBy("updatedAt", "desc")
|
||||
: null,
|
||||
@@ -56,9 +59,7 @@ export default ({ children }) => {
|
||||
// Subscribe to user's liked projects
|
||||
useDataFromRef({
|
||||
ref: currentUID
|
||||
? firebase
|
||||
.firestore()
|
||||
.collection("projects")
|
||||
? projectsRef
|
||||
.where("likedBy", "array-contains", currentUID)
|
||||
.orderBy("updatedAt", "desc")
|
||||
: null,
|
||||
@@ -69,20 +70,14 @@ export default ({ children }) => {
|
||||
onUpdate: (list) => setUserLikedProjects(Array.isArray(list) ? list : []),
|
||||
});
|
||||
|
||||
// userLiked music
|
||||
// Subscribe to user's playlists
|
||||
useDataFromRef({
|
||||
ref: currentUID
|
||||
? firebase
|
||||
.firestore()
|
||||
.collection("projects")
|
||||
.where("likedBy", "array-contains", currentUID)
|
||||
.orderBy("updatedAt", "desc")
|
||||
: null,
|
||||
ref: currentUID ? playlistsRef.where("createdBy", "==", currentUID) : null,
|
||||
simpleRef: false,
|
||||
listener: true,
|
||||
condition: !!currentUID,
|
||||
refreshArray: [currentUID],
|
||||
onUpdate: (list) => setUserLikedMusic(Array.isArray(list) ? list : []),
|
||||
onUpdate: (list) => setUserPlaylists(Array.isArray(list) ? list : []),
|
||||
});
|
||||
|
||||
const updatePendingUserData = (newData) => {
|
||||
@@ -149,8 +144,6 @@ export default ({ children }) => {
|
||||
cleanData.creationTimestamp = new Date();
|
||||
}
|
||||
|
||||
console.log("cleanData", cleanData);
|
||||
|
||||
await usersRef.doc(dynamicUID).set(cleanData, { merge: true });
|
||||
|
||||
if (shouldSetTooltip) {
|
||||
@@ -197,6 +190,7 @@ export default ({ children }) => {
|
||||
currentUserData,
|
||||
userProjects,
|
||||
userLikedProjects,
|
||||
userPlaylists,
|
||||
|
||||
setCurrentUserData,
|
||||
|
||||
|
||||
@@ -1,31 +1,44 @@
|
||||
import { View, Text, Image, Pressable, Platform } from "react-native";
|
||||
import React from "react";
|
||||
import Page from "../../layouts/Page";
|
||||
import { background, icons } from "../../assets";
|
||||
import { gutters, Palette, Style } from "../../styles";
|
||||
import { BlurView } from "expo-blur";
|
||||
import React from "react";
|
||||
import { Image, Platform, Pressable, Text, View } from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import { background, icons } from "../../assets";
|
||||
import Page from "../../layouts/Page";
|
||||
import { gutters, Palette, Style } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { size } from "../../styles/Style";
|
||||
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
const AllMyPlaylist = () => {
|
||||
const { userPlaylists = [] } = useUser();
|
||||
return (
|
||||
<Page
|
||||
headerType="NAVIGATION"
|
||||
backgroundImg={background.libraryBG}
|
||||
title="Mes Playlists"
|
||||
rightComponent={() => (
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
SheetManager.show("Playlist", { payload: { startAtCreate: true } })
|
||||
}
|
||||
>
|
||||
<Image
|
||||
source={icons.add}
|
||||
style={size({ size: 18 })}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</Pressable>
|
||||
)}
|
||||
contentContainerStyle={{
|
||||
paddingBottom: gutters * 2,
|
||||
}}
|
||||
>
|
||||
<View style={{ flex: 1 }}>
|
||||
<View style={{ gap: 8 }}>
|
||||
{[
|
||||
"Musiques de lover",
|
||||
"Musiques triste",
|
||||
"Happy new year",
|
||||
"Happy songs",
|
||||
].map((item, index) => (
|
||||
<View style={{ borderRadius: 12, overflow: "hidden" }} key={index}>
|
||||
{(Array.isArray(userPlaylists) ? userPlaylists : []).map((item) => (
|
||||
<View
|
||||
style={{ borderRadius: 12, overflow: "hidden" }}
|
||||
key={item?.id}
|
||||
>
|
||||
<BlurView
|
||||
intensity={20}
|
||||
style={{
|
||||
@@ -44,7 +57,7 @@ const AllMyPlaylist = () => {
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
}}
|
||||
>
|
||||
{item}
|
||||
{item?.name || "Sans nom"}
|
||||
</Text>
|
||||
<Pressable>
|
||||
<Image
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { playlistsRef } from "../../../config/firebase";
|
||||
|
||||
export const createPlaylist = async (payload = {}) => {
|
||||
try {
|
||||
const createdBy = payload?.createdBy;
|
||||
const name = payload?.name?.trim?.();
|
||||
const musics = Array.isArray(payload?.musics) ? payload.musics : [];
|
||||
|
||||
const doc = {
|
||||
createdBy,
|
||||
name,
|
||||
musics,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
const docRef = await playlistsRef.add(doc);
|
||||
return docRef.id;
|
||||
} catch (error) {
|
||||
console.error("Error creating playlist:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -1,21 +1,29 @@
|
||||
import { BlurView } from "expo-blur";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
Image,
|
||||
Platform,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
Platform,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Palette, Style } from "../../../styles";
|
||||
import { icons, img } from "../../../assets";
|
||||
import { size } from "../../../styles/Style";
|
||||
import { BlurView } from "expo-blur";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { useGlobal } from "reactn";
|
||||
import { projectsRef, arrayUnion, arrayRemove } from "../../../config/firebase";
|
||||
import { icons, img } from "../../../assets";
|
||||
import { arrayRemove, arrayUnion, projectsRef } from "../../../config/firebase";
|
||||
import { Palette, Style } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { size } from "../../../styles/Style";
|
||||
|
||||
const MusicCard = ({ onPress, onPressMore, title = "Sans titre", subtitle = "MusicLand", imageUri = null, projectId = null, likedBy = [] }) => {
|
||||
const MusicCard = ({
|
||||
onPress,
|
||||
onPressMore,
|
||||
title = "Sans titre",
|
||||
subtitle = "MusicLand",
|
||||
imageUri = null,
|
||||
projectId = null,
|
||||
likedBy = [],
|
||||
}) => {
|
||||
const [currentUID] = useGlobal("currentUID");
|
||||
const [selected, setSelected] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { View } from "react-native";
|
||||
import React from "react";
|
||||
import { View } from "react-native";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { useUser } from "../../../providers/UserDataProvider";
|
||||
import CardContainer from "./CardContainer";
|
||||
import MusicCard from "./MusicCard";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { useUser } from "../../../providers/UserDataProvider";
|
||||
|
||||
const MyMusic = () => {
|
||||
const { userProjects = [] } = useUser();
|
||||
const projects = Array.isArray(userProjects)
|
||||
? userProjects.slice(0, 3)
|
||||
: [];
|
||||
|
||||
const projects = Array.isArray(userProjects) ? userProjects.slice(0, 3) : [];
|
||||
return (
|
||||
<CardContainer
|
||||
label="Mes musiques"
|
||||
@@ -28,6 +25,7 @@ const MyMusic = () => {
|
||||
projectId={p?.id}
|
||||
likedBy={p?.likedBy || []}
|
||||
onPress={() => navigate(Routes.MusicDetails, { projectId: p.id })}
|
||||
onPressMore={() => console.log("More options for", p.id)}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
|
||||
@@ -8,16 +8,21 @@ import { Palette } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { useUser } from "../../../providers/UserDataProvider";
|
||||
|
||||
const MyPlaylist = () => {
|
||||
const { userPlaylists = [] } = useUser();
|
||||
const playlists = Array.isArray(userPlaylists)
|
||||
? userPlaylists.slice(0, 2)
|
||||
: [];
|
||||
return (
|
||||
<CardContainer
|
||||
label="Mes Playlists"
|
||||
onPress={() => navigate(Routes.AllMyPlaylist)}
|
||||
>
|
||||
<View style={{ gap: 8 }}>
|
||||
{["Musiques de lover", "Musiques triste"].map((item, index) => (
|
||||
<View style={{ borderRadius: 12, overflow: "hidden" }} key={index}>
|
||||
{playlists.map((item) => (
|
||||
<View style={{ borderRadius: 12, overflow: "hidden" }} key={item.id}>
|
||||
<BlurView
|
||||
intensity={20}
|
||||
style={{
|
||||
@@ -36,7 +41,7 @@ const MyPlaylist = () => {
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
}}
|
||||
>
|
||||
{item}
|
||||
{item?.name || "Sans nom"}
|
||||
</Text>
|
||||
<Pressable>
|
||||
<Image
|
||||
|
||||
Reference in New Issue
Block a user