loadMore method
Appends the next page. A failure here keeps whatever is already on screen — losing a scrolled list because page four timed out is worse than the missing page — but loadMoreFailed still flips, so the trailing row can show a retry instead of a spinner that never resolves into anything the user is told about.
A 401 is the exception, and it is why isUnauthenticated is set here too: the session is gone, so every retry the trailing row offers will fail the same way, and the screen has to be told to route to the unauthenticated state rather than show a generic retry forever. Keeping the rows is right for a timeout and wrong for a signed-out user.
Implementation
Future<void> loadMore() async {
if (!_hasMore || _isLoadingMore || _status.isLoading) return;
final requestId = ++_requestId;
_isLoadingMore = true;
_loadMoreFailed = false;
_errorMessage = null;
notifyListeners();
try {
final page = await source.list(
resource.key,
page: _page + 1,
search: _searchTerm,
sort: _activeSort?.key,
direction: _activeSort?.direction,
filters: _filters,
);
// Appending a stale page would splice the previous query's rows into the
// new result set, and take `hasMore` from the wrong query.
if (requestId != _requestId) return;
_records = [..._records, ...page.records];
_page = page.meta.currentPage;
_hasMore = page.meta.hasMore;
} catch (e) {
if (requestId != _requestId) return;
_errorMessage = messageOf(e);
_loadMoreFailed = true;
if (e is FilamentTransportException && e.statusCode == 401) {
_isUnauthenticated = true;
_status = LoadStatus.failure;
}
}
_isLoadingMore = false;
notifyListeners();
}