Tweak deposit dialog layout
This commit is contained in:
parent
25b6604487
commit
21e8770ef0
|
@ -82,7 +82,7 @@ export default function AddTokenDialog({ open, onClose }) {
|
|||
{tokenAccountCost ? (
|
||||
<DialogContentText>
|
||||
Add a token to your wallet. This will cost{' '}
|
||||
{feeFormat.format(tokenAccountCost / LAMPORTS_PER_SOL)} Solana.
|
||||
{feeFormat.format(tokenAccountCost / LAMPORTS_PER_SOL)} SOL.
|
||||
</DialogContentText>
|
||||
) : (
|
||||
<LoadingIndicator />
|
||||
|
|
|
@ -13,6 +13,7 @@ import LoadingIndicator from './LoadingIndicator';
|
|||
import Collapse from '@material-ui/core/Collapse';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import TokenInfoDialog from './TokenInfoDialog';
|
||||
import Link from '@material-ui/core/Link';
|
||||
import ExpandLess from '@material-ui/icons/ExpandLess';
|
||||
import ExpandMore from '@material-ui/icons/ExpandMore';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
@ -25,12 +26,16 @@ import Toolbar from '@material-ui/core/Toolbar';
|
|||
import AddIcon from '@material-ui/icons/Add';
|
||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import InfoIcon from '@material-ui/icons/Info';
|
||||
import InfoIcon from '@material-ui/icons/InfoOutlined';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import AddTokenDialog from './AddTokenDialog';
|
||||
import SendDialog from './SendDialog';
|
||||
import DepositDialog from './DepositDialog';
|
||||
import { refreshAccountInfo } from '../utils/connection';
|
||||
import {
|
||||
refreshAccountInfo,
|
||||
useSolanaExplorerUrlSuffix,
|
||||
} from '../utils/connection';
|
||||
import { showTokenInfoDialog } from '../utils/config';
|
||||
|
||||
const balanceFormat = new Intl.NumberFormat(undefined, {
|
||||
minimumFractionDigits: 4,
|
||||
|
@ -106,15 +111,12 @@ function BalanceListItem({ publicKey }) {
|
|||
const balanceInfo = useBalanceInfo(publicKey);
|
||||
const classes = useStyles();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [sendDialogOpen, setSendDialogOpen] = useState(false);
|
||||
const [depositDialogOpen, setDepositDialogOpen] = useState(false);
|
||||
const [tokenInfoDialogOpen, setTokenInfoDialogOpen] = useState(false);
|
||||
|
||||
if (!balanceInfo) {
|
||||
return <LoadingIndicator delay={0} />;
|
||||
}
|
||||
|
||||
let { amount, decimals, mint, tokenName, tokenSymbol, owner } = balanceInfo;
|
||||
let { amount, decimals, mint, tokenName, tokenSymbol } = balanceInfo;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -133,37 +135,86 @@ function BalanceListItem({ publicKey }) {
|
|||
{open ? <ExpandLess /> : <ExpandMore />}
|
||||
</ListItem>
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<div className={classes.itemDetails}>
|
||||
<div className={classes.buttonContainer}>
|
||||
{!publicKey.equals(owner) && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="inherit"
|
||||
startIcon={<InfoIcon />}
|
||||
onClick={() => setTokenInfoDialogOpen(true)}
|
||||
>
|
||||
Token Info
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
startIcon={<ReceiveIcon />}
|
||||
onClick={() => setDepositDialogOpen(true)}
|
||||
>
|
||||
Receive
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
startIcon={<SendIcon />}
|
||||
onClick={() => setSendDialogOpen(true)}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<BalanceListItemDetails
|
||||
publicKey={publicKey}
|
||||
balanceInfo={balanceInfo}
|
||||
/>
|
||||
</Collapse>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function BalanceListItemDetails({ publicKey, balanceInfo }) {
|
||||
const urlSuffix = useSolanaExplorerUrlSuffix();
|
||||
const classes = useStyles();
|
||||
const [sendDialogOpen, setSendDialogOpen] = useState(false);
|
||||
const [depositDialogOpen, setDepositDialogOpen] = useState(false);
|
||||
const [tokenInfoDialogOpen, setTokenInfoDialogOpen] = useState(false);
|
||||
|
||||
if (!balanceInfo) {
|
||||
return <LoadingIndicator delay={0} />;
|
||||
}
|
||||
|
||||
let { mint, tokenName, tokenSymbol, owner } = balanceInfo;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={classes.itemDetails}>
|
||||
<div className={classes.buttonContainer}>
|
||||
{!publicKey.equals(owner) && showTokenInfoDialog ? (
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="default"
|
||||
startIcon={<InfoIcon />}
|
||||
onClick={() => setTokenInfoDialogOpen(true)}
|
||||
>
|
||||
Token Info
|
||||
</Button>
|
||||
) : null}
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
startIcon={<ReceiveIcon />}
|
||||
onClick={() => setDepositDialogOpen(true)}
|
||||
>
|
||||
Receive
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
startIcon={<SendIcon />}
|
||||
onClick={() => setSendDialogOpen(true)}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</div>
|
||||
<Typography variant="body2" className={classes.address}>
|
||||
Deposit Address: {publicKey.toBase58()}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
Token Name: {tokenName ?? 'Unknown'}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
Token Symbol: {tokenSymbol ?? 'Unknown'}
|
||||
</Typography>
|
||||
{mint ? (
|
||||
<Typography variant="body2" className={classes.address}>
|
||||
Token Address: {mint.toBase58()}
|
||||
</Typography>
|
||||
) : null}
|
||||
<Typography variant="body2">
|
||||
<Link
|
||||
href={
|
||||
`https://explorer.solana.com/account/${publicKey.toBase58()}` +
|
||||
urlSuffix
|
||||
}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
View on Solana Explorer
|
||||
</Link>
|
||||
</Typography>
|
||||
</div>
|
||||
<SendDialog
|
||||
open={sendDialogOpen}
|
||||
onClose={() => setSendDialogOpen(false)}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import React, { useRef } from 'react';
|
||||
import { Button, TextField } from '@material-ui/core';
|
||||
import { TextField } from '@material-ui/core';
|
||||
import CopyIcon from 'mdi-material-ui/ContentCopy';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import QrcodeIcon from 'mdi-material-ui/Qrcode';
|
||||
import QRCode from 'qrcode.react';
|
||||
import DialogForm from './DialogForm';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
|
@ -10,21 +15,13 @@ const useStyles = makeStyles((theme) => ({
|
|||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
button: {
|
||||
marginLeft: theme.spacing(3),
|
||||
whiteSpace: 'nowrap',
|
||||
marginTop: theme.spacing(2),
|
||||
},
|
||||
buttonIcon: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
}));
|
||||
|
||||
export default function CopyableDisplay({
|
||||
value,
|
||||
label,
|
||||
autoFocus,
|
||||
buttonProps,
|
||||
qrCode,
|
||||
helperText,
|
||||
}) {
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
|
@ -57,14 +54,37 @@ export default function CopyableDisplay({
|
|||
label={label}
|
||||
spellCheck={false}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={copyLink}
|
||||
className={classes.button}
|
||||
{...buttonProps}
|
||||
>
|
||||
<CopyIcon className={classes.buttonIcon} /> {'Copy'}
|
||||
</Button>
|
||||
<IconButton onClick={copyLink}>
|
||||
<CopyIcon />
|
||||
</IconButton>
|
||||
{qrCode ? <Qrcode value={value} /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const useQrCodeStyles = makeStyles((theme) => ({
|
||||
qrcodeContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
function Qrcode({ value }) {
|
||||
const [showQrcode, setShowQrcode] = React.useState(false);
|
||||
const classes = useQrCodeStyles();
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconButton onClick={() => setShowQrcode(true)}>
|
||||
<QrcodeIcon />
|
||||
</IconButton>
|
||||
<DialogForm open={showQrcode} onClose={() => setShowQrcode(false)}>
|
||||
<DialogContent className={classes.qrcodeContainer}>
|
||||
<QRCode value={value} size={256} includeMargin />
|
||||
</DialogContent>
|
||||
</DialogForm>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,11 +3,12 @@ import DialogTitle from '@material-ui/core/DialogTitle';
|
|||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogForm from './DialogForm';
|
||||
import { abbreviateAddress } from '../utils/utils';
|
||||
import { Button, Typography } from '@material-ui/core';
|
||||
import CopyableDisplay from './CopyableDisplay';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import QrcodeIcon from 'mdi-material-ui/Qrcode';
|
||||
import QRCode from 'qrcode.react';
|
||||
import Link from '@material-ui/core/Link';
|
||||
import { useSolanaExplorerUrlSuffix } from '../utils/connection';
|
||||
import DialogContentText from '@material-ui/core/DialogContentText';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
export default function DepositDialog({
|
||||
open,
|
||||
|
@ -15,72 +16,50 @@ export default function DepositDialog({
|
|||
publicKey,
|
||||
balanceInfo,
|
||||
}) {
|
||||
const urlSuffix = useSolanaExplorerUrlSuffix();
|
||||
let { mint, tokenName, tokenSymbol, owner } = balanceInfo;
|
||||
|
||||
return (
|
||||
<DialogForm open={open} onClose={onClose}>
|
||||
<DialogTitle>
|
||||
Deposit {tokenName ?? abbreviateAddress(mint)}
|
||||
Deposit {tokenName ?? mint.toBase58()}
|
||||
{tokenSymbol ? ` (${tokenSymbol})` : null}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
{publicKey.equals(owner) ? (
|
||||
<Typography>
|
||||
<DialogContentText>
|
||||
This address can only be used to receive SOL. Do not send other
|
||||
tokens to this address.
|
||||
</Typography>
|
||||
</DialogContentText>
|
||||
) : (
|
||||
<Typography>
|
||||
This address can only be used to receive {tokenSymbol}. Do not send
|
||||
SOL to this address.
|
||||
</Typography>
|
||||
<DialogContentText>
|
||||
This address can only be used to receive{' '}
|
||||
{tokenSymbol ?? abbreviateAddress(mint)}. Do not send SOL to this
|
||||
address.
|
||||
</DialogContentText>
|
||||
)}
|
||||
<CopyableDisplay
|
||||
value={publicKey.toBase58()}
|
||||
label={'Deposit Address'}
|
||||
autoFocus
|
||||
qrCode
|
||||
/>
|
||||
<Qrcode value={publicKey.toBase58()} />
|
||||
<DialogContentText variant="body2">
|
||||
<Link
|
||||
href={
|
||||
`https://explorer.solana.com/account/${publicKey.toBase58()}` +
|
||||
urlSuffix
|
||||
}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
View on Solana Explorer
|
||||
</Link>
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onClose}>Close</Button>
|
||||
</DialogActions>
|
||||
</DialogForm>
|
||||
);
|
||||
}
|
||||
|
||||
const useQrCodeStyles = makeStyles((theme) => ({
|
||||
qrcodeButton: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
qrcodeIcon: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
qrcodeContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
function Qrcode({ value }) {
|
||||
const [showQrcode, setShowQrcode] = React.useState(false);
|
||||
|
||||
const classes = useQrCodeStyles();
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => setShowQrcode(!showQrcode)}
|
||||
className={classes.qrcodeButton}
|
||||
>
|
||||
<QrcodeIcon className={classes.qrcodeIcon} />
|
||||
{showQrcode ? 'Hide QR Code' : 'Show QR Code'}
|
||||
</Button>
|
||||
{showQrcode && (
|
||||
<div className={classes.qrcodeContainer}>
|
||||
<QRCode value={value} size={256} includeMargin />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import Tooltip from '@material-ui/core/Tooltip';
|
|||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
paddingTop: theme.spacing(3),
|
||||
paddingBottom: theme.spacing(3),
|
||||
paddingLeft: theme.spacing(1),
|
||||
|
@ -49,34 +50,10 @@ export default function NavigationFrame({ children }) {
|
|||
</Typography>
|
||||
<WalletSelector />
|
||||
<NetworkSelector />
|
||||
<Hidden xsDown>
|
||||
<Button
|
||||
component="a"
|
||||
color="inherit"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
href="https://github.com/serum-foundation/spl-token-wallet"
|
||||
className={classes.button}
|
||||
>
|
||||
Source
|
||||
</Button>
|
||||
</Hidden>
|
||||
<Hidden smUp>
|
||||
<Tooltip title="View Source" arrow>
|
||||
<IconButton
|
||||
component="a"
|
||||
color="inherit"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
href="https://github.com/serum-foundation/spl-token-wallet"
|
||||
>
|
||||
<CodeIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Hidden>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<main className={classes.content}>{children}</main>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -215,3 +192,30 @@ function WalletSelector() {
|
|||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const useFooterStyles = makeStyles((theme) => ({
|
||||
footer: {
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
margin: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
function Footer() {
|
||||
const classes = useFooterStyles();
|
||||
return (
|
||||
<footer className={classes.footer}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
component="a"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
href="https://github.com/serum-foundation/spl-token-wallet"
|
||||
startIcon={<CodeIcon />}
|
||||
>
|
||||
View Source
|
||||
</Button>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,11 @@ body {
|
|||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
html, body, #root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export const showTokenInfoDialog = !!localStorage.getItem(
|
||||
'showTokenInfoDialog',
|
||||
);
|
Loading…
Reference in New Issue