Allow account name editing (#44)
* Some progress * Lift wallet selection state into wallet provider * Account names * Some bug squashing
This commit is contained in:
parent
78f555b2fc
commit
3884128d08
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue