on master help sign in
Rearranged login view
0b5533cLiam Fitzgerald
src/views/Login.js+7−30
@@ -13,51 +13,28 @@ import Footer from 'components/Footer';
13import { ForwardButton, OfflineButton } from 'components/Buttons';
13import { ForwardButton, OfflineButton } from 'components/Buttons';
14
14
15import Ticket from './Login/Ticket';
15import Ticket from './Login/Ticket';
16−import Mnemonic from './Login/Mnemonic';
16+import Other from './Login/Other';
17−import Advanced from './Login/Advanced';
18−import Hardware from './Login/Hardware';
19−import Metamask from './Login/Metamask';
20
17
21const NAMES = {
18const NAMES = {
22 TICKET: 'TICKET',
19 TICKET: 'TICKET',
23− MNEMONIC: 'MNEMONIC',
20+ OTHER: 'OTHER',
24− HARDWARE: 'HARDWARE',
25− ADVANCED: 'ADVANCED',
26− METAMASK: 'METAMASK',
27};
21};
28
22
29const VIEWS = {
23const VIEWS = {
30 [NAMES.TICKET]: Ticket,
24 [NAMES.TICKET]: Ticket,
31− [NAMES.MNEMONIC]: Mnemonic,
25+ [NAMES.OTHER]: Other,
32− [NAMES.HARDWARE]: Hardware,
33− [NAMES.ADVANCED]: Advanced,
34− [NAMES.METAMASK]: Metamask,
35};
26};
36
27
37const OPTIONS = [
28const OPTIONS = [
38 { text: 'Master Ticket', value: NAMES.TICKET },
29 { text: 'Master Ticket', value: NAMES.TICKET },
39− { text: 'Mnemonic', value: NAMES.MNEMONIC },
30+ { text: 'Other', value: NAMES.OTHER },
40− { text: 'Hardware', value: NAMES.HARDWARE },
41− { text: 'Advanced', value: NAMES.ADVANCED },
42− { text: 'Metamask', value: NAMES.METAMASK },
43];
31];
44
32
45const walletTypeToViewName = walletType => {
33const walletTypeToViewName = walletType => {
46− switch (walletType) {
34+ if (walletType === WALLET_TYPES.TICKET || !walletType) {
47− case WALLET_TYPES.MNEMONIC:
48− return NAMES.MNEMONIC;
49− case WALLET_TYPES.LEDGER:
50− case WALLET_TYPES.TREZOR:
51− return NAMES.HARDWARE;
52− case WALLET_TYPES.KEYSTORE:
53− case WALLET_TYPES.PRIVATE_KEY:
54− return NAMES.ADVANCED;
55− case WALLET_TYPES.TICKET:
56− case WALLET_TYPES.SHARDS:
57− return NAMES.TICKET;
58− default:
59− return NAMES.TICKET;
35+ return NAMES.TICKET;
60 }
36 }
37+ return NAMES.OTHER;
61};
38};
62
39
63export default function Login() {
40export default function Login() {
src/views/Login/Metamask.js+27−24
@@ -1,5 +1,4 @@
1import React, { useCallback } from 'react';
1import React, { useCallback } from 'react';
2−import cn from 'classnames';
3import { Grid, Text, LinkButton, H5 } from 'indigo-react';
2import { Grid, Text, LinkButton, H5 } from 'indigo-react';
4import { Just } from 'folktale/maybe';
3import { Just } from 'folktale/maybe';
5
4
@@ -7,11 +6,13 @@ import { useWallet } from 'store/wallet';
7
6
8import { WALLET_TYPES } from 'lib/wallet';
7import { WALLET_TYPES } from 'lib/wallet';
9import { MetamaskWallet } from 'lib/metamask';
8import { MetamaskWallet } from 'lib/metamask';
9+import useLoginView from 'lib/useLoginView';
10
10
11import SubmitButton from 'form/SubmitButton';
11import SubmitButton from 'form/SubmitButton';
12import BridgeForm from 'form/BridgeForm';
12import BridgeForm from 'form/BridgeForm';
13
13
14export default function Metamask({ className, goHome }) {
14export default function Metamask({ className, goHome }) {
15+ useLoginView(WALLET_TYPES.METAMASK);
15 const { setWallet, setWalletType } = useWallet();
16 const { setWallet, setWalletType } = useWallet();
16
17
17 const onSubmit = useCallback(async () => {
18 const onSubmit = useCallback(async () => {
@@ -19,9 +20,32 @@ export default function Metamask({ className, goHome }) {
19 const wallet = new MetamaskWallet(accounts[0]);
20 const wallet = new MetamaskWallet(accounts[0]);
20 setWallet(Just(wallet));
21 setWallet(Just(wallet));
21 setWalletType(WALLET_TYPES.METAMASK);
22 setWalletType(WALLET_TYPES.METAMASK);
22− }, [setWallet]);
23+ }, [setWallet, setWalletType]);
23
24
24− const login = () => (
25+ return (
26+ <Grid className={className}>
27+ {(window.ethereum && Login({ onSubmit, goHome })) || Unsupported()}
28+ </Grid>
29+ );
30+}
31+
32+function Unsupported() {
33+ return (
34+ <>
35+ <Grid.Item full as={H5}>
36+ Unsupported
37+ </Grid.Item>
38+ <Grid.Item full as={Text} className="f6 mb3">
39+ Metamask is not installed on this browser. <br />
40+ <LinkButton href="https://metamask.io" as={LinkButton}>
41+ Get Metamask
42+ </LinkButton>
43+ </Grid.Item>
44+ </>
45+ );
46+}
47+function Login({ onSubmit, goHome }) {
48+ return (
25 <>
49 <>
26 <Grid.Item full as={H5}>
50 <Grid.Item full as={H5}>
27 Authenticate with Metamask
51 Authenticate with Metamask
@@ -41,25 +65,4 @@ export default function Metamask({ className, goHome }) {
41 </BridgeForm>
65 </BridgeForm>
42 </>
66 </>
43 );
67 );
44− return (
45− <Grid className={cn('mt4', className)}>
46− {(window.ethereum && login()) || MetamaskUnsupported()}
47− </Grid>
48− );
49−}
50−
51−function MetamaskUnsupported() {
52− return (
53− <>
54− <Grid.Item full as={H5}>
55− Metamask unsupported
56− </Grid.Item>
57− <Grid.Item full as={Text} className="f6 mb3">
58− Metamask is not installed on this browser.
59− <LinkButton href="https://metamask.io" as={LinkButton}>
60− Get Metamask
61− </LinkButton>
62− </Grid.Item>
63− </>
64− );
65}
68}
src/views/Login/Other.jsnew file+67
@@ -0,0 +1,67 @@
1+import React, { useState, useMemo } from 'react';
2+
3+import useBreakpoints from 'lib/useBreakpoints';
4+
5+import Accordion from 'components/Accordion';
6+
7+import PrivateKey from './PrivateKey';
8+import Keystore from './Keystore';
9+import Ledger from './Ledger';
10+import Metamask from './Metamask';
11+import Trezor from './Trezor';
12+import Mnemonic from './Mnemonic';
13+
14+const NAMES = {
15+ PRIVATE_KEY: 'PRIVATE_KEY',
16+ KEYSTORE: 'KEYSTORE',
17+ LEDGER: 'LEDGER',
18+ TREZOR: 'TREZOR',
19+ METAMASK: 'METAMASK',
20+ MNEMONIC: 'MNEMONIC',
21+};
22+
23+const VIEWS = {
24+ [NAMES.PRIVATE_KEY]: PrivateKey,
25+ [NAMES.KEYSTORE]: Keystore,
26+ [NAMES.LEDGER]: Ledger,
27+ [NAMES.TREZOR]: Trezor,
28+ [NAMES.METAMASK]: Metamask,
29+ [NAMES.MNEMONIC]: Mnemonic,
30+};
31+
32+const OPTIONS = [
33+ { text: 'Mnemonic (BIP 39)', value: NAMES.MNEMONIC },
34+ { text: 'Ledger', value: NAMES.LEDGER },
35+ { text: 'Trezor', value: NAMES.TREZOR },
36+ { text: 'Metamask', value: NAMES.METAMASK },
37+ { text: 'Ethereum Private Key', value: NAMES.PRIVATE_KEY },
38+ { text: 'Ethereum Keystore', value: NAMES.KEYSTORE },
39+];
40+
41+const isHardware = name => !![NAMES.TREZOR, NAMES.LEDGER].find(n => n === name);
42+
43+export default function Other({ className, ...rest }) {
44+ const [currentTab, setCurrentTab] = useState(undefined);
45+
46+ const hardwareAllowed = useBreakpoints([false, true, true]);
47+ const options = useMemo(
48+ () =>
49+ OPTIONS.map(o =>
50+ !isHardware(o.value)
51+ ? o
52+ : { ...o, disabled: !hardwareAllowed && ' not available on mobile' }
53+ ),
54+ [hardwareAllowed]
55+ );
56+ return (
57+ <Accordion
58+ className={className}
59+ views={VIEWS}
60+ options={options}
61+ currentTab={currentTab}
62+ onTabChange={setCurrentTab}
63+ //
64+ {...rest}
65+ />
66+ );
67+}