From 8356b04eb2fccf8709a4fb8fb193dc539ae2728d Mon Sep 17 00:00:00 2001 From: leon-morival Date: Fri, 24 Oct 2025 14:15:59 +0200 Subject: [PATCH] new tickets --- src/components/FullscreenIntroVideo.native.js | 60 +++++++++++++++---- src/components/FullscreenIntroVideo.web.js | 17 ++++-- src/components/SearchBar.js | 9 +-- src/components/modal/ShareQrModal.js | 10 ++++ src/hooks/useSearch.js | 2 +- src/screens/Library/AllMyPlaylist.js | 6 +- src/screens/Library/AllMyPlaylist.web.js | 9 ++- src/screens/Library/components/MyPlaylist.js | 6 +- .../Library/components/SearchResultsList.js | 24 ++++++-- src/screens/Register.js | 2 +- 10 files changed, 113 insertions(+), 32 deletions(-) diff --git a/src/components/FullscreenIntroVideo.native.js b/src/components/FullscreenIntroVideo.native.js index 852b583..fb25cd7 100644 --- a/src/components/FullscreenIntroVideo.native.js +++ b/src/components/FullscreenIntroVideo.native.js @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React, { useCallback, useEffect, useRef } from "react"; import { View, Pressable, Text } from "react-native"; import { VideoView, useVideoPlayer } from "expo-video"; import { videos } from "../assets"; @@ -10,37 +10,73 @@ import { Portal } from "@gorhom/portal"; // - visible?: boolean, when false returns null // - onClose: () => void, called when user skips or when video ends const FullscreenIntroVideo = ({ url, visible = true, onClose }) => { - if (!visible) return null; const source = url ? typeof url === "string" ? { uri: url } : url : videos.test; + const hasClosedRef = useRef(false); + + const handleClose = useCallback(() => { + if (hasClosedRef.current) return; + hasClosedRef.current = true; + try { + onClose?.(); + } catch (e) {} + }, [onClose]); + const player = useVideoPlayer(source, (p) => { p.loop = false; p.timeUpdateEventInterval = 0.25; }); useEffect(() => { + if (visible) { + hasClosedRef.current = false; + } else { + hasClosedRef.current = true; + try { + player?.pause?.(); + } catch (e) {} + } + }, [player, visible]); + + useEffect(() => { + if (!visible) { + return; + } try { player?.play?.(); } catch (e) {} - }, [player]); + }, [player, visible]); useEffect(() => { - if (!player) return; - const sub = player.addListener?.("playToEnd", () => { - try { - onClose?.(); - } catch (e) {} - }); + if (!player || !visible) return; + const playToEndSub = player.addListener?.("playToEnd", handleClose); + const timeUpdateSub = player.addListener?.( + "timeUpdate", + ({ currentTime } = {}) => { + if (!player?.duration || hasClosedRef.current) { + return; + } + const remaining = player.duration - currentTime; + if (Number.isFinite(remaining) && remaining <= 0.1) { + handleClose(); + } + } + ); return () => { try { - sub?.remove?.(); + playToEndSub?.remove?.(); + timeUpdateSub?.remove?.(); } catch (e) {} }; - }, [player, onClose]); + }, [handleClose, player, visible]); + + if (!visible) { + return null; + } return ( @@ -65,7 +101,7 @@ const FullscreenIntroVideo = ({ url, visible = true, onClose }) => { style={{ position: "absolute", top: 0, bottom: 0, left: 0, right: 0 }} /> onClose?.()} + onPress={handleClose} style={{ position: "absolute", top: 50, diff --git a/src/components/FullscreenIntroVideo.web.js b/src/components/FullscreenIntroVideo.web.js index 817ccd7..4e145f0 100644 --- a/src/components/FullscreenIntroVideo.web.js +++ b/src/components/FullscreenIntroVideo.web.js @@ -1,6 +1,6 @@ import { Portal } from "@gorhom/portal"; import { Asset } from "expo-asset"; -import React, { useEffect, useRef, useState } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; import { Pressable, Text, View } from "react-native"; const overlayStyle = { @@ -56,6 +56,13 @@ const FullscreenIntroVideo = ({ url, visible = true, onClose }) => { const videoRef = useRef(null); const [uri, setUri] = useState(null); const [muted, setMuted] = useState(false); + const hasClosedRef = useRef(false); + + const handleClose = useCallback(() => { + if (hasClosedRef.current) return; + hasClosedRef.current = true; + onClose?.(); + }, [onClose]); useEffect(() => { let isMounted = true; @@ -97,13 +104,15 @@ const FullscreenIntroVideo = ({ url, visible = true, onClose }) => { return undefined; } + hasClosedRef.current = false; + const video = videoRef.current; if (!video || !uri) { return undefined; } - const handleEnded = () => onClose?.(); + const handleEnded = handleClose; video.addEventListener("ended", handleEnded); video.currentTime = 0; @@ -125,7 +134,7 @@ const FullscreenIntroVideo = ({ url, visible = true, onClose }) => { video.pause(); video.removeEventListener("ended", handleEnded); }; - }, [muted, onClose, uri, visible]); + }, [handleClose, muted, uri, visible]); useEffect(() => { const video = videoRef.current; @@ -161,7 +170,7 @@ const FullscreenIntroVideo = ({ url, visible = true, onClose }) => { controls={false} /> ) : null} - onClose?.()} style={closeButtonStyle}> + Passer la vidéo diff --git a/src/components/SearchBar.js b/src/components/SearchBar.js index dffb099..13a311a 100644 --- a/src/components/SearchBar.js +++ b/src/components/SearchBar.js @@ -1,10 +1,10 @@ -import { View, TextInput, Image } from "react-native"; -import React from "react"; import { BlurView } from "expo-blur"; +import React from "react"; +import { Image, TextInput, View } from "react-native"; import { icons } from "../assets"; -import Style, { size } from "../styles/Style"; import { Palette } from "../styles"; import { FONT_FAMILY } from "../styles/Fonts"; +import Style from "../styles/Style"; const SearchBar = ({ placeholder = "Que souhaites-tu écouter?", @@ -13,12 +13,13 @@ const SearchBar = ({ return ( diff --git a/src/components/modal/ShareQrModal.js b/src/components/modal/ShareQrModal.js index 461842d..9ac54a0 100644 --- a/src/components/modal/ShareQrModal.js +++ b/src/components/modal/ShareQrModal.js @@ -75,10 +75,20 @@ const styles = StyleSheet.create({ overlay: { ...StyleSheet.absoluteFillObject, zIndex: 200, + ...Platform.select({ + web: { + position: "fixed", + }, + }), }, backdrop: { ...StyleSheet.absoluteFillObject, backgroundColor: "rgba(0, 0, 0, 0.65)", + ...Platform.select({ + web: { + position: "fixed", + }, + }), }, centerWrapper: { flex: 1, diff --git a/src/hooks/useSearch.js b/src/hooks/useSearch.js index 45124a4..beb7b7c 100644 --- a/src/hooks/useSearch.js +++ b/src/hooks/useSearch.js @@ -34,7 +34,7 @@ const useSearch = () => { algoliaObject: AlgoliaProjectConfig, batch: batchSizes.projects, searchParams: { - filters: `hasPlayback:false AND hasSong:true`, + filters: `hasSong:true`, }, }); diff --git a/src/screens/Library/AllMyPlaylist.js b/src/screens/Library/AllMyPlaylist.js index 969f7b9..63c5fd5 100644 --- a/src/screens/Library/AllMyPlaylist.js +++ b/src/screens/Library/AllMyPlaylist.js @@ -48,8 +48,9 @@ const AllMyPlaylist = () => { intensity={Platform.OS !== "ios" ? 10 : 20} style={{ ...Style.containerSpaceBetween, - height: 59, + minHeight: 59, paddingHorizontal: 10, + paddingVertical: 12, }} // experimentalBlurMethod={ // Platform.OS !== "ios" ? "dimezisBlurView" : "none" @@ -57,9 +58,12 @@ const AllMyPlaylist = () => { > {item?.name || "Sans nom"} diff --git a/src/screens/Library/AllMyPlaylist.web.js b/src/screens/Library/AllMyPlaylist.web.js index 9f11aee..63cb030 100644 --- a/src/screens/Library/AllMyPlaylist.web.js +++ b/src/screens/Library/AllMyPlaylist.web.js @@ -120,17 +120,21 @@ const AllMyPlaylist = ({ route }) => { intensity={30} style={{ ...Style.containerSpaceBetween, - height: 59, + minHeight: 59, paddingHorizontal: 16, + paddingVertical: 12, }} > {item?.name || "Sans nom"} @@ -172,7 +176,8 @@ const AllMyPlaylist = ({ route }) => { style={{ ...Style.containerSpaceBetween, paddingHorizontal: 16, - height: 59, + minHeight: 59, + paddingVertical: 12, }} > { intensity={Platform.OS !== "ios" ? 10 : 20} style={{ ...Style.containerSpaceBetween, - height: 59, + minHeight: 59, paddingHorizontal: 10, + paddingVertical: 12, }} // experimentalBlurMethod={ // Platform.OS !== "ios" ? "dimezisBlurView" : "none" @@ -54,9 +55,12 @@ const MyPlaylist = () => { > {item?.name || "Sans nom"} diff --git a/src/screens/Library/components/SearchResultsList.js b/src/screens/Library/components/SearchResultsList.js index 26eec63..bcf22b4 100644 --- a/src/screens/Library/components/SearchResultsList.js +++ b/src/screens/Library/components/SearchResultsList.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useMemo, useState } from "react"; import { Pressable, ScrollView, Text, View } from "react-native"; import MoreMenu from "../../../components/MoreMenu"; import ProfilePicture from "../../../components/ProfilePicture"; @@ -70,8 +70,20 @@ const SearchResultsList = ({ onResultSelected?.(); }; + const musicItems = useMemo(() => { + if (!Array.isArray(musics)) { + return []; + } + + if (selected === "Musiques") { + return musics; + } + + return musics.filter((project) => project?.hasPlayback !== true); + }, [musics, selected]); + const shouldShowMusics = - (!selected && (musics.length > 0 || musicsLoading)) || + (!selected && (musicItems.length > 0 || musicsLoading)) || selected === "Musiques"; const shouldShowPlaybacks = @@ -89,10 +101,10 @@ const SearchResultsList = ({ > {shouldShowMusics && ( - {musics.length > 0 && ( + {musicItems.length > 0 && ( <> - {Array.isArray(musics) && - musics.slice(0, 6).map((project) => ( + {Array.isArray(musicItems) && + musicItems.slice(0, 6).map((project) => ( )} - {musics.length === 0 && !musicsLoading && ( + {musicItems.length === 0 && !musicsLoading && ( )} diff --git a/src/screens/Register.js b/src/screens/Register.js index 2c66b0c..f1c80c8 100644 --- a/src/screens/Register.js +++ b/src/screens/Register.js @@ -308,7 +308,7 @@ const styles = StyleSheet.create({ width: "100%", maxWidth: 420, maxHeight: "80%", - backgroundColor: Palette.ultraLightWhite, + backgroundColor: Palette.ultraLightBlack, borderRadius: 20, padding: 16, gap: 12,