mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-11 20:44:32 -05:00
Add loading indicator when loading more transactions in mobile transaction list (#3900)
* Add isLoadingMore property to useTransactions hook * Release notes * Start loading more earlier
This commit is contained in:
committed by
GitHub
parent
5104a1a563
commit
e96b986ad0
@@ -236,6 +236,7 @@ function TransactionListWithPreviews({
|
||||
transactions,
|
||||
isLoading,
|
||||
reload: reloadTransactions,
|
||||
isLoadingMore,
|
||||
loadMore: loadMoreTransactions,
|
||||
} = useTransactions({
|
||||
query: transactionsQuery,
|
||||
@@ -269,7 +270,7 @@ function TransactionListWithPreviews({
|
||||
tables.includes('category_mapping') ||
|
||||
tables.includes('payee_mapping')
|
||||
) {
|
||||
reloadTransactions?.();
|
||||
reloadTransactions();
|
||||
}
|
||||
|
||||
if (tables.includes('payees') || tables.includes('payee_mapping')) {
|
||||
@@ -326,6 +327,7 @@ function TransactionListWithPreviews({
|
||||
balance={balanceQueries.balance}
|
||||
balanceCleared={balanceQueries.cleared}
|
||||
balanceUncleared={balanceQueries.uncleared}
|
||||
isLoadingMore={isLoadingMore}
|
||||
onLoadMore={loadMoreTransactions}
|
||||
searchPlaceholder={`Search ${accountName}`}
|
||||
onSearch={onSearch}
|
||||
|
||||
@@ -40,6 +40,7 @@ export function CategoryTransactions({ category, month }) {
|
||||
const {
|
||||
transactions,
|
||||
isLoading,
|
||||
isLoadingMore,
|
||||
loadMore: loadMoreTransactions,
|
||||
reload: reloadTransactions,
|
||||
} = useTransactions({
|
||||
@@ -56,7 +57,7 @@ export function CategoryTransactions({ category, month }) {
|
||||
tables.includes('category_mapping') ||
|
||||
tables.includes('payee_mapping')
|
||||
) {
|
||||
reloadTransactions?.();
|
||||
reloadTransactions();
|
||||
}
|
||||
|
||||
if (tables.includes('payees') || tables.includes('payee_mapping')) {
|
||||
@@ -112,6 +113,7 @@ export function CategoryTransactions({ category, month }) {
|
||||
balanceUncleared={balanceUncleared}
|
||||
searchPlaceholder={`Search ${category.name}`}
|
||||
onSearch={onSearch}
|
||||
isLoadingMore={isLoadingMore}
|
||||
onLoadMore={loadMoreTransactions}
|
||||
onOpenTransaction={onOpenTransaction}
|
||||
/>
|
||||
|
||||
@@ -6,10 +6,9 @@ import React, {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { ListBox, Section, Header, Collection } from 'react-aria-components';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { t } from 'i18next';
|
||||
|
||||
import { setNotificationInset } from 'loot-core/client/actions';
|
||||
import { groupById, integerToCurrency } from 'loot-core/shared/util';
|
||||
import * as monthUtils from 'loot-core/src/shared/months';
|
||||
@@ -41,12 +40,32 @@ import { TransactionListItem } from './TransactionListItem';
|
||||
|
||||
const NOTIFICATION_BOTTOM_INSET = 75;
|
||||
|
||||
function Loading({ style, 'aria-label': ariaLabel }) {
|
||||
return (
|
||||
<View
|
||||
aria-label={ariaLabel || 'Loading...'}
|
||||
style={{
|
||||
backgroundColor: theme.mobilePageBackground,
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
<AnimatedLoading width={25} height={25} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
export function TransactionList({
|
||||
isLoading,
|
||||
transactions,
|
||||
onOpenTransaction,
|
||||
isLoadingMore,
|
||||
onLoadMore,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const sections = useMemo(() => {
|
||||
// Group by date. We can assume transactions is ordered
|
||||
const sections = [];
|
||||
@@ -83,29 +102,19 @@ export function TransactionList({
|
||||
);
|
||||
|
||||
useScrollListener(({ hasScrolledToEnd }) => {
|
||||
if (hasScrolledToEnd('down', 5)) {
|
||||
if (hasScrolledToEnd('down', 100)) {
|
||||
onLoadMore?.();
|
||||
}
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<View
|
||||
aria-label={t('Loading...')}
|
||||
style={{
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<AnimatedLoading width={25} height={25} />
|
||||
</View>
|
||||
);
|
||||
return <Loading aria-label={t('Loading transactions...')} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListBox
|
||||
aria-label="Transaction list"
|
||||
aria-label={t('Transaction list')}
|
||||
selectionMode={selectedTransactions.size > 0 ? 'multiple' : 'single'}
|
||||
selectedKeys={selectedTransactions}
|
||||
dependencies={[selectedTransactions]}
|
||||
@@ -159,6 +168,17 @@ export function TransactionList({
|
||||
</Section>
|
||||
)}
|
||||
</ListBox>
|
||||
|
||||
{isLoadingMore && (
|
||||
<Loading
|
||||
aria-label={t('Loading more transactions...')}
|
||||
style={{
|
||||
// Same height as transaction list item
|
||||
height: 60,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{selectedTransactions.size > 0 && (
|
||||
<SelectedTransactionsFloatingActionBar transactions={transactions} />
|
||||
)}
|
||||
|
||||
@@ -65,6 +65,7 @@ export function TransactionListWithBalances({
|
||||
balanceUncleared,
|
||||
searchPlaceholder = 'Search...',
|
||||
onSearch,
|
||||
isLoadingMore,
|
||||
onLoadMore,
|
||||
onOpenTransaction,
|
||||
onRefresh,
|
||||
@@ -104,6 +105,7 @@ export function TransactionListWithBalances({
|
||||
<TransactionList
|
||||
isLoading={isLoading}
|
||||
transactions={transactions}
|
||||
isLoadingMore={isLoadingMore}
|
||||
onLoadMore={onLoadMore}
|
||||
onOpenTransaction={onOpenTransaction}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState, useMemo } from 'react';
|
||||
import { useEffect, useRef, useState, useMemo, useCallback } from 'react';
|
||||
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
@@ -24,10 +24,11 @@ type UseTransactionsProps = {
|
||||
|
||||
type UseTransactionsResult = {
|
||||
transactions: ReadonlyArray<TransactionEntity>;
|
||||
isLoading?: boolean;
|
||||
isLoading: boolean;
|
||||
error?: Error;
|
||||
reload?: () => void;
|
||||
loadMore?: () => void;
|
||||
reload: () => void;
|
||||
loadMore: () => void;
|
||||
isLoadingMore: boolean;
|
||||
};
|
||||
|
||||
export function useTransactions({
|
||||
@@ -35,6 +36,7 @@ export function useTransactions({
|
||||
options = { pageCount: 50 },
|
||||
}: UseTransactionsProps): UseTransactionsResult {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
||||
const [error, setError] = useState<Error | undefined>(undefined);
|
||||
const [transactions, setTransactions] = useState<
|
||||
ReadonlyArray<TransactionEntity>
|
||||
@@ -88,12 +90,32 @@ export function useTransactions({
|
||||
};
|
||||
}, [query]);
|
||||
|
||||
const loadMore = useCallback(async () => {
|
||||
if (!pagedQueryRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoadingMore(true);
|
||||
|
||||
await pagedQueryRef.current
|
||||
.fetchNext()
|
||||
.catch(setError)
|
||||
.finally(() => {
|
||||
setIsLoadingMore(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const reload = useCallback(() => {
|
||||
pagedQueryRef.current?.run();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
transactions,
|
||||
isLoading,
|
||||
error,
|
||||
reload: pagedQueryRef.current?.run,
|
||||
loadMore: pagedQueryRef.current?.fetchNext,
|
||||
reload,
|
||||
loadMore,
|
||||
isLoadingMore,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
6
upcoming-release-notes/3900.md
Normal file
6
upcoming-release-notes/3900.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Enhancements
|
||||
authors: [joel-jeremy]
|
||||
---
|
||||
|
||||
Add loading indicator when loading more transactions in mobile transaction list.
|
||||
Reference in New Issue
Block a user