diff --git a/src/PageManager.tsx b/src/PageManager.tsx index 5922cdec..b8b5af9a 100644 --- a/src/PageManager.tsx +++ b/src/PageManager.tsx @@ -4,7 +4,17 @@ import { Separator } from '@/components/ui/separator' import { cn } from '@/lib/utils' import NoteListPage from '@/pages/primary/NoteListPage' import HomePage from '@/pages/secondary/HomePage' -import { cloneElement, createContext, ReactNode, useContext, useEffect, useState } from 'react' +import { TPageRef } from '@/types' +import { + cloneElement, + createContext, + createRef, + ReactNode, + RefObject, + useContext, + useEffect, + useState +} from 'react' import MePage from './pages/primary/MePage' import NotificationListPage from './pages/primary/NotificationListPage' import { useScreenSize } from './providers/ScreenSizeProvider' @@ -26,13 +36,20 @@ type TSecondaryPageContext = { type TStackItem = { index: number url: string - component: React.ReactNode | null + component: React.ReactElement | null + ref: RefObject | null +} + +const PRIMARY_PAGE_REF_MAP = { + home: createRef(), + notifications: createRef(), + me: createRef() } const PRIMARY_PAGE_MAP = { - home: , - notifications: , - me: + home: , + notifications: , + me: } const PrimaryPageContext = createContext(undefined) @@ -111,13 +128,22 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { const topItem = newStack[newStack.length - 1] as TStackItem | undefined if (!topItem) { // Create a new stack item if it's not exist (e.g. when the user refreshes the page, the stack will be empty) - const newComponent = findAndCreateComponent(state.url, state.index) - if (newComponent) { - newStack.push({ index: state.index, url: state.url, component: newComponent }) + const { component, ref } = findAndCreateComponent(state.url, state.index) + if (component) { + newStack.push({ + index: state.index, + url: state.url, + component, + ref + }) } } else if (!topItem.component) { // Load the component if it's not cached - topItem.component = findAndCreateComponent(topItem.url, state.index) + const { component, ref } = findAndCreateComponent(topItem.url, state.index) + if (component) { + topItem.component = component + topItem.ref = ref + } } if (newStack.length === 0) { window.history.replaceState(null, '', '/') @@ -139,6 +165,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { setPrimaryPages((prev) => [...prev, { name: page, element: PRIMARY_PAGE_MAP[page] }]) } setCurrentPrimaryPage(page) + PRIMARY_PAGE_REF_MAP[page].current?.scrollToTop() if (isSmallScreen) { clearSecondaryPages() } @@ -146,7 +173,13 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { const pushSecondaryPage = (url: string, index?: number) => { setSecondaryStack((prevStack) => { - if (isCurrentPage(prevStack, url)) return prevStack + if (isCurrentPage(prevStack, url)) { + const currentItem = prevStack[prevStack.length - 1] + if (currentItem?.ref?.current) { + currentItem.ref.current.scrollToTop() + } + return prevStack + } const { newStack, newItem } = pushNewPageToStack(prevStack, url, maxStackSize, index) if (newItem) { @@ -302,10 +335,11 @@ function findAndCreateComponent(url: string, index: number) { const match = matcher(path) if (!match) continue - if (!element) return null - return cloneElement(element, { ...match.params, index } as any) + if (!element) return {} + const ref = createRef() + return { component: cloneElement(element, { ...match.params, index, ref } as any), ref } } - return null + return {} } function pushNewPageToStack( @@ -317,10 +351,10 @@ function pushNewPageToStack( const currentItem = stack[stack.length - 1] const currentIndex = specificIndex ?? (currentItem ? currentItem.index + 1 : 0) - const component = findAndCreateComponent(url, currentIndex) + const { component, ref } = findAndCreateComponent(url, currentIndex) if (!component) return { newStack: stack, newItem: null } - const newItem = { component, url, index: currentIndex } + const newItem = { component, ref, url, index: currentIndex } const newStack = [...stack, newItem] const lastCachedIndex = newStack.findIndex((stack) => stack.component) // Clear the oldest cached component if there are too many cached components diff --git a/src/components/BottomNavigationBar/BottomNavigationBarItem.tsx b/src/components/BottomNavigationBar/BottomNavigationBarItem.tsx index dce83d32..1ae8d428 100644 --- a/src/components/BottomNavigationBar/BottomNavigationBarItem.tsx +++ b/src/components/BottomNavigationBar/BottomNavigationBarItem.tsx @@ -15,9 +15,8 @@ export default function BottomNavigationBarItem({