Skip to content

Commit

Permalink
refactor: use next.js routing (#560)
Browse files Browse the repository at this point in the history
  • Loading branch information
spsjvc authored Feb 2, 2023
1 parent 9d77d2a commit f257a6e
Show file tree
Hide file tree
Showing 15 changed files with 185 additions and 298 deletions.
4 changes: 3 additions & 1 deletion packages/arb-token-bridge-ui/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ module.exports = {
})

return config
}
},
// https://nextjs.org/docs/api-reference/next.config.js/exportPathMap#adding-a-trailing-slash
trailingSlash: true
}
3 changes: 1 addition & 2 deletions packages/arb-token-bridge-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
"framer-motion": "^4.1.17",
"lodash-es": "^4.17.21",
"next": "^13.1.5",
"next-query-params": "^4.1.0",
"overmind": "^28.0.1",
"overmind-react": "^29.0.1",
"query-string": "^7.1.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-loader-spinner": "^4.0.0",
"react-router-dom": "^5.2.0",
"react-use": "^17.2.4",
"react-virtualized": "^9.22.3",
"tailwind-merge": "^0.9.0",
Expand Down Expand Up @@ -69,7 +69,6 @@
"@types/node": "^16.6.1",
"@types/react": "^17.0.18",
"@types/react-dom": "^17.0.9",
"@types/react-router-dom": "^5.1.8",
"@types/react-virtualized": "^9.21.20",
"@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.44.0",
Expand Down
142 changes: 36 additions & 106 deletions packages/arb-token-bridge-ui/src/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useWallet } from '@arbitrum/use-wallet'
import axios from 'axios'
import { createOvermind, Overmind } from 'overmind'
import { Provider } from 'overmind-react'
import { Route, BrowserRouter as Router, Switch } from 'react-router-dom'
import { useLocalStorage } from 'react-use'
import { ConnectionState } from '../../util'
import { TokenBridgeParams } from 'token-bridge-sdk'
Expand All @@ -16,15 +15,13 @@ import { config, useActions, useAppState } from '../../state'
import { modalProviderOpts } from '../../util/modelProviderOpts'
import { Alert } from '../common/Alert'
import { Button } from '../common/Button'
import { Layout } from '../common/Layout'
import { MainContent } from '../MainContent/MainContent'
import { ArbTokenBridgeStoreSync } from '../syncers/ArbTokenBridgeStoreSync'
import { BalanceUpdater } from '../syncers/BalanceUpdater'
import { PendingTransactionsUpdater } from '../syncers/PendingTransactionsUpdater'
import { PWLoadedUpdater } from '../syncers/PWLoadedUpdater'
import { RetryableTxnsIncluder } from '../syncers/RetryableTxnsIncluder'
import { TokenListSyncer } from '../syncers/TokenListSyncer'
import { TermsOfService, TOS_VERSION } from '../TermsOfService/TermsOfService'
import { ExternalLink } from '../common/ExternalLink'
import { useDialog } from '../common/Dialog'
import {
Expand Down Expand Up @@ -53,6 +50,8 @@ import { MainNetworkNotSupported } from '../common/MainNetworkNotSupported'
import { HeaderNetworkNotSupported } from '../common/HeaderNetworkNotSupported'
import { NetworkSelectionContainer } from '../common/NetworkSelectionContainer'
import { isTestingEnvironment } from '../../util/CommonUtils'
import { TOS_VERSION } from '../../constants'
import { AppConnectionFallbackContainer } from './AppConnectionFallbackContainer'

declare global {
interface Window {
Expand Down Expand Up @@ -223,63 +222,6 @@ const Injector = ({ children }: { children: React.ReactNode }): JSX.Element => {
)
}

function Routes() {
const key = 'arbitrum:bridge:tos-v' + TOS_VERSION
const [tosAccepted, setTosAccepted] = useLocalStorage<string>(key)
const [welcomeDialogProps, openWelcomeDialog] = useDialog()

const isTosAccepted = tosAccepted !== undefined

useEffect(() => {
if (!isTosAccepted) {
openWelcomeDialog()
}
}, [isTosAccepted, openWelcomeDialog])

function onClose(confirmed: boolean) {
// Only close after confirming (agreeing to terms)
if (confirmed) {
setTosAccepted('true')
welcomeDialogProps.onClose(confirmed)
}
}

return (
<Router>
<ArbQueryParamProvider>
<WelcomeDialog {...welcomeDialogProps} onClose={onClose} />
<Switch>
<Route path="/tos" exact>
<TermsOfService />
</Route>

<Route path="/" exact>
<NetworkReady>
<AppContextProvider>
<Injector>{isTosAccepted && <AppContent />}</Injector>
</AppContextProvider>
</NetworkReady>
</Route>

<Route path="*">
<div className="flex w-full flex-col items-center space-y-4 px-8 py-4 text-center lg:py-0">
<span className="text-8xl text-white">404</span>
<p className="text-3xl text-white">
Page not found in this solar system
</p>
<img
src="/images/arbinaut-fixing-spaceship.webp"
alt="Arbinaut fixing a spaceship"
className="lg:max-w-md"
/>
</div>
</Route>
</Switch>
</ArbQueryParamProvider>
</Router>
)
}

function NetworkReady({ children }: { children: React.ReactNode }) {
const [{ l2ChainId }] = useArbQueryParams()

Expand All @@ -293,43 +235,6 @@ function NetworkReady({ children }: { children: React.ReactNode }) {
)
}

function ConnectionFallbackContainer({
layout = 'col',
imgProps = {
className: 'sm:w-[420px]',
src: '/images/three-arbinauts.webp',
alt: 'Three Arbinauts'
},
children
}: {
layout?: 'row' | 'col'
imgProps?: {
className?: string
src?: string
alt?: string
}
children: React.ReactNode
}) {
return (
<div className="my-24 flex items-center justify-center px-8">
<div
className={`flex flex-col items-center md:flex-${layout} md:items-${
layout === 'col' ? 'center' : 'start'
}`}
>
{children}
<ExternalLink href="https://metamask.io/download">
<img
className={imgProps.className}
src={imgProps.src}
alt={imgProps.alt}
/>
</ExternalLink>
</div>
</div>
)
}

function ConnectionFallback(props: FallbackProps): JSX.Element {
const { connect } = useWallet()

Expand All @@ -349,11 +254,11 @@ function ConnectionFallback(props: FallbackProps): JSX.Element {
<HeaderNetworkLoadingIndicator />
</HeaderContent>

<ConnectionFallbackContainer>
<AppConnectionFallbackContainer>
<div className="fixed inset-0 m-auto h-[44px] w-[44px]">
<Loader type="TailSpin" color="white" height={44} width={44} />
</div>
</ConnectionFallbackContainer>
</AppConnectionFallbackContainer>
</>
)

Expand All @@ -364,11 +269,11 @@ function ConnectionFallback(props: FallbackProps): JSX.Element {
<HeaderConnectWalletButton />
</HeaderContent>

<ConnectionFallbackContainer>
<AppConnectionFallbackContainer>
<Button variant="primary" onClick={showConnectionModal}>
Connect Wallet
</Button>
</ConnectionFallbackContainer>
</AppConnectionFallbackContainer>
</>
)

Expand All @@ -385,7 +290,7 @@ function ConnectionFallback(props: FallbackProps): JSX.Element {
</NetworkSelectionContainer>
</HeaderContent>

<ConnectionFallbackContainer
<AppConnectionFallbackContainer
layout="row"
imgProps={{
className: 'sm:w-[300px]',
Expand All @@ -394,7 +299,7 @@ function ConnectionFallback(props: FallbackProps): JSX.Element {
}}
>
<MainNetworkNotSupported supportedNetworks={supportedNetworks} />
</ConnectionFallbackContainer>
</AppConnectionFallbackContainer>
</>
)
}
Expand All @@ -403,11 +308,36 @@ function ConnectionFallback(props: FallbackProps): JSX.Element {
export default function App() {
const [overmind] = useState<Overmind<typeof config>>(createOvermind(config))

const key = 'arbitrum:bridge:tos-v' + TOS_VERSION
const [tosAccepted, setTosAccepted] = useLocalStorage<string>(key)
const [welcomeDialogProps, openWelcomeDialog] = useDialog()

const isTosAccepted = tosAccepted !== undefined

useEffect(() => {
if (!isTosAccepted) {
openWelcomeDialog()
}
}, [isTosAccepted, openWelcomeDialog])

function onClose(confirmed: boolean) {
// Only close after confirming (agreeing to terms)
if (confirmed) {
setTosAccepted('true')
welcomeDialogProps.onClose(confirmed)
}
}

return (
<Provider value={overmind}>
<Layout>
<Routes />
</Layout>
<ArbQueryParamProvider>
<WelcomeDialog {...welcomeDialogProps} onClose={onClose} />
<NetworkReady>
<AppContextProvider>
<Injector>{isTosAccepted && <AppContent />}</Injector>
</AppContextProvider>
</NetworkReady>
</ArbQueryParamProvider>
</Provider>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ExternalLink } from '../common/ExternalLink'

export function AppConnectionFallbackContainer({
layout = 'col',
imgProps = {
className: 'sm:w-[420px]',
src: '/images/three-arbinauts.webp',
alt: 'Three Arbinauts'
},
children
}: {
layout?: 'row' | 'col'
imgProps?: {
className?: string
src?: string
alt?: string
}
children: React.ReactNode
}) {
return (
<div className="my-24 flex items-center justify-center px-8">
<div
className={`flex flex-col items-center md:flex-${layout} md:items-${
layout === 'col' ? 'center' : 'start'
}`}
>
{children}
<ExternalLink href="https://metamask.io/download">
<img
className={imgProps.className}
src={imgProps.src}
alt={imgProps.alt}
/>
</ExternalLink>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { useRef } from 'react'
import { Dialog as HeadlessUIDialog } from '@headlessui/react'
import { useRouteMatch } from 'react-router-dom'

import { Button } from '../common/Button'
import { ExternalLink } from '../common/ExternalLink'
import { Dialog, UseDialogProps } from '../common/Dialog'

export function WelcomeDialog(props: UseDialogProps) {
const confirmButtonRef = useRef(null)
const isTosRoute = useRouteMatch('/tos')

if (isTosRoute) {
return null
}

return (
<Dialog {...props} initialFocus={confirmButtonRef} isCustom>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useHistory } from 'react-router-dom'
import { Listbox } from '@headlessui/react'
import {
ChevronDownIcon,
Expand Down Expand Up @@ -334,7 +333,6 @@ export function TransferPanelMain({
React.SetStateAction<string | undefined>
>
}) {
const history = useHistory()
const actions = useActions()

const { l1, l2, isConnectedToArbitrum, isSmartContractWallet } =
Expand Down Expand Up @@ -384,7 +382,7 @@ export function TransferPanelMain({

// Keep the connected L2 chain id in search params, so it takes preference in any L1 => L2 actions
setQueryParams({ l2ChainId })
}, [isConnectedToArbitrum, externalFrom, externalTo, history, setQueryParams])
}, [isConnectedToArbitrum, externalFrom, externalTo, setQueryParams])

// whenever the user changes the `amount` input, it should update the amount in browser query params as well
useEffect(() => {
Expand Down Expand Up @@ -717,7 +715,7 @@ export function TransferPanelMain({
}
}
}
}, [isDepositMode, isConnectedToArbitrum, l1.network, from, to, history])
}, [isDepositMode, isConnectedToArbitrum, l1.network, from, to])

async function setMaxAmount() {
const ethBalance = isDepositMode ? ethL1Balance : ethL2Balance
Expand Down
2 changes: 2 additions & 0 deletions packages/arb-token-bridge-ui/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export const TOS_VERSION = 1

export const GET_HELP_LINK =
'https://support.arbitrum.io/hc/en-us/requests/new?&tf_subject=Issue%20with%20bridging&tf_description=1.%20Describe%20the%20issue%20in%20detail:%3Cbr%3E%3Cbr%3E2.%20Your%20browser%20(Chrome,%20Firefox,%20Brave,%20etc.)%3Cbr%3E%3Cbr%3E3.%20Are%20you%20moving%20funds%20to%20Mainnet%20or%20Arbitrum?%3Cbr%3E%3Cbr%3E4.%20(optional)%20Steps%20to%20reproduce:%3Cbr%3E5.%20(optional)%20What%20token%20are%20you%20transferring:&tf_1260832145490=You%20can%20find%20your%20TxID%20in%20your%20profile%20tab%20on%20the%20bridge&tf_1900010553864=true'
12 changes: 6 additions & 6 deletions packages/arb-token-bridge-ui/src/hooks/useArbQueryParams.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
This hook is an abstraction over `useQueryParams` hooks' library
- It contains all the browser query params we use / intend to use in our application
- It contains all the browser query params we use / intend to use in our application
- Provides methods to listen to, and update all these query params
- If we introduce a new queryParam for our bridge in the future, define it here and it will be accessible throughout the app :)
- Example - to get the value of `?amount=` in browser, simply use
`const [{ amount }] = useArbQueryParams()`
Expand All @@ -14,7 +14,7 @@
*/
import React from 'react'
import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'
import { NextAdapter } from 'next-query-params'
import { parse, stringify } from 'query-string'
import {
NumberParam,
Expand All @@ -30,10 +30,10 @@ export enum AmountQueryParamEnum {

export const useArbQueryParams = () => {
/*
returns [
returns [
queryParams (getter for all query state variables),
setQueryParams (setter for all query state variables)
]
]
*/
return useQueryParams({
Expand Down Expand Up @@ -101,7 +101,7 @@ export function ArbQueryParamProvider({
}) {
return (
<QueryParamProvider
adapter={ReactRouter5Adapter}
adapter={NextAdapter}
options={{
searchStringToObject: parse,
objectToSearchString: stringify,
Expand Down
Loading

1 comment on commit f257a6e

@vercel
Copy link

@vercel vercel bot commented on f257a6e Feb 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.