From 224cd0e680f38a6fe0cd105c6df484d7bf978e8e Mon Sep 17 00:00:00 2001 From: Thebora Kompanioni Date: Mon, 20 Nov 2023 19:48:23 +0100 Subject: [PATCH] ui: improve phrasing and display rescanning alert (#693) * chore: switch terms active/inactive to unlocked/locked * fix(ui): show rescanning alert on CreateWallet page * feat(ui): show rescanning alert on Wallets page --- src/components/CreateWallet.test.tsx | 16 ++++++++++ src/components/CreateWallet.tsx | 44 +++++++++++++++++++++------- src/components/ImportWallet.tsx | 4 +-- src/components/Wallet.test.tsx | 10 +++---- src/components/Wallet.tsx | 4 +-- src/components/Wallets.test.tsx | 29 ++++++++++++++---- src/components/Wallets.tsx | 5 ++++ src/i18n/locales/en/translation.json | 3 ++ 8 files changed, 89 insertions(+), 26 deletions(-) diff --git a/src/components/CreateWallet.test.tsx b/src/components/CreateWallet.test.tsx index 49c0eafe..89d1a454 100644 --- a/src/components/CreateWallet.test.tsx +++ b/src/components/CreateWallet.test.tsx @@ -41,6 +41,22 @@ describe('', () => { ;(apiMock.getSession as jest.Mock).mockResolvedValue(neverResolvingPromise) }) + it('should display alert when rescanning is active', async () => { + ;(apiMock.getSession as jest.Mock).mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + rescanning: true, + }), + }) + + await act(async () => setup({})) + + expect(screen.getByText('create_wallet.title')).toBeVisible() + expect(screen.getByTestId('alert-rescanning')).toBeVisible() + expect(screen.queryByText('create_wallet.button_create')).not.toBeInTheDocument() + }) + it('should render without errors', () => { act(() => setup({})) diff --git a/src/components/CreateWallet.tsx b/src/components/CreateWallet.tsx index 5ae21a7e..d5471efa 100644 --- a/src/components/CreateWallet.tsx +++ b/src/components/CreateWallet.tsx @@ -106,6 +106,12 @@ export default function CreateWallet({ parentRoute, startWallet }: CreateWalletP const [alert, setAlert] = useState() const [createdWallet, setCreatedWallet] = useState() + const isCreated = useMemo(() => !!createdWallet?.walletFileName && !!createdWallet?.auth, [createdWallet]) + const canCreate = useMemo( + () => !isCreated && !serviceInfo?.walletFileName && !serviceInfo?.rescanning, + [isCreated, serviceInfo], + ) + const createWallet = useCallback( async ({ walletName, password }) => { setAlert(undefined) @@ -152,17 +158,33 @@ export default function CreateWallet({ parentRoute, startWallet }: CreateWalletP )} {alert && {alert.message}} - {serviceInfo?.walletFileName && !createdWallet ? ( - - - Currently {{ walletName: walletDisplayName(serviceInfo.walletFileName) }} is active. You - need to lock it first. - - Go back - - . - - + {!canCreate && !isCreated ? ( + <> + {serviceInfo?.walletFileName && ( + + + Currently {{ walletName: walletDisplayName(serviceInfo.walletFileName) }} is active. + You need to lock it first. + + Go back + + . + + + )} + {serviceInfo?.rescanning === true && ( + + + Rescanning the timechain is currently in progress. Please wait until the process finishes and then try + again. + + Go back + + . + + + )} + ) : ( <> diff --git a/src/components/ImportWallet.tsx b/src/components/ImportWallet.tsx index 5ae94bbe..c103abf2 100644 --- a/src/components/ImportWallet.tsx +++ b/src/components/ImportWallet.tsx @@ -394,7 +394,7 @@ export default function ImportWallet({ parentRoute, startWallet }: ImportWalletP const [importDetailsFormValues, setImportDetailsFormValues] = useState() const [recoveredWallet, setRecoveredWallet] = useState() - const isRecovered = useMemo(() => !!recoveredWallet?.walletFileName && recoveredWallet?.auth, [recoveredWallet]) + const isRecovered = useMemo(() => !!recoveredWallet?.walletFileName && !!recoveredWallet?.auth, [recoveredWallet]) const canRecover = useMemo( () => !isRecovered && !serviceInfo?.walletFileName && !serviceInfo?.rescanning, [isRecovered, serviceInfo], @@ -571,7 +571,7 @@ export default function ImportWallet({ parentRoute, startWallet }: ImportWalletP )} {serviceInfo?.rescanning === true && ( - + Rescanning the timechain is currently in progress. Please wait until the process finishes and then try again. diff --git a/src/components/Wallet.test.tsx b/src/components/Wallet.test.tsx index 026d7874..22d5384f 100644 --- a/src/components/Wallet.test.tsx +++ b/src/components/Wallet.test.tsx @@ -52,7 +52,7 @@ describe('', () => { act(() => setup({ walletFileName: dummyWalletFileName })) expect(screen.getByText(walletDisplayName(dummyWalletFileName))).toBeInTheDocument() - expect(screen.getByText('wallets.wallet_preview.wallet_inactive')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_locked')).toBeInTheDocument() expect(screen.queryByPlaceholderText('wallets.wallet_preview.placeholder_password')).not.toBeInTheDocument() expect(screen.queryByText('wallets.wallet_preview.button_unlock')).not.toBeInTheDocument() expect(screen.queryByText('wallets.wallet_preview.button_open')).not.toBeInTheDocument() @@ -62,7 +62,7 @@ describe('', () => { it('should unlock inactive wallet successfully', async () => { await act(async () => setup({ walletFileName: dummyWalletFileName, unlockWallet: mockUnlockWallet })) - expect(screen.getByText('wallets.wallet_preview.wallet_inactive')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_locked')).toBeInTheDocument() expect(screen.getByText('wallets.wallet_preview.button_unlock')).toBeInTheDocument() expect(screen.getByPlaceholderText('wallets.wallet_preview.placeholder_password')).toBeInTheDocument() expect(screen.queryByText('wallets.wallet_preview.button_open')).not.toBeInTheDocument() @@ -93,7 +93,7 @@ describe('', () => { ) expect(screen.getByText(walletDisplayName(dummyWalletFileName))).toBeInTheDocument() - expect(screen.getByText('wallets.wallet_preview.wallet_active')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_unlocked')).toBeInTheDocument() expect(screen.queryByPlaceholderText('wallets.wallet_preview.placeholder_password')).toBeInTheDocument() expect(screen.queryByText('wallets.wallet_preview.button_unlock')).toBeInTheDocument() expect(screen.queryByText('wallets.wallet_preview.button_open')).not.toBeInTheDocument() @@ -110,7 +110,7 @@ describe('', () => { ) expect(screen.getByText(walletDisplayName(dummyWalletFileName))).toBeInTheDocument() - expect(screen.getByText('wallets.wallet_preview.wallet_active')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_unlocked')).toBeInTheDocument() expect(screen.getByText('wallets.wallet_preview.button_open')).toBeInTheDocument() expect(screen.getByText('wallets.wallet_preview.button_lock')).toBeInTheDocument() expect(screen.queryByPlaceholderText('wallets.wallet_preview.placeholder_password')).not.toBeInTheDocument() @@ -126,7 +126,7 @@ describe('', () => { }), ) - expect(screen.getByText('wallets.wallet_preview.wallet_active')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_unlocked')).toBeInTheDocument() expect(screen.getByText('wallets.wallet_preview.button_lock')).toBeInTheDocument() await act(async () => { diff --git a/src/components/Wallet.tsx b/src/components/Wallet.tsx index 6cf9e0b1..ebfa1f07 100644 --- a/src/components/Wallet.tsx +++ b/src/components/Wallet.tsx @@ -190,9 +190,9 @@ export default function Wallet({ {isActive ? ( - {t('wallets.wallet_preview.wallet_active')} + {t('wallets.wallet_preview.wallet_unlocked')} ) : ( - {t('wallets.wallet_preview.wallet_inactive')} + {t('wallets.wallet_preview.wallet_locked')} )} diff --git a/src/components/Wallets.test.tsx b/src/components/Wallets.test.tsx index a12c6ae9..18dfbe9c 100644 --- a/src/components/Wallets.test.tsx +++ b/src/components/Wallets.test.tsx @@ -6,7 +6,6 @@ import user from '@testing-library/user-event' import * as apiMock from '../libs/JmWalletApi' import Wallets from './Wallets' -import { walletDisplayName } from '../utils' import { CurrentWallet } from '../context/WalletContext' jest.mock('../libs/JmWalletApi', () => ({ @@ -44,7 +43,7 @@ describe('', () => { ;(apiMock.getGetinfo as jest.Mock).mockResolvedValue(neverResolvingPromise) }) - it('should render without errors', () => { + it('should display loading indicator while fetching data', () => { const neverResolvingPromise = new Promise(() => {}) ;(apiMock.getSession as jest.Mock).mockResolvedValueOnce(neverResolvingPromise) ;(apiMock.getWalletAll as jest.Mock).mockResolvedValueOnce(neverResolvingPromise) @@ -75,6 +74,24 @@ describe('', () => { expect(screen.getByText('wallets.button_new_wallet')).toBeInTheDocument() }) + it('should display alert when rescanning is active', async () => { + ;(apiMock.getWalletAll as jest.Mock).mockResolvedValueOnce({ + ok: false, + }) + ;(apiMock.getSession as jest.Mock).mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + rescanning: true, + }), + }) + + await act(async () => setup({})) + + expect(screen.getByText('wallets.title')).toBeVisible() + expect(screen.getByTestId('alert-rescanning')).toBeVisible() + }) + it('should display big call-to-action buttons if no wallet has been created yet', async () => { ;(apiMock.getSession as jest.Mock).mockResolvedValueOnce({ ok: true, @@ -214,7 +231,7 @@ describe('', () => { await act(async () => setup({})) - expect(screen.getByText('wallets.wallet_preview.wallet_inactive')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_locked')).toBeInTheDocument() expect(screen.getByText('wallets.wallet_preview.button_unlock')).toBeInTheDocument() expect(screen.getByPlaceholderText('wallets.wallet_preview.placeholder_password')).toBeInTheDocument() @@ -261,7 +278,7 @@ describe('', () => { await act(async () => setup({})) - expect(screen.getByText('wallets.wallet_preview.wallet_inactive')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_locked')).toBeInTheDocument() expect(screen.getByText('wallets.wallet_preview.button_unlock')).toBeInTheDocument() expect(screen.getByPlaceholderText('wallets.wallet_preview.placeholder_password')).toBeInTheDocument() @@ -313,7 +330,7 @@ describe('', () => { }), ) - expect(screen.getByText('wallets.wallet_preview.wallet_active')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_unlocked')).toBeInTheDocument() expect(screen.getByText('wallets.wallet_preview.button_lock')).toBeInTheDocument() await act(async () => { @@ -361,7 +378,7 @@ describe('', () => { }), ) - expect(screen.getByText('wallets.wallet_preview.wallet_active')).toBeInTheDocument() + expect(screen.getByText('wallets.wallet_preview.wallet_unlocked')).toBeInTheDocument() expect(screen.getByText('wallets.wallet_preview.button_lock')).toBeInTheDocument() await act(async () => { diff --git a/src/components/Wallets.tsx b/src/components/Wallets.tsx index 9b4d686c..dbead45c 100644 --- a/src/components/Wallets.tsx +++ b/src/components/Wallets.tsx @@ -210,6 +210,11 @@ export default function Wallets({ currentWallet, startWallet, stopWallet }: Wall subtitle={walletList?.length === 0 ? t('wallets.subtitle_no_wallets') : undefined} center={true} /> + {serviceInfo?.rescanning === true && ( + + {t('app.alert_rescan_in_progress')} + + )} {alert && } {isLoading ? (
diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index b01bc72e..423c6dcb 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -105,6 +105,8 @@ "alert_wallet_already_locked": "{{ walletName }} already locked.", "wallet_active": "Active", "wallet_inactive": "Inactive", + "wallet_locked": "Locked", + "wallet_unlocked": "Unlocked", "placeholder_password": "Password", "button_open": "Open", "button_lock": "Lock", @@ -123,6 +125,7 @@ "title_wallet_created": "Wallet created successfully!", "subtitle_wallet_created": "Please write down your seed phrase and password! Without this information you will not be able to access and recover your wallet!", "alert_other_wallet_unlocked": "Currently <1>{{ walletName }} is active. You need to lock it first. <3>Go back.", + "alert_rescan_in_progress": "Rescanning the timechain is currently in progress. Please wait until the process finishes and then try again. <1>Go back.", "feedback_valid": "Looks good!", "label_wallet_name": "Wallet name", "placeholder_wallet_name": "Your Wallet...",