on master help sign in
Merge pull request #409 from urbit/jy/login-screen
dc70bbdJimmy
package-lock.json+11−30
@@ -6958,8 +6958,7 @@
6958 },
6958 },
6959 "ansi-regex": {
6959 "ansi-regex": {
6960 "version": "2.1.1",
6960 "version": "2.1.1",
6961− "bundled": true,
6961+ "bundled": true
6962− "optional": true
6963 },
6962 },
6964 "aproba": {
6963 "aproba": {
6965 "version": "1.2.0",
6964 "version": "1.2.0",
@@ -6977,13 +6976,11 @@
6977 },
6976 },
6978 "balanced-match": {
6977 "balanced-match": {
6979 "version": "1.0.0",
6978 "version": "1.0.0",
6980− "bundled": true,
6979+ "bundled": true
6981− "optional": true
6982 },
6980 },
6983 "brace-expansion": {
6981 "brace-expansion": {
6984 "version": "1.1.11",
6982 "version": "1.1.11",
6985 "bundled": true,
6983 "bundled": true,
6986− "optional": true,
6987 "requires": {
6984 "requires": {
6988 "balanced-match": "^1.0.0",
6985 "balanced-match": "^1.0.0",
6989 "concat-map": "0.0.1"
6986 "concat-map": "0.0.1"
@@ -6996,18 +6993,15 @@
6996 },
6993 },
6997 "code-point-at": {
6994 "code-point-at": {
6998 "version": "1.1.0",
6995 "version": "1.1.0",
6999− "bundled": true,
6996+ "bundled": true
7000− "optional": true
7001 },
6997 },
7002 "concat-map": {
6998 "concat-map": {
7003 "version": "0.0.1",
6999 "version": "0.0.1",
7004− "bundled": true,
7000+ "bundled": true
7005− "optional": true
7006 },
7001 },
7007 "console-control-strings": {
7002 "console-control-strings": {
7008 "version": "1.1.0",
7003 "version": "1.1.0",
7009− "bundled": true,
7004+ "bundled": true
7010− "optional": true
7011 },
7005 },
7012 "core-util-is": {
7006 "core-util-is": {
7013 "version": "1.0.2",
7007 "version": "1.0.2",
@@ -7110,8 +7104,7 @@
7110 },
7104 },
7111 "inherits": {
7105 "inherits": {
7112 "version": "2.0.3",
7106 "version": "2.0.3",
7113− "bundled": true,
7107+ "bundled": true
7114− "optional": true
7115 },
7108 },
7116 "ini": {
7109 "ini": {
7117 "version": "1.3.5",
7110 "version": "1.3.5",
@@ -7121,7 +7114,6 @@
7121 "is-fullwidth-code-point": {
7114 "is-fullwidth-code-point": {
7122 "version": "1.0.0",
7115 "version": "1.0.0",
7123 "bundled": true,
7116 "bundled": true,
7124− "optional": true,
7125 "requires": {
7117 "requires": {
7126 "number-is-nan": "^1.0.0"
7118 "number-is-nan": "^1.0.0"
7127 }
7119 }
@@ -7134,20 +7126,17 @@
7134 "minimatch": {
7126 "minimatch": {
7135 "version": "3.0.4",
7127 "version": "3.0.4",
7136 "bundled": true,
7128 "bundled": true,
7137− "optional": true,
7138 "requires": {
7129 "requires": {
7139 "brace-expansion": "^1.1.7"
7130 "brace-expansion": "^1.1.7"
7140 }
7131 }
7141 },
7132 },
7142 "minimist": {
7133 "minimist": {
7143 "version": "0.0.8",
7134 "version": "0.0.8",
7144− "bundled": true,
7135+ "bundled": true
7145− "optional": true
7146 },
7136 },
7147 "minipass": {
7137 "minipass": {
7148 "version": "2.3.5",
7138 "version": "2.3.5",
7149 "bundled": true,
7139 "bundled": true,
7150− "optional": true,
7151 "requires": {
7140 "requires": {
7152 "safe-buffer": "^5.1.2",
7141 "safe-buffer": "^5.1.2",
7153 "yallist": "^3.0.0"
7142 "yallist": "^3.0.0"
@@ -7164,7 +7153,6 @@
7164 "mkdirp": {
7153 "mkdirp": {
7165 "version": "0.5.1",
7154 "version": "0.5.1",
7166 "bundled": true,
7155 "bundled": true,
7167− "optional": true,
7168 "requires": {
7156 "requires": {
7169 "minimist": "0.0.8"
7157 "minimist": "0.0.8"
7170 }
7158 }
@@ -7237,8 +7225,7 @@
7237 },
7225 },
7238 "number-is-nan": {
7226 "number-is-nan": {
7239 "version": "1.0.1",
7227 "version": "1.0.1",
7240− "bundled": true,
7228+ "bundled": true
7241− "optional": true
7242 },
7229 },
7243 "object-assign": {
7230 "object-assign": {
7244 "version": "4.1.1",
7231 "version": "4.1.1",
@@ -7248,7 +7235,6 @@
7248 "once": {
7235 "once": {
7249 "version": "1.4.0",
7236 "version": "1.4.0",
7250 "bundled": true,
7237 "bundled": true,
7251− "optional": true,
7252 "requires": {
7238 "requires": {
7253 "wrappy": "1"
7239 "wrappy": "1"
7254 }
7240 }
@@ -7324,8 +7310,7 @@
7324 },
7310 },
7325 "safe-buffer": {
7311 "safe-buffer": {
7326 "version": "5.1.2",
7312 "version": "5.1.2",
7327− "bundled": true,
7313+ "bundled": true
7328− "optional": true
7329 },
7314 },
7330 "safer-buffer": {
7315 "safer-buffer": {
7331 "version": "2.1.2",
7316 "version": "2.1.2",
@@ -7355,7 +7340,6 @@
7355 "string-width": {
7340 "string-width": {
7356 "version": "1.0.2",
7341 "version": "1.0.2",
7357 "bundled": true,
7342 "bundled": true,
7358− "optional": true,
7359 "requires": {
7343 "requires": {
7360 "code-point-at": "^1.0.0",
7344 "code-point-at": "^1.0.0",
7361 "is-fullwidth-code-point": "^1.0.0",
7345 "is-fullwidth-code-point": "^1.0.0",
@@ -7373,7 +7357,6 @@
7373 "strip-ansi": {
7357 "strip-ansi": {
7374 "version": "3.0.1",
7358 "version": "3.0.1",
7375 "bundled": true,
7359 "bundled": true,
7376− "optional": true,
7377 "requires": {
7360 "requires": {
7378 "ansi-regex": "^2.0.0"
7361 "ansi-regex": "^2.0.0"
7379 }
7362 }
@@ -7412,13 +7395,11 @@
7412 },
7395 },
7413 "wrappy": {
7396 "wrappy": {
7414 "version": "1.0.2",
7397 "version": "1.0.2",
7415− "bundled": true,
7398+ "bundled": true
7416− "optional": true
7417 },
7399 },
7418 "yallist": {
7400 "yallist": {
7419 "version": "3.0.3",
7401 "version": "3.0.3",
7420− "bundled": true,
7402+ "bundled": true
7421− "optional": true
7422 }
7403 }
7423 }
7404 }
7424 },
7405 },
src/assets/secret-hidden.svgnew file+17
@@ -0,0 +1,17 @@
1+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2+<rect width="16" height="16" fill="white"/>
3+<path fill-rule="evenodd" clip-rule="evenodd" d="M8 13C13.0495 13 16 8 16 8C16 8 13.0495 3 8 3C2.95054 3 0 8 0 8C0 8 2.95054 13 8 13ZM8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z" fill="black"/>
4+<g filter="url(#filter0_d)">
5+<path d="M2 2.70588L2.70588 2L14 13.2941L13.2941 14L2 2.70588Z" fill="black"/>
6+</g>
7+<defs>
8+<filter id="filter0_d" x="1" y="2" width="13" height="12" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
9+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
10+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
11+<feOffset dx="-1"/>
12+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
13+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
14+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
15+</filter>
16+</defs>
17+</svg>
src/assets/secret-show.svgnew file+4
@@ -0,0 +1,4 @@
1+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2+<rect width="16" height="16" fill="white"/>
3+<path fill-rule="evenodd" clip-rule="evenodd" d="M8 13C13.0495 13 16 8 16 8C16 8 13.0495 3 8 3C2.95054 3 0 8 0 8C0 8 2.95054 13 8 13ZM8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z" fill="#B1B2B3"/>
4+</svg>
src/components/View.js+1−5
@@ -70,11 +70,7 @@ function View({
70 className
70 className
71 )}
71 )}
72 {...rest}>
72 {...rest}>
73− <Flex.Item
74− as={Flex}
75− col
76− style={{ width: '48px' }}
77− className={cn(insetPadding)}>
73+ <Flex.Item as={Flex} col className={cn(insetPadding)}>
78 {showBackButton && !backIsLogout && (
74 {showBackButton && !backIsLogout && (
79 <MiniBackButton
75 <MiniBackButton
80 hpadding={!isMobile}
76 hpadding={!isMobile}
src/form/Inputs.js+4−3
@@ -18,6 +18,7 @@ const PLACEHOLDER_HD_PATH = DEFAULT_HD_PATH;
18const PLACEHOLDER_MNEMONIC =
18const PLACEHOLDER_MNEMONIC =
19 'example crew supreme gesture quantum web media hazard theory mercy wing kitten';
19 'example crew supreme gesture quantum web media hazard theory mercy wing kitten';
20const PLACEHOLDER_TICKET = '~sampel-ticlyt-migfun-falmel';
20const PLACEHOLDER_TICKET = '~sampel-ticlyt-migfun-falmel';
21+const PLACEHOLDER_PASSWORD = '••••••-••••••-••••••-••••••';
21const PLACEHOLDER_ADDRESS = '0x';
22const PLACEHOLDER_ADDRESS = '0x';
22const PLACEHOLDER_HEX = '0x';
23const PLACEHOLDER_HEX = '0x';
23const PLACEHOLDER_PRIVATE_KEY =
24const PLACEHOLDER_PRIVATE_KEY =
@@ -26,7 +27,7 @@ const PLACEHOLDER_EMAIL = 'email@example.com';
26
27
27const formatPat = buildFormatter([downcase, ensurePatFormat]);
28const formatPat = buildFormatter([downcase, ensurePatFormat]);
28
29
29−export function TicketInput({ name, ...rest }) {
30+export function TicketInput({ name, hidden, ...rest }) {
30 const {
31 const {
31 meta: { valid, error, validating, touched, active },
32 meta: { valid, error, validating, touched, active },
32 } = useField(name, {
33 } = useField(name, {
@@ -41,10 +42,10 @@ export function TicketInput({ name, ...rest }) {
41
42
42 return (
43 return (
43 <Input
44 <Input
44− type="text"
45+ type={hidden ? 'password' : 'text'}
45 name={name}
46 name={name}
46 obscure={value => value.replace(/[^~-]+/g, '••••••')}
47 obscure={value => value.replace(/[^~-]+/g, '••••••')}
47− placeholder={PLACEHOLDER_TICKET}
48+ placeholder={hidden ? PLACEHOLDER_PASSWORD : PLACEHOLDER_TICKET}
48 autoCapitalize="none"
49 autoCapitalize="none"
49 autoCorrect="off"
50 autoCorrect="off"
50 accessory={
51 accessory={
src/indigo-react/components/CheckboxInput.js+14−4
@@ -9,6 +9,9 @@ export default function CheckboxInput({
9 name,
9 name,
10 label,
10 label,
11 className,
11 className,
12+ style,
13+ inline = false,
14+ white = false,
12
15
13 disabled,
16 disabled,
14}) {
17}) {
@@ -23,7 +26,8 @@ export default function CheckboxInput({
23 <Flex
26 <Flex
24 row
27 row
25 align="center"
28 align="center"
26− className={cn(className, 'mv2', {
29+ className={cn(className, {
30+ mv2: !inline,
27 black: !disabled,
31 black: !disabled,
28 gray4: disabled,
32 gray4: disabled,
29 })}
33 })}
@@ -39,19 +43,25 @@ export default function CheckboxInput({
39 <Flex.Item
43 <Flex.Item
40 flex
44 flex
41 as="label"
45 as="label"
46+ className={cn(
47+ { mr3: !inline },
42− className="f6 mr3 lh-tall us-none pointer flex-row align-center"
48+ 'f6 lh-tall us-none pointer flex-row align-center'
49+ )}
43 htmlFor={name}>
50 htmlFor={name}>
44 <Flex
51 <Flex
45 justify="center"
52 justify="center"
46 align="center"
53 align="center"
47− className={cn('b1 p1 mr3', {
54+ className={cn('b1 p1', {
55+ mr3: !inline,
56+ mr1: inline,
48 'bg-gray1': disabled,
57 'bg-gray1': disabled,
49− 'bg-black white b-black': !disabled && input.value,
58+ 'bg-black white b-black': !disabled && (input.value || white),
50 'bg-white black b-black': !disabled && !input.value,
59 'bg-white black b-black': !disabled && !input.value,
51 })}
60 })}
52 style={{
61 style={{
53 height: '14px',
62 height: '14px',
54 width: '14px',
63 width: '14px',
64+ ...style,
55 }}>
65 }}>
56 {input.value && '✓'}
66 {input.value && '✓'}
57 </Flex>
67 </Flex>
src/indigo-react/components/Input.js+9−4
@@ -11,6 +11,7 @@ export default function Input({
11 label,
11 label,
12 className,
12 className,
13 accessory,
13 accessory,
14+ labelAccessory,
14 disabled = false,
15 disabled = false,
15 mono = false,
16 mono = false,
16 obscure,
17 obscure,
@@ -65,13 +66,17 @@ export default function Input({
65 }),
66 }),
66 }}>
67 }}>
67 <Flex.Item
68 <Flex.Item
68− as="label"
69+ as={Flex}
70+ justify="between"
71+ align="center"
69 className={cn('f6 lh-tall', {
72 className={cn('f6 lh-tall', {
70 black: !disabled,
73 black: !disabled,
71 gray4: disabled,
74 gray4: disabled,
72− })}
75+ })}>
73− htmlFor={name}>
76+ <Flex.Item as="label" justify htmlFor={name}>
74− {label}
77+ {label}
78+ </Flex.Item>
79+ {labelAccessory && <Flex.Item>{labelAccessory}</Flex.Item>}
75 </Flex.Item>
80 </Flex.Item>
76 <Flex.Item as={Flex} row className="rel">
81 <Flex.Item as={Flex} row className="rel">
77 <Flex.Item
82 <Flex.Item
src/indigo-react/components/ToggleInput.js+4−1
@@ -11,6 +11,7 @@ export default function ToggleInput({
11 label,
11 label,
12 inverseLabel,
12 inverseLabel,
13 inverseColor = 'black',
13 inverseColor = 'black',
14+ small = false,
14 className,
15 className,
15
16
16 //
17 //
@@ -55,7 +56,9 @@ export default function ToggleInput({
55 htmlFor={name}>
56 htmlFor={name}>
56 <LinkButton
57 <LinkButton
57 disabled={disabled}
58 disabled={disabled}
58− className={cn('f5', {
59+ className={cn({
60+ f5: !small,
61+ f6: small,
59 black: !input.checked,
62 black: !input.checked,
60 [inverseColor]: input.checked,
63 [inverseColor]: input.checked,
61 })}>
64 })}>
src/lib/routeNames.js+1
@@ -7,6 +7,7 @@ export const ROUTE_NAMES = {
7 INVITES_MANAGE: Symbol('INVITES_MANAGE'),
7 INVITES_MANAGE: Symbol('INVITES_MANAGE'),
8 //
8 //
9 LOGIN: Symbol('LOGIN'),
9 LOGIN: Symbol('LOGIN'),
10+ LOGIN_OTHER: Symbol('OTHER'),
10 ADMIN: Symbol('ADMIN'),
11 ADMIN: Symbol('ADMIN'),
11 REDOWNLOAD: Symbol('REDOWNLOAD'),
12 REDOWNLOAD: Symbol('REDOWNLOAD'),
12 RETICKET: Symbol('RETICKET'),
13 RETICKET: Symbol('RETICKET'),
src/lib/router.js+2
@@ -1,5 +1,6 @@
1import Disclaimer from 'views/Disclaimer';
1import Disclaimer from 'views/Disclaimer';
2import Login from 'views/Login.js';
2import Login from 'views/Login.js';
3+import Other from 'views/Login/Other.js';
3import Admin from 'views/Admin';
4import Admin from 'views/Admin';
4import Senate from 'views/Senate';
5import Senate from 'views/Senate';
5import CreateGalaxy from 'views/CreateGalaxy';
6import CreateGalaxy from 'views/CreateGalaxy';
@@ -22,6 +23,7 @@ export const ROUTES = {
22 [ROUTE_NAMES.DISCLAIMER]: Disclaimer,
23 [ROUTE_NAMES.DISCLAIMER]: Disclaimer,
23 [ROUTE_NAMES.ACTIVATE]: Activate,
24 [ROUTE_NAMES.ACTIVATE]: Activate,
24 [ROUTE_NAMES.LOGIN]: Login,
25 [ROUTE_NAMES.LOGIN]: Login,
26+ [ROUTE_NAMES.LOGIN_OTHER]: Other,
25 [ROUTE_NAMES.POINTS]: Points,
27 [ROUTE_NAMES.POINTS]: Points,
26 [ROUTE_NAMES.POINT]: Point,
28 [ROUTE_NAMES.POINT]: Point,
27 [ROUTE_NAMES.CREATE_GALAXY]: CreateGalaxy,
29 [ROUTE_NAMES.CREATE_GALAXY]: CreateGalaxy,
src/lib/useEthereumTransaction.js+1
@@ -204,6 +204,7 @@ export default function useEthereumTransaction(
204 pointCursor,
204 pointCursor,
205 setError,
205 setError,
206 signedTransactions,
206 signedTransactions,
207+ walletType,
207 ]);
208 ]);
208
209
209 const reset = useCallback(() => {
210 const reset = useCallback(() => {
src/views/Invite/Cohort.js+1−1
@@ -50,7 +50,7 @@ function CohortMember({ point, pending = false, className }) {
50 const DetailText = useCallback(
50 const DetailText = useCallback(
51 () =>
51 () =>
52 pending ? 'Pending' : <> {matchBlinky(sentInvites)} points invited </>,
52 pending ? 'Pending' : <> {matchBlinky(sentInvites)} points invited </>,
53− [sentInvites]
53+ [pending, sentInvites]
54 );
54 );
55
55
56 return (
56 return (
src/views/Invite/Email.js+1−1
@@ -103,7 +103,7 @@ const InviteMail = ({ setSubmitting }) => {
103 form.reset();
103 form.reset();
104 }, 1500);
104 }, 1500);
105 },
105 },
106− [generateInvites, setCount, setStatus, sendInvites, setSubmitting]
106+ [setSubmitting, generateInvites, sendInvites, resetInvites]
107 );
107 );
108
108
109 const validateHasReceived = useCallback(
109 const validateHasReceived = useCallback(
src/views/Login.js+46−31
@@ -1,5 +1,5 @@
1import React, { useCallback, useState } from 'react';
1import React, { useCallback, useState } from 'react';
2−import { P, H4, Grid } from 'indigo-react';
2+import { P, H4, H5, Grid, Text, Button, Flex, LinkButton } from 'indigo-react';
3
3
4import { version } from '../../package.json';
4import { version } from '../../package.json';
5
5
@@ -45,9 +45,7 @@ export default function Login() {
45 const { walletType } = useWallet();
45 const { walletType } = useWallet();
46
46
47 // inputs
47 // inputs
48− const [currentTab, setCurrentTab] = useState(
48+ const [isOther, setisOther] = useState(false);
49− walletTypeToViewName(walletType)
50− );
51
49
52 const goToActivate = useCallback(() => push(names.ACTIVATE), [
50 const goToActivate = useCallback(() => push(names.ACTIVATE), [
53 push,
51 push,
@@ -61,37 +59,54 @@ export default function Login() {
61 return (
59 return (
62 <View pop={pop} inset>
60 <View pop={pop} inset>
63 <Grid>
61 <Grid>
64− <Grid.Item full as={Crumbs} routes={[{ text: 'Bridge' }]} />
62+ <Grid.Item full as={Text} className="flex justify-center mt9 mb7">
65− <Grid.Item full as={H4} className="mt4">
63+ <Grid.Item as={Text} className="gray3">
66− Login
64+ Urbit ID /&nbsp;
65+ </Grid.Item>
67− </Grid.Item>
66+ <Grid.Item as={Text}>Login</Grid.Item>
68−
69− <Grid.Item
70− full
71− as={Tabs}
72− className="mt1"
73− // Tabs
74− views={VIEWS}
75− options={OPTIONS}
76− currentTab={currentTab}
77− onTabChange={setCurrentTab}
78− // Tab extra
79− goHome={goHome}
80− />
81− <Grid.Item full as={P} className="f6">
82− Version {version}
83 </Grid.Item>
67 </Grid.Item>
68+ {isOther && <Grid.Item full as={Other} goHome={goHome} />}
69+ {!isOther && <Grid.Item full as={Ticket} goHome={goHome} />}
70+ {!isOther && (
71+ <>
72+ <Grid.Item full className="t-center mv4 gray4">
73+ or
74+ </Grid.Item>
75+ <Grid.Item
76+ full
77+ as={Button}
78+ className="b-solid b1 b-black"
79+ center
80+ onClick={() => setisOther(true)}>
81+ Metamask, Mnemonic, Hardware Wallet...
82+ </Grid.Item>
83+ <Grid.Item full onClick={goToActivate} className="mv10 t-center f6">
84+ <span className="gray4">New Urbit ID? </span>
85+ <LinkButton>Activate</LinkButton>
86+ </Grid.Item>
87+ </>
88+ )}
89+ {isOther && (
90+ <Grid.Item
91+ as={LinkButton}
92+ onClick={() => setisOther(false)}
93+ full
94+ className="t-center underline f6 mt8">
95+ Back
96+ </Grid.Item>
97+ )}
84 </Grid>
98 </Grid>
85
99
86 <Footer>
100 <Footer>
87− <Grid>
101+ <Flex className="mb8 f6" justify="between">
88− <Grid.Divider />
102+ <Flex.Item
89− <Grid.Item full as={ForwardButton} onClick={goToActivate}>
103+ as="a"
90− Activate
104+ href="https://github.com/urbit/bridge/releases"
105+ className="us-none pointer">
106+ <span className="underline">Offline</span> ↗
91− </Grid.Item>
107+ </Flex.Item>
92− <Grid.Divider />
108+ <Flex.Item className="gray4">v{version}</Flex.Item>
93− <Grid.Item full as={OfflineButton} />
109+ </Flex>
94− </Grid>
95 </Footer>
110 </Footer>
96 </View>
111 </View>
97 );
112 );
src/views/Login/Keystore.js+2−2
@@ -1,6 +1,6 @@
1import React, { useCallback, useMemo } from 'react';
1import React, { useCallback, useMemo } from 'react';
2import { Just } from 'folktale/maybe';
2import { Just } from 'folktale/maybe';
3−import { P, Grid } from 'indigo-react';
3+import { Text, Grid } from 'indigo-react';
4import * as keythereum from 'keythereum';
4import * as keythereum from 'keythereum';
5
5
6import { useWallet } from 'store/wallet';
6import { useWallet } from 'store/wallet';
@@ -56,7 +56,7 @@ export default function Keystore({ className, goHome }) {
56
56
57 return (
57 return (
58 <Grid className={className}>
58 <Grid className={className}>
59− <Grid.Item full as={P}>
59+ <Grid.Item full as={Text} className="f6 gray4 mb3">
60 Please upload your Ethereum keystore file. If your keystore file is
60 Please upload your Ethereum keystore file. If your keystore file is
61 encrypted with a password, you'll also need to enter that below.
61 encrypted with a password, you'll also need to enter that below.
62 </Grid.Item>
62 </Grid.Item>
src/views/Login/Ledger.js+1−4
@@ -150,10 +150,7 @@ export default function Ledger({ className, goHome }) {
150
150
151 const renderHTTPS = () => (
151 const renderHTTPS = () => (
152 <>
152 <>
153− <Grid.Item full as={H5}>
153+ <Grid.Item full as={Text} className="f6 gray4 mb3">
154− Authenticate With Your Ledger
155− </Grid.Item>
156− <Grid.Item full as={Text} className="f6 mb3">
157 Connect and authenticate to your Ledger, and then open the "Ethereum"
154 Connect and authenticate to your Ledger, and then open the "Ethereum"
158 application. If you're running on older firmware, make sure the "browser
155 application. If you're running on older firmware, make sure the "browser
159 support" option is turned on. To sign transactions, you'll also need to
156 support" option is turned on. To sign transactions, you'll also need to
src/views/Login/Metamask.js+1−4
@@ -47,10 +47,7 @@ function Unsupported() {
47function Login({ onSubmit, goHome }) {
47function Login({ onSubmit, goHome }) {
48 return (
48 return (
49 <>
49 <>
50− <Grid.Item full as={H5}>
50+ <Grid.Item full as={Text} className="f6 gray4 mb3">
51− Authenticate with Metamask
52− </Grid.Item>
53− <Grid.Item full as={Text} className="f6 mb3">
54 If you wish to login with a different wallet, please change it in the
51 If you wish to login with a different wallet, please change it in the
55 Metamask extension
52 Metamask extension
56 </Grid.Item>
53 </Grid.Item>
src/views/Login/Mnemonic.js+1−1
@@ -113,7 +113,7 @@ export default function Mnemonic({ className, goHome }) {
113 <Grid.Item full as={FormError} />
113 <Grid.Item full as={FormError} />
114
114
115 <Grid.Item full as={SubmitButton} handleSubmit={handleSubmit}>
115 <Grid.Item full as={SubmitButton} handleSubmit={handleSubmit}>
116− Continue
116+ Login
117 </Grid.Item>
117 </Grid.Item>
118 </>
118 </>
119 )}
119 )}
src/views/Login/Other.js+15−10
@@ -1,7 +1,9 @@
1import React, { useState, useMemo } from 'react';
1import React, { useState, useMemo } from 'react';
2+import { Grid } from 'indigo-react';
2
3
3import useBreakpoints from 'lib/useBreakpoints';
4import useBreakpoints from 'lib/useBreakpoints';
4
5
6+import View from 'components/View';
5import Accordion from 'components/Accordion';
7import Accordion from 'components/Accordion';
6
8
7import PrivateKey from './PrivateKey';
9import PrivateKey from './PrivateKey';
@@ -30,10 +32,10 @@ const VIEWS = {
30};
32};
31
33
32const OPTIONS = [
34const OPTIONS = [
35+ { text: 'Metamask', value: NAMES.METAMASK },
33 { text: 'Mnemonic (BIP 39)', value: NAMES.MNEMONIC },
36 { text: 'Mnemonic (BIP 39)', value: NAMES.MNEMONIC },
34 { text: 'Ledger', value: NAMES.LEDGER },
37 { text: 'Ledger', value: NAMES.LEDGER },
35 { text: 'Trezor', value: NAMES.TREZOR },
38 { text: 'Trezor', value: NAMES.TREZOR },
36− { text: 'Metamask', value: NAMES.METAMASK },
37 { text: 'Ethereum Private Key', value: NAMES.PRIVATE_KEY },
39 { text: 'Ethereum Private Key', value: NAMES.PRIVATE_KEY },
38 { text: 'Ethereum Keystore', value: NAMES.KEYSTORE },
40 { text: 'Ethereum Keystore', value: NAMES.KEYSTORE },
39];
41];
@@ -54,14 +56,17 @@ export default function Other({ className, ...rest }) {
54 [hardwareAllowed]
56 [hardwareAllowed]
55 );
57 );
56 return (
58 return (
59+ <>
60+ <Grid.Divider />
57− <Accordion
61+ <Accordion
58− className={className}
62+ className={className}
59− views={VIEWS}
63+ views={VIEWS}
60− options={options}
64+ options={options}
61− currentTab={currentTab}
65+ currentTab={currentTab}
62− onTabChange={setCurrentTab}
66+ onTabChange={setCurrentTab}
63− //
67+ //
64− {...rest}
68+ {...rest}
65− />
69+ />
70+ </>
66 );
71 );
67}
72}
src/views/Login/PrivateKey.js+1−1
@@ -53,7 +53,7 @@ export default function PrivateKey({ className, goHome }) {
53 />
53 />
54 <Grid.Item full as={FormError} />
54 <Grid.Item full as={FormError} />
55 <Grid.Item full as={SubmitButton} handleSubmit={handleSubmit}>
55 <Grid.Item full as={SubmitButton} handleSubmit={handleSubmit}>
56− Continue
56+ Login
57 </Grid.Item>
57 </Grid.Item>
58 </>
58 </>
59 )}
59 )}
src/views/Login/Ticket.js+81−35
@@ -3,7 +3,13 @@ import { Just } from 'folktale/maybe';
3import cn from 'classnames';
3import cn from 'classnames';
4import * as azimuth from 'azimuth-js';
4import * as azimuth from 'azimuth-js';
5import * as kg from 'urbit-key-generation';
5import * as kg from 'urbit-key-generation';
6+import {
7+ Grid,
8+ CheckboxInput,
9+ Flex,
10+ ToggleInput,
11+ AccessoryIcon,
6−import { Grid, CheckboxInput, Flex, ToggleInput } from 'indigo-react';
12+} from 'indigo-react';
7import { FORM_ERROR } from 'final-form';
13import { FORM_ERROR } from 'final-form';
8
14
9import { useNetwork } from 'store/network';
15import { useNetwork } from 'store/network';
@@ -31,6 +37,56 @@ import FormError from 'form/FormError';
31import SubmitButton from 'form/SubmitButton';
37import SubmitButton from 'form/SubmitButton';
32import { WARNING } from 'form/helpers';
38import { WARNING } from 'form/helpers';
33
39
40+import { ReactComponent as SecretShowIcon } from 'assets/secret-show.svg';
41+import { ReactComponent as SecretHideIcon } from 'assets/secret-hidden.svg';
42+
43+function AdvancedOptions() {
44+ return (
45+ <Flex.Item as={Flex}>
46+ <Condition when="useAdvanced" is={true}>
47+ <Flex.Item
48+ as={CheckboxInput}
49+ inline
50+ white
51+ className="mr4"
52+ name="usePassphrase"
53+ label="Passphrase"
54+ style={{ boxSizing: 'border-box' }}
55+ />
56+ <Flex.Item
57+ as={CheckboxInput}
58+ inline
59+ white
60+ className="mr4"
61+ name="useShards"
62+ label="Shards"
63+ style={{ boxSizing: 'border-box' }}
64+ />
65+ </Condition>
66+ <Flex.Item
67+ as={ToggleInput}
68+ name="useAdvanced"
69+ label="Settings"
70+ small
71+ inverseLabel="Close"
72+ />
73+ </Flex.Item>
74+ );
75+}
76+
77+function TicketInputAccessory({ name }) {
78+ return (
79+ <AccessoryIcon>
80+ <ToggleInput
81+ name={name}
82+ className="mt1"
83+ inverseLabel={<SecretShowIcon />}
84+ label={<SecretHideIcon />}
85+ />
86+ </AccessoryIcon>
87+ );
88+}
89+
34export default function Ticket({ className, goHome }) {
90export default function Ticket({ className, goHome }) {
35 useLoginView(WALLET_TYPES.TICKET);
91 useLoginView(WALLET_TYPES.TICKET);
36
92
@@ -124,7 +180,7 @@ export default function Ticket({ className, goHome }) {
124 shard1: buildPatqValidator(),
180 shard1: buildPatqValidator(),
125 shard2: buildPatqValidator(),
181 shard2: buildPatqValidator(),
126 shard3: buildPatqValidator(),
182 shard3: buildPatqValidator(),
127− showTicket: buildCheckboxValidator(),
183+ ticketHidden: buildCheckboxValidator(),
128 passphrase: buildPassphraseValidator(),
184 passphrase: buildPassphraseValidator(),
129 },
185 },
130 validateForm
186 validateForm
@@ -137,14 +193,14 @@ export default function Ticket({ className, goHome }) {
137 point: impliedPoint || '',
193 point: impliedPoint || '',
138 usePasshrase: false,
194 usePasshrase: false,
139 useShards: false,
195 useShards: false,
140− showTicket: true,
196+ ticketHidden: true,
141 useAdvanced: false,
197 useAdvanced: false,
142 }),
198 }),
143 [impliedPoint]
199 [impliedPoint]
144 );
200 );
145
201
146 return (
202 return (
147− <Grid className={cn('mt4', className)}>
203+ <Grid className={className}>
148 <BridgeForm
204 <BridgeForm
149 validate={validate}
205 validate={validate}
150 onSubmit={onSubmit}
206 onSubmit={onSubmit}
@@ -158,7 +214,10 @@ export default function Ticket({ className, goHome }) {
158 <Grid.Item
214 <Grid.Item
159 full
215 full
160 as={TicketInput}
216 as={TicketInput}
161− type={values.showTicket ? 'text' : 'password'}
217+ hidden={values.ticketHidden}
218+ labelAccessory={<AdvancedOptions />}
219+ accessory={<TicketInputAccessory name="ticketHidden" />}
220+ className="mt3"
162 name="ticket"
221 name="ticket"
163 label="Master Ticket"
222 label="Master Ticket"
164 />
223 />
@@ -168,32 +227,38 @@ export default function Ticket({ className, goHome }) {
168 <Grid.Item
227 <Grid.Item
169 full
228 full
170 as={TicketInput}
229 as={TicketInput}
171− type={values.showTicket ? 'text' : 'password'}
230+ accessory={<TicketInputAccessory name="ticketHidden" />}
231+ hidden={values.ticketHidden}
232+ labelAccessory={<AdvancedOptions />}
233+ className="mt3"
172 name="shard1"
234 name="shard1"
173 label="Shard 1"
235 label="Shard 1"
174 />
236 />
175 <Grid.Item
237 <Grid.Item
176 full
238 full
177 as={TicketInput}
239 as={TicketInput}
178− type={values.showTicket ? 'text' : 'password'}
240+ accessory={<TicketInputAccessory name="ticketHidden" />}
241+ hidden={values.ticketHidden}
242+ className="mt3"
179 name="shard2"
243 name="shard2"
180 label="Shard 2"
244 label="Shard 2"
181 />
245 />
182 <Grid.Item
246 <Grid.Item
183 full
247 full
184 as={TicketInput}
248 as={TicketInput}
185− type={values.showTicket ? 'text' : 'password'}
249+ className="mt3"
250+ accessory={<TicketInputAccessory name="ticketHidden" />}
251+ hidden={values.ticketHidden}
186 name="shard3"
252 name="shard3"
187 label="Shard 3"
253 label="Shard 3"
188 />
254 />
189 </Condition>
255 </Condition>
190
256
191− <Grid.Item full as={CheckboxInput} name="showTicket" label="Show" />
192−
193 <Condition when="usePassphrase" is={true}>
257 <Condition when="usePassphrase" is={true}>
194 <Grid.Item
258 <Grid.Item
195 full
259 full
196 as={PassphraseInput}
260 as={PassphraseInput}
261+ className="mt3"
197 name="passphrase"
262 name="passphrase"
198 label="Wallet Passphrase"
263 label="Wallet Passphrase"
199 />
264 />
@@ -201,38 +266,19 @@ export default function Ticket({ className, goHome }) {
201
266
202 <Grid.Item full as={FormError} />
267 <Grid.Item full as={FormError} />
203
268
269+ <Grid.Item
270+ full
271+ as={SubmitButton}
272+ center
204− <Grid.Item full as={SubmitButton} handleSubmit={handleSubmit}>
273+ handleSubmit={handleSubmit}>
205 {isWarning =>
274 {isWarning =>
206 submitting
275 submitting
207 ? 'Logging in...'
276 ? 'Logging in...'
208 : isWarning
277 : isWarning
209 ? 'Login Anyway'
278 ? 'Login Anyway'
210− : 'Continue'
279+ : 'Login'
211 }
280 }
212 </Grid.Item>
281 </Grid.Item>
213−
214− <Grid.Item full as={Flex} justify="between">
215− <Flex.Item
216− as={ToggleInput}
217− name="useAdvanced"
218− label="Advanced"
219− inverseLabel="Hide"
220− />
221− <Condition when="useAdvanced" is={true}>
222− <Flex.Item as={Flex}>
223− <Flex.Item
224− as={CheckboxInput}
225− name="usePassphrase"
226− label="Passphrase"
227− />
228− <Flex.Item
229− as={CheckboxInput}
230− name="useShards"
231− label="Shards"
232− />
233− </Flex.Item>
234− </Condition>
235− </Grid.Item>
236 </>
282 </>
237 )}
283 )}
238 </BridgeForm>
284 </BridgeForm>
src/views/Login/Trezor.js+1−5
@@ -94,11 +94,7 @@ export default function Trezor({ className, goHome }) {
94
94
95 return (
95 return (
96 <Grid className={className}>
96 <Grid className={className}>
97− <Grid.Item full as={H5}>
97+ <Grid.Item full as={Text} className="f6 gray4 mb3">
98− Authenticate With Your Trezor
99− </Grid.Item>
100−
101− <Grid.Item full as={Text} className="f6 mb3">
102 Connect and authenticate to your Trezor. If you'd like to use a custom
98 Connect and authenticate to your Trezor. If you'd like to use a custom
103 derivation path, you may enter it below.
99 derivation path, you may enter it below.
104 </Grid.Item>
100 </Grid.Item>