Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Wallet management icon #3114

Merged
merged 3 commits into from
Feb 6, 2025
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
2 changes: 1 addition & 1 deletion docs/content/docs/onboarding/project-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Domain's model **must**:
- Export single object without `Model` suffix (`accounts`, not `accountsModel`).
- Provide storage logic.
- Create integrations with data sources.
- Be isolated, no other models in dependecies.
- Be isolated, no other models in dependencies.
- Be testable.

Model file should export single object with same name as entity.
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/domains/network/accounts/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function isUniversalAccount(account: Pick<AnyAccount, 'type'>): account is Unive
}

function isAccountAvailableOnChain(account: Pick<AnyAccount, 'type' | 'cryptoType'>, chain: Chain) {
if (isCryptoMatch(account, chain) === false) {
if (!isCryptoMatch(account, chain)) {
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/renderer/domains/network/accounts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface UniversalAccount {

/**
* @summary
* Account related to specific chain. This is most common case and such accounts
* Account related to specific chain. This is the most common case and such accounts
* have "one to one" relations with other entities in the system.
*/
export interface ChainAccount {
Expand Down
6 changes: 2 additions & 4 deletions src/renderer/entities/wallet/ui/Cards/WalletCardLg.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { type PropsWithChildren, type ReactNode } from 'react';

import { type Wallet, WalletIconType } from '@/shared/core';
import { cnTw } from '@/shared/lib/utils';
import { BodyText, FootnoteText } from '@/shared/ui';
import { walletUtils } from '../../lib/wallet-utils';
import { WalletIcon } from '../WalletIcon/WalletIcon';

type Props = PropsWithChildren<{
className?: string;
wallet: Wallet;
description?: string | ReactNode;
additionalInfo?: ReactNode;
}>;

export const WalletCardLg = ({ wallet, description, additionalInfo, className, children }: Props) => {
export const WalletCardLg = ({ wallet, description, additionalInfo, children }: Props) => {
const type =
walletUtils.isFlexibleMultisig(wallet) && !wallet.activated
? WalletIconType.FLEXIBLE_MULTISIG_INACTIVE
: wallet.type;

return (
<div className={cnTw('flex h-8 w-full min-w-0 items-center gap-x-2', className)}>
<div className="flex h-8 w-full min-w-0 items-center gap-x-2">
<div className="relative">
<WalletIcon type={type} size={32} />
{additionalInfo}
Expand Down
20 changes: 4 additions & 16 deletions src/renderer/entities/wallet/ui/Cards/WalletCardMd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,14 @@ import { cnTw, nonNullable, nullable } from '@/shared/lib/utils';
import { BodyText, FootnoteText } from '@/shared/ui';
import { WalletIcon } from '../WalletIcon/WalletIcon';

type Props = {
type Props = PropsWithChildren<{
wallet: Wallet;
description?: string | ReactNode;
meta?: ReactNode;
prefix?: ReactNode;
hideIcon?: boolean;
onClick?: () => void;
};
}>;

export const WalletCardMd = ({
wallet,
description,
meta,
prefix,
hideIcon,
children,
onClick,
}: PropsWithChildren<Props>) => {
export const WalletCardMd = ({ wallet, description, meta, children, onClick }: Props) => {
const handleClick = (fn?: () => void) => {
return (event: MouseEvent<HTMLButtonElement>) => {
if (!fn) return;
Expand All @@ -46,9 +36,7 @@ export const WalletCardMd = ({
})}
onClick={handleClick(onClick)}
>
{prefix}

{!hideIcon && <WalletIcon type={wallet.type} size={20} className="shrink-0" />}
<WalletIcon type={wallet.type} size={20} className="shrink-0" />
<div className="flex min-w-0 flex-col">
<div className="flex items-center gap-x-2">
<BodyText
Expand Down
27 changes: 15 additions & 12 deletions src/renderer/entities/wallet/ui/Cards/WalletCardSm.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { type MouseEvent } from 'react';
import { type MouseEvent, type PropsWithChildren } from 'react';

import { type Wallet } from '@/shared/core';
import { cnTw } from '@/shared/lib/utils';
import { FootnoteText, IconButton } from '@/shared/ui';
import { FootnoteText } from '@/shared/ui';
import { WalletIcon } from '../WalletIcon/WalletIcon';

type Props = {
type Props = PropsWithChildren<{
wallet: Wallet;
iconSize?: number;
className?: string;
onClick?: () => void;
onInfoClick?: () => void;
};
}>;

export const WalletCardSm = ({ wallet, className, iconSize = 16, onClick, onInfoClick }: Props) => {
export const WalletCardSm = ({ wallet, onClick, children }: Props) => {
const handleClick = (fn?: () => void) => {
return (event: MouseEvent<HTMLButtonElement>) => {
if (!fn) return;
Expand All @@ -28,11 +25,10 @@ export const WalletCardSm = ({ wallet, className, iconSize = 16, onClick, onInfo
className={cnTw(
'group relative flex w-full items-center rounded transition-colors',
'focus-within:bg-action-background-hover hover:bg-action-background-hover',
className,
)}
>
<button className="flex w-full items-center gap-x-2 rounded py-[3px] pl-2 pr-7" onClick={handleClick(onClick)}>
<WalletIcon className="shrink-0" type={wallet.type} size={iconSize} />
<WalletIcon className="shrink-0" type={wallet.type} size={16} />
<FootnoteText
className={cnTw(
'truncate text-text-secondary transition-colors',
Expand All @@ -42,8 +38,15 @@ export const WalletCardSm = ({ wallet, className, iconSize = 16, onClick, onInfo
{wallet.name}
</FootnoteText>
</button>
{/* TODO: do the same as in WalletCardMd */}
<IconButton className="absolute right-2" name="details" size={16} onClick={handleClick(onInfoClick)} />

<div
className={cnTw(
'absolute right-2 top-1/2 flex -translate-y-1/2 opacity-0 transition-opacity',
'focus:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100',
)}
>
{children}
</div>
</div>
);
};
15 changes: 4 additions & 11 deletions src/renderer/features/extension-wallet/components/WalletGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { Slot, createSlot } from '@/shared/di';
import { useI18n } from '@/shared/i18n';
import { performSearch } from '@/shared/lib/utils';
import { Icon, type IconNames } from '@/shared/ui';
import { WalletManagement } from '@/shared/ui-entities';
import { Accordion, Box, Label } from '@/shared/ui-kit';
import { WalletCardMd } from '@/entities/wallet';
import { walletsFiatBalanceFeature } from '@/features/wallet-fiat-balance';

// TODO invert this dependency
Expand All @@ -26,6 +26,7 @@ type Props = {

export const WalletGroup = memo(({ wallets, icon, query, title, onSelect }: Props) => {
const { t } = useI18n();

const filteredWallets = performSearch({
query,
records: wallets,
Expand All @@ -48,24 +49,16 @@ export const WalletGroup = memo(({ wallets, icon, query, title, onSelect }: Prop
<Accordion.Content>
<Box gap={1} padding={[1, 0, 0]}>
{filteredWallets.map((wallet) => (
<WalletCardMd
<WalletManagement
key={wallet.id}
hideIcon
wallet={wallet}
description={
<WalletFiatBalance walletId={wallet.id} className="max-w-[215px] truncate text-help-text" />
}
prefix={
wallet.isActive ? (
<Icon name="checkmark" className="shrink-0 text-icon-accent" size={20} />
) : (
<div className="row-span-2 h-5 w-5 shrink-0" />
)
}
onClick={() => onSelect(wallet)}
>
<Slot id={walletActionsSlot} props={{ wallet }} />
</WalletCardMd>
</WalletManagement>
))}
</Box>
</Accordion.Content>
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/features/wallet-details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import { walletActionsSlot as proxiedActionsSlot } from '@/features/wallet-proxi
import { walletActionsSlot as walletConnectActionsSlot } from '@/features/wallet-wallet-connect';
import { walletActionsSlot as watchOnlyActionsSlot } from '@/features/wallet-watch-only';

import { WalletDetails } from './ui/components/WalletDetails';
import { WalletDetails } from './ui/components';

export { WalletDetails };

/**
* The reason for the existence of this feature is WalletDetails component
* implementation. walletDetailsFeature should be absolete and details for each
* implementation. walletDetailsFeature should be obsolete and details for each
* type of wallet should be coupled with wallet implementation.
*/

Expand Down
31 changes: 4 additions & 27 deletions src/renderer/features/wallet-multisig/components/WalletGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { memo } from 'react';

import { type Wallet, WalletType } from '@/shared/core';
import { Slot, createSlot } from '@/shared/di';
import { useI18n } from '@/shared/i18n';
import { performSearch } from '@/shared/lib/utils';
import { Icon } from '@/shared/ui';
import { Accordion, Box, Tooltip } from '@/shared/ui-kit';
import { WalletCardMd, WalletIcon } from '@/entities/wallet';
import { walletsFiatBalanceFeature } from '@/features/wallet-fiat-balance';
import { WalletIcon } from '@/entities/wallet';

// TODO invert this dependency
const {
views: { WalletFiatBalance },
} = walletsFiatBalanceFeature;

export const walletActionsSlot = createSlot<{ wallet: Wallet }>();
import { WalletRow } from './WalletRow';

type Props = {
title: string;
Expand All @@ -26,6 +19,7 @@ type Props = {

export const WalletGroup = memo(({ wallets, walletType, query, title, onSelect }: Props) => {
const { t } = useI18n();

const filteredWallets = performSearch({
query,
records: wallets,
Expand Down Expand Up @@ -57,24 +51,7 @@ export const WalletGroup = memo(({ wallets, walletType, query, title, onSelect }
<Accordion.Content>
<Box gap={1} padding={[1, 0, 0]}>
{filteredWallets.map(wallet => (
<WalletCardMd
key={wallet.id}
hideIcon
wallet={wallet}
description={
<WalletFiatBalance walletId={wallet.id} className="max-w-[215px] truncate text-help-text" />
}
prefix={
wallet.isActive ? (
<Icon name="checkmark" className="shrink-0 text-icon-accent" size={20} />
) : (
<div className="row-span-2 h-5 w-5 shrink-0" />
)
}
onClick={() => onSelect(wallet)}
>
<Slot id={walletActionsSlot} props={{ wallet }} />
</WalletCardMd>
<WalletRow key={wallet.id} wallet={wallet} onSelect={onSelect} />
))}
</Box>
</Accordion.Content>
Expand Down
44 changes: 44 additions & 0 deletions src/renderer/features/wallet-multisig/components/WalletRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useStoreMap, useUnit } from 'effector-react';

import { type Wallet } from '@/shared/core';
import { Slot, createSlot } from '@/shared/di';
import { WalletManagement } from '@/shared/ui-entities';
import { accounts as accountsDomainModel, accountsService } from '@/domains/network';
import { ChainIcon } from '@/entities/chain';
import { networkModel } from '@/entities/network';
import { walletsFiatBalanceFeature } from '@/features/wallet-fiat-balance';

const {
views: { WalletFiatBalance },
} = walletsFiatBalanceFeature;

export const walletActionsSlot = createSlot<{ wallet: Wallet }>();

type Props = {
wallet: Wallet;
onSelect: (wallet: Wallet) => unknown;
};
export const WalletRow = ({ wallet, onSelect }: Props) => {
const chains = useUnit(networkModel.$chains);

const account = useStoreMap({
store: accountsDomainModel.$list,
keys: [wallet.id],
fn: (accounts, [walletId]) => {
const match = accountsService.filterAccountsByWallet(accounts, walletId).at(0);

return match && accountsService.isChainAccount(match) ? match : null;
},
});

return (
<WalletManagement
wallet={wallet}
meta={account ? <ChainIcon src={chains[account.chainId].icon} size={16} /> : null}
description={<WalletFiatBalance walletId={wallet.id} className="max-w-[215px] truncate text-help-text" />}
onClick={() => onSelect(wallet)}
>
<Slot id={walletActionsSlot} props={{ wallet }} />
</WalletManagement>
);
};
5 changes: 3 additions & 2 deletions src/renderer/features/wallet-multisig/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { accountsService } from '@/domains/network';
import { WalletIcon, accountUtils, walletUtils } from '@/entities/wallet';
import { walletGroupSlot, walletIconSlot } from '@/features/wallet-select';

import { WalletGroup, walletActionsSlot } from './components/WalletGroup';
import { WalletGroup } from './components/WalletGroup';
import { walletActionsSlot } from './components/WalletRow';
import { walletsModel } from './model/wallets';

export { walletActionsSlot };
Expand Down Expand Up @@ -39,7 +40,7 @@ walletMultisigFeature.inject(walletGroupSlot, {
render({ query, onSelect }) {
const { t } = useI18n();
const regular = useUnit(walletsModel.$regularMultisig);
const flexible = useUnit(walletsModel.$flexibleMutisig);
const flexible = useUnit(walletsModel.$flexibleMultisig);

return (
<>
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/features/wallet-multisig/model/wallets.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { walletModel, walletUtils } from '@/entities/wallet';

export const $regularMultisig = walletModel.$wallets.map(list => list.filter(walletUtils.isRegularMultisig));
export const $flexibleMutisig = walletModel.$wallets.map(list => list.filter(walletUtils.isFlexibleMultisig));
export const $flexibleMultisig = walletModel.$wallets.map(list => list.filter(walletUtils.isFlexibleMultisig));

export const walletsModel = {
$regularMultisig,
$flexibleMutisig,
$flexibleMultisig,
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { memo } from 'react';
import { type Wallet, type WalletType } from '@/shared/core';
import { Slot, createSlot } from '@/shared/di';
import { performSearch } from '@/shared/lib/utils';
import { Icon } from '@/shared/ui';
import { WalletManagement } from '@/shared/ui-entities';
import { Accordion, Box } from '@/shared/ui-kit';
import { WalletCardMd, WalletIcon } from '@/entities/wallet';
import { WalletIcon } from '@/entities/wallet';
import { walletsFiatBalanceFeature } from '@/features/wallet-fiat-balance';

// TODO invert this dependency
Expand Down Expand Up @@ -45,24 +45,16 @@ export const WalletGroup = memo(({ wallets, walletType, query, title, onSelect }
<Accordion.Content>
<Box gap={1} padding={[1, 0, 0]}>
{filteredWallets.map(wallet => (
<WalletCardMd
<WalletManagement
key={wallet.id}
hideIcon
wallet={wallet}
description={
<WalletFiatBalance walletId={wallet.id} className="max-w-[215px] truncate text-help-text" />
}
prefix={
wallet.isActive ? (
<Icon name="checkmark" className="shrink-0 text-icon-accent" size={20} />
) : (
<div className="row-span-2 h-5 w-5 shrink-0" />
)
}
onClick={() => onSelect(wallet)}
>
<Slot id={walletActionsSlot} props={{ wallet }} />
</WalletCardMd>
</WalletManagement>
))}
</Box>
</Accordion.Content>
Expand Down
Loading
Loading