remember position on load older based on event id instead of scroll progress

This commit is contained in:
Henry Hiles 2026-06-02 21:04:23 -04:00
commit cdcc34acaa
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs

View file

@ -79,12 +79,15 @@ class RoomChat extends HookConsumerWidget {
final scrollController = useScrollController(); final scrollController = useScrollController();
final controllerData = ref.watch(controllerProvider); final controllerData = ref.watch(controllerProvider);
final heightBeforeLoad = useState<double?>(null); final topEventBeforeLoad = useState<String?>(null);
Future<void> loadOlder() async { Future<void> loadOlder() async {
heightBeforeLoad.value = scrollController.position.maxScrollExtent; if (controllerData
case AsyncData(:final value) || AsyncLoading(:final value?)) {
topEventBeforeLoad.value = value.firstOrNull?.eventId;
await notifier.loadOlder(); await notifier.loadOlder();
} }
}
useEffect(() { useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
@ -97,26 +100,37 @@ class RoomChat extends HookConsumerWidget {
}, [scrollController.hasClients]); }, [scrollController.hasClients]);
useEffect(() { useEffect(() {
if (!scrollController.hasClients || controllerData is! AsyncData) return; if (controllerData case AsyncData(
:final value,
if (heightBeforeLoad.value != null) { ) when scrollController.hasClients) {
if (topEventBeforeLoad.value != null) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (scrollController.hasClients) { if (scrollController.hasClients) {
scrollController.jumpTo( final index = value.indexWhere(
scrollController.position.maxScrollExtent - (event) => event.eventId == topEventBeforeLoad.value,
heightBeforeLoad.value!, );
if (index != -1) {
listController.value.jumpToItem(
index: index,
scrollController: scrollController,
alignment: 0,
); );
} }
heightBeforeLoad.value = null; }
topEventBeforeLoad.value = null;
}); });
} else if (scrollController.position.atEdge && } else if (scrollController.position.atEdge &&
scrollController.position.pixels != 0) { scrollController.position.pixels != 0) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (scrollController.hasClients) { if (scrollController.hasClients) {
scrollController.jumpTo(scrollController.position.maxScrollExtent); scrollController.jumpTo(
scrollController.position.maxScrollExtent,
);
} }
}); });
} }
}
return null; return null;
}, [controllerData]); }, [controllerData]);
@ -142,7 +156,7 @@ class RoomChat extends HookConsumerWidget {
scrollController.addListener(listener); scrollController.addListener(listener);
return () => scrollController.removeListener(listener); return () => scrollController.removeListener(listener);
}, [roomId]); }, [roomId, controllerData]);
final composerNode = useFocusNode( final composerNode = useFocusNode(
onKeyEvent: (_, event) { onKeyEvent: (_, event) {