last fixes, home and videos
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Text, View } from "react-native";
|
||||
import { background } from "../../assets";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Image, Pressable, Text, View } from "react-native";
|
||||
import { background, icons } from "../../assets";
|
||||
import BorderGradientButton from "../../components/BorderGradientButton";
|
||||
import GradientButton from "../../components/GradientButton";
|
||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||
@@ -32,14 +38,22 @@ const RecordedPlayback = ({ route }) => {
|
||||
const songUrl = project?.songUrl || null;
|
||||
console.log("video uri is : ", videoUri);
|
||||
// AUDIO PLAYER (expo-audio → seconds)
|
||||
const audioPlayer = useSharedAudioPlayer(songUrl ? { uri: songUrl } : undefined, {
|
||||
id: project?.id ? `recorded-${project.id}` : songUrl ? `recorded-${songUrl}` : undefined,
|
||||
title: typeof project?.title === "string" ? project.title : "Sans titre",
|
||||
artist: typeof project?.userName === "string" ? project.userName : "MusicLand",
|
||||
artwork: project?.coverUrl || null,
|
||||
coverUrl: project?.coverUrl || null,
|
||||
metadata: { projectId: project?.id, screen: "RecordedPlayback" },
|
||||
});
|
||||
const audioPlayer = useSharedAudioPlayer(
|
||||
songUrl ? { uri: songUrl } : undefined,
|
||||
{
|
||||
id: project?.id
|
||||
? `recorded-${project.id}`
|
||||
: songUrl
|
||||
? `recorded-${songUrl}`
|
||||
: undefined,
|
||||
title: typeof project?.title === "string" ? project.title : "Sans titre",
|
||||
artist:
|
||||
typeof project?.userName === "string" ? project.userName : "MusicLand",
|
||||
artwork: project?.coverUrl || null,
|
||||
coverUrl: project?.coverUrl || null,
|
||||
metadata: { projectId: project?.id, screen: "RecordedPlayback" },
|
||||
},
|
||||
);
|
||||
|
||||
// Optionnel: si tu veux quand même un rendu vidéo sur web si tu as une source
|
||||
const videoElRef = useRef(null);
|
||||
@@ -149,8 +163,11 @@ const RecordedPlayback = ({ route }) => {
|
||||
};
|
||||
|
||||
const wasPlayingRef = useRef(false);
|
||||
const onSeekStart = async () => {
|
||||
const isSeekingRef = useRef(false);
|
||||
const onSeekStart = useCallback(async () => {
|
||||
try {
|
||||
if (isSeekingRef.current) return;
|
||||
isSeekingRef.current = true;
|
||||
wasPlayingRef.current = !!audioPlayer?.playing;
|
||||
playbackEndedRef.current = false;
|
||||
if (audioPlayer?.playing) await audioPlayer.pause?.();
|
||||
@@ -158,80 +175,151 @@ const RecordedPlayback = ({ route }) => {
|
||||
videoElRef.current.pause();
|
||||
}
|
||||
} catch {}
|
||||
};
|
||||
const onSeekEnd = async () => {
|
||||
}, [audioPlayer]);
|
||||
const onSeekEnd = useCallback(async () => {
|
||||
try {
|
||||
if (!isSeekingRef.current) return;
|
||||
isSeekingRef.current = false;
|
||||
if (wasPlayingRef.current) {
|
||||
if (audioPlayer) await audioPlayer.play?.();
|
||||
if (videoElRef.current && videoUri)
|
||||
videoElRef.current.play().catch(() => {});
|
||||
}
|
||||
} catch {}
|
||||
};
|
||||
}, [audioPlayer, videoUri]);
|
||||
|
||||
const handleTogglePlayback = useCallback(async () => {
|
||||
try {
|
||||
const duration = Number(progress?.durS || 0);
|
||||
const position = Number(progress?.posS || 0);
|
||||
const isAtEnd = duration > 0 && duration - position < 0.35;
|
||||
const isCurrentlyPlaying = !!audioPlayer?.playing;
|
||||
|
||||
if (isCurrentlyPlaying) {
|
||||
playbackEndedRef.current = false;
|
||||
await stopPlayback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAtEnd) {
|
||||
if (audioPlayer) await audioPlayer.seekTo?.(0);
|
||||
if (videoElRef.current && videoUri) {
|
||||
videoElRef.current.currentTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
playbackEndedRef.current = false;
|
||||
if (songUrl && audioPlayer) {
|
||||
await audioPlayer.play?.();
|
||||
}
|
||||
if (videoElRef.current && videoUri) {
|
||||
videoElRef.current.muted = true;
|
||||
videoElRef.current.play().catch(() => {});
|
||||
}
|
||||
} catch {}
|
||||
}, [audioPlayer, songUrl, stopPlayback, progress, videoUri]);
|
||||
|
||||
return (
|
||||
<Page backgroundImg={background.playbackBG2} headerType="NONE">
|
||||
<MusicLandHeader progress={19} onPressBack={goBack} />
|
||||
<Page
|
||||
containerStyle={{
|
||||
alignItems: "none",
|
||||
}}
|
||||
backgroundImg={background.playbackBG2}
|
||||
headerType="NONE"
|
||||
>
|
||||
<MusicLandHeader
|
||||
progress={19}
|
||||
onPressBack={goBack}
|
||||
style={{
|
||||
marginBottom: 40,
|
||||
}}
|
||||
/>
|
||||
<View
|
||||
style={{ flex: 1, paddingTop: 12, gap: 14, paddingBottom: gutters * 2 }}
|
||||
style={{
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<View style={{ flex: 1, gap: 22, alignItems: "center" }}>
|
||||
{/* Bloc vidéo optionnel si jamais tu as un videoUri sur web */}
|
||||
{videoUri ? (
|
||||
<View
|
||||
{/* Bloc vidéo optionnel si jamais tu as un videoUri sur web */}
|
||||
{videoUri ? (
|
||||
<Pressable
|
||||
onPress={handleTogglePlayback}
|
||||
style={{
|
||||
width: isWeb ? WEB_PREVIEW_WIDTH : "80%",
|
||||
maxWidth: "100%",
|
||||
aspectRatio: 9 / 16,
|
||||
borderRadius: 12,
|
||||
backgroundColor: "#00000066",
|
||||
overflow: "hidden",
|
||||
alignSelf: "center",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<video
|
||||
ref={videoElRef}
|
||||
src={videoUri}
|
||||
muted
|
||||
playsInline
|
||||
style={{
|
||||
width: isWeb ? WEB_PREVIEW_WIDTH : "80%",
|
||||
maxWidth: "100%",
|
||||
aspectRatio: 9 / 16,
|
||||
borderRadius: 12,
|
||||
backgroundColor: "#00000066",
|
||||
overflow: "hidden",
|
||||
alignSelf: "center",
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "cover",
|
||||
backgroundColor: "black",
|
||||
}}
|
||||
>
|
||||
<video
|
||||
ref={videoElRef}
|
||||
src={videoUri}
|
||||
muted
|
||||
playsInline
|
||||
controls={false}
|
||||
/>
|
||||
{!progress.playing && (
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "cover",
|
||||
backgroundColor: "black",
|
||||
position: "absolute",
|
||||
left: "50%",
|
||||
top: "50%",
|
||||
transform: [{ translateX: -36 }, { translateY: -36 }],
|
||||
width: 72,
|
||||
height: 72,
|
||||
borderRadius: 36,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "rgba(10, 5, 24, 0.75)",
|
||||
borderWidth: 1,
|
||||
borderColor: "#F94697",
|
||||
}}
|
||||
controls={false}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
// Placeholder quand pas de vidéo sur web
|
||||
<View
|
||||
style={{
|
||||
width: isWeb ? WEB_PREVIEW_WIDTH : "80%",
|
||||
maxWidth: "100%",
|
||||
aspectRatio: 9 / 16,
|
||||
borderRadius: 12,
|
||||
backgroundColor: "#00000066",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
overflow: "hidden",
|
||||
alignSelf: "center",
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: Palette.white, opacity: 0.8 }}>
|
||||
Aperçu vidéo non disponible sur le web
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
>
|
||||
<Image source={icons.play} style={{ width: 26, height: 26 }} />
|
||||
</View>
|
||||
)}
|
||||
</Pressable>
|
||||
) : (
|
||||
// Placeholder quand pas de vidéo sur web
|
||||
<View
|
||||
style={{
|
||||
width: isWeb ? WEB_PREVIEW_WIDTH : "80%",
|
||||
maxWidth: "100%",
|
||||
aspectRatio: 9 / 16,
|
||||
borderRadius: 12,
|
||||
backgroundColor: "#00000066",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
overflow: "hidden",
|
||||
alignSelf: "center",
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: Palette.white, opacity: 0.8 }}>
|
||||
Aperçu vidéo non disponible sur le web
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: isWeb ? WEB_PREVIEW_WIDTH : "80%",
|
||||
maxWidth: "100%",
|
||||
alignSelf: "center",
|
||||
marginTop: 6,
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<View style={{ width: "100%" }}>
|
||||
<Slider
|
||||
value={fmtSeconds(progress.posS)} // mm:ss (seconds)
|
||||
maxValue={fmtSeconds(progress.durS)} // mm:ss (seconds)
|
||||
@@ -243,36 +331,36 @@ const RecordedPlayback = ({ route }) => {
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: isWeb ? WEB_PREVIEW_WIDTH : "80%",
|
||||
maxWidth: "100%",
|
||||
alignSelf: "center",
|
||||
marginTop: 4,
|
||||
gap: 12,
|
||||
<View
|
||||
style={{
|
||||
width: isWeb ? WEB_PREVIEW_WIDTH : "80%",
|
||||
maxWidth: "100%",
|
||||
alignSelf: "center",
|
||||
gap: 12,
|
||||
marginTop: 50,
|
||||
}}
|
||||
>
|
||||
<GradientButton
|
||||
title="Je valide"
|
||||
onPress={() => {
|
||||
navigate(Routes.DownloadSongs, {
|
||||
action: "playback",
|
||||
uri: videoUri || null, // peut être null sur web
|
||||
project,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<GradientButton
|
||||
title="Je valide"
|
||||
onPress={() => {
|
||||
navigate(Routes.DownloadSongs, {
|
||||
action: "playback",
|
||||
uri: videoUri || null, // peut être null sur web
|
||||
project,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<BorderGradientButton
|
||||
title="Recommencer"
|
||||
onPress={async () => {
|
||||
try {
|
||||
await stopPlayback();
|
||||
} catch {}
|
||||
navigate(Routes.RecordPlayback, { project });
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
/>
|
||||
<BorderGradientButton
|
||||
title="Recommencer"
|
||||
onPress={async () => {
|
||||
try {
|
||||
await stopPlayback();
|
||||
} catch {}
|
||||
navigate(Routes.RecordPlayback, { project });
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user