import React, { createContext, useContext, useState, } from 'react'; import { useTranslation } from 'react-i18next'; import { useDelay } from '../../../hooks/useDelay'; import './index.scss'; export type FullscreenLoaderContext = { showLoader: boolean setShowLoader: (show: boolean) => void } const initialContext: FullscreenLoaderContext = { showLoader: false, setShowLoader: undefined, }; const Context = createContext(initialContext); const delayBeforeRender = 500; const animationDuration = 500; const minShowTime = (animationDuration * 2) + 750; const baseClass = 'fullscreenLoader'; export const FullscreenLoaderProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) => { const { t } = useTranslation('general'); const [showLoader, setShowLoader] = useState(false); const [isShowing, setIsShowing] = React.useState(false); const [hasDelayed, setHasDelayed] = useDelay(delayBeforeRender, showLoader); const [isHiding, setIsHiding] = React.useState(false); const [displayedAt, setDisplayedAt] = React.useState(); React.useEffect(() => { if (hasDelayed && showLoader && !isShowing) { setDisplayedAt(Date.now()); setIsShowing(true); } }, [showLoader, isShowing, displayedAt, hasDelayed]); React.useEffect(() => { let closeTimeout: NodeJS.Timeout; const shouldHide = isShowing && !showLoader; const hide = () => { const timeDisplayed = Date.now() - displayedAt; const remainingShowTime = minShowTime - timeDisplayed; if (remainingShowTime > 0 && timeDisplayed < minShowTime) { closeTimeout = setTimeout(hide, remainingShowTime); } else { setIsHiding(true); closeTimeout = setTimeout(() => { setIsShowing(false); setHasDelayed(false); setIsHiding(false); }, animationDuration); } }; if (shouldHide) { hide(); } return () => { if (closeTimeout) clearTimeout(closeTimeout); }; }, [showLoader, isShowing, displayedAt, setHasDelayed]); return ( {hasDelayed && isShowing && (
{t('loading')}
)} {children} ); }; export const useFullscreenLoader = (): FullscreenLoaderContext => useContext(Context); export default Context;