import { InteractionManager } from 'react-native'; import { router } from 'expo-router'; import { showGlobalLoader, hideGlobalLoader } from '../stores/uiStore'; let loaderEnhancementEnabled = false; // Performance monitoring (only in dev) const isDev = process.env.NODE_ENV !== 'production'; const perfLogs: Record = {}; const logPerformance = (methodName: string, duration: number) => { if (!isDev) return; if (!perfLogs[methodName]) { perfLogs[methodName] = []; } perfLogs[methodName].push(duration); // Log average every 5 calls if (perfLogs[methodName].length % 5 === 0) { const avg = perfLogs[methodName].reduce((a, b) => a + b, 0) / perfLogs[methodName].length; console.log(`[nav-perf] ${methodName}: avg ${avg.toFixed(2)}ms (${perfLogs[methodName].length} calls)`); } }; const scheduleHide = () => { // Use requestIdleCallback if available, otherwise InteractionManager if (typeof requestIdleCallback !== 'undefined') { requestIdleCallback(() => { hideGlobalLoader(); }, { timeout: 100 }); } else { InteractionManager.runAfterInteractions(() => { hideGlobalLoader(); }); } }; const wrapNavigationMethod = any>( methodName: string, originalMethod: T ): T => { const wrapped = ((...args: Parameters) => { const startTime = isDev && typeof performance !== 'undefined' ? performance.now() : 0; console.log(`[router-loader] ${methodName} invoked`); // Show loader after a small delay to avoid flicker on fast navigations const loaderTimeout = setTimeout(() => { showGlobalLoader(); }, 100); try { const result = originalMethod(...args); // Clear loader timeout and schedule hide clearTimeout(loaderTimeout); scheduleHide(); if (isDev && typeof performance !== 'undefined') { const duration = performance.now() - startTime; logPerformance(methodName, duration); if (duration > 300) { console.warn(`[nav-perf] Slow navigation: ${methodName} took ${duration.toFixed(2)}ms`); } } return result; } catch (error) { clearTimeout(loaderTimeout); hideGlobalLoader(); throw error; } }) as T; return wrapped; }; export const enableRouterLoader = () => { if (loaderEnhancementEnabled) { return; } loaderEnhancementEnabled = true; const originalPush = router.push.bind(router); const originalReplace = router.replace.bind(router); const originalNavigate = router.navigate.bind(router); const originalBack = router.back.bind(router); (router as any).push = wrapNavigationMethod('push', originalPush); (router as any).replace = wrapNavigationMethod('replace', originalReplace); (router as any).navigate = wrapNavigationMethod('navigate', originalNavigate); (router as any).back = wrapNavigationMethod('back', originalBack); };