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

fix: native WalletConnect styling #2617

Merged
merged 1 commit into from
Oct 11, 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: 8 additions & 0 deletions public/images/common/connection-dots.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions public/images/common/question.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions src/components/common/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ const Header = ({ onMenuToggle, onBatchToggle }: HeaderProps): ReactElement => {
</div>
)}

<div className={classnames(css.element, css.hideMobile)}>
<WalletConnectHeaderWidget />
</div>

{safeAddress && (
<div className={classnames(css.element, css.hideMobile)}>
<BatchIndicator onClick={handleBatchToggle} />
Expand All @@ -82,6 +78,10 @@ const Header = ({ onMenuToggle, onBatchToggle }: HeaderProps): ReactElement => {
</PushNotificationsBanner>
</div>

<div className={classnames(css.element, css.hideMobile)}>
<WalletConnectHeaderWidget />
</div>

<div className={classnames(css.element, css.connectWallet)}>
<ConnectWallet />
</div>
Expand Down
70 changes: 70 additions & 0 deletions src/components/walletconnect/ConnectionForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import useLocalStorage from '@/services/local-storage/useLocalStorage'
import { Grid, Typography, Divider, FormControlLabel, Checkbox, SvgIcon, IconButton, Tooltip } from '@mui/material'
import type { SessionTypes } from '@walletconnect/types'
import type { ReactElement } from 'react'

import { Hints } from '../Hints'
import SessionList from '../SessionList'
import WcInput from '../WcInput'
import InfoIcon from '@/public/images/notifications/info.svg'
import { WalletConnectHeader } from '../SessionManager/Header'

import css from './styles.module.css'

const WC_HINTS_KEY = 'wcHints'

export const ConnectionForm = ({
sessions,
onDisconnect,
}: {
sessions: SessionTypes.Struct[]
onDisconnect: (session: SessionTypes.Struct) => Promise<void>
}): ReactElement => {
const [hideHints = false, setHideHints] = useLocalStorage<boolean>(WC_HINTS_KEY)

return (
<Grid className={css.container}>
<Grid item textAlign="center">
{hideHints && (
<Tooltip title="How does WalletConnect work?" placement="top">
<span>
<IconButton onClick={() => setHideHints(false)} className={css.infoIcon}>
<SvgIcon component={InfoIcon} inheritViewBox color="border" />
</IconButton>
</span>
</Tooltip>
)}

<WalletConnectHeader />

<Typography variant="body2" color="text.secondary" mb={3}>
Connnect your Safe to any dApp via WalletConnect and trigger transactions
</Typography>

<WcInput />
</Grid>

<Divider flexItem className={css.divider} />

<Grid item>
<SessionList sessions={sessions} onDisconnect={onDisconnect} />
</Grid>

{!hideHints && (
<>
<Divider flexItem className={css.divider} />

<Grid item>
<Hints />

<FormControlLabel
control={<Checkbox checked={hideHints} onChange={(_, checked) => setHideHints(checked)} />}
label="Don't show this anymore"
sx={{ mt: 1 }}
/>
</Grid>
</>
)}
</Grid>
)
}
21 changes: 21 additions & 0 deletions src/components/walletconnect/ConnectionForm/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.container :global .MuiGrid-item {
padding: var(--space-3) 0;
}

.container :global .MuiGrid-item:first-of-type {
padding: 0 0 var(--space-3) 0;
}

.container :global .MuiGrid-item:last-of-type {
padding: var(--space-3) 0 0 0;
}

.infoIcon {
position: absolute;
top: var(--space-3);
right: var(--space-3);
}

.divider {
margin: 0 calc(-1 * var(--space-4));
}
51 changes: 41 additions & 10 deletions src/components/walletconnect/HeaderWidget/index.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,55 @@
import { useCallback, useContext, useRef, useState } from 'react'
import { Badge, Box } from '@mui/material'
import { useCallback, useContext, useEffect, useRef, useState } from 'react'
import { Badge } from '@mui/material'
import type { CoreTypes, SessionTypes } from '@walletconnect/types'
import type { ReactElement } from 'react'

import { WalletConnectContext } from '@/services/walletconnect/WalletConnectContext'
import useWalletConnectSessions from '@/services/walletconnect/useWalletConnectSessions'
import Icon from './Icon'
import SessionManager from '../SessionManager'
import Popup from '../Popup'
import { useWalletConnectSearchParamUri } from '@/services/walletconnect/useWalletConnectSearchParamUri'
import { SuccessBanner } from '../SuccessBanner'

const WalletConnectHeaderWidget = () => {
const { error } = useContext(WalletConnectContext)
const WalletConnectHeaderWidget = (): ReactElement => {
const { error, walletConnect } = useContext(WalletConnectContext)
const [popupOpen, setPopupOpen] = useState(false)
const [wcUri] = useWalletConnectSearchParamUri()
const iconRef = useRef<HTMLDivElement>(null)
const sessions = useWalletConnectSessions()
const [metadata, setMetadata] = useState<CoreTypes.Metadata>()

const onOpen = useCallback(() => setPopupOpen(true), [])
const onClose = useCallback(() => setPopupOpen(false), [])
const onOpenSessionManager = useCallback(() => setPopupOpen(true), [])
const onCloseSessionManager = useCallback(() => setPopupOpen(false), [])

const onCloseSuccesBanner = useCallback(() => setMetadata(undefined), [])
const onSuccess = useCallback(
({ peer }: SessionTypes.Struct) => {
onCloseSessionManager()

// Show success banner
setMetadata(peer.metadata)

setTimeout(() => {
onCloseSuccesBanner()
}, 2_000)
},
[onCloseSessionManager, onCloseSuccesBanner],
)

useEffect(() => {
if (!walletConnect) {
return
}

return walletConnect.onSessionAdd(onSuccess)
}, [onSuccess, walletConnect])

return (
<Box display="flex">
<>
<div ref={iconRef}>
<Icon
onClick={onOpen}
onClick={onOpenSessionManager}
sessionCount={sessions.length}
sessionInfo={
sessions[0]
Expand All @@ -33,10 +60,14 @@ const WalletConnectHeaderWidget = () => {
<Badge color="error" variant="dot" invisible={!error} />
</div>

<Popup anchorEl={iconRef.current} open={popupOpen || !!wcUri} onClose={onClose} keepMounted>
<Popup anchorEl={iconRef.current} open={popupOpen || !!wcUri} onClose={onCloseSessionManager} keepMounted>
<SessionManager sessions={sessions} />
</Popup>
</Box>

<Popup anchorEl={iconRef.current} open={!!metadata} onClose={onCloseSuccesBanner}>
{metadata && <SuccessBanner metadata={metadata} />}
</Popup>
</>
)
}

Expand Down
53 changes: 53 additions & 0 deletions src/components/walletconnect/Hints/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { Accordion, AccordionSummary, Typography, AccordionDetails, SvgIcon } from '@mui/material'
import type { TypographyProps } from '@mui/material'
import type { ReactElement } from 'react'

import Question from '@/public/images/common/question.svg'

const AccordionTitle = ({ children }: { children: TypographyProps['children'] }): ReactElement => {
return (
<Typography sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<SvgIcon
component={Question}
inheritViewBox
sx={{ color: 'currentColor', verticalAlign: 'middle', mr: 1 }}
fontSize="inherit"
/>
{children}
</Typography>
)
}

// TODO: Add content to the hints
export const Hints = (): ReactElement => {
return (
<>
<Accordion sx={{ mb: 1 }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<AccordionTitle>How do I connect to a dApp?</AccordionTitle>
</AccordionSummary>

<AccordionDetails>
<Typography>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</Typography>
</AccordionDetails>
</Accordion>

<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<AccordionTitle>How do I interact with a dApp?</AccordionTitle>
</AccordionSummary>

<AccordionDetails>
<Typography>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit
leo lobortis eget.
</Typography>
</AccordionDetails>
</Accordion>
</>
)
}
5 changes: 3 additions & 2 deletions src/components/walletconnect/Popup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Paper, Popover } from '@mui/material'
import type { PopoverProps } from '@mui/material'
import type { ReactElement } from 'react'

const Popup = ({ children, ...props }: PopoverProps) => {
const Popup = ({ children, ...props }: PopoverProps): ReactElement => {
return (
<Popover
anchorOrigin={{
Expand All @@ -14,7 +15,7 @@ const Popup = ({ children, ...props }: PopoverProps) => {
}}
{...props}
>
<Paper sx={{ p: 4 }}>{children}</Paper>
<Paper sx={{ p: 4, width: '454px' }}>{children}</Paper>
</Popover>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { AlertColor } from '@mui/material'
import AlertIcon from '@/public/images/notifications/alert.svg'

import type { Verify } from '@walletconnect/types'
import type { ComponentType } from 'react'
import type { ComponentType, ReactElement } from 'react'
import CloseIcon from '@/public/images/common/close.svg'
import InfoIcon from '@/public/images/notifications/info.svg'
import CheckIcon from '@/public/images/common/check.svg'
Expand Down Expand Up @@ -34,9 +34,14 @@ const Validation: {
},
}

const ProposalVerification = ({ proposal }: { proposal: Web3WalletTypes.SessionProposal }) => {
const ProposalVerification = ({ proposal }: { proposal: Web3WalletTypes.SessionProposal }): ReactElement | null => {
const { proposer } = proposal.params
const { isScam, validation } = proposal.verifyContext.verified

if (validation === 'UNKNOWN') {
return null
}

const _validation = Validation[validation]
const color = isScam ? 'error' : _validation.color
const Icon = isScam ? AlertIcon : _validation.Icon
Expand Down
27 changes: 27 additions & 0 deletions src/components/walletconnect/ProposalForm/UnsupportedChain.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Alert, AlertTitle, Typography } from '@mui/material'
import type { ReactElement } from 'react'

import ChainIndicator from '@/components/common/ChainIndicator'

import css from './styles.module.css'

export const UnsupportedChain = ({ chainIds }: { chainIds: Array<string> }): ReactElement => {
return (
<>
<Alert severity="info" className={css.alert}>
<AlertTitle>dApp does not support Safe network</AlertTitle>
If you want to interact with this dApp, please switch to a Safe on a supported network.
</Alert>

<Typography mt={3} mb={1}>
Supported chains
</Typography>

<div>
{chainIds.map((chainId) => (
<ChainIndicator inline chainId={chainId} key={chainId} className={css.chain} />
))}
</div>
</>
)
}
Loading
Loading