Skip to content

Commit

Permalink
fix: improve dynamic sizing of virtuoso lists, ref #5149, #5242
Browse files Browse the repository at this point in the history
  • Loading branch information
pete-watters committed Apr 17, 2024
1 parent 4c9c167 commit 1a970b6
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 111 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@
"react-qr-code": "2.0.12",
"react-redux": "9.1.0",
"react-router-dom": "6.22.3",
"react-virtuoso": "4.7.1",
"react-virtuoso": "4.7.7",
"redux-persist": "6.0.0",
"rxjs": "7.8.1",
"style-loader": "3.3.4",
Expand Down
77 changes: 29 additions & 48 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions src/app/common/hooks/use-get-virtuoso-height.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { token } from 'leather-styles/tokens';

import { pxStringToNumber } from '@shared/utils/px-string-to-number';

import { useViewportMinWidth } from '@app/common/hooks/use-media-query';
import { useHasLedgerKeys } from '@app/store/ledger/ledger.selectors';
import { getHeightOffset } from '@app/ui/components/containers/dialog/dialog';

// virtuosoHeight = calc(InteractiveItem height - negative margin)
// calc(72px - 24px) = 58
export const virtuosoHeight = 58;

type VirtuosoVariants = 'footer' | 'no-footer' | 'popup';

export function useGetVirtuosoHeight(accountNum: number, variant: VirtuosoVariants) {
const isAtleastBreakpointMd = useViewportMinWidth('md');

const isLedger = useHasLedgerKeys();
const offset = getHeightOffset(true, !isLedger);

// TODO rename dialogHeight as actionPopupHeight in monorepo
const actionPopupHeight = token('sizes.dialogHeight');
// handles resizing of a full size browser - non popup
const isNarrowLargeWindow =
window.innerHeight > pxStringToNumber(actionPopupHeight) && !isAtleastBreakpointMd;

if (accountNum > 10) {
if (variant === 'popup') return '50vh';
if (isNarrowLargeWindow) {
return variant === 'footer' ? '85vh' : '95vh';
}
return variant === 'footer' ? '70vh' : '85vh';
}
const visibleAccounts = virtuosoHeight * accountNum;
return visibleAccounts + offset;
}
23 changes: 23 additions & 0 deletions src/app/common/hooks/use-media-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect, useState } from 'react';

import { BreakpointToken, token } from 'leather-styles/tokens';

function useMediaQuery(query: string) {
const [matches, setMatches] = useState(false);

useEffect(() => {
const media = window.matchMedia(query);
if (media.matches !== matches) {
setMatches(media.matches);
}
const listener = () => setMatches(media.matches);
window.addEventListener('resize', listener);
return () => window.removeEventListener('resize', listener);
}, [matches, query]);

return matches;
}

export function useViewportMinWidth(viewport: BreakpointToken) {
return useMediaQuery(`(min-width: ${token(`breakpoints.${viewport}`)})`);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { memo } from 'react';
import { memo, useCallback } from 'react';

import { useAccountDisplayName } from '@app/common/hooks/account/use-account-names';
import { useSwitchAccount } from '@app/common/hooks/account/use-switch-account';
Expand All @@ -8,49 +8,44 @@ import { AcccountAddresses } from '@app/components/account/account-addresses';
import { AccountListItemLayout } from '@app/components/account/account-list-item.layout';
import { AccountNameLayout } from '@app/components/account/account-name';
import { useNativeSegwitSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useStacksAccounts } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { type StacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.models';
import { AccountAvatarItem } from '@app/ui/components/account/account-avatar/account-avatar-item';

interface SwitchAccountListItemProps {
handleClose(): void;
currentAccountIndex: number;
index: number;
stxAccount: StacksAccount;
}
export const SwitchAccountListItem = memo(
({ handleClose, currentAccountIndex, index }: SwitchAccountListItemProps) => {
const stacksAccounts = useStacksAccounts();
const stxAddress = stacksAccounts[index]?.address || '';
({ handleClose, currentAccountIndex, index, stxAccount }: SwitchAccountListItemProps) => {
const bitcoinSigner = useNativeSegwitSigner(index);
const btcAddress = bitcoinSigner?.(0).address || '';

const { address: stxAddress, stxPublicKey } = stxAccount;

const { isLoading, setIsLoading, setIsIdle } = useLoading(
'SWITCH_ACCOUNTS' + stxAddress || btcAddress
);
const { handleSwitchAccount } = useSwitchAccount(handleClose);
const { name, isLoading: isLoadingBnsName } = useAccountDisplayName({
address: stxAddress,
address: stxAccount?.address,
index,
});

const handleClick = async () => {
const handleClick = useCallback(async () => {
setIsLoading();
setTimeout(async () => {
await handleSwitchAccount(index);
setIsIdle();
}, 80);
};
}, [index, handleSwitchAccount, setIsIdle, setIsLoading]);

return (
<AccountListItemLayout
accountAddresses={<AcccountAddresses index={index} />}
accountName={<AccountNameLayout isLoading={isLoadingBnsName}>{name}</AccountNameLayout>}
avatar={
<AccountAvatarItem
index={index}
publicKey={stacksAccounts[index]?.stxPublicKey || ''}
name={name}
/>
}
avatar={<AccountAvatarItem index={index} publicKey={stxPublicKey || ''} name={name} />}
balanceLabel={<AccountTotalBalance stxAddress={stxAddress} btcAddress={btcAddress} />}
index={index}
isLoading={isLoading}
Expand Down
Loading

0 comments on commit 1a970b6

Please sign in to comment.