refactor: page manager
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import Sidebar from '@/components/Sidebar'
|
import Sidebar from '@/components/Sidebar'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import NoteListPage from '@/pages/primary/NoteListPage'
|
|
||||||
import { CurrentRelaysProvider } from '@/providers/CurrentRelaysProvider'
|
import { CurrentRelaysProvider } from '@/providers/CurrentRelaysProvider'
|
||||||
import { TPageRef } from '@/types'
|
import { TPageRef } from '@/types'
|
||||||
import {
|
import {
|
||||||
@@ -19,23 +18,14 @@ import BottomNavigationBar from './components/BottomNavigationBar'
|
|||||||
import CreateWalletGuideToast from './components/CreateWalletGuideToast'
|
import CreateWalletGuideToast from './components/CreateWalletGuideToast'
|
||||||
import TooManyRelaysAlertDialog from './components/TooManyRelaysAlertDialog'
|
import TooManyRelaysAlertDialog from './components/TooManyRelaysAlertDialog'
|
||||||
import { normalizeUrl } from './lib/url'
|
import { normalizeUrl } from './lib/url'
|
||||||
import BookmarkPage from './pages/primary/BookmarkPage'
|
|
||||||
import ExplorePage from './pages/primary/ExplorePage'
|
|
||||||
import MePage from './pages/primary/MePage'
|
|
||||||
import NotificationListPage from './pages/primary/NotificationListPage'
|
|
||||||
import ProfilePage from './pages/primary/ProfilePage'
|
|
||||||
import RelayPage from './pages/primary/RelayPage'
|
|
||||||
import SearchPage from './pages/primary/SearchPage'
|
|
||||||
import SettingsPage from './pages/primary/SettingsPage'
|
|
||||||
import { NotificationProvider } from './providers/NotificationProvider'
|
import { NotificationProvider } from './providers/NotificationProvider'
|
||||||
import { useScreenSize } from './providers/ScreenSizeProvider'
|
import { useScreenSize } from './providers/ScreenSizeProvider'
|
||||||
import { useTheme } from './providers/ThemeProvider'
|
import { useTheme } from './providers/ThemeProvider'
|
||||||
import { useUserPreferences } from './providers/UserPreferencesProvider'
|
import { useUserPreferences } from './providers/UserPreferencesProvider'
|
||||||
import { routes } from './routes'
|
import { PRIMARY_PAGE_MAP, PRIMARY_PAGE_REF_MAP, TPrimaryPageName } from './routes/primary'
|
||||||
|
import { SECONDARY_ROUTES } from './routes/secondary'
|
||||||
import modalManager from './services/modal-manager.service'
|
import modalManager from './services/modal-manager.service'
|
||||||
|
|
||||||
export type TPrimaryPageName = keyof typeof PRIMARY_PAGE_MAP
|
|
||||||
|
|
||||||
type TPrimaryPageContext = {
|
type TPrimaryPageContext = {
|
||||||
navigate: (page: TPrimaryPageName, props?: object) => void
|
navigate: (page: TPrimaryPageName, props?: object) => void
|
||||||
current: TPrimaryPageName | null
|
current: TPrimaryPageName | null
|
||||||
@@ -51,34 +41,10 @@ type TSecondaryPageContext = {
|
|||||||
type TStackItem = {
|
type TStackItem = {
|
||||||
index: number
|
index: number
|
||||||
url: string
|
url: string
|
||||||
component: React.ReactElement | null
|
element: React.ReactElement | null
|
||||||
ref: RefObject<TPageRef> | null
|
ref: RefObject<TPageRef> | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRIMARY_PAGE_REF_MAP = {
|
|
||||||
home: createRef<TPageRef>(),
|
|
||||||
explore: createRef<TPageRef>(),
|
|
||||||
notifications: createRef<TPageRef>(),
|
|
||||||
me: createRef<TPageRef>(),
|
|
||||||
profile: createRef<TPageRef>(),
|
|
||||||
relay: createRef<TPageRef>(),
|
|
||||||
search: createRef<TPageRef>(),
|
|
||||||
bookmark: createRef<TPageRef>(),
|
|
||||||
settings: createRef<TPageRef>()
|
|
||||||
}
|
|
||||||
|
|
||||||
const PRIMARY_PAGE_MAP = {
|
|
||||||
home: <NoteListPage ref={PRIMARY_PAGE_REF_MAP.home} />,
|
|
||||||
explore: <ExplorePage ref={PRIMARY_PAGE_REF_MAP.explore} />,
|
|
||||||
notifications: <NotificationListPage ref={PRIMARY_PAGE_REF_MAP.notifications} />,
|
|
||||||
me: <MePage ref={PRIMARY_PAGE_REF_MAP.me} />,
|
|
||||||
profile: <ProfilePage ref={PRIMARY_PAGE_REF_MAP.profile} />,
|
|
||||||
relay: <RelayPage ref={PRIMARY_PAGE_REF_MAP.relay} />,
|
|
||||||
search: <SearchPage ref={PRIMARY_PAGE_REF_MAP.search} />,
|
|
||||||
bookmark: <BookmarkPage ref={PRIMARY_PAGE_REF_MAP.bookmark} />,
|
|
||||||
settings: <SettingsPage ref={PRIMARY_PAGE_REF_MAP.settings} />
|
|
||||||
}
|
|
||||||
|
|
||||||
const PrimaryPageContext = createContext<TPrimaryPageContext | undefined>(undefined)
|
const PrimaryPageContext = createContext<TPrimaryPageContext | undefined>(undefined)
|
||||||
|
|
||||||
const SecondaryPageContext = createContext<TSecondaryPageContext | undefined>(undefined)
|
const SecondaryPageContext = createContext<TSecondaryPageContext | undefined>(undefined)
|
||||||
@@ -203,20 +169,20 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||||||
const topItem = newStack[newStack.length - 1] as TStackItem | undefined
|
const topItem = newStack[newStack.length - 1] as TStackItem | undefined
|
||||||
if (!topItem) {
|
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)
|
// Create a new stack item if it's not exist (e.g. when the user refreshes the page, the stack will be empty)
|
||||||
const { component, ref } = findAndCreateComponent(state.url, state.index)
|
const { element, ref } = findAndCloneElement(state.url, state.index)
|
||||||
if (component) {
|
if (element) {
|
||||||
newStack.push({
|
newStack.push({
|
||||||
index: state.index,
|
index: state.index,
|
||||||
url: state.url,
|
url: state.url,
|
||||||
component,
|
element,
|
||||||
ref
|
ref
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (!topItem.component) {
|
} else if (!topItem.element) {
|
||||||
// Load the component if it's not cached
|
// Load the element if it's not cached
|
||||||
const { component, ref } = findAndCreateComponent(topItem.url, state.index)
|
const { element, ref } = findAndCloneElement(topItem.url, state.index)
|
||||||
if (component) {
|
if (element) {
|
||||||
topItem.component = component
|
topItem.element = element
|
||||||
topItem.ref = ref
|
topItem.ref = ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,7 +282,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||||||
display: index === secondaryStack.length - 1 ? 'block' : 'none'
|
display: index === secondaryStack.length - 1 ? 'block' : 'none'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.component}
|
{item.element}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{primaryPages.map(({ name, element, props }) => (
|
{primaryPages.map(({ name, element, props }) => (
|
||||||
@@ -373,7 +339,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||||||
display: index === secondaryStack.length - 1 ? 'block' : 'none'
|
display: index === secondaryStack.length - 1 ? 'block' : 'none'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.component}
|
{item.element}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{primaryPages.map(({ name, element, props }) => (
|
{primaryPages.map(({ name, element, props }) => (
|
||||||
@@ -464,7 +430,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|||||||
className="flex flex-col h-full w-full"
|
className="flex flex-col h-full w-full"
|
||||||
style={{ display: index === secondaryStack.length - 1 ? 'block' : 'none' }}
|
style={{ display: index === secondaryStack.length - 1 ? 'block' : 'none' }}
|
||||||
>
|
>
|
||||||
{item.component}
|
{item.element}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -516,15 +482,15 @@ function isCurrentPage(stack: TStackItem[], url: string) {
|
|||||||
return currentPage.url === url
|
return currentPage.url === url
|
||||||
}
|
}
|
||||||
|
|
||||||
function findAndCreateComponent(url: string, index: number) {
|
function findAndCloneElement(url: string, index: number) {
|
||||||
const path = url.split('?')[0].split('#')[0]
|
const path = url.split('?')[0].split('#')[0]
|
||||||
for (const { matcher, element } of routes) {
|
for (const { matcher, element } of SECONDARY_ROUTES) {
|
||||||
const match = matcher(path)
|
const match = matcher(path)
|
||||||
if (!match) continue
|
if (!match) continue
|
||||||
|
|
||||||
if (!element) return {}
|
if (!element) return {}
|
||||||
const ref = createRef<TPageRef>()
|
const ref = createRef<TPageRef>()
|
||||||
return { component: cloneElement(element, { ...match.params, index, ref } as any), ref }
|
return { element: cloneElement(element, { ...match.params, index, ref } as any), ref }
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
@@ -538,15 +504,15 @@ function pushNewPageToStack(
|
|||||||
const currentItem = stack[stack.length - 1]
|
const currentItem = stack[stack.length - 1]
|
||||||
const currentIndex = specificIndex ?? (currentItem ? currentItem.index + 1 : 0)
|
const currentIndex = specificIndex ?? (currentItem ? currentItem.index + 1 : 0)
|
||||||
|
|
||||||
const { component, ref } = findAndCreateComponent(url, currentIndex)
|
const { element, ref } = findAndCloneElement(url, currentIndex)
|
||||||
if (!component) return { newStack: stack, newItem: null }
|
if (!element) return { newStack: stack, newItem: null }
|
||||||
|
|
||||||
const newItem = { component, ref, url, index: currentIndex }
|
const newItem = { element, ref, url, index: currentIndex }
|
||||||
const newStack = [...stack, newItem]
|
const newStack = [...stack, newItem]
|
||||||
const lastCachedIndex = newStack.findIndex((stack) => stack.component)
|
const lastCachedIndex = newStack.findIndex((stack) => stack.element)
|
||||||
// Clear the oldest cached component if there are too many cached components
|
// Clear the oldest cached element if there are too many cached elements
|
||||||
if (newStack.length - lastCachedIndex > maxStackSize) {
|
if (newStack.length - lastCachedIndex > maxStackSize) {
|
||||||
newStack[lastCachedIndex].component = null
|
newStack[lastCachedIndex].element = null
|
||||||
}
|
}
|
||||||
return { newStack, newItem }
|
return { newStack, newItem }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import ScrollToTopButton from '@/components/ScrollToTopButton'
|
import ScrollToTopButton from '@/components/ScrollToTopButton'
|
||||||
import { Titlebar } from '@/components/Titlebar'
|
import { Titlebar } from '@/components/Titlebar'
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area'
|
import { ScrollArea } from '@/components/ui/scroll-area'
|
||||||
import { TPrimaryPageName, usePrimaryPage } from '@/PageManager'
|
import { usePrimaryPage } from '@/PageManager'
|
||||||
import { DeepBrowsingProvider } from '@/providers/DeepBrowsingProvider'
|
import { DeepBrowsingProvider } from '@/providers/DeepBrowsingProvider'
|
||||||
import { useNostr } from '@/providers/NostrProvider'
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
|
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
|
||||||
|
import { TPrimaryPageName } from '@/routes/primary'
|
||||||
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react'
|
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react'
|
||||||
|
|
||||||
const PrimaryPageLayout = forwardRef(
|
const PrimaryPageLayout = forwardRef(
|
||||||
|
|||||||
@@ -2,24 +2,19 @@ import BookmarkList from '@/components/BookmarkList'
|
|||||||
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
||||||
import { TPageRef } from '@/types'
|
import { TPageRef } from '@/types'
|
||||||
import { BookmarkIcon } from 'lucide-react'
|
import { BookmarkIcon } from 'lucide-react'
|
||||||
import { forwardRef, useImperativeHandle, useRef } from 'react'
|
import { forwardRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const BookmarkPage = forwardRef((_, ref) => {
|
const BookmarkPage = forwardRef<TPageRef>((_, ref) => (
|
||||||
const layoutRef = useRef<TPageRef>(null)
|
<PrimaryPageLayout
|
||||||
useImperativeHandle(ref, () => layoutRef.current)
|
pageName="bookmark"
|
||||||
|
ref={ref}
|
||||||
return (
|
titlebar={<BookmarkPageTitlebar />}
|
||||||
<PrimaryPageLayout
|
displayScrollToTopButton
|
||||||
pageName="bookmark"
|
>
|
||||||
ref={layoutRef}
|
<BookmarkList />
|
||||||
titlebar={<BookmarkPageTitlebar />}
|
</PrimaryPageLayout>
|
||||||
displayScrollToTopButton
|
))
|
||||||
>
|
|
||||||
<BookmarkList />
|
|
||||||
</PrimaryPageLayout>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
BookmarkPage.displayName = 'BookmarkPage'
|
BookmarkPage.displayName = 'BookmarkPage'
|
||||||
export default BookmarkPage
|
export default BookmarkPage
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
|
|||||||
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
||||||
import { getReplaceableEventIdentifier } from '@/lib/event'
|
import { getReplaceableEventIdentifier } from '@/lib/event'
|
||||||
import { useUserTrust } from '@/providers/UserTrustProvider'
|
import { useUserTrust } from '@/providers/UserTrustProvider'
|
||||||
|
import { TPageRef } from '@/types'
|
||||||
import { Compass, Plus } from 'lucide-react'
|
import { Compass, Plus } from 'lucide-react'
|
||||||
import { NostrEvent } from 'nostr-tools'
|
import { NostrEvent } from 'nostr-tools'
|
||||||
import { forwardRef, useCallback, useMemo, useState } from 'react'
|
import { forwardRef, useCallback, useMemo, useState } from 'react'
|
||||||
@@ -14,7 +15,7 @@ import { useTranslation } from 'react-i18next'
|
|||||||
|
|
||||||
type TExploreTabs = 'following' | 'explore' | 'reviews'
|
type TExploreTabs = 'following' | 'explore' | 'reviews'
|
||||||
|
|
||||||
const ExplorePage = forwardRef((_, ref) => {
|
const ExplorePage = forwardRef<TPageRef>((_, ref) => {
|
||||||
const { hideUntrustedNotes } = useUserTrust()
|
const { hideUntrustedNotes } = useUserTrust()
|
||||||
const [tab, setTab] = useState<TExploreTabs>('explore')
|
const [tab, setTab] = useState<TExploreTabs>('explore')
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { toBookmarks, toProfile, toRelaySettings, toSettings, toWallet } from '@
|
|||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { useSecondaryPage } from '@/PageManager'
|
import { useSecondaryPage } from '@/PageManager'
|
||||||
import { useNostr } from '@/providers/NostrProvider'
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
|
import { TPageRef } from '@/types'
|
||||||
import {
|
import {
|
||||||
ArrowDownUp,
|
ArrowDownUp,
|
||||||
Bookmark,
|
Bookmark,
|
||||||
@@ -25,7 +26,7 @@ import {
|
|||||||
import { forwardRef, HTMLProps, useState } from 'react'
|
import { forwardRef, HTMLProps, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const MePage = forwardRef((_, ref) => {
|
const MePage = forwardRef<TPageRef>((_, ref) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { push } = useSecondaryPage()
|
const { push } = useSecondaryPage()
|
||||||
const { pubkey } = useNostr()
|
const { pubkey } = useNostr()
|
||||||
|
|||||||
@@ -24,14 +24,15 @@ import FeedButton from './FeedButton'
|
|||||||
import FollowingFeed from './FollowingFeed'
|
import FollowingFeed from './FollowingFeed'
|
||||||
import RelaysFeed from './RelaysFeed'
|
import RelaysFeed from './RelaysFeed'
|
||||||
|
|
||||||
const NoteListPage = forwardRef((_, ref) => {
|
const NoteListPage = forwardRef<TPageRef>((_, ref) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { addRelayUrls, removeRelayUrls } = useCurrentRelays()
|
const { addRelayUrls, removeRelayUrls } = useCurrentRelays()
|
||||||
const layoutRef = useRef<TPageRef>(null)
|
const layoutRef = useRef<TPageRef>(null)
|
||||||
const { pubkey } = useNostr()
|
const { pubkey } = useNostr()
|
||||||
const { feedInfo, relayUrls, isReady, switchFeed } = useFeed()
|
const { feedInfo, relayUrls, isReady, switchFeed } = useFeed()
|
||||||
const [showRelayDetails, setShowRelayDetails] = useState(false)
|
const [showRelayDetails, setShowRelayDetails] = useState(false)
|
||||||
useImperativeHandle(ref, () => layoutRef.current)
|
|
||||||
|
useImperativeHandle(ref, () => layoutRef.current as TPageRef)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (layoutRef.current) {
|
if (layoutRef.current) {
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import HideUntrustedContentButton from '@/components/HideUntrustedContentButton'
|
|||||||
import NotificationList from '@/components/NotificationList'
|
import NotificationList from '@/components/NotificationList'
|
||||||
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
||||||
import { usePrimaryPage } from '@/PageManager'
|
import { usePrimaryPage } from '@/PageManager'
|
||||||
|
import { TPageRef } from '@/types'
|
||||||
import { Bell } from 'lucide-react'
|
import { Bell } from 'lucide-react'
|
||||||
import { forwardRef, useEffect, useRef } from 'react'
|
import { forwardRef, useEffect, useRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const NotificationListPage = forwardRef((_, ref) => {
|
const NotificationListPage = forwardRef<TPageRef>((_, ref) => {
|
||||||
const { current } = usePrimaryPage()
|
const { current } = usePrimaryPage()
|
||||||
const firstRenderRef = useRef(true)
|
const firstRenderRef = useRef(true)
|
||||||
const notificationListRef = useRef<{ refresh: () => void }>(null)
|
const notificationListRef = useRef<{ refresh: () => void }>(null)
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import Profile from '@/components/Profile'
|
import Profile from '@/components/Profile'
|
||||||
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
||||||
import { useNostr } from '@/providers/NostrProvider'
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
|
import { TPageRef } from '@/types'
|
||||||
import { UserRound } from 'lucide-react'
|
import { UserRound } from 'lucide-react'
|
||||||
import { forwardRef } from 'react'
|
import { forwardRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const ProfilePage = forwardRef((_, ref) => {
|
const ProfilePage = forwardRef<TPageRef>((_, ref) => {
|
||||||
const { pubkey } = useNostr()
|
const { pubkey } = useNostr()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import Relay from '@/components/Relay'
|
import Relay from '@/components/Relay'
|
||||||
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
||||||
import { normalizeUrl, simplifyUrl } from '@/lib/url'
|
import { normalizeUrl, simplifyUrl } from '@/lib/url'
|
||||||
|
import { TPageRef } from '@/types'
|
||||||
import { Server } from 'lucide-react'
|
import { Server } from 'lucide-react'
|
||||||
import { forwardRef, useMemo } from 'react'
|
import { forwardRef, useMemo } from 'react'
|
||||||
|
|
||||||
const RelayPage = forwardRef(({ url }: { url?: string }, ref) => {
|
const RelayPage = forwardRef<TPageRef>(({ url }: { url?: string }, ref) => {
|
||||||
const normalizedUrl = useMemo(() => (url ? normalizeUrl(url) : undefined), [url])
|
const normalizedUrl = useMemo(() => (url ? normalizeUrl(url) : undefined), [url])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import SearchBar, { TSearchBarRef } from '@/components/SearchBar'
|
|||||||
import SearchResult from '@/components/SearchResult'
|
import SearchResult from '@/components/SearchResult'
|
||||||
import PrimaryPageLayout, { TPrimaryPageLayoutRef } from '@/layouts/PrimaryPageLayout'
|
import PrimaryPageLayout, { TPrimaryPageLayoutRef } from '@/layouts/PrimaryPageLayout'
|
||||||
import { usePrimaryPage } from '@/PageManager'
|
import { usePrimaryPage } from '@/PageManager'
|
||||||
import { TSearchParams } from '@/types'
|
import { TPageRef, TSearchParams } from '@/types'
|
||||||
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
|
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
|
||||||
|
|
||||||
const SearchPage = forwardRef((_, ref) => {
|
const SearchPage = forwardRef<TPageRef>((_, ref) => {
|
||||||
const { current, display } = usePrimaryPage()
|
const { current, display } = usePrimaryPage()
|
||||||
const [input, setInput] = useState('')
|
const [input, setInput] = useState('')
|
||||||
const [searchParams, setSearchParams] = useState<TSearchParams | null>(null)
|
const [searchParams, setSearchParams] = useState<TSearchParams | null>(null)
|
||||||
|
|||||||
@@ -2,24 +2,19 @@ import Settings from '@/components/Settings'
|
|||||||
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
||||||
import { TPageRef } from '@/types'
|
import { TPageRef } from '@/types'
|
||||||
import { SettingsIcon } from 'lucide-react'
|
import { SettingsIcon } from 'lucide-react'
|
||||||
import { forwardRef, useImperativeHandle, useRef } from 'react'
|
import { forwardRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const SettingsPage = forwardRef((_, ref) => {
|
const SettingsPage = forwardRef<TPageRef>((_, ref) => (
|
||||||
const layoutRef = useRef<TPageRef>(null)
|
<PrimaryPageLayout
|
||||||
useImperativeHandle(ref, () => layoutRef.current)
|
pageName="settings"
|
||||||
|
ref={ref}
|
||||||
return (
|
titlebar={<SettingsPageTitlebar />}
|
||||||
<PrimaryPageLayout
|
displayScrollToTopButton
|
||||||
pageName="settings"
|
>
|
||||||
ref={layoutRef}
|
<Settings />
|
||||||
titlebar={<SettingsPageTitlebar />}
|
</PrimaryPageLayout>
|
||||||
displayScrollToTopButton
|
))
|
||||||
>
|
|
||||||
<Settings />
|
|
||||||
</PrimaryPageLayout>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
SettingsPage.displayName = 'SettingsPage'
|
SettingsPage.displayName = 'SettingsPage'
|
||||||
export default SettingsPage
|
export default SettingsPage
|
||||||
|
|
||||||
|
|||||||
46
src/routes/primary.tsx
Normal file
46
src/routes/primary.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import BookmarkPage from '@/pages/primary/BookmarkPage'
|
||||||
|
import ExplorePage from '@/pages/primary/ExplorePage'
|
||||||
|
import MePage from '@/pages/primary/MePage'
|
||||||
|
import NoteListPage from '@/pages/primary/NoteListPage'
|
||||||
|
import NotificationListPage from '@/pages/primary/NotificationListPage'
|
||||||
|
import ProfilePage from '@/pages/primary/ProfilePage'
|
||||||
|
import RelayPage from '@/pages/primary/RelayPage'
|
||||||
|
import SearchPage from '@/pages/primary/SearchPage'
|
||||||
|
import SettingsPage from '@/pages/primary/SettingsPage'
|
||||||
|
import { TPageRef } from '@/types'
|
||||||
|
import { createRef, ForwardRefExoticComponent, RefAttributes } from 'react'
|
||||||
|
|
||||||
|
type RouteConfig = {
|
||||||
|
key: string
|
||||||
|
component: ForwardRefExoticComponent<RefAttributes<TPageRef>>
|
||||||
|
}
|
||||||
|
|
||||||
|
const PRIMARY_ROUTE_CONFIGS: RouteConfig[] = [
|
||||||
|
{ key: 'home', component: NoteListPage },
|
||||||
|
{ key: 'explore', component: ExplorePage },
|
||||||
|
{ key: 'notifications', component: NotificationListPage },
|
||||||
|
{ key: 'me', component: MePage },
|
||||||
|
{ key: 'profile', component: ProfilePage },
|
||||||
|
{ key: 'relay', component: RelayPage },
|
||||||
|
{ key: 'search', component: SearchPage },
|
||||||
|
{ key: 'bookmark', component: BookmarkPage },
|
||||||
|
{ key: 'settings', component: SettingsPage }
|
||||||
|
]
|
||||||
|
|
||||||
|
export const PRIMARY_PAGE_REF_MAP = PRIMARY_ROUTE_CONFIGS.reduce(
|
||||||
|
(acc, { key }) => {
|
||||||
|
acc[key] = createRef<TPageRef>()
|
||||||
|
return acc
|
||||||
|
},
|
||||||
|
{} as Record<string, React.RefObject<TPageRef>>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const PRIMARY_PAGE_MAP = PRIMARY_ROUTE_CONFIGS.reduce(
|
||||||
|
(acc, { key, component: Component }) => {
|
||||||
|
acc[key] = <Component ref={PRIMARY_PAGE_REF_MAP[key]} />
|
||||||
|
return acc
|
||||||
|
},
|
||||||
|
{} as Record<string, JSX.Element>
|
||||||
|
)
|
||||||
|
|
||||||
|
export type TPrimaryPageName = keyof typeof PRIMARY_PAGE_MAP
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
|
import AppearanceSettingsPage from '@/pages/secondary/AppearanceSettingsPage'
|
||||||
|
import BookmarkPage from '@/pages/secondary/BookmarkPage'
|
||||||
|
import FollowingListPage from '@/pages/secondary/FollowingListPage'
|
||||||
|
import GeneralSettingsPage from '@/pages/secondary/GeneralSettingsPage'
|
||||||
|
import MuteListPage from '@/pages/secondary/MuteListPage'
|
||||||
|
import NoteListPage from '@/pages/secondary/NoteListPage'
|
||||||
|
import NotePage from '@/pages/secondary/NotePage'
|
||||||
|
import OthersRelaySettingsPage from '@/pages/secondary/OthersRelaySettingsPage'
|
||||||
|
import PostSettingsPage from '@/pages/secondary/PostSettingsPage'
|
||||||
|
import ProfileEditorPage from '@/pages/secondary/ProfileEditorPage'
|
||||||
|
import ProfileListPage from '@/pages/secondary/ProfileListPage'
|
||||||
|
import ProfilePage from '@/pages/secondary/ProfilePage'
|
||||||
|
import RelayPage from '@/pages/secondary/RelayPage'
|
||||||
|
import RelayReviewsPage from '@/pages/secondary/RelayReviewsPage'
|
||||||
|
import RelaySettingsPage from '@/pages/secondary/RelaySettingsPage'
|
||||||
|
import RizfulPage from '@/pages/secondary/RizfulPage'
|
||||||
|
import SearchPage from '@/pages/secondary/SearchPage'
|
||||||
|
import SettingsPage from '@/pages/secondary/SettingsPage'
|
||||||
|
import TranslationPage from '@/pages/secondary/TranslationPage'
|
||||||
|
import WalletPage from '@/pages/secondary/WalletPage'
|
||||||
import { match } from 'path-to-regexp'
|
import { match } from 'path-to-regexp'
|
||||||
import { isValidElement } from 'react'
|
import { isValidElement } from 'react'
|
||||||
import AppearanceSettingsPage from './pages/secondary/AppearanceSettingsPage'
|
|
||||||
import BookmarkPage from './pages/secondary/BookmarkPage'
|
|
||||||
import FollowingListPage from './pages/secondary/FollowingListPage'
|
|
||||||
import GeneralSettingsPage from './pages/secondary/GeneralSettingsPage'
|
|
||||||
import MuteListPage from './pages/secondary/MuteListPage'
|
|
||||||
import NoteListPage from './pages/secondary/NoteListPage'
|
|
||||||
import NotePage from './pages/secondary/NotePage'
|
|
||||||
import OthersRelaySettingsPage from './pages/secondary/OthersRelaySettingsPage'
|
|
||||||
import PostSettingsPage from './pages/secondary/PostSettingsPage'
|
|
||||||
import ProfileEditorPage from './pages/secondary/ProfileEditorPage'
|
|
||||||
import ProfileListPage from './pages/secondary/ProfileListPage'
|
|
||||||
import ProfilePage from './pages/secondary/ProfilePage'
|
|
||||||
import RelayPage from './pages/secondary/RelayPage'
|
|
||||||
import RelayReviewsPage from './pages/secondary/RelayReviewsPage'
|
|
||||||
import RelaySettingsPage from './pages/secondary/RelaySettingsPage'
|
|
||||||
import RizfulPage from './pages/secondary/RizfulPage'
|
|
||||||
import SearchPage from './pages/secondary/SearchPage'
|
|
||||||
import SettingsPage from './pages/secondary/SettingsPage'
|
|
||||||
import TranslationPage from './pages/secondary/TranslationPage'
|
|
||||||
import WalletPage from './pages/secondary/WalletPage'
|
|
||||||
|
|
||||||
const ROUTES = [
|
// Right column routes
|
||||||
|
const SECONDARY_ROUTE_CONFIGS = [
|
||||||
{ path: '/notes', element: <NoteListPage /> },
|
{ path: '/notes', element: <NoteListPage /> },
|
||||||
{ path: '/notes/:id', element: <NotePage /> },
|
{ path: '/notes/:id', element: <NotePage /> },
|
||||||
{ path: '/users', element: <ProfileListPage /> },
|
{ path: '/users', element: <ProfileListPage /> },
|
||||||
@@ -44,7 +45,7 @@ const ROUTES = [
|
|||||||
{ path: '/bookmarks', element: <BookmarkPage /> }
|
{ path: '/bookmarks', element: <BookmarkPage /> }
|
||||||
]
|
]
|
||||||
|
|
||||||
export const routes = ROUTES.map(({ path, element }) => ({
|
export const SECONDARY_ROUTES = SECONDARY_ROUTE_CONFIGS.map(({ path, element }) => ({
|
||||||
path,
|
path,
|
||||||
element: isValidElement(element) ? element : null,
|
element: isValidElement(element) ? element : null,
|
||||||
matcher: match(path)
|
matcher: match(path)
|
||||||
Reference in New Issue
Block a user