Add infinite scroll and pull to refresh#499
Conversation
- refactor DRY widget - delete redundant provider - fix bad number formatting locale
…into beast/language-support
- use intl from sdk - import legacy provider
Setting already cleared in substarte service logout
- implement infinite scroll - implement pull to refresh
…into beast/language-support
…etwork/quantus-apps into beast/integrate-infinite-scroll-and-refresh-to-activity-screen
…etwork/quantus-apps into beast/integrate-infinite-scroll-and-refresh-to-activity-screen
…into beast/add-infinite-scroll-and-pull-to-refresh
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a7a831a. Configure here.
| if (pagination == null || pagination.isFetching) return; | ||
|
|
||
| await activeAccountPaginationNotifier(ref, _filterOption)?.loadingRefresh(); | ||
| } |
There was a problem hiding this comment.
Filter change keeps scroll offset
Medium Severity
Changing the activity filter causes the _scrollController to retain its previous scroll position. This means the new list might not start at the top, hiding recent items, and can immediately trigger fetchMore() without user interaction.
Reviewed by Cursor Bugbot for commit a7a831a. Configure here.
| if (pagination == null || pagination.isFetching || !pagination.hasMore) return; | ||
|
|
||
| activeAccountPaginationNotifier(ref, _filterOption)?.fetchMore(); | ||
| } |
There was a problem hiding this comment.
Premature infinite scroll fetch
Medium Severity
_onScroll treats pixels >= maxScrollExtent - 200 as “near bottom,” but when the list is shorter than the viewport maxScrollExtent is often zero or small, so that condition is true at scroll offset zero and fetchMore() runs without the user reaching the end of the list.
Reviewed by Cursor Bugbot for commit a7a831a. Configure here.
|
I've done a thorough review of PR #499. Here's my analysis. PR #499 Review — Add infinite scroll and pull to refreshOverall this is a clean, well-scoped UX improvement. The core mechanics (shared Behavior issues1. Pull-to-refresh wipes the list to skeletons (UX regression). final targetAccountIds = _getAccountIds();
if (targetAccountIds.isEmpty) {
state = PaginationState.initial().copyWith(hasMore: false);
return;
}
// Reset to initial state to show loading
state = PaginationState.initial();
await _fetchPage(targetAccountIds);After that, the combined provider returns Pick one of:
2. void _onScroll() {
if (!_scrollController.hasClients) return;
final pos = _scrollController.position;
if (pos.pixels < pos.maxScrollExtent - _loadMoreThreshold) return;
final pagination = ref.read(activeAccountPaginationProvider(_filterOption));
if (pagination == null || pagination.isFetching || !pagination.hasMore) return;
activeAccountPaginationNotifier(ref, _filterOption)?.fetchMore();
}When the list is shorter than the viewport, if (pos.maxScrollExtent <= 0) return;
if (pos.pixels < pos.maxScrollExtent - _loadMoreThreshold) return;If you actually want auto-fill-to-viewport behavior (fetch more until the list fills the screen), do it explicitly in the controller after a fetch completes, not as a side-effect of touching the screen. 3. Bugbot's "filter change keeps scroll offset" — not actually a bug, but worth confirming. You added API / semantics4. hasMore: hasMore ?? this.hasMore,
isFetching: isFetching ?? this.isFetching,
error: error,
stackTrace: stackTrace,This is the right fix for "can't clear the error", but it changes semantics for every call site: any 5. if (pagination.isFetching && pagination.otherTransfers.isEmpty) {
return const AsyncValue.loading();
}You added Minor / style6. Logging inconsistency. Providers now use 7. Naming: 8. Duplicated 9. 10. Things I think are good
RecommendationApprove with the following changes requested:
The rest (naming, DRY of Want me to apply any of these as edits, or open follow-up comments on the PR? Per your rules, I won't post to GitHub or push without your go-ahead. |


Summary
Continuation of this PR #493 , closing that one because of broken git history.
Note
Low Risk
UI and pagination UX changes with no auth or payment logic; load-more errors are logged instead of replacing the list.
Overview
The Activity screen now supports pull-to-refresh and infinite scroll for the active account’s transaction list (per send/receive/all filter), wired to the existing filtered pagination controller.
New Riverpod helpers expose pagination state and the notifier for the active account so the UI can call
fetchMorenear the list bottom andloadingRefreshon refresh. The list uses a sharedScrollController, always-scrollable physics (including empty state), a load-more footer loader, and a filter-keyed list so scroll behavior resets when the filter changes.Pagination behavior is tightened:
hasLoadedChainDatadistinguishes initial load failures from load-more errors—providers only surfaceAsyncValue.errorwhen there is no cached chain data; otherwise they log and keep showing existing rows.PaginationState.copyWithnow replaceserror/stackTracewhen passed (including clearing withnull) instead of keeping stale errors. Analyzer excludesbuild/**.Reviewed by Cursor Bugbot for commit a7a831a. Bugbot is set up for automated code reviews on this repo. Configure here.