mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-11 12:43:09 -05:00
Mobile Payees - move to react-aria GridList to improve performance (#5802)
This commit is contained in:
committed by
GitHub
parent
6365a8f4bb
commit
3559b2df3a
@@ -1,5 +1,5 @@
|
||||
---
|
||||
description:
|
||||
description:
|
||||
globs: *.ts,*.tsx
|
||||
alwaysApply: false
|
||||
---
|
||||
@@ -21,7 +21,7 @@ Naming Conventions
|
||||
|
||||
TypeScript Usage
|
||||
|
||||
- Use TypeScript for all code; prefer interfaces over types.
|
||||
- Use TypeScript for all code; prefer types over interfaces.
|
||||
- Avoid enums; use objects or maps instead.
|
||||
- Avoid using `any` or `unknown` unless absolutely necessary. Look for type definitions in the codebase instead.
|
||||
- Avoid type assertions with `as` or `!`; prefer using `satisfies`.
|
||||
|
||||
@@ -154,4 +154,10 @@ export const styles: Record<string, any> = {
|
||||
borderRadius: 4,
|
||||
padding: '3px 5px',
|
||||
},
|
||||
mobileListItem: {
|
||||
borderBottom: `1px solid ${theme.tableBorder}`,
|
||||
backgroundColor: theme.tableBackground,
|
||||
padding: 16,
|
||||
cursor: 'pointer',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Trans } from 'react-i18next';
|
||||
import { GridList } from 'react-aria-components';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import { AnimatedLoading } from '@actual-app/components/icons/AnimatedLoading';
|
||||
import { Text } from '@actual-app/components/text';
|
||||
@@ -24,6 +25,8 @@ export function PayeesList({
|
||||
isLoading = false,
|
||||
onPayeePress,
|
||||
}: PayeesListProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (isLoading && payees.length === 0) {
|
||||
return (
|
||||
<View
|
||||
@@ -63,22 +66,30 @@ export function PayeesList({
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{ flex: 1, paddingBottom: MOBILE_NAV_HEIGHT, overflow: 'auto' }}
|
||||
>
|
||||
{payees.map(payee => (
|
||||
<PayeesListItem
|
||||
key={payee.id}
|
||||
payee={payee}
|
||||
ruleCount={ruleCounts.get(payee.id) ?? 0}
|
||||
onPress={() => onPayeePress(payee)}
|
||||
/>
|
||||
))}
|
||||
<View>
|
||||
<GridList
|
||||
aria-label={t('Payees')}
|
||||
aria-busy={isLoading || undefined}
|
||||
items={payees}
|
||||
style={{
|
||||
flex: 1,
|
||||
paddingBottom: MOBILE_NAV_HEIGHT,
|
||||
overflow: 'auto',
|
||||
}}
|
||||
>
|
||||
{payee => (
|
||||
<PayeesListItem
|
||||
value={payee}
|
||||
ruleCount={ruleCounts.get(payee.id) ?? 0}
|
||||
onAction={() => onPayeePress(payee)}
|
||||
/>
|
||||
)}
|
||||
</GridList>
|
||||
{isLoading && (
|
||||
<View
|
||||
style={{
|
||||
alignItems: 'center',
|
||||
paddingVertical: 20,
|
||||
paddingTop: 20,
|
||||
}}
|
||||
>
|
||||
<AnimatedLoading style={{ width: 20, height: 20 }} />
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from 'react';
|
||||
import React, { memo } from 'react';
|
||||
import { GridListItem, type GridListItemProps } from 'react-aria-components';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Button } from '@actual-app/components/button';
|
||||
import { SvgBookmark } from '@actual-app/components/icons/v1';
|
||||
import { SpaceBetween } from '@actual-app/components/space-between';
|
||||
import { styles } from '@actual-app/components/styles';
|
||||
import { theme } from '@actual-app/components/theme';
|
||||
|
||||
import { type PayeeEntity } from 'loot-core/types/models';
|
||||
@@ -11,84 +12,82 @@ import { type PayeeEntity } from 'loot-core/types/models';
|
||||
import { PayeeRuleCountLabel } from '@desktop-client/components/payees/PayeeRuleCountLabel';
|
||||
|
||||
type PayeesListItemProps = {
|
||||
payee: PayeeEntity;
|
||||
value: PayeeEntity;
|
||||
ruleCount: number;
|
||||
onPress: () => void;
|
||||
};
|
||||
} & Omit<GridListItemProps<PayeeEntity>, 'value'>;
|
||||
|
||||
export function PayeesListItem({
|
||||
payee,
|
||||
export const PayeesListItem = memo(function PayeeListItem({
|
||||
value: payee,
|
||||
ruleCount,
|
||||
onPress,
|
||||
...props
|
||||
}: PayeesListItemProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="bare"
|
||||
style={{
|
||||
minHeight: 56,
|
||||
width: '100%',
|
||||
borderRadius: 0,
|
||||
borderWidth: '0 0 1px 0',
|
||||
borderColor: theme.tableBorder,
|
||||
borderStyle: 'solid',
|
||||
backgroundColor: theme.tableBackground,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
padding: '12px 16px',
|
||||
gap: 5,
|
||||
}}
|
||||
onPress={onPress}
|
||||
>
|
||||
{payee.favorite && (
|
||||
<SvgBookmark
|
||||
width={15}
|
||||
height={15}
|
||||
style={{
|
||||
color: theme.pageText,
|
||||
flexShrink: 0,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<SpaceBetween
|
||||
style={{
|
||||
justifyContent: 'space-between',
|
||||
flex: 1,
|
||||
alignItems: 'flex-start',
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
fontSize: 15,
|
||||
fontWeight: 500,
|
||||
color: payee.transfer_acct ? theme.pageTextSubdued : theme.pageText,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
flex: 1,
|
||||
textAlign: 'left',
|
||||
}}
|
||||
title={payee.name}
|
||||
>
|
||||
{(payee.transfer_acct ? t('Transfer: ') : '') + payee.name}
|
||||
</span>
|
||||
const label = payee.transfer_acct
|
||||
? t('Transfer: {{name}}', { name: payee.name })
|
||||
: payee.name;
|
||||
|
||||
<span
|
||||
return (
|
||||
<GridListItem
|
||||
id={payee.id}
|
||||
value={payee}
|
||||
textValue={label}
|
||||
style={styles.mobileListItem}
|
||||
{...props}
|
||||
>
|
||||
<SpaceBetween gap={5}>
|
||||
{payee.favorite && (
|
||||
<SvgBookmark
|
||||
aria-hidden
|
||||
focusable={false}
|
||||
width={15}
|
||||
height={15}
|
||||
style={{
|
||||
color: theme.pageText,
|
||||
flexShrink: 0,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<SpaceBetween
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
padding: '3px 6px',
|
||||
backgroundColor: theme.noticeBackground,
|
||||
border: '1px solid ' + theme.noticeBackground,
|
||||
color: theme.noticeTextDark,
|
||||
fontSize: 12,
|
||||
flexShrink: 0,
|
||||
justifyContent: 'space-between',
|
||||
flex: 1,
|
||||
alignItems: 'flex-start',
|
||||
}}
|
||||
>
|
||||
<PayeeRuleCountLabel count={ruleCount} style={{ fontSize: 12 }} />
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
fontSize: 15,
|
||||
fontWeight: 500,
|
||||
color: payee.transfer_acct
|
||||
? theme.pageTextSubdued
|
||||
: theme.pageText,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
flex: 1,
|
||||
textAlign: 'left',
|
||||
}}
|
||||
title={label}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
|
||||
<span
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
padding: '3px 6px',
|
||||
backgroundColor: theme.noticeBackground,
|
||||
border: '1px solid ' + theme.noticeBackground,
|
||||
color: theme.noticeTextDark,
|
||||
fontSize: 12,
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
<PayeeRuleCountLabel count={ruleCount} style={{ fontSize: 12 }} />
|
||||
</span>
|
||||
</SpaceBetween>
|
||||
</SpaceBetween>
|
||||
</Button>
|
||||
</GridListItem>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
6
upcoming-release-notes/5802.md
Normal file
6
upcoming-release-notes/5802.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Maintenance
|
||||
authors: [MatissJanis]
|
||||
---
|
||||
|
||||
Mobile payee list - moved to react-aria GridList to improve performance
|
||||
Reference in New Issue
Block a user