feat: fetch the next page of books before the reader hits the bottom
The prefetch zone is a viewport deep rather than 200px, and the observer re-observes after a page lands so a chain of loads is not cut short.
This commit is contained in:
@@ -28,6 +28,8 @@ export class BookCollectionState {
|
||||
public moreBooks = $state(false);
|
||||
private currentBookPage = $state(1);
|
||||
public loading = $state(false);
|
||||
/** A page append, as opposed to `loading`, which replaces the whole list. */
|
||||
public loadingMore = $state(false);
|
||||
|
||||
/**
|
||||
* Whether the reader has loaded past the first page. Anything that refetches
|
||||
@@ -165,22 +167,37 @@ export class BookCollectionState {
|
||||
});
|
||||
|
||||
this.books = [...result.items];
|
||||
this.moreBooks = result.total > result.items.length;
|
||||
this.currentBookPage = 1;
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetching means the trigger can fire again while a page is still in
|
||||
* flight, so the guard is here rather than in the observer — every caller
|
||||
* gets it, and a second call is dropped instead of duplicating a page.
|
||||
*/
|
||||
async loadMoreBooks() {
|
||||
const result = await this.ops.listBooks({
|
||||
currentPage: this.currentBookPage + 1,
|
||||
pageSize: 50,
|
||||
sortOrder: this.sortOrder,
|
||||
orderBy: this.orderBy,
|
||||
...this.filters
|
||||
});
|
||||
if (this.loadingMore || !this.moreBooks) return;
|
||||
|
||||
this.books = [...this.books, ...result.items];
|
||||
this.moreBooks = result.total > this.books.length;
|
||||
this.currentBookPage++;
|
||||
this.loadingMore = true;
|
||||
try {
|
||||
const result = await this.ops.listBooks({
|
||||
currentPage: this.currentBookPage + 1,
|
||||
pageSize: 50,
|
||||
sortOrder: this.sortOrder,
|
||||
orderBy: this.orderBy,
|
||||
...this.filters
|
||||
});
|
||||
|
||||
this.books = [...this.books, ...result.items];
|
||||
// An empty page means the count we were given was stale; stop asking
|
||||
// rather than loop on a page that never grows the list.
|
||||
this.moreBooks = result.items.length > 0 && result.total > this.books.length;
|
||||
this.currentBookPage++;
|
||||
} finally {
|
||||
this.loadingMore = false;
|
||||
}
|
||||
}
|
||||
|
||||
updateBooks(books: PaginatedResponse<Book>) {
|
||||
|
||||
Reference in New Issue
Block a user