// GlobalVideoPlayer.tsx import videojs from "video.js"; import { useGlobalPlayerStore } from "../state/pip"; import { useCallback, useContext, useEffect, useRef, useState } from "react"; import { Box, IconButton } from "@mui/material"; import { VideoContainer } from "../components/VideoPlayer/VideoPlayer-styles"; import { Rnd } from "react-rnd"; import { useProgressStore } from "../state/video"; import CloseIcon from "@mui/icons-material/Close"; import PlayArrowIcon from "@mui/icons-material/PlayArrow"; import PauseIcon from "@mui/icons-material/Pause"; import OpenInFullIcon from "@mui/icons-material/OpenInFull"; import { GlobalContext } from "../context/GlobalProvider"; import { isTouchDevice } from "../components/VideoPlayer/VideoPlayer"; import { useNavigate } from "react-router-dom"; export const GlobalPipPlayer = () => { const { videoSrc, reset, isPlaying, location, type, currentTime, mode, videoId, } = useGlobalPlayerStore(); const [playing, setPlaying] = useState(false); const [hasStarted, setHasStarted] = useState(false); const playerRef = useRef(null); const containerRef = useRef(null); const context = useContext(GlobalContext); const navigate = useNavigate() const videoNode = useRef(null); const hideTimeoutRef = useRef(null); const { setProgress } = useProgressStore(); const updateProgress = useCallback(() => { const player = playerRef?.current; if (!player || typeof player?.currentTime !== "function") return; const currentTime = player.currentTime(); if (typeof currentTime === "number" && videoId && currentTime > 0.1) { setProgress(videoId, currentTime); } }, [videoId]); const rndRef = useRef(null); useEffect(() => { if (!playerRef.current && videoNode.current) { playerRef.current = videojs(videoNode.current, { autoplay: true, controls: false, responsive: true, fluid: true, }); playerRef.current?.on("error", () => { // Optional: display user-friendly message }); // Resume playback if needed playerRef.current.on("ready", () => { if (videoSrc) { playerRef.current.src(videoSrc); playerRef.current.currentTime(currentTime); if (isPlaying) playerRef.current.play(); } }); } return () => { // optional: don't destroy, just hide }; }, []); useEffect(() => { if (!videoSrc) { setHasStarted(false); } }, [videoSrc]); useEffect(() => { const player = playerRef.current; if (!player) return; if (!videoSrc && player.src) { // Only pause the player and unload the source without re-triggering playback player.pause(); // player.src({ src: '', type: '' }); // ⬅️ this is the safe way to clear it setPlaying(false); setHasStarted(false); // Optionally clear the poster and currentTime player.poster(""); player.currentTime(0); return; } if (videoSrc) { // Set source and resume if needed player.src({ src: videoSrc, type: type }); player.currentTime(currentTime); if (isPlaying) { const playPromise = player.play(); if (playPromise?.catch) { playPromise.catch((err: any) => { console.warn("Unable to autoplay:", err); }); } } else { player.pause(); } } }, [videoSrc, type, isPlaying, currentTime]); // const onDragStart = () => { // timer = Date.now(); // isDragging.current = true; // }; // const handleStopDrag = async () => { // const time = Date.now(); // if (timer && time - timer < 300) { // isDragging.current = false; // } else { // isDragging.current = true; // } // }; // const onDragStop = () => { // handleStopDrag(); // }; // const checkIfDrag = useCallback(() => { // return isDragging.current; // }, []); const margin = 50; const [height, setHeight] = useState(300); const [width, setWidth] = useState(400); const savedHeightRef = useRef(null) const savedWidthRef = useRef(null) useEffect(() => { if (!videoSrc) return; const screenWidth = window.innerWidth; const screenHeight = window.innerHeight; const aspectRatio = 0.75; // 300 / 400 = 3:4 const maxWidthByScreen = screenWidth * 0.75; const maxWidthByHeight = (screenHeight * 0.3) / aspectRatio; const maxWidth = savedWidthRef.current || Math.min(maxWidthByScreen, maxWidthByHeight); const maxHeight = savedHeightRef.current || maxWidth * aspectRatio; setWidth(maxWidth); setHeight(maxHeight); rndRef.current.updatePosition({ x: screenWidth - maxWidth - margin, y: screenHeight - maxHeight - margin, width: maxWidth, height: maxHeight, }); }, [videoSrc]); const [showControls, setShowControls] = useState(false); const handleMouseMove = () => { if (isTouchDevice) return; setShowControls(true); }; const handleMouseLeave = () => { if (isTouchDevice) return; setShowControls(false); }; const startPlay = useCallback(() => { try { const player = playerRef.current; if (!player) return; try { player.play(); } catch (err) { console.warn("Play failed:", err); } } catch (error) { console.error("togglePlay", error); } }, []); const stopPlay = useCallback(() => { const player = playerRef.current; if (!player) return; try { player.pause(); } catch (err) { console.warn("Play failed:", err); } }, []); const onPlayHandlerStart = useCallback(() => { setPlaying(true); setHasStarted(true); }, [setPlaying]); const onPlayHandlerStop = useCallback(() => { setPlaying(false); }, [setPlaying]); const resetHideTimeout = () => { setShowControls(true); if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current); hideTimeoutRef.current = setTimeout(() => { setShowControls(false); }, 3000); }; useEffect(() => { const container = containerRef.current; if (!videoSrc || !container) return; const handleInteraction = () => { resetHideTimeout(); }; container.addEventListener("touchstart", handleInteraction, { passive: true, capture: true, }); return () => { container.removeEventListener("touchstart", handleInteraction, { capture: true, }); }; }, [videoSrc]); return ( { setWidth(ref.offsetWidth); setHeight(ref.offsetHeight); savedHeightRef.current = ref.offsetHeight savedWidthRef.current = ref.offsetWidth }} // default={{ // x: 500, // y: 500, // width: 350, // height: "auto", // }} // eslint-disable-next-line @typescript-eslint/no-empty-function onDrag={() => {}} > {/*
*/} {/* {backgroundColor: showControls ? 'rgba(0,0,0,.5)' : 'unset'} */} {showControls && ( {location && ( { e.stopPropagation() if (navigate) { navigate(location); } }} onTouchStart={(e) => { e.stopPropagation() if (navigate) { navigate(location); } }} > )} {playing && ( )} {!playing && ( )} )} {/*
*/}
); };