From 39bb3be2f43759217ebba1bdc13260e2a92a0ef9 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Sun, 1 Dec 2024 19:46:03 +0100 Subject: [PATCH] fix: fix big prefetch index not working for prepending (#12) * fix: fix prepend load when `prefetchIndex` is far from the items visible on the screen. Signed-off-by: Sahil Kumar * chore: update CHANGELOG.md Signed-off-by: Sahil Kumar --------- Signed-off-by: Sahil Kumar --- CHANGELOG.md | 1 + lib/src/page_fetcher.dart | 6 ++ .../bidirectional_paging_list_view.dart | 82 ++++++------------- lib/src/widget/paging_sliver_list.dart | 60 ++++---------- 4 files changed, 44 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69700db..e25da73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Upcoming +- [[#11]](https://github.com/xsahil03x/super_paging/issues/11) Fix generating prepend load trigger notification when `prefetchIndex` is bigger than the items visible on the screen. - [[#7](https://github.com/xsahil03x/super_paging/issues/7)] Fix generating load trigger notification when `itemCount` is less than `prefetchIndex`. - Added support for the `Pager.refresh` method to accept an optional `refreshKey` parameter. diff --git a/lib/src/page_fetcher.dart b/lib/src/page_fetcher.dart index 5358e5e..941ef43 100644 --- a/lib/src/page_fetcher.dart +++ b/lib/src/page_fetcher.dart @@ -94,6 +94,9 @@ class PageFetcher extends ValueNotifier> { log.fine('Initial load cancelled'); }, () async { + // Skip load if already in a loading state. + if (value.getLoadState(LoadType.refresh) case Loading()) return; + // Update load state to loading. value = value.setLoading(LoadType.refresh); @@ -145,6 +148,9 @@ class PageFetcher extends ValueNotifier> { 'Use doInitialLoad for LoadType == refresh', ); + // Skip load if already in a loading state. + if (value.getLoadState(loadType) case Loading()) return; + final loadKey = _nextLoadKeyOrNull(loadType); if (loadKey == null) return; diff --git a/lib/src/widget/bidirectional_paging_list_view.dart b/lib/src/widget/bidirectional_paging_list_view.dart index 5e30e6d..a80e806 100644 --- a/lib/src/widget/bidirectional_paging_list_view.dart +++ b/lib/src/widget/bidirectional_paging_list_view.dart @@ -348,34 +348,20 @@ class _BidirectionalPagingListViewState topPages, reverse: true, onBuildingPrependLoadTriggerItem: () { - final canMakeRequest = prependLoadState.maybeMap( - notLoading: (it) => !it.endOfPaginationReached, - orElse: () => false, - ); - - if (canMakeRequest) { - // Schedules the request for the end of this frame. - WidgetsBinding.instance.addPostFrameCallback((_) { - pager.load(LoadType.prepend); - }); - } + // Schedules the request for the end of this frame. + WidgetsBinding.instance.addPostFrameCallback((_) { + pager.load(LoadType.prepend); + }); }, onBuildingAppendLoadTriggerItem: () { // If the bottom list contain items, we don't need to handle // append here. if (!bottomPages.isListEmpty) return; - final canMakeRequest = appendLoadState.maybeMap( - notLoading: (it) => !it.endOfPaginationReached, - orElse: () => false, - ); - - if (canMakeRequest) { - // Schedules the request for the end of this frame. - WidgetsBinding.instance.addPostFrameCallback((_) { - pager.load(LoadType.append); - }); - } + // Schedules the request for the end of this frame. + WidgetsBinding.instance.addPostFrameCallback((_) { + pager.load(LoadType.append); + }); }, ), ), @@ -392,30 +378,16 @@ class _BidirectionalPagingListViewState // prepend here. if (!topPages.isListEmpty) return; - final canMakeRequest = prependLoadState.maybeMap( - notLoading: (it) => !it.endOfPaginationReached, - orElse: () => false, - ); - - if (canMakeRequest) { - // Schedules the request for the end of this frame. - WidgetsBinding.instance.addPostFrameCallback((_) { - pager.load(LoadType.prepend); - }); - } + // Schedules the request for the end of this frame. + WidgetsBinding.instance.addPostFrameCallback((_) { + pager.load(LoadType.prepend); + }); }, onBuildingAppendLoadTriggerItem: () { - final canMakeRequest = appendLoadState.maybeMap( - notLoading: (it) => !it.endOfPaginationReached, - orElse: () => false, - ); - - if (canMakeRequest) { - // Schedules the request for the end of this frame. - WidgetsBinding.instance.addPostFrameCallback((_) { - pager.load(LoadType.append); - }); - } + // Schedules the request for the end of this frame. + WidgetsBinding.instance.addPostFrameCallback((_) { + pager.load(LoadType.append); + }); }, ), ), @@ -471,24 +443,16 @@ class _BidirectionalPagingListViewState // notifications. if (prefetchIndex == null) return; - // Generate notifications at the beginning and end of the list if the - // [itemCount] is less than [prefetchIndex]. - if (prefetchIndex > itemCount) { - if (index == 0) onBuildingPrependLoadTriggerItem?.call(); - if (index == itemCount - 1) onBuildingAppendLoadTriggerItem?.call(); - return; - } - - // Check if the index corresponds to near the top or bottom of the list - // based on the [reverse] flag. - final (nearTop, nearBottom) = switch (reverse) { - true => (index == itemCount - prefetchIndex, index == prefetchIndex), - false => (index == prefetchIndex, index == itemCount - prefetchIndex), + // Check if the index is near the edge of the list based on the prefetch + // index and the direction of the list. + final (shouldPrependItems, shouldAppendItems) = switch (reverse) { + true => (index >= itemCount - prefetchIndex, index <= prefetchIndex), + false => (index <= prefetchIndex, index >= itemCount - prefetchIndex), }; // Generate notifications. - if (nearTop) onBuildingPrependLoadTriggerItem?.call(); - if (nearBottom) onBuildingAppendLoadTriggerItem?.call(); + if (shouldPrependItems) onBuildingPrependLoadTriggerItem?.call(); + if (shouldAppendItems) onBuildingAppendLoadTriggerItem?.call(); } final separatorBuilder = widget.separatorBuilder; diff --git a/lib/src/widget/paging_sliver_list.dart b/lib/src/widget/paging_sliver_list.dart index 4ce01ae..101aefb 100644 --- a/lib/src/widget/paging_sliver_list.dart +++ b/lib/src/widget/paging_sliver_list.dart @@ -210,31 +210,11 @@ class _PagingSliverListState SliverList( delegate: _createDelegate( pages, - onBuildingPrependLoadTriggerItem: () { - final canMakeRequest = prependLoadState.maybeMap( - notLoading: (it) => !it.endOfPaginationReached, - orElse: () => false, - ); - - if (canMakeRequest) { - // Schedules the request for the end of this frame. - WidgetsBinding.instance.addPostFrameCallback((_) { - pager.load(LoadType.prepend); - }); - } - }, onBuildingAppendLoadTriggerItem: () { - final canMakeRequest = appendLoadState.maybeMap( - notLoading: (it) => !it.endOfPaginationReached, - orElse: () => false, - ); - - if (canMakeRequest) { - // Schedules the request for the end of this frame. - WidgetsBinding.instance.addPostFrameCallback((_) { - pager.load(LoadType.append); - }); - } + // Schedules the request for the end of this frame. + WidgetsBinding.instance.addPostFrameCallback((_) { + pager.load(LoadType.append); + }); }, ), ), @@ -258,7 +238,6 @@ class _PagingSliverListState SliverChildDelegate _createDelegate( List> pages, { - VoidCallback? onBuildingPrependLoadTriggerItem, VoidCallback? onBuildingAppendLoadTriggerItem, }) { final items = pages.items; @@ -266,28 +245,17 @@ class _PagingSliverListState final prefetchIndex = pager.config.prefetchIndex; // Helper function to generate prepend and append load trigger notifications - void generatePrependAppendLoadTriggerNotification(int index) { + void generateAppendLoadTriggerNotification(int index) { // If there is no prefetch index, we don't have to generate any // notification. if (prefetchIndex == null) return; - // Generate notifications at the beginning and end of the list if the - // [itemCount] is less than [prefetchIndex]. - if (prefetchIndex > itemCount) { - if (index == 0) onBuildingPrependLoadTriggerItem?.call(); - if (index == itemCount - 1) onBuildingAppendLoadTriggerItem?.call(); - return; - } - - // Check if the index corresponds to near the top or bottom of the list. - final (nearTop, nearBottom) = ( - index == prefetchIndex, - index == itemCount - prefetchIndex, - ); + // Check if the index is close to the end of the list based on the + // prefetch index. + final shouldAppendItems = index >= itemCount - prefetchIndex; - // Generate notifications. - if (nearTop) onBuildingPrependLoadTriggerItem?.call(); - if (nearBottom) onBuildingAppendLoadTriggerItem?.call(); + // Generate notification. + if (shouldAppendItems) onBuildingAppendLoadTriggerItem?.call(); } final itemBuilder = widget.itemBuilder; @@ -297,8 +265,8 @@ class _PagingSliverListState (BuildContext context, int index) { final int itemIndex = index ~/ 2; if (index.isEven) { - // Generate prepend and append notification. - generatePrependAppendLoadTriggerNotification(itemIndex); + // Generate append notification. + generateAppendLoadTriggerNotification(itemIndex); // Build items. return itemBuilder(context, itemIndex); @@ -319,8 +287,8 @@ class _PagingSliverListState return SliverChildBuilderDelegate( (BuildContext context, int index) { - // Generate prepend and append notification. - generatePrependAppendLoadTriggerNotification(index); + // Generate append notification. + generateAppendLoadTriggerNotification(index); // Build items. return itemBuilder(context, index);