diff --git a/packages/neuron-ui/src/components/PageContainer/index.tsx b/packages/neuron-ui/src/components/PageContainer/index.tsx index 3c1243bf38..6237ba4ad4 100755 --- a/packages/neuron-ui/src/components/PageContainer/index.tsx +++ b/packages/neuron-ui/src/components/PageContainer/index.tsx @@ -68,7 +68,7 @@ const PageContainer: React.FC = props => { return [ bestBlockNumber > 0 && cacheTipBlockNumber > 0 ? `${+((cacheTipBlockNumber * 100) / bestBlockNumber).toFixed(2)}%` - : '0', + : '0.00%', `${cacheTipBlockNumber >= 0 ? localNumberFormatter(cacheTipBlockNumber) : '-'} / ${ bestBlockNumber >= 0 ? localNumberFormatter(bestBlockNumber) : '-' }`, diff --git a/packages/neuron-ui/src/containers/Main/index.tsx b/packages/neuron-ui/src/containers/Main/index.tsx index 0f2175d155..7d77ae8242 100644 --- a/packages/neuron-ui/src/containers/Main/index.tsx +++ b/packages/neuron-ui/src/containers/Main/index.tsx @@ -2,8 +2,10 @@ import React, { useCallback, useMemo } from 'react' import { useNavigate, useLocation, Outlet } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { useState as useGlobalState, useDispatch, dismissGlobalAlertDialog } from 'states' -import { useOnDefaultContextMenu, useOnLocaleChange } from 'utils' +import { useMigrate, useOnDefaultContextMenu, useOnLocaleChange } from 'utils' import AlertDialog from 'widgets/AlertDialog' +import Dialog from 'widgets/Dialog' +import Button from 'widgets/Button' import { useSubscription, useSyncChainData, useOnCurrentWalletChange } from './hooks' const MainContent = () => { @@ -49,6 +51,7 @@ const MainContent = () => { const onCancelGlobalDialog = useCallback(() => { dismissGlobalAlertDialog()(dispatch) }, [dispatch]) + const { isMigrateDialogShow, onCancel, onBackUp, onConfirm } = useMigrate() return (
@@ -61,6 +64,18 @@ const MainContent = () => { type={globalAlertDialog?.type ?? 'success'} onCancel={onCancelGlobalDialog} /> + + {t('messages.rebuild-sync') + .split('\n') + .map((s: string) => ( +

{s}

+ ))} +
+
+
) } diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json index 4af0e2bc4c..4878419ed2 100644 --- a/packages/neuron-ui/src/locales/en.json +++ b/packages/neuron-ui/src/locales/en.json @@ -568,6 +568,7 @@ "experimental-message": "This is an experimental feature, it could change at any time. Please use with caution.", "rebuild-sync": "For better user experience, Neuron has adopted a new storage, which requires a migrating of data (estimated 20 ~ 60min).\nSorry for the inconvenience.", "migrate-warning": "Warning: The migration process may fail for unknown reasons resulting in resynchronization, please back up manually and start the migration!", + "migrate-ckb-data": "Migrate", "migrate": "Migrate", "secp256k1/blake160-address-required": "Secp256k1/blake160 address is required", "light-client-locktime-warning": "2.Light client mode doesn't support showing lock-time CKBytes.", diff --git a/packages/neuron-ui/src/locales/zh-tw.json b/packages/neuron-ui/src/locales/zh-tw.json index c965ac67f1..a1f2bde2c7 100644 --- a/packages/neuron-ui/src/locales/zh-tw.json +++ b/packages/neuron-ui/src/locales/zh-tw.json @@ -562,6 +562,7 @@ "experimental-message": "本頁面為實驗性功能,可能隨時變更。請謹慎使用。", "rebuild-sync": "為了提供更好的用戶體驗,Neuron 採取了新的存儲方案,該方案需要壹次性遷移數據(預期同步時間為 20~60 分鐘)。\n抱歉給您帶來不便。", "migrate-warning": "註意:遷移過程中可能由於未知原因失敗導致需要重新同步,請備份完成後開始遷移!", + "migrate-ckb-data": "數據遷移", "migrate": "遷移", "secp256k1/blake160-address-required": "請輸入 secp256k1/blake160 地址", "light-client-locktime-warning": "2.輕節點模式不支持展示到期解鎖的 CKBytes。", diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json index d9f7b3f354..19d9048896 100644 --- a/packages/neuron-ui/src/locales/zh.json +++ b/packages/neuron-ui/src/locales/zh.json @@ -563,6 +563,7 @@ "experimental-message": "本页面为实验性功能,可能随时变更。请谨慎使用。", "rebuild-sync": "为了提供更好的用户体验,Neuron 採取了新的存储方案,该方案需要一次性迁移数据(预期同步时间为 20~60 分钟)。\n抱歉给您带来不便。", "migrate-warning": "注意:迁移过程中可能由于未知原因失败导致需要重新同步,请备份完成后开始迁移!", + "migrate-ckb-data": "数据迁移", "migrate": "迁移", "secp256k1/blake160-address-required": "请输入 secp256k1/blake160 地址", "light-client-locktime-warning": "2.轻节点模式不支持展示到期解锁的 CKBytes。", diff --git a/packages/neuron-ui/src/services/subjects.ts b/packages/neuron-ui/src/services/subjects.ts index 9d5e63bcdb..b78aebf9d2 100644 --- a/packages/neuron-ui/src/services/subjects.ts +++ b/packages/neuron-ui/src/services/subjects.ts @@ -37,13 +37,14 @@ const SubjectConstructor = ( return ipcRenderer ? { subscribe: (handler: (data: T) => void) => { - ipcRenderer.on(channel, (_e: Event, data: T) => { + const handlerWrap = (_e: Event, data: T) => { handler(data) - }) + } + ipcRenderer.on(channel, handlerWrap) return { unsubscribe: () => { if (isMulti) { - ipcRenderer.removeListener(channel, handler) + ipcRenderer.removeListener(channel, handlerWrap) } else { ipcRenderer.removeAllListeners(channel) } @@ -67,7 +68,7 @@ export const Navigation = SubjectConstructor('navigation') export const SetLocale = SubjectConstructor<(typeof LOCALES)[number]>('set-locale') export const DeviceSignIndex = SubjectConstructor('device-sign-index') export const MultisigOutputUpdate = SubjectConstructor('multisig-output-update') -export const Migrate = SubjectConstructor<'need-migrate' | 'migrating' | 'failed' | 'finish'>('migrate') +export const Migrate = SubjectConstructor<'need-migrate' | 'migrating' | 'failed' | 'finish'>('migrate', true) export default { DataUpdate, diff --git a/packages/neuron-ui/src/utils/hooks/index.ts b/packages/neuron-ui/src/utils/hooks/index.ts index 261674a879..8de2d6897d 100644 --- a/packages/neuron-ui/src/utils/hooks/index.ts +++ b/packages/neuron-ui/src/utils/hooks/index.ts @@ -1,7 +1,7 @@ import { useState, useMemo, useCallback, useEffect, useRef } from 'react' -import { useNavigate } from 'react-router-dom' +import { useLocation, useNavigate } from 'react-router-dom' import { TFunction, i18n as i18nType } from 'i18next' -import { openContextMenu, requestPassword, migrateData } from 'services/remote' +import { openContextMenu, requestPassword, migrateData, getCkbNodeDataPath } from 'services/remote' import { loadedWalletIDs, syncRebuildNotification, wallets } from 'services/localCache' import { Migrate, SetLocale as SetLocaleSubject } from 'services/subjects' import { @@ -13,7 +13,7 @@ import { showPageNotice, useDispatch, } from 'states' -import { epochParser, isReadyByVersion, calculateClaimEpochValue, CONSTANTS } from 'utils' +import { epochParser, isReadyByVersion, calculateClaimEpochValue, CONSTANTS, isSuccessResponse } from 'utils' import { validateTokenId, validateAssetAccountName, @@ -24,7 +24,7 @@ import { validateAddress, validateAmountRange, } from 'utils/validators' -import { MenuItemConstructorOptions } from 'electron' +import { MenuItemConstructorOptions, shell } from 'electron' import { ErrorWithI18n, isErrorWithI18n } from 'exceptions' export * from './createSUDTAccount' @@ -405,10 +405,23 @@ export const useToggleChoiceGroupBorder = (containerSelector: string, borderClas } }, [containerSelector, borderClassName]) -export const useGlobalNotifications = ( - dispatch: React.Dispatch<{ type: AppActions.SetGlobalDialog; payload: State.GlobalDialogType }>, - hasDismissMigrate: boolean -) => { +export const useMigrate = () => { + const [isMigrateDialogShow, setIsMigrateDialogShow] = useState(false) + const [hasDismissMigrate, setHasDismissMigrate] = useState(false) + const [ckbDataPath, setCkbDataPath] = useState() + const location = useLocation() + useEffect(() => { + getCkbNodeDataPath().then(res => { + if (isSuccessResponse(res) && res.result) { + setCkbDataPath(res.result) + } + }) + }, [location.pathname]) + const onBackUp = useCallback(() => { + if (ckbDataPath) { + shell.openPath(ckbDataPath) + } + }, [ckbDataPath]) useEffect(() => { const lastVersion = syncRebuildNotification.load() const isVersionUpdate = isReadyByVersion(CONSTANTS.SYNC_REBUILD_SINCE_VERSION, lastVersion) @@ -420,16 +433,34 @@ export const useGlobalNotifications = ( migrateSubscription.unsubscribe() } else if (!hasDismissMigrate) { // means need click ok to migrate - dispatch({ - type: AppActions.SetGlobalDialog, - payload: 'rebuild-sync', - }) + setIsMigrateDialogShow(true) } }) return () => { migrateSubscription.unsubscribe() } - }, [dispatch, hasDismissMigrate]) + }, [hasDismissMigrate]) + const onCancel = useCallback(() => { + setIsMigrateDialogShow(false) + setHasDismissMigrate(true) + }, []) + const onConfirm = useCallback(() => { + migrateData() + .then(res => { + if (isSuccessResponse(res)) { + setIsMigrateDialogShow(false) + } + }) + .finally(() => { + syncRebuildNotification.save() + }) + }, []) + return { + isMigrateDialogShow, + onCancel, + onBackUp, + onConfirm, + } } export const useDidMount = (cb: () => void) => {