Skip to content

Commit

Permalink
refactor: update routes of popup (#11630)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed May 16, 2024
1 parent 01d5084 commit 2a729e7
Show file tree
Hide file tree
Showing 45 changed files with 229 additions and 317 deletions.
201 changes: 87 additions & 114 deletions packages/mask/popups/Popup.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { PageUIProvider, PersonaContext } from '@masknet/shared'
import { MaskMessages, PopupModalRoutes, PopupRoutes as PopupPaths } from '@masknet/shared-base'
import { MaskMessages, PopupModalRoutes, PopupRoutes } from '@masknet/shared-base'
import { PopupSnackbarProvider } from '@masknet/theme'
import { EVMWeb3ContextProvider } from '@masknet/web3-hooks-base'
import { ProviderType } from '@masknet/web3-shared-evm'
import { Box } from '@mui/material'
import { Suspense, lazy, memo, useEffect, useMemo, useState, type ReactNode } from 'react'
import { Suspense, memo, useEffect, useMemo, useState, type ReactNode } from 'react'
import { useIdleTimer } from 'react-idle-timer'
import { HashRouter, Navigate, Route, Routes, useNavigate, useSearchParams } from 'react-router-dom'
import {
createHashRouter,
Navigate,
Outlet,
Route,
RouterProvider,
Routes,
useNavigate,
useSearchParams,
} from 'react-router-dom'
import { usePopupTheme } from './hooks/usePopupTheme.js'
import Services from '#services'
import { LoadingPlaceholder } from './components/LoadingPlaceholder/index.js'
Expand Down Expand Up @@ -36,113 +45,87 @@ import { UserContext, queryPersistOptions } from '../shared-ui/index.js'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { queryClient } from '@masknet/shared-base-ui'

const Wallet = lazy(() => import(/* webpackPreload: true */ './pages/Wallet/index.js'))
const Personas = lazy(() => import(/* webpackMode: 'eager' */ './pages/Personas/index.js'))
const RequestPermissionPage = lazy(() => import('./pages/RequestPermission/index.js'))
const Contacts = lazy(() => import('./pages/Friends/index.js'))
const Settings = lazy(() => import('./pages/Settings/index.js'))
import { PersonaFrame, personaRoute } from './pages/Personas/index.js'
import { WalletFrame, walletRoutes } from './pages/Wallet/index.js'
import { ContactsFrame, contactsRoutes } from './pages/Friends/index.js'

const personaInitialState = {
queryOwnedPersonaInformation: Services.Identity.queryOwnedPersonaInformation,
queryPersonaAvatarLastUpdateTime: Services.Identity.getPersonaAvatarLastUpdateTime,
queryPersonaAvatar: Services.Identity.getPersonaAvatar,
}
const PopupRoutes = memo(function PopupRoutes() {

const pending = (
<Box height="100vh" display="flex">
<LoadingPlaceholder />
</Box>
)
const routedModals = (
<>
<Route path={PopupModalRoutes.verifyBackupPassword} element={wrapModal(<VerifyBackupPasswordModal />)} />
<Route path={PopupModalRoutes.SetBackupPassword} element={wrapModal(<SetBackupPasswordModal />)} />
<Route path={PopupModalRoutes.PersonaRename} element={wrapModal(<PersonaRenameModal />)} />
<Route path={PopupModalRoutes.PersonaSettings} element={wrapModal(<PersonaSettingModal />)} />
<Route path={PopupModalRoutes.SwitchPersona} element={wrapModal(<SwitchPersonaModal />)} />
<Route path={PopupModalRoutes.ChooseCurrency} element={wrapModal(<ChooseCurrencyModal />)} />
<Route path={PopupModalRoutes.ChooseNetwork} element={wrapModal(<ChooseNetworkModal />)} />
<Route path={PopupModalRoutes.SwitchWallet} element={wrapModal(<SwitchWallet />)} />
<Route path={PopupModalRoutes.ConnectSocialAccount} element={wrapModal(<ConnectSocialAccountModal />)} />
<Route path={PopupModalRoutes.SelectProvider} element={wrapModal(<SelectProviderModal />)} />
<Route path={PopupModalRoutes.ConnectProvider} element={wrapModal(<ConnectProviderModal />)} />
<Route path={PopupModalRoutes.WalletAccount} element={wrapModal(<WalletGroupModal />)} />
<Route path={PopupModalRoutes.SelectLanguage} element={wrapModal(<SelectLanguageModal />)} />
<Route path={PopupModalRoutes.SelectAppearance} element={wrapModal(<SelectAppearanceModal />)} />
<Route path={PopupModalRoutes.SupportedSitesModal} element={wrapModal(<SupportedSitesModal />)} />
<Route path={PopupModalRoutes.ChangeBackupPassword} element={wrapModal(<ChangeBackupPasswordModal />)} />
</>
)
const PopupShell = memo(function PopupShell() {
const [searchParams] = useSearchParams()
const modal = searchParams.get('modal')

return (
<Suspense
fallback={
<Box height="100vh" display="flex">
<LoadingPlaceholder />
</Box>
}>
<PersonaContext.Provider initialState={personaInitialState}>
<UserContext.Provider>
<RouterListener />
<Routes>
<Route path="/" element={<PopupLayout />}>
<Route path={PopupPaths.Personas + '/*'} element={withSuspense(<Personas />)} />
<Route path={PopupPaths.Wallet + '/*'} element={withSuspense(<Wallet />)} />
<Route path={PopupPaths.Friends + '/*'} element={withSuspense(<Contacts />)} />
<Route path={PopupPaths.Settings} element={withSuspense(<Settings />)} />
</Route>
const navigate = useNavigate()
useEffect(() => {
return MaskMessages.events.popupRouteUpdated.on((url) => navigate(url, { replace: true }))
}, [])

useEffect(() => {
document.getElementById('app-spinner')?.remove()
}, [])

<Route path={PopupPaths.RequestPermission} element={<RequestPermissionPage />} />
<Route path="*" element={<Navigate replace to={PopupPaths.Personas} />} />
</Routes>
{searchParams.get('modal') ?
<Routes location={searchParams.get('modal') || ''}>
<Route
path={PopupModalRoutes.verifyBackupPassword}
element={wrapModal(<VerifyBackupPasswordModal />)}
/>
<Route
path={PopupModalRoutes.SetBackupPassword}
element={wrapModal(<SetBackupPasswordModal />)}
/>
<Route path={PopupModalRoutes.PersonaRename} element={wrapModal(<PersonaRenameModal />)} />
<Route
path={PopupModalRoutes.PersonaSettings}
element={wrapModal(<PersonaSettingModal />)}
/>
<Route path={PopupModalRoutes.SwitchPersona} element={wrapModal(<SwitchPersonaModal />)} />
<Route
path={PopupModalRoutes.ChooseCurrency}
element={wrapModal(<ChooseCurrencyModal />)}
/>
<Route path={PopupModalRoutes.ChooseNetwork} element={wrapModal(<ChooseNetworkModal />)} />
<Route path={PopupModalRoutes.SwitchWallet} element={wrapModal(<SwitchWallet />)} />
<Route
path={PopupModalRoutes.ConnectSocialAccount}
element={wrapModal(<ConnectSocialAccountModal />)}
/>
<Route
path={PopupModalRoutes.SelectProvider}
element={wrapModal(<SelectProviderModal />)}
/>
<Route
path={PopupModalRoutes.ConnectProvider}
element={wrapModal(<ConnectProviderModal />)}
/>
<Route path={PopupModalRoutes.WalletAccount} element={wrapModal(<WalletGroupModal />)} />
<Route
path={PopupModalRoutes.SelectLanguage}
element={wrapModal(<SelectLanguageModal />)}
/>
<Route
path={PopupModalRoutes.SelectAppearance}
element={wrapModal(<SelectAppearanceModal />)}
/>
<Route
path={PopupModalRoutes.SupportedSitesModal}
element={wrapModal(<SupportedSitesModal />)}
/>
<Route
path={PopupModalRoutes.ChangeBackupPassword}
element={wrapModal(<ChangeBackupPasswordModal />)}
/>
</Routes>
: null}
</UserContext.Provider>
</PersonaContext.Provider>
</Suspense>
)
})
PopupRoutes.displayName = 'PopupRoutes'
function withSuspense(children: ReactNode) {
return (
<Suspense
fallback={
<Box height="100vh" display="flex">
<LoadingPlaceholder />
</Box>
}>
{children}
</Suspense>
<PersonaContext.Provider initialState={personaInitialState}>
<UserContext.Provider>
<Suspense fallback={pending}>
<Outlet />
</Suspense>
<Modals />
{modal ?
<Routes location={modal}>{routedModals}</Routes>
: null}
</UserContext.Provider>
</PersonaContext.Provider>
)
}
})

const router = createHashRouter([
{
element: <PopupShell />,
children: [
{
element: <PopupLayout />,
children: [
{ path: PopupRoutes.Personas, element: <PersonaFrame />, children: personaRoute },
{ path: PopupRoutes.Wallet, element: <WalletFrame />, children: walletRoutes },
{ path: PopupRoutes.Friends, element: <ContactsFrame />, children: contactsRoutes },
{ path: PopupRoutes.Settings, lazy: () => import('./pages/Settings/index.js') },
],
},
{ path: PopupRoutes.RequestPermission, lazy: () => import('./pages/RequestPermission/index.js') },
{ path: '*', element: <Navigate replace to={PopupRoutes.Personas} /> },
],
},
])

export default function Popups() {
const [title, setTitle] = useState('')
Expand Down Expand Up @@ -170,10 +153,11 @@ export default function Popups() {
<EVMWeb3ContextProvider providerType={ProviderType.MaskWallet}>
<PopupContext.Provider>
<PageTitleContext.Provider value={titleContext}>
<HashRouter>
<PopupRoutes />
<Modals />
</HashRouter>
<RouterProvider
router={router}
fallbackElement={pending}
future={{ v7_startTransition: true }}
/>
</PageTitleContext.Provider>
</PopupContext.Provider>
</EVMWeb3ContextProvider>
Expand All @@ -183,14 +167,3 @@ export default function Popups() {
</PersistQueryClientProvider>
)
}
function RouterListener() {
const navigate = useNavigate()
useEffect(() => {
return MaskMessages.events.popupRouteUpdated.on((url) => navigate(url, { replace: true }))
}, [])

useEffect(() => {
document.getElementById('app-spinner')?.remove()
}, [])
return null
}
5 changes: 3 additions & 2 deletions packages/mask/popups/components/NormalHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { memo, useCallback, useContext, type ReactNode } from 'react'
import { useNavigate, useOutletContext } from 'react-router-dom'
import { useNavigate } from 'react-router-dom'
import { Box, Typography } from '@mui/material'
import { makeStyles } from '@masknet/theme'
import { Icons } from '@masknet/icons'
import { PageTitleContext } from '../../hooks/index.js'
import { useHasNavigator } from '../../hooks/useHasNavigator.js'

const useStyles = makeStyles()((theme) => ({
container: {
Expand Down Expand Up @@ -63,7 +64,7 @@ export const NormalHeader = memo<NormalHeaderProps>(function NormalHeader(props)
const showTitle = title !== undefined

const handleBack = useCallback(() => navigate(-1), [])
const { hasNavigator } = useOutletContext() as { hasNavigator: boolean }
const hasNavigator = useHasNavigator()

const leftAction =
hasNavigator ? null
Expand Down
12 changes: 6 additions & 6 deletions packages/mask/popups/components/PopupLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { memo, useMemo, type PropsWithChildren, lazy, Suspense } from 'react'
import { memo, lazy, Suspense } from 'react'
import { matchPath, Outlet, useLocation } from 'react-router-dom'
import { PopupRoutes } from '@masknet/shared-base'
import { makeStyles } from '@masknet/theme'
import { GlobalStyles, Paper } from '@mui/material'
import { Navigator } from '../Navigator/index.js'
import { HasNavigatorContext } from '../../hooks/useHasNavigator.js'

const GlobalCss = (
<GlobalStyles
Expand Down Expand Up @@ -66,20 +67,19 @@ const PATTERNS = [

const LoadMaskSDK = lazy(() => import('./LoadMaskSDK.js'))

export const PopupLayout = memo(function PopupLayout({ children }: PropsWithChildren<{}>) {
export const PopupLayout = memo(function PopupLayout() {
const { classes } = useStyles()

const location = useLocation()
const matched = PATTERNS.some((pattern) => matchPath(pattern, location.pathname))
const outletContext = useMemo(() => ({ hasNavigator: matched }), [matched])

return (
<>
<HasNavigatorContext.Provider value={matched}>
{GlobalCss}
<Paper elevation={0} sx={{ height: '100vh', overflowY: 'auto', minHeight: 600, borderRadius: 0 }}>
<div className={classes.container} data-hide-scrollbar>
<div className={classes.body} data-hide-scrollbar>
{children ?? <Outlet context={outletContext} />}
<Outlet />
</div>
<Suspense fallback={null}>
{matched ?
Expand All @@ -91,6 +91,6 @@ export const PopupLayout = memo(function PopupLayout({ children }: PropsWithChil
: null}
</div>
</Paper>
</>
</HasNavigatorContext.Provider>
)
})
6 changes: 6 additions & 0 deletions packages/mask/popups/hooks/useHasNavigator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createContext, useContext } from 'react'

export const HasNavigatorContext = createContext(false)
export function useHasNavigator() {
return useContext(HasNavigatorContext)
}
2 changes: 1 addition & 1 deletion packages/mask/popups/pages/Friends/Detail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useQueryClient, useMutation, type InfiniteData } from '@tanstack/react-
import { usePopupCustomSnackbar } from '@masknet/theme'
import { type Friend } from '../../../hooks/index.js'

export const FriendsDetail = memo(function FriendsDetail() {
export const Component = memo(function FriendsDetail() {
const location = useLocation()
const t = useMaskSharedTrans()
const { showSnackbar } = usePopupCustomSnackbar()
Expand Down
4 changes: 1 addition & 3 deletions packages/mask/popups/pages/Friends/Home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { useMaskSharedTrans } from '../../../../shared-ui/index.js'
import Fuse from 'fuse.js'

const FriendsHome = memo(function FriendsHome() {
export const Component = memo(function FriendsHome() {
const t = useMaskSharedTrans()
useTitle(t.popups_encrypted_friends())

Expand Down Expand Up @@ -75,5 +75,3 @@ const FriendsHome = memo(function FriendsHome() {
/>
)
})

export default FriendsHome
21 changes: 10 additions & 11 deletions packages/mask/popups/pages/Friends/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { lazy, memo, Suspense, useEffect } from 'react'
import { Route, Routes, useSearchParams, useMatch } from 'react-router-dom'
import { memo, Suspense, useEffect } from 'react'
import { useSearchParams, useMatch, type RouteObject, Navigate, Outlet } from 'react-router-dom'
import { PopupModalRoutes, PopupRoutes, relativeRouteOf } from '@masknet/shared-base'
import { LoadingPlaceholder } from '../../components/LoadingPlaceholder/index.js'
import { useModalNavigate, NormalHeader } from '../../components/index.js'
import { FriendsDetail } from './Detail/index.js'
import { RestorableScrollContext } from '@masknet/shared'

const Home = lazy(() => import(/* webpackPreload: true */ './Home/index.js'))
const r = relativeRouteOf(PopupRoutes.Friends)

const Contacts = memo(function Contacts() {
export const contactsRoutes: RouteObject[] = [
{ index: true, lazy: () => import('./Home/index.js') },
{ path: `${r(PopupRoutes.FriendsDetail)}/:id?`, lazy: () => import('./Detail/index.js') },
{ path: '*', element: <Navigate to={PopupRoutes.Contacts} /> },
]

export const ContactsFrame = memo(function Contacts() {
const modalNavigate = useModalNavigate()
const [params] = useSearchParams()
const matchDetail = useMatch(`${PopupRoutes.FriendsDetail}/:id`)
Expand All @@ -25,13 +29,8 @@ const Contacts = memo(function Contacts() {
<Suspense fallback={<LoadingPlaceholder />}>
{matchDetail ? null : <NormalHeader />}
<RestorableScrollContext.Provider>
<Routes>
<Route path="*" element={<Home />} />
<Route path={`${r(PopupRoutes.FriendsDetail)}/:id?`} element={<FriendsDetail />} />
</Routes>
<Outlet />
</RestorableScrollContext.Provider>
</Suspense>
)
})

export default Contacts
5 changes: 2 additions & 3 deletions packages/mask/popups/pages/Personas/AccountDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { DisconnectEventMap } from '../../../../shared/definitions/event.js'
import { PageTitleContext, useTitle } from '../../../hooks/index.js'
import { AccountDetailUI } from './UI.js'

const AccountDetail = memo(() => {
export const Component = memo(() => {
const t = useMaskSharedTrans()
const navigate = useNavigate()
const theme = useTheme()
Expand Down Expand Up @@ -240,5 +240,4 @@ const AccountDetail = memo(() => {
/>
)
})

export default AccountDetail
Component.displayName = 'AccountDetail'

0 comments on commit 2a729e7

Please sign in to comment.