Skip to content

Commit

Permalink
feat: send select asset sheet, closes LEA-1643 and LEA-1628
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Nov 11, 2024
1 parent 8c18118 commit 4937d9b
Show file tree
Hide file tree
Showing 24 changed files with 417 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useWindowDimensions } from 'react-native';

import { ToastWrapper } from '@/components/toast/toast-context';
import { HasChildren } from '@/utils/types';
import { NavigationContainer } from '@react-navigation/native';

Expand All @@ -8,8 +9,10 @@ import { Box } from '@leather.io/ui/native';
export function SheetNavigationContainer({ children }: HasChildren) {
const { height } = useWindowDimensions();
return (
<Box flex={1} height={height}>
<NavigationContainer independent>{children}</NavigationContainer>
</Box>
<ToastWrapper>
<Box flex={1} height={height}>
<NavigationContainer independent>{children}</NavigationContainer>
</Box>
</ToastWrapper>
);
}
28 changes: 28 additions & 0 deletions apps/mobile/src/components/address-type-badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useLingui } from '@lingui/react';

import { Box, Text } from '@leather.io/ui/native';

interface AddressTypeBadgeProps {
type: string;
}
export function AddressTypeBadge({ type }: AddressTypeBadgeProps) {
const { i18n } = useLingui();

return (
<Box
bg="ink.background-secondary"
borderColor="ink.border-transparent"
borderRadius="xs"
borderWidth={1}
px="1"
>
<Text color="ink.text-subdued" fontSize={11} fontWeight={500} lineHeight={12}>
{i18n._({
id: 'address_type_badge.label',
message: '{type}',
values: { type },
})}
</Text>
</Box>
);
}
3 changes: 3 additions & 0 deletions apps/mobile/src/components/toast/toast-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ export interface ToastContextType {
export const ToastContext = createContext<ToastContextType>({
displayToast: () => {},
});

export function useToastContext() {
return useContext(ToastContext);
}

export function ToastWrapper({ children }: HasChildren) {
const toastRef = useRef<ToastMethods>(null);

Expand All @@ -24,6 +26,7 @@ export function ToastWrapper({ children }: HasChildren) {
},
[toastRef.current]

Check warning on line 27 in apps/mobile/src/components/toast/toast-context.tsx

View workflow job for this annotation

GitHub Actions / lint-eslint

React Hook useCallback has an unnecessary dependency: 'toastRef.current'. Either exclude it or remove the dependency array. Mutable values like 'toastRef.current' aren't valid dependencies because mutating them doesn't re-render the component

Check warning on line 27 in apps/mobile/src/components/toast/toast-context.tsx

View workflow job for this annotation

GitHub Actions / lint-eslint

React Hook useCallback has an unnecessary dependency: 'toastRef.current'. Either exclude it or remove the dependency array. Mutable values like 'toastRef.current' aren't valid dependencies because mutating them doesn't re-render the component

Check warning on line 27 in apps/mobile/src/components/toast/toast-context.tsx

View workflow job for this annotation

GitHub Actions / lint-eslint

React Hook useCallback has an unnecessary dependency: 'toastRef.current'. Either exclude it or remove the dependency array. Mutable values like 'toastRef.current' aren't valid dependencies because mutating them doesn't re-render the component
);

return (
<ToastContext.Provider value={{ displayToast }}>
{children}
Expand Down
4 changes: 2 additions & 2 deletions apps/mobile/src/features/account-list/account-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Avatar, Flag, ItemLayout, Pressable } from '@leather.io/ui/native';

interface AccountListItemProps {
accountName: string;
address: string;
balance: string;
address: React.ReactNode;
balance: React.ReactNode;
icon: React.ReactNode;
iconTestID?: string;
onPress?(): void;
Expand Down
13 changes: 9 additions & 4 deletions apps/mobile/src/features/account-list/account-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { TestId } from '@/shared/test-id';
import { Account } from '@/store/accounts/accounts';
import { WalletLoader } from '@/store/wallets/wallets.read';
import { defaultIconTestId } from '@/utils/testing-utils';
import { t } from '@lingui/macro';
import { useTheme } from '@shopify/restyle';

import { Theme } from '@leather.io/ui/native';

import { AccountListItem } from './account-list-item';
import { AccountAddress } from './components/account-address';
import { AccountBalance } from './components/account-balance';

interface AccountListProps {
accounts: Account[];
Expand All @@ -23,13 +24,17 @@ export function AccountList({ accounts, onPress, showWalletInfo }: AccountListPr
{wallet => (
<AccountListItem
accountName={account.name}
address={t`Address`}
balance={t`$1234`}
address={
<AccountAddress accountIndex={account.accountIndex} fingerprint={account.fingerprint} />
}
balance={
<AccountBalance accountIndex={account.accountIndex} fingerprint={account.fingerprint} />
}
icon={<AvatarIcon color={theme.colors['ink.background-primary']} icon={account.icon} />}
iconTestID={defaultIconTestId(account.icon)}
onPress={() => onPress(account)}
testID={TestId.walletListAccountCard}
walletName={showWalletInfo ? wallet.name : undefined}
walletName={showWalletInfo ? wallet.name : ' '}
/>
)}
</WalletLoader>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AccountId } from '@/models/domain.model';
import { useAccountDisplayAddress } from '@/store/settings/settings.read';

import { Text } from '@leather.io/ui/native';
import { truncateMiddle } from '@leather.io/utils';

type AccountAddressProps = AccountId;

export function AccountAddress({ accountIndex, fingerprint }: AccountAddressProps) {
const displayAddress = useAccountDisplayAddress(fingerprint, accountIndex);
return (
<Text variant="caption01" color="ink.text-subdued">
{truncateMiddle(displayAddress)}
</Text>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Balance } from '@/components/balance/balance';
import { AccountId } from '@/models/domain.model';
import { useAccountTotalBalance } from '@/queries/balance/total-balance.query';

type AccountBalanceProps = AccountId;

export function AccountBalance({ accountIndex, fingerprint }: AccountBalanceProps) {
const { totalBalance } = useAccountTotalBalance({ fingerprint, accountIndex });
return <Balance balance={totalBalance} variant="label02" />;
}
36 changes: 29 additions & 7 deletions apps/mobile/src/features/balances/bitcoin/bitcoin-balance.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { AccountId } from '@/models/domain.model';
import {
useBitcoinAccountTotalBitcoinBalance,
useWalletTotalBitcoinBalance,
Expand All @@ -13,17 +12,22 @@ import { TokenBalance } from '../token-balance';
interface BitcoinTokenBalanceProps {
availableBalance: Money;
fiatBalance: Money;
onPress?(): void;
}
export function BitcoinTokenBalance({ availableBalance, fiatBalance }: BitcoinTokenBalanceProps) {
export function BitcoinTokenBalance({
availableBalance,
fiatBalance,
onPress,
}: BitcoinTokenBalanceProps) {
return (
<TokenBalance
ticker="BTC"
icon={<BtcAvatarIcon />}
tokenName={t`Bitcoin`}
chain={t`Bitcoin blockchain`}
chain={t`Layer 1`}
fiatBalance={fiatBalance}
showChain={false}
availableBalance={availableBalance}
onPress={onPress}
/>
);
}
Expand All @@ -33,7 +37,25 @@ export function BitcoinBalance() {
return <BitcoinTokenBalance availableBalance={availableBalance} fiatBalance={fiatBalance} />;
}

export function BitcoinBalanceByAccount(props: AccountId) {
const { availableBalance, fiatBalance } = useBitcoinAccountTotalBitcoinBalance(props);
return <BitcoinTokenBalance availableBalance={availableBalance} fiatBalance={fiatBalance} />;
interface BitcoinBalanceByAccountProps {
accountIndex: number;
fingerprint: string;
onPress?(): void;
}
export function BitcoinBalanceByAccount({
accountIndex,
fingerprint,
onPress,
}: BitcoinBalanceByAccountProps) {
const { availableBalance, fiatBalance } = useBitcoinAccountTotalBitcoinBalance({
accountIndex,
fingerprint,
});
return (
<BitcoinTokenBalance
availableBalance={availableBalance}
fiatBalance={fiatBalance}
onPress={onPress}
/>
);
}
33 changes: 26 additions & 7 deletions apps/mobile/src/features/balances/stacks/stacks-balance.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { TokenIcon } from '@/components/widgets/tokens/token-icon';
import { AccountId } from '@/models/domain.model';
import { useStxBalance } from '@/queries/balance/stacks-balance.query';
import { t } from '@lingui/macro';

Expand All @@ -11,17 +10,22 @@ import { useGetStacksAddresses } from './use-get-stacks-addresses';
interface StacksTokenBalanceProps {
availableBalance: Money;
fiatBalance: Money;
onPress?(): void;
}
export function StacksTokenBalance({ availableBalance, fiatBalance }: StacksTokenBalanceProps) {
export function StacksTokenBalance({
availableBalance,
fiatBalance,
onPress,
}: StacksTokenBalanceProps) {
return (
<TokenBalance
ticker="STX"
icon={<TokenIcon ticker="STX" />}
tokenName={t`Stacks`}
chain={t`Stacks blockchain`}
chain={t`Layer 1`}
fiatBalance={fiatBalance}
showChain={false}
availableBalance={availableBalance}
onPress={onPress}
/>
);
}
Expand All @@ -32,8 +36,23 @@ export function StacksBalance() {
return <StacksTokenBalance availableBalance={availableBalance} fiatBalance={fiatBalance} />;
}

export function StacksBalanceByAccount(props: AccountId) {
const addresses = useGetStacksAddresses(props);
interface StacksBalanceByAccountProps {
accountIndex: number;
fingerprint: string;
onPress?(): void;
}
export function StacksBalanceByAccount({
accountIndex,
fingerprint,
onPress,
}: StacksBalanceByAccountProps) {
const addresses = useGetStacksAddresses({ accountIndex, fingerprint });
const { availableBalance, fiatBalance } = useStxBalance(addresses);
return <StacksTokenBalance availableBalance={availableBalance} fiatBalance={fiatBalance} />;
return (
<StacksTokenBalance
availableBalance={availableBalance}
fiatBalance={fiatBalance}
onPress={onPress}
/>
);
}
24 changes: 13 additions & 11 deletions apps/mobile/src/features/balances/token-balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ReactNode } from 'react';
import { Balance } from '@/components/balance/balance';

import { Money } from '@leather.io/models';
import { Flag, ItemLayout } from '@leather.io/ui/native';
import { Flag, ItemLayout, Pressable } from '@leather.io/ui/native';

interface TokenBalanceProps {
ticker: string;
Expand All @@ -12,7 +12,7 @@ interface TokenBalanceProps {
availableBalance?: Money;
chain: string;
fiatBalance: Money;
showChain: boolean; // true except for BTC and STX
onPress?(): void;
}
export function TokenBalance({
ticker,
Expand All @@ -21,16 +21,18 @@ export function TokenBalance({
availableBalance,
chain,
fiatBalance,
showChain,
onPress,
}: TokenBalanceProps) {
return (
<Flag key={ticker} img={icon} align="middle" spacing="1" reverse={false}>
<ItemLayout
titleLeft={tokenName}
titleRight={availableBalance && <Balance balance={availableBalance} />}
captionLeft={showChain ? chain : ''}
captionRight={<Balance balance={fiatBalance} color="ink.text-subdued" />}
/>
</Flag>
<Pressable flexDirection="row" disabled={!onPress} onPress={onPress}>
<Flag key={ticker} img={icon}>
<ItemLayout
titleLeft={tokenName}
titleRight={availableBalance && <Balance balance={availableBalance} />}
captionLeft={chain}
captionRight={<Balance balance={fiatBalance} color="ink.text-subdued" />}
/>
</Flag>
</Pressable>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { AddressTypeBadge } from '@/components/address-type-badge';

import {
Box,
CopyIcon,
Flag,
IconButton,
ItemLayout,
Pressable,
Text,
} from '@leather.io/ui/native';

interface ReceiveAssetItemProps {
address: string;
addressType?: string;
assetName: string;
assetSymbol: string;
icon: React.ReactNode;
onCopy: () => void;
onPress: () => void;
}
export function ReceiveAssetItem({
address,
addressType,
assetName,
assetSymbol,
icon,
onCopy,
onPress,
}: ReceiveAssetItemProps) {
return (
<Pressable flexDirection="row" onPress={onPress}>
<Flag key={assetSymbol} img={icon}>
<ItemLayout
titleLeft={
<Box alignItems="center" flexDirection="row" gap="1">
<Text variant="label02">{assetName}</Text>
{addressType && <AddressTypeBadge type={addressType} />}
</Box>
}
actionIcon={<IconButton icon={<CopyIcon />} onPress={onCopy} />}
captionLeft={address}
/>
</Flag>
</Pressable>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { RefObject } from 'react';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

import { useSettings } from '@/store/settings/settings';
import { t } from '@lingui/macro';
import { useTheme } from '@shopify/restyle';

import { Box, Sheet, SheetRef, Text, Theme } from '@leather.io/ui/native';

interface ReceiveAssetSheetProps {
sheetRef: RefObject<SheetRef>;
}
export function ReceiveAssetSheet({ sheetRef }: ReceiveAssetSheetProps) {
const { bottom } = useSafeAreaInsets();
const { themeDerivedFromThemePreference } = useSettings();
const theme = useTheme<Theme>();

return (
<Sheet isScrollView ref={sheetRef} themeVariant={themeDerivedFromThemePreference}>
<Box
style={{
paddingBottom: theme.spacing[5] + bottom,
paddingHorizontal: theme.spacing[5],
paddingTop: theme.spacing[4],
}}
>
<Text>{t`Receive`}</Text>
</Box>
</Sheet>
);
}
Loading

0 comments on commit 4937d9b

Please sign in to comment.