diff --git a/packages/neuron-ui/src/components/Addresses/index.tsx b/packages/neuron-ui/src/components/Addresses/index.tsx index 575ce0843d..f880735d28 100644 --- a/packages/neuron-ui/src/components/Addresses/index.tsx +++ b/packages/neuron-ui/src/components/Addresses/index.tsx @@ -2,6 +2,7 @@ import React, { useCallback } from 'react' import { Container } from 'react-bootstrap' import { RouteComponentProps } from 'react-router-dom' import { useTranslation } from 'react-i18next' +import { History } from 'history' import Table from '../../widgets/Table' import { Routes, EXPLORER } from '../../utils/const' import { mockAddresses } from './mock' @@ -41,7 +42,7 @@ const getTransactionsForAddress = (address: string) => { return address.length } -const AddressPanel = ({ address, history }: { address: string; history: any }) => { +const AddressPanel = ({ address, history }: { address: string; history: History }) => { const [t] = useTranslation() const actionItems = [ { @@ -79,7 +80,7 @@ const AddressPanel = ({ address, history }: { address: string; history: any }) = ) } -const fetchHDAddresses = (history: any) => { +const fetchHDAddresses = (history: History) => { const addresses = generateHDAddresses().map(address => ({ type: address.type, address: , diff --git a/packages/neuron-ui/src/components/NetworkSetting/index.tsx b/packages/neuron-ui/src/components/NetworkSetting/index.tsx index 1f61159901..3b4eb2a0cc 100644 --- a/packages/neuron-ui/src/components/NetworkSetting/index.tsx +++ b/packages/neuron-ui/src/components/NetworkSetting/index.tsx @@ -5,12 +5,13 @@ import { useTranslation } from 'react-i18next' import { ContentProps } from '../../containers/MainContent' import { Routes } from '../../utils/const' +import { useNeuronWallet } from '../../utils/hooks' import { MainActions, actionCreators } from '../../containers/MainContent/reducer' import Dialog from '../../widgets/Dialog' +import ListGroupWithMaxHeight from '../../widgets/ListGroupWithMaxHeight' import ContextMenuZone from '../../widgets/ContextMenuZone' import RemoveNetworkDialog from './RemoveNetworkDialog' -import { useNeuronWallet } from '../../utils/hooks' interface MenuItemParams { id: string @@ -66,20 +67,11 @@ const Networks = (props: React.PropsWithoutRef - + {networks.map(network => { - const isChecked = - // chain.network.remote === network.remote && // it will make things too complex - chain.network.id === network.id + const isChecked = chain.network.id === network.id return ( - + ) })} - + {t('settings.network.add-network')} diff --git a/packages/neuron-ui/src/components/NetworkStatus/index.tsx b/packages/neuron-ui/src/components/NetworkStatus/index.tsx index 839221f61b..550c2f4540 100644 --- a/packages/neuron-ui/src/components/NetworkStatus/index.tsx +++ b/packages/neuron-ui/src/components/NetworkStatus/index.tsx @@ -83,16 +83,20 @@ const ConnectStatusHeader = ({ selected={networkItems.findIndex(network => network.label === chain.network.name)} style={{ position: 'absolute', - top: 'calc(100% + 1px)', + top: '100%', left: tipNumber === null ? 'auto' : '0', right: tipNumber === null ? '0' : 'auto', zIndex: '999', display: 'none', + maxHeight: '50vh', + overflowY: 'scroll', + border: '1px solid #ddd', }} itemsStyle={{ textTransform: 'capitalize', boxShadow: '0px 0px 1px rgba(120, 120, 120, 0.5)', maxWidth: '200px', + minHeight: '48px', }} /> diff --git a/packages/neuron-ui/src/components/Router/index.tsx b/packages/neuron-ui/src/components/Router/index.tsx index d3da571d74..c045f3c083 100644 --- a/packages/neuron-ui/src/components/Router/index.tsx +++ b/packages/neuron-ui/src/components/Router/index.tsx @@ -18,7 +18,7 @@ import Transaction from '../Transaction' import Settings from '../Settings' import GeneralSetting from '../GeneralSetting' import Addresses from '../Addresses' -import Wallets from '../Settings/Wallets' +import Wallets from '../WalletSetting' import NetworkSetting from '../NetworkSetting' import NetworkEditor from '../NetworkEditor' import WalletEditor from '../WalletEditor' diff --git a/packages/neuron-ui/src/components/Settings/InputWalletPasswordDialog.tsx b/packages/neuron-ui/src/components/Settings/InputWalletPasswordDialog.tsx deleted file mode 100644 index 5848e6fde5..0000000000 --- a/packages/neuron-ui/src/components/Settings/InputWalletPasswordDialog.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import React, { useState } from 'react' -import styled from 'styled-components' -import { useTranslation } from 'react-i18next' -import { Card, Button, Form, Row, Col } from 'react-bootstrap' - -import { MainActions, actionCreators } from '../../containers/MainContent/reducer' -import { Wallet } from '../../contexts/NeuronWallet' - -export enum CheckType { - EditWallet, - DeleteWallet, -} - -interface InputPasswordProps { - wallet?: Wallet - dispatch: any - handle?: any - errorMessage: string - checkType: CheckType - newWalletName?: string - newPassword?: string -} - -const ButtonDiv = styled.div` - display: flex; - justify-content: space-between; -` - -const InputWalletPasswordDialog = ({ - wallet, - dispatch, - checkType, - errorMessage, - newWalletName, - newPassword, -}: InputPasswordProps) => { - const [password, setPassword] = useState('') - const [t] = useTranslation() - - const handleSubmit = (id: string) => { - switch (checkType) { - case CheckType.EditWallet: - dispatch( - actionCreators.updateWallet({ - id, - password, - newPassword, - name: newWalletName, - }), - ) - break - case CheckType.DeleteWallet: - dispatch(actionCreators.deleteWallet({ id, password })) - break - default: - break - } - } - - return ( - ) => { - e.preventDefault() - e.stopPropagation() - }} - style={{ - width: '40%', - }} - > - {wallet ? ( - <> - {t('settings.wallet-manager.delete-wallet-title', { name: wallet.name })} - - - - setPassword(e.currentTarget.value)} - isInvalid={errorMessage !== ''} - /> - {errorMessage} - - - - - - - - - - - ) : ( -
Wallet not found
- )} -
- ) -} - -export default InputWalletPasswordDialog diff --git a/packages/neuron-ui/src/components/Settings/Wallets.tsx b/packages/neuron-ui/src/components/Settings/Wallets.tsx deleted file mode 100644 index 36d261ff13..0000000000 --- a/packages/neuron-ui/src/components/Settings/Wallets.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import React, { useMemo, useEffect, useState } from 'react' -import { Link, RouteComponentProps } from 'react-router-dom' -import { Col, Row, ListGroup, Form, Container, Pagination } from 'react-bootstrap' -import { useTranslation } from 'react-i18next' - -import { Routes, MnemonicAction } from '../../utils/const' -import { ContentProps } from '../../containers/MainContent' -import { actionCreators, MainActions } from '../../containers/MainContent/reducer' -import InputWalletPasswordDialog, { CheckType } from './InputWalletPasswordDialog' -import Dialog from '../../widgets/Dialog' -import { useNeuronWallet } from '../../utils/hooks' -import ContextMenuZone from '../../widgets/ContextMenuZone' - -interface MenuItemParams { - id: string -} - -const buttons = [ - { label: 'wizard.create-new-wallet', href: `${Routes.Mnemonic}/${MnemonicAction.Create}` }, - { label: 'wizard.import-wallet', href: `${Routes.Mnemonic}/${MnemonicAction.Import}` }, -] - -const Wallets = (props: React.PropsWithoutRef) => { - const { - wallet: activeWallet, - settings: { wallets }, - messages: errorMessage, - } = useNeuronWallet() - const { dispatch, dialog, history } = props - const [t] = useTranslation() - const pageSize = 5 - const [totalPage, setTotalPage] = useState(0) - const [pageNo, setPageNo] = useState(1) - const showWallets = wallets.slice(pageSize * (pageNo - 1), pageSize * pageNo) - - useEffect(() => { - dispatch({ - type: MainActions.SetDialog, - payload: { - open: false, - }, - }) - setTotalPage(Math.ceil(wallets.length / pageSize)) - }, [wallets.length]) - - useEffect(() => { - if (pageNo > totalPage) { - setPageNo(1) - } - }, [totalPage]) - - const menuItems = useMemo( - () => [ - { - label: t('menuitem.select'), - click: ({ id }: MenuItemParams) => { - dispatch(actionCreators.activateWallet(id)) - }, - }, - { - label: t('menuitem.backup'), - click: ({ id }: MenuItemParams) => { - dispatch(actionCreators.backupWallet(id)) - }, - }, - { - label: t('menuitem.edit'), - click: ({ id }: MenuItemParams) => { - history.push(`${Routes.WalletEditor}/${id}`) - }, - }, - { - label: t('menuitem.remove'), - click: ({ id }: MenuItemParams) => { - dispatch({ - type: MainActions.SetDialog, - payload: { - open: true, - id, - }, - }) - }, - }, - ], - [], - ) - - const pageItems = useMemo(() => { - const items = [] - for (let number = 1; number <= totalPage; number++) { - items.push( - { - setPageNo(number) - }} - > - {number} - , - ) - } - return items - }, [totalPage, pageNo]) - - return ( - <> - - - {showWallets.map(wallet => { - const isChecked = wallet.id === activeWallet.id - return ( - - { - dispatch(actionCreators.activateWallet(wallet.id)) - }} - /> - - ) - })} - - - - {pageItems} - - - - {buttons.map(({ label, href }) => ( - - - {t(label)} - - - ))} - - - { - dispatch({ - type: MainActions.SetDialog, - payload: { - open: false, - }, - }) - }} - > - wallet.id === dialog.id)} - dispatch={dispatch} - errorMessage={errorMessage.length > 0 ? errorMessage[errorMessage.length - 1].content : ''} - checkType={CheckType.DeleteWallet} - /> - - - ) -} - -export default Wallets diff --git a/packages/neuron-ui/src/components/Settings/index.tsx b/packages/neuron-ui/src/components/Settings/index.tsx index 174138bbaa..4c6931fdf3 100644 --- a/packages/neuron-ui/src/components/Settings/index.tsx +++ b/packages/neuron-ui/src/components/Settings/index.tsx @@ -1,4 +1,5 @@ import React from 'react' +import { Location } from 'history' import { NavLink } from 'react-router-dom' import { Nav } from 'react-bootstrap' import { useTranslation } from 'react-i18next' @@ -19,8 +20,8 @@ const Settings = () => { { - if (history.pathname === Routes.Settings && idx === 0) { + isActive={(match: any, location: Location) => { + if (location.pathname === Routes.Settings && idx === 0) { return true } return !!match diff --git a/packages/neuron-ui/src/components/WalletEditor/index.tsx b/packages/neuron-ui/src/components/WalletEditor/index.tsx index 295afe4079..2c484eb627 100644 --- a/packages/neuron-ui/src/components/WalletEditor/index.tsx +++ b/packages/neuron-ui/src/components/WalletEditor/index.tsx @@ -83,9 +83,6 @@ export default (props: React.PropsWithoutRef <> {t('settings.wallet-manager.delete-wallet-title', { name: wallet.name })} diff --git a/packages/neuron-ui/src/components/WalletSetting/hooks.ts b/packages/neuron-ui/src/components/WalletSetting/hooks.ts new file mode 100644 index 0000000000..6ad89665e0 --- /dev/null +++ b/packages/neuron-ui/src/components/WalletSetting/hooks.ts @@ -0,0 +1,103 @@ +import { useState, useCallback, useMemo } from 'react' +import { History } from 'history' +import { MainActions, actionCreators } from '../../containers/MainContent/reducer' +import i18n from '../../utils/i18n' +import { Routes } from '../../utils/const' +import { Wallet } from '../../contexts/NeuronWallet/wallet' + +interface MenuItemParams { + id: string +} + +export const useToggleDialog = (dispatch: React.Dispatch) => + useCallback( + (open: boolean) => { + dispatch({ + type: MainActions.SetDialog, + payload: { + open, + }, + }) + }, + [dispatch], + ) + +export const useDeleteWallet = () => { + const [id, setId] = useState('') + const [password, setPassword] = useState('') + + return { + id: { + value: id, + set: (deleteId: string) => setId(deleteId), + onChange: (e: React.FormEvent<{ value: string }>) => setId(e.currentTarget.value), + }, + password: { + value: password, + onChange: (e: React.FormEvent<{ value: string }>) => setPassword(e.currentTarget.value), + }, + } +} + +export const useMenuItems = ( + deleteWallet: ReturnType, + history: History, + toggleDialog: ReturnType, + dispatch: React.Dispatch, +) => { + return useMemo( + () => [ + { + label: i18n.t('menuitem.select'), + click: ({ id }: MenuItemParams) => { + dispatch(actionCreators.activateWallet(id)) + }, + }, + { + label: i18n.t('menuitem.backup'), + click: ({ id }: MenuItemParams) => { + dispatch(actionCreators.backupWallet(id)) + }, + }, + { + label: i18n.t('menuitem.edit'), + click: ({ id }: MenuItemParams) => { + history.push(`${Routes.WalletEditor}/${id}`) + }, + }, + { + label: i18n.t('menuitem.remove'), + click: ({ id }: MenuItemParams) => { + deleteWallet.id.set(id) + toggleDialog(true) + }, + }, + ], + [deleteWallet.id, dispatch, history, toggleDialog], + ) +} +export const useWalletToDelete = (deleteId: string, wallets: Wallet[]) => + useMemo(() => wallets.find(w => w.id === deleteId), [deleteId, wallets]) + +export const useHandleConfirm = ( + deleteWallet: ReturnType, + toggleDialog: ReturnType, + dispatch: React.Dispatch, +) => + useCallback(() => { + toggleDialog(false) + dispatch( + actionCreators.deleteWallet({ + id: deleteWallet.id.value, + password: deleteWallet.password.value, + }), + ) + }, [deleteWallet, toggleDialog, dispatch]) + +export default { + useToggleDialog, + useDeleteWallet, + useMenuItems, + useWalletToDelete, + useHandleConfirm, +} diff --git a/packages/neuron-ui/src/components/WalletSetting/index.tsx b/packages/neuron-ui/src/components/WalletSetting/index.tsx new file mode 100644 index 0000000000..c75c990a35 --- /dev/null +++ b/packages/neuron-ui/src/components/WalletSetting/index.tsx @@ -0,0 +1,108 @@ +import React from 'react' +import { Link, RouteComponentProps } from 'react-router-dom' +import { Col, Card, Button, Row, ListGroup, Form, Container } from 'react-bootstrap' +import { useTranslation } from 'react-i18next' + +import { Routes, MnemonicAction } from '../../utils/const' +import { useNeuronWallet } from '../../utils/hooks' +import { ContentProps } from '../../containers/MainContent' +import { actionCreators } from '../../containers/MainContent/reducer' + +import Dialog from '../../widgets/Dialog' +import ListGroupWithMaxHeight from '../../widgets/ListGroupWithMaxHeight' +import ContextMenuZone from '../../widgets/ContextMenuZone' + +import { useToggleDialog, useDeleteWallet, useMenuItems, useWalletToDelete, useHandleConfirm } from './hooks' + +const buttons = [ + { label: 'wizard.create-new-wallet', href: `${Routes.Mnemonic}/${MnemonicAction.Create}` }, + { label: 'wizard.import-wallet', href: `${Routes.Mnemonic}/${MnemonicAction.Import}` }, +] + +const Wallets = ({ dispatch, dialog, history }: React.PropsWithoutRef) => { + const { + wallet: { id: activeId }, + settings: { wallets }, + } = useNeuronWallet() + + const deleteWallet = useDeleteWallet() + const [t] = useTranslation() + const toggleDialog = useToggleDialog(dispatch) + const menuItems = useMenuItems(deleteWallet, history, toggleDialog, dispatch) + const handleConfirm = useHandleConfirm(deleteWallet, toggleDialog, dispatch) + const walletToDelete = useWalletToDelete(deleteWallet.id.value, wallets) + + return ( + <> + + + {wallets.map(wallet => { + const isChecked = wallet.id === activeId + return ( + + { + dispatch(actionCreators.activateWallet(wallet.id)) + }} + /> + + ) + })} + + + + + {buttons.map(({ label, href }) => ( + + + {t(label)} + + + ))} + + + toggleDialog(false)}> + ) => { + e.preventDefault() + e.stopPropagation() + }} + > + {walletToDelete ? ( + {t('settings.wallet-manager.delete-wallet-title', { name: walletToDelete.name })} + ) : ( + Not found + )} + {walletToDelete ? ( + + + + + + + + ) : null} + + + + + + + + ) +} + +export default Wallets diff --git a/packages/neuron-ui/src/containers/MainContent/index.tsx b/packages/neuron-ui/src/containers/MainContent/index.tsx index 99ae1ddf51..d0bcbdd182 100644 --- a/packages/neuron-ui/src/containers/MainContent/index.tsx +++ b/packages/neuron-ui/src/containers/MainContent/index.tsx @@ -8,9 +8,10 @@ import { useNeuronWallet } from '../../utils/hooks' const Main = styled.main` display: flex; flex-direction: column; - height: 100%; + height: calc(100% -100px); width: 100%; padding-top: 50px; + box-sizing: border-box; ` export interface ContentProps extends InitState { diff --git a/packages/neuron-ui/src/containers/Providers/index.tsx b/packages/neuron-ui/src/containers/Providers/index.tsx index 101de22ed4..0f43618906 100644 --- a/packages/neuron-ui/src/containers/Providers/index.tsx +++ b/packages/neuron-ui/src/containers/Providers/index.tsx @@ -226,7 +226,7 @@ const withProviders = (Comp: React.ComponentType<{ providerDispatch: ProviderDis }) } }) - }, []) + }, [i18n]) return ( diff --git a/packages/neuron-ui/src/locales/en.ts b/packages/neuron-ui/src/locales/en.ts index d19203df6a..dc129fdedc 100644 --- a/packages/neuron-ui/src/locales/en.ts +++ b/packages/neuron-ui/src/locales/en.ts @@ -73,8 +73,9 @@ export default { 'edit-wallet': 'Edit Wallet', }, 'delete-wallet-title': 'Please Enter {{name}} Password', + password: 'Password', 'wallet-detail': { - balance: 'balance', + balance: 'Balance', }, }, network: { diff --git a/packages/neuron-ui/src/locales/zh.ts b/packages/neuron-ui/src/locales/zh.ts index a2e4984788..bb52fcaaa2 100644 --- a/packages/neuron-ui/src/locales/zh.ts +++ b/packages/neuron-ui/src/locales/zh.ts @@ -68,6 +68,7 @@ export default { 'edit-wallet': '编辑钱包', }, 'delete-wallet-title': '请输入{{name}}的密码', + password: '密码', 'wallet-detail': { balance: '余额', }, diff --git a/packages/neuron-ui/src/widgets/ListGroupWithMaxHeight/index.tsx b/packages/neuron-ui/src/widgets/ListGroupWithMaxHeight/index.tsx new file mode 100644 index 0000000000..0f0143df39 --- /dev/null +++ b/packages/neuron-ui/src/widgets/ListGroupWithMaxHeight/index.tsx @@ -0,0 +1,20 @@ +import styled from 'styled-components' +import { ListGroup } from 'react-bootstrap' + +const ListGroupWithMaxHeight = styled(ListGroup)` + max-height: calc(100vh - 300px); + overflow-y: scroll; + margin-bottom: 50px; + scroll-behavior: smooth; + scroll-snap-type: y mandatory; + & > div { + display: flex; + justify-content: space-between; + min-height: 48px; + scroll-snap-align: start; + } +` + +ListGroupWithMaxHeight.displayName = 'ListGroupWithMaxHeight' + +export default ListGroupWithMaxHeight