Allow account name editing (#44)

* Some progress

* Lift wallet selection state into wallet provider

* Account names

* Some bug squashing
This commit is contained in:
Nathaniel Parke 2020-11-13 12:42:37 +08:00 committed by GitHub
parent 78f555b2fc
commit 3884128d08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 12 deletions

View File

@ -7,7 +7,7 @@ import {
refreshWalletPublicKeys,
useBalanceInfo,
useWallet,
useWalletPublicKeys,
useWalletPublicKeys, useWalletSelector,
} from '../utils/wallet';
import LoadingIndicator from './LoadingIndicator';
import Collapse from '@material-ui/core/Collapse';
@ -29,6 +29,7 @@ import RefreshIcon from '@material-ui/icons/Refresh';
import IconButton from '@material-ui/core/IconButton';
import InfoIcon from '@material-ui/icons/InfoOutlined';
import Tooltip from '@material-ui/core/Tooltip';
import EditIcon from '@material-ui/icons/Edit';
import AddTokenDialog from './AddTokenDialog';
import ExportAccountDialog from './ExportAccountDialog';
import SendDialog from './SendDialog';
@ -41,6 +42,7 @@ import { showTokenInfoDialog } from '../utils/config';
import CloseTokenAccountDialog from './CloseTokenAccountButton';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import TokenIcon from './TokenIcon';
import EditAccountNameDialog from "./EditAccountNameDialog";
const balanceFormat = new Intl.NumberFormat(undefined, {
minimumFractionDigits: 4,
@ -52,14 +54,24 @@ export default function BalancesList() {
const wallet = useWallet();
const [publicKeys, loaded] = useWalletPublicKeys();
const [showAddTokenDialog, setShowAddTokenDialog] = useState(false);
const [showEditAccountNameDialog, setShowEditAccountNameDialog] = useState(false);
const { accounts, setAccountName } = useWalletSelector();
const selectedAccount = accounts.find(a => a.isSelected)
return (
<Paper>
<AppBar position="static" color="default" elevation={1}>
<Toolbar>
<Typography variant="h6" style={{ flexGrow: 1 }} component="h2">
Balances
{selectedAccount && selectedAccount.name} Balances
</Typography>
{selectedAccount && selectedAccount.name !== "Main account" &&
<Tooltip title="Edit Account Name" arrow>
<IconButton onClick={() => setShowEditAccountNameDialog(true)}>
<EditIcon />
</IconButton>
</Tooltip>
}
<Tooltip title="Add Token" arrow>
<IconButton onClick={() => setShowAddTokenDialog(true)}>
<AddIcon />
@ -90,6 +102,15 @@ export default function BalancesList() {
open={showAddTokenDialog}
onClose={() => setShowAddTokenDialog(false)}
/>
<EditAccountNameDialog
open={showEditAccountNameDialog}
onClose={() => setShowEditAccountNameDialog(false)}
oldName={selectedAccount ? selectedAccount.name : ''}
onEdit={(name) => {
setAccountName(selectedAccount.selector, name);
setShowEditAccountNameDialog(false)
}}
/>
</Paper>
);
}

View File

@ -0,0 +1,45 @@
import React, {useState} from "react";
import DialogForm from "./DialogForm";
import DialogContent from "@material-ui/core/DialogContent";
import DialogTitle from "@material-ui/core/DialogTitle";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
import DialogActions from "@material-ui/core/DialogActions";
export default function EditAccountNameDialog({open, oldName, onClose, onEdit}) {
const [name, setName] = useState(oldName);
return (
<DialogForm
open={open}
onEnter={() => setName(oldName)}
onClose={onClose}
onSubmit={() => onEdit(name.trim())}
fullWidth
>
<DialogTitle>Edit Account</DialogTitle>
<DialogContent>
<div
style={{
display: 'flex',
flexDirection: 'column',
}}
>
<TextField
label="Name"
fullWidth
variant="outlined"
margin="normal"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>Close</Button>
<Button type="submit" color="primary">
Save
</Button>
</DialogActions>
</DialogForm>
);
}

View File

@ -9,7 +9,6 @@ import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import { clusterApiUrl } from '@solana/web3.js';
import { useWalletSelector } from '../utils/wallet';
import { forgetWallet } from '../utils/wallet-seed';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import CheckIcon from '@material-ui/icons/Check';
import AddIcon from '@material-ui/icons/Add';

View File

@ -3,6 +3,8 @@ import { randomBytes, secretbox } from 'tweetnacl';
import * as bip32 from 'bip32';
import bs58 from 'bs58';
import { EventEmitter } from 'events';
import {useContext} from "react";
import {useWalletPrivateKeyImports} from "./wallet";
export async function generateMnemonicAndSeed() {
const bip39 = await import('bip39');
@ -132,11 +134,7 @@ function deriveImportsEncryptionKey(seed) {
}
export function forgetWallet() {
localStorage.removeItem('walletIndex');
localStorage.removeItem('walletCount');
localStorage.removeItem('walletPrivateKeyImports');
localStorage.removeItem('locked');
localStorage.removeItem('unlocked');
localStorage.clear()
sessionStorage.removeItem('unlocked');
unlockedMnemonicAndSeed = { mnemonic: null, seed: null, importsEncryptionKey: null };
walletSeedChanged.emit('change', unlockedMnemonicAndSeed);

View File

@ -1,4 +1,4 @@
import React, { useContext, useMemo } from 'react';
import React, {useContext, useMemo, useState} from 'react';
import * as bip32 from 'bip32';
import * as bs58 from 'bs58';
import {
@ -189,6 +189,24 @@ export function WalletProvider({ children }) {
}
}
const getWalletNames = () => {
return JSON.stringify(
[...Array(walletCount).keys()]
.map(idx => localStorage.getItem(`name${idx}`))
);
}
const [walletNames, setWalletNames] = useState(getWalletNames())
function setAccountName(selector, newName) {
if (selector.importedPubkey) {
let newPrivateKeyImports = { ...privateKeyImports };
newPrivateKeyImports[selector.importedPubkey.toString()].name = newName;
setPrivateKeyImports(newPrivateKeyImports);
} else {
localStorage.setItem(`name${selector.walletIndex}`, newName);
setWalletNames(getWalletNames());
}
}
const accounts = useMemo(() => {
if (!seed) {
return [];
@ -217,7 +235,8 @@ export function WalletProvider({ children }) {
});
return derivedAccounts.concat(importedAccounts);
}, [seed, walletCount, walletSelector, privateKeyImports]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [seed, walletCount, walletSelector, privateKeyImports, walletNames]);
return (
<WalletContext.Provider
@ -231,7 +250,8 @@ export function WalletProvider({ children }) {
privateKeyImports,
setPrivateKeyImports,
accounts,
addAccount
addAccount,
setAccountName
}}
>
{children}
@ -355,7 +375,8 @@ export function useWalletSelector() {
accounts,
addAccount,
setWalletSelector,
setAccountName,
} = useContext(WalletContext);
return { accounts, setWalletSelector, addAccount };
return { accounts, setWalletSelector, addAccount, setAccountName };
}