on master help sign in
Make /views/Login/Shards functional/stateless
commitd2c2674231e3792740fbac4cf73dca3f9500bbd2 authorFang <git@fang.io> dateTue 25 Jun 2019, 00:08 (7 years ago) parent1acc940
1 file changed+70−191
src/views/Login/Shards.js+70−191
src/views/Login/Shards.js+70−191
@@ -1,78 +1,28 @@
11import { Just, Nothing } from 'folktale/maybe';
2−import React from 'react';
3−import { Button } from '../../components/old/Base';
2+import React, { useState } from 'react';
3+import * as kg from 'urbit-key-generation/dist/index';
4+
5+import View from '../../components/View';
46import {
5− InnerLabel,
6− ValidatedSigil,
77 PointInput,
8− ShardInput,
9− InputCaption,
10− Input,
11−} from '../../components/old/Base';
12−import { Row, Col, H1, P } from '../../components/old/Base';
13−import * as kg from 'urbit-key-generation/dist/index';
14−import * as ob from 'urbit-ob';
8+ TicketInput,
9+ PassphraseInput,
10+} from '../../components/Inputs';
11+import { ForwardButton } from '../../components/Buttons';
1512
1613import { urbitWalletFromTicket } from '../../lib/wallet';
17−import { compose } from '../../lib/lib';
18−import { withWallet } from '../../store/wallet';
19−
20−const placeholder = len => {
21− let bytes = window.crypto.getRandomValues(new Uint8Array(len));
22− let hex = bytes.reduce(
23− (acc, byt) => acc + byt.toString(16).padStart(2, '0'),
24− ''
25− );
26− return ob.hex2patq(hex);
27−};
28−
29−const SHARDS = {
30− SHARD1: Symbol('SHARD1'),
31− SHARD2: Symbol('SHARD2'),
32− SHARD3: Symbol('SHARD3'),
33−};
34−
35−class Shards extends React.Component {
36− constructor(props) {
37− super(props);
14+import { useWallet } from '../../store/wallet';
3815
39− this.state = {
40− shard1: '',
41− shard2: '',
42− shard3: '',
43− passphrase: '',
44− pointName: '',
45− };
16+export default function Shards({ loginCompleted }) {
17+ const { wallet, setUrbitWallet } = useWallet();
4618
47− this.pointPlaceholder = placeholder(4);
48− this.ticketPlaceholder = placeholder(16);
19+ const [shard1, setShard1] = useState('');
20+ const [shard2, setShard2] = useState('');
21+ const [shard3, setShard3] = useState('');
22+ const [passphrase, setPassphrase] = useState('');
23+ const [pointName, setPointName] = useState('');
4924
50− this.handlePassphraseInput = this.handlePassphraseInput.bind(this);
51− this.handleShardInput = this.handleShardInput.bind(this);
52− this.handlePointNameInput = this.handlePointNameInput.bind(this);
53− }
54−
55− handleShardInput(shard, input) {
56− if (shard === SHARDS.SHARD1) {
57− this.setState({ shard1: input });
58− } else if (shard === SHARDS.SHARD2) {
59− this.setState({ shard2: input });
60− } else if (shard === SHARDS.SHARD3) {
61− this.setState({ shard3: input });
62− }
63− }
64−
65− handlePassphraseInput(passphrase) {
66− this.setState({ passphrase });
67− }
68−
69− handlePointNameInput(pointName) {
70− if (pointName.length < 15) {
71− this.setState({ pointName });
72− }
73− }
74−
75− async walletFromShards(shard1, shard2, shard3, pointName, passphrase) {
25+ const walletFromShards = async () => {
7626 const s1 = shard1 === '' ? undefined : shard1;
7727 const s2 = shard2 === '' ? undefined : shard2;
7828 const s3 = shard3 === '' ? undefined : shard3;
@@ -86,129 +36,58 @@ class Shards extends React.Component {
8636
8737 if (ticket !== undefined) {
8838 const uhdw = await urbitWalletFromTicket(ticket, pointName, passphrase);
89− this.props.setUrbitWallet(Just(uhdw));
39+ setUrbitWallet(Just(uhdw));
9040 }
91− }
92−
93− render() {
94− const { wallet } = this.props;
95− const { shard1, shard2, shard3, pointName, passphrase } = this.state;
96−
97− const phPoint = this.pointPlaceholder;
98− const phTick = this.ticketPlaceholder;
99−
100− const shards = [shard1, shard2, shard3];
101− const ready = shards.filter(x => x !== '').length > 1;
102−
103− return (
104− <Row>
105− <Col>
106− <H1>{'Authenticate'}</H1>
107−
108− <P>
109− {`Enter your point and at least two of your three Urbit master
110− ticket shards here. The index of the input field needs to
111− match the index of the shard.`}
112− </P>
113−
114− <PointInput
115− className="mono mt-8"
116− prop-size="lg"
117− prop-format="innerLabel"
118− type="text"
119− autoFocus
120− placeholder={`e.g. ${phPoint}`}
121− value={pointName}
122− onChange={this.handlePointNameInput}>
123− <InnerLabel>{'Point'}</InnerLabel>
124− <ValidatedSigil
125− className={'tr-0 mt-05 mr-0 abs'}
126− patp={pointName}
127− size={68}
128− margin={8}
129− />
130− </PointInput>
131−
132− <ShardInput
133− className="mono mt-8"
134− prop-size="md"
135− prop-format="innerLabel"
136− type="text"
137− name="shard1"
138− placeholder={`e.g. ${phTick}`}
139− value={shard1}
140− onChange={inp => this.handleShardInput(SHARDS.SHARD1, inp)}>
141− <InnerLabel>{'Shard 1'}</InnerLabel>
142− </ShardInput>
143−
144− <ShardInput
145− className="mono mt-8"
146− prop-size="md"
147− prop-format="innerLabel"
148− type="text"
149− name="shard2"
150− placeholder={`e.g. ${phTick}`}
151− value={shard2}
152− onChange={inp => this.handleShardInput(SHARDS.SHARD2, inp)}>
153− <InnerLabel>{'Shard 2'}</InnerLabel>
154− </ShardInput>
155−
156− <ShardInput
157− className="mono mt-8"
158− prop-size="md"
159− prop-format="innerLabel"
160− type="text"
161− name="shard3"
162− placeholder={`e.g. ${phTick}`}
163− value={shard3}
164− onChange={inp => this.handleShardInput(SHARDS.SHARD3, inp)}>
165− <InnerLabel>{'Shard 3'}</InnerLabel>
166− </ShardInput>
167−
168− <InputCaption>
169− {'If your wallet requires a passphrase, you may enter it below.'}
170− </InputCaption>
171−
172− <Input
173− className="pt-8"
174− prop-size="md"
175− prop-format="innerLabel"
176− name="passphrase"
177− type="password"
178− value={passphrase}
179− autocomplete="off"
180− onChange={this.handlePassphraseInput}>
181− <InnerLabel>{'Passphrase'}</InnerLabel>
182− </Input>
183−
184− <Button
185− disabled={!ready}
186− className={'mt-8'}
187− prop-size={'lg wide'}
188− // prop-color={this.buttonTriState(wallet)}
189− onClick={() =>
190− this.walletFromShards(
191− shard1,
192− shard2,
193− shard3,
194− pointName,
195− passphrase
196− )
197− }>
198− {'Unlock Wallet →'}
199− </Button>
200−
201− <Button
202− className={'mt-4'}
203− prop-size={'xl wide'}
204− disabled={Nothing.hasInstance(wallet)}
205− onClick={this.props.loginCompleted}>
206− {'Continue →'}
207− </Button>
208− </Col>
209− </Row>
210− );
211− }
41+ };
42+
43+ const shards = [shard1, shard2, shard3];
44+ const ready = shards.filter(x => x !== '').length > 1;
45+
46+ return (
47+ <View>
48+ Enter your point and at least two of your three Urbit master ticket shards
49+ here. The index of the input field needs to match the index of the shard.
50+ <PointInput
51+ name="point"
52+ label="Point"
53+ initialValue={pointName}
54+ onValue={setPointName}
55+ autoFocus
56+ />
57+ <TicketInput
58+ name="shard1"
59+ label="Shard 1"
60+ initialValue={shard1}
61+ onValue={setShard1}></TicketInput>
62+ <TicketInput
63+ name="shard2"
64+ label="Shard 2"
65+ initialValue={shard2}
66+ onValue={setShard2}></TicketInput>
67+ <TicketInput
68+ name="shard3"
69+ label="Shard 3"
70+ initialValue={shard3}
71+ onValue={setShard3}></TicketInput>
72+ If your wallet requires a passphrase, you may enter it below.
73+ <PassphraseInput
74+ name="passphrase"
75+ label="(Optional) Wallet Passphrase"
76+ initialValue={passphrase}
77+ onValue={setPassphrase}
78+ />
79+ <ForwardButton
80+ className={'mt3'}
81+ disabled={!ready}
82+ onClick={walletFromShards}>
83+ {'Unlock Wallet →'}
84+ </ForwardButton>
85+ <ForwardButton
86+ className={'mt3'}
87+ disabled={Nothing.hasInstance(wallet)}
88+ onClick={loginCompleted}>
89+ {'Continue →'}
90+ </ForwardButton>
91+ </View>
92+ );
21293}
213−
214−export default compose(withWallet)(Shards);