Skip to content

Commit

Permalink
Add loading indicator when loading more transactions in mobile transa…
Browse files Browse the repository at this point in the history
…ction list (#3900)

* Add isLoadingMore property to useTransactions hook

* Release notes

* Start loading more earlier
  • Loading branch information
joel-jeremy authored Dec 10, 2024
1 parent 5104a1a commit e96b986
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ function TransactionListWithPreviews({
transactions,
isLoading,
reload: reloadTransactions,
isLoadingMore,
loadMore: loadMoreTransactions,
} = useTransactions({
query: transactionsQuery,
Expand Down Expand Up @@ -269,7 +270,7 @@ function TransactionListWithPreviews({
tables.includes('category_mapping') ||
tables.includes('payee_mapping')
) {
reloadTransactions?.();
reloadTransactions();
}

if (tables.includes('payees') || tables.includes('payee_mapping')) {
Expand Down Expand Up @@ -326,6 +327,7 @@ function TransactionListWithPreviews({
balance={balanceQueries.balance}
balanceCleared={balanceQueries.cleared}
balanceUncleared={balanceQueries.uncleared}
isLoadingMore={isLoadingMore}
onLoadMore={loadMoreTransactions}
searchPlaceholder={`Search ${accountName}`}
onSearch={onSearch}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function CategoryTransactions({ category, month }) {
const {
transactions,
isLoading,
isLoadingMore,
loadMore: loadMoreTransactions,
reload: reloadTransactions,
} = useTransactions({
Expand All @@ -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')) {
Expand Down Expand Up @@ -112,6 +113,7 @@ export function CategoryTransactions({ category, month }) {
balanceUncleared={balanceUncleared}
searchPlaceholder={`Search ${category.name}`}
onSearch={onSearch}
isLoadingMore={isLoadingMore}
onLoadMore={loadMoreTransactions}
onOpenTransaction={onOpenTransaction}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 = [];
Expand Down Expand Up @@ -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]}
Expand Down Expand Up @@ -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} />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export function TransactionListWithBalances({
balanceUncleared,
searchPlaceholder = 'Search...',
onSearch,
isLoadingMore,
onLoadMore,
onOpenTransaction,
onRefresh,
Expand Down Expand Up @@ -104,6 +105,7 @@ export function TransactionListWithBalances({
<TransactionList
isLoading={isLoading}
transactions={transactions}
isLoadingMore={isLoadingMore}
onLoadMore={onLoadMore}
onOpenTransaction={onOpenTransaction}
/>
Expand Down
34 changes: 28 additions & 6 deletions packages/loot-core/src/client/data-hooks/transactions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useRef, useState, useMemo } from 'react';
import { useEffect, useRef, useState, useMemo, useCallback } from 'react';

import debounce from 'lodash/debounce';

Expand All @@ -24,17 +24,19 @@ 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({
query,
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>
Expand Down Expand Up @@ -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,
};
}

Expand Down
6 changes: 6 additions & 0 deletions upcoming-release-notes/3900.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [joel-jeremy]
---

Add loading indicator when loading more transactions in mobile transaction list.

0 comments on commit e96b986

Please sign in to comment.