Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Add external block explorer links to used addresses
- Settings search
- Support macOS "Number Format" system setting
- Move insurance to Marketplace

## v4.51.1
- iOS: fix App Store submission by packaging Inter as TTF fonts
Expand Down
5 changes: 0 additions & 5 deletions frontends/web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,6 @@ export const App = () => {
navigate('/');
return;
}
// if on the /bitsurance/ view and there are no accounts view route to /
if (accounts.length === 0 && currentURL.startsWith('/bitsurance/')) {
navigate('/');
return;
}
// if in no-accounts settings and has account go to manage-accounts
if (accounts.length && currentURL === '/settings/no-accounts') {
navigate('/settings/manage-accounts');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const BottomNavigation = ({
<Link
className={`
${styles.link || ''}
${pathname.startsWith('/settings') || pathname.startsWith('/bitsurance/') ? (styles.active || '') : ''}
${pathname.startsWith('/settings') ? (styles.active || '') : ''}
`}
to="/settings/more"
>
Expand Down
2 changes: 1 addition & 1 deletion frontends/web/src/components/bottom-navigation/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const getBottomNavKey = (pathname: string): string => {
if (pathname.startsWith('/market/')) {
return 'market';
}
if (pathname.startsWith('/settings') || pathname.startsWith('/bitsurance/')) {
if (pathname.startsWith('/settings')) {
return 'more';
}
return 'other';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: Apache-2.0

import '../../../__mocks__/i18n';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import type { TAccountBase } from '@/api/account';
import { GroupedAccountSelector } from './groupedaccountselector';

const account: TAccountBase = {
active: false,
code: 'btc-0',
coinCode: 'btc',
coinUnit: 'BTC',
isToken: false,
keystore: {
connected: false,
lastConnected: '',
name: 'BitBox',
rootFingerprint: 'root-fingerprint',
watchonly: false,
},
name: 'Bitcoin account',
};

describe('components/groupedaccountselector', () => {
beforeEach(() => {
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation(query => ({
addEventListener: vi.fn(),
dispatchEvent: vi.fn(),
matches: false,
media: query,
onchange: null,
removeEventListener: vi.fn(),
})),
});
});

it('disables proceed when the selected account code is not available', async () => {
render(
<GroupedAccountSelector
accounts={[account]}
selected="eth-0"
onChange={vi.fn()}
onProceed={vi.fn()}
/>,
);

expect(await screen.findByRole('button', { name: 'buy.info.next' })).toBeDisabled();
});

it('enables proceed when the selected account code is available', async () => {
render(
<GroupedAccountSelector
accounts={[account]}
selected={account.code}
onChange={vi.fn()}
onProceed={vi.fn()}
/>,
);

expect(await screen.findByRole('button', { name: 'buy.info.next' })).not.toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export const GroupedAccountSelector = <T extends TAccountBase, >({
? { label: t('buy.info.selectLabel'), value: 'choose', disabled: true }
: options.flatMap(o => o.options).find(opt => opt.value === selected)
);
const isProceedDisabled = disabled || !selectedOption || selectedOption.disabled;

const renderOption = (option: TOption, isSelectedValue: boolean) => {
const isStacked = stackedLayout && isSelectedValue;
Expand Down Expand Up @@ -207,7 +208,7 @@ export const GroupedAccountSelector = <T extends TAccountBase, >({
<Button
primary
onClick={onProceed}
disabled={!selected || disabled}>
disabled={isProceedDisabled}>
{t('buy.info.next')}
</Button>
</div>
Expand Down

This file was deleted.

2 changes: 0 additions & 2 deletions frontends/web/src/components/icon/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ import outlinedUnorderedListDarkSVG from './assets/icons/outlined-unordered-list
import outlinedUnorderedListLightSVG from './assets/icons/outlined-unordered-list-light.svg';
import shieldSVG from './assets/icons/shield.svg';
import shieldDarkSVG from './assets/icons/shield-dark.svg';
import shieldLightSVG from './assets/icons/shield-light.svg';
import syncSVG from './assets/icons/sync.svg';
import syncLightSVG from './assets/icons/sync-light.svg';
import selectedCheckLightSVG from './assets/icons/selected-check-light.svg';
Expand Down Expand Up @@ -198,7 +197,6 @@ export const QRCodeLight = (props: ImgProps) => (<img src={qrCodeLightSVG} dragg
export const RedDot = (props: ImgProps) => (<img src={redDotSVG} draggable={false} {...props} />);
export const Shield = (props: ImgProps) => (<img src={shieldSVG} draggable={false} {...props} />);
export const ShieldDark = (props: ImgProps) => (<img src={shieldDarkSVG} draggable={false} {...props} />);
export const ShieldLight = (props: ImgProps) => (<img src={shieldLightSVG} draggable={false} {...props} />);
export const SpinnerRingDark = (props: ImgProps) => (<img src={spinnerRingDarkSVG} draggable={false} {...props} />);
export const SpinnerRingLight = (props: ImgProps) => (<img src={spinnerRingLightSVG} draggable={false} {...props} />);
export const Sync = (props: ImgProps) => (<img src={syncSVG} draggable={false} {...props} />);
Expand Down
17 changes: 3 additions & 14 deletions frontends/web/src/components/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { deregisterTest } from '@/api/keystores';
import { getVersion } from '@/api/bitbox02';
import { debug } from '@/utils/env';
import { AppLogoInverted, Logo } from '@/components/icon/logo';
import { CloseXWhite, CogLight, Coins, Device, Eject, Linechart, RedDot, ShieldLight } from '@/components/icon';
import { CloseXWhite, CogLight, Coins, Device, Eject, Linechart, RedDot } from '@/components/icon';
import { getAccountsByKeystore } from '@/routes/account/utils';
import { SkipForTesting } from '@/routes/device/components/skipfortesting';
import { AppContext } from '@/contexts/AppContext';
Expand Down Expand Up @@ -92,7 +92,7 @@ const Sidebar = ({
};

const accountsByKeystore = getAccountsByKeystore(accounts);
const userInSpecificAccountMarketPage = (pathname.startsWith('/market'));
const inMarketSection = pathname.startsWith('/market');

return (
<div className={style.sidebarContainer}>
Expand Down Expand Up @@ -150,7 +150,7 @@ const Sidebar = ({
<>
<div key="market" className={style.sidebarItem}>
<NavLink
className={({ isActive }) => isActive || userInSpecificAccountMarketPage ? style.sidebarActive : ''}
className={({ isActive }) => isActive || inMarketSection ? style.sidebarActive : ''}
to="/market/select">
<div className={style.single}>
<Coins />
Expand All @@ -167,17 +167,6 @@ const Sidebar = ({
</span>
</NavLink>
</div>
<div key="insurance" className={style.sidebarItem}>
<NavLink
className={({ isActive }) => isActive ? style.sidebarActive : ''}
to="/bitsurance/bitsurance"
>
<div className={style.single}>
<ShieldLight alt={t('sidebar.insurance')} />
</div>
<span className={style.sidebarLabel}>{t('sidebar.insurance')}</span>
Comment thread
thisconnect marked this conversation as resolved.
</NavLink>
</div>
</>
) : null }

Expand Down
11 changes: 7 additions & 4 deletions frontends/web/src/contexts/BackNavigationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ const getTabId = (pathname: string): TabId => {
}
if (pathname.startsWith('/manage-backups/')
|| pathname.startsWith('/settings')
|| pathname.startsWith('/add-account')
|| pathname.startsWith('/bitsurance/')) {
|| pathname.startsWith('/add-account')) {
return 'settings';
}
return 'unknown';
Expand Down Expand Up @@ -71,8 +70,12 @@ const implicitBackRules: ImplicitBackRule[] = [
previousPattern: '/account/:code',
})),
{
currentPattern: '/bitsurance/bitsurance',
previousPattern: '/settings/more',
currentPattern: '/market/bitsurance/:code',
previousPattern: '/market/select/:code',
},
{
currentPattern: '/market/bitsurance/dashboard/:code',
previousPattern: '/market/select/:code',
},
];

Expand Down
5 changes: 2 additions & 3 deletions frontends/web/src/locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,7 @@
"bitsuranceAccount": {
"errorNoXpub": "Error: Was not able to get xpub from account.",
"noAccount": "There are no accounts that can be insured.",
"select": "Select account",
"title": "Insurance"
"select": "Select account"
},
"blink": {
"button": "Blink"
Expand Down Expand Up @@ -1024,6 +1023,7 @@
"enable": "Enable",
"enabled_false": "Disabled",
"enabled_true": "Enabled",
"insure": "Insure",
"max": "Max",
"new": "New",
"noOptionOnIos": "Not available on iOS",
Expand Down Expand Up @@ -2001,7 +2001,6 @@
"setup": "Setup device",
"sidebar": {
"device": "Manage device",
"insurance": "Insurance",
"leave": "Leave",
"settings": "Settings"
},
Expand Down
2 changes: 1 addition & 1 deletion frontends/web/src/routes/account/account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ const RemountAccount = ({
</A>
</Dialog>
<Header
title={<h2><span>{account.name}</span>{insured && (<Insured />)}</h2>}>
title={<h2><span>{account.name}</span>{insured && (<Insured code={code} />)}</h2>}>
<Link
to={`/account/${code}/info`}
title={t('accountInfo.title')}
Expand Down
8 changes: 6 additions & 2 deletions frontends/web/src/routes/account/components/insuredtag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import { Link } from 'react-router-dom';
import { Shield } from '@/components/icon';
import style from './insuredtag.module.css';

export const Insured = () => {
type TInsuredProps = {
code: string;
};

export const Insured = ({ code }: TInsuredProps) => {
const { t } = useTranslation();
return (
<Link className={style.insured} to="/bitsurance/dashboard">
<Link className={style.insured} to={`/market/bitsurance/dashboard/${code}`}>
<div>
<Shield/>
<span>{t('account.insured')}</span>
Expand Down
34 changes: 22 additions & 12 deletions frontends/web/src/routes/bitsurance/account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { useState, useEffect, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { TAccount } from '@/api/account';
import { BitsuranceGuide } from './guide';
import { Header, GuidedContent, GuideWrapper, Main } from '@/components/layout';
import { MarketTab } from '@/routes/market/components/markettab';
import { GroupedAccountSelector } from '@/components/groupedaccountselector/groupedaccountselector';
import { GuidedContent, GuideWrapper, Header, Main } from '@/components/layout';
import { Spinner } from '@/components/spinner/Spinner';
import { View, ViewContent } from '@/components/view/view';
import { bitsuranceLookup } from '@/api/bitsurance';
import { alertUser } from '@/components/alert/Alert';
import { connectKeystore } from '@/api/keystores';
import { BitsuranceGuide } from './guide';

type TProps = {
accounts: TAccount[];
Expand All @@ -20,14 +21,13 @@ type TProps = {

export const BitsuranceAccount = ({ code, accounts }: TProps) => {
const navigate = useNavigate();
const [selected, setSelected] = useState<string>(code);
const [disabled, setDisabled] = useState<boolean>(false);
const [btcAccounts, setBtcAccounts] = useState<TAccount[]>();

const { t } = useTranslation();

const handleChangeAccount = (selected: string) => {
setSelected(selected);
const handleChangeAccount = (accountCode: string) => {
navigate(`/market/bitsurance/account/${accountCode}`, { replace: true });
};

const detect = useCallback(async () => {
Expand Down Expand Up @@ -63,15 +63,15 @@ export const BitsuranceAccount = ({ code, accounts }: TProps) => {
return;
}
// replace current history item when redirecting so that the user can go back
navigate(`/bitsurance/widget/${account.code}`, { replace: true });
navigate(`/market/bitsurance/widget/${account.code}`, { replace: true });
});
}
}, [btcAccounts, navigate]);

const handleProceed = async () => {
setDisabled(true);
try {
const account = btcAccounts?.find(acc => acc.code === selected);
const account = btcAccounts?.find(acc => acc.code === code);
if (account === undefined) {
return;
}
Expand All @@ -82,7 +82,7 @@ export const BitsuranceAccount = ({ code, accounts }: TProps) => {
} finally {
setDisabled(false);
}
navigate(`/bitsurance/widget/${selected}`);
navigate(`/market/bitsurance/widget/${code}`);
};

if (btcAccounts === undefined) {
Expand All @@ -93,8 +93,18 @@ export const BitsuranceAccount = ({ code, accounts }: TProps) => {
<Main>
<GuideWrapper>
<GuidedContent>
<Header title={<h2>{t('bitsuranceAccount.title')}</h2>} />
Comment thread
thisconnect marked this conversation as resolved.
<View width="550px" verticallyCentered fullscreen={false}>
<Header title={<h2>{t('generic.buySell')}</h2>} />
<MarketTab
accounts={accounts}
activeTab="insure"
code={code}
/>
<View
fullscreen={false}
minHeight="600px"
verticallyCentered
width="550px"
>
<ViewContent>
{ btcAccounts.length === 0 ? (
<div>{t('bitsuranceAccount.noAccount')}</div>
Expand All @@ -103,15 +113,15 @@ export const BitsuranceAccount = ({ code, accounts }: TProps) => {
title={t('bitsuranceAccount.select')}
disabled={disabled}
accounts={btcAccounts}
selected={selected}
selected={code}
onChange={handleChangeAccount}
onProceed={handleProceed}
/>
)}
</ViewContent>
</View>
</GuidedContent>
<BitsuranceGuide/>
<BitsuranceGuide />
</GuideWrapper>
</Main>
);
Expand Down
Loading