From 20b132f5abbddc6033d0f7fc5119d39985c329f5 Mon Sep 17 00:00:00 2001 From: leon-morival Date: Fri, 29 Aug 2025 12:08:46 +0200 Subject: [PATCH] music options --- src/assets/icons/heart.png | Bin 796 -> 6101 bytes src/assets/icons/heartOutline.png | Bin 336 -> 1495 bytes src/assets/icons/more.png | Bin 160 -> 330 bytes src/components/MoreMenu.js | 151 ++++++++++++++++++++ src/components/modal/PlaylistModal.js | 22 ++- src/screens/Library/AllMyLikedMusic.js | 70 ++------- src/screens/Library/PlaylistDetails.js | 23 ++- src/screens/Library/Research.js | 16 +++ src/screens/Library/components/MusicCard.js | 2 +- src/screens/Library/components/MyMusic.js | 19 ++- src/screens/Profile/Profile.js | 123 +++++----------- 11 files changed, 276 insertions(+), 150 deletions(-) create mode 100644 src/components/MoreMenu.js diff --git a/src/assets/icons/heart.png b/src/assets/icons/heart.png index 0c59bc47684be241b7684e58fb8f4d78f6fdf9ef..33bba43450a98747f65f85a9f9a530a6584588f3 100644 GIT binary patch literal 6101 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 Js#LIw_#dZTsSf}E delta 779 zcmV+m1N8jWFPsK8iBL{Q4GJ0x0000DNk~Le0000L0000J2nGNE0Dn$KivR!s32;bR za{vGf6951U69E94oEVWdAAbU|Nkld4_Ij#=mx&H5DMgU#hR_jRHM1rX>|JbC=0iwn8g~LIcHoXxZf#U z3Jqz5xRnq9KS<{P*nbC--Bwj8+Qkg2-W|!A$C7o7v^*CE8)2XO2sEkz1j50bNRE+g zAt}aB4cyl3kx+g_2l7^fjI&?bHqTlCx1@0n?qp`{B|HpHQ}Kx zkK;pYc~X_M&{>wpx4{=6o{V~L?SpFN{mC&TYGnZ6)p`i#wtRccd>KDDPDgt}dgkM! zJ*J5BsT)FD9PI$WS-1Ado=A236^LeD=BpwZJZ0DwI-{aAT_bry|<|m+D;hy3ENaf zluyvB&uKSb990heeuC7*`R?6^40}6PJMME4M}9y=&F4SPwTfr|keaygX|2H|+mi&j zE^-?C+|I_+?@O;v=1(OxvGV!WMuza(eX8V{?4<*-3QVB>7)Ef--%bgp))nGVdg zxWrc*40X6S1Zp%6RtEpenMrD5x7I0_qPZsD^1VCXu58c3{{`=TauuII#T5Vm002ov JPDHLkV1mg|XzTz0 diff --git a/src/assets/icons/heartOutline.png b/src/assets/icons/heartOutline.png index a749911838c86c230054b8b9088a58850a7ec616..5ebc5a96a169d0db0010d79fa5085cd861d2f096 100644 GIT binary patch delta 1484 zcmV;-1vC240@n*RiBL{Q4GJ0x0000DNk~Le0001M0001N2nGNE0ByQVv;Y7A32;bR za{vG=O8@{YO97=lmZ_08AAbdGNklcly7x%*vQuE z@~+F9mhlHI4XuE+E?;#yAdbB*_f~;(%D2*GYp)l>t1geW0oINFCmzmF07s+CZfd2V zYeaiY!wxkXZDJ*yVmxz87h;q;lYE99W-{93eU??`Ch!##=ih8;ZT*PS<<=Gz_ziR3 zpSsUzDPF!OD_DPX94 zeFb^FKTX31-+xz4mZD!E*WP2SNz?N)W!q$F-01G|(_eT1PYX`oPjR5jOkFV8foZ{t3W4$bc|G3KLKGE*_52+Q2+gM;bwolx^Liy=6zKQ$2a4o3isKKb{zk$m z?Bkpdk6U84G6+2fx z)>!U{#VrYAadj0v`V(a=W(KT6rYEo!;ttid6v;W+pm^7LxO#e_NX{|Vi&OtX!Wh<0 zecmu=d4G56;#mXOXMXDRGu@^9Lv!PK04e=e0Ccm6FMjYC?O8V6d~rT5=Fxtkxcd1{ zsX(sTIu!zbHkhJRctWA{T?|DuZ1iXAd?ld=`t$MAcNzMkUmPJ0l4yK{Ni4FiBylHI zZbh<7m*<$qNtLTyk=TrLFgt6CK0#^YUAd*20q zMP`1lI^v1XcXWlIfEA&GpnuG0{M{s4}GozZ>Xs?kB-- z>1L>EqK(H;vv1j#9QZfHs=~uOhH9|XCk)_Idc&3q1^$hio5dRHNKFPqc>iBT*FX&h zgFi949zz|0Kk1l#58IKlafX_0Bjn-xF-J>*ZyAu?&Qpq(e90N6!trt2fk< zfWZv2r}hZH`a))FxmblgdlWX?05HO@z9{dJd`ZCniiif&zdy_Ob_4TSQJYH^3%YrC z2amxfnKcD|lm1y6#o|G@AKTKIARP8~kVN7<5Pq{y6YBx+r{xCepQZr*e#|I-Fn?P_ zm%N0+o-72M68LYRkKs#s&RYl0%RXANSTGzG@15^|3wWf2y%fNoEgrqh^i8h;qe|FI z3BuW;4>RLR!d@=mPd;34lAGKT81S;ic+=!BmClJa$^&&<#Tnz6op8P<*&|611VIo4 mK@bE%5ClOG1VIoC{{w`cjeB?Xm{QEd3W!YHtk!Qk0J-g7|ovs%a>AW%JJJnXXea&G9R!ykVt)wuHS;FI?uPM{{YdXik%eEPJBZQBf>waY>J5J4NgkXp!>9MMO>P+!rW6Q-6^LRq6l$ N002ovPDHLkV1oKYf`tG8 diff --git a/src/assets/icons/more.png b/src/assets/icons/more.png index 7d21747074a0cf32ad9f708eebc12f86792d2e32..33b707feb23167834c4008c275cf9c683cd51a9f 100644 GIT binary patch delta 308 zcmZ3$c#6raGr-TCmrII^fq{Y7)59eQNGE_W2OE%lG^5-CNO2Z;L>4nJ=y-!L<5Jsc zD<_&M)Zh1XaSW+oe0%+N?jZ*O)(eWF0ZemM=S~p1H1RIu%L7Y?YYIjp(9XIk-+ zpP#(Gd;NYmmjh@TGN{m=xl`|RY}$#%u`|!_XuS71>vZlZpUQjxZmWr1s=ha;Y5J+T z(_)S@Rh?h0`+e&5+ir{ReSRi#CsagcQEA}%%GEP6=SLOSg}OAyeYR_A&)V6r@zI<7 zEz;WO_W9h~tM@?tR4nJa0`PlBg3pY z5);i7yi7e^978G?-=5mY%b>u+eDJ^{!O7ApDqIUncI`iQ)S8JQ%hN0OW!Br`Yn|PT hzgF~S%knbJQL}%b|7^JsPYuvm22WQ%mvv4FO#m01C_VrH diff --git a/src/components/MoreMenu.js b/src/components/MoreMenu.js new file mode 100644 index 0000000..aaf6c7a --- /dev/null +++ b/src/components/MoreMenu.js @@ -0,0 +1,151 @@ +import { BlurView } from "expo-blur"; +import React from "react"; +import { Platform, Pressable, Text, View } from "react-native"; +import { SheetManager } from "react-native-actions-sheet"; +import Animated, { Easing, FadeIn, FadeOut } from "react-native-reanimated"; +import { arrayRemove, playlistsRef } from "../config/firebase"; +import useMinuit from "react-native-minuit/src/hooks/useMinuit"; +import { Palette } from "../styles"; +import { FONT_FAMILY } from "../styles/Fonts"; + +const MoreMenu = ({ + visible = false, + top = 0, + onClose = () => {}, + inPlaylist = false, + playlistId = null, + projectId = null, + extraItems = [], +}) => { + if (!visible) return null; + const { setTooltip } = useMinuit(); + + const removeFromPlaylist = async () => { + try { + if (inPlaylist && playlistId && projectId) { + await playlistsRef + .doc(playlistId) + .update({ musics: arrayRemove(projectId), updatedAt: new Date() }); + setTooltip({ type: "success", text: "Supprimé de la playlist" }); + } + } catch (e) { + console.log("Remove from playlist error", e?.message); + setTooltip({ type: "error", text: e?.message || "Suppression impossible" }); + } finally { + onClose?.(); + } + }; + + const addToPlaylist = () => { + if (projectId) { + SheetManager.show("Playlist", { payload: { projectId } }); + } else { + SheetManager.show("Playlist"); + } + onClose?.(); + }; + + return ( + + + {inPlaylist && ( + + + + Supprimer de la playlist + + + + )} + + + + + Ajouter à une playlist + + + + + {Array.isArray(extraItems) && + extraItems.map((item, idx) => ( + { + try { + item?.onPress?.(); + } finally { + onClose?.(); + } + }} + > + + + {item?.label || "Action"} + + + + ))} + + + ); +}; + +export default MoreMenu; diff --git a/src/components/modal/PlaylistModal.js b/src/components/modal/PlaylistModal.js index 79902d9..ca970a8 100644 --- a/src/components/modal/PlaylistModal.js +++ b/src/components/modal/PlaylistModal.js @@ -12,6 +12,7 @@ import { SheetManager } from "react-native-actions-sheet"; import SwiperFlatList from "react-native-swiper-flatlist"; import { icons } from "../../assets"; import { arrayUnion, playlistsRef } from "../../config/firebase"; +import useMinuit from "react-native-minuit/src/hooks/useMinuit"; import { useUserData } from "../../providers/UserDataProvider"; import { createPlaylist } from "../../screens/Library/Playlists/playlist"; import { Palette } from "../../styles"; @@ -30,6 +31,7 @@ const PlaylistModal = (props) => { const [isCreating, setIsCreating] = useState(false); const { currentUID, userPlaylists = [] } = useUserData(); const startAtCreate = props?.payload?.startAtCreate || false; + const { setTooltip } = useMinuit(); return ( @@ -104,9 +106,19 @@ const PlaylistModal = (props) => { musics: arrayUnion(projectId), updatedAt: new Date(), }); + const addedPlaylist = (Array.isArray(userPlaylists) + ? userPlaylists + : [] + ).find((p) => p?.id === selectedId); + const name = addedPlaylist?.name || "la playlist"; + setTooltip({ + type: "success", + text: `Ajouté à “${name}”`, + }); } } catch (e) { console.log("Add to playlist error", e?.message); + setTooltip({ type: "error", text: e?.message || "Ajout impossible" }); } finally { SheetManager.hide("Playlist"); } @@ -175,20 +187,28 @@ const PlaylistModal = (props) => { if (!playlist?.trim()?.length || !currentUID) return; try { setIsCreating(true); + const name = playlist.trim(); await createPlaylist({ createdBy: currentUID, - name: playlist.trim(), + name, musics: props?.payload?.projectId ? [props.payload.projectId] : [], createdAt: new Date(), updatedAt: new Date(), }); + setTooltip({ + type: "success", + text: props?.payload?.projectId + ? `Playlist “${name}” créée et musique ajoutée` + : `Playlist “${name}” créée`, + }); setPlaylist(""); SheetManager.hide("Playlist"); scrollRef.current.scrollToIndex({ index: 0, animated: true }); } catch (e) { console.log(e); + setTooltip({ type: "error", text: e?.message || "Création impossible" }); } finally { setIsCreating(false); } diff --git a/src/screens/Library/AllMyLikedMusic.js b/src/screens/Library/AllMyLikedMusic.js index fce7263..afe81f3 100644 --- a/src/screens/Library/AllMyLikedMusic.js +++ b/src/screens/Library/AllMyLikedMusic.js @@ -1,8 +1,6 @@ import { BlurView } from "expo-blur"; import React, { useState } from "react"; -import { Platform, Pressable, Text, View } from "react-native"; -import { SheetManager } from "react-native-actions-sheet"; -import Animated, { Easing, FadeIn, FadeOut } from "react-native-reanimated"; +import { View } from "react-native"; import { background } from "../../assets"; import Page from "../../layouts/Page"; import { Routes } from "../../navigation"; @@ -11,10 +9,12 @@ import { useUser } from "../../providers/UserDataProvider"; import { gutters, Palette } from "../../styles"; import { FONT_FAMILY } from "../../styles/Fonts"; import MusicCard from "./components/MusicCard"; +import MoreMenu from "../../components/MoreMenu"; const AllMyLikedMusic = () => { const [top, setTop] = useState(0); const [showMenu, setShowMenu] = useState(false); + const [selectedProjectId, setSelectedProjectId] = useState(null); const { userLikedProjects: projects } = useUser(); return ( @@ -39,65 +39,19 @@ const AllMyLikedMusic = () => { navigate(Routes.MusicDetails, { projectId: item.id }) } onPressMore={(posTop) => { + setSelectedProjectId(item.id); setTop(posTop); - if (showMenu) { - if (posTop === top) { - setShowMenu(false); - } else { - setShowMenu(false); - setTimeout(() => { - setShowMenu(true); - }, 300); - } - } else { - setShowMenu(true); - } + setShowMenu((prev) => !prev || posTop !== top); }} /> ))} - {showMenu && ( - - { - setShowMenu(false); - SheetManager.show("Delete"); - }} - > - - - Supprimer de la playlist - - - - - )} + setShowMenu(false)} + inPlaylist={false} + projectId={selectedProjectId} + /> diff --git a/src/screens/Library/PlaylistDetails.js b/src/screens/Library/PlaylistDetails.js index 7ac2f0f..b8110c3 100644 --- a/src/screens/Library/PlaylistDetails.js +++ b/src/screens/Library/PlaylistDetails.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import { View } from "react-native"; import Page from "../../layouts/Page"; import { background } from "../../assets"; @@ -8,6 +8,7 @@ import { useDataFromRef } from "react-native-minuit/src/hooks"; import useDataFromArrayId from "react-native-minuit/src/hooks/useDataFromArrayId"; import { playlistsRef, projectsRef } from "../../config/firebase"; import MusicCard from "./components/MusicCard"; +import MoreMenu from "../../components/MoreMenu"; import { navigate } from "../../navigation/NavigationService"; import { Routes } from "../../navigation"; @@ -32,6 +33,10 @@ const PlaylistDetails = () => { refreshArray: [playlistId, playlist?.musics?.length || 0], }); + const [menuTop, setMenuTop] = useState(0); + const [showMenu, setShowMenu] = useState(false); + const [selectedProjectId, setSelectedProjectId] = useState(null); + return ( { projectId={p?.id} likedBy={p?.likedBy || []} onPress={() => navigate(Routes.MusicDetails, { projectId: p.id })} - onPressMore={() => {}} + onPressMore={(posTop) => { + setSelectedProjectId(p.id); + setMenuTop(posTop); + setShowMenu((prev) => !prev || posTop !== menuTop); + }} /> ))} + + setShowMenu(false)} + inPlaylist + playlistId={playlistId} + projectId={selectedProjectId} + /> ); }; export default PlaylistDetails; - diff --git a/src/screens/Library/Research.js b/src/screens/Library/Research.js index 0bb6730..2f4eca3 100644 --- a/src/screens/Library/Research.js +++ b/src/screens/Library/Research.js @@ -17,12 +17,16 @@ import BorderGradient from "../../components/BorderGradient/BorderGradient"; import { BlurView } from "expo-blur"; import ResearchHeader from "./components/ResearchHeader"; import MusicCard from "./components/MusicCard"; +import MoreMenu from "../../components/MoreMenu"; import { size } from "../../styles/Style"; import { navigate } from "../../navigation/NavigationService"; import { Routes } from "../../navigation"; const Research = () => { const [selected, setSelected] = useState(null); + const [menuTop, setMenuTop] = useState(0); + const [showMenu, setShowMenu] = useState(false); + const [selectedProjectId, setSelectedProjectId] = useState(null); const onPressMenu = (item) => { if (selected === item) { @@ -61,6 +65,11 @@ const Research = () => { navigate(Routes.MusicDetails)} + onPressMore={(posTop) => { + setSelectedProjectId(null); + setMenuTop(posTop); + setShowMenu((prev) => !prev || posTop !== menuTop); + }} /> ))} @@ -135,6 +144,13 @@ const Research = () => { )} + setShowMenu(false)} + inPlaylist={false} + projectId={selectedProjectId} + /> diff --git a/src/screens/Library/components/MusicCard.js b/src/screens/Library/components/MusicCard.js index be6f85b..b9b08ac 100644 --- a/src/screens/Library/components/MusicCard.js +++ b/src/screens/Library/components/MusicCard.js @@ -105,7 +105,7 @@ const MusicCard = ({ /> - + diff --git a/src/screens/Library/components/MyMusic.js b/src/screens/Library/components/MyMusic.js index 9ab04d8..5b69d2e 100644 --- a/src/screens/Library/components/MyMusic.js +++ b/src/screens/Library/components/MyMusic.js @@ -1,13 +1,17 @@ -import React from "react"; +import React, { useState } 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 MoreMenu from "../../../components/MoreMenu"; const MyMusic = () => { const { userProjects = [] } = useUser(); + const [menuTop, setMenuTop] = useState(0); + const [showMenu, setShowMenu] = useState(false); + const [selectedProjectId, setSelectedProjectId] = useState(null); const projects = Array.isArray(userProjects) ? userProjects.slice(0, 3) : []; return ( { projectId={p?.id} likedBy={p?.likedBy || []} onPress={() => navigate(Routes.MusicDetails, { projectId: p.id })} - onPressMore={() => console.log("More options for", p.id)} + onPressMore={(posTop) => { + setSelectedProjectId(p.id); + setMenuTop(posTop); + setShowMenu((prev) => !prev || posTop !== menuTop); + }} /> ))} + setShowMenu(false)} + inPlaylist={false} + projectId={selectedProjectId} + /> ); diff --git a/src/screens/Profile/Profile.js b/src/screens/Profile/Profile.js index d83cdb3..e7dff84 100644 --- a/src/screens/Profile/Profile.js +++ b/src/screens/Profile/Profile.js @@ -17,6 +17,7 @@ import { Palette } from "../../styles"; import { FONT_FAMILY } from "../../styles/Fonts"; import BorderGradient from "../../components/BorderGradient/BorderGradient"; import MusicCard from "../Library/components/MusicCard"; +import MoreMenu from "../../components/MoreMenu"; import { useUser } from "../../providers/UserDataProvider"; import { SheetManager } from "react-native-actions-sheet"; import { navigate } from "../../navigation/NavigationService"; @@ -201,96 +202,48 @@ const Profile = () => { } onPressMore={(posTop) => { setSelectedProjectId(item.id); - if (showMenu) { - if (posTop === menuTop) { - setShowMenu(false); - } else { - setShowMenu(false); - setTimeout(() => { - setMenuTop(posTop); - setShowMenu(true); - }, 200); - } - } else { - setMenuTop(posTop); - setShowMenu(true); - } + setMenuTop(posTop); + setShowMenu((prev) => !prev || posTop !== menuTop); }} /> )} /> - {showMenu && ( - - - setShowMenu(false)}> - - Annuler - - - { - setShowMenu(false); - alert( - "Confirmer la suppression", - "Cette action supprimera définitivement ce projet.", - [ - { text: "Annuler", style: "cancel", onPress: () => {} }, - { - text: "Supprimer", - onPress: async () => { - try { - if (!selectedProjectId) return; - await projectsRef.doc(selectedProjectId).delete(); - setTooltip({ type: "success", text: "Projet supprimé" }); - } catch (e) { - setTooltip({ - type: "error", - text: e?.message || "Suppression impossible", - }); - } - }, + setShowMenu(false)} + inPlaylist={false} + projectId={selectedProjectId} + extraItems={[ + { + label: "Supprimer", + onPress: () => + alert( + "Confirmer la suppression", + "Cette action supprimera définitivement ce projet.", + [ + { text: "Annuler", style: "cancel", onPress: () => {} }, + { + text: "Supprimer", + onPress: async () => { + try { + if (!selectedProjectId) return; + await projectsRef.doc(selectedProjectId).delete(); + setTooltip({ type: "success", text: "Projet supprimé" }); + } catch (e) { + setTooltip({ + type: "error", + text: e?.message || "Suppression impossible", + }); + } }, - ], - { cancelable: true }, - ); - }} - > - - Supprimer - - - - - )} + }, + ], + { cancelable: true }, + ), + }, + ]} + /> )}