"use client"; import * as React from "react"; import { usePathname, useSearchParams } from "next/navigation"; import { completeNavigationProgress, subscribeNavigationProgress, } from "@/lib/navigation-progress"; const START_VALUE = 18; const MAX_ACTIVE_VALUE = 90; export default function RouteProgress() { const pathname = usePathname(); const searchParams = useSearchParams(); const [visible, setVisible] = React.useState(false); const [progress, setProgress] = React.useState(0); const intervalRef = React.useRef(null); const finishTimeoutRef = React.useRef(null); const safetyTimeoutRef = React.useRef(null); const activeRef = React.useRef(false); const routeKey = `${pathname ?? ""}?${searchParams?.toString() ?? ""}`; const clearTimers = React.useCallback(() => { if (intervalRef.current !== null) { window.clearInterval(intervalRef.current); intervalRef.current = null; } if (finishTimeoutRef.current !== null) { window.clearTimeout(finishTimeoutRef.current); finishTimeoutRef.current = null; } if (safetyTimeoutRef.current !== null) { window.clearTimeout(safetyTimeoutRef.current); safetyTimeoutRef.current = null; } }, []); const finish = React.useCallback(() => { if (!activeRef.current) { return; } activeRef.current = false; clearTimers(); setProgress(100); finishTimeoutRef.current = window.setTimeout(() => { setVisible(false); setProgress(0); }, 220); }, [clearTimers]); const start = React.useCallback(() => { clearTimers(); activeRef.current = true; setVisible(true); setProgress(START_VALUE); window.requestAnimationFrame(() => { setProgress(28); }); intervalRef.current = window.setInterval(() => { setProgress((current) => { if (current >= MAX_ACTIVE_VALUE) { return current; } const delta = Math.max((MAX_ACTIVE_VALUE - current) * 0.14, 1.5); return Math.min(MAX_ACTIVE_VALUE, current + delta); }); }, 180); safetyTimeoutRef.current = window.setTimeout(() => { finish(); }, 12000); }, [clearTimers, finish]); React.useEffect(() => { return subscribeNavigationProgress((event) => { if (event === "start") { start(); return; } finish(); }); }, [finish, start]); React.useEffect(() => { finish(); }, [finish, routeKey]); React.useEffect(() => { return () => { clearTimers(); }; }, [clearTimers]); return (