From d14e2ae8db142e11dadda616b61487062edd1459 Mon Sep 17 00:00:00 2001 From: rimar1337 <132627503+rimar1337@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:48:10 +0700 Subject: [PATCH] notif tabs scroll restoration --- src/routes/notifications.tsx | 69 ++++++++++++++++++++++++++++++------ src/utils/atoms.ts | 9 +++++ 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/routes/notifications.tsx b/src/routes/notifications.tsx index 94393ea..a4d99ac 100644 --- a/src/routes/notifications.tsx +++ b/src/routes/notifications.tsx @@ -4,6 +4,7 @@ import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query"; import { createFileRoute, Link, useNavigate } from "@tanstack/react-router"; import { useAtom } from "jotai"; import * as React from "react"; +import { useEffect, useLayoutEffect } from "react"; import defaultpfp from "~/../public/favicon.png"; import { Header } from "~/components/Header"; @@ -14,7 +15,12 @@ import { UniversalPostRendererATURILoader, } from "~/components/UniversalPostRenderer"; import { useAuth } from "~/providers/UnifiedAuthProvider"; -import { constellationURLAtom, imgCDNAtom, isAtTopAtom } from "~/utils/atoms"; +import { + constellationURLAtom, + imgCDNAtom, + isAtTopAtom, + notificationsScrollAtom, +} from "~/utils/atoms"; import { useInfiniteQueryAuthorFeed, useQueryConstellation, @@ -49,20 +55,42 @@ export const Route = createFileRoute("/notifications")({ }); export default function NotificationsTabs() { - const [activeTab, setActiveTab] = React.useState("mentions"); + const [notifState, setNotifState] = useAtom(notificationsScrollAtom); + const activeTab = notifState.activeTab; const [isAtTop] = useAtom(isAtTopAtom); - const scrollPositions = React.useRef>({}); - const handleValueChange = (newTab: string) => { - scrollPositions.current[activeTab] = window.scrollY; - setActiveTab(newTab); + console.log(newTab); + setNotifState((prev) => { + const wow = { + ...prev, + scrollPositions: { + ...prev.scrollPositions, + [prev.activeTab]: window.scrollY, + }, + activeTab: newTab, + }; + //console.log(wow); + return wow; + }); }; - React.useEffect(() => { - const savedY = scrollPositions.current[activeTab] ?? 0; - window.scrollTo(0, savedY); - }, [activeTab]); + useLayoutEffect(() => { + return () => { + setNotifState((prev) => { + const wow = { + ...prev, + scrollPositions: { + ...prev.scrollPositions, + [activeTab]: window.scrollY, + }, + }; + //console.log(wow); + return wow; + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return ( { + const savedY = notifState.scrollPositions[activeTab] ?? 0; + window.scrollTo(0, savedY); + }, [activeTab, notifState.scrollPositions]); + if (isLoading) return ; if (isError) return ; @@ -200,6 +235,13 @@ function FollowsTab() { ); }, [infiniteFollowsData]); + const [notifState] = useAtom(notificationsScrollAtom); + const activeTab = notifState.activeTab; + useEffect(() => { + const savedY = notifState.scrollPositions[activeTab] ?? 0; + window.scrollTo(0, savedY); + }, [activeTab, notifState.scrollPositions]); + if (isLoading) return ; if (isError) return ; @@ -253,6 +295,13 @@ function PostInteractionsTab() { [postsData] ); + const [notifState] = useAtom(notificationsScrollAtom); + const activeTab = notifState.activeTab; + useEffect(() => { + const savedY = notifState.scrollPositions[activeTab] ?? 0; + window.scrollTo(0, savedY); + }, [activeTab, notifState.scrollPositions]); + return ( <> {posts.map((m) => ( diff --git a/src/utils/atoms.ts b/src/utils/atoms.ts index 564e24a..e5e5c4f 100644 --- a/src/utils/atoms.ts +++ b/src/utils/atoms.ts @@ -21,6 +21,15 @@ export const feedScrollPositionsAtom = atomWithStorage>( {} ); +type NotificationsScrollState = { + activeTab: string; + scrollPositions: Record; +}; +export const notificationsScrollAtom = atom({ + activeTab: "mentions", + scrollPositions: {}, +}); + export const likedPostsAtom = atomWithStorage>( "likedPosts", {} -- 2.51.2