diff --git a/src/layouts/AppLayout.tsx b/src/layouts/AppLayout.tsx index 863a2c1..b71588b 100644 --- a/src/layouts/AppLayout.tsx +++ b/src/layouts/AppLayout.tsx @@ -1,11 +1,16 @@ -import { useState, useCallback } from "react" -import { Navigate, Outlet } from "react-router-dom" +import { useState, useCallback, useEffect, useMemo, useRef } from "react" +import { Navigate, Outlet, useLocation } from "react-router-dom" import { Sidebar } from "../components/sidebar/Sidebar" import { Topbar } from "../components/topbar/Topbar" export function AppLayout() { const [sidebarOpen, setSidebarOpen] = useState(false) const [sidebarCollapsed, setSidebarCollapsed] = useState(false) + const mainRef = useRef(null) + const previousRouteKeyRef = useRef("") + const location = useLocation() + const scrollStoragePrefix = "app:scroll:" + const routeKey = useMemo(() => `${location.pathname}${location.search}`, [location.pathname, location.search]) const token = localStorage.getItem("access_token") if (!token) { @@ -20,6 +25,39 @@ export function AppLayout() { setSidebarOpen(false) }, []) + useEffect(() => { + const container = mainRef.current + if (!container) return + + const saveScroll = (key: string) => { + sessionStorage.setItem(`${scrollStoragePrefix}${key}`, String(container.scrollTop || 0)) + } + + const previousKey = previousRouteKeyRef.current + if (previousKey && previousKey !== routeKey) { + saveScroll(previousKey) + } + previousRouteKeyRef.current = routeKey + + const restoreRaw = sessionStorage.getItem(`${scrollStoragePrefix}${routeKey}`) + const restoreTop = restoreRaw ? Number(restoreRaw) : 0 + const top = Number.isFinite(restoreTop) && restoreTop > 0 ? restoreTop : 0 + requestAnimationFrame(() => { + container.scrollTo({ top, behavior: "auto" }) + }) + + const onScroll = () => saveScroll(routeKey) + const onBeforeUnload = () => saveScroll(routeKey) + container.addEventListener("scroll", onScroll, { passive: true }) + window.addEventListener("beforeunload", onBeforeUnload) + + return () => { + saveScroll(routeKey) + container.removeEventListener("scroll", onScroll) + window.removeEventListener("beforeunload", onBeforeUnload) + } + }, [routeKey]) + return (
-
+