diff --git a/.ckb-version b/.ckb-version
index 5affb131c0..420000f959 100644
--- a/.ckb-version
+++ b/.ckb-version
@@ -1 +1 @@
-v0.31.1
+v0.32.0
diff --git a/.gitignore b/.gitignore
index 6707801586..4cf618898a 100755
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,6 @@ node_modules
# testing
/coverage
*.snap
-/packages/neuron-wallet/tests-e2e/errors
# production
build
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7115913602..516c0f37ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,29 @@
+# 0.31.0-rc1 (2020-05-29)
+
+### Bundled CKB node
+
+[CKB v0.32.0](https://github.com/nervosnetwork/ckb/releases/tag/v0.32.0) was released on May 22nd, 2020. This version of CKB node is now bundled and preconfigured in Neuron.
+
+### New features
+
+We added several new features with this version:
+
+* New style of logo.
+* Enable exporting transaction history.
+* Make the `Settings` window to be independent with new style.
+* Add Language Switching function in `Settings` - `General` page.
+* Export more bundled CKB logs for debug info.
+* Include the bundled CKB version on the `About Neuron` window.
+* Replace the `Expected speed` drop-down box with `Quick Pick Price` in `Advanced fee settings`.
+
+### User Experience
+
+We also make some improvements for better user expeierence:
+
+* Optimize the `Copy` component, also remove unnecessary normal context menu (right-click menu).
+* Display password error in password dialog.
+
+
# 0.30.0 (2020-05-15)
### Bundled CKB node
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index b0068392d9..9f6f955304 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -4,7 +4,6 @@ trigger:
include:
- master
- develop
- - e2e-tests
- rc/*
tags:
include:
@@ -90,27 +89,6 @@ stages:
yarn test
name: Test
-- stage: e2e_tests
- displayName: Integration Tests
- dependsOn: []
- condition: false # eq(variables['build.sourceBranch'], 'refs/heads/master')
- jobs:
- - job: Integration
- displayName: Integration Tests
- pool:
- vmImage: 'macos-10.14'
- steps:
- - task: NodeTool@0
- inputs:
- versionSpec: 12.x
- displayName: 'Install Node.js'
- - script: |
- yarn global add lerna
- yarn bootstrap
- name: Bootstrap
- - script: yarn test:e2e
- name: Test
-
- stage: release
displayName: Release Binaries
condition: eq(variables['build.sourceBranch'], 'refs/heads/master')
diff --git a/lerna.json b/lerna.json
index a5da955a23..8e80e9f6bf 100644
--- a/lerna.json
+++ b/lerna.json
@@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
- "version": "0.30.0",
+ "version": "0.31.0-rc1",
"npmClient": "yarn",
"useWorkspaces": true
}
diff --git a/package.json b/package.json
index a68f4d29ad..126a4ab3b2 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "neuron",
"productName": "Neuron",
"description": "CKB Neuron Wallet",
- "version": "0.30.0",
+ "version": "0.31.0-rc1",
"private": true,
"author": {
"name": "Nervos Core Dev",
@@ -31,7 +31,6 @@
"build": "lerna run --stream build",
"release": "yarn build && ./scripts/copy-ui-files.sh && ./scripts/release.sh",
"test": "lerna run --parallel test",
- "test:e2e": "yarn build && ./scripts/copy-ui-files.sh && lerna run --parallel test:e2e",
"lint": "lerna run --stream lint",
"postinstall": "lerna run rebuild:nativemodules",
"db:chain": "node ./node_modules/.bin/typeorm"
diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json
index 7a1cd4c3ad..f727b2df4e 100644
--- a/packages/neuron-ui/package.json
+++ b/packages/neuron-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "neuron-ui",
- "version": "0.30.0",
+ "version": "0.31.0-rc1",
"private": true,
"author": {
"name": "Nervos Core Dev",
@@ -58,7 +58,6 @@
"react-dom": "16.12.0",
"react-i18next": "11.2.5",
"react-router-dom": "5.1.2",
- "react-scripts": "3.3.1",
"styled-components": "5.0.0-beta.0"
},
"devDependencies": {
@@ -93,6 +92,7 @@
"node-sass": "4.13.0",
"prettier": "1.19.1",
"react-app-rewired": "2.1.5",
+ "react-scripts": "3.4.1",
"react-test-renderer": "16.12.0",
"rimraf": "3.0.0",
"storybook-react-router": "1.0.8"
diff --git a/packages/neuron-ui/public/favicon.ico b/packages/neuron-ui/public/favicon.ico
index 9bbd9ca99c..9b60cd0b22 100644
Binary files a/packages/neuron-ui/public/favicon.ico and b/packages/neuron-ui/public/favicon.ico differ
diff --git a/packages/neuron-ui/public/icon.png b/packages/neuron-ui/public/icon.png
index e132bc4987..389fe2538b 100644
Binary files a/packages/neuron-ui/public/icon.png and b/packages/neuron-ui/public/icon.png differ
diff --git a/packages/neuron-ui/src/components/Addresses/addresses.module.scss b/packages/neuron-ui/src/components/Addresses/addresses.module.scss
index 01cc5354e4..a19b6cb458 100644
--- a/packages/neuron-ui/src/components/Addresses/addresses.module.scss
+++ b/packages/neuron-ui/src/components/Addresses/addresses.module.scss
@@ -14,14 +14,14 @@ $change-color: #6666cc;
border-collapse: collapse;
tbody {
- input+span {
+ input + span {
display: none !important;
}
tr:hover {
background-color: #f5f5f5;
- input+span {
+ input + span {
display: flex !important;
}
}
@@ -36,12 +36,10 @@ $change-color: #6666cc;
border-bottom: 1px solid #b3b3b3;
}
-
th {
- @include SemiBoldText;
+ @include semi-bold-text;
font-size: 1rem;
font-weight: 600;
- letter-spacing: 0.6px;
color: #000;
padding: 18px 0;
@@ -52,7 +50,6 @@ $change-color: #6666cc;
td {
font-size: 0.875rem;
- letter-spacing: 0.5px;
color: #000;
padding: 10px 0;
@@ -69,7 +66,6 @@ $change-color: #6666cc;
}
}
-
.type {
width: 100px;
word-wrap: none;
@@ -84,6 +80,7 @@ $change-color: #6666cc;
}
.address {
+ line-height: 1.625rem;
&:hover {
div::after {
display: block;
@@ -99,7 +96,7 @@ $change-color: #6666cc;
.addressOverflow {
word-break: break-all;
text-align: right;
- height: 1rem;
+ height: 1.625rem;
overflow: hidden;
text-align: right;
}
@@ -109,22 +106,21 @@ $change-color: #6666cc;
}
@media screen and (max-width: 1365px) {
-
.ellipsis {
display: inline;
}
}
@media screen and (max-width: 1680px) {
- width: 30vw;
+ width: 20vw;
&::after {
position: absolute;
top: 150%;
left: 50%;
+ z-index: 1;
content: attr(data-address);
font-size: 0.875rem;
- letter-spacing: 0.5px;
color: #000;
box-shadow: 1px 2px 6px 0 rgba(97, 97, 97, 0.5);
background: #fff;
@@ -134,14 +130,9 @@ $change-color: #6666cc;
}
}
- @media screen and (max-width: 1350px) {
- width: 20vw;
- }
-
@media screen and (max-width: 1000px) {
width: 15vw;
}
-
}
}
@@ -167,13 +158,13 @@ $change-color: #6666cc;
}
.descriptionField {
- @include descriptionField;
+ @include description-field;
input {
font-size: 0.875rem;
}
- &>div {
+ & > div {
border: none;
}
@@ -185,11 +176,16 @@ $change-color: #6666cc;
}
.balance {
+ div {
+ display: flex;
+ align-items: center;
+ height: 1.625rem;
+ }
span {
display: inline-block;
min-width: 200px;
- @media screen and (max-width:1160px) {
+ @media screen and (max-width: 1160px) {
min-width: auto;
width: 8vw;
}
@@ -199,5 +195,4 @@ $change-color: #6666cc;
.txCount {
min-width: 100px;
}
-
}
diff --git a/packages/neuron-ui/src/components/Addresses/index.tsx b/packages/neuron-ui/src/components/Addresses/index.tsx
index 1e86dce40d..3df920d283 100644
--- a/packages/neuron-ui/src/components/Addresses/index.tsx
+++ b/packages/neuron-ui/src/components/Addresses/index.tsx
@@ -3,16 +3,21 @@ import { useHistory } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { Edit } from 'grommet-icons'
import TextField from 'widgets/TextField'
+import CopyZone from 'widgets/CopyZone'
-import { useState as useGlobalState, useDispatch } from 'states/stateProvider'
+import { useState as useGlobalState, useDispatch } from 'states'
import { openExternal, openContextMenu } from 'services/remote'
-import { useLocalDescription } from 'utils/hooks'
-import { localNumberFormatter, shannonToCKBFormatter } from 'utils/formatters'
-import { Routes } from 'utils/const'
-import { backToTop } from 'utils/animations'
-import getExplorerUrl from 'utils/getExplorerUrl'
-import isMainnetUtil from 'utils/isMainnet'
+import {
+ useLocalDescription,
+ backToTop,
+ RoutePath,
+ localNumberFormatter,
+ shannonToCKBFormatter,
+ getExplorerUrl,
+ isMainnet as isMainnetUtil,
+} from 'utils'
+
import styles from './addresses.module.scss'
const Addresses = () => {
@@ -54,7 +59,7 @@ const Addresses = () => {
{
label: t('addresses.request-payment'),
click: () => {
- history.push(`${Routes.Receive}/${item.address}`)
+ history.push(`${RoutePath.Receive}/${item.address}`)
},
},
{
@@ -85,16 +90,20 @@ const Addresses = () => {
{addresses.map(addr => {
const isSelected = localDescription.key === addr.address
const typeLabel = addr.type === 0 ? t('addresses.receiving-address') : t('addresses.change-address')
+ const balance = `${shannonToCKBFormatter(addr.balance)} CKB`
+
return (
{typeLabel}
|
-
+ |
- {addr.address.slice(0, -6)}
- ...
- {addr.address.slice(-6)}
+
+ {addr.address.slice(0, -6)}
+ ...
+ {addr.address.slice(-6)}
+
|
@@ -127,8 +136,10 @@ const Addresses = () => {
}
/>
|
-
- {`${shannonToCKBFormatter(addr.balance)} CKB`}
+ |
+
+ {balance}
+
|
{localNumberFormatter(addr.txCount)}
diff --git a/packages/neuron-ui/src/components/BalanceSyncingIcon/balanceSyncIcon.module.scss b/packages/neuron-ui/src/components/BalanceSyncingIcon/balanceSyncIcon.module.scss
index 5d4fab27f7..a1563ce800 100644
--- a/packages/neuron-ui/src/components/BalanceSyncingIcon/balanceSyncIcon.module.scss
+++ b/packages/neuron-ui/src/components/BalanceSyncingIcon/balanceSyncIcon.module.scss
@@ -5,7 +5,6 @@ $arrow: 10px;
position: relative;
font-size: 0.75rem;
color: var(--nervos-green);
- user-select: none;
border-radius: 2px;
z-index: 1;
@@ -13,9 +12,10 @@ $arrow: 10px;
width: 1rem;
height: 0.75rem;
pointer-events: none;
+ position: relative;
+ top: 1px;
}
-
&::after {
display: none;
content: attr(data-content);
@@ -47,7 +47,6 @@ $arrow: 10px;
}
&:hover {
-
&::after,
&::before {
display: block;
diff --git a/packages/neuron-ui/src/components/BalanceSyncingIcon/index.tsx b/packages/neuron-ui/src/components/BalanceSyncingIcon/index.tsx
index 45b64a5aa6..be761394e2 100644
--- a/packages/neuron-ui/src/components/BalanceSyncingIcon/index.tsx
+++ b/packages/neuron-ui/src/components/BalanceSyncingIcon/index.tsx
@@ -1,6 +1,6 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
-import { ConnectionStatus, SyncStatus } from 'utils/const'
+import { ConnectionStatus, SyncStatus } from 'utils'
import { ReactComponent as BalanceSyncing } from 'widgets/Icons/BalanceSyncing.svg'
import { ReactComponent as BalanceSyncFailed } from 'widgets/Icons/BalanceSyncFailed.svg'
import styles from './balanceSyncIcon.module.scss'
diff --git a/packages/neuron-ui/src/components/CompensationPeriodTooltip/index.tsx b/packages/neuron-ui/src/components/CompensationPeriodTooltip/index.tsx
index e98f561627..1ca7463ea8 100644
--- a/packages/neuron-ui/src/components/CompensationPeriodTooltip/index.tsx
+++ b/packages/neuron-ui/src/components/CompensationPeriodTooltip/index.tsx
@@ -1,11 +1,10 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
-import getCompensationPeriod from 'utils/getCompensationPeriod'
-import getCompensatedTime from 'utils/getCompensatedTime'
-import { WITHDRAW_EPOCHS, CompensationPeriod, IMMATURE_EPOCHS } from 'utils/const'
-import { uniformTimeFormatter } from 'utils/formatters'
+import { getCompensatedTime, getCompensationPeriod, CONSTANTS, CompensationPeriod, uniformTimeFormatter } from 'utils'
import styles from './compensationPeriodTooltip.module.scss'
+const { WITHDRAW_EPOCHS, IMMATURE_EPOCHS } = CONSTANTS
+
const HOUR = 3_600_000
const HOURS_PER_EPOCH = 4 * HOUR
const SECS_PER_DAY = 24 * HOUR
diff --git a/packages/neuron-ui/src/components/DepositDialog/depositDialog.module.scss b/packages/neuron-ui/src/components/DepositDialog/depositDialog.module.scss
index 38399b1454..1e4efded0d 100644
--- a/packages/neuron-ui/src/components/DepositDialog/depositDialog.module.scss
+++ b/packages/neuron-ui/src/components/DepositDialog/depositDialog.module.scss
@@ -1,7 +1,7 @@
-@import "../../styles/mixin.scss";
+@import '../../styles/mixin.scss';
.dialog {
- @include dialogContainer;
+ @include dialog-container;
padding: 30px 50px;
&::backdrop {
@@ -21,7 +21,7 @@
line-height: 1.4;
margin-bottom: 25px;
- &>span:first-of-type {
+ & > span:first-of-type {
font-weight: 900;
&:after {
@@ -32,7 +32,6 @@
}
}
-
.errorMessage {
display: flex;
align-items: center;
@@ -70,7 +69,7 @@
}
.footer {
- @include dialogFooter;
+ @include dialog-footer;
button:last-of-type {
margin-left: 9px;
diff --git a/packages/neuron-ui/src/components/DepositDialog/index.tsx b/packages/neuron-ui/src/components/DepositDialog/index.tsx
index 08f94e0869..5fa35265b2 100644
--- a/packages/neuron-ui/src/components/DepositDialog/index.tsx
+++ b/packages/neuron-ui/src/components/DepositDialog/index.tsx
@@ -6,11 +6,14 @@ import Spinner from 'widgets/Spinner'
import Button from 'widgets/Button'
import { ReactComponent as Attention } from 'widgets/Icons/Attention.svg'
import { openExternal } from 'services/remote'
-import { SHANNON_CKB_RATIO, NERVOS_DAO_RFC_URL } from 'utils/const'
-import { localNumberFormatter, shannonToCKBFormatter } from 'utils/formatters'
-import { useDialog } from 'utils/hooks'
+import { CONSTANTS, localNumberFormatter, shannonToCKBFormatter, useDialog } from 'utils'
import styles from './depositDialog.module.scss'
+const { SHANNON_CKB_RATIO } = CONSTANTS
+
+const NERVOS_DAO_RFC_URL =
+ 'https://www.github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md'
+
interface DepositDialogProps {
show: boolean
value: any
diff --git a/packages/neuron-ui/src/components/GeneralSetting/index.tsx b/packages/neuron-ui/src/components/GeneralSetting/index.tsx
index 6580ee9354..2ed2c78ad7 100644
--- a/packages/neuron-ui/src/components/GeneralSetting/index.tsx
+++ b/packages/neuron-ui/src/components/GeneralSetting/index.tsx
@@ -1,22 +1,25 @@
-import React, { useCallback, useState } from 'react'
+import React, { useCallback, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { Stack, Text, ProgressIndicator } from 'office-ui-fabric-react'
+import { ProgressIndicator } from 'office-ui-fabric-react'
import Button from 'widgets/Button'
import Spinner from 'widgets/Spinner'
-import { StateDispatch } from 'states/stateProvider/reducer'
-import { addPopup } from 'states/stateProvider/actionCreators'
-import { checkForUpdates, downloadUpdate, installUpdate, clearCellCache } from 'services/remote'
+import Dropdown from 'widgets/Dropdown'
+import { ReactComponent as Attention } from 'widgets/Icons/Attention.svg'
+import { StateDispatch, addPopup } from 'states'
+import { checkForUpdates, downloadUpdate, installUpdate, clearCellCache, setLocale, getVersion } from 'services/remote'
+import { cacheClearDate } from 'services/localCache'
+import { CONSTANTS } from 'utils'
+
import styles from './style.module.scss'
-const UpdateDownloadStatus = ({
- progress = 0,
- newVersion = '',
- releaseNotes = '',
-}: {
+const { LOCALES } = CONSTANTS
+interface UpdateDowloadStatusProps {
progress: number
newVersion: string
releaseNotes: string
-}) => {
+}
+
+const UpdateDownloadStatus = ({ progress = 0, newVersion = '', releaseNotes = '' }: UpdateDowloadStatusProps) => {
const [t] = useTranslation()
const available = newVersion !== '' && progress < 0
const downloaded = progress >= 1
@@ -33,24 +36,15 @@ const UpdateDownloadStatus = ({
/* eslint-disable react/no-danger */
return (
-
-
- {t('updates.updates-found-do-you-want-to-update', { version: newVersion })}
-
- {t('updates.release-notes')}
+
+ {t('updates.updates-found-do-you-want-to-update', { version: newVersion })}
+
+
+
-
-
-
-
+
)
}
@@ -60,35 +54,33 @@ const UpdateDownloadStatus = ({
}
return (
-
-
- {t('updates.updates-downloaded-about-to-quit-and-install')}
-
-
+
+ {t('updates.updates-downloaded-about-to-quit-and-install')}
+
-
-
+
+
)
}
- return (
-
- )
+ return
}
-const GeneralSetting = ({ updater, dispatch }: { updater: State.AppUpdater; dispatch: StateDispatch }) => {
- const [t] = useTranslation()
+interface GeneralSettingProps {
+ updater: State.AppUpdater
+ dispatch: StateDispatch
+}
+
+const GeneralSetting = ({ updater, dispatch }: GeneralSettingProps) => {
+ const [t, i18n] = useTranslation()
const [clearingCache, setClearingCache] = useState(false)
+ const [lng, setLng] = useState(i18n.language)
+ const [clearedDate, setClearedDate] = useState(cacheClearDate.load())
const checkUpdates = useCallback(() => {
checkForUpdates()
@@ -99,22 +91,31 @@ const GeneralSetting = ({ updater, dispatch }: { updater: State.AppUpdater; disp
setTimeout(() => {
clearCellCache().finally(() => {
addPopup('clear-cache-successfully')(dispatch)
+ const date = new Date().toISOString().slice(0, 10)
+ cacheClearDate.save(date)
+ setClearedDate(date)
setClearingCache(false)
})
}, 100)
- }, [dispatch])
+ }, [dispatch, setClearedDate])
+
+ const onApplyLanguage = useCallback(() => {
+ setLocale(lng as typeof LOCALES[number])
+ }, [lng])
+
+ const version = useMemo(() => {
+ return getVersion()
+ }, [])
+
+ const showNewVersion = updater.version !== '' || updater.downloadProgress >= 0
return (
-
-
-
- {updater.version !== '' || updater.downloadProgress >= 0 ? (
-
- ) : (
+
+ {t('settings.general.version')}
+ {showNewVersion ? null : (
+ <>
+ {version}
+
+ >
+ )}
+
+ {showNewVersion ? (
+
+ ) : null}
+
-
-
+
+ {clearedDate ? (
+ {t('settings.general.cache-cleared-on', { date: clearedDate })}
+ ) : null}
+
+
{t('settings.general.clear-cache-description')}
-
-
-
-
-
-
+
+
+
+
+
+ {t('settings.general.language')}
+
+ ({ key: locale, text: t(`settings.locale.${locale}`) }))}
+ selectedKey={lng}
+ onChange={(_, item) => {
+ if (item) {
+ setLng(item.key as typeof LOCALES[number])
+ }
+ }}
+ />
+
+
+
+
+
)
}
diff --git a/packages/neuron-ui/src/components/GeneralSetting/style.module.scss b/packages/neuron-ui/src/components/GeneralSetting/style.module.scss
index 328cb7b86d..9008153480 100644
--- a/packages/neuron-ui/src/components/GeneralSetting/style.module.scss
+++ b/packages/neuron-ui/src/components/GeneralSetting/style.module.scss
@@ -1,27 +1,124 @@
+@import '../../styles/mixin.scss';
+
+$action-button-width: 11.25rem;
.container {
+ font-size: 0.875rem;
+ margin-top: 1.25rem;
button {
- width: 9.375rem;
+ min-width: auto;
+ width: $action-button-width;
+ box-sizing: border-box;
+ height: 1.625rem;
+ padding: 0;
+ }
+
+ display: grid;
+ grid-template:
+ 'version-label version-value version-action' auto
+ 'language-label language-select language-action' auto
+ 'clear-cache-detail clear-cache-detail clear-cache-action' auto/
+ 120px 1fr $action-button-width;
+ grid-gap: 30px 10px;
+}
+.label {
+ @include regular-text;
+ font-weight: 600;
+ align-self: center;
+ &:after {
+ content: ':';
}
}
-.releaseNotesStyle {
- overflow: scroll;
- height: 200px;
- margin-bottom: 20px;
- padding: 10px 15px 15px 15px;
- border: solid 1px #ccc;
+.version {
+ &.label {
+ grid-area: version-label;
+ }
+
+ &.value {
+ align-self: center;
+ grid-area: version-value;
+ }
+
+ &.action {
+ grid-area: version-action;
+ }
+}
- ul {
- list-style-type: disc;
- padding-left: 30px;
+.newVersion {
+ grid-area: 1/2/2/4;
+}
- li {
- margin: 5px 0;
+.language {
+ &.label {
+ grid-area: language-label;
+ }
+ &.select {
+ grid-area: language-select;
+ max-width: 300px;
+ & > div {
+ margin: 0;
}
}
- a {
- text-decoration: none;
- pointer-events: none;
+ &.action {
+ grid-area: language-action;
+ }
+}
+.clearCache {
+ &.detail {
+ grid-area: clear-cache-detail;
+ .date {
+ display: flex;
+ align-items: center;
+ font-size: 0.875rem;
+ height: 1.125rem;
+ margin-bottom: 5px;
+ }
+ .desc {
+ display: flex;
+ font-size: 0.6875rem;
+ color: #666;
+ }
+ svg {
+ height: 0.6875rem;
+ width: 0.6875rem;
+ filter: grayscale(1) opacity(0.6);
+ margin: 2px 5px 0 0;
+ }
+ }
+ &.action {
+ grid-area: clear-cache-action;
+ }
+}
+
+.install {
+ display: grid;
+ grid-template:
+ 'note action' auto
+ 'release-note release-note'/
+ 1fr $action-button-width;
+
+ .releaseNotesStyle {
+ grid-area: release-note;
+ overflow: scroll;
+ min-height: 200px;
+ height: calc(100vh - 400px);
+ margin: 6px auto 20px;
+ padding: 10px 15px 15px 15px;
+ border: solid 1px #ccc;
+
+ ul {
+ list-style-type: disc;
+ padding-left: 30px;
+
+ li {
+ margin: 5px 0;
+ }
+ }
+
+ a {
+ text-decoration: none;
+ pointer-events: none;
+ }
}
}
diff --git a/packages/neuron-ui/src/components/History/history.module.scss b/packages/neuron-ui/src/components/History/history.module.scss
index 448f1d986a..27e649dedb 100644
--- a/packages/neuron-ui/src/components/History/history.module.scss
+++ b/packages/neuron-ui/src/components/History/history.module.scss
@@ -1,8 +1,53 @@
@import '../../styles/mixin.scss';
.history {
- // need more discussion
- // min-height: calc(100vh - 100px);
+ .tools {
+ display: grid;
+ grid-template:
+ 'search-input search-button export-button' auto/
+ 1fr auto auto;
+ margin-bottom: 15px;
+ .searchBox {
+ grid-area: search-input;
+ button:hover {
+ background: rgb(220, 220, 220);
+ }
+ }
+
+ .searchBtn,
+ .exportBtn {
+ height: 1.625rem;
+ min-width: unset;
+ padding: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 2px;
+ }
+
+ .searchBtn {
+ grid-area: search-button;
+ padding: 0 15px;
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ background-color: rgb(204, 204, 204);
+ color: rgb(97, 97, 97);
+ border: none;
+ }
+
+ .exportBtn {
+ grid-area: export-button;
+ width: 1.625rem;
+ margin-left: 10px;
+ svg {
+ width: 16px;
+ height: 16px;
+ path {
+ fill: #fff;
+ }
+ }
+ }
+ }
.listContainer {
background-color: #fff;
@@ -14,11 +59,11 @@
display: flex;
flex: 1;
flex-direction: column;
- justify-content: flex-end
+ justify-content: flex-end;
}
}
.noTxs {
- @include MediumText;
+ @include medium-text;
padding: 20px 13px;
}
diff --git a/packages/neuron-ui/src/components/History/hooks.ts b/packages/neuron-ui/src/components/History/hooks.ts
index 2c0012cb03..3e4e9c58f1 100644
--- a/packages/neuron-ui/src/components/History/hooks.ts
+++ b/packages/neuron-ui/src/components/History/hooks.ts
@@ -1,7 +1,6 @@
import { useState, useEffect } from 'react'
import { updateTransactionList } from 'states/stateProvider/actionCreators/transactions'
-import { queryParsers } from 'utils/parsers'
-import { backToTop } from 'utils/animations'
+import { queryParsers, backToTop } from 'utils'
export const useSearch = (search: string = '', walletID: string = '', dispatch: React.Dispatch) => {
const [keywords, setKeywords] = useState('')
diff --git a/packages/neuron-ui/src/components/History/index.tsx b/packages/neuron-ui/src/components/History/index.tsx
index 86578915da..a4d3f856a6 100644
--- a/packages/neuron-ui/src/components/History/index.tsx
+++ b/packages/neuron-ui/src/components/History/index.tsx
@@ -1,14 +1,16 @@
-import React, { useCallback, useMemo } from 'react'
+import React, { useState, useCallback, useMemo } from 'react'
import { useHistory, useLocation } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { Stack, SearchBox } from 'office-ui-fabric-react'
import { Pagination } from '@uifabric/experiments'
import TransactionList from 'components/TransactionList'
-import { useState as useGlobalState, useDispatch } from 'states/stateProvider'
+import { useState as useGlobalState, useDispatch } from 'states'
+import Button from 'widgets/Button'
+import { exportTransactions } from 'services/remote'
+import { ReactComponent as Export } from 'widgets/Icons/ExportHistory.svg'
-import { Routes } from 'utils/const'
-import isMainnetUtil from 'utils/isMainnet'
+import { RoutePath, isMainnet as isMainnetUtil } from 'utils'
import { useSearch } from './hooks'
import styles from './history.module.scss'
@@ -31,10 +33,21 @@ const History = () => {
const [t] = useTranslation()
const history = useHistory()
const { search } = useLocation()
+ const [isExporting, setIsExporting] = useState(false)
const isMainnet = isMainnetUtil(networks, networkID)
const { keywords, onKeywordsChange } = useSearch(search, id, dispatch)
- const onSearch = useCallback(() => history.push(`${Routes.History}?keywords=${keywords}`), [history, keywords])
+ const onSearch = useCallback(() => history.push(`${RoutePath.History}?keywords=${keywords}`), [history, keywords])
+ const onExport = useCallback(() => {
+ setIsExporting(true)
+ const timer = setTimeout(() => {
+ setIsExporting(false)
+ }, 3000)
+ exportTransactions({ walletID: id }).finally(() => {
+ clearTimeout(timer)
+ setIsExporting(false)
+ })
+ }, [id, setIsExporting])
const tipBlockNumber = useMemo(() => {
return Math.max(+syncedBlockNumber, +chainBlockNumber).toString()
@@ -43,21 +56,36 @@ const History = () => {
const List = useMemo(() => {
return (
-
+
+
+
+
+
{totalCount ? (
{
lastPageIconProps={{ iconName: 'LastPage' }}
format="buttons"
onPageChange={(idx: number) => {
- history.push(`${Routes.History}?pageNo=${idx + 1}&keywords=${keywords}`)
+ history.push(`${RoutePath.History}?pageNo=${idx + 1}&keywords=${keywords}`)
}}
/>
) : null}
@@ -112,6 +140,8 @@ const History = () => {
history,
isMainnet,
t,
+ isExporting,
+ onExport,
])
return List
diff --git a/packages/neuron-ui/src/components/ImportKeystore/importKeystore.module.scss b/packages/neuron-ui/src/components/ImportKeystore/importKeystore.module.scss
index c1b6762a90..7180840cf1 100644
--- a/packages/neuron-ui/src/components/ImportKeystore/importKeystore.module.scss
+++ b/packages/neuron-ui/src/components/ImportKeystore/importKeystore.module.scss
@@ -13,5 +13,5 @@
}
.actions {
- @include formFooter;
+ @include form-footer;
}
diff --git a/packages/neuron-ui/src/components/ImportKeystore/index.tsx b/packages/neuron-ui/src/components/ImportKeystore/index.tsx
index af8e030564..1fc341cbe5 100644
--- a/packages/neuron-ui/src/components/ImportKeystore/index.tsx
+++ b/packages/neuron-ui/src/components/ImportKeystore/index.tsx
@@ -3,21 +3,22 @@ import { useHistory } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import i18n from 'i18next'
import { importKeystore, showOpenDialogModal, showErrorMessage } from 'services/remote'
-import { useState as useGlobalState } from 'states/stateProvider'
-import { useGoBack } from 'utils/hooks'
-import generateWalletName from 'utils/generateWalletName'
+import { useState as useGlobalState } from 'states'
import TextField from 'widgets/TextField'
import Button from 'widgets/Button'
import Spinner from 'widgets/Spinner'
-import { Routes, ErrorCode, MAX_WALLET_NAME_LENGTH, MAX_PASSWORD_LENGTH } from 'utils/const'
+import { generateWalletName, RoutePath, ErrorCode, CONSTANTS, useGoBack, isSuccessResponse } from 'utils'
+
import styles from './importKeystore.module.scss'
+const { MAX_WALLET_NAME_LENGTH, MAX_PASSWORD_LENGTH } = CONSTANTS
+
export const importWalletWithKeystore = (params: Controller.ImportKeystoreParams) => (
history: ReturnType
) => {
return importKeystore(params).then(res => {
- if (res.status === 1) {
- history.push(Routes.Overview)
+ if (isSuccessResponse(res)) {
+ history.push(window.neuron.role === 'main' ? RoutePath.Overview : RoutePath.SettingsWallets)
} else if (res.status > 0) {
showErrorMessage(i18n.t(`messages.error`), i18n.t(`messages.codes.${res.status}`))
} else if (res.message) {
diff --git a/packages/neuron-ui/src/components/LaunchScreen/index.tsx b/packages/neuron-ui/src/components/LaunchScreen/index.tsx
index 9b29df881c..106033107c 100644
--- a/packages/neuron-ui/src/components/LaunchScreen/index.tsx
+++ b/packages/neuron-ui/src/components/LaunchScreen/index.tsx
@@ -2,11 +2,10 @@ import React, { useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { Panel, PanelType, SpinnerSize } from 'office-ui-fabric-react'
-import { useState as useGlobalState } from 'states/stateProvider'
+import { useState as useGlobalState } from 'states'
+import { RoutePath } from 'utils'
import Spinner from 'widgets/Spinner'
-import { Routes } from 'utils/const'
-
export const LaunchScreen = () => {
const {
wallet: { id = '' },
@@ -16,7 +15,7 @@ export const LaunchScreen = () => {
useEffect(() => {
if (id) {
- history.push(Routes.Overview)
+ history.push(RoutePath.Overview)
}
}, [id, history])
diff --git a/packages/neuron-ui/src/components/NervosDAO/hooks.ts b/packages/neuron-ui/src/components/NervosDAO/hooks.ts
index ffdbe55ab1..497f1bebc7 100644
--- a/packages/neuron-ui/src/components/NervosDAO/hooks.ts
+++ b/packages/neuron-ui/src/components/NervosDAO/hooks.ts
@@ -3,20 +3,16 @@ import { TFunction } from 'i18next'
import { AppActions, StateAction } from 'states/stateProvider/reducer'
import { updateNervosDaoData, clearNervosDaoData } from 'states/stateProvider/actionCreators'
-import { verifyAmount } from 'utils/validators'
-import calculateAPC from 'utils/calculateAPC'
-
-import { CKBToShannonFormatter, shannonToCKBFormatter } from 'utils/formatters'
import {
- MIN_AMOUNT,
- MILLISECONDS_IN_YEAR,
- MIN_DEPOSIT_AMOUNT,
- MEDIUM_FEE_RATE,
- SHANNON_CKB_RATIO,
- MAX_DECIMAL_DIGITS,
+ calculateAPC,
ErrorCode,
CapacityUnit,
-} from 'utils/const'
+ CONSTANTS,
+ CKBToShannonFormatter,
+ shannonToCKBFormatter,
+ isSuccessResponse,
+ verifyAmount,
+} from 'utils'
import {
generateDaoWithdrawTx,
@@ -26,6 +22,14 @@ import {
} from 'services/remote'
import { ckbCore, getHeaderByNumber, calculateDaoMaximumWithdraw } from 'services/chain'
+const {
+ MIN_AMOUNT,
+ MILLISECONDS_IN_YEAR,
+ MIN_DEPOSIT_AMOUNT,
+ MEDIUM_FEE_RATE,
+ SHANNON_CKB_RATIO,
+ MAX_DECIMAL_DIGITS,
+} = CONSTANTS
let timer: NodeJS.Timeout
const getRecordKey = ({ depositOutPoint, outPoint }: State.NervosDAORecord) => {
@@ -49,7 +53,7 @@ export const useUpdateMaxDeposit = ({
feeRate: `${MEDIUM_FEE_RATE}`,
})
.then(res => {
- if (res.status === 1) {
+ if (isSuccessResponse(res)) {
const fee = BigInt(res.result.fee)
const maxValue = fee < BigInt(wallet.balance) ? BigInt(wallet.balance) - fee : BigInt(0)
setMaxDepositAmount(maxValue)
@@ -160,7 +164,7 @@ export const useUpdateDepositValue = ({
capacity,
walletID,
}).then(res => {
- if (res.status === 1) {
+ if (isSuccessResponse(res)) {
dispatch({
type: AppActions.UpdateGeneratedTx,
payload: res.result,
@@ -295,7 +299,7 @@ export const useOnWithdrawDialogSubmit = ({
feeRate: `${MEDIUM_FEE_RATE}`,
})
.then(res => {
- if (res.status === 1) {
+ if (isSuccessResponse(res)) {
dispatch({
type: AppActions.UpdateGeneratedTx,
payload: res.result,
@@ -356,7 +360,7 @@ export const useOnActionClick = ({
feeRate: `${MEDIUM_FEE_RATE}`,
})
.then(res => {
- if (res.status === 1) {
+ if (isSuccessResponse(res)) {
dispatch({
type: AppActions.UpdateGeneratedTx,
payload: res.result,
diff --git a/packages/neuron-ui/src/components/NervosDAO/index.tsx b/packages/neuron-ui/src/components/NervosDAO/index.tsx
index df48845d8c..c95ef48e5b 100644
--- a/packages/neuron-ui/src/components/NervosDAO/index.tsx
+++ b/packages/neuron-ui/src/components/NervosDAO/index.tsx
@@ -1,25 +1,32 @@
import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import appState from 'states/initStates/app'
-import { useState as useGlobalState, useDispatch } from 'states/stateProvider'
+import appState from 'states/init/app'
+import { useState as useGlobalState, useDispatch } from 'states'
-import calculateFee from 'utils/calculateFee'
-import { shannonToCKBFormatter } from 'utils/formatters'
-import { MIN_DEPOSIT_AMOUNT, ConnectionStatus, SyncStatus } from 'utils/const'
-import { backToTop } from 'utils/animations'
-import getSyncStatus from 'utils/getSyncStatus'
-import getCurrentUrl from 'utils/getCurrentUrl'
+import {
+ CONSTANTS,
+ backToTop,
+ calculateFee,
+ ConnectionStatus,
+ SyncStatus,
+ shannonToCKBFormatter,
+ getCurrentUrl,
+ getSyncStatus,
+} from 'utils'
import DepositDialog from 'components/DepositDialog'
import WithdrawDialog from 'components/WithdrawDialog'
import DAORecord from 'components/NervosDAORecord'
import BalanceSyncIcon from 'components/BalanceSyncingIcon'
import Button from 'widgets/Button'
+import CopyZone from 'widgets/CopyZone'
import hooks from './hooks'
import styles from './nervosDAO.module.scss'
+const { MIN_DEPOSIT_AMOUNT } = CONSTANTS
+
const NervosDAO = () => {
const [focusedRecord, setFocusedRecord] = useState('')
const [tabIdx, setTabIdx] = useState('0')
@@ -256,14 +263,35 @@ const NervosDAO = () => {
const onlineAndSynced = ConnectionStatus.Online === connectionStatus && SyncStatus.SyncCompleted === syncStatus
+ const freeBalance = shannonToCKBFormatter(`${free}`)
+ const lockedBalance = shannonToCKBFormatter(`${locked}`)
+
const info = [
{
key: 'free',
- value: `${shannonToCKBFormatter(`${free}`)} CKB`,
+ value: (
+
+ {`${freeBalance} CKB`}
+
+ ),
},
{
key: 'locked',
- value: onlineAndSynced ? `${shannonToCKBFormatter(`${locked}`)} CKB` : `-- CKB`,
+ value: onlineAndSynced ? (
+
+ {`${lockedBalance} CKB`}
+
+ ) : (
+ `-- CKB`
+ ),
},
{
key: 'apc',
@@ -279,13 +307,13 @@ const NervosDAO = () => {
return (
{label}
-
{value}
-
+
)
})}
diff --git a/packages/neuron-ui/src/components/NervosDAO/nervosDAO.module.scss b/packages/neuron-ui/src/components/NervosDAO/nervosDAO.module.scss
index 2ed93a63cf..3331250919 100644
--- a/packages/neuron-ui/src/components/NervosDAO/nervosDAO.module.scss
+++ b/packages/neuron-ui/src/components/NervosDAO/nervosDAO.module.scss
@@ -1,21 +1,20 @@
-@import "../../styles/mixin.scss";
+@import '../../styles/mixin.scss';
$infoHeight: 1.75rem;
.nervosDAOContainer {
display: grid;
grid-template:
- 'title title title'auto 'free network-alert deposit'auto 'locked . deposit'auto 'apc . .'auto 'records records records'auto/ minmax(350px, 500px) 35px 1fr;
+ 'title title title' auto
+ 'free network-alert deposit' auto
+ 'locked . deposit' auto
+ 'apc . .' auto
+ 'records records records' auto/
+ minmax(350px, 500px) 35px 1fr;
}
.title {
+ @include page-title;
grid-area: title;
- font-size: 1.375rem;
- font-weight: 900;
- line-height: 1.75rem;
- color: #000;
- padding-top: 5px;
- padding-bottom: 12px;
- margin: 0;
}
.free {
@@ -45,19 +44,24 @@ $infoHeight: 1.75rem;
height: $infoHeight;
font-size: 0.875rem;
- span:first-child {
+ & > span {
font-weight: 600;
padding-right: 15px;
+ white-space: nowrap;
&:after {
content: ':';
}
}
- span:last-child {
- text-overflow: ellipsis;
- overflow: hidden;
+ & > div {
+ width: 70%;
white-space: nowrap;
+ text-align: right;
+ }
+ .balance {
+ @include text-overflow-ellipsis;
+ padding: 0;
}
}
@@ -75,7 +79,7 @@ $infoHeight: 1.75rem;
border: none;
&[disabled] {
- @include disabledBtn;
+ @include disabled-button;
}
}
}
@@ -95,7 +99,7 @@ $infoHeight: 1.75rem;
border-bottom: 1px solid #ccc;
button {
- @include BoldText;
+ @include bold-text;
appearance: none;
flex: 1;
display: flex;
@@ -112,8 +116,6 @@ $infoHeight: 1.75rem;
color: var(--nervos-green);
opacity: 0.8;
}
-
-
}
.underline {
@@ -136,7 +138,7 @@ $infoHeight: 1.75rem;
}
}
- &>div {
+ & > div {
margin: 10px auto;
}
@@ -144,5 +146,4 @@ $infoHeight: 1.75rem;
font-size: 0.875rem;
font-weight: 600;
}
-
}
diff --git a/packages/neuron-ui/src/components/NervosDAORecord/daoRecordRow.module.scss b/packages/neuron-ui/src/components/NervosDAORecord/daoRecordRow.module.scss
index 2ad09b90d5..b66874ec8a 100644
--- a/packages/neuron-ui/src/components/NervosDAORecord/daoRecordRow.module.scss
+++ b/packages/neuron-ui/src/components/NervosDAORecord/daoRecordRow.module.scss
@@ -193,7 +193,7 @@
.deposited,
.withdrawn,
.unlocked {
- @include RegularText;
+ @include regular-text;
position: relative;
display: flex;
justify-content: space-between;
@@ -225,7 +225,7 @@
}
&:last-of-type {
- @include SemiBoldText;
+ @include semi-bold-text;
}
}
}
diff --git a/packages/neuron-ui/src/components/NervosDAORecord/hooks.ts b/packages/neuron-ui/src/components/NervosDAORecord/hooks.ts
index 9b46c6c337..d57ef27cf0 100644
--- a/packages/neuron-ui/src/components/NervosDAORecord/hooks.ts
+++ b/packages/neuron-ui/src/components/NervosDAORecord/hooks.ts
@@ -1,8 +1,9 @@
import { useEffect, useCallback } from 'react'
import { showTransactionDetails } from 'services/remote'
import { getHeaderByNumber } from 'services/chain'
-import { MILLISECONDS_IN_YEAR } from 'utils/const'
-import calculateAPC from 'utils/calculateAPC'
+import { calculateAPC, CONSTANTS } from 'utils'
+
+const { MILLISECONDS_IN_YEAR } = CONSTANTS
export const useUpdateWithdrawEpochs = ({
isWithdrawn,
diff --git a/packages/neuron-ui/src/components/NervosDAORecord/index.tsx b/packages/neuron-ui/src/components/NervosDAORecord/index.tsx
index dba903437f..6be26b774e 100644
--- a/packages/neuron-ui/src/components/NervosDAORecord/index.tsx
+++ b/packages/neuron-ui/src/components/NervosDAORecord/index.tsx
@@ -2,16 +2,24 @@ import React, { useState } from 'react'
import { useTranslation } from 'react-i18next'
import CompensationProgressBar from 'components/CompensationProgressBar'
import Button from 'widgets/Button'
-import { shannonToCKBFormatter, uniformTimeFormatter } from 'utils/formatters'
-import calculateClaimEpochValue from 'utils/calculateClaimEpochValue'
-import { epochParser } from 'utils/parsers'
-import getDAOCellStatus, { CellStatus } from 'utils/getDAOCellStatus'
-import { IMMATURE_EPOCHS, ConnectionStatus, HOURS_PER_EPOCH } from 'utils/const'
+import CopyZone from 'widgets/CopyZone'
+import {
+ calculateClaimEpochValue,
+ ConnectionStatus,
+ CONSTANTS,
+ shannonToCKBFormatter,
+ uniformTimeFormatter,
+ getDAOCellStatus,
+ CellStatus,
+ epochParser,
+} from 'utils'
import CompensationPeriodTooltip from 'components/CompensationPeriodTooltip'
import styles from './daoRecordRow.module.scss'
import hooks from './hooks'
+const { IMMATURE_EPOCHS, HOURS_PER_EPOCH } = CONSTANTS
+
const EPOCHS_PER_DAY = 6
const getDaysAndHours = (seconds: number) => {
@@ -232,6 +240,8 @@ export const DAORecord = ({
)
}
+ const amount = shannonToCKBFormatter(capacity)
+
return (
{badge}
@@ -250,9 +260,7 @@ export const DAORecord = ({
-
- {`${shannonToCKBFormatter(capacity)} CKB`}
-
+ {`${amount} CKB`}
{progressOrPeriod}
diff --git a/packages/neuron-ui/src/components/NetworkEditor/hooks.ts b/packages/neuron-ui/src/components/NetworkEditor/hooks.ts
index 4998d3b277..e5b99417e3 100644
--- a/packages/neuron-ui/src/components/NetworkEditor/hooks.ts
+++ b/packages/neuron-ui/src/components/NetworkEditor/hooks.ts
@@ -1,20 +1,30 @@
import { useCallback } from 'react'
import { useHistory } from 'react-router-dom'
-import { StateDispatch } from 'states/stateProvider/reducer'
-import { createNetwork, updateNetwork, addNotification } from 'states/stateProvider/actionCreators'
+import { StateDispatch, createNetwork, updateNetwork, addNotification } from 'states'
+import { ErrorCode, CONSTANTS } from 'utils'
-import { MAX_NETWORK_NAME_LENGTH, ErrorCode } from 'utils/const'
+const { MAX_NETWORK_NAME_LENGTH } = CONSTANTS
-export const useOnSubmit = (
- id: string = '',
- name: string = '',
- remote: string = '',
- networks: Readonly = [],
- history: ReturnType,
- dispatch: StateDispatch,
+export const useOnSubmit = ({
+ id = '',
+ name = '',
+ remote = '',
+ networks = [],
+ history,
+ dispatch,
+ disabled,
+ setIsUpdating,
+}: {
+ id: string
+ name: string
+ remote: string
+ networks: Readonly
+ history: ReturnType
+ dispatch: StateDispatch
disabled: boolean
-) =>
+ setIsUpdating: React.Dispatch
+}) =>
useCallback(
(e: React.FormEvent): void => {
e.preventDefault()
@@ -110,15 +120,16 @@ export const useOnSubmit = (
addNotification(errorMessage)(dispatch)
return
}
+ setIsUpdating(true)
updateNetwork({
networkID: id!,
options: {
name,
remote,
},
- })(dispatch, history)
+ })(dispatch, history).then(() => setIsUpdating(false))
},
- [id, name, remote, networks, history, dispatch, disabled]
+ [id, name, remote, networks, history, dispatch, disabled, setIsUpdating]
)
export default {
diff --git a/packages/neuron-ui/src/components/NetworkEditor/index.tsx b/packages/neuron-ui/src/components/NetworkEditor/index.tsx
index d2085039e3..e6bd6cd1d4 100644
--- a/packages/neuron-ui/src/components/NetworkEditor/index.tsx
+++ b/packages/neuron-ui/src/components/NetworkEditor/index.tsx
@@ -6,18 +6,15 @@ import TextField from 'widgets/TextField'
import Button from 'widgets/Button'
import Spinner from 'widgets/Spinner'
-import { useState as useGlobalState, useDispatch } from 'states/stateProvider'
-import { verifyNetworkName, verifyURL } from 'utils/validators'
-import { useGoBack } from 'utils/hooks'
-import { MAX_NETWORK_NAME_LENGTH } from 'utils/const'
+import { CONSTANTS, useGoBack, verifyNetworkName, verifyURL } from 'utils'
+import { useState as useGlobalState, useDispatch } from 'states'
import { useOnSubmit } from './hooks'
import styles from './networkEditor.module.scss'
+const { MAX_NETWORK_NAME_LENGTH } = CONSTANTS
+
const NetworkEditor = () => {
const {
- app: {
- loadings: { network: isUpdating = false },
- },
settings: { networks = [] },
} = useGlobalState()
const dispatch = useDispatch()
@@ -36,6 +33,7 @@ const NetworkEditor = () => {
url: '',
urlError: '',
})
+ const [isUpdating, setIsUpdating] = useState(false)
const disabled = !!(
!editor.name ||
@@ -89,7 +87,16 @@ const NetworkEditor = () => {
)
const goBack = useGoBack(history)
- const onSubmit = useOnSubmit(id, editor.name, editor.url, networks, history, dispatch, disabled)
+ const onSubmit = useOnSubmit({
+ id: id!,
+ name: editor.name,
+ remote: editor.url,
+ networks,
+ history,
+ dispatch,
+ disabled,
+ setIsUpdating,
+ })
return (
diff --git a/packages/neuron-ui/src/components/NetworkEditor/networkEditor.module.scss b/packages/neuron-ui/src/components/NetworkEditor/networkEditor.module.scss
index 386351e02c..d5fca86c52 100644
--- a/packages/neuron-ui/src/components/NetworkEditor/networkEditor.module.scss
+++ b/packages/neuron-ui/src/components/NetworkEditor/networkEditor.module.scss
@@ -1,5 +1,5 @@
@import '../../styles/mixin.scss';
.actions {
- @include formFooter;
+ @include form-footer;
}
diff --git a/packages/neuron-ui/src/components/NetworkSetting/index.tsx b/packages/neuron-ui/src/components/NetworkSetting/index.tsx
index ba21ab6c48..cc6d62037a 100644
--- a/packages/neuron-ui/src/components/NetworkSetting/index.tsx
+++ b/packages/neuron-ui/src/components/NetworkSetting/index.tsx
@@ -1,17 +1,19 @@
import React, { useEffect, useCallback } from 'react'
import { useHistory } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
+import { TFunction } from 'i18next'
import { ChoiceGroup, IChoiceGroupOption } from 'office-ui-fabric-react'
import Button from 'widgets/Button'
+import { ReactComponent as EditNetwork } from 'widgets/Icons/Edit.svg'
+import { ReactComponent as DeleteNetwork } from 'widgets/Icons/Delete.svg'
-import chainState from 'states/initStates/chain'
-import { setCurrentNetowrk, openContextMenu, deleteNetwork } from 'services/remote'
+import chainState from 'states/init/chain'
+import { setCurrentNetowrk } from 'services/remote'
-import { Routes } from 'utils/const'
-import { backToTop } from 'utils/animations'
+import { backToTop, RoutePath, useOnHandleNetwork, useOnWindowResize, useToggleChoiceGroupBorder } from 'utils'
import styles from './networkSetting.module.scss'
-const Label = ({ type, t }: { type: 'ckb' | 'ckb_testnet' | 'ckb_dev' | string; t: any }) => {
+const Label = ({ type, t }: { type: 'ckb' | 'ckb_testnet' | 'ckb_dev' | string; t: TFunction }) => {
switch (type) {
case 'ckb': {
return {t('settings.network.mainnet')}
@@ -32,54 +34,33 @@ const NetworkSetting = ({ chain = chainState, settings: { networks = [] } }: Sta
backToTop()
}, [])
- const onChoiceChange = useCallback((_e, option?: IChoiceGroupOption) => {
- if (option) {
- setCurrentNetowrk(option.key)
- }
- }, [])
-
- const goToCreateNetwork = useCallback(() => {
- history.push(`${Routes.NetworkEditor}/new`)
- }, [history])
+ const { networkID: currentId } = chain
- const onContextMenu = useCallback(
- (e: React.MouseEvent) => {
- e.stopPropagation()
- e.preventDefault()
- const { networkId } = (e.target as HTMLElement).dataset
- const item = networks.find(n => n.id === networkId)
- if (item) {
- const isCurrent = item.id === chain.networkID
- const isDefault = item.type === 0
- const menuTemplate = [
- {
- label: t('common.select'),
- enabled: !isCurrent,
- click: () => {
- setCurrentNetowrk(item.id)
- },
- },
- {
- label: t('common.edit'),
- enabled: true,
- click: () => {
- history.push(`${Routes.NetworkEditor}/${item.id}`)
- },
- },
- {
- label: t('common.delete'),
- enabled: !isDefault,
- click: () => {
- deleteNetwork(item.id)
- },
- },
- ]
- openContextMenu(menuTemplate)
+ const onChoiceChange = useCallback(
+ (_e, option?: IChoiceGroupOption) => {
+ if (option && option.key !== currentId) {
+ setCurrentNetowrk(option.key)
}
},
- [chain.networkID, networks, history, t]
+ [currentId]
)
+ const goToCreateNetwork = useCallback(() => {
+ history.push(`${RoutePath.NetworkEditor}/new`)
+ }, [history])
+
+ const toggleBottomBorder = useToggleChoiceGroupBorder(`.${styles.networks}`, styles.hasBottomBorder)
+
+ useEffect(() => {
+ if (networks.length) {
+ toggleBottomBorder()
+ }
+ }, [toggleBottomBorder, networks.length])
+
+ useOnWindowResize(toggleBottomBorder)
+
+ const onHandleNetwork = useOnHandleNetwork({ history })
+
return (
{
+ const isDefault = network.type === 0
return (
-
+
{text}
+ {`(${network.remote}`}
+
- {`(${network.remote})`}
-
+
+
+ {isDefault ? null : (
+
+ )}
)
},
diff --git a/packages/neuron-ui/src/components/NetworkSetting/networkSetting.module.scss b/packages/neuron-ui/src/components/NetworkSetting/networkSetting.module.scss
index 650a3bdd67..5a5b8c8508 100644
--- a/packages/neuron-ui/src/components/NetworkSetting/networkSetting.module.scss
+++ b/packages/neuron-ui/src/components/NetworkSetting/networkSetting.module.scss
@@ -1,24 +1,86 @@
+@import '../../styles/mixin.scss';
+
.container {
display: grid;
- grid-template:
- 'networks'auto 'actions'auto;
+ grid-template: 'networks' auto 'actions' auto;
grid-row-gap: 15px;
}
.networks {
grid-area: networks;
+ height: calc(100vh - 200px);
+ overflow: auto;
+ padding: 0 0 5px 8px;
}
-.network {
- span:nth-of-type(2) {
- margin: 0 5px;
+.choiceLabel {
+ display: flex !important;
+ align-items: center;
+ border: 1px solid transparent;
+ padding: 3px;
+ box-sizing: border-box;
+
+ .networkLabel {
+ display: flex;
+ align-items: center;
+ pointer-events: none;
+ .url {
+ position: relative;
+ @include text-overflow-ellipsis;
+ max-width: 650px;
+ color: #999;
+ pointer-events: none;
+ padding-right: 0.6em;
+ &:before {
+ position: absolute;
+ right: 0;
+ content: ')';
+ }
+ }
+ }
+ button {
+ display: flex;
+ height: 1.25rem;
+ align-items: center;
+ visibility: hidden;
+ appearance: none;
+ margin: 0 0 0 10px;
+ padding: 0;
+ border: none;
+ background: transparent;
+ svg {
+ pointer-events: none;
+ path,
+ g {
+ fill: #888;
+ }
+ }
+ &:hover {
+ svg {
+ path,
+ g {
+ fill: var(--nervos-green);
+ }
+ }
+ }
+ }
+ &:hover,
+ &:focus {
+ border-color: #aeaeae;
+ button {
+ visibility: visible;
+ }
}
}
.actions {
grid-area: actions;
-
+ justify-self: flex-end;
button {
width: 9.375rem;
}
}
+
+.hasBottomBorder {
+ border-bottom: 0.5px solid #ccc;
+}
diff --git a/packages/neuron-ui/src/components/NetworkStatus/index.tsx b/packages/neuron-ui/src/components/NetworkStatus/index.tsx
index 0314d7530b..7c9cd77857 100644
--- a/packages/neuron-ui/src/components/NetworkStatus/index.tsx
+++ b/packages/neuron-ui/src/components/NetworkStatus/index.tsx
@@ -1,8 +1,6 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
-import { ConnectionStatus, SyncStatus } from 'utils/const'
-import { localNumberFormatter } from 'utils/formatters'
-
+import { ConnectionStatus, SyncStatus, localNumberFormatter } from 'utils'
import styles from './networkStatus.module.scss'
export interface NetworkStatusProps {
diff --git a/packages/neuron-ui/src/components/NetworkStatus/networkStatus.module.scss b/packages/neuron-ui/src/components/NetworkStatus/networkStatus.module.scss
index f2d73db7aa..20385f47c8 100644
--- a/packages/neuron-ui/src/components/NetworkStatus/networkStatus.module.scss
+++ b/packages/neuron-ui/src/components/NetworkStatus/networkStatus.module.scss
@@ -14,6 +14,7 @@ $hover-bg-color: #3cc68a4d;
display: flex;
align-items: center;
line-height: 1em;
+ word-break: break-all;
&::before {
position: absolute;
@@ -52,7 +53,7 @@ $hover-bg-color: #3cc68a4d;
}
.tooltip {
- @include MediumText;
+ @include medium-text;
display: none;
position: absolute;
bottom: calc(100% + 10px);
@@ -69,7 +70,6 @@ $hover-bg-color: #3cc68a4d;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.22);
transition: all 0.2s ease-in-out;
opacity: 0;
- user-select: none;
pointer-events: none;
font-size: 0.75rem;
line-height: 1.5em;
diff --git a/packages/neuron-ui/src/components/Overview/index.tsx b/packages/neuron-ui/src/components/Overview/index.tsx
index 83ba80ec71..28a9b29d1a 100644
--- a/packages/neuron-ui/src/components/Overview/index.tsx
+++ b/packages/neuron-ui/src/components/Overview/index.tsx
@@ -1,27 +1,27 @@
import React, { useCallback, useMemo, useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
-import PropertyList, { Property } from 'widgets/PropertyList'
-import Balance from 'widgets/Balance'
+import BalanceSyncIcon from 'components/BalanceSyncingIcon'
+import CopyZone from 'widgets/CopyZone'
import { showTransactionDetails } from 'services/remote'
-import { useState as useGlobalState, useDispatch } from 'states/stateProvider'
-import { updateTransactionList } from 'states/stateProvider/actionCreators'
+import { useState as useGlobalState, useDispatch, updateTransactionList } from 'states'
-import { localNumberFormatter, shannonToCKBFormatter, uniformTimeFormatter } from 'utils/formatters'
-import getSyncStatus from 'utils/getSyncStatus'
-import getCurrentUrl from 'utils/getCurrentUrl'
import {
- SyncStatus as SyncStatusEnum,
- SyncStatusThatBalanceUpdating,
- ConnectionStatus,
- PAGE_SIZE,
- Routes,
- CONFIRMATION_THRESHOLD,
-} from 'utils/const'
-import { backToTop } from 'utils/animations'
+ localNumberFormatter,
+ shannonToCKBFormatter,
+ uniformTimeFormatter,
+ backToTop,
+ CONSTANTS,
+ RoutePath,
+ getCurrentUrl,
+ getSyncStatus,
+} from 'utils'
+
import styles from './overview.module.scss'
+const { PAGE_SIZE, CONFIRMATION_THRESHOLD } = CONSTANTS
+
const genTypeLabel = (type: 'send' | 'receive', status: 'pending' | 'confirming' | 'success' | 'failed') => {
switch (type) {
case 'send': {
@@ -51,7 +51,7 @@ const genTypeLabel = (type: 'send' | 'receive', status: 'pending' | 'confirming'
const Overview = () => {
const {
app: { tipBlockNumber, tipBlockTimestamp },
- wallet: { id, name, balance = '' },
+ wallet: { id, balance = '' },
chain: {
tipBlockNumber: syncedBlockNumber,
transactions: { items = [] },
@@ -87,42 +87,9 @@ const Overview = () => {
})(dispatch)
}, [id, dispatch])
const onGoToHistory = useCallback(() => {
- history.push(Routes.History)
+ history.push(RoutePath.History)
}, [history])
- const balanceProperties: Property[] = useMemo(() => {
- const balanceValue = shannonToCKBFormatter(balance)
- let prompt = null
- if (ConnectionStatus.Connecting === connectionStatus) {
- prompt = {t('sync.connecting')}
- } else if (ConnectionStatus.Offline === connectionStatus) {
- prompt = (
-
- {t('sync.sync-failed')}
-
- )
- } else if (SyncStatusEnum.SyncNotStart === syncStatus) {
- prompt = (
-
- {t('sync.sync-not-start')}
-
- )
- } else if (SyncStatusThatBalanceUpdating.includes(syncStatus) || ConnectionStatus.Connecting === connectionStatus) {
- prompt = {t('sync.syncing-balance')}
- }
- return [
- {
- label: t('overview.balance'),
- value: (
-
-
- {prompt}
-
- ),
- },
- ]
- }, [t, balance, syncStatus, connectionStatus])
-
const onRecentActivityDoubleClick = useCallback((e: React.SyntheticEvent) => {
const cellElement = e.target as HTMLTableCellElement
if (cellElement?.parentElement?.dataset?.hash) {
@@ -221,10 +188,19 @@ const Overview = () => {
)
}, [recentItems, syncedBlockNumber, tipBlockNumber, t, onRecentActivityDoubleClick])
+ const ckbBalance = shannonToCKBFormatter(balance)
+
return (
- {name}
-
+ {/* {name} */}
+ {t('navbar.overview')}
+
+ {`${t('overview.balance')}:`}
+
+ {`${ckbBalance}`}
+
+
+
{t('overview.recent-activities')}
{items.length ? (
diff --git a/packages/neuron-ui/src/components/Overview/overview.module.scss b/packages/neuron-ui/src/components/Overview/overview.module.scss
index 60bb3627be..125c1137d1 100644
--- a/packages/neuron-ui/src/components/Overview/overview.module.scss
+++ b/packages/neuron-ui/src/components/Overview/overview.module.scss
@@ -8,85 +8,50 @@ $confirming-color: #b3b3b3;
.overview {
display: grid;
grid-template:
- 'wallet-name wallet-name'auto 'balance balance'auto 'activities-title activities-title'auto 'activities activities'auto 'more-link more-link'auto/ 1fr auto;
- // padding: 39px 11px 0; this size is from design, but not used now.
- padding: 39px 0 0;
+ 'page-title page-title' auto
+ 'balance balance' auto
+ 'activities-title activities-title' auto
+ 'activities activities' auto
+ 'more-link more-link' auto/
+ 1fr auto;
}
-.walletName,
+.pageTitle,
.recentActivitiesTitle {
- @include BoldText;
+ @include bold-text;
font-size: 1.375rem;
- line-height: 1.22em;
- letter-spacing: 1.1px;
color: #000;
margin: 0;
}
-.walletName {
- grid-area: wallet-name;
- margin-bottom: 11px;
+.pageTitle {
+ @include page-title;
+ grid-area: page-title;
}
.recentActivitiesTitle {
grid-area: activities-title;
- margin-top: 45px;
- margin-bottom: 17px;
+ margin-top: 30px;
+ margin-bottom: 15px;
+ font-size: 1rem;
+ font-weight: 500;
}
.balance {
grid-area: balance;
+ font-size: 0.875rem;
+ font-weight: 600;
}
.balanceValue {
- display: flex;
- flex-direction: column;
- text-align: left;
-}
-
-.balancePrompt {
- @include BoldText;
- color: var(--nervos-green);
- font-size: 0.8rem;
- margin-top: 3px;
-}
-
-.balanceInt {
- @include BoldText;
- font-size: 1.125rem;
-}
-
-section {
- position: absolute;
- left: 0;
- top: 100%;
- width: 100%;
- background-color: #f5f5f5;
- box-shadow: 1px 1px 3px 0 rgba(0, 0, 0, 0.12);
- padding: 6px 0;
- z-index: 1;
-
- &>div {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 6px 11px;
-
- &:hover {
- background-color: #e3e3e3;
- }
-
- &>span {
- font-size: 0.75rem;
- font-weight: 600;
- letter-spacing: 0.45px;
- color: #000;
-
- &:last-child {
- font-weight: normal;
- }
- }
-
+ font-weight: 500;
+ max-width: 60%;
+ padding: 0 5px 0 60px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ &:after {
+ content: ' CKB';
}
}
@@ -116,7 +81,6 @@ section {
text-align: left;
font-size: 0.875rem;
font-weight: 600;
- letter-spacing: 0.7px;
color: #000;
line-height: 1em;
padding: 16px 0;
@@ -126,60 +90,58 @@ section {
font-size: 0.875rem;
line-height: 1em;
padding: 2px 0;
- letter-spacing: 0.7px;
color: #000;
}
.txStatus {
- &>div::after {
+ & > div::after {
position: absolute;
display: block;
content: '';
border-radius: 50%;
width: 8px;
height: 8px;
- left: 100%;
+ left: 0;
top: 50%;
transform: translateY(-50%);
}
- &[data-status="pending"]>div::after {
+ &[data-status='pending'] > div::after {
background-color: $pending-color;
filter: drop-shadow(0 0 1px $pending-color);
animation: blink 5s infinite;
}
- &[data-status="confirming"]>div::after {
+ &[data-status='confirming'] > div::after {
background-color: $pending-color;
filter: drop-shadow(0 0 1px $pending-color);
animation: blink 5s infinite;
}
- &[data-status="success"]>div::after {
+ &[data-status='success'] > div::after {
background-color: $success-color;
filter: drop-shadow(0 0 1px $success-color);
}
- &[data-status="failed"]>div::after {
+ &[data-status='failed'] > div::after {
background-color: $failed-color;
filter: drop-shadow(0 0 1px $failed-color);
}
- &>div {
+ & > div {
display: flex;
flex-direction: column;
position: relative;
- width: 150px;
+ padding-left: 20px;
- &>span:first-child {
- flex: 1
+ & > span:first-child {
+ flex: 1;
}
- &>span:nth-child(2) {
+ & > span:nth-child(2) {
color: #626262;
font-size: 0.625rem;
line-height: 0.8125rem;
- letter-spacing: 0.5px;
margin-top: 3px;
}
}
@@ -188,22 +150,22 @@ section {
.linkToHistory {
grid-area: more-link;
- font-size: 0.625rem;
- letter-spacing: 0.5px;
+ font-size: 0.75rem;
color: #000;
margin-top: 13px;
- &>span:hover {
+ & > span:hover {
color: var(--nervos-green);
}
}
.noActivities {
grid-area: more-link;
+ font-size: 0.75rem;
+ color: #000;
}
@keyframes blink {
-
from,
to {
opacity: 0.5;
diff --git a/packages/neuron-ui/src/components/PasswordRequest/index.tsx b/packages/neuron-ui/src/components/PasswordRequest/index.tsx
index 96abe14640..8ebbf51067 100644
--- a/packages/neuron-ui/src/components/PasswordRequest/index.tsx
+++ b/packages/neuron-ui/src/components/PasswordRequest/index.tsx
@@ -1,12 +1,20 @@
-import React, { useRef, useCallback, useMemo } from 'react'
+import React, { useState, useRef, useCallback, useMemo, useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import Button from 'widgets/Button'
import TextField from 'widgets/TextField'
-import { useDialog } from 'utils/hooks'
-import { useState as useGlobalState, useDispatch } from 'states/stateProvider'
-import { AppActions } from 'states/stateProvider/reducer'
-import { sendTransaction, deleteWallet, backupWallet } from 'states/stateProvider/actionCreators'
+import Spinner from 'widgets/Spinner'
+import { useDialog, ResponseCode, ErrorCode, RoutePath } from 'utils'
+
+import {
+ useState as useGlobalState,
+ useDispatch,
+ AppActions,
+ sendTransaction,
+ deleteWallet,
+ backupWallet,
+} from 'states'
+import { PasswordIncorrectException } from 'exceptions'
import styles from './passwordRequest.module.scss'
const PasswordRequest = () => {
@@ -14,7 +22,7 @@ const PasswordRequest = () => {
app: {
send: { description, generatedTx },
loadings: { sending: isSending = false },
- passwordRequest: { walletID = '', actionType = null, password = '' },
+ passwordRequest: { walletID = '', actionType = null },
},
settings: { wallets = [] },
} = useGlobalState()
@@ -22,6 +30,15 @@ const PasswordRequest = () => {
const [t] = useTranslation()
const history = useHistory()
const dialogRef = useRef (null)
+
+ const [password, setPassword] = useState('')
+ const [error, setError] = useState('')
+
+ useEffect(() => {
+ setPassword('')
+ setError('')
+ }, [actionType, setError, setPassword])
+
const onDismiss = useCallback(() => {
dispatch({
type: AppActions.DismissPasswordRequest,
@@ -31,72 +48,84 @@ const PasswordRequest = () => {
const wallet = useMemo(() => wallets.find(w => w.id === walletID), [walletID, wallets])
- const disabled = !password || (actionType === 'send' && isSending)
+ const isLoading = ['send', 'unlock'].includes(actionType || '') && isSending
+ const disabled = !password || isSending
const onSubmit = useCallback(
- (e?: React.FormEvent): void => {
+ async (e?: React.FormEvent) => {
if (e) {
e.preventDefault()
}
if (disabled) {
return
}
- switch (actionType) {
- case 'send': {
- if (isSending) {
+ try {
+ switch (actionType) {
+ case 'send': {
+ if (isSending) {
+ break
+ }
+ await sendTransaction({ walletID, tx: generatedTx, description, password })(dispatch).then(status => {
+ if (status === ResponseCode.SUCCESS) {
+ history.push(RoutePath.History)
+ } else if (status === ErrorCode.PasswordIncorrect) {
+ throw new PasswordIncorrectException()
+ }
+ })
break
}
- sendTransaction({
- walletID,
- tx: generatedTx,
- description,
- password,
- })(dispatch, history)
- break
- }
- case 'delete': {
- deleteWallet({
- id: walletID,
- password,
- })(dispatch)
- break
- }
- case 'backup': {
- backupWallet({
- id: walletID,
- password,
- })(dispatch)
- break
- }
- case 'unlock': {
- if (isSending) {
+ case 'delete': {
+ await deleteWallet({ id: walletID, password })(dispatch).then(status => {
+ if (status === ErrorCode.PasswordIncorrect) {
+ throw new PasswordIncorrectException()
+ }
+ })
+ break
+ }
+ case 'backup': {
+ await backupWallet({ id: walletID, password })(dispatch).then(status => {
+ if (status === ErrorCode.PasswordIncorrect) {
+ throw new PasswordIncorrectException()
+ }
+ })
+ break
+ }
+ case 'unlock': {
+ if (isSending) {
+ break
+ }
+ await sendTransaction({ walletID, tx: generatedTx, description, password })(dispatch).then(status => {
+ if (status === ResponseCode.SUCCESS) {
+ dispatch({
+ type: AppActions.SetGlobalDialog,
+ payload: 'unlock-success',
+ })
+ } else if (status === ErrorCode.PasswordIncorrect) {
+ throw new PasswordIncorrectException()
+ }
+ })
+ break
+ }
+ default: {
break
}
- sendTransaction({
- walletID,
- tx: generatedTx,
- description,
- password,
- })(dispatch, history, { type: 'unlock' })
- break
}
- default: {
- break
+ } catch (err) {
+ if (err.code === ErrorCode.PasswordIncorrect) {
+ setError(t(err.message))
}
}
},
- [dispatch, walletID, password, actionType, description, history, isSending, generatedTx, disabled]
+ [dispatch, walletID, password, actionType, description, history, isSending, generatedTx, disabled, setError, t]
)
const onChange = useCallback(
(e: React.SyntheticEvent) => {
const { value } = e.target as HTMLInputElement
- dispatch({
- type: AppActions.UpdatePassword,
- payload: value,
- })
+ setPassword(value)
+ setError('')
},
- [dispatch]
+ [setPassword, setError]
)
if (!wallet) {
@@ -118,10 +147,13 @@ const PasswordRequest = () => {
autoFocus
required
className={styles.passwordInput}
+ error={error}
/>
-
+
diff --git a/packages/neuron-ui/src/components/PasswordRequest/passwordRequest.module.scss b/packages/neuron-ui/src/components/PasswordRequest/passwordRequest.module.scss
index 08a308eb54..23802741ea 100644
--- a/packages/neuron-ui/src/components/PasswordRequest/passwordRequest.module.scss
+++ b/packages/neuron-ui/src/components/PasswordRequest/passwordRequest.module.scss
@@ -1,7 +1,7 @@
-@import '../../styles//mixin.scss';
+@import '../../styles/mixin.scss';
.dialog {
- @include dialogContainer;
+ @include dialog-container;
padding: 49px 73px;
&::backdrop {
@@ -10,7 +10,7 @@
}
.footer {
- @include dialogFooter;
+ @include dialog-footer;
button:last-of-type {
margin-left: 9px;
@@ -26,12 +26,12 @@
&:after {
display: inline;
- content: ':'
+ content: ':';
}
}
.walletName {
- @include BoldText;
+ @include bold-text;
color: var(--nervos-green);
}
diff --git a/packages/neuron-ui/src/components/Receive/index.tsx b/packages/neuron-ui/src/components/Receive/index.tsx
index 3789e55472..34e56a13e4 100644
--- a/packages/neuron-ui/src/components/Receive/index.tsx
+++ b/packages/neuron-ui/src/components/Receive/index.tsx
@@ -1,12 +1,10 @@
-import React, { useCallback, useMemo } from 'react'
+import React, { useMemo } from 'react'
import { useRouteMatch } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
-import { TooltipHost } from 'office-ui-fabric-react'
-import { ReactComponent as Copy } from 'widgets/Icons/ReceiveCopy.svg'
-import { useState as useGlobalState, useDispatch } from 'states/stateProvider'
+import { useState as useGlobalState, useDispatch } from 'states'
import QRCode from 'widgets/QRCode'
-import { addPopup } from 'states/stateProvider/actionCreators'
+import CopyZone from 'widgets/CopyZone'
import styles from './receive.module.scss'
const Receive = () => {
@@ -20,36 +18,10 @@ const Receive = () => {
} = useRouteMatch()
const accountAddress = useMemo(
- () => address || (addresses.find(addr => addr.type === 0 && addr.txCount === 0) || { address: '' }).address || '',
+ () => (address || addresses.find(addr => addr.type === 0 && addr.txCount === 0)?.address) ?? '',
[address, addresses]
)
- const copyAddress = useCallback(() => {
- window.navigator.clipboard.writeText(accountAddress)
- addPopup('addr-copied')(dispatch)
- }, [accountAddress, dispatch])
-
- const Address = useMemo(
- () => (
-
-
- <>
-
-
- >
-
-
- ),
- [copyAddress, accountAddress, t]
- )
-
if (!accountAddress) {
return {t('receive.address-not-found')}
}
@@ -62,7 +34,11 @@ const Receive = () => {
}}
>
- {Address}
+
+
+ {accountAddress}
+
+
{t('receive.prompt')}
)
diff --git a/packages/neuron-ui/src/components/Receive/receive.module.scss b/packages/neuron-ui/src/components/Receive/receive.module.scss
index bcdc9f87c7..7afcd40680 100644
--- a/packages/neuron-ui/src/components/Receive/receive.module.scss
+++ b/packages/neuron-ui/src/components/Receive/receive.module.scss
@@ -1,23 +1,7 @@
.address {
- display: flex;
- width: 520px;
margin: 20px auto 0;
-
- &>div {
- display: flex;
- justify-content: space-between;
- align-items: center;
- flex: 1;
- }
-
- input {
- flex: 1;
- padding: 6px 17px;
- border: 1px solid #000;
- color: #000;
- font-size: 1rem;
- letter-spacing: 0.6px;
- }
+ display: flex;
+ justify-content: center;
}
.copyBtn {
@@ -26,10 +10,8 @@
background: transparent;
&:hover {
-
g,
path {
-
stroke: var(--nervos-green);
fill: var(--nervos-green);
}
@@ -39,6 +21,5 @@
.notation {
width: 450px;
font-size: 0.75rem;
- letter-spacing: 0.5px;
- margin: 20px auto 0;
+ margin: 6px auto 0;
}
diff --git a/packages/neuron-ui/src/components/Send/hooks.ts b/packages/neuron-ui/src/components/Send/hooks.ts
index ee1ca6d46e..e8a5d4fe0a 100644
--- a/packages/neuron-ui/src/components/Send/hooks.ts
+++ b/packages/neuron-ui/src/components/Send/hooks.ts
@@ -1,15 +1,21 @@
import React, { useState, useCallback, useEffect, useMemo } from 'react'
import { TFunction } from 'i18next'
-import i18n from 'utils/i18n'
import jsQR from 'jsqr'
import { AppActions, StateDispatch } from 'states/stateProvider/reducer'
import { captureScreenshot, showErrorMessage } from 'services/remote'
import { generateTx, generateSendingAllTx } from 'services/remote/wallets'
-import { outputsToTotalAmount, CKBToShannonFormatter, shannonToCKBFormatter } from 'utils/formatters'
-import { verifyTransactionOutputs, verifyAddress } from 'utils/validators'
-import calculateFee from 'utils/calculateFee'
+import {
+ outputsToTotalAmount,
+ CKBToShannonFormatter,
+ shannonToCKBFormatter,
+ calculateFee,
+ verifyTransactionOutputs,
+ verifyAddress,
+} from 'utils'
+import i18n from 'utils/i18n'
+
import styles from './send.module.scss'
let generateTxTimer: ReturnType
diff --git a/packages/neuron-ui/src/components/Send/index.tsx b/packages/neuron-ui/src/components/Send/index.tsx
index 018c52c190..4c3a327ca0 100644
--- a/packages/neuron-ui/src/components/Send/index.tsx
+++ b/packages/neuron-ui/src/components/Send/index.tsx
@@ -17,34 +17,33 @@ import Calendar from 'widgets/Icons/Calendar.png'
import ActiveCalendar from 'widgets/Icons/ActiveCalendar.png'
import { ReactComponent as Attention } from 'widgets/Icons/Attention.svg'
-import { useState as useGlobalState, useDispatch } from 'states/stateProvider'
-import appState from 'states/initStates/app'
+import { useState as useGlobalState, useDispatch } from 'states'
+import appState from 'states/init/app'
import {
PlaceHolders,
ErrorCode,
- MAX_DECIMAL_DIGITS,
- MAINNET_TAG,
SyncStatus,
SyncStatusThatBalanceUpdating,
ConnectionStatus,
- SINCE_FIELD_SIZE,
-} from 'utils/const'
-import getSyncStatus from 'utils/getSyncStatus'
-import getCurrentUrl from 'utils/getCurrentUrl'
-import { shannonToCKBFormatter, localNumberFormatter } from 'utils/formatters'
-import {
+ CONSTANTS,
+ shannonToCKBFormatter,
+ localNumberFormatter,
+ getCurrentUrl,
+ getSyncStatus,
verifyTotalAmount,
verifyTransactionOutputs,
verifyAmount,
verifyAmountRange,
verifyAddress,
-} from 'utils/validators'
+} from 'utils'
-import DatetimePicker from 'widgets/DatetimePicker'
+import DatetimePicker, { formatDate } from 'widgets/DatetimePicker'
import { useInitialize } from './hooks'
import styles from './send.module.scss'
+const { MAX_DECIMAL_DIGITS, MAINNET_TAG, SINCE_FIELD_SIZE } = CONSTANTS
+
const Send = () => {
const {
app: {
@@ -305,7 +304,7 @@ const Send = () => {
- {item.date ? `${t('send.release-on')}: ${new Date(+item.date).toLocaleDateString()}` : null}
+ {item.date ? `${t('send.release-on')}: ${formatDate(new Date(+item.date))}` : null}
|