Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -265,14 +265,15 @@ export const AssetLogo = ({
onLoad={handleOnLoad}
onError={handleLoadError}
/>
{showNetworkIcon && (
<StyledNetworkIcon
networkSymbol={symbol as NetworkSymbol | LegacyNetworkSymbol}
size={size * 0.375}
/>
)}
</ElevationUp>
)}

{showNetworkIcon && (
<StyledNetworkIcon
networkSymbol={symbol as NetworkSymbol | LegacyNetworkSymbol}
size={size * 0.375}
/>
)}
</Container>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,14 @@ export const SearchAsset = ({
value={selectedOption}
onChange={option => selectConfig.onChange(option.value)}
size="small"
formatOptionLabel={option => (
<Option>
formatOptionLabel={(option, meta) => (
<Option
data-testid={
meta.context === 'menu'
? `${dataTestId}/select-option/${option.value ?? 'all-networks'}`
: `${dataTestId}/select-option-value/${option.value ?? 'all-networks'}`
}
>
{option.value && (
<CoinLogo size={20} symbol={option.value} type="network" />
)}
Expand All @@ -81,7 +87,9 @@ export const SearchAsset = ({
)}
width="auto"
minValueWidth="170px"
data-testid={`${dataTestId}/select`}
isRenderedInModal
openMenuOnFocus={false}
/>
</SelectWrapper>
) : undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ import styled from 'styled-components';
import { Text } from '@trezor/components';
import { borders, mapElevationToBorder, spacings, spacingsPx } from '@trezor/theme';

import { AssetLogo, AssetLogoProps } from '../AssetLogo/AssetLogo';
import { AssetLogo, AssetLogoProps, shouldShowNetworkIcon } from '../AssetLogo/AssetLogo';
import { CoinLogo } from '../CoinLogo/CoinLogo';

const Container = styled.div<{ $itemsCount: number }>`
display: grid;
grid-template-columns: repeat(${({ $itemsCount }) => $itemsCount}, 1fr);
border: 1px solid ${({ theme }) => mapElevationToBorder({ $elevation: 1, theme })};
border-radius: ${borders.radii.sm};
border-radius: ${borders.radii.md};
align-items: center;
width: 100%;
overflow: hidden;
position: relative;
`;

const Item = styled('button')<{ $isLast: boolean }>`
Expand All @@ -30,6 +32,11 @@ const Item = styled('button')<{ $isLast: boolean }>`
gap: ${spacingsPx.xxs};
flex-direction: column;
padding: ${spacings.xs * 1.25}px ${spacings.xs * 1.5}px ${spacings.xs * 0.75}px;
transition: background-color 150ms ease-in-out;
&:hover {
background-color: ${({ theme }) => theme.backgroundTertiaryPressedOnElevation1};
}
`;

export type Asset = {
Expand All @@ -43,12 +50,12 @@ export interface TopAssetsProps {
assets: Asset[];
onAssetClick: (asset: Asset) => void;
logoSize?: AssetLogoProps['size'];
className?: string;
dataTestId?: string;
}

export function TopAssets({ assets, logoSize = 40, onAssetClick, className }: TopAssetsProps) {
export function TopAssets({ assets, logoSize = 40, onAssetClick, dataTestId }: TopAssetsProps) {
return (
<Container $itemsCount={assets.length} className={className}>
<Container $itemsCount={assets.length}>
{assets.map((asset, index) => {
const displaySymbol = asset.symbol.toUpperCase();

Expand All @@ -57,6 +64,7 @@ export function TopAssets({ assets, logoSize = 40, onAssetClick, className }: To
key={asset.id}
$isLast={index === assets.length - 1}
onClick={() => onAssetClick(asset)}
data-testid={`${dataTestId}/${asset.id}`}
>
{asset.isNativeToken ? (
<CoinLogo
Expand All @@ -72,6 +80,10 @@ export function TopAssets({ assets, logoSize = 40, onAssetClick, className }: To
symbol={asset.symbol}
contractAddress={asset.contractAddress}
placeholder={displaySymbol}
showNetworkIcon={shouldShowNetworkIcon(
asset.symbol,
asset.contractAddress,
)}
/>
)}

Expand Down
4 changes: 4 additions & 0 deletions packages/suite/src/components/suite/Translation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import messages from '../../support/messages';

export type TranslationKey = keyof typeof messages;

export function isTranslationKey(key: unknown): key is TranslationKey {
return typeof key === 'string' && Object.hasOwn(messages, key);
}

export const Translation = ({ defaultMessage, id, values }: ExtendedMessageDescriptor) => {
// prevent runtime errors
if (!defaultMessage && id !== undefined && !messages[id]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styled from 'styled-components';
import { NetworkSymbol, getDisplaySymbol, getNetwork } from '@suite-common/wallet-config';
import { Badge, Column, Row, Text } from '@trezor/components';
import { spacings } from '@trezor/theme';
import { hasOwn } from '@trezor/utils';

const TextWrapper = styled.div`
overflow: hidden;
Expand All @@ -16,10 +17,20 @@ const BadgeWrapper = styled.div`
type AssetDetailsProps = {
name: string;
symbol: string;
networkSymbol: NetworkSymbol;
};
} & (
| {
networkSymbol: NetworkSymbol;
}
| {
networkName: string;
}
);

export function AssetDetails({ name, symbol, ...props }: AssetDetailsProps) {
const badge = hasOwn(props, 'networkSymbol')
? getNetwork(props.networkSymbol).name
: props.networkName;

export function AssetDetails({ name, symbol, networkSymbol }: AssetDetailsProps) {
return (
<Column alignItems="flex-start" justifyContent="flex-start">
<TextWrapper>
Expand All @@ -31,9 +42,11 @@ export function AssetDetails({ name, symbol, networkSymbol }: AssetDetailsProps)
<Text typographyStyle="hint" variant="tertiary">
{getDisplaySymbol(symbol)}
</Text>
<BadgeWrapper>
<Badge size="small">{getNetwork(networkSymbol).name}</Badge>
</BadgeWrapper>
{badge !== name && (
<BadgeWrapper>
<Badge size="small">{badge}</Badge>
</BadgeWrapper>
)}
</Row>
</Column>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { ReactNode } from 'react';
import { Text } from '@trezor/components';
import { spacings } from '@trezor/theme';

import { Translation, TranslationKey, isTranslationKey } from 'src/components/suite/Translation';

export const ASSET_ROW_GROUP_LABEL_HEIGHT = 24;

export type AssetGroupLabelProps = {
label: ReactNode;
label: ReactNode | TranslationKey;
};

export function AssetGroupLabel({ label }: AssetGroupLabelProps) {
Expand All @@ -17,7 +19,7 @@ export function AssetGroupLabel({ label }: AssetGroupLabelProps) {
margin={{ bottom: spacings.xxs, left: spacings.md }}
as="div"
>
{label}
{isTranslationKey(label) ? <Translation id={label} /> : label}
</Text>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@ import { spacings } from '@trezor/theme';
import { ItemClickableContainer } from '../ItemClickableContainer';
import { AccountAmount } from './AccountAmount';

export type AssetRowSendFromAccountProps = {
export type AssetRowAccountWithBalanceProps = {
account: Account;
'data-testid'?: string;
dataTestId?: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for this change? We use this prop name only in 4 files and I would prefer to keep the same and consistent naming.

image

onClick: (account: Account) => void;
};

export function AssetRowSendFromAccount({
'data-testid': dataTestId,
export function AssetRowAccountWithBalance({
dataTestId,
account,
onClick,
}: AssetRowSendFromAccountProps) {
}: AssetRowAccountWithBalanceProps) {
return (
<ItemClickableContainer onClick={() => onClick(account)}>
<Row data-testid={dataTestId} gap={spacings.sm} alignItems="center">
<Row
data-testid={`${dataTestId}/${account.symbol}`}
gap={spacings.sm}
alignItems="center"
>
<CoinLogo symbol={account.symbol} size={40} type="tokenWithNetwork" />

<Column alignItems="flex-start" justifyContent="flex-start">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import { ItemClickableContainer } from '../ItemClickableContainer';

export type AssetRowReceiveToAccountProps = {
account: Account;
'data-testid'?: string;
dataTestId?: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, no need to change naming here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because then you can't just pass it to the component but you need to re-assigned it to another variable (with valid name). So this has valid name from the beginning. Nothing wrong about that. This gonna stay.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry but I disagree.
I understand you want to do it in your way, but your reason is not good enough to break current rule/habit. Right now if you pass prop you don't have to think if you use dataTestId or data-testid. You have just one option everywhere which makes sense. I'd like to keep it that way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially hoped we can focus during review on important stuff. And you somewhat did, for example with the perf. issue and some imperfect styles thanks for that. But this is not one them and we are losing time by discussing something that not important at all.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally understand that a lot of stuff are not that important. And I'm also fine with approving PR without fixing all of them. But at the same time, we follow some rules and good practises for a good reason. Like not using classnames, or be very strict with unified prop names. I understand you are used to do it in different way, but we set these rules based on our previous experience and so far we have very good results with them. Please respect that some of these rules are there and we can be pretty irritating with enforcing them. If you follow them I'm sure you will get our βœ… much faster. Also we care about the visual language and we want to have it as consistent as possible.

Also if you want to ship features faster, I suggest to create small PRs. It's extremely hard to understand logic in PRs with 1000+ lines, it takes too much time to review and I understand it can be also pretty hard to merge it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember last time I did so huge PR and I didn't initially expect it to grow that much. I'm sorry about that I know it's then hard to review it properly. As I wrote today to the PR comment and created all commits again in much more granular fashion and categorized them by prio. in the PR description. Hopefully, it will help a bit.

onClick: (account: Account) => void;
};

export function AssetRowReceiveToAccount({
'data-testid': dataTestId,
dataTestId,
account,
onClick,
}: AssetRowReceiveToAccountProps) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './constants';
export * from './AssetRowReceiveToAccount';
export * from './AssetRowSendFromAccount';
export * from './AssetRowAccountWithBalance';
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { TradingAssetOption } from '@suite-common/trading';
import { Row } from '@trezor/components';
import { AssetLogo, CoinLogo, shouldShowNetworkIcon } from '@trezor/product-components';
import { spacings } from '@trezor/theme';

import { AssetDetails } from '../AssetDetails';
import { ItemClickableContainer } from '../ItemClickableContainer';

export const ASSET_ROW_ASSET_HEIGHT = 68;

export type AssetRowAssetProps = {
asset: TradingAssetOption;
onClick: (asset: TradingAssetOption) => void;
dataTestId?: string;
};

export function AssetRowAsset({ asset, dataTestId, onClick }: AssetRowAssetProps) {
return (
<ItemClickableContainer
onClick={() => {
onClick(asset);
}}
>
<Row data-testid={`${dataTestId}/${asset.id}`} gap={spacings.sm}>
{asset.isNativeToken ? (
<CoinLogo size={40} symbol={asset.symbol} type="tokenWithNetwork" />
) : (
<AssetLogo
size={40}
coingeckoId={asset.coingeckoId}
symbol={asset.networkSymbol}
contractAddress={asset.contractAddress}
placeholder={asset.displaySymbol}
showNetworkIcon={shouldShowNetworkIcon(
asset.networkSymbol,
asset.contractAddress,
)}
/>
)}
<AssetDetails
name={asset.name}
symbol={asset.symbol}
networkName={asset.networkName}
/>
</Row>
</ItemClickableContainer>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,39 @@ import { getCoingeckoId, getDisplaySymbol } from '@suite-common/wallet-config';
import { Account } from '@suite-common/wallet-types';
import { asBaseCurrencyAmount } from '@suite-common/wallet-utils';
import { Row } from '@trezor/components';
import { AssetLogo } from '@trezor/product-components';
import { AssetLogo, shouldShowNetworkIcon } from '@trezor/product-components';
import { spacings } from '@trezor/theme';

import { TokensWithRates } from 'src/utils/wallet/tokenUtils';

import { ItemClickableContainer } from '../ItemClickableContainer';
import { AssetAmount } from './AssetAmount';
import { AssetDetails } from './AssetDetails';
import { AssetDetails } from '../AssetDetails';

export const ASSET_ROW_TOKEN_HEIGHT = 68;

export type AssetRowTokenProps = {
token: TokensWithRates;
account: Account;
onClick: (token: TokensWithRates, account: Account) => void;
'data-testid'?: string;
dataTestId?: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, no need to change naming here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

};

export function AssetRowToken({
token,
account,
'data-testid': dataTestId,
onClick,
}: AssetRowTokenProps) {
export function AssetRowToken({ token, account, dataTestId, onClick }: AssetRowTokenProps) {
return (
<ItemClickableContainer
onClick={() => {
onClick(token, account);
}}
>
<Row data-testid={dataTestId} gap={spacings.sm}>
<Row data-testid={`${dataTestId}/${account.symbol}/${token.symbol}`} gap={spacings.sm}>
<AssetLogo
size={40}
coingeckoId={getCoingeckoId(account.symbol) ?? account.networkType}
coingeckoId={getCoingeckoId(account.symbol)!}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not happy about this. We should have better typings or use some early return (my preferred variant here) or fallback value. Overusing of ! is not right.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you take closer look on useTradingAssets vs the prev. useTradingInfo, you can see how greatly I have improved types there. So I don't use this lightly. However, I can't fix everything in this codebase what had already been there wrong, e.g. TokenInfo you're referring here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not questioning your typing improvements. I just want to say that I believe it should be pretty easy to get rid of ! here. Just early return and that should be it. Correct me if I'm wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The coingeckoId is defined for all non-test nets. So it's just imperfect type but the values are gonna be correct.

symbol={account.symbol}
contractAddress={token.contract}
placeholder={getDisplaySymbol(token.symbol!, token.contract)}
showNetworkIcon={shouldShowNetworkIcon(account.symbol, token.contract)}
/>
<AssetDetails
name={token.name!}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactNode, RefObject, useCallback, useState } from 'react';
import { ReactNode, RefObject, memo, useCallback, useState } from 'react';

import { BaseItemProps, VirtualizedList, useScrollShadow } from '@trezor/components';
import { mapElevationToBackgroundToken } from '@trezor/theme';
Expand All @@ -14,7 +14,7 @@ export interface AssetsListProps<T> {

export const LIST_MIN_HEIGHT = 200;

export function AssetsList<T extends BaseItemProps>({
function AssetsListInner<T extends BaseItemProps>({
items,
itemsFingerprint,
renderItem,
Expand Down Expand Up @@ -49,3 +49,5 @@ export function AssetsList<T extends BaseItemProps>({
</ShadowContainer>
);
}

export const AssetsList = memo(AssetsListInner) as typeof AssetsListInner;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export * from './AssetsList/AssetsList';
export * from './AssetsListEmpty/AssetsListEmpty';
export * from './AssetSearchWithNetworkFilter/AssetSearchWithNetworkFilter';
export * from './AssetsModal/AssetsModal';
export * from './AssetRow/AssetRowAccount';
export * from './AssetRow/AssetGroupLabel';
export * from './AssetRow/AssetGroupSpace';
export * from './AssetRow/AssetRowToken/AssetRowToken';
export * from './AssetRow/AssetRowAsset/AssetRowAsset';
Loading