diff --git a/eas.json b/eas.json
index c035dfa..f075478 100644
--- a/eas.json
+++ b/eas.json
@@ -5,25 +5,24 @@
"promptToConfigurePushNotifications": true
},
"build": {
+ "preview": {
+ "distribution": "internal",
+ "android": {
+ "buildType": "apk"
+ },
+ "ios": {
+ "simulator": true
+ }
+ },
"production": {
+ "android": {
+ "buildType": "app-bundle",
+ "autoIncrement": "versionCode",
+ "resourceClass": "large"
+ },
"ios": {
"buildConfiguration": "Release",
"autoIncrement": "buildNumber"
- },
- "android": {
- "buildType": "apk",
- "autoIncrement": "versionCode"
- }
- },
- "preview": {
- "distribution": "internal",
- "ios": {
- "simulator": true
- },
- "android": {
- "buildType": "apk",
- "gradleCommand": ":app:assembleDebug",
- "applicationArchivePath": "android/app/build/outputs/apk/debug/app-debug.apk"
}
}
},
diff --git a/src/components/AnimatedPaginationDot/AnimatedPaginationDot.js b/src/components/AnimatedPaginationDot/AnimatedPaginationDot.js
index cca6259..fcf1a7e 100644
--- a/src/components/AnimatedPaginationDot/AnimatedPaginationDot.js
+++ b/src/components/AnimatedPaginationDot/AnimatedPaginationDot.js
@@ -22,7 +22,7 @@ const AnimatedPaginationDot = ({
}) => {
const animatedValue = useMemo(
() => scrollValue || new Animated.Value(0),
- [scrollValue],
+ [scrollValue]
);
const { width, height } = useWindowDimensions();
@@ -36,7 +36,10 @@ const AnimatedPaginationDot = ({
return Math.max(width, 1);
}, [height, itemDimension, orientation, width]);
- const resolvedDotStyle = useMemo(() => StyleSheet.flatten(dotStyle) || {}, [dotStyle]);
+ const resolvedDotStyle = useMemo(
+ () => StyleSheet.flatten(dotStyle) || {},
+ [dotStyle]
+ );
const defaultSize = Math.max(baseDotSize, 1);
const baseWidth =
typeof resolvedDotStyle?.width === "number"
diff --git a/src/components/player/GlobalAudioPlayer.js b/src/components/player/GlobalAudioPlayer.js
index 99e9648..d47ce77 100644
--- a/src/components/player/GlobalAudioPlayer.js
+++ b/src/components/player/GlobalAudioPlayer.js
@@ -1,11 +1,14 @@
import { BlurView } from "expo-blur";
-import React, { useMemo } from "react";
+import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Image, Pressable, StyleSheet, Text, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { icons, img } from "../../assets";
+import { arrayRemove, arrayUnion, projectsRef } from "../../config/firebase";
import { isWeb } from "../../hooks/useLayoutType";
+import useDataFromRef from "../../hooks/useDataFromRef";
import usePlayer from "../../hooks/usePlayer";
+import { useUser } from "../../providers/UserDataProvider";
import { gutters, Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
@@ -21,16 +24,90 @@ const formatDuration = (ms) => {
const GlobalAudioPlayer = () => {
const { currentTrack, isPlaying, positionMs, durationMs, pause, resume } =
usePlayer();
+ const { currentUID } = useUser() || {};
+ const [pendingLike, setPendingLike] = useState(null);
+
+ const projectId = useMemo(() => {
+ const metadataProjectId =
+ typeof currentTrack?.metadata?.projectId === "string"
+ ? currentTrack.metadata.projectId
+ : null;
+ const metadataPlaybackId =
+ typeof currentTrack?.metadata?.playbackId === "string"
+ ? currentTrack.metadata.playbackId
+ : null;
+ const contextProjectId =
+ typeof currentTrack?.context?.projectId === "string"
+ ? currentTrack.context.projectId
+ : null;
+
+ return metadataProjectId || metadataPlaybackId || contextProjectId || null;
+ }, [
+ currentTrack?.context?.projectId,
+ currentTrack?.metadata?.playbackId,
+ currentTrack?.metadata?.projectId,
+ ]);
+
+ const { data: projectData } = useDataFromRef({
+ ref: projectId ? projectsRef.doc(projectId) : null,
+ simpleRef: true,
+ listener: true,
+ condition: !!projectId,
+ refreshArray: [projectId],
+ });
+
+ const likedByList = Array.isArray(projectData?.likedBy)
+ ? projectData.likedBy
+ : [];
+
+ const likedFromDoc = useMemo(() => {
+ if (!projectId || !currentUID) return false;
+ return likedByList.includes(currentUID);
+ }, [likedByList, projectId, currentUID]);
+
+ const effectiveIsLiked =
+ pendingLike !== null ? pendingLike : likedFromDoc;
+
+ const isLikeProcessing =
+ pendingLike !== null && pendingLike !== likedFromDoc;
+
+ useEffect(() => {
+ setPendingLike(null);
+ }, [projectId, currentUID]);
+
+ useEffect(() => {
+ if (pendingLike === null) return;
+ if (pendingLike === likedFromDoc) {
+ setPendingLike(null);
+ }
+ }, [pendingLike, likedFromDoc]);
+
+ const handleToggleLike = useCallback(async () => {
+ if (!projectId || !currentUID || isLikeProcessing) return;
+ const next = !effectiveIsLiked;
+ setPendingLike(next);
+ try {
+ await projectsRef.doc(projectId).set(
+ {
+ likedBy: next ? arrayUnion(currentUID) : arrayRemove(currentUID),
+ },
+ { merge: true }
+ );
+ } catch (_error) {
+ setPendingLike(null);
+ }
+ }, [
+ currentUID,
+ effectiveIsLiked,
+ isLikeProcessing,
+ projectId,
+ ]);
const insets = useSafeAreaInsets();
const hasTrack = !!currentTrack?.source;
- if (!hasTrack) return null;
-
const title = currentTrack?.title || "Lecture en cours";
const artist = currentTrack?.artist || "";
- const progress =
- durationMs > 0 ? Math.min(1, Math.max(0, positionMs / durationMs)) : 0;
const artworkSource = useMemo(() => {
if (typeof currentTrack?.artwork === "number") return currentTrack.artwork;
@@ -55,6 +132,8 @@ const GlobalAudioPlayer = () => {
const GAP_WITH_TAB = 8;
const bottomOffset = (isWeb ? gutters : 3) + TAB_BAR_HEIGHT + GAP_WITH_TAB;
+ if (!hasTrack) return null;
+
return (
{
)}
+
+
+
{
const creatorName = item?.userName;
const audioPlayer = useSharedAudioPlayer(audioSource || undefined, {
- id: item?.id ? `playback-${item.id}` : audioSource?.uri ? `playback-${audioSource.uri}` : undefined,
+ id: item?.id
+ ? `playback-${item.id}`
+ : audioSource?.uri
+ ? `playback-${audioSource.uri}`
+ : undefined,
title: typeof item?.title === "string" ? item.title : "",
artist: typeof item?.userName === "string" ? item.userName : "",
artwork: item?.coverUrl || null,
@@ -217,57 +221,6 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
backgroundColor: "black",
}}
>
- {(projectTitle || creatorName) && (
-
-
- {projectTitle ? (
-
- {projectTitle}
-
- ) : null}
- {creatorName ? (
-
- {creatorName}
-
- ) : null}
-
-
- )}
{!!videoUrl ? (
{
return (
- {(activeTitle || activeCreatorName) && (
-
-
- {activeTitle ? (
-
- {activeTitle}
-
- ) : null}
- {activeCreatorName ? (
-
- {activeCreatorName}
-
- ) : null}
-
-
- )}
{activeVideoUrl ? (