Skip to content

Commit

Permalink
fix: fix big prefetch index not working for prepending (#12)
Browse files Browse the repository at this point in the history
* fix: fix prepend load when `prefetchIndex` is far from the items visible on the screen.

Signed-off-by: Sahil Kumar <xdsahil@gmail.com>

* chore: update CHANGELOG.md

Signed-off-by: Sahil Kumar <xdsahil@gmail.com>

---------

Signed-off-by: Sahil Kumar <xdsahil@gmail.com>
  • Loading branch information
xsahil03x authored Dec 1, 2024
1 parent 72ab5dc commit 39bb3be
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 105 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
6 changes: 6 additions & 0 deletions lib/src/page_fetcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class PageFetcher<Key, Value> extends ValueNotifier<PagingState<Key, Value>> {
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);

Expand Down Expand Up @@ -145,6 +148,9 @@ class PageFetcher<Key, Value> extends ValueNotifier<PagingState<Key, Value>> {
'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;

Expand Down
82 changes: 23 additions & 59 deletions lib/src/widget/bidirectional_paging_list_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,34 +348,20 @@ class _BidirectionalPagingListViewState<Key, Value>
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);
});
},
),
),
Expand All @@ -392,30 +378,16 @@ class _BidirectionalPagingListViewState<Key, Value>
// 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);
});
},
),
),
Expand Down Expand Up @@ -471,24 +443,16 @@ class _BidirectionalPagingListViewState<Key, Value>
// 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;
Expand Down
60 changes: 14 additions & 46 deletions lib/src/widget/paging_sliver_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -210,31 +210,11 @@ class _PagingSliverListState<Key, Value>
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);
});
},
),
),
Expand All @@ -258,36 +238,24 @@ class _PagingSliverListState<Key, Value>

SliverChildDelegate _createDelegate(
List<LoadResultPage<Key, Value>> pages, {
VoidCallback? onBuildingPrependLoadTriggerItem,
VoidCallback? onBuildingAppendLoadTriggerItem,
}) {
final items = pages.items;
final itemCount = items.length;
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;
Expand All @@ -297,8 +265,8 @@ class _PagingSliverListState<Key, Value>
(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);
Expand All @@ -319,8 +287,8 @@ class _PagingSliverListState<Key, Value>

return SliverChildBuilderDelegate(
(BuildContext context, int index) {
// Generate prepend and append notification.
generatePrependAppendLoadTriggerNotification(index);
// Generate append notification.
generateAppendLoadTriggerNotification(index);

// Build items.
return itemBuilder(context, index);
Expand Down

0 comments on commit 39bb3be

Please sign in to comment.