kinetic-slider
Version:
A WebGL-powered kinetic slider component using PIXI.js
1 lines • 34.2 kB
Source Map (JSON)
{"version":3,"file":"useIdleTimer.cjs","sources":["../../../src/hooks/useIdleTimer.ts"],"sourcesContent":["import { useEffect, useRef, useCallback, type RefObject } from 'react';\nimport { DisplacementFilter } from 'pixi.js';\nimport { gsap } from 'gsap';\nimport ResourceManager from '../managers/ResourceManager';\nimport RenderScheduler from '../managers/RenderScheduler';\nimport { UpdateType } from '../managers/UpdateTypes';\nimport AnimationCoordinator, { AnimationGroupType } from '../managers/AnimationCoordinator';\n\n// Development environment check\nconst isDevelopment = import.meta.env?.MODE === 'development';\n\n// Type definitions for function parameters\ninterface UseIdleTimerProps {\n sliderRef: RefObject<HTMLDivElement | null>;\n cursorActive: RefObject<boolean>;\n bgDispFilterRef: RefObject<DisplacementFilter | null>;\n cursorDispFilterRef: RefObject<DisplacementFilter | null>;\n cursorImgEffect: boolean;\n defaultBgFilterScale: number;\n defaultCursorFilterScale: number;\n idleTimeout?: number;\n resourceManager?: ResourceManager | null;\n}\n\n// Interface for animation state tracking\ninterface AnimationState {\n isAnimating: boolean;\n activeAnimations: gsap.core.Tween[];\n pendingBatchAnimations: gsap.core.Tween[];\n}\n\n/**\n * Hook to manage idle timer for resetting displacement effects\n * Fully optimized with:\n * - Batch resource management\n * - Efficient timer handling\n * - Comprehensive error handling\n * - Memory leak prevention\n * - Optimized animation management\n * - Cancellation mechanisms\n * - Animation coordination\n */\nconst useIdleTimer = ({\n sliderRef,\n cursorActive,\n bgDispFilterRef,\n cursorDispFilterRef,\n cursorImgEffect,\n defaultBgFilterScale,\n defaultCursorFilterScale,\n idleTimeout = 300,\n resourceManager\n }: UseIdleTimerProps) => {\n // Store idle timer reference\n const idleTimerRef = useRef<number | null>(null);\n\n // Store animation state with a ref to avoid re-renders\n const animationStateRef = useRef<AnimationState>({\n isAnimating: false,\n activeAnimations: [],\n pendingBatchAnimations: []\n });\n\n // Flag to prevent operations during unmounting\n const isUnmountingRef = useRef(false);\n\n // Last animation operation timestamp for performance tracking\n const lastAnimationOpRef = useRef<number>(0);\n\n // Get the animation coordinator\n const animationCoordinator = AnimationCoordinator.getInstance();\n\n /**\n * Process pending animations in batch for better performance\n */\n const processPendingAnimations = useCallback(() => {\n try {\n // Skip if unmounting or no resource manager\n if (isUnmountingRef.current || !resourceManager) return;\n\n const { pendingBatchAnimations } = animationStateRef.current;\n\n // Process animations in batch if any exist\n if (pendingBatchAnimations.length > 0) {\n if (isDevelopment) {\n console.log(`Processing batch of ${pendingBatchAnimations.length} animations`);\n }\n\n resourceManager.trackAnimationBatch(pendingBatchAnimations);\n\n // Clear the array after tracking (more efficient than creating a new array)\n pendingBatchAnimations.length = 0;\n\n // Record performance metrics\n const now = performance.now();\n const opTime = now - lastAnimationOpRef.current;\n if (isDevelopment && lastAnimationOpRef.current > 0) {\n console.debug(`Animation batch processing took ${opTime.toFixed(2)}ms`);\n }\n lastAnimationOpRef.current = now;\n }\n } catch (error) {\n if (isDevelopment) {\n console.error('Error processing pending animations:', error);\n }\n // Clear pending animations even on error to avoid stuck state\n animationStateRef.current.pendingBatchAnimations = [];\n }\n }, [resourceManager]);\n\n /**\n * Track an animation for batch processing\n */\n const trackAnimationForBatch = useCallback((animation: gsap.core.Tween): gsap.core.Tween => {\n try {\n // Skip if unmounting\n if (isUnmountingRef.current) return animation;\n\n // Add to pending batch\n animationStateRef.current.pendingBatchAnimations.push(animation);\n return animation;\n } catch (error) {\n if (isDevelopment) {\n console.error('Error tracking animation for batch:', error);\n }\n return animation;\n }\n }, []);\n\n /**\n * Create animations for filter scale changes\n * Now uses AnimationCoordinator for better coordination\n */\n const createFilterAnimations = useCallback((\n targetScale: number,\n duration: number = 0.5,\n onComplete?: () => void\n ): gsap.core.Tween[] => {\n try {\n // Skip if unmounting\n if (isUnmountingRef.current) return [];\n\n // Record start time for performance tracking\n lastAnimationOpRef.current = performance.now();\n\n if (isDevelopment) {\n console.log(`Creating filter animations with targetScale: ${targetScale}, duration: ${duration}`, {\n bgFilterCurrent: bgDispFilterRef.current ?\n { x: bgDispFilterRef.current.scale.x, y: bgDispFilterRef.current.scale.y } : 'no filter',\n cursorFilterCurrent: cursorDispFilterRef.current ?\n { x: cursorDispFilterRef.current.scale.x, y: cursorDispFilterRef.current.scale.y } : 'no filter',\n defaultBgFilterScale,\n defaultCursorFilterScale\n });\n }\n\n // Create animations array for batch tracking\n const animations: gsap.core.Tween[] = [];\n\n // Create background displacement filter animation\n if (bgDispFilterRef.current) {\n // Ensure we're using the correct target scale\n const actualTargetScale = targetScale === 0 ? 0 : defaultBgFilterScale;\n\n // Apply immediate scale if needed for visibility\n if (targetScale > 0 && (bgDispFilterRef.current.scale.x === 0 || bgDispFilterRef.current.scale.y === 0)) {\n bgDispFilterRef.current.scale.x = actualTargetScale;\n bgDispFilterRef.current.scale.y = actualTargetScale;\n\n if (isDevelopment) {\n console.log(`Applied immediate scale to background filter: ${actualTargetScale}`);\n }\n }\n\n const bgTween = gsap.to(bgDispFilterRef.current.scale, {\n x: actualTargetScale,\n y: actualTargetScale,\n duration,\n ease: \"power2.out\",\n onComplete: () => {\n // Re-track the filter after animation\n if (resourceManager && bgDispFilterRef.current) {\n resourceManager.trackFilter(bgDispFilterRef.current);\n }\n\n if (isDevelopment) {\n console.log(`Background filter animation complete, scale: (${actualTargetScale}, ${actualTargetScale})`);\n }\n }\n });\n\n animations.push(bgTween);\n }\n\n // Create cursor displacement filter animation if enabled\n if (cursorImgEffect && cursorDispFilterRef.current) {\n const cursorScale = targetScale === 0 ? 0 : defaultCursorFilterScale;\n\n // Apply immediate scale if needed for visibility\n if (targetScale > 0 && (cursorDispFilterRef.current.scale.x === 0 || cursorDispFilterRef.current.scale.y === 0)) {\n cursorDispFilterRef.current.scale.x = cursorScale;\n cursorDispFilterRef.current.scale.y = cursorScale;\n\n if (isDevelopment) {\n console.log(`Applied immediate scale to cursor filter: ${cursorScale}`);\n }\n }\n\n const cursorTween = gsap.to(cursorDispFilterRef.current.scale, {\n x: cursorScale,\n y: cursorScale,\n duration,\n ease: \"power2.out\",\n onComplete: () => {\n // Re-track the filter after animation\n if (resourceManager && cursorDispFilterRef.current) {\n resourceManager.trackFilter(cursorDispFilterRef.current);\n }\n\n if (isDevelopment) {\n console.log(`Cursor filter animation complete, scale: (${cursorScale}, ${cursorScale})`);\n }\n }\n });\n\n animations.push(cursorTween);\n }\n\n // Use AnimationCoordinator to create a coordinated animation group\n const groupType = targetScale === 0\n ? AnimationGroupType.IDLE_EFFECT\n : AnimationGroupType.INTERACTION;\n\n animationCoordinator.queueAnimationGroup({\n id: `filter_animation_${Date.now()}`,\n type: groupType,\n animations,\n onComplete\n });\n\n return animations;\n } catch (error) {\n if (isDevelopment) {\n console.error('Error creating filter animations:', error);\n }\n\n // Call completion handler even on error\n if (onComplete) onComplete();\n return [];\n }\n }, [\n bgDispFilterRef,\n cursorDispFilterRef,\n cursorImgEffect,\n defaultCursorFilterScale,\n defaultBgFilterScale,\n resourceManager,\n animationCoordinator\n ]);\n\n /**\n * Reset filters to idle state (no effect)\n * Now uses AnimationCoordinator for better coordination\n */\n const resetFilters = useCallback(() => {\n try {\n // Skip if unmounting\n if (isUnmountingRef.current) return;\n\n if (isDevelopment) {\n console.log('Resetting filters to idle state');\n }\n\n // Cancel any active idle timer\n if (idleTimerRef.current !== null) {\n window.clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n\n // Skip if cursor is active\n if (cursorActive.current) {\n if (isDevelopment) {\n console.log('Skipping filter reset - cursor is active');\n }\n return;\n }\n\n // Cancel any existing animations of the same type\n animationCoordinator.cancelAnimationsByType(AnimationGroupType.IDLE_EFFECT);\n\n // Create animations to reset filters\n createFilterAnimations(0, 0.5, () => {\n if (isDevelopment) {\n console.log('Filters reset to idle state');\n }\n });\n\n // Schedule a render update\n animationCoordinator.scheduleAnimationUpdate(\n AnimationGroupType.IDLE_EFFECT,\n () => {\n if (isDevelopment) {\n console.log('Idle effect render update completed');\n }\n },\n 'idle_reset'\n );\n } catch (error) {\n if (isDevelopment) {\n console.error('Error resetting filters:', error);\n }\n }\n }, [\n cursorActive,\n createFilterAnimations,\n animationCoordinator\n ]);\n\n /**\n * Restore filters to active state\n * Now uses AnimationCoordinator for better coordination\n * @param immediate Whether to apply changes immediately without animation\n */\n const restoreFilters = useCallback((immediate = false) => {\n try {\n // Skip if unmounting\n if (isUnmountingRef.current) return;\n\n if (isDevelopment) {\n console.log(`Restoring filters to active state (immediate: ${immediate})`, {\n defaultBgFilterScale,\n defaultCursorFilterScale,\n bgFilterCurrent: bgDispFilterRef.current ?\n { x: bgDispFilterRef.current.scale.x, y: bgDispFilterRef.current.scale.y } : 'no filter',\n cursorFilterCurrent: cursorDispFilterRef.current ?\n { x: cursorDispFilterRef.current.scale.x, y: cursorDispFilterRef.current.scale.y } : 'no filter'\n });\n }\n\n // Cancel any active idle timer\n if (idleTimerRef.current !== null) {\n window.clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n\n // Cancel any existing animations of the same type\n animationCoordinator.cancelAnimationsByType(AnimationGroupType.INTERACTION);\n\n // Ensure the cursor is marked as active\n cursorActive.current = true;\n\n // Apply immediate changes to ensure filters are visible right away\n if (bgDispFilterRef.current) {\n // Store original values for debugging\n const originalX = bgDispFilterRef.current.scale.x;\n const originalY = bgDispFilterRef.current.scale.y;\n\n // Set to full scale values\n bgDispFilterRef.current.scale.x = defaultBgFilterScale;\n bgDispFilterRef.current.scale.y = defaultBgFilterScale;\n\n if (isDevelopment) {\n console.log(`Directly set background filter scale from (${originalX}, ${originalY}) to (${defaultBgFilterScale}, ${defaultBgFilterScale})`);\n }\n }\n\n if (cursorImgEffect && cursorDispFilterRef.current) {\n // Store original values for debugging\n const originalX = cursorDispFilterRef.current.scale.x;\n const originalY = cursorDispFilterRef.current.scale.y;\n\n // Set to full scale values\n cursorDispFilterRef.current.scale.x = defaultCursorFilterScale;\n cursorDispFilterRef.current.scale.y = defaultCursorFilterScale;\n\n if (isDevelopment) {\n console.log(`Directly set cursor filter scale from (${originalX}, ${originalY}) to (${defaultCursorFilterScale}, ${defaultCursorFilterScale})`);\n }\n }\n\n // Schedule an immediate render update to ensure changes are visible\n RenderScheduler.getInstance().scheduleTypedUpdate(\n 'idleTimer',\n UpdateType.DISPLACEMENT_EFFECT,\n () => {\n if (isDevelopment) {\n console.log('Immediate render update for filter restoration');\n }\n },\n immediate ? 'critical' : 'high' // Use critical priority for immediate restoration\n );\n\n // If immediate is true, we've already set the filter scales directly\n // For smoother transitions, still create animations but with shorter duration\n const animationDuration = immediate ? 0.2 : 0.5;\n\n // Create animations to restore filters (for smooth transition)\n createFilterAnimations(defaultBgFilterScale, animationDuration, () => {\n if (isDevelopment) {\n console.log('Filters restored to active state - animation complete', {\n bgFilterFinal: bgDispFilterRef.current ?\n { x: bgDispFilterRef.current.scale.x, y: bgDispFilterRef.current.scale.y } : 'no filter',\n cursorFilterFinal: cursorDispFilterRef.current ?\n { x: cursorDispFilterRef.current.scale.x, y: cursorDispFilterRef.current.scale.y } : 'no filter'\n });\n }\n });\n\n // Schedule a render update with appropriate priority\n animationCoordinator.scheduleAnimationUpdate(\n AnimationGroupType.INTERACTION,\n () => {\n if (isDevelopment) {\n console.log('Interaction effect render update completed');\n }\n },\n immediate ? 'critical' : 'high'\n );\n } catch (error) {\n if (isDevelopment) {\n console.error('Error restoring filters:', error);\n }\n }\n }, [\n defaultBgFilterScale,\n defaultCursorFilterScale,\n bgDispFilterRef,\n cursorDispFilterRef,\n cursorImgEffect,\n cursorActive,\n createFilterAnimations,\n animationCoordinator\n ]);\n\n /**\n * Handle mouse movement to reset idle timer\n */\n const handleMouseMove = useCallback(() => {\n try {\n // Skip if unmounting\n if (isUnmountingRef.current) return;\n\n // Cancel any active idle timer\n if (idleTimerRef.current !== null) {\n window.clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n\n // Set cursor as active\n if (cursorActive.current !== true) {\n cursorActive.current = true;\n\n if (isDevelopment) {\n console.log('Mouse movement detected - setting cursor as active');\n }\n\n // Immediately restore filters when cursor becomes active after being inactive\n // This ensures there's no delay in showing the displacement effect\n const bgFilter = bgDispFilterRef.current;\n const cursorFilter = cursorDispFilterRef.current;\n\n if (bgFilter) {\n // Apply full scale immediately for instant visibility\n bgFilter.scale.x = defaultBgFilterScale;\n bgFilter.scale.y = defaultBgFilterScale;\n\n if (isDevelopment) {\n console.log(`Immediately set background filter scale to ${defaultBgFilterScale} after idle`);\n }\n }\n\n if (cursorImgEffect && cursorFilter) {\n // Apply full scale immediately for instant visibility\n cursorFilter.scale.x = defaultCursorFilterScale;\n cursorFilter.scale.y = defaultCursorFilterScale;\n\n if (isDevelopment) {\n console.log(`Immediately set cursor filter scale to ${defaultCursorFilterScale} after idle`);\n }\n }\n\n // Schedule an immediate render update to ensure changes are visible\n RenderScheduler.getInstance().scheduleTypedUpdate(\n 'idleTimer',\n UpdateType.DISPLACEMENT_EFFECT,\n () => {\n if (isDevelopment) {\n console.log('Immediate render update for filter restoration after idle');\n }\n },\n 'critical' // Use critical priority to ensure immediate processing\n );\n\n // Then call restoreFilters to handle animations and other logic\n restoreFilters(true); // Pass true to indicate immediate restoration\n }\n\n // Check if filters need to be restored\n const bgFilter = bgDispFilterRef.current;\n const cursorFilter = cursorDispFilterRef.current;\n\n const bgFilterInactive = bgFilter && (bgFilter.scale.x === 0 || bgFilter.scale.y === 0);\n const cursorFilterInactive = cursorImgEffect && cursorFilter &&\n (cursorFilter.scale.x === 0 || cursorFilter.scale.y === 0);\n\n if (bgFilterInactive || cursorFilterInactive) {\n if (isDevelopment) {\n console.log('Filters are inactive, restoring them immediately', {\n bgFilterInactive,\n cursorFilterInactive,\n bgScale: bgFilter ? [bgFilter.scale.x, bgFilter.scale.y] : 'no filter',\n cursorScale: cursorFilter ? [cursorFilter.scale.x, cursorFilter.scale.y] : 'no filter'\n });\n }\n\n // Restore filters to active state immediately\n restoreFilters(true); // Pass true to indicate immediate restoration\n }\n\n // Set a new idle timer\n idleTimerRef.current = window.setTimeout(() => {\n // Set cursor as inactive\n cursorActive.current = false;\n\n if (isDevelopment) {\n console.log('Idle timeout reached - setting cursor as inactive');\n }\n\n // Reset filters when idle\n resetFilters();\n\n // Clear timer reference\n idleTimerRef.current = null;\n }, idleTimeout);\n } catch (error) {\n if (isDevelopment) {\n console.error('Error handling mouse movement:', error);\n }\n }\n }, [\n cursorActive,\n bgDispFilterRef,\n cursorDispFilterRef,\n cursorImgEffect,\n defaultBgFilterScale,\n defaultCursorFilterScale,\n idleTimeout,\n resetFilters,\n restoreFilters\n ]);\n\n // Set up mouse movement tracking\n useEffect(() => {\n // Skip during server-side rendering\n if (typeof window === 'undefined') return;\n\n // Skip if slider reference is not available\n if (!sliderRef.current) return;\n\n // Reset unmounting flag\n isUnmountingRef.current = false;\n\n try {\n const node = sliderRef.current;\n\n // Register event listeners\n if (resourceManager) {\n // Batch registration with ResourceManager\n const listeners = new Map<string, EventCallback[]>();\n listeners.set('mousemove', [handleMouseMove]);\n resourceManager.addEventListenerBatch(node, listeners);\n } else {\n // Direct registration\n node.addEventListener('mousemove', handleMouseMove, { passive: true });\n }\n\n // Set initial idle timer\n idleTimerRef.current = window.setTimeout(() => {\n // Set cursor as inactive\n cursorActive.current = false;\n\n // Reset filters when idle\n resetFilters();\n\n // Clear timer reference\n idleTimerRef.current = null;\n }, idleTimeout);\n\n // Cleanup on unmount\n return () => {\n // Update unmounting flag immediately\n isUnmountingRef.current = true;\n\n try {\n // Cancel any active idle timer\n if (idleTimerRef.current !== null) {\n window.clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n\n // ResourceManager handles its own cleanup\n if (!resourceManager) {\n node.removeEventListener('mousemove', handleMouseMove);\n }\n } catch (cleanupError) {\n if (isDevelopment) {\n console.error('Error during idle timer cleanup:', cleanupError);\n }\n }\n };\n } catch (error) {\n if (isDevelopment) {\n console.error('Error setting up idle timer:', error);\n }\n // Return empty cleanup function\n return () => {};\n }\n }, [\n sliderRef,\n handleMouseMove,\n idleTimeout,\n resetFilters,\n resourceManager\n ]);\n\n // Return methods for external control\n return {\n resetFilters,\n restoreFilters\n };\n};\n\n// Type definition for event callback - to match ResourceManager's expected type\ntype EventCallback = EventListenerOrEventListenerObject;\n\nexport default useIdleTimer;"],"names":["useRef","AnimationCoordinator","useCallback","gsap","AnimationGroupType","RenderScheduler","UpdateType","bgFilter","cursorFilter","useEffect"],"mappings":"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"}