Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: replace layout modals #1040

Merged
merged 4 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import React from 'react'

import { ChainId } from '@dcl/schemas/dist/dapps/chain-id'
import WalletSelectorModal from 'decentraland-gatsby/dist/components/Modal/WalletSelectorModal'
import WrongNetworkModal from 'decentraland-gatsby/dist/components/Modal/WrongNetworkModal'
import useAuthContext from 'decentraland-gatsby/dist/context/Auth/useAuthContext'
import { changeLocale } from 'decentraland-gatsby/dist/plugins/intl'
import { DecentralandIntlContext } from 'decentraland-gatsby/dist/plugins/intl/types'
Expand All @@ -13,6 +11,9 @@ import { Navbar, NavbarProps } from 'decentraland-ui/dist/components/Navbar/Navb
import type { PageProps } from 'gatsby'
import type { DropdownProps } from 'semantic-ui-react/dist/commonjs/modules/Dropdown'

import WalletSelectorModal from '../Modal/WalletSelectorModal'
import WrongNetworkModal from '../Modal/WrongNetworkModal'

import './Layout.css'

const CHAIN_ID: ChainId[] = env('GATSBY_DEFAULT_CHAIN_ID', String(ChainId.ETHEREUM_MAINNET))
Expand Down Expand Up @@ -59,13 +60,14 @@ export default function Layout({ children, pageContext, ...props }: LayoutProps)
<main>{children}</main>
<WrongNetworkModal
currentNetwork={state.chainId}
expectedNetwork={getSupportedChainIds()}
expectedNetworks={getSupportedChainIds()}
onSwitchNetwork={(chainId) => state.switchTo(chainId)}
providerType={state.providerType}
/>
<WalletSelectorModal
open={state.selecting}
loading={state.loading}
chainId={getSupportedChainIds()[0]}
error={state.error}
onConnect={(providerType, chainId) => state.connect(providerType, chainId)}
onClose={() => state.select(false)}
Expand Down
4 changes: 4 additions & 0 deletions src/components/Modal/WalletSelectorModal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.WalletSelectorModal p.dg.Paragraph {
font-size: 13px;
line-height: 1.5;
}
95 changes: 95 additions & 0 deletions src/components/Modal/WalletSelectorModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useCallback, useEffect, useState } from 'react'

import { ChainId } from '@dcl/schemas/dist/dapps/chain-id'
import { ProviderType } from '@dcl/schemas/dist/dapps/provider-type'
import { connection } from 'decentraland-connect/dist/ConnectionManager'
import { toModalOptionType } from 'decentraland-dapps/dist/containers/LoginModal/utils'
import Markdown from 'decentraland-gatsby/dist/components/Text/Markdown'
import { useFeatureFlagContext } from 'decentraland-gatsby/dist/context/FeatureFlag'
import useAnchor from 'decentraland-gatsby/dist/hooks/useAnchor'
import useFormatMessage from 'decentraland-gatsby/dist/hooks/useFormatMessage'
import { LoginModal, LoginModalOptionType } from 'decentraland-ui/dist/components/LoginModal/LoginModal'

import './WalletSelectorModal.css'

type Props = {
open: boolean
loading: boolean
chainId: ChainId
error: string | null
onConnect: (providerType: ProviderType, chainId: ChainId) => void
onClose: () => void
}

const availableProviders = new Set(connection.getAvailableProviders())

export default function WalletSelectorModal({ chainId, onConnect, onClose, error, open, loading }: Props) {
const t = useFormatMessage()
const [provider, setProvider] = useState(LoginModalOptionType.METAMASK)
const [ff] = useFeatureFlagContext()

useEffect(() => {
setProvider(toModalOptionType(ProviderType.INJECTED) || LoginModalOptionType.METAMASK)
}, [])

const handleConnect = useCallback(
(providerType: ProviderType, chainId: ChainId) => {
if (onConnect) {
onConnect(providerType, chainId)
}
},
[onConnect]
)

const handleDownloadMetamaskClick = useAnchor('https://metamask.io/download.html')
const handleConnectInjected = useCallback(() => {
if (availableProviders.has(ProviderType.INJECTED)) {
handleConnect(ProviderType.INJECTED, chainId)
} else {
handleDownloadMetamaskClick()
}
}, [handleConnect, handleDownloadMetamaskClick, chainId])
const handleConnectFortmatic = useCallback(
() => handleConnect(ProviderType.FORTMATIC, chainId),
[chainId, handleConnect]
)
const handleConnectWalletConnect = useCallback(
() =>
handleConnect(
ff.enabled('dapps-wallet-connect-v2') ? ProviderType.WALLET_CONNECT_V2 : ProviderType.WALLET_CONNECT,
chainId
),
[ff, chainId, handleConnect]
)
const handleConnectWalletLink = useCallback(
() => handleConnect(ProviderType.WALLET_LINK, chainId),
[chainId, handleConnect]
)

return (
<LoginModal
open={open}
onClose={onClose}
className="WalletSelectorModal"
message={
<small className="message">
<Markdown>{t('modal.wallet_selector.trezor')}</Markdown>
</small>
}
hasError={!!error}
loading={loading}
>
<LoginModal.Option type={provider} onClick={handleConnectInjected} />
{availableProviders.has(ProviderType.FORTMATIC) && (
<LoginModal.Option type={LoginModalOptionType.FORTMATIC} onClick={handleConnectFortmatic} />
)}
{availableProviders.has(ProviderType.WALLET_CONNECT) && (
<LoginModal.Option type={LoginModalOptionType.WALLET_CONNECT} onClick={handleConnectWalletConnect} />
)}
{availableProviders.has(ProviderType.WALLET_LINK) && (
<LoginModal.Option type={LoginModalOptionType.WALLET_LINK} onClick={handleConnectWalletLink} />
)}
{error && <p className="error visible">{error}</p>}
</LoginModal>
)
}
81 changes: 81 additions & 0 deletions src/components/Modal/WrongNetworkModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useMemo } from 'react'

