173 lines
3.3 KiB
JavaScript
173 lines
3.3 KiB
JavaScript
import { Portal } from "@gorhom/portal";
|
|
import { Asset } from "expo-asset";
|
|
import React, { useEffect, useRef, useState } from "react";
|
|
import { Pressable, Text, View } from "react-native";
|
|
|
|
const overlayStyle = {
|
|
position: "fixed",
|
|
top: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
left: 0,
|
|
backgroundColor: "black",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
zIndex: 9999,
|
|
};
|
|
|
|
const videoStyle = {
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
width: "100%",
|
|
height: "100%",
|
|
objectFit: "cover",
|
|
};
|
|
|
|
const closeButtonStyle = {
|
|
position: "absolute",
|
|
top: 50,
|
|
right: 20,
|
|
backgroundColor: "#00000080",
|
|
paddingVertical: 10,
|
|
paddingHorizontal: 14,
|
|
borderRadius: 20,
|
|
borderWidth: 1,
|
|
borderColor: "#FFFFFF55",
|
|
cursor: "pointer",
|
|
};
|
|
|
|
const closeTextStyle = {
|
|
color: "#FFF",
|
|
fontSize: 14,
|
|
};
|
|
|
|
const resolveModuleUri = async (module) => {
|
|
const asset = Asset.fromModule(module);
|
|
|
|
if (!asset.localUri && !asset.uri) {
|
|
await asset.downloadAsync();
|
|
}
|
|
|
|
return asset.localUri ?? asset.uri ?? null;
|
|
};
|
|
|
|
const FullscreenIntroVideo = ({ url, visible = true, onClose }) => {
|
|
const videoRef = useRef(null);
|
|
const [uri, setUri] = useState(null);
|
|
const [muted, setMuted] = useState(false);
|
|
|
|
useEffect(() => {
|
|
let isMounted = true;
|
|
|
|
const assignUri = (nextUri) => {
|
|
if (isMounted) {
|
|
setMuted(false);
|
|
setUri(nextUri);
|
|
}
|
|
};
|
|
|
|
if (typeof url === "string") {
|
|
assignUri(url);
|
|
return () => {
|
|
isMounted = false;
|
|
};
|
|
}
|
|
|
|
const load = async () => {
|
|
try {
|
|
const nextUri = await resolveModuleUri(url);
|
|
assignUri(nextUri);
|
|
} catch {
|
|
if (isMounted) {
|
|
setUri(null);
|
|
}
|
|
}
|
|
};
|
|
|
|
load();
|
|
|
|
return () => {
|
|
isMounted = false;
|
|
};
|
|
}, [url]);
|
|
|
|
useEffect(() => {
|
|
if (!visible) {
|
|
return undefined;
|
|
}
|
|
|
|
const video = videoRef.current;
|
|
|
|
if (!video || !uri) {
|
|
return undefined;
|
|
}
|
|
|
|
const handleEnded = () => onClose?.();
|
|
video.addEventListener("ended", handleEnded);
|
|
|
|
video.currentTime = 0;
|
|
const attemptPlay = () => {
|
|
const result = video.play();
|
|
|
|
if (result?.catch) {
|
|
result.catch((error) => {
|
|
if (error?.name === "NotAllowedError" && !muted) {
|
|
setMuted(true);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
attemptPlay();
|
|
|
|
return () => {
|
|
video.pause();
|
|
video.removeEventListener("ended", handleEnded);
|
|
};
|
|
}, [muted, onClose, uri, visible]);
|
|
|
|
useEffect(() => {
|
|
const video = videoRef.current;
|
|
|
|
if (!video || !muted) {
|
|
return;
|
|
}
|
|
|
|
const result = video.play();
|
|
|
|
if (result?.catch) {
|
|
result.catch(() => {});
|
|
}
|
|
}, [muted]);
|
|
|
|
if (!visible) {
|
|
return null;
|
|
}
|
|
|
|
console.log("video uri", uri);
|
|
return (
|
|
<Portal>
|
|
<View pointerEvents="box-none" style={overlayStyle}>
|
|
{uri ? (
|
|
<video
|
|
ref={videoRef}
|
|
src={uri}
|
|
style={videoStyle}
|
|
playsInline
|
|
autoPlay
|
|
loop={false}
|
|
muted={muted}
|
|
controls={false}
|
|
/>
|
|
) : null}
|
|
<Pressable onPress={() => onClose?.()} style={closeButtonStyle}>
|
|
<Text style={closeTextStyle}>Passer la vidéo</Text>
|
|
</Pressable>
|
|
</View>
|
|
</Portal>
|
|
);
|
|
};
|
|
|
|
export default FullscreenIntroVideo;
|