new project modal & seperate playback and music likes
This commit is contained in:
@@ -13,6 +13,7 @@ import { Routes } from "../../navigation";
|
||||
import { navigate } from "../../navigation/NavigationService";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { getArtistDisplayName } from "../../utils/artistName";
|
||||
import { getProjectLikes, LIKE_TARGET } from "../../utils/likes";
|
||||
import { Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import MusicCard from "../Library/components/MusicCard";
|
||||
@@ -86,7 +87,7 @@ const HomeSave = () => {
|
||||
subtitle={item?.userName || ownerDisplayName}
|
||||
imageUri={item?.coverUrl || null}
|
||||
projectId={item?.id}
|
||||
likedBy={item?.likedBy || []}
|
||||
likedBy={getProjectLikes(item, LIKE_TARGET.SONG)}
|
||||
onPress={() => {
|
||||
selectProject(item.id);
|
||||
navigate(Routes.Home);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import {
|
||||
FlatList,
|
||||
Image,
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
View,
|
||||
useWindowDimensions,
|
||||
} from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import GradientButton from "../../../components/GradientButton";
|
||||
import useLayoutType from "../../../hooks/useLayoutType";
|
||||
import { Routes } from "../../../navigation";
|
||||
@@ -29,7 +30,10 @@ const BackTracks = () => {
|
||||
0,
|
||||
Math.floor((containerWidth - gap * (numColumns - 1)) / numColumns)
|
||||
);
|
||||
console.log("BackTracks items:", items);
|
||||
|
||||
const openPlaybackPicker = useCallback(() => {
|
||||
SheetManager.show("PlaybackPicker");
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<CardContainer
|
||||
@@ -41,7 +45,7 @@ const BackTracks = () => {
|
||||
liked: false,
|
||||
})
|
||||
}
|
||||
onPressPlus={() => navigate(Routes.WritingLyrics)}
|
||||
onPressPlus={openPlaybackPicker}
|
||||
>
|
||||
<View>
|
||||
{items.length > 0 ? (
|
||||
@@ -85,7 +89,7 @@ const BackTracks = () => {
|
||||
</Text>
|
||||
<GradientButton
|
||||
containerStyle={{ padding: 2 }}
|
||||
onPress={() => navigate(Routes.WritingLyrics)}
|
||||
onPress={openPlaybackPicker}
|
||||
title=" Créer un playback"
|
||||
></GradientButton>
|
||||
</View>
|
||||
|
||||
@@ -13,7 +13,7 @@ import { responsiveWidth } from "react-native-responsive-dimensions";
|
||||
import { useGlobal } from "reactn";
|
||||
import { icons, img } from "../../../assets";
|
||||
import PressableScale from "../../../components/PressableScale";
|
||||
import { arrayRemove, arrayUnion, projectsRef } from "../../../config/firebase";
|
||||
import { LIKE_TARGET, toggleProjectLike } from "../../../utils/likes";
|
||||
import { Palette, Style } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { size } from "../../../styles/Style";
|
||||
@@ -26,6 +26,7 @@ const MusicCard = ({
|
||||
imageUri = null,
|
||||
projectId = null,
|
||||
likedBy = [],
|
||||
likeTarget = LIKE_TARGET.SONG,
|
||||
}) => {
|
||||
const [currentUID] = useGlobal("currentUID");
|
||||
const [selected, setSelected] = useState(false);
|
||||
@@ -58,8 +59,11 @@ const MusicCard = ({
|
||||
const next = !selected;
|
||||
setSelected(next);
|
||||
try {
|
||||
await projectsRef.doc(projectId).update({
|
||||
likedBy: next ? arrayUnion(currentUID) : arrayRemove(currentUID),
|
||||
await toggleProjectLike({
|
||||
projectId,
|
||||
target: likeTarget,
|
||||
currentUID,
|
||||
next,
|
||||
});
|
||||
} catch (e) {
|
||||
// rollback on failure
|
||||
|
||||
@@ -15,12 +15,7 @@ import { icons, img } from "../../assets";
|
||||
import { openComments } from "../../components/bottomsheets/CommentsBottomSheet";
|
||||
import KaraokeLyrics from "../../components/KaraokeLyrics";
|
||||
import ProfilePicture from "../../components/ProfilePicture";
|
||||
import {
|
||||
arrayRemove,
|
||||
arrayUnion,
|
||||
projectsRef,
|
||||
usersRef,
|
||||
} from "../../config/firebase";
|
||||
import { projectsRef, usersRef } from "../../config/firebase";
|
||||
import useDataFromRef from "../../hooks/useDataFromRef";
|
||||
import { Routes } from "../../navigation";
|
||||
import { navigate } from "../../navigation/NavigationService";
|
||||
@@ -28,11 +23,16 @@ import { useUser } from "../../providers/UserDataProvider";
|
||||
import { Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { size } from "../../styles/Style";
|
||||
import {
|
||||
getProjectLikes,
|
||||
LIKE_TARGET,
|
||||
toggleProjectLike,
|
||||
} from "../../utils/likes";
|
||||
|
||||
const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
||||
const { currentUID, followUser, unfollowUser } = useUser() || {};
|
||||
const videoUrl = item?.playbackUrl || null;
|
||||
const initialLikedBy = Array.isArray(item?.likedBy) ? item.likedBy : [];
|
||||
const initialLikedBy = getProjectLikes(item, LIKE_TARGET.PLAYBACK);
|
||||
const [isLiked, setIsLiked] = useState(
|
||||
currentUID ? initialLikedBy.includes(currentUID) : false
|
||||
);
|
||||
@@ -100,10 +100,10 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
||||
}, [owner?.followedBy, currentUID]);
|
||||
|
||||
useEffect(() => {
|
||||
const lb = Array.isArray(item?.likedBy) ? item.likedBy : [];
|
||||
const lb = getProjectLikes(item, LIKE_TARGET.PLAYBACK);
|
||||
setLikesCount(lb.length);
|
||||
setIsLiked(currentUID ? lb.includes(currentUID) : false);
|
||||
}, [item?.likedBy, currentUID]);
|
||||
}, [item?.likes?.playback, currentUID]);
|
||||
|
||||
const projectTitle = typeof item?.title === "string" ? item.title.trim() : "";
|
||||
|
||||
@@ -292,16 +292,12 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
||||
setIsLiked(nextLiked);
|
||||
setLikesCount((c) => Math.max(0, c + (nextLiked ? 1 : -1)));
|
||||
|
||||
const ref = projectsRef.doc(item.id);
|
||||
await ref.set(
|
||||
{
|
||||
likedBy: nextLiked
|
||||
? arrayUnion(currentUID)
|
||||
: arrayRemove(currentUID),
|
||||
// Optionally: updatedAt could be set if needed
|
||||
},
|
||||
{ merge: true }
|
||||
);
|
||||
await toggleProjectLike({
|
||||
projectId: item.id,
|
||||
currentUID,
|
||||
target: LIKE_TARGET.PLAYBACK,
|
||||
next: nextLiked,
|
||||
});
|
||||
} catch (e) {
|
||||
// rollback on failure
|
||||
setIsLiked((v) => !v);
|
||||
|
||||
@@ -17,12 +17,7 @@ import {
|
||||
} from "react-native";
|
||||
import { icons, img } from "../../../assets";
|
||||
import KaraokeLyrics from "../../../components/KaraokeLyrics";
|
||||
import {
|
||||
arrayRemove,
|
||||
arrayUnion,
|
||||
projectsRef,
|
||||
usersRef,
|
||||
} from "../../../config/firebase";
|
||||
import { usersRef } from "../../../config/firebase";
|
||||
import { Routes } from "../../../navigation";
|
||||
import { navigate } from "../../../navigation/NavigationService";
|
||||
import { useUser } from "../../../providers/UserDataProvider";
|
||||
@@ -30,6 +25,11 @@ import { Palette } from "../../../styles";
|
||||
import { FONT_FAMILY } from "../../../styles/Fonts";
|
||||
import { size } from "../../../styles/Style";
|
||||
import CommentsPanel from "./CommentsPanel.web";
|
||||
import {
|
||||
getProjectLikes,
|
||||
LIKE_TARGET,
|
||||
toggleProjectLike,
|
||||
} from "../../../utils/likes";
|
||||
|
||||
// Debug logging toggle for web playback
|
||||
const DEBUG_PLAYBACK_WEB = true;
|
||||
@@ -61,7 +61,7 @@ const PlaybackItem = ({
|
||||
const wasActiveRef = useRef(false);
|
||||
const startedRef = useRef(false);
|
||||
|
||||
const initialLikedBy = Array.isArray(item?.likedBy) ? item.likedBy : [];
|
||||
const initialLikedBy = getProjectLikes(item, LIKE_TARGET.PLAYBACK);
|
||||
const [isLiked, setIsLiked] = useState(
|
||||
currentUID ? initialLikedBy.includes(currentUID) : false
|
||||
);
|
||||
@@ -130,10 +130,10 @@ const PlaybackItem = ({
|
||||
}, [owner?.followedBy, currentUID]);
|
||||
|
||||
useEffect(() => {
|
||||
const lb = Array.isArray(item?.likedBy) ? item.likedBy : [];
|
||||
const lb = getProjectLikes(item, LIKE_TARGET.PLAYBACK);
|
||||
setLikesCount(lb.length);
|
||||
setIsLiked(currentUID ? lb.includes(currentUID) : false);
|
||||
}, [item?.likedBy, currentUID]);
|
||||
}, [item?.likes?.playback, currentUID]);
|
||||
|
||||
useEffect(() => {
|
||||
startedRef.current = false;
|
||||
@@ -428,15 +428,12 @@ const PlaybackItem = ({
|
||||
setIsLiked(nextLiked);
|
||||
setLikesCount((c) => Math.max(0, c + (nextLiked ? 1 : -1)));
|
||||
|
||||
const ref = projectsRef.doc(item.id);
|
||||
await ref.set(
|
||||
{
|
||||
likedBy: nextLiked
|
||||
? arrayUnion(currentUID)
|
||||
: arrayRemove(currentUID),
|
||||
},
|
||||
{ merge: true }
|
||||
);
|
||||
await toggleProjectLike({
|
||||
projectId: item.id,
|
||||
currentUID,
|
||||
target: LIKE_TARGET.PLAYBACK,
|
||||
next: nextLiked,
|
||||
});
|
||||
} catch (_e) {
|
||||
setIsLiked((v) => !v);
|
||||
setLikesCount((c) =>
|
||||
|
||||
@@ -35,6 +35,7 @@ import { Routes } from "../../navigation";
|
||||
import { push } from "../../navigation/NavigationService";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { getArtistDisplayName } from "../../utils/artistName";
|
||||
import { getProjectLikes, LIKE_TARGET } from "../../utils/likes";
|
||||
import { Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import Style, { gutters, size } from "../../styles/Style";
|
||||
@@ -191,7 +192,11 @@ const Profile = () => {
|
||||
};
|
||||
|
||||
// Composant factorisé pour afficher la liste de musiques
|
||||
const MusicListSection = ({ data, emptyText }) => (
|
||||
const MusicListSection = ({
|
||||
data,
|
||||
emptyText,
|
||||
likeTarget = LIKE_TARGET.SONG,
|
||||
}) => (
|
||||
<ScrollView style={{ flex: 1, marginBottom: 70 }}>
|
||||
{Array.isArray(data) && data.length > 0 ? (
|
||||
<FlatList
|
||||
@@ -207,12 +212,21 @@ const Profile = () => {
|
||||
subtitle={isSelf ? selfDisplayName : targetDisplayName}
|
||||
imageUri={item?.coverUrl || null}
|
||||
projectId={item?.id}
|
||||
likedBy={item?.likedBy || []}
|
||||
likedBy={getProjectLikes(item, likeTarget)}
|
||||
likeTarget={likeTarget}
|
||||
onPress={() =>
|
||||
navigateToMusicDetails({
|
||||
projectId: item.id,
|
||||
songUrl: item?.songUrl,
|
||||
project: item,
|
||||
queueProjects: data,
|
||||
queueSource: {
|
||||
id: isSelf ? "profile-self" : "profile-other",
|
||||
type: "collection",
|
||||
name: isSelf
|
||||
? "Mes musiques"
|
||||
: targetDisplayName || "Profil",
|
||||
},
|
||||
})
|
||||
}
|
||||
onPressMore={(posTop) => {
|
||||
@@ -528,6 +542,7 @@ const Profile = () => {
|
||||
<MusicListSection
|
||||
data={displayedPlaybacks}
|
||||
emptyText="Aucun playback pour le moment"
|
||||
likeTarget={LIKE_TARGET.PLAYBACK}
|
||||
/>
|
||||
)}
|
||||
{selected === "Chansons" && (
|
||||
|
||||
Reference in New Issue
Block a user