fix historical event jumps

Fixes #118
This commit is contained in:
Henry Hiles 2026-10-14 23:48:32 -04:00
commit dbf30c3706
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
2 changed files with 25 additions and 16 deletions

View file

@ -18,26 +18,30 @@ class EventController(final GetEventRequest request)
if (event != null) return event; if (event != null) return event;
final link = ref.keepAlive();
final fetchedEvent = await ref final fetchedEvent = await ref
.read(ClientController.provider.notifier) .read(ClientController.provider.notifier)
.getEvent(request) .getEvent(request)
.onError((_, _) => null); .onError((_, _) => null)
.whenComplete(link.close);
if (fetchedEvent != null) { if (fetchedEvent != null) {
ref // Storing the event invalidates this provider, as it watches the room.
.read(RoomsController.provider.notifier) // If nothing is listening, Riverpod won't rebuild it, and this build's
.update( // result would be lost, so store it after returning.
final rooms = ref.read(RoomsController.provider.notifier);
Future.microtask(
() => rooms.update(
.new({ .new({
request.roomId: .new( request.roomId: .new(
events: .new({fetchedEvent.rowId: fetchedEvent}), events: .new({fetchedEvent.rowId: fetchedEvent}),
), ),
}), }),
),
); );
return fetchedEvent;
} }
return null; return fetchedEvent;
} }
static final provider = AsyncNotifierProvider.family static final provider = AsyncNotifierProvider.family

View file

@ -127,10 +127,15 @@ final class ChatScroll({
final isAtBottom = position.extentBefore <= 0; final isAtBottom = position.extentBefore <= 0;
if (isAtBottom != atBottom.value) atBottom.value = isAtBottom; if (isAtBottom != atBottom.value) atBottom.value = isAtBottom;
// contextualEvent updates immediately when jumping, but
// controllerData is only for the historical timeline once it loads
final isHistorical =
contextualEvent.value != null &&
controllerData.value?.historicalData != null;
if (position.extentAfter <= loadThreshold) { if (position.extentAfter <= loadThreshold) {
await paginate(.backward); await paginate(.backward);
} else if (contextualEvent.value != null && } else if (isHistorical && position.extentBefore <= loadThreshold) {
position.extentBefore <= loadThreshold) {
await paginate(.forward); await paginate(.forward);
} else if (position.extentBefore <= 0) { } else if (position.extentBefore <= 0) {
await markRead(); await markRead();
@ -139,7 +144,7 @@ final class ChatScroll({
if (controllerData.isLoading == false && if (controllerData.isLoading == false &&
position.extentBefore <= 0 && position.extentBefore <= 0 &&
controllerData.value?.hasMoreForward == false && controllerData.value?.hasMoreForward == false &&
contextualEvent.value != null) { isHistorical) {
anchorId.value = null; anchorId.value = null;
contextualEvent.value = null; contextualEvent.value = null;
} }