import { ChainId, getChainName } from '@dcl/schemas/dist/dapps/chain-id'
import { ProviderType } from '@dcl/schemas/dist/dapps/provider-type'
import useFormatMessage from 'decentraland-gatsby/dist/hooks/useFormatMessage'
import { Button } from 'decentraland-ui/dist/components/Button/Button'
import { Modal } from 'decentraland-ui/dist/components/Modal/Modal'
import { ModalNavigation } from 'decentraland-ui/dist/components/ModalNavigation/ModalNavigation'

type Props = {
currentNetwork: ChainId | null
expectedNetworks: ChainId[]
onSwitchNetwork: (chainId: ChainId) => void
providerType: ProviderType | null
}

export default function WrongNetworkModal({ currentNetwork, expectedNetworks, onSwitchNetwork, providerType }: Props) {
const t = useFormatMessage()

const isOpen = useMemo(
() => !!currentNetwork && !expectedNetworks.includes(currentNetwork),
[currentNetwork, expectedNetworks]
)

const expectedChainName = useMemo(() => {
switch (expectedNetworks.length) {
case 0:
return <b />
case 1:
return <b>{getChainName(expectedNetworks[0])}</b>
default:
return (
<span>
{expectedNetworks.map((chainId, i, list) => (
<span key={chainId}>
<b>{getChainName(chainId)}</b>
{i === list.length - 1 ? ', ' : t('modal.wrong_network.separator')}
</span>
))}
</span>
)
}
}, [t, expectedNetworks])

const chainName = currentNetwork ? getChainName(currentNetwork) : undefined
const currentChainName = <b>{chainName || t('modal.wrong_network.unknown_chain')}</b>

const allowNetworkSwitch = providerType === ProviderType.INJECTED

return (
<Modal size="tiny" open={isOpen}>
<ModalNavigation title={t('modal.wrong_network.header')} />
<Modal.Content>
{t('modal.wrong_network.message', {
currentChainName,
expectedChainName,
})}
</Modal.Content>
{allowNetworkSwitch && expectedNetworks.length > 0 && (
<Modal.Content>
{expectedNetworks.map((chainId: ChainId, index: number) => {
return (
<Button
fluid
key={chainId}
basic={index !== 0}
primary={index === 0}
style={index === 0 ? {} : { marginTop: '1em' }}
onClick={() => onSwitchNetwork && onSwitchNetwork(chainId)}
>
{t('modal.wrong_network.change_chain', {
expectedChainName: <b>{getChainName(chainId)}</b>,
})}
</Button>
)
})}
</Modal.Content>
)}
</Modal>
)
}
12 changes: 12 additions & 0 deletions src/intl/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,18 @@
"card_description": "Let the world know that you are behind those witty tweets about the Metaverse."
},
"soon": "Soon"
},
"wallet_selector": {
"title": "Sign In",
"subtitle": "Choose a method to connect",
"trezor": "Trezor and smart contract wallets (like Dapper or Argent) cannot interact Polygon. Read more about the Trezor support status [here](https://github.com/trezor/trezor-firmware/pull/1568)"
},
"wrong_network": {
"header": "Wrong Network",
"message": "You need to be connected to {expectedChainName} to use this app, but you are currently connected to {currentChainName}.",
"change_chain": "switch to {expectedChainName}",
"separator": " or ",
"unknown_chain": "Unknown"
}
},
"component": {
Expand Down