import { useEffect, useRef, useState } from 'react' interface PageLifecycleState { isVisible: boolean wasEverHidden: boolean timeHidden: number timeVisible: number } export function usePageLifecycle() { const [state, setState] = useState({ isVisible: true, wasEverHidden: false, timeHidden: 0, timeVisible: Date.now() }) const hiddenTimeRef = useRef(0) const wasFreezingRef = useRef(false) useEffect(() => { const handleVisibilityChange = () => { const now = Date.now() const isVisible = !document.hidden if (isVisible) { // Page became visible const timeHidden = hiddenTimeRef.current > 0 ? now - hiddenTimeRef.current : 0 setState(prev => ({ ...prev, isVisible: true, timeVisible: now, timeHidden })) hiddenTimeRef.current = 0 } else { // Page became hidden hiddenTimeRef.current = now setState(prev => ({ ...prev, isVisible: false, wasEverHidden: true })) } } const handleFreeze = () => { wasFreezingRef.current = true } const handleResume = () => { if (wasFreezingRef.current) { wasFreezingRef.current = false // Page was suspended, treat as significant event setState(prev => ({ ...prev, wasEverHidden: true, timeVisible: Date.now() })) } } const handlePageShow = () => { // Page show event (possibly from cache) } const handlePageHide = () => { // Page hide event (possibly being cached) } // Add all the event listeners document.addEventListener('visibilitychange', handleVisibilityChange) document.addEventListener('freeze', handleFreeze) document.addEventListener('resume', handleResume) window.addEventListener('pageshow', handlePageShow) window.addEventListener('pagehide', handlePageHide) // Initial state handleVisibilityChange() return () => { document.removeEventListener('visibilitychange', handleVisibilityChange) document.removeEventListener('freeze', handleFreeze) document.removeEventListener('resume', handleResume) window.removeEventListener('pageshow', handlePageShow) window.removeEventListener('pagehide', handlePageHide) } }, []) const shouldRefreshData = (thresholdMs: number = 30000) => { return state.timeHidden > thresholdMs || wasFreezingRef.current } const shouldPreserveState = () => { // Preserve state if user just switched tabs briefly return state.wasEverHidden && state.timeHidden < 30000 } return { ...state, shouldRefreshData, shouldPreserveState, wasRecentlyHidden: state.timeHidden > 0 && state.timeHidden < 5000 } }