From 64fd988d2fd93be87d99bb2bf492b79f97742668 Mon Sep 17 00:00:00 2001 From: leon-morival Date: Wed, 3 Sep 2025 14:55:01 +0200 Subject: [PATCH] comments --- App.js | 2 + app.json | 23 +-- src/assets/icons/chatBubble.png | Bin 0 -> 1714 bytes src/assets/index.js | 108 ++++++------- src/components/AppActionSheet.js | 8 +- .../CommentsBottomSheet.js} | 153 ++++++++++++++---- src/providers/SharedProviders.js | 2 + src/screens/Playbacks.js | 12 +- src/utils/Sheet.js | 2 - 9 files changed, 187 insertions(+), 123 deletions(-) create mode 100644 src/assets/icons/chatBubble.png rename src/components/{modal/CommentsModal.js => bottomsheets/CommentsBottomSheet.js} (60%) diff --git a/App.js b/App.js index 66c9196..207fcce 100644 --- a/App.js +++ b/App.js @@ -36,6 +36,7 @@ import { import "./src/utils/Sheet"; import {LogBox} from "react-native"; +import CommentsBottomSheet from "./src/components/bottomsheets/CommentsBottomSheet"; console.disableYellowBox = true; console.reportErrorsAsExceptions = false; @@ -142,6 +143,7 @@ const App = () => { > + diff --git a/app.json b/app.json index 677a39b..3db0ba1 100644 --- a/app.json +++ b/app.json @@ -16,14 +16,7 @@ "fallbackToCacheTimeout": 0 }, "packagerOpts": { - "sourceExts": [ - "js", - "json", - "ts", - "tsx", - "jsx", - "vue" - ] + "sourceExts": ["js", "json", "ts", "tsx", "jsx", "vue"] }, "splash": { "image": "./assets/splash.png", @@ -35,9 +28,7 @@ "supportsTablet": true, "requireFullScreen": true, "userInterfaceStyle": "dark", - "associatedDomains": [ - "applinks:minuit.starter" - ], + "associatedDomains": ["applinks:minuit.starter"], "bundleIdentifier": "com.minuit.starter", "infoPlist": { "UISupportedInterfaceOrientations": [ @@ -48,10 +39,7 @@ "UIInterfaceOrientationLandscapeLeft", "UIInterfaceOrientationLandscapeRight" ], - "LSApplicationQueriesSchemes": [ - "itms-apps", - "minuit" - ] + "LSApplicationQueriesSchemes": ["itms-apps", "minuit"] }, "config": { "usesNonExemptEncryption": false @@ -62,15 +50,14 @@ "appleTeamId": "W2QZ9CTMYJ" }, "android": { + "softwareKeyboardLayoutMode": "resize", "googleServicesFile": "./config/google-services.json", "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#0A0D12" }, "package": "com.minuit.starter", - "permissions": [ - "android.permission.RECORD_AUDIO" - ] + "permissions": ["android.permission.RECORD_AUDIO"] }, "web": { "bundler": "metro" diff --git a/src/assets/icons/chatBubble.png b/src/assets/icons/chatBubble.png new file mode 100644 index 0000000000000000000000000000000000000000..e50f09bb76fe4187b7bcfcb3b53917f653e5a87e GIT binary patch literal 1714 zcmV;j22J^iP)@~0drDELIAGL9O(c600d`2O+f$vv5yPuO^Cp+u*>%{>OX&UwusQ0edl(wxYKQ4aCQN;Krqi@d7;9R40_}nzjm@ zRy}oWjB*YkMap`K?iPTLGqfdq19Z`Shzr%}hS6rf$AMb)+)v%T{mi zZ5^%=_sjVU&1+U2sRaLKXd`s!oOufkaWhzEUHG1$Js>$yjvyWl=2_^GKzo3dS0Dm6 zd$CJl9b@Zy7iot)W<_j4&Qw?q#G_*lP?jBQBJOn86WWdl;(=GaXq!MDk8r^Z?G)dU zrI3Fae+D<|moT(*;BLxF6f`%G)&7Q*7vN@dLXM37QCORVwwunEMYKzw zl5HWPWz$5Ake%nQrk{oY*_Rb<=l((INUHlEDP8$2}4&sIi*Ep7d$YR1GTvc@-&r39Wt^ z$0SBE~N?)f)i9g2*oC_Prk# z>Ip0?)v^{KuK=oO!i$QFt5wV5K;Bl}(3C)4T&+9c2tZ!UKmBs!h?Y&?TUH8|-iRim zWjZeV4aghO%)6LB(rd0sc>!*lCoHO6M}=8-52Y0l>C}tunb>>ZiLC?K6xNG%XvhJ` zt~UyUygeba?1VYO4Pj{G zpxfIA^O_7tIGlf?jRR)_>s1Mh!OjNEa8Y2JR&kr;=Mo^#BPKr$3};@9Pua~u`tseP z{k6t5avjb!w3*YEng(OkKX&%q67#ayUAzk|aPAOxF8MW$!dII-sU1)Om zZ@WZQ$ilQirq9|d006Ywe`&EZF5&!@I07*qo IM6N<$f*;8n { const insets = useSafeAreaInsets(); diff --git a/src/components/modal/CommentsModal.js b/src/components/bottomsheets/CommentsBottomSheet.js similarity index 60% rename from src/components/modal/CommentsModal.js rename to src/components/bottomsheets/CommentsBottomSheet.js index d344df3..0abd697 100644 --- a/src/components/modal/CommentsModal.js +++ b/src/components/bottomsheets/CommentsBottomSheet.js @@ -1,5 +1,18 @@ +// CommentsBottomSheet.jsx +import { + BottomSheetBackdrop, + BottomSheetModal, + BottomSheetScrollView, +} from "@gorhom/bottom-sheet"; import { BlurView } from "expo-blur"; -import React, { useMemo, useState } from "react"; +import { Image as ExpoImage } from "expo-image"; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; import { Image, Platform, @@ -8,6 +21,7 @@ import { 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"; @@ -15,7 +29,11 @@ import { useUser } from "../../providers/UserDataProvider"; import { Palette } from "../../styles"; import { FONT_FAMILY } from "../../styles/Fonts"; import { size } from "../../styles/Style"; -import AppActionSheet from "../AppActionSheet"; + +let externalOpen; +export const openComments = (projectId) => { + if (typeof externalOpen === "function") externalOpen(projectId); +}; const formatRelativeTime = (date) => { try { @@ -35,10 +53,26 @@ const formatRelativeTime = (date) => { } }; -const CommentsModal = ({ sheetId, payload }) => { - const projectId = payload?.projectId || null; +const CommentsBottomSheet = () => { + const modalRef = useRef(null); + const insets = useSafeAreaInsets(); const { currentUID, currentUserData } = useUser(); + + const [projectId, setProjectId] = useState(null); const [text, setText] = useState(""); + const [typing, setTyping] = useState(false); + + useEffect(() => { + externalOpen = (pid) => { + setProjectId(pid || null); + requestAnimationFrame(() => modalRef.current?.present()); + }; + return () => { + externalOpen = undefined; + }; + }, []); + + const snapPoints = useMemo(() => ["50%", "90%"], []); const commentsRef = useMemo(() => { try { @@ -48,7 +82,7 @@ const CommentsModal = ({ sheetId, payload }) => { .collection("comments") .orderBy("createdAt", "desc") : null; - } catch (e) { + } catch { return null; } }, [projectId]); @@ -66,38 +100,84 @@ const CommentsModal = ({ sheetId, payload }) => { if (!value || !projectId || !currentUID) return; try { setText(""); - const docRef = projectsRef.doc(projectId).collection("comments"); - await docRef.add({ - userId: currentUID, - userName: currentUserData?.userName || "", - profilePicture: currentUserData?.profilePictureURL || "", - text: value, - createdAt: serverTimestamp(), - }); - } catch (e) { - // Ignore + await projectsRef + .doc(projectId) + .collection("comments") + .add({ + userId: currentUID, + userName: currentUserData?.userName || "", + profilePicture: currentUserData?.profilePictureURL || "", + text: value, + createdAt: serverTimestamp(), + }); + } catch { + // ignore } }; + const renderBackdrop = useCallback( + (props) => ( + + ), + [typing] + ); + return ( - - - + + + + Commentaires + + + + - Commentaires - - {Array.isArray(comments) && comments.length > 0 ? ( comments.map((c) => ( - + {c?.profilePicture ? ( - { Aucun commentaire pour le moment )} - - + {/* INPUT en bas du contenu */} + { gap: 10, paddingHorizontal: 16, backgroundColor: Palette.glass, - borderRadius: 16, overflow: "hidden", height: 54, + borderRadius: 16, }} experimentalBlurMethod={ Platform.OS !== "ios" ? "dimezisBlurView" : "none" @@ -192,6 +272,8 @@ const CommentsModal = ({ sheetId, payload }) => { placeholderTextColor="#FFFFFFAA" value={text} onChangeText={setText} + onFocus={() => setTyping(true)} + onBlur={() => setTyping(false)} style={{ flex: 1, color: Palette.white, @@ -207,10 +289,11 @@ const CommentsModal = ({ sheetId, payload }) => { /> - - - + + + + ); }; -export default CommentsModal; +export default CommentsBottomSheet; diff --git a/src/providers/SharedProviders.js b/src/providers/SharedProviders.js index 1723d96..35018ed 100644 --- a/src/providers/SharedProviders.js +++ b/src/providers/SharedProviders.js @@ -1,6 +1,7 @@ import React from "react"; import { ActionSheetProvider } from "@expo/react-native-action-sheet"; import { SafeAreaProvider } from "react-native-safe-area-context"; +import { BottomSheetModalProvider } from "@gorhom/bottom-sheet"; import UserDataProvider from "./UserDataProvider"; import WebViewProvider from "./WebViewProvider"; @@ -18,6 +19,7 @@ const SharedProviders = ({ children }) => { [UserDataProvider, {}], [StripeEmbeddedProvider, {}], [UniversalLinkProvider, {}], + [BottomSheetModalProvider, {}], [SheetProvider, {}], ]; diff --git a/src/screens/Playbacks.js b/src/screens/Playbacks.js index 515cdd9..73578f5 100644 --- a/src/screens/Playbacks.js +++ b/src/screens/Playbacks.js @@ -10,10 +10,10 @@ import React, { useState, } from "react"; import { Image, Platform, Pressable, Text, View } from "react-native"; -import { SheetManager } from "react-native-actions-sheet"; import Carousel from "react-native-reanimated-carousel"; import { responsiveHeight } from "react-native-responsive-dimensions"; import { icons, img } from "../assets"; +import { openComments } from "../components/bottomsheets/CommentsBottomSheet"; import KaraokeLyrics from "../components/KaraokeLyrics"; import { arrayRemove, @@ -355,16 +355,10 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { )} { - if (item?.id) { - SheetManager.show("Comments", { - payload: { projectId: item.id }, - }); - } - }} + onPress={() => item?.id && openComments(item.id)} style={{ alignItems: "center" }} > - + diff --git a/src/utils/Sheet.js b/src/utils/Sheet.js index 1a3e645..1ac8bf8 100644 --- a/src/utils/Sheet.js +++ b/src/utils/Sheet.js @@ -5,7 +5,6 @@ import DeleteAccountModal from "../components/modal/DeleteAccountModal"; import DeletePlaybackModal from "../components/modal/DeletePlaybackModal"; import DeleteAudioModal from "../components/modal/DeleteAudioModal"; import PlaylistModal from "../components/modal/PlaylistModal"; -import CommentsModal from "../components/modal/CommentsModal"; registerSheet("Delete", DeleteModal); registerSheet("ProfileSettings", ProfileSettingsModal); @@ -13,6 +12,5 @@ registerSheet("DeleteAccount", DeleteAccountModal); registerSheet("DeletePlayback", DeletePlaybackModal); registerSheet("DeleteAudio", DeleteAudioModal); registerSheet("Playlist", PlaylistModal); -registerSheet("Comments", CommentsModal); export {};