-
Notifications
You must be signed in to change notification settings - Fork 155
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* not showing password entry screen - why? * flow working - need to polish up * flow working - need to polish up * remove keystore app tests temporarily * remove intermediary state * need to fix transitions & then re-do tests * tests green * tests re-added for AddKeystore * use advanceTimersAfterInput * addressing PR comments - stop flashing of old stater * fix tests * lowercase * allow advanceTimersAfterInput to be a number, pass through * remove act * rebase fixup * fix prop --------- Co-authored-by: goosewobbler <432005+goosewobbler@users.noreply.github.com> Co-authored-by: goosewobbler <goosewobbler@protonmail.com> Co-authored-by: Matt Holtzman <matt.holtzman@gmail.com>
- Loading branch information
1 parent
d1f6cb3
commit c9d7bc6
Showing
9 changed files
with
300 additions
and
249 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,251 +1,109 @@ | ||
import React from 'react' | ||
import Restore from 'react-restore' | ||
|
||
import React, { useEffect, useState } from 'react' | ||
import { AddHotAccount } from '../Components' | ||
import link from '../../../../../resources/link' | ||
import svg from '../../../../../resources/svg' | ||
import RingIcon from '../../../../../resources/Components/RingIcon' | ||
|
||
class AddRing extends React.Component { | ||
constructor(...args) { | ||
super(...args) | ||
this.state = { | ||
index: 0, | ||
adding: false, | ||
password: '', | ||
status: '', | ||
error: false, | ||
mode: this.props.mode ? this.props.mode : 'manual', | ||
keystore: '', | ||
keystorePassword: '' | ||
} | ||
this.forms = { | ||
keystorePassword: React.createRef(), | ||
keystoreCreatePassword: React.createRef() | ||
import { PasswordInput } from '../../../../../resources/Components/Password' | ||
|
||
const navForward = (accountData) => | ||
link.send('nav:forward', 'dash', { | ||
view: 'accounts', | ||
data: { | ||
showAddAccounts: true, | ||
newAccountType: 'keystore', | ||
accountData | ||
} | ||
} | ||
}) | ||
|
||
onChange(key, e) { | ||
e.preventDefault() | ||
const update = {} | ||
update[key] = e.target.value || '' | ||
this.setState(update) | ||
} | ||
|
||
onBlur(key, e) { | ||
e.preventDefault() | ||
const update = {} | ||
update[key] = this.state[key] || '' | ||
this.setState(update) | ||
} | ||
const LocateKeystore = ({ addKeystore, error, setError }) => { | ||
useEffect(() => { | ||
if (!error) return | ||
setTimeout(() => { | ||
setError('') | ||
}, 1_500) | ||
}, [error]) | ||
return ( | ||
<div className='addAccountItemOptionSetupFrame'> | ||
{error ? ( | ||
<div role='button' className='addAccountItemOptionError'> | ||
{error} | ||
</div> | ||
) : ( | ||
<div | ||
role='button' | ||
className='addAccountItemOptionSubmit' | ||
style={{ marginTop: '10px' }} | ||
onClick={() => addKeystore()} | ||
> | ||
Locate Keystore File (json) | ||
</div> | ||
)} | ||
</div> | ||
) | ||
} | ||
|
||
onFocus(key, e) { | ||
e.preventDefault() | ||
if (this.state[key] === '') { | ||
const update = {} | ||
update[key] = '' | ||
this.setState(update) | ||
} | ||
const Locating = () => ( | ||
<div className='addAccountItemOptionSetupFrame'> | ||
<div role={'status'} className='addAccountItemOptionTitle' style={{ marginTop: '15px' }}> | ||
Locating Keystore file | ||
</div> | ||
</div> | ||
) | ||
|
||
const EnterKeystorePassword = ({ keystore }) => { | ||
const next = (keystorePassword) => { | ||
navForward({ | ||
secret: keystore, | ||
creationArgs: [keystorePassword] | ||
}) | ||
} | ||
//TODO: validate keystore password here? | ||
const getError = () => {} | ||
const title = 'Enter Keystore Password' | ||
const buttonText = 'Continue' | ||
return <PasswordInput {...{ next, getError, title, buttonText }} /> | ||
} | ||
|
||
next() { | ||
this.blurActive() | ||
this.setState({ index: ++this.state.index }) | ||
this.focusActive() | ||
} | ||
const LoadKeystore = ({ accountData }) => { | ||
const { keystore, selecting, secret } = accountData | ||
|
||
createKeystore() { | ||
this.next() | ||
link.rpc( | ||
'createFromKeystore', | ||
this.state.keystore, | ||
this.state.keystorePassword, | ||
this.state.password, | ||
(err, signer) => { | ||
if (err) { | ||
this.setState({ status: err, error: true }) | ||
} else { | ||
// reset nav state to before the start of the flow and open the new signer | ||
link.send('tray:action', 'backDash', 2) | ||
const crumb = { | ||
view: 'expandedSigner', | ||
data: { signer: signer.id } | ||
} | ||
link.send('tray:action', 'navDash', crumb) | ||
} | ||
} | ||
) | ||
} | ||
const [error, setError] = useState('') | ||
|
||
addKeystore() { | ||
this.setState({ mode: 'keystore' }) | ||
this.next() | ||
const addKeystore = () => { | ||
navForward({ selecting: true }) | ||
setTimeout(() => { | ||
link.rpc('locateKeystore', (err, keystore) => { | ||
link.rpc('locateKeystore', (err, locatedKeystore) => { | ||
link.send('nav:back', 'dash') | ||
if (err) { | ||
this.setState({ keystore: '', error: err }) | ||
setError(err) | ||
} else { | ||
this.setState({ keystore }) | ||
this.next() | ||
navForward({ keystore: locatedKeystore }) | ||
} | ||
}) | ||
}, 640) | ||
} | ||
|
||
restart() { | ||
this.setState({ | ||
index: 1, | ||
adding: false, | ||
password: '', | ||
mode: 'manual', | ||
privateKey: '', | ||
keystore: '', | ||
keystorePassword: '' | ||
}) | ||
setTimeout(() => { | ||
this.setState({ status: '', error: false }) | ||
}, 500) | ||
this.focusActive() | ||
} | ||
|
||
keyPress(e, next) { | ||
if (e.key === 'Enter') { | ||
e.preventDefault() | ||
next() | ||
} | ||
} | ||
|
||
adding() { | ||
this.setState({ adding: true }) | ||
} | ||
|
||
blurActive() { | ||
const formInput = this.currentForm() | ||
if (formInput) formInput.current.blur() | ||
} | ||
|
||
focusActive() { | ||
setTimeout(() => { | ||
const formInput = this.currentForm() | ||
if (formInput) formInput.current.focus() | ||
}, 500) | ||
} | ||
const viewIndex = secret || keystore ? 2 : selecting ? 1 : 0 | ||
|
||
currentForm() { | ||
let current | ||
if (this.state.index === 2) current = this.forms.keystorePassword | ||
if (this.state.index === 3) current = this.forms.keystoreCreatePassword | ||
return current | ||
} | ||
|
||
render() { | ||
let itemClass = 'addAccountItem addAccountItemSmart addAccountItemAdding' | ||
return ( | ||
<div className={itemClass} style={{ transitionDelay: (0.64 * this.props.index) / 4 + 's' }}> | ||
<div className='addAccountItemBar addAccountItemHot' /> | ||
<div className='addAccountItemWrap'> | ||
<div className='addAccountItemTop'> | ||
<div className='addAccountItemTopType'> | ||
<div className='addAccountItemIcon'> | ||
<div className='addAccountItemIconType addAccountItemIconHot'> | ||
<RingIcon svgName={'file'} /> | ||
</div> | ||
<div className='addAccountItemIconHex addAccountItemIconHexHot' /> | ||
</div> | ||
<div className='addAccountItemTopTitle'>Keystore</div> | ||
</div> | ||
{/* <div className='addAccountItemClose' onMouseDown={() => this.props.close()}>{'Done'}</div> */} | ||
<div className='addAccountItemSummary'> | ||
A keystore account lets you add accounts from your keystore.json file | ||
</div> | ||
</div> | ||
<div className='addAccountItemOption'> | ||
<div | ||
className='addAccountItemOptionIntro' | ||
onMouseDown={() => { | ||
this.adding() | ||
setTimeout(() => { | ||
link.send('tray:action', 'navDash', { | ||
view: 'notify', | ||
data: { notify: 'hotAccountWarning', notifyData: {} } | ||
}) | ||
}, 800) | ||
}} | ||
> | ||
Add Keyring Account | ||
</div> | ||
<div | ||
className='addAccountItemOptionSetup' | ||
style={{ transform: `translateX(-${100 * this.state.index}%)` }} | ||
> | ||
<div className='addAccountItemOptionSetupFrames'> | ||
<div className='addAccountItemOptionSetupFrame'> | ||
<div className='addAccountItemOptionTitle'>Add Keystore File</div> | ||
<div | ||
className='addAccountItemOptionSubmit' | ||
style={{ marginTop: '10px' }} | ||
onMouseDown={() => this.addKeystore()} | ||
> | ||
Locate Keystore File (json) | ||
</div> | ||
</div> | ||
<div className='addAccountItemOptionSetupFrame'> | ||
<div className='addAccountItemOptionTitle'>Locating Keystore</div> | ||
</div> | ||
<div className='addAccountItemOptionSetupFrame'> | ||
<div className='addAccountItemOptionTitle'>Enter Keystore Password</div> | ||
<div className='addAccountItemOptionInput'> | ||
<input | ||
type='password' | ||
tabIndex='-1' | ||
ref={this.forms.keystorePassword} | ||
value={this.state.keystorePassword} | ||
onChange={(e) => this.onChange('keystorePassword', e)} | ||
onFocus={(e) => this.onFocus('keystorePassword', e)} | ||
onBlur={(e) => this.onBlur('keystorePassword', e)} | ||
onKeyPress={(e) => this.keyPress(e, () => this.next())} | ||
/> | ||
</div> | ||
<div className='addAccountItemOptionSubmit' onMouseDown={() => this.next()}> | ||
Next | ||
</div> | ||
</div> | ||
<div className='addAccountItemOptionSetupFrame'> | ||
<div className='addAccountItemOptionTitle'>Create Account Password</div> | ||
<div className='addAccountItemOptionInput addAccountItemOptionInputPassword'> | ||
<div className='addAccountItemOptionSubtitle'> | ||
password must be 12 characters or longer | ||
</div> | ||
<input | ||
type='password' | ||
tabIndex='-1' | ||
ref={this.forms.keystoreCreatePassword} | ||
value={this.state.password} | ||
onChange={(e) => this.onChange('password', e)} | ||
onFocus={(e) => this.onFocus('password', e)} | ||
onBlur={(e) => this.onBlur('password', e)} | ||
onKeyPress={(e) => this.keyPress(e, () => this.createKeystore())} | ||
/> | ||
</div> | ||
<div className='addAccountItemOptionSubmit' onMouseDown={() => this.createKeystore()}> | ||
Create | ||
</div> | ||
</div> | ||
<div className='addAccountItemOptionSetupFrame'> | ||
<div className='addAccountItemOptionTitle'>{this.state.status}</div> | ||
{this.state.error ? ( | ||
<div className='addAccountItemOptionSubmit' onMouseDown={() => this.restart()}> | ||
try again | ||
</div> | ||
) : null} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div className='addAccountItemFooter' /> | ||
</div> | ||
</div> | ||
) | ||
} | ||
const steps = [ | ||
<LocateKeystore key={0} {...{ addKeystore, error, setError }} />, | ||
<Locating key={1} />, | ||
<EnterKeystorePassword key={2} keystore={accountData.keystore} /> | ||
] | ||
return <>{steps[viewIndex]}</> | ||
} | ||
|
||
export default Restore.connect(AddRing) | ||
const AddKeystore = ({ accountData }) => ( | ||
<AddHotAccount | ||
title='Key Store' | ||
summary='A keystore account lets you add accounts from your keystore.json file' | ||
svgName='file' | ||
intro='Add KeyStore Account' | ||
createSignerMethod='createFromKeystore' | ||
newAccountType='keystore' | ||
backSteps={6} | ||
accountData={accountData} | ||
firstStep={<LoadKeystore key={0} accountData={accountData} />} | ||
validateSecret={() => {}} | ||
/> | ||
) | ||
|
||
export default AddKeystore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.