Skip to content

Commit 57efbe9

Browse files
chore: add selected network to the explore path (#94)
* add selected network to the explore path * redirect on unknown network --------- Co-authored-by: Neil Campbell <[email protected]>
1 parent 426120c commit 57efbe9

25 files changed

+273
-214
lines changed

src/App.routes.tsx

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { AssetPage, assetPageTitle } from './features/assets/pages/asset-page'
1313
import { ApplicationPage, applicationPageTitle } from './features/applications/pages/application-page'
1414
import { SettingsPage } from './features/settings/pages/settings-page'
1515
import { TxPage } from './features/transactions/pages/tx-page'
16+
import { IndexPage } from '@/index-page'
17+
import { NetworkPage } from '@/features/network/pages/network-page'
1618

1719
export const routes = evalTemplates([
1820
{
@@ -26,53 +28,72 @@ export const routes = evalTemplates([
2628
children: [
2729
{
2830
template: Urls.Index,
29-
element: <ExplorePage />,
31+
element: <IndexPage />,
3032
errorElement: <ErrorPage title={explorePageTitle} />,
3133
},
3234
{
33-
template: Urls.Transaction.ById,
34-
errorElement: <ErrorPage title={transactionPageTitle} />,
35+
template: Urls.Network,
36+
element: (
37+
<NetworkPage>
38+
<Outlet />
39+
</NetworkPage>
40+
),
3541
children: [
3642
{
37-
template: Urls.Transaction.ById,
38-
element: <TransactionPage />,
43+
template: Urls.Network,
44+
element: <ExplorePage />,
45+
errorElement: <ErrorPage title={explorePageTitle} />,
3946
},
4047
{
41-
template: Urls.Transaction.ById.Inner.ById,
42-
element: <InnerTransactionPage />,
48+
template: Urls.Network.Transaction.ById,
49+
errorElement: <ErrorPage title={transactionPageTitle} />,
50+
children: [
51+
{
52+
template: Urls.Network.Transaction.ById,
53+
element: <TransactionPage />,
54+
},
55+
{
56+
template: Urls.Network.Transaction.ById.Inner.ById,
57+
element: <InnerTransactionPage />,
58+
},
59+
],
60+
},
61+
{
62+
template: Urls.Network.Block.ByRound,
63+
children: [
64+
{
65+
template: Urls.Network.Block.ByRound,
66+
errorElement: <ErrorPage title={blockPageTitle} />,
67+
element: <BlockPage />,
68+
},
69+
{
70+
template: Urls.Network.Block.ByRound.Group.ById,
71+
errorElement: <ErrorPage title={groupPageTitle} />,
72+
element: <GroupPage />,
73+
},
74+
],
75+
},
76+
{
77+
template: Urls.Network.Account.ByAddress,
78+
element: <AccountPage />,
79+
errorElement: <ErrorPage title={accountPageTitle} />,
80+
},
81+
{
82+
template: Urls.Network.Asset.ById,
83+
element: <AssetPage />,
84+
errorElement: <ErrorPage title={assetPageTitle} />,
4385
},
44-
],
45-
},
46-
{
47-
template: Urls.Block.ByRound,
48-
children: [
4986
{
50-
template: Urls.Block.ByRound,
51-
errorElement: <ErrorPage title={blockPageTitle} />,
52-
element: <BlockPage />,
87+
template: Urls.Network.Application.ById,
88+
errorElement: <ErrorPage title={applicationPageTitle} />,
89+
element: <ApplicationPage />,
5390
},
5491
{
55-
template: Urls.Block.ByRound.Group.ById,
56-
errorElement: <ErrorPage title={groupPageTitle} />,
57-
element: <GroupPage />,
92+
template: Urls.Network.Tx,
93+
element: <TxPage />,
5894
},
5995
],
6096
},
61-
{
62-
template: Urls.Account.ByAddress,
63-
element: <AccountPage />,
64-
errorElement: <ErrorPage title={accountPageTitle} />,
65-
},
66-
{
67-
template: Urls.Asset.ById,
68-
element: <AssetPage />,
69-
errorElement: <ErrorPage title={assetPageTitle} />,
70-
},
71-
{
72-
template: Urls.Application.ById,
73-
errorElement: <ErrorPage title={applicationPageTitle} />,
74-
element: <ApplicationPage />,
75-
},
7697
{
7798
template: Urls.AppStudio,
7899
element: <div>App Studio</div>,
@@ -81,10 +102,6 @@ export const routes = evalTemplates([
81102
template: Urls.Settings,
82103
element: <SettingsPage />,
83104
},
84-
{
85-
template: Urls.Tx,
86-
element: <TxPage />,
87-
},
88105
],
89106
},
90107
])

src/features/accounts/components/account-link.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ellipseAddress } from '@/utils/ellipse-address'
66
import { fixedForwardRef } from '@/utils/fixed-forward-ref'
77
import { PropsWithChildren, useCallback } from 'react'
88
import { toast } from 'react-toastify'
9+
import { useSelectedNetwork } from '@/features/settings/data'
910

1011
type Props = PropsWithChildren<{
1112
address: string
@@ -16,6 +17,7 @@ type Props = PropsWithChildren<{
1617

1718
export const AccountLink = fixedForwardRef(
1819
({ address, short, className, children, showCopyButton, ...rest }: Props, ref?: React.LegacyRef<HTMLAnchorElement>) => {
20+
const [selectedNetwork] = useSelectedNetwork()
1921
const copyClipboard = useCallback(async () => {
2022
await navigator.clipboard.writeText(address)
2123
toast.success('Address copied to clipboard')
@@ -24,8 +26,8 @@ export const AccountLink = fixedForwardRef(
2426
<>
2527
<TemplatedNavLink
2628
className={cn(!children && 'text-primary underline', className)}
27-
urlTemplate={Urls.Account.ByAddress}
28-
urlParams={{ address }}
29+
urlTemplate={Urls.Network.Account.ByAddress}
30+
urlParams={{ address, networkId: selectedNetwork }}
2931
ref={ref}
3032
{...rest}
3133
>

src/features/applications/components/application-link.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@ import { TemplatedNavLink } from '@/features/routing/components/templated-nav-li
33
import { Urls } from '@/routes/urls'
44
import { PropsWithChildren } from 'react'
55
import { ApplicationId } from '../data/types'
6+
import { useSelectedNetwork } from '@/features/settings/data'
67

78
type Props = PropsWithChildren<{
89
applicationId: ApplicationId
910
className?: string
1011
}>
1112

1213
export function ApplicationLink({ applicationId, className, children }: Props) {
14+
const [selectedNetwork] = useSelectedNetwork()
1315
return (
1416
<TemplatedNavLink
1517
className={cn(!children && 'text-primary underline', className)}
16-
urlTemplate={Urls.Application.ById}
17-
urlParams={{ applicationId: applicationId.toString() }}
18+
urlTemplate={Urls.Network.Application.ById}
19+
urlParams={{ applicationId: applicationId.toString(), networkId: selectedNetwork }}
1820
>
1921
{children ? children : applicationId}
2022
</TemplatedNavLink>

src/features/assets/components/asset-link.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { AsyncMaybeAtom } from '@/features/common/data/types'
77
import { RenderInlineAsyncAtom } from '@/features/common/components/render-inline-async-atom'
88
import { CopyButton } from '@/features/common/components/copy-button'
99
import { toast } from 'react-toastify'
10+
import { useSelectedNetwork } from '@/features/settings/data'
1011

1112
type CommonProps = {
1213
className?: string
@@ -33,6 +34,7 @@ type AssetLinkProps = PropsWithChildren<
3334
>
3435

3536
function Link(props: AssetIdLinkProps | AssetIdAndNameLinkProps) {
37+
const [selectedNetwork] = useSelectedNetwork()
3638
const copyClipboard = useCallback(async () => {
3739
await navigator.clipboard.writeText(props.assetId.toString())
3840
toast.success('Asset ID copied to clipboard')
@@ -42,8 +44,8 @@ function Link(props: AssetIdLinkProps | AssetIdAndNameLinkProps) {
4244
<>
4345
<TemplatedNavLink
4446
className={cn(!props.children && 'text-primary underline', props.className)}
45-
urlTemplate={Urls.Asset.ById}
46-
urlParams={{ assetId: props.assetId.toString() }}
47+
urlTemplate={Urls.Network.Asset.ById}
48+
urlParams={{ assetId: props.assetId.toString(), networkId: selectedNetwork }}
4749
>
4850
{props.children ? props.children : props.assetId}
4951
</TemplatedNavLink>

src/features/blocks/components/block-link.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ import { cn } from '@/features/common/utils'
22
import { TemplatedNavLink } from '@/features/routing/components/templated-nav-link/templated-nav-link'
33
import { Urls } from '@/routes/urls'
44
import { PropsWithChildren } from 'react'
5+
import { useSelectedNetwork } from '@/features/settings/data'
56

67
type Props = PropsWithChildren<{
78
round: number
89
className?: string
910
}>
1011

1112
export function BlockLink({ round, className, children }: Props) {
13+
const [selectedNetwork] = useSelectedNetwork()
14+
1215
return (
1316
<TemplatedNavLink
1417
className={cn(!children && 'text-primary underline', className)}
15-
urlTemplate={Urls.Block.ByRound}
16-
urlParams={{ round: round.toString() }}
18+
urlTemplate={Urls.Network.Block.ByRound}
19+
urlParams={{ round: round.toString(), networkId: selectedNetwork }}
1720
>
1821
{children ? children : round}
1922
</TemplatedNavLink>

src/features/deep-link/hooks/use-deep-link.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { useCallback, useEffect } from 'react'
2-
import 'react-toastify/dist/ReactToastify.css'
32
import { listen } from '@tauri-apps/api/event'
43
import { useNavigate } from 'react-router-dom'
5-
import { useSetSelectedNetwork } from '@/features/settings/data'
4+
import { useSelectedNetwork } from '@/features/settings/data'
65
import { parseDeepLink } from '@/features/deep-link/parse-deep-link'
76
import { Urls } from '@/routes/urls'
87

98
export function useDeepLink() {
10-
const setSelectedNetwork = useSetSelectedNetwork()
9+
const [_, setSelectedNetwork] = useSelectedNetwork()
1110
const navigate = useNavigate()
1211

1312
const handleDeepLink = useCallback(
@@ -16,7 +15,7 @@ export function useDeepLink() {
1615
if (options) {
1716
await setSelectedNetwork(options.networkId)
1817
if (options.transactionId) {
19-
navigate(Urls.Transaction.ById.build({ transactionId: options.transactionId }))
18+
navigate(Urls.Network.Transaction.ById.build({ transactionId: options.transactionId, networkId: options.networkId }))
2019
} else {
2120
navigate(Urls.Index.build({}))
2221
}

src/features/groups/components/group-link.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Urls } from '@/routes/urls'
55
import { PropsWithChildren } from 'react'
66
import { GroupId } from '../data/types'
77
import { ellipseId } from '@/utils/ellipse-id'
8+
import { useSelectedNetwork } from '@/features/settings/data'
89

910
type Props = PropsWithChildren<{
1011
round: Round
@@ -14,11 +15,13 @@ type Props = PropsWithChildren<{
1415
}>
1516

1617
export function GroupLink({ round, groupId, short = false, className, children }: Props) {
18+
const [selectedNetwork] = useSelectedNetwork()
19+
1720
return (
1821
<TemplatedNavLink
1922
className={cn(!children && 'text-primary underline', className)}
20-
urlTemplate={Urls.Block.ByRound.Group.ById}
21-
urlParams={{ round: round.toString(), groupId: encodeURIComponent(groupId) }}
23+
urlTemplate={Urls.Network.Block.ByRound.Group.ById}
24+
urlParams={{ round: round.toString(), groupId: encodeURIComponent(groupId), networkId: selectedNetwork }}
2225
>
2326
{children ? children : short ? <abbr title={groupId}>{ellipseId(groupId)}</abbr> : groupId}
2427
</TemplatedNavLink>

src/features/layout/components/left-side-bar-menu.tsx

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
import { TemplatedNavLink } from '../../routing/components/templated-nav-link/templated-nav-link'
2-
import { Urls } from '../../../routes/urls'
2+
import { Urls } from '@/routes/urls'
33
import { NavigationMenu, NavigationMenuItem, NavigationMenuLink, NavigationMenuList } from '@/features/common/components/navigation-menu'
44
import { cn } from '@/features/common/utils'
55
import SvgCodeBlock from '@/features/common/components/icons/code-block'
66
import SvgHome from '@/features/common/components/icons/home'
77
import { Button } from '@/features/common/components/button'
88
import SvgChevronLeft from '@/features/common/components/icons/chevron-left'
9-
import { useCallback, useMemo } from 'react'
9+
import { useCallback } from 'react'
1010
import SvgChevronRight from '@/features/common/components/icons/chevron-right'
1111
import SvgCog from '@/features/common/components/icons/cog'
12-
import { useLayout } from '@/features/settings/data'
13-
import { useLocation } from 'react-router-dom'
12+
import { useLayout, useSelectedNetwork } from '@/features/settings/data'
1413

1514
type Props = {
1615
className?: string
1716
}
1817

1918
export function LeftSideBarMenu({ className }: Props) {
19+
const [selectedNetwork] = useSelectedNetwork()
20+
2021
const menuItems = [
21-
{ urlTemplate: Urls.Index, icon: <SvgHome />, text: 'Home' },
22+
{ urlTemplate: Urls.Network, icon: <SvgHome />, text: 'Home' },
2223
{ urlTemplate: Urls.AppStudio, icon: <SvgCodeBlock />, text: 'App Studio' },
2324
{ urlTemplate: Urls.Settings, icon: <SvgCog />, text: 'Settings' },
2425
]
@@ -29,21 +30,6 @@ export function LeftSideBarMenu({ className }: Props) {
2930
[setLayout]
3031
)
3132

32-
// The little hack to make the index (root) menu item active when transaction, block, account, asset, application are viewed
33-
// This needs to be done because React router doesn't match the root URL with any sub-path
34-
// The doc: https://reactrouter.com/en/main/components/nav-link#end
35-
const location = useLocation()
36-
const isIndexActive = useMemo(() => {
37-
const forceMatchWithIndex = [
38-
Urls.Transaction.build({}),
39-
Urls.Block.build({}),
40-
Urls.Account.build({}),
41-
Urls.Asset.build({}),
42-
Urls.Application.build({}),
43-
]
44-
return forceMatchWithIndex.some((path) => location.pathname.startsWith(path))
45-
}, [location.pathname])
46-
4733
return (
4834
<NavigationMenu
4935
className={cn('bg-card transition-all duration-300 min-h-screen', className, layout.isLeftSideBarExpanded ? 'w-52' : 'w-10')}
@@ -59,10 +45,8 @@ export function LeftSideBarMenu({ className }: Props) {
5945
<NavigationMenuLink asChild>
6046
<TemplatedNavLink
6147
urlTemplate={menuItem.urlTemplate}
62-
className={cn(
63-
'[&.active]:text-primary flex items-center p-2 gap-2 min-h-10 pl-3 whitespace-nowrap',
64-
menuItem.urlTemplate === Urls.Index && isIndexActive ? 'active' : ''
65-
)}
48+
urlParams={{ networkId: selectedNetwork }}
49+
className={cn('[&.active]:text-primary flex items-center p-2 gap-2 min-h-10 pl-3 whitespace-nowrap')}
6650
>
6751
<div className={cn('text-primary')}>{menuItem.icon}</div>
6852
<div className={cn(layout.isLeftSideBarExpanded ? 'visible delay-100' : 'invisible delay-100')}>{menuItem.text}</div>

src/features/layout/pages/layout-page.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ describe('when rendering the layout page', () => {
252252
expect(network).toBeTruthy()
253253
const networkConfig = settingsStore.get(networkConfigAtom)
254254
expect(networkConfig.id).toBe('mainnet')
255-
expect(mockNavigate).toHaveBeenCalledWith(`/transaction/JC4VRVWOA7ZQX6OJX5GCAPJVAEEQB3Q4MYWJXVJC7LCNH6HW62WQ/inner/41-1`)
255+
expect(mockNavigate).toHaveBeenCalledWith(
256+
`/mainnet/transaction/JC4VRVWOA7ZQX6OJX5GCAPJVAEEQB3Q4MYWJXVJC7LCNH6HW62WQ/inner/41-1`
257+
)
256258
})
257259
}
258260
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { useRequiredParam } from '@/features/common/hooks/use-required-param'
2+
import { UrlParams, Urls } from '@/routes/urls'
3+
import { networksConfigs } from '@/features/settings/data'
4+
import { useNavigate } from 'react-router-dom'
5+
import { useEffect } from 'react'
6+
7+
type Props = {
8+
children: React.ReactNode
9+
}
10+
export function NetworkPage({ children }: Props) {
11+
const { networkId } = useRequiredParam(UrlParams.NetworkId)
12+
const navigate = useNavigate()
13+
14+
useEffect(() => {
15+
if (!networksConfigs.find((c) => c.id === networkId)) {
16+
navigate(Urls.Index.build({}))
17+
}
18+
}, [navigate, networkId])
19+
20+
return children
21+
}

0 commit comments

Comments
 (0)