feature(settings): add export private keys in settings view

This commit is contained in:
George Lima 2019-01-12 16:30:44 -03:00
parent 3cf4d058f7
commit b586e7ed7f
1 changed files with 117 additions and 55 deletions

View File

@ -3,10 +3,12 @@ import React, { PureComponent } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { Button } from '../components/button'; import { Button } from '../components/button';
import { ModalComponent } from '../components/modal';
import { ConfirmDialogComponent } from '../components/confirm-dialog'; import { ConfirmDialogComponent } from '../components/confirm-dialog';
import { TextComponent } from '../components/text'; import { TextComponent } from '../components/text';
import { InputComponent } from '../components/input'; import { InputComponent } from '../components/input';
import { InputLabelComponent } from '../components/input-label';
import { RowComponent } from '../components/row';
import { Clipboard } from '../components/clipboard';
import rpc from '../../services/api'; import rpc from '../../services/api';
@ -17,10 +19,26 @@ const Wrapper = styled.div`
const ModalContent = styled.div` const ModalContent = styled.div`
padding: 20px; padding: 20px;
width: 100%; width: 100%;
overflow-x: hidden; max-height: 600px;
overflow-y: auto;
p {
word-break: break-all;
}
`; `;
type ViewKey = { const Btn = styled(Button)`
margin-bottom: 10px;
`;
const ClipboardButton = styled(Clipboard)`
width: 50px;
border-radius: ${props => props.theme.boxBorderRadius};
height: 45px;
margin-left: 5px;
`;
type Key = {
zAddress: string, zAddress: string,
key: string, key: string,
}; };
@ -29,18 +47,20 @@ type Props = {
addresses: string[], addresses: string[],
}; };
type State = { type State = {
viewKeys: ViewKey[], viewKeys: Key[],
privateKeys: Key[],
isLoading: boolean, isLoading: boolean,
successExportViewKeys: boolean, successExportViewKeys: boolean,
message: string | null, successExportPrivateKeys: boolean,
}; };
export class SettingsView extends PureComponent<Props, State> { export class SettingsView extends PureComponent<Props, State> {
state = { state = {
viewKeys: [], viewKeys: [],
privateKeys: [],
isLoading: false, isLoading: false,
successExportViewKeys: false, successExportViewKeys: false,
message: null, successExportPrivateKeys: false,
}; };
exportViewKeys = () => { exportViewKeys = () => {
@ -48,6 +68,8 @@ export class SettingsView extends PureComponent<Props, State> {
const zAddresses = addresses.filter(addr => addr.startsWith('z')); const zAddresses = addresses.filter(addr => addr.startsWith('z'));
this.setState({ isLoading: true });
Promise.all( Promise.all(
zAddresses.map(async (zAddr) => { zAddresses.map(async (zAddr) => {
const viewKey = await rpc.z_exportviewingkey(zAddr); const viewKey = await rpc.z_exportviewingkey(zAddr);
@ -57,76 +79,116 @@ export class SettingsView extends PureComponent<Props, State> {
this.setState({ this.setState({
viewKeys, viewKeys,
successExportViewKeys: true, successExportViewKeys: true,
isLoading: false,
}); });
}); });
}; };
handleCloseModal = (fn: () => void) => () => { exportPrivateKeys = () => {
this.setState( const { addresses } = this.props;
{
message: null, const zAddresses = addresses.filter(addr => addr.startsWith('z'));
},
fn, this.setState({ isLoading: true });
);
Promise.all(
zAddresses.map(async (zAddr) => {
const privateKey = await rpc.z_exportkey(zAddr);
return { zAddress: zAddr, key: privateKey };
}),
).then((privateKeys) => {
this.setState({
privateKeys,
successExportPrivateKeys: true,
isLoading: false,
});
});
}; };
render = () => { render = () => {
const { const {
viewKeys, isLoading, successExportViewKeys, message, viewKeys,
isLoading,
successExportViewKeys,
privateKeys,
successExportPrivateKeys,
} = this.state; } = this.state;
return ( return (
<Wrapper> <Wrapper>
<ModalComponent <ConfirmDialogComponent
title='Export view keys'
renderTrigger={toggleVisibility => ( renderTrigger={toggleVisibility => (
<Button label='Export view keys' onClick={toggleVisibility} /> <Btn label='Export view keys' onClick={toggleVisibility} />
)} )}
closeOnBackdropClick={false} onConfirm={this.exportViewKeys}
closeOnEsc={false} showButtons={!successExportViewKeys}
width={750}
> >
{toggleVisibility => ( <ModalContent>
<ConfirmDialogComponent {successExportViewKeys ? (
title='Export view keys' viewKeys.map(({ zAddress, key }) => (
handleClose={this.handleCloseModal(toggleVisibility)} <>
onConfirm={this.exportViewKeys} <InputLabelComponent value={zAddress} />
showButtons={!successExportViewKeys} <RowComponent alignItems='center'>
width={750}
>
<ModalContent>
{successExportViewKeys ? (
<>
<InputComponent <InputComponent
inputType='textarea' value={key}
rows={10}
value={viewKeys.reduce(
(acc, cur, idx) => `${acc}${cur.key} ${
idx === viewKeys.length - 1 ? '' : '\n\n'
}`,
'',
)}
onFocus={(event) => { onFocus={(event) => {
event.currentTarget.select(); event.currentTarget.select();
document.execCommand('copy');
this.setState({ message: 'Copied to clipboard!' });
}} }}
/> />
{message && ( <ClipboardButton text={key} />
<TextComponent value={message} align='center' /> </RowComponent>
)} </>
</> ))
) : ( ) : (
<TextComponent <TextComponent
value={ value={
isLoading isLoading
? 'Loading...' ? 'Loading...'
: 'Ut id vulputate arcu. Curabitur mattis aliquam magna sollicitudin vulputate. Morbi tempus bibendum porttitor. Quisque dictum ac ipsum a luctus. Donec et lacus ac erat consectetur molestie a id erat.' : 'Ut id vulputate arcu. Curabitur mattis aliquam magna sollicitudin vulputate. Morbi tempus bibendum porttitor. Quisque dictum ac ipsum a luctus. Donec et lacus ac erat consectetur molestie a id erat.'
} }
/> />
)} )}
</ModalContent> </ModalContent>
</ConfirmDialogComponent> </ConfirmDialogComponent>
<ConfirmDialogComponent
title='Export private keys'
renderTrigger={toggleVisibility => (
<Btn label='Export private keys' onClick={toggleVisibility} />
)} )}
</ModalComponent> onConfirm={this.exportPrivateKeys}
showButtons={!successExportPrivateKeys}
width={750}
>
<ModalContent>
{successExportPrivateKeys ? (
privateKeys.map(({ zAddress, key }) => (
<>
<InputLabelComponent value={zAddress} />
<RowComponent alignItems='center'>
<InputComponent
value={key}
onFocus={(event) => {
event.currentTarget.select();
}}
/>
<ClipboardButton text={key} />
</RowComponent>
</>
))
) : (
<TextComponent
value={
isLoading
? 'Loading...'
: 'Ut id vulputate arcu. Curabitur mattis aliquam magna sollicitudin vulputate. Morbi tempus bibendum porttitor. Quisque dictum ac ipsum a luctus. Donec et lacus ac erat consectetur molestie a id erat.'
}
/>
)}
</ModalContent>
</ConfirmDialogComponent>
</Wrapper> </Wrapper>
); );
}; };