From 1922a200b5ea3cd6f2e72f9f6c12a03315bc38c0 Mon Sep 17 00:00:00 2001 From: heisenberg Date: Fri, 20 Dec 2024 18:40:04 +0800 Subject: [PATCH 01/13] feat: store unencryptedKeyringData --- src/background/service/keyring/index.ts | 48 ++++++++++++++++++------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/background/service/keyring/index.ts b/src/background/service/keyring/index.ts index d2f1d01bc0a..4ff6005cb47 100644 --- a/src/background/service/keyring/index.ts +++ b/src/background/service/keyring/index.ts @@ -47,6 +47,11 @@ import { } from 'background/utils/password'; import uninstalledMetricService from '../uninstalled'; +const UNENCRYPTED_IGNORE_KEYRING = [ + KEYRING_TYPE.SimpleKeyring, + KEYRING_TYPE.HdKeyring, +]; + export const KEYRING_SDK_TYPES = { SimpleKeyring, HdKeyring, @@ -64,6 +69,11 @@ export const KEYRING_SDK_TYPES = { EthImKeyKeyring, }; +export type KeyringSerializedData = { + type: string; + data: T; +}; + interface MemStoreState { isUnlocked: boolean; keyringTypes: any[]; @@ -346,6 +356,11 @@ export class KeyringService extends EventEmitter { this.setUnlocked(); } + // force store unencrypted keyring data if not exist + if (!this.store.getState().unencryptedKeyringData) { + await this.persistAllKeyrings(); + } + return this.fullUpdate(); } @@ -786,14 +801,14 @@ export class KeyringService extends EventEmitter { * @param {string} password - The keyring controller password. * @returns {Promise} Resolves to true once keyrings are persisted. */ - persistAllKeyrings(): Promise { + async persistAllKeyrings(): Promise { if (!this.isUnlocked()) { return Promise.reject( new Error('KeyringController - password is not a string') ); } - return Promise.all( + const serializedKeyrings = await Promise.all( this.keyrings.map((keyring) => { return Promise.all([keyring.type, keyring.serialize()]).then( (serializedKeyringArray) => { @@ -801,21 +816,28 @@ export class KeyringService extends EventEmitter { return { type: serializedKeyringArray[0], data: serializedKeyringArray[1], - }; + } as KeyringSerializedData; } ); }) - ) - .then((serializedKeyrings) => { - return passwordEncrypt({ - data: serializedKeyrings, - password: this.password, - }); + ); + + const unencryptedKeyringData = serializedKeyrings + .map(({ type, data }) => { + if (!UNENCRYPTED_IGNORE_KEYRING.includes(type as any)) { + return { type, data }; + } }) - .then((encryptedString) => { - this.store.updateState({ vault: encryptedString }); - return true; - }); + .filter(Boolean) as KeyringSerializedData[]; + + const encryptedString = await passwordEncrypt({ + data: serializedKeyrings, + password: this.password, + }); + + this.store.updateState({ vault: encryptedString, unencryptedKeyringData }); + + return true; } /** From 8e463134011c566216e3a08d41a70f86896b028c Mon Sep 17 00:00:00 2001 From: heisenberg Date: Mon, 23 Dec 2024 10:50:49 +0800 Subject: [PATCH 02/13] fix: undefined --- src/background/service/keyring/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/background/service/keyring/index.ts b/src/background/service/keyring/index.ts index 4ff6005cb47..e5a2589adcc 100644 --- a/src/background/service/keyring/index.ts +++ b/src/background/service/keyring/index.ts @@ -827,6 +827,7 @@ export class KeyringService extends EventEmitter { if (!UNENCRYPTED_IGNORE_KEYRING.includes(type as any)) { return { type, data }; } + return undefined; }) .filter(Boolean) as KeyringSerializedData[]; From fdf888078a0b51fcad708497cb1a0b2f4c9ef681 Mon Sep 17 00:00:00 2001 From: heisenberg Date: Wed, 25 Dec 2024 16:39:44 +0900 Subject: [PATCH 03/13] feat: new unlock screen --- _raw/locales/en/messages.json | 5 +- src/background/controller/wallet.ts | 3 + src/background/service/keyring/index.ts | 18 +++- src/ui/assets/unlock/background.svg | 49 +++++++++++ src/ui/assets/unlock/rabby.svg | 24 ++++++ .../views/ForgotPassword/ForgotPassword.tsx | 15 ++++ src/ui/views/Unlock/index.tsx | 85 +++++++++++++++---- src/ui/views/Unlock/style.less | 33 ------- src/ui/views/index.tsx | 5 ++ 9 files changed, 186 insertions(+), 51 deletions(-) create mode 100644 src/ui/assets/unlock/background.svg create mode 100644 src/ui/assets/unlock/rabby.svg create mode 100644 src/ui/views/ForgotPassword/ForgotPassword.tsx delete mode 100644 src/ui/views/Unlock/style.less diff --git a/_raw/locales/en/messages.json b/_raw/locales/en/messages.json index 03de2481f4e..f7474053c1b 100644 --- a/_raw/locales/en/messages.json +++ b/_raw/locales/en/messages.json @@ -1741,7 +1741,10 @@ "required": "Enter the Password to Unlock", "placeholder": "Enter the Password to Unlock", "error": "incorrect password" - } + }, + "title": "Rabby Wallet", + "description": "The game-changing wallet for Ethereum and all EVM chains", + "btnForgotPassword": "Forgot Password?" }, "addToken": { "noTokenFound": "No token found", diff --git a/src/background/controller/wallet.ts b/src/background/controller/wallet.ts index 333da424135..4bc7438e98d 100644 --- a/src/background/controller/wallet.ts +++ b/src/background/controller/wallet.ts @@ -4980,6 +4980,9 @@ export class WalletController extends BaseController { tx, }); }; + + hasUnencryptedKeyringData = async () => + keyringService.hasUnencryptedKeyringData(); } const wallet = new WalletController(); diff --git a/src/background/service/keyring/index.ts b/src/background/service/keyring/index.ts index e5a2589adcc..67fa994e1f6 100644 --- a/src/background/service/keyring/index.ts +++ b/src/background/service/keyring/index.ts @@ -822,11 +822,13 @@ export class KeyringService extends EventEmitter { }) ); + let hasEncryptedKeyringData = false; const unencryptedKeyringData = serializedKeyrings .map(({ type, data }) => { if (!UNENCRYPTED_IGNORE_KEYRING.includes(type as any)) { return { type, data }; } + hasEncryptedKeyringData = true; return undefined; }) .filter(Boolean) as KeyringSerializedData[]; @@ -836,7 +838,11 @@ export class KeyringService extends EventEmitter { password: this.password, }); - this.store.updateState({ vault: encryptedString, unencryptedKeyringData }); + this.store.updateState({ + vault: encryptedString, + unencryptedKeyringData, + hasEncryptedKeyringData, + }); return true; } @@ -1258,6 +1264,16 @@ export class KeyringService extends EventEmitter { isUnlocked(): boolean { return this.memStore.getState().isUnlocked; } + + // ledger, trezor, etc hardware wallet data is unencrypted + hasUnencryptedKeyringData(): boolean { + return !!this.store.getState().unencryptedKeyringData; + } + + // private key and mnemonic data is encrypted + hasEncryptedKeyringData(): boolean { + return this.store.getState().hasEncryptedKeyringData; + } } export default new KeyringService(); diff --git a/src/ui/assets/unlock/background.svg b/src/ui/assets/unlock/background.svg new file mode 100644 index 00000000000..e54872da032 --- /dev/null +++ b/src/ui/assets/unlock/background.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ui/assets/unlock/rabby.svg b/src/ui/assets/unlock/rabby.svg new file mode 100644 index 00000000000..4453f0fe32e --- /dev/null +++ b/src/ui/assets/unlock/rabby.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ui/views/ForgotPassword/ForgotPassword.tsx b/src/ui/views/ForgotPassword/ForgotPassword.tsx new file mode 100644 index 00000000000..02d96931729 --- /dev/null +++ b/src/ui/views/ForgotPassword/ForgotPassword.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import Browser from 'webextension-polyfill'; + +export const ForgotPassword = () => { + // This useEffect is used to close the window when the extension icon is clicked + React.useEffect(() => { + Browser.runtime.onMessage.addListener((request) => { + if (request.type === 'pageOpened') { + window.close(); + } + }); + }, []); + + return
Forgot Password
; +}; diff --git a/src/ui/views/Unlock/index.tsx b/src/ui/views/Unlock/index.tsx index ba9c2921f9e..f5b07dd914c 100644 --- a/src/ui/views/Unlock/index.tsx +++ b/src/ui/views/Unlock/index.tsx @@ -2,9 +2,16 @@ import React, { useEffect, useRef } from 'react'; import { Input, Form, Button } from 'antd'; import { useTranslation } from 'react-i18next'; import { useHistory } from 'react-router-dom'; -import { useWallet, useApproval, useWalletRequest, getUiType } from 'ui/utils'; - -import './style.less'; +import { + useWallet, + useApproval, + useWalletRequest, + getUiType, + openInternalPageInTab, +} from 'ui/utils'; +import { ReactComponent as RabbySVG } from '@/ui/assets/unlock/rabby.svg'; +import { ReactComponent as BackgroundSVG } from '@/ui/assets/unlock/background.svg'; +import clsx from 'clsx'; const Unlock = () => { const wallet = useWallet(); @@ -15,6 +22,7 @@ const Unlock = () => { const { t } = useTranslation(); const history = useHistory(); const isUnlockingRef = useRef(false); + const [hasForgotPassword, setHasForgotPassword] = React.useState(false); useEffect(() => { if (!inputEl.current) return; @@ -47,19 +55,39 @@ const Unlock = () => { isUnlockingRef.current = false; }; + useEffect(() => { + wallet.hasUnencryptedKeyringData().then(setHasForgotPassword); + }, []); + return ( -
-
- +
+ +
+ +

+ {t('page.unlock.title')} +

+

+ {t('page.unlock.description')} +

-
+ { > - + + +
+ {hasForgotPassword && ( + + )} +
); }; diff --git a/src/ui/views/Unlock/style.less b/src/ui/views/Unlock/style.less deleted file mode 100644 index fd9332bcecc..00000000000 --- a/src/ui/views/Unlock/style.less +++ /dev/null @@ -1,33 +0,0 @@ -.unlock { - height: 100vh; - display: flex; - flex-direction: column; - overflow: hidden; - .header { - height: 400px; - width: 100%; - background: linear-gradient(101.58deg, #8bb2ff 1.04%, #7a7cff 90.78%); - background-size: 100%; - position: relative; - .image { - position: absolute; - width: 337px; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - } - .slogan { - position: absolute; - bottom: 42px; - color: white; - text-align: center; - width: 100%; - } - } - - .ant-input { - border-radius: 6px; - border: 1px solid var(--r-neutral-line, #D3D8E0); - background: var(--r-neutral-card-2, #F2F4F7); - } -} diff --git a/src/ui/views/index.tsx b/src/ui/views/index.tsx index 263d919abc3..1caee9d0bfe 100644 --- a/src/ui/views/index.tsx +++ b/src/ui/views/index.tsx @@ -18,6 +18,7 @@ import { useMount } from 'react-use'; import { useMemoizedFn } from 'ahooks'; import { useThemeModeOnMain } from '../hooks/usePreference'; import { useSubscribeCurrentAccountChanged } from '../hooks/backgroundState/useAccount'; +import { ForgotPassword } from './ForgotPassword/ForgotPassword'; const AsyncMainRoute = lazy(() => import('./MainRoute')); const useAutoLock = () => { @@ -76,6 +77,10 @@ const Main = () => { + + + + From 8169f95065f683c3adef2eec74651dd1e8302c30 Mon Sep 17 00:00:00 2001 From: heisenberg Date: Thu, 26 Dec 2024 10:42:17 +0900 Subject: [PATCH 04/13] feat: init ui --- _raw/locales/en/messages.json | 29 +++++ src/background/controller/wallet.ts | 6 + src/background/service/keyring/index.ts | 19 ++- src/ui/assets/forgot/lock.svg | 5 + src/ui/assets/forgot/recycle.svg | 35 +++++ src/ui/assets/forgot/time-cc.svg | 12 ++ src/ui/assets/forgot/trash-cc.svg | 14 ++ src/ui/assets/new-user-import/background.svg | 39 ++++++ src/ui/component/NewUserImport/index.tsx | 10 +- src/ui/views/ForgotPassword/CommonEntry.tsx | 53 ++++++++ .../views/ForgotPassword/ForgotPassword.tsx | 93 ++++++++++++- src/ui/views/ForgotPassword/ResetConfirm.tsx | 122 ++++++++++++++++++ src/ui/views/ForgotPassword/ResetTip.tsx | 53 ++++++++ src/ui/views/NewUserImport/Guide.tsx | 16 ++- src/ui/views/NewUserImport/PasswordCard.tsx | 17 ++- src/ui/views/Unlock/index.tsx | 2 +- 16 files changed, 507 insertions(+), 18 deletions(-) create mode 100644 src/ui/assets/forgot/lock.svg create mode 100644 src/ui/assets/forgot/recycle.svg create mode 100644 src/ui/assets/forgot/time-cc.svg create mode 100644 src/ui/assets/forgot/trash-cc.svg create mode 100644 src/ui/assets/new-user-import/background.svg create mode 100644 src/ui/views/ForgotPassword/CommonEntry.tsx create mode 100644 src/ui/views/ForgotPassword/ResetConfirm.tsx create mode 100644 src/ui/views/ForgotPassword/ResetTip.tsx diff --git a/_raw/locales/en/messages.json b/_raw/locales/en/messages.json index f7474053c1b..78dcdddf877 100644 --- a/_raw/locales/en/messages.json +++ b/_raw/locales/en/messages.json @@ -2441,6 +2441,35 @@ "placeholder": "Input safe address", "loading": "Searching the deployed chain of this address" } + }, + "forgotPassword": { + "home": { + "title": "Forgot Password", + "description": "Rabby不会保存你的密码,因此丢失密码无法找回 如果忘记密码只能重置钱包并重新设置密码", + "button": "开始重置流程" + }, + "reset": { + "title": "Reset Rabby Wallet", + "button": "Confirm Reset", + "alert": { + "title": "重置后会清除以下数据,且无法帮你找回", + "seed": "助记词", + "privateKey": "私钥" + }, + "tip": { + "title": "会保留以下数据", + "hardware": "已导入的 硬件钱包/Safe/观察地址", + "whitelist": "转账白名单", + "alias": "地址备注", + "records": "签名记录" + }, + "confirm": "如确认重置钱包, 请输入:" + }, + "tip": { + "title": "Rabby Wallet 已经重置", + "description": "请设定一个新的密码继续使用钱包", + "button": "设置新密码" + } } }, "component": { diff --git a/src/background/controller/wallet.ts b/src/background/controller/wallet.ts index 4bc7438e98d..dd78009544b 100644 --- a/src/background/controller/wallet.ts +++ b/src/background/controller/wallet.ts @@ -4981,6 +4981,12 @@ export class WalletController extends BaseController { }); }; + savedUnencryptedKeyringData = async () => + keyringService.savedUnencryptedKeyringData(); + + hasEncryptedKeyringData = async () => + keyringService.hasEncryptedKeyringData(); + hasUnencryptedKeyringData = async () => keyringService.hasUnencryptedKeyringData(); } diff --git a/src/background/service/keyring/index.ts b/src/background/service/keyring/index.ts index 67fa994e1f6..b6ca10c877e 100644 --- a/src/background/service/keyring/index.ts +++ b/src/background/service/keyring/index.ts @@ -1265,15 +1265,26 @@ export class KeyringService extends EventEmitter { return this.memStore.getState().isUnlocked; } - // ledger, trezor, etc hardware wallet data is unencrypted - hasUnencryptedKeyringData(): boolean { - return !!this.store.getState().unencryptedKeyringData; + /** + * unencryptedKeyringData is saved in the store + */ + savedUnencryptedKeyringData(): boolean { + return 'unencryptedKeyringData' in this.store.getState(); } - // private key and mnemonic data is encrypted + /** + * has seed phrase or private key in the store + */ hasEncryptedKeyringData(): boolean { return this.store.getState().hasEncryptedKeyringData; } + + /** + * has unencrypted keyring data (not seed phrase or private key) in the store + */ + hasUnencryptedKeyringData(): boolean { + return this.store.getState().unencryptedKeyringData?.length > 0; + } } export default new KeyringService(); diff --git a/src/ui/assets/forgot/lock.svg b/src/ui/assets/forgot/lock.svg new file mode 100644 index 00000000000..7bf6acfd430 --- /dev/null +++ b/src/ui/assets/forgot/lock.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/ui/assets/forgot/recycle.svg b/src/ui/assets/forgot/recycle.svg new file mode 100644 index 00000000000..ab86aa58891 --- /dev/null +++ b/src/ui/assets/forgot/recycle.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ui/assets/forgot/time-cc.svg b/src/ui/assets/forgot/time-cc.svg new file mode 100644 index 00000000000..931db09d3f0 --- /dev/null +++ b/src/ui/assets/forgot/time-cc.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/ui/assets/forgot/trash-cc.svg b/src/ui/assets/forgot/trash-cc.svg new file mode 100644 index 00000000000..c8eb35af591 --- /dev/null +++ b/src/ui/assets/forgot/trash-cc.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/ui/assets/new-user-import/background.svg b/src/ui/assets/new-user-import/background.svg new file mode 100644 index 00000000000..f88b16dc3c9 --- /dev/null +++ b/src/ui/assets/new-user-import/background.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ui/component/NewUserImport/index.tsx b/src/ui/component/NewUserImport/index.tsx index 27fdd9c4e92..9af17792019 100644 --- a/src/ui/component/NewUserImport/index.tsx +++ b/src/ui/component/NewUserImport/index.tsx @@ -17,7 +17,7 @@ const StyledCard = styled.div` width: 400px; min-height: 520px; border-radius: 16px; - background: var(--r-neutral-bg1, #fff); + background-color: var(--r-neutral-bg1, #fff); box-shadow: 0px 40px 80px 0px rgba(43, 57, 143, 0.4); padding: 20px; padding-top: 0px; @@ -85,19 +85,23 @@ export const Card = ({ onBack, className, headerClassName, + headerBlock, + cardStyle, }: React.PropsWithChildren<{ title?: React.ReactNode; step?: 1 | 2; onBack?: () => void; className?: string; headerClassName?: string; + headerBlock?: boolean; + cardStyle?: React.CSSProperties; }>) => { return ( - +
void; +}> = ({ hasStep = false, onNext }) => { + const { t } = useTranslation(); + + return ( + +
+
+ +
+

+ {t('page.forgotPassword.home.title')} +

+

+ {t('page.forgotPassword.home.description')} +

+
+ +
+
+
+ ); +}; diff --git a/src/ui/views/ForgotPassword/ForgotPassword.tsx b/src/ui/views/ForgotPassword/ForgotPassword.tsx index 02d96931729..2a5ae8ab6df 100644 --- a/src/ui/views/ForgotPassword/ForgotPassword.tsx +++ b/src/ui/views/ForgotPassword/ForgotPassword.tsx @@ -1,15 +1,102 @@ import React from 'react'; import Browser from 'webextension-polyfill'; +import { useWallet } from '@/ui/utils'; +import { CommonEntry } from './CommonEntry'; +import { ResetConfirm } from './ResetConfirm'; +import { PasswordCard } from '../NewUserImport/PasswordCard'; +import { ResetTip } from './ResetTip'; +import { useHistory } from 'react-router-dom'; export const ForgotPassword = () => { + const history = useHistory(); + const wallet = useWallet(); + // seed phrase, private key, etc. + const [hasEncryptedKeyringData, setHasEncryptedKeyringData] = React.useState( + false + ); + // hardware wallet, watch address, etc. + const [ + hasUnencryptedKeyringData, + setHasUnencryptedKeyringData, + ] = React.useState(false); + const [step, setStep] = React.useState< + 'entry' | 'reset-confirm' | 'reset-tip' | 'reset-password' + >('entry'); + const [prevStep, setPrevStep] = React.useState(step); + + const handleSetStep = React.useCallback( + (newStep: typeof step) => { + setPrevStep(step); + setStep(newStep); + }, + [step] + ); + + const handleBack = React.useCallback(() => { + handleSetStep(prevStep); + }, [handleSetStep, prevStep]); + const onEntryNext = React.useCallback(() => { + if (hasEncryptedKeyringData) { + handleSetStep('reset-confirm'); + } else { + handleSetStep('reset-password'); + } + }, [hasEncryptedKeyringData, handleSetStep]); + const onResetConfirmNext = React.useCallback(() => { + handleSetStep('reset-tip'); + }, [handleSetStep]); + const onRestTipNext = React.useCallback(() => { + if (hasUnencryptedKeyringData) { + handleSetStep('reset-password'); + } else { + history.push('/new-user/guide'); + } + }, [handleSetStep, hasUnencryptedKeyringData]); + const onPasswordSubmit = React.useCallback( + async (password: string) => { + // TODO: handle password submit + console.log('password', password); + }, + [handleSetStep] + ); + // This useEffect is used to close the window when the extension icon is clicked React.useEffect(() => { - Browser.runtime.onMessage.addListener((request) => { + const handleWindowClose = (request: any) => { if (request.type === 'pageOpened') { window.close(); } - }); + }; + Browser.runtime.onMessage.addListener(handleWindowClose); + + return () => { + Browser.runtime.onMessage.removeListener(handleWindowClose); + }; + }, []); + + React.useEffect(() => { + wallet.hasEncryptedKeyringData().then(setHasEncryptedKeyringData); + wallet.hasUnencryptedKeyringData().then(setHasUnencryptedKeyringData); }, []); - return
Forgot Password
; + return ( + <> + {step === 'entry' && ( + + )} + {step === 'reset-confirm' && ( + + )} + {step === 'reset-password' && ( + + )} + {step === 'reset-tip' && ( + + )} + + ); }; diff --git a/src/ui/views/ForgotPassword/ResetConfirm.tsx b/src/ui/views/ForgotPassword/ResetConfirm.tsx new file mode 100644 index 00000000000..a8f6479cbe9 --- /dev/null +++ b/src/ui/views/ForgotPassword/ResetConfirm.tsx @@ -0,0 +1,122 @@ +import { Card } from '@/ui/component/NewUserImport'; +import React from 'react'; +import { ReactComponent as TrashSVG } from '@/ui/assets/forgot/trash-cc.svg'; +import { ReactComponent as TimeSVG } from '@/ui/assets/forgot/time-cc.svg'; +import { useTranslation } from 'react-i18next'; +import { Button, Input } from 'antd'; +import clsx from 'clsx'; + +export const ResetConfirm: React.FC<{ + onConfirm: () => void; + onBack: () => void; +}> = ({ onConfirm, onBack }) => { + const { t } = useTranslation(); + const [disabled, setDisabled] = React.useState(true); + const [input, setInput] = React.useState(''); + + return ( + +
+
+ +

+ {t('page.forgotPassword.reset.alert.title')} +

+
+
    + {[ + t('page.forgotPassword.reset.alert.seed'), + t('page.forgotPassword.reset.alert.privateKey'), + ].map((text, index) => ( +
  • + {text} +
  • + ))} +
+
+ +
+
+ +

+ {t('page.forgotPassword.reset.tip.title')} +

+
+
    + {[ + t('page.forgotPassword.reset.tip.hardware'), + t('page.forgotPassword.reset.tip.whitelist'), + t('page.forgotPassword.reset.tip.alias'), + t('page.forgotPassword.reset.tip.records'), + ].map((text, index) => ( +
  • + {text} +
  • + ))} +
+
+ +
+ {t('page.forgotPassword.reset.confirm')} + RESET +
+ +
+ { + setInput(e.target.value); + setDisabled(e.target.value !== 'RESET'); + }} + value={input} + placeholder="RESET" + className={clsx( + 'h-[52px] rounded-[8px]', + 'border-rabby-neutral-line bg-r-neutral-bg1 hover:border-rabby-blue-default focus:border-rabby-blue-default', + 'text-r-neutral-foot text-15' + )} + size="large" + /> +
+ +
+ +
+
+ ); +}; diff --git a/src/ui/views/ForgotPassword/ResetTip.tsx b/src/ui/views/ForgotPassword/ResetTip.tsx new file mode 100644 index 00000000000..1129aaab87f --- /dev/null +++ b/src/ui/views/ForgotPassword/ResetTip.tsx @@ -0,0 +1,53 @@ +import { Card } from '@/ui/component/NewUserImport'; +import React from 'react'; +import { ReactComponent as RecycleSVG } from '@/ui/assets/forgot/recycle.svg'; +import { useTranslation } from 'react-i18next'; +import { Button } from 'antd'; +import clsx from 'clsx'; + +export const ResetTip: React.FC<{ + hasStep: boolean; + onNext: () => void; +}> = ({ hasStep = false, onNext }) => { + const { t } = useTranslation(); + + return ( + +
+
+ +
+

+ {t('page.forgotPassword.tip.title')} +

+

+ {t('page.forgotPassword.tip.description')} +

+
+ +
+
+
+ ); +}; diff --git a/src/ui/views/NewUserImport/Guide.tsx b/src/ui/views/NewUserImport/Guide.tsx index e77e3b4b217..d7960732bde 100644 --- a/src/ui/views/NewUserImport/Guide.tsx +++ b/src/ui/views/NewUserImport/Guide.tsx @@ -5,6 +5,8 @@ import { Button } from 'antd'; import clsx from 'clsx'; import { useHistory } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; +import BackgroundSVG from '@/ui/assets/new-user-import/background.svg'; +import { useThemeMode } from '@/ui/hooks/usePreference'; export const Guide = () => { const { t } = useTranslation(); @@ -18,8 +20,20 @@ export const Guide = () => { history.push('/new-user/import-list'); }, []); + const { isDarkTheme } = useThemeMode(); + return ( - +
= ({ onSubmit, step, onBack }) => { ]} > = ({ onSubmit, step, onBack }) => { ]} > { }; useEffect(() => { - wallet.hasUnencryptedKeyringData().then(setHasForgotPassword); + wallet.savedUnencryptedKeyringData().then(setHasForgotPassword); }, []); return ( From 3cc6760059aaaa3ed316324783ab774fc40ad280 Mon Sep 17 00:00:00 2001 From: heisenberg Date: Thu, 26 Dec 2024 11:58:44 +0900 Subject: [PATCH 05/13] feat: ui --- _raw/locales/en/messages.json | 5 ++ src/background/controller/wallet.ts | 5 ++ src/background/service/keyring/index.ts | 22 +++++++ src/ui/assets/forgot/lock-success.svg | 5 ++ .../ForgotPassword/CommonConfirmCard.tsx | 60 +++++++++++++++++++ src/ui/views/ForgotPassword/CommonEntry.tsx | 50 ++++------------ .../views/ForgotPassword/ForgotPassword.tsx | 28 +++++++-- src/ui/views/ForgotPassword/ResetSuccess.tsx | 21 +++++++ src/ui/views/ForgotPassword/ResetTip.tsx | 49 +++------------ 9 files changed, 159 insertions(+), 86 deletions(-) create mode 100644 src/ui/assets/forgot/lock-success.svg create mode 100644 src/ui/views/ForgotPassword/CommonConfirmCard.tsx create mode 100644 src/ui/views/ForgotPassword/ResetSuccess.tsx diff --git a/_raw/locales/en/messages.json b/_raw/locales/en/messages.json index 78dcdddf877..cb345ae48be 100644 --- a/_raw/locales/en/messages.json +++ b/_raw/locales/en/messages.json @@ -2469,6 +2469,11 @@ "title": "Rabby Wallet 已经重置", "description": "请设定一个新的密码继续使用钱包", "button": "设置新密码" + }, + "success": { + "title": "密码创建成功", + "description": "请继续使用Rabby", + "button": "Done" } } }, diff --git a/src/background/controller/wallet.ts b/src/background/controller/wallet.ts index dd78009544b..e38080b2f05 100644 --- a/src/background/controller/wallet.ts +++ b/src/background/controller/wallet.ts @@ -4989,6 +4989,11 @@ export class WalletController extends BaseController { hasUnencryptedKeyringData = async () => keyringService.hasUnencryptedKeyringData(); + + resetPassword = async (password: string) => + keyringService.resetPassword(password); + + resetBooted = async () => keyringService.resetBooted(); } const wallet = new WalletController(); diff --git a/src/background/service/keyring/index.ts b/src/background/service/keyring/index.ts index b6ca10c877e..6a0ec73ca53 100644 --- a/src/background/service/keyring/index.ts +++ b/src/background/service/keyring/index.ts @@ -1285,6 +1285,28 @@ export class KeyringService extends EventEmitter { hasUnencryptedKeyringData(): boolean { return this.store.getState().unencryptedKeyringData?.length > 0; } + + async resetPassword(password: string) { + // update vault and booted with new password + const unencryptedKeyringData = this.store.getState().unencryptedKeyringData; + const booted = await passwordEncrypt({ + data: 'true', + password, + }); + const vault = await passwordEncrypt({ + data: unencryptedKeyringData, + password, + }); + + this.store.updateState({ vault, booted, hasEncryptedKeyringData: false }); + + // lock wallet + this.setLocked(); + } + + async resetBooted() { + this.store.updateState({ booted: undefined }); + } } export default new KeyringService(); diff --git a/src/ui/assets/forgot/lock-success.svg b/src/ui/assets/forgot/lock-success.svg new file mode 100644 index 00000000000..357fe19e063 --- /dev/null +++ b/src/ui/assets/forgot/lock-success.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/ui/views/ForgotPassword/CommonConfirmCard.tsx b/src/ui/views/ForgotPassword/CommonConfirmCard.tsx new file mode 100644 index 00000000000..d147eb68a8a --- /dev/null +++ b/src/ui/views/ForgotPassword/CommonConfirmCard.tsx @@ -0,0 +1,60 @@ +import { Card } from '@/ui/component/NewUserImport'; +import React from 'react'; +import { Button } from 'antd'; +import clsx from 'clsx'; + +export const CommonConfirmCard: React.FC<{ + hasStep?: boolean; + onNext: () => void; + logoClassName?: string; + logo?: React.ReactNode; + titleText?: string; + descriptionText?: string; + buttonText?: string; +}> = ({ + hasStep = false, + onNext, + logoClassName, + logo, + titleText, + descriptionText, + buttonText, +}) => { + return ( + +
+
{logo}
+

+ {titleText} +

+

+ {descriptionText} +

+
+ +
+
+
+ ); +}; diff --git a/src/ui/views/ForgotPassword/CommonEntry.tsx b/src/ui/views/ForgotPassword/CommonEntry.tsx index af59095d816..0078e07c3d8 100644 --- a/src/ui/views/ForgotPassword/CommonEntry.tsx +++ b/src/ui/views/ForgotPassword/CommonEntry.tsx @@ -1,9 +1,7 @@ -import { Card } from '@/ui/component/NewUserImport'; import React from 'react'; import { ReactComponent as LockSVG } from '@/ui/assets/forgot/lock.svg'; import { useTranslation } from 'react-i18next'; -import { Button } from 'antd'; -import clsx from 'clsx'; +import { CommonConfirmCard } from './CommonConfirmCard'; export const CommonEntry: React.FC<{ hasStep: boolean; @@ -12,42 +10,14 @@ export const CommonEntry: React.FC<{ const { t } = useTranslation(); return ( - -
-
- -
-

- {t('page.forgotPassword.home.title')} -

-

- {t('page.forgotPassword.home.description')} -

-
- -
-
-
+ } + logoClassName="p-16 rounded-full bg-r-neutral-card2" + titleText={t('page.forgotPassword.home.title')} + descriptionText={t('page.forgotPassword.home.description')} + /> ); }; diff --git a/src/ui/views/ForgotPassword/ForgotPassword.tsx b/src/ui/views/ForgotPassword/ForgotPassword.tsx index 2a5ae8ab6df..d0ae1a0bb2f 100644 --- a/src/ui/views/ForgotPassword/ForgotPassword.tsx +++ b/src/ui/views/ForgotPassword/ForgotPassword.tsx @@ -6,6 +6,8 @@ import { ResetConfirm } from './ResetConfirm'; import { PasswordCard } from '../NewUserImport/PasswordCard'; import { ResetTip } from './ResetTip'; import { useHistory } from 'react-router-dom'; +import { ResetSuccess } from './ResetSuccess'; +import { message } from 'antd'; export const ForgotPassword = () => { const history = useHistory(); @@ -20,7 +22,7 @@ export const ForgotPassword = () => { setHasUnencryptedKeyringData, ] = React.useState(false); const [step, setStep] = React.useState< - 'entry' | 'reset-confirm' | 'reset-tip' | 'reset-password' + 'entry' | 'reset-confirm' | 'reset-tip' | 'reset-password' | 'reset-success' >('entry'); const [prevStep, setPrevStep] = React.useState(step); @@ -42,23 +44,34 @@ export const ForgotPassword = () => { handleSetStep('reset-password'); } }, [hasEncryptedKeyringData, handleSetStep]); - const onResetConfirmNext = React.useCallback(() => { + const onResetConfirmNext = React.useCallback(async () => { + // If there is no unencrypted keyring data, reset the booted status + if (!hasUnencryptedKeyringData) { + await wallet.resetBooted(); + } handleSetStep('reset-tip'); - }, [handleSetStep]); + }, [hasUnencryptedKeyringData, handleSetStep]); const onRestTipNext = React.useCallback(() => { if (hasUnencryptedKeyringData) { handleSetStep('reset-password'); } else { - history.push('/new-user/guide'); + wallet.tryOpenOrActiveUserGuide(); } }, [handleSetStep, hasUnencryptedKeyringData]); const onPasswordSubmit = React.useCallback( async (password: string) => { - // TODO: handle password submit - console.log('password', password); + try { + await wallet.resetPassword(password); + handleSetStep('reset-success'); + } catch (e) { + message.error(e.message); + } }, [handleSetStep] ); + const onResultSuccessNext = React.useCallback(() => { + window.close(); + }, []); // This useEffect is used to close the window when the extension icon is clicked React.useEffect(() => { @@ -97,6 +110,9 @@ export const ForgotPassword = () => { {step === 'reset-tip' && ( )} + {step === 'reset-success' && ( + + )} ); }; diff --git a/src/ui/views/ForgotPassword/ResetSuccess.tsx b/src/ui/views/ForgotPassword/ResetSuccess.tsx new file mode 100644 index 00000000000..d7ea948ca35 --- /dev/null +++ b/src/ui/views/ForgotPassword/ResetSuccess.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { ReactComponent as LockSVG } from '@/ui/assets/forgot/lock-success.svg'; +import { useTranslation } from 'react-i18next'; +import { CommonConfirmCard } from './CommonConfirmCard'; + +export const ResetSuccess: React.FC<{ + onNext: () => void; +}> = ({ onNext }) => { + const { t } = useTranslation(); + + return ( + } + logoClassName="p-16 rounded-full bg-r-green-light" + titleText={t('page.forgotPassword.success.title')} + descriptionText={t('page.forgotPassword.success.description')} + buttonText={t('page.forgotPassword.success.button')} + /> + ); +}; diff --git a/src/ui/views/ForgotPassword/ResetTip.tsx b/src/ui/views/ForgotPassword/ResetTip.tsx index 1129aaab87f..21f75ab9bb5 100644 --- a/src/ui/views/ForgotPassword/ResetTip.tsx +++ b/src/ui/views/ForgotPassword/ResetTip.tsx @@ -1,9 +1,7 @@ -import { Card } from '@/ui/component/NewUserImport'; import React from 'react'; import { ReactComponent as RecycleSVG } from '@/ui/assets/forgot/recycle.svg'; import { useTranslation } from 'react-i18next'; -import { Button } from 'antd'; -import clsx from 'clsx'; +import { CommonConfirmCard } from './CommonConfirmCard'; export const ResetTip: React.FC<{ hasStep: boolean; @@ -12,42 +10,13 @@ export const ResetTip: React.FC<{ const { t } = useTranslation(); return ( - -
-
- -
-

- {t('page.forgotPassword.tip.title')} -

-

- {t('page.forgotPassword.tip.description')} -

-
- -
-
-
+ } + titleText={t('page.forgotPassword.tip.title')} + descriptionText={t('page.forgotPassword.tip.description')} + /> ); }; From e26f363afe3da0e4e5040193d5e6597d6f02f664 Mon Sep 17 00:00:00 2001 From: heisenberg Date: Thu, 26 Dec 2024 12:41:08 +0900 Subject: [PATCH 06/13] fix: reset tip --- _raw/locales/en/messages.json | 4 +++- src/ui/views/ForgotPassword/ForgotPassword.tsx | 6 +++++- src/ui/views/ForgotPassword/ResetTip.tsx | 18 +++++++++++++----- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/_raw/locales/en/messages.json b/_raw/locales/en/messages.json index cb345ae48be..34b692267aa 100644 --- a/_raw/locales/en/messages.json +++ b/_raw/locales/en/messages.json @@ -2468,7 +2468,9 @@ "tip": { "title": "Rabby Wallet 已经重置", "description": "请设定一个新的密码继续使用钱包", - "button": "设置新密码" + "button": "设置新密码", + "descriptionNoData": "请重新导入地址后使用钱包", + "buttonNoData": "重新导入地址" }, "success": { "title": "密码创建成功", diff --git a/src/ui/views/ForgotPassword/ForgotPassword.tsx b/src/ui/views/ForgotPassword/ForgotPassword.tsx index d0ae1a0bb2f..043b15fe748 100644 --- a/src/ui/views/ForgotPassword/ForgotPassword.tsx +++ b/src/ui/views/ForgotPassword/ForgotPassword.tsx @@ -75,6 +75,7 @@ export const ForgotPassword = () => { // This useEffect is used to close the window when the extension icon is clicked React.useEffect(() => { + wallet.tryOpenOrActiveUserGuide(); const handleWindowClose = (request: any) => { if (request.type === 'pageOpened') { window.close(); @@ -108,7 +109,10 @@ export const ForgotPassword = () => { /> )} {step === 'reset-tip' && ( - + )} {step === 'reset-success' && ( diff --git a/src/ui/views/ForgotPassword/ResetTip.tsx b/src/ui/views/ForgotPassword/ResetTip.tsx index 21f75ab9bb5..5268e7dbc97 100644 --- a/src/ui/views/ForgotPassword/ResetTip.tsx +++ b/src/ui/views/ForgotPassword/ResetTip.tsx @@ -4,19 +4,27 @@ import { useTranslation } from 'react-i18next'; import { CommonConfirmCard } from './CommonConfirmCard'; export const ResetTip: React.FC<{ - hasStep: boolean; + hasUnencryptedKeyringData: boolean; onNext: () => void; -}> = ({ hasStep = false, onNext }) => { +}> = ({ hasUnencryptedKeyringData = false, onNext }) => { const { t } = useTranslation(); return ( } titleText={t('page.forgotPassword.tip.title')} - descriptionText={t('page.forgotPassword.tip.description')} + descriptionText={ + hasUnencryptedKeyringData + ? t('page.forgotPassword.tip.description') + : t('page.forgotPassword.tip.descriptionNoData') + } /> ); }; From 46cd680cde515717ab20dd4e176e648d941e2437 Mon Sep 17 00:00:00 2001 From: heisenberg Date: Thu, 26 Dec 2024 14:44:47 +0900 Subject: [PATCH 07/13] chore: text --- _raw/locales/en/messages.json | 39 ++++++++++--------- _raw/locales/zh-CN/messages.json | 38 ++++++++++++++++++ src/ui/views/ForgotPassword/CommonEntry.tsx | 18 ++++++--- .../views/ForgotPassword/ForgotPassword.tsx | 5 ++- src/ui/views/ForgotPassword/ResetConfirm.tsx | 12 ++++-- 5 files changed, 84 insertions(+), 28 deletions(-) diff --git a/_raw/locales/en/messages.json b/_raw/locales/en/messages.json index 34b692267aa..b257a241092 100644 --- a/_raw/locales/en/messages.json +++ b/_raw/locales/en/messages.json @@ -2445,36 +2445,39 @@ "forgotPassword": { "home": { "title": "Forgot Password", - "description": "Rabby不会保存你的密码,因此丢失密码无法找回 如果忘记密码只能重置钱包并重新设置密码", - "button": "开始重置流程" + "description": "Rabby Wallet doesn't store your password and can't help you retrieve it. Reset your wallet to set up a new one.", + "button": "Begin Reset Process", + "descriptionNoData": "Rabby Wallet doesn't store your password and can't help you retrieve it. Set a new password if you forgot", + "buttonNoData": "Set Password" }, "reset": { "title": "Reset Rabby Wallet", "button": "Confirm Reset", "alert": { - "title": "重置后会清除以下数据,且无法帮你找回", - "seed": "助记词", - "privateKey": "私钥" + "title": "Data will be deleted and unrecoverable:", + "seed": "Seed Phrase", + "privateKey": "Private Key" }, "tip": { - "title": "会保留以下数据", - "hardware": "已导入的 硬件钱包/Safe/观察地址", - "whitelist": "转账白名单", - "alias": "地址备注", - "records": "签名记录" + "title": "Data will be kept:", + "hardware": "Imported Hardware Wallets", + "whitelist": "Whitelist Settings", + "records": "Signature Records", + "safe": "Imported Safe Wallets", + "watch": "Contacts and Watch-Only Addresses" }, - "confirm": "如确认重置钱包, 请输入:" + "confirm": "Type <1>RESET in the box to confirm and proceed" }, "tip": { - "title": "Rabby Wallet 已经重置", - "description": "请设定一个新的密码继续使用钱包", - "button": "设置新密码", - "descriptionNoData": "请重新导入地址后使用钱包", - "buttonNoData": "重新导入地址" + "title": "Rabby Wallet Reset Completed", + "description": "Create a new password to continue", + "button": "Set Password", + "descriptionNoData": "Add your address to get started", + "buttonNoData": "Add Address" }, "success": { - "title": "密码创建成功", - "description": "请继续使用Rabby", + "title": "Password Successfully Set", + "description": "You're all set to use Rabby Wallet", "button": "Done" } } diff --git a/_raw/locales/zh-CN/messages.json b/_raw/locales/zh-CN/messages.json index 404349bd001..9ba5efd256e 100644 --- a/_raw/locales/zh-CN/messages.json +++ b/_raw/locales/zh-CN/messages.json @@ -2038,6 +2038,44 @@ }, "sign": { "transactionSpeed": "交易速度" + }, + "forgotPassword": { + "home": { + "buttonNoData": "设置新密码", + "button": "开始重置流程", + "title": "忘记密码", + "description": "Rabby不会保存你的密码,因此丢失密码无法找回\n如果忘记密码只能重置钱包并重新设置密码", + "descriptionNoData": "Rabby不会保存你的密码,因此丢失密码无法找回\n如果忘记密码只能重新设置密码" + }, + "reset": { + "title": "重置 Rabby Wallet", + "alert": { + "title": "重置后会清除以下数据,且无法帮你找回", + "seed": "助记词", + "privateKey": "私钥" + }, + "tip": { + "title": "会保留以下数据", + "hardware": "已导入的硬件钱包地址", + "safe": "已导入的 Safe 地址", + "watch": "已导入的观察地址", + "whitelist": "转账白名单", + "records": "签名记录" + }, + "confirm": "如确认重置钱包, 请输入:<1>RESET" + }, + "success": { + "title": "密码创建成功", + "description": "请继续使用 Rabby", + "button": "完成" + }, + "tip": { + "title": "Rabby Wallet 已经重置", + "button": "设置新密码", + "buttonNoData": "重新导入地址", + "description": "请设定一个新的密码继续使用钱包", + "descriptionNoData": "请重新导入地址后使用钱包" + } } }, "component": { diff --git a/src/ui/views/ForgotPassword/CommonEntry.tsx b/src/ui/views/ForgotPassword/CommonEntry.tsx index 0078e07c3d8..6d9caabbb98 100644 --- a/src/ui/views/ForgotPassword/CommonEntry.tsx +++ b/src/ui/views/ForgotPassword/CommonEntry.tsx @@ -4,20 +4,28 @@ import { useTranslation } from 'react-i18next'; import { CommonConfirmCard } from './CommonConfirmCard'; export const CommonEntry: React.FC<{ - hasStep: boolean; + hasEncryptedKeyringData: boolean; onNext: () => void; -}> = ({ hasStep = false, onNext }) => { +}> = ({ hasEncryptedKeyringData = false, onNext }) => { const { t } = useTranslation(); return ( } logoClassName="p-16 rounded-full bg-r-neutral-card2" titleText={t('page.forgotPassword.home.title')} - descriptionText={t('page.forgotPassword.home.description')} + descriptionText={ + hasEncryptedKeyringData + ? t('page.forgotPassword.home.description') + : t('page.forgotPassword.home.descriptionNoData') + } /> ); }; diff --git a/src/ui/views/ForgotPassword/ForgotPassword.tsx b/src/ui/views/ForgotPassword/ForgotPassword.tsx index 043b15fe748..ff7da48a4d8 100644 --- a/src/ui/views/ForgotPassword/ForgotPassword.tsx +++ b/src/ui/views/ForgotPassword/ForgotPassword.tsx @@ -96,7 +96,10 @@ export const ForgotPassword = () => { return ( <> {step === 'entry' && ( - + )} {step === 'reset-confirm' && ( diff --git a/src/ui/views/ForgotPassword/ResetConfirm.tsx b/src/ui/views/ForgotPassword/ResetConfirm.tsx index a8f6479cbe9..3c74b4e0596 100644 --- a/src/ui/views/ForgotPassword/ResetConfirm.tsx +++ b/src/ui/views/ForgotPassword/ResetConfirm.tsx @@ -2,7 +2,7 @@ import { Card } from '@/ui/component/NewUserImport'; import React from 'react'; import { ReactComponent as TrashSVG } from '@/ui/assets/forgot/trash-cc.svg'; import { ReactComponent as TimeSVG } from '@/ui/assets/forgot/time-cc.svg'; -import { useTranslation } from 'react-i18next'; +import { Trans, useTranslation } from 'react-i18next'; import { Button, Input } from 'antd'; import clsx from 'clsx'; @@ -55,8 +55,9 @@ export const ResetConfirm: React.FC<{
    {[ t('page.forgotPassword.reset.tip.hardware'), + t('page.forgotPassword.reset.tip.safe'), + t('page.forgotPassword.reset.tip.watch'), t('page.forgotPassword.reset.tip.whitelist'), - t('page.forgotPassword.reset.tip.alias'), t('page.forgotPassword.reset.tip.records'), ].map((text, index) => (
  • @@ -73,8 +74,11 @@ export const ResetConfirm: React.FC<{ 'text-center' )} > - {t('page.forgotPassword.reset.confirm')} - RESET + + Type + RESET + in the box to confirm and proceed +
From d37de397db23a4b58a2ffba4dec0c7c369ed7e1c Mon Sep 17 00:00:00 2001 From: heisenberg Date: Thu, 26 Dec 2024 14:50:49 +0900 Subject: [PATCH 08/13] fix: text --- _raw/locales/zh-CN/messages.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/_raw/locales/zh-CN/messages.json b/_raw/locales/zh-CN/messages.json index 9ba5efd256e..7d22495fad4 100644 --- a/_raw/locales/zh-CN/messages.json +++ b/_raw/locales/zh-CN/messages.json @@ -1702,7 +1702,8 @@ "error": "密码错误", "placeholder": "输入密码解锁", "required": "输入密码解锁" - } + }, + "btnForgotPassword": "忘记密码?" }, "addressDetail": { "add-to-whitelist": "添加到白名单", @@ -2062,7 +2063,8 @@ "whitelist": "转账白名单", "records": "签名记录" }, - "confirm": "如确认重置钱包, 请输入:<1>RESET" + "confirm": "如确认重置钱包, 请输入: <1>RESET", + "button": "确认重置" }, "success": { "title": "密码创建成功", From 1be9669531f7d61947f0f5c261577d07648b6628 Mon Sep 17 00:00:00 2001 From: heisenberg Date: Thu, 26 Dec 2024 15:06:26 +0900 Subject: [PATCH 09/13] fix: ui --- _raw/locales/zh-CN/messages.json | 4 ++-- src/ui/views/ForgotPassword/CommonConfirmCard.tsx | 2 +- src/ui/views/ForgotPassword/ResetConfirm.tsx | 4 ++-- src/ui/views/NewUserImport/Success.tsx | 4 +++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/_raw/locales/zh-CN/messages.json b/_raw/locales/zh-CN/messages.json index 7d22495fad4..bce66fa4b9d 100644 --- a/_raw/locales/zh-CN/messages.json +++ b/_raw/locales/zh-CN/messages.json @@ -2045,8 +2045,8 @@ "buttonNoData": "设置新密码", "button": "开始重置流程", "title": "忘记密码", - "description": "Rabby不会保存你的密码,因此丢失密码无法找回\n如果忘记密码只能重置钱包并重新设置密码", - "descriptionNoData": "Rabby不会保存你的密码,因此丢失密码无法找回\n如果忘记密码只能重新设置密码" + "description": "Rabby不会保存你的密码,因此丢失密码无法找回 如果忘记密码只能重置钱包并重新设置密码", + "descriptionNoData": "Rabby不会保存你的密码,因此丢失密码无法找回 如果忘记密码只能重新设置密码" }, "reset": { "title": "重置 Rabby Wallet", diff --git a/src/ui/views/ForgotPassword/CommonConfirmCard.tsx b/src/ui/views/ForgotPassword/CommonConfirmCard.tsx index d147eb68a8a..82aaaafec5a 100644 --- a/src/ui/views/ForgotPassword/CommonConfirmCard.tsx +++ b/src/ui/views/ForgotPassword/CommonConfirmCard.tsx @@ -33,7 +33,7 @@ export const CommonConfirmCard: React.FC<{ > {titleText} -

+

{descriptionText}

@@ -92,7 +92,7 @@ export const ResetConfirm: React.FC<{ className={clsx( 'h-[52px] rounded-[8px]', 'border-rabby-neutral-line bg-r-neutral-bg1 hover:border-rabby-blue-default focus:border-rabby-blue-default', - 'text-r-neutral-foot text-15' + 'text-r-neutral-title1 text-15 placeholder-r-neutral-foot placeholder-opacity-70' )} size="large" /> diff --git a/src/ui/views/NewUserImport/Success.tsx b/src/ui/views/NewUserImport/Success.tsx index 72331ecd505..d2a1a63fb0d 100644 --- a/src/ui/views/NewUserImport/Success.tsx +++ b/src/ui/views/NewUserImport/Success.tsx @@ -94,7 +94,9 @@ const AccountItem = ({ account }: { account: Account }) => { /> ) : (
- {name} + + {name} +
)} From 4edd427c5d556a33887380f68351ae7a84944ba4 Mon Sep 17 00:00:00 2001 From: heisenberg Date: Thu, 26 Dec 2024 21:21:55 +0900 Subject: [PATCH 10/13] fix: unlock ui --- src/ui/views/Unlock/index.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ui/views/Unlock/index.tsx b/src/ui/views/Unlock/index.tsx index 80c2ab942a5..2e9f30909dc 100644 --- a/src/ui/views/Unlock/index.tsx +++ b/src/ui/views/Unlock/index.tsx @@ -12,6 +12,18 @@ import { import { ReactComponent as RabbySVG } from '@/ui/assets/unlock/rabby.svg'; import { ReactComponent as BackgroundSVG } from '@/ui/assets/unlock/background.svg'; import clsx from 'clsx'; +import styled from 'styled-components'; + +const InputFormStyled = styled(Form.Item)` + .ant-form-item-explain { + font-size: 13px; + line-height: 16px; + margin-top: 12px; + margin-bottom: 24px; + min-height: 0px; + color: var(--r-red-default); + } +`; const Unlock = () => { const wallet = useWallet(); @@ -86,7 +98,7 @@ const Unlock = () => {

- { ref={inputEl} spellCheck={false} /> - +