From e79a4c71401c5fc6224705d4c4ba359a877bce03 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 16 Sep 2025 15:17:35 +0200 Subject: [PATCH] add - commentsCount --- .../bottomsheets/CommentsBottomSheet.js | 119 ++++++++-------- src/screens/Playbacks.js | 132 +++++++++--------- 2 files changed, 126 insertions(+), 125 deletions(-) diff --git a/src/components/bottomsheets/CommentsBottomSheet.js b/src/components/bottomsheets/CommentsBottomSheet.js index 01b66d9..1b868d9 100644 --- a/src/components/bottomsheets/CommentsBottomSheet.js +++ b/src/components/bottomsheets/CommentsBottomSheet.js @@ -3,16 +3,16 @@ import { BottomSheetBackdrop, BottomSheetModal, BottomSheetScrollView, -} from "@gorhom/bottom-sheet"; -import { BlurView } from "expo-blur"; -import { Image as ExpoImage } from "expo-image"; +} from '@gorhom/bottom-sheet'; +import { BlurView } from 'expo-blur'; +import { Image as ExpoImage } from 'expo-image'; import React, { useCallback, useEffect, useMemo, useRef, useState, -} from "react"; +} from 'react'; import { Image, Platform, @@ -20,29 +20,29 @@ import { Text, TextInput, View, -} from "react-native"; -import { useSafeAreaInsets } from "react-native-safe-area-context"; -import { icons } from "../../assets"; -import { projectsRef, serverTimestamp } from "../../config/firebase"; -import useDataFromRef from "../../hooks/useDataFromRef"; -import { useUser } from "../../providers/UserDataProvider"; -import { Palette } from "../../styles"; -import { FONT_FAMILY } from "../../styles/Fonts"; -import { size } from "../../styles/Style"; +} from 'react-native'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import { icons } from '../../assets'; +import { increment, projectsRef, serverTimestamp } from '../../config/firebase'; +import useDataFromRef from '../../hooks/useDataFromRef'; +import { useUser } from '../../providers/UserDataProvider'; +import { Palette } from '../../styles'; +import { FONT_FAMILY } from '../../styles/Fonts'; +import { size } from '../../styles/Style'; let externalOpen; let externalClose; export const openComments = (projectId) => { - if (typeof externalOpen === "function") externalOpen(projectId); + if (typeof externalOpen === 'function') externalOpen(projectId); }; export const closeComments = () => { - if (typeof externalClose === "function") externalClose(); + if (typeof externalClose === 'function') externalClose(); }; const formatRelativeTime = (date) => { try { const d = date instanceof Date ? date : date?.toDate?.() || null; - if (!d) return ""; + if (!d) return ''; const diff = Math.max(0, Date.now() - d.getTime()); const sec = Math.floor(diff / 1000); if (sec < 60) return `${sec}s`; @@ -53,7 +53,7 @@ const formatRelativeTime = (date) => { const dA = Math.floor(h / 24); return `${dA}j`; } catch (e) { - return ""; + return ''; } }; @@ -63,7 +63,7 @@ const CommentsBottomSheet = () => { const { currentUID, currentUserData } = useUser(); const [projectId, setProjectId] = useState(null); - const [text, setText] = useState(""); + const [text, setText] = useState(''); const [typing, setTyping] = useState(false); useEffect(() => { @@ -82,15 +82,15 @@ const CommentsBottomSheet = () => { }; }, []); - const snapPoints = useMemo(() => ["50%", "90%"], []); + const snapPoints = useMemo(() => ['50%', '90%'], []); const commentsRef = useMemo(() => { try { return projectId ? projectsRef .doc(projectId) - .collection("comments") - .orderBy("createdAt", "desc") + .collection('comments') + .orderBy('createdAt', 'desc') : null; } catch { return null; @@ -113,26 +113,31 @@ const CommentsBottomSheet = () => { }); const onSend = async () => { - const value = (text || "").trim(); + const value = (text || '').trim(); if (!value || !projectId || !currentUID) return; try { - setText(""); + setText(''); const docRef = await projectsRef .doc(projectId) - .collection("comments") + .collection('comments') .add({ userId: currentUID, - userName: currentUserData?.userName || "", - profilePicture: currentUserData?.profilePictureURL || "", + userName: currentUserData?.userName || '', + profilePicture: currentUserData?.profilePictureURL || '', text: value, createdAt: serverTimestamp(), }); + try { + await projectsRef + .doc(projectId) + .set({ commentsCount: increment(1) }, { merge: true }); + } catch {} // Optimistic: ajouter immédiatement le commentaire en tête de liste const optimistic = { id: docRef?.id || Math.random().toString(36).slice(2), userId: currentUID, - userName: currentUserData?.userName || "", - profilePicture: currentUserData?.profilePictureURL || "", + userName: currentUserData?.userName || '', + profilePicture: currentUserData?.profilePictureURL || '', text: value, createdAt: new Date(), }; @@ -187,15 +192,14 @@ const CommentsBottomSheet = () => { bottomInset={insets.bottom} backdropComponent={renderBackdrop} handleIndicatorStyle={{ backgroundColor: Palette.white }} - backgroundStyle={{ backgroundColor: "transparent" }} + backgroundStyle={{ backgroundColor: 'transparent' }} onDismiss={() => { setProjectId(null); setTyping(false); - setText(""); - }} - > + setText(''); + }}> { modalRef.current?.dismiss?.()} - style={{ position: "absolute", right: 10, top: 8, padding: 6 }} - hitSlop={8} - > + style={{ position: 'absolute', right: 10, top: 8, padding: 6 }} + hitSlop={8}> { fontSize: 22, color: Palette.white, fontFamily: FONT_FAMILY.InterSemiBold, - alignSelf: "center", - }} - > + alignSelf: 'center', + }}> Commentaires @@ -238,14 +240,12 @@ const CommentsBottomSheet = () => { paddingHorizontal: 14, paddingBottom: (insets?.bottom || 0) + 12, }} - showsVerticalScrollIndicator - > + showsVerticalScrollIndicator> {Array.isArray(comments) && comments.length > 0 ? ( comments.map((c) => ( + style={{ flexDirection: 'row', gap: 12, marginBottom: 14 }}> {c?.profilePicture ? ( { style={{ ...size({ size: 42 }), borderRadius: 100, - backgroundColor: "#FFFFFF22", + backgroundColor: '#FFFFFF22', }} /> )} + }}> - {c?.userId === currentUID ? "vous" : c?.userName || ""} + }}> + {c?.userId === currentUID ? 'vous' : c?.userName || ''} { color: Palette.white, opacity: 0.75, fontFamily: FONT_FAMILY.InterRegular, - }} - > + }}> • {formatRelativeTime(c?.createdAt)} @@ -297,8 +294,7 @@ const CommentsBottomSheet = () => { fontSize: 14, color: Palette.white, fontFamily: FONT_FAMILY.InterRegular, - }} - > + }}> {c?.text} @@ -311,10 +307,9 @@ const CommentsBottomSheet = () => { color: Palette.white, opacity: 0.8, fontFamily: FONT_FAMILY.InterRegular, - textAlign: "center", + textAlign: 'center', marginTop: 6, - }} - > + }}> Aucun commentaire pour le moment )} @@ -322,14 +317,14 @@ const CommentsBottomSheet = () => { {/* INPUT en bas du contenu */} { const { currentUID, followUser, unfollowUser } = useUser() || {}; @@ -45,6 +45,11 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { ); const [likesCount, setLikesCount] = useState(initialLikedBy.length); + const commentsCount = useMemo( + () => Number(item?.commentsCount || 0), + [item?.commentsCount] + ); + const [owner, setOwner] = useState( item?.userId && userCache?.current?.get(item.userId) ? userCache.current.get(item.userId) @@ -171,7 +176,7 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : []; return arr.map((w) => ({ - word: String(w?.word ?? ""), + word: String(w?.word ?? ''), startS: Number(w?.startS ?? 0), endS: Number(w?.endS ?? 0), })); @@ -197,47 +202,43 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { + position: 'relative', + backgroundColor: 'black', + }}> {!!videoUrl ? ( ) : ( )} {/* Right side actions */} + }}> - + }}> + { navigate(Routes.SingerProfile, { userId: item?.userId }); - }} - > + }}> {owner?.profilePictureURL ? ( { // rollback on failure setIsFollowing((v) => !v); } - }} - > + }}> { fontSize: 13, color: Palette.white, fontFamily: FONT_FAMILY.InterMedium, - }} - > - {isFollowing ? "Ne plus suivre" : "Suivre"} + }}> + {isFollowing ? 'Ne plus suivre' : 'Suivre'} @@ -333,8 +332,7 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { setLikesCount((c) => (isLiked ? c + 1 : Math.max(0, c - 1))); } }} - style={{ alignItems: "center" }} - > + style={{ alignItems: 'center' }}> { fontSize: 11, marginTop: 4, fontFamily: FONT_FAMILY.InterMedium, - textAlign: "center", - }} - > + textAlign: 'center', + }}> {likesCount} )} item?.id && openComments(item.id)} - style={{ alignItems: "center" }} - > + style={{ alignItems: 'center' }}> + {!!commentsCount && ( + + {commentsCount} + + )} { try { - const url = item?.playbackUrl || ""; - const title = item?.title || "Partager"; + const url = item?.playbackUrl || ''; + const title = item?.title || 'Partager'; const base = item?.title ? `Découvre « ${item.title} » sur MusicLand` : `Découvre ce playback sur MusicLand`; @@ -377,21 +385,20 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { }) ); } catch (e) {} - }} - > + }}> { fontSize: 12, color: Palette.white, fontFamily: FONT_FAMILY.InterRegular, - }} - > - {item?.title || "Description chanson"} + }}> + {item?.title || 'Description chanson'} )} @@ -430,7 +436,7 @@ const Playbacks = () => { const { getUserByUid } = useUser() || {}; const isFocused = useIsFocused(); const { data: playbacks = [], loadMore } = useDataFromRef({ - ref: projectsRef.where("playbackUrl", "!=", null), + ref: projectsRef.where('playbackUrl', '!=', null), simpleRef: false, listener: false, usePagination: true, @@ -469,7 +475,7 @@ const Playbacks = () => { }, [focusProjectId, playbacks, loadMore]); return ( - +