Better lazy loading, and improve consistency between pages
parent
23121331dd
commit
4c76cc141f
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
|
|
@ -34,14 +35,32 @@ class DriftActivitiesPage extends HookConsumerWidget {
|
|||
scrollToBottom();
|
||||
}
|
||||
|
||||
void loadMoreIfNeeded() {
|
||||
if (activityNotifier.hasMore && !activityNotifier.isLoadingMore) {
|
||||
activityNotifier.loadMore();
|
||||
}
|
||||
}
|
||||
|
||||
void checkIfViewportNotFilled() {
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||
if (listViewScrollController.hasClients &&
|
||||
listViewScrollController.position.maxScrollExtent <= 0) {
|
||||
loadMoreIfNeeded();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-load more pages if content doesn't fill the viewport
|
||||
ref.listen(albumActivityProvider(album.id, assetId), (_, __) {
|
||||
checkIfViewportNotFilled();
|
||||
});
|
||||
|
||||
useEffect(() {
|
||||
void onScroll() {
|
||||
// In a reversed ListView, scrolling toward older items means reaching maxScrollExtent
|
||||
if (listViewScrollController.position.pixels >=
|
||||
listViewScrollController.position.maxScrollExtent - 200) {
|
||||
if (activityNotifier.hasMore && !activityNotifier.isLoadingMore) {
|
||||
activityNotifier.loadMore();
|
||||
}
|
||||
loadMoreIfNeeded();
|
||||
}
|
||||
}
|
||||
listViewScrollController.addListener(onScroll);
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ export class ActivityRepository {
|
|||
.$if(!!before, (qb) => qb.where('activity.createdAt', '<', before!))
|
||||
.$if(!!at, (qb) => qb.where('activity.createdAt', '=', at!))
|
||||
.orderBy('activity.createdAt', take !== undefined ? 'desc' : 'asc')
|
||||
.orderBy('activity.id', take !== undefined ? 'desc' : 'asc')
|
||||
.$if(take !== undefined, (qb) => qb.limit(take!))
|
||||
.execute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export class ActivityService extends BaseService {
|
|||
// Fetch all activities at exactly that timestamp and prepend any not already loaded.
|
||||
if (results.length > 0) {
|
||||
const boundaryTime = results[0].createdAt;
|
||||
const loadedIds = new Set(results.filter((a) => +new Date(a.createdAt) === +new Date(boundaryTime)).map((a) => a.id));
|
||||
const loadedIds = new Set(results.filter((a) => a.createdAt.getTime() === boundaryTime.getTime()).map((a) => a.id));
|
||||
const extras = await this.activityRepository.search({ ...searchOptions, at: boundaryTime });
|
||||
const newExtras = extras.map(mapActivity).filter((a) => !loadedIds.has(a.id));
|
||||
return [...newExtras, ...results];
|
||||
|
|
|
|||
|
|
@ -136,6 +136,21 @@
|
|||
}
|
||||
};
|
||||
|
||||
// Auto-load more pages if content doesn't fill the scroll container
|
||||
$effect(() => {
|
||||
// Track reactive dependencies
|
||||
void activityManager.activities.length;
|
||||
void activityManager.isLoadingMore;
|
||||
|
||||
if (!scrollContainer || !activityManager.hasMore || activityManager.isLoadingMore) return;
|
||||
// After rendering, check if there's no scrollable overflow
|
||||
tick().then(() => {
|
||||
if (scrollContainer && scrollContainer.scrollHeight <= scrollContainer.clientHeight) {
|
||||
void loadMoreAndPreserveScroll();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const onsubmit = async (event: Event) => {
|
||||
event.preventDefault();
|
||||
await handleSendComment();
|
||||
|
|
|
|||
Loading…
Reference in New Issue