import PropTypes from 'prop-types'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import ControlsContext from './context'; import useMobileBreakpoint from '../MobileBreakpoint/useMobileBreakpoint'; const ControlsProvider = ({ children }) => { const { isMobileView } = useMobileBreakpoint(); const [isControlsOpen, setIsControlsOpen] = useState(false); const [isHovered, setIsHovered] = useState(false); const timeoutId = useRef(null); const clearControlsTimeout = useCallback(() => { clearTimeout(timeoutId.current); timeoutId.current = null; }, []); const resetControlsTimeout = useCallback(() => { clearControlsTimeout(); timeoutId.current = setTimeout(() => { setIsControlsOpen(false); timeoutId.current = null; }, 3000); }, [clearControlsTimeout]); const stopPropagAndResetTimeout = useCallback( (event) => { if (!isMobileView) return; event.stopPropagation(); resetControlsTimeout(); }, [isMobileView, resetControlsTimeout] ); // Desktop controls toggling logic useEffect(() => { if (isMobileView === false && isHovered) { clearControlsTimeout(); setIsControlsOpen(true); } else if (isMobileView === false && !isHovered) { resetControlsTimeout(); } }, [clearControlsTimeout, isHovered, isMobileView, resetControlsTimeout]); // Mobile controls toggling logic useEffect(() => { const mobileClickHandler = () => { if (!timeoutId.current) { setIsControlsOpen(true); resetControlsTimeout(); } else { setIsControlsOpen(false); clearControlsTimeout(); } }; if (isMobileView) { mobileClickHandler(); document.addEventListener('pointerdown', mobileClickHandler); } return () => { document.removeEventListener('pointerdown', mobileClickHandler); }; }, [clearControlsTimeout, isMobileView, resetControlsTimeout]); const value = useMemo( () => ({ clearControlsTimeout, isControlsOpen, resetControlsTimeout, setIsControlsOpen, setIsHovered, stopPropagAndResetTimeout }), [ clearControlsTimeout, isControlsOpen, stopPropagAndResetTimeout, resetControlsTimeout ] ); return ( {children} ); }; ControlsProvider.propTypes = { children: PropTypes.node.isRequired }; export default ControlsProvider;