fix: timeline pagination

This commit is contained in:
Erwan Leboucher 2026-08-09 23:13:54 +02:00
commit 0f364d7613
No known key found for this signature in database
GPG key ID: E191CC9EB650480E

View file

@ -17,27 +17,31 @@ import "package:nexus/models/room.dart";
class RoomChatController extends AsyncNotifier<IList<Event>?> { class RoomChatController extends AsyncNotifier<IList<Event>?> {
final String roomId; final String roomId;
Future<bool>? _loadingOlder;
RoomChatController(this.roomId); RoomChatController(this.roomId);
@override @override
Future<IList<Event>?> build() async { Future<IList<Event>?> build() async {
final client = ref.watch(ClientController.provider.notifier); final client = ref.watch(ClientController.provider.notifier);
final room = ref.watch( final initialRoom = ref.watch(
RoomsController.provider.select((rooms) => rooms[roomId]), RoomsController.provider.select((rooms) => rooms[roomId]),
); );
if (room == null) return null; if (initialRoom == null) return null;
Room room = initialRoom;
if (!room.hasFetchedState) { if (!room.hasFetchedState) {
final state = await client.getRoomState(.new(roomId: roomId)); final state = await client.getRoomState(.new(roomId: roomId));
await ref.read(RoomsController.provider.notifier).addState(roomId, state); await ref.read(RoomsController.provider.notifier).addState(roomId, state);
room = ref.read(RoomsController.provider)[roomId] ?? room;
} }
// While there are under 20 events, try to load more // While there are under 20 events, try to load more
// until there's no more or the conditions are met. // until there's no more or the conditions are met.
if (room.hasMore && room.timeline.length < 20) { if (room.hasMore && room.timeline.length < 20) {
loadOlder(); await loadOlder();
room = ref.read(RoomsController.provider)[roomId] ?? room;
} }
return room.timeline return room.timeline
@ -74,18 +78,22 @@ class RoomChatController extends AsyncNotifier<IList<Event>?> {
), ),
); );
Future<bool> loadOlder() async { Future<bool> loadOlder() => _loadingOlder ??= _loadOlder().whenComplete(() {
final timelineKeys = ref _loadingOlder = null;
.read(RoomsController.provider.select((value) => value[roomId])) });
?.timeline
.keys; Future<bool> _loadOlder() async {
final room = ref.read(RoomsController.provider)[roomId];
if (room == null || !room.hasMore) return false;
final timelineKeys = room.timeline.keys;
final response = await ref final response = await ref
.watch(ClientController.provider.notifier) .watch(ClientController.provider.notifier)
.paginate( .paginate(
.new( .new(
roomId: roomId, roomId: roomId,
maxTimelineId: timelineKeys?.isNotEmpty == true maxTimelineId: timelineKeys.isNotEmpty
? timelineKeys?.reduce(min) ? timelineKeys.reduce(min)
: null, : null,
), ),
); );