182 lines
5.5 KiB
JavaScript
182 lines
5.5 KiB
JavaScript
import React, { Suspense, useState } from 'react';
|
|
import { makeStyles, List, ListItem } from '@material-ui/core';
|
|
import CssBaseline from '@material-ui/core/CssBaseline';
|
|
import useMediaQuery from '@material-ui/core/useMediaQuery';
|
|
import {
|
|
ThemeProvider,
|
|
unstable_createMuiStrictModeTheme as createMuiTheme,
|
|
} from '@material-ui/core/styles';
|
|
import blue from '@material-ui/core/colors/blue';
|
|
import DialogTitle from '@material-ui/core/DialogTitle';
|
|
import DialogContent from '@material-ui/core/DialogContent';
|
|
import DialogActions from '@material-ui/core/DialogActions';
|
|
import Button from '@material-ui/core/Button';
|
|
import Typography from '@material-ui/core/Typography';
|
|
import DialogForm from './components/DialogForm';
|
|
import NavigationFrame from './components/NavigationFrame';
|
|
import { ConnectionProvider } from './utils/connection';
|
|
import WalletPage from './pages/WalletPage';
|
|
import { useWallet, WalletProvider } from './utils/wallet';
|
|
import { ConnectedWalletsProvider } from './utils/connected-wallets';
|
|
import { TokenRegistryProvider } from './utils/tokens/names';
|
|
import LoadingIndicator from './components/LoadingIndicator';
|
|
import { SnackbarProvider } from 'notistack';
|
|
import PopupPage from './pages/PopupPage';
|
|
import LoginPage from './pages/LoginPage';
|
|
import ConnectionsPage from './pages/ConnectionsPage';
|
|
import { isExtension } from './utils/utils';
|
|
import { PageProvider, usePage } from './utils/page';
|
|
|
|
export default function App() {
|
|
// TODO: add toggle for dark mode
|
|
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
|
const theme = React.useMemo(
|
|
() =>
|
|
createMuiTheme({
|
|
palette: {
|
|
type: prefersDarkMode ? 'dark' : 'light',
|
|
primary: blue,
|
|
},
|
|
// TODO consolidate popup dimensions
|
|
ext: '450',
|
|
}),
|
|
[prefersDarkMode],
|
|
);
|
|
|
|
// Disallow rendering inside an iframe to prevent clickjacking.
|
|
if (window.self !== window.top) {
|
|
return null;
|
|
}
|
|
|
|
let appElement = (
|
|
<NavigationFrame>
|
|
<Suspense fallback={<LoadingIndicator />}>
|
|
<PageContents />
|
|
</Suspense>
|
|
</NavigationFrame>
|
|
);
|
|
|
|
if (isExtension) {
|
|
appElement = (
|
|
<ConnectedWalletsProvider>
|
|
<PageProvider>{appElement}</PageProvider>
|
|
</ConnectedWalletsProvider>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Suspense fallback={<LoadingIndicator />}>
|
|
<ThemeProvider theme={theme}>
|
|
<CssBaseline />
|
|
|
|
<ConnectionProvider>
|
|
<TokenRegistryProvider>
|
|
<SnackbarProvider maxSnack={5} autoHideDuration={8000}>
|
|
<WalletProvider>{appElement}</WalletProvider>
|
|
</SnackbarProvider>
|
|
</TokenRegistryProvider>
|
|
</ConnectionProvider>
|
|
</ThemeProvider>
|
|
</Suspense>
|
|
);
|
|
}
|
|
|
|
function PageContents() {
|
|
const wallet = useWallet();
|
|
const [page] = usePage();
|
|
const [showWalletSuggestion, setShowWalletSuggestion] = useState(true);
|
|
const suggestionKey = 'private-irgnore-wallet-suggestion';
|
|
const ignoreSuggestion = window.localStorage.getItem(suggestionKey);
|
|
if (!wallet) {
|
|
return (
|
|
<>
|
|
{!ignoreSuggestion && (
|
|
<WalletSuggestionDialog
|
|
open={showWalletSuggestion}
|
|
onClose={() => setShowWalletSuggestion(false)}
|
|
onIgnore={() => {
|
|
window.localStorage.setItem(suggestionKey, true);
|
|
setShowWalletSuggestion(false);
|
|
}}
|
|
/>
|
|
)}
|
|
<LoginPage />
|
|
</>
|
|
);
|
|
}
|
|
if (window.opener) {
|
|
return <PopupPage opener={window.opener} />;
|
|
}
|
|
if (page === 'wallet') {
|
|
return <WalletPage />;
|
|
} else if (page === 'connections') {
|
|
return <ConnectionsPage />;
|
|
}
|
|
}
|
|
|
|
const useStyles = makeStyles(() => ({
|
|
walletButton: {
|
|
width: '100%',
|
|
padding: '16px',
|
|
'&:hover': {
|
|
cursor: 'pointer',
|
|
},
|
|
},
|
|
}));
|
|
|
|
function WalletSuggestionDialog({ open, onClose, onIgnore }) {
|
|
const classes = useStyles();
|
|
return (
|
|
<DialogForm open={open} onClose={onClose} fullWidth>
|
|
<DialogTitle>Looking for a Wallet?</DialogTitle>
|
|
<DialogContent>
|
|
<Typography>
|
|
For the best Solana experience, it is recommended to use{' '}
|
|
<b>Backpack</b>
|
|
</Typography>
|
|
<List disablePadding style={{ marginTop: '16px' }}>
|
|
<ListItem button disablePadding style={{ padding: 0 }}>
|
|
<div
|
|
className={classes.walletButton}
|
|
style={{ display: 'flex' }}
|
|
onClick={() => {
|
|
window.location = 'https://backpack.app/download';
|
|
}}
|
|
>
|
|
<div>
|
|
<img
|
|
alt=""
|
|
style={{ height: '39px' }}
|
|
src="https://github.com/coral-xyz/backpack/raw/master/assets/backpack.png"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<Typography
|
|
style={{
|
|
marginLeft: '16px',
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
flexDirection: 'column',
|
|
height: '39px',
|
|
fontWeight: 'bold',
|
|
}}
|
|
>
|
|
Backpack
|
|
</Typography>
|
|
</div>
|
|
</div>
|
|
</ListItem>
|
|
</List>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button type="submit" color="primary" onClick={onIgnore}>
|
|
Ignore Future Dialog
|
|
</Button>
|
|
<Button type="submit" color="primary" onClick={onClose}>
|
|
Ok
|
|
</Button>
|
|
</DialogActions>
|
|
</DialogForm>
|
|
);
|
|
}
|