don't depend on SuperSliverList for scrolls

This commit is contained in:
Henry Hiles 2026-09-26 13:58:30 -04:00
commit 3217c17ea0
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
2 changed files with 13 additions and 40 deletions

View file

@ -7,15 +7,12 @@ import "package:material_ui/material_ui.dart";
import "package:nexus/models/direction.dart"; import "package:nexus/models/direction.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
import "package:nexus/models/room_chat.dart"; import "package:nexus/models/room_chat.dart";
import "package:super_sliver_list/super_sliver_list.dart";
final class ChatScroll({ final class ChatScroll({
required final IList<Event> historyItems, required final IList<Event> historyItems,
required final IList<Event> liveItems, required final IList<Event> liveItems,
required final GlobalKey centerKey, required final GlobalKey centerKey,
required final GlobalKey anchorItemKey, required final GlobalKey anchorItemKey,
required final ListController historyListController,
required final ListController liveListController,
required final ScrollController scrollController, required final ScrollController scrollController,
required final bool atBottom, required final bool atBottom,
required final Future<void> Function(String id) jumpToId, required final Future<void> Function(String id) jumpToId,
@ -31,8 +28,6 @@ final class ChatScroll({
final anchorItemKey = useMemoized(GlobalKey.new, [anchorId.value]); final anchorItemKey = useMemoized(GlobalKey.new, [anchorId.value]);
final historyListController = useMemoized(ListController.new);
final liveListController = useMemoized(ListController.new);
final scrollController = useScrollController(); final scrollController = useScrollController();
final centerKey = useMemoized(GlobalKey.new); final centerKey = useMemoized(GlobalKey.new);
@ -156,47 +151,29 @@ final class ChatScroll({
], ],
); );
double? resolveOffset(String itemId) {
final historyIndex = split.history.indexWhere(
(item) => item.eventId == itemId,
);
if (historyIndex != -1) {
// TODO: Replace SuperSliverView because of the bug that requires this: #94
// ignore: invalid_use_of_visible_for_testing_member
return historyListController.getOffsetToReveal(historyIndex, 0.5);
}
final liveIndex = split.live.indexWhere((item) => item.eventId == itemId);
if (liveIndex != -1) {
// ignore: invalid_use_of_visible_for_testing_member
return liveListController.getOffsetToReveal(liveIndex, 0.5);
}
return null;
}
Future<void> jumpToId(String itemId) async { Future<void> jumpToId(String itemId) async {
if (!scrollController.hasClients) return; if (!scrollController.hasClients) return;
final offset = resolveOffset(itemId); if (anchorId.value != itemId) {
final completer = Completer<BuildContext>();
anchorMountedCompleter.value = completer;
pendingAnchorTarget.value = itemId;
contextualEvent.value = itemId;
if (offset != null) { final context = await completer.future;
await scrollController.animateTo( if (!context.mounted) return;
offset,
await Scrollable.ensureVisible(
context,
alignment: 0.5,
duration: const .new(milliseconds: 700), duration: const .new(milliseconds: 700),
curve: Curves.easeInOut, curve: Curves.easeInOut,
); );
return; return;
} }
final completer = Completer<BuildContext>(); final context = anchorItemKey.currentContext;
anchorMountedCompleter.value = completer; if (context != null && context.mounted) {
pendingAnchorTarget.value = itemId;
contextualEvent.value = itemId;
final context = await completer.future;
if (context.mounted) {
await Scrollable.ensureVisible( await Scrollable.ensureVisible(
context, context,
alignment: 0.5, alignment: 0.5,
@ -226,8 +203,6 @@ final class ChatScroll({
liveItems: split.live, liveItems: split.live,
centerKey: centerKey, centerKey: centerKey,
anchorItemKey: anchorItemKey, anchorItemKey: anchorItemKey,
historyListController: historyListController,
liveListController: liveListController,
scrollController: scrollController, scrollController: scrollController,
atBottom: atBottom.value, atBottom: atBottom.value,
jumpToId: jumpToId, jumpToId: jumpToId,

View file

@ -50,7 +50,6 @@ class const ChatTimeline({
SliverToBoxAdapter(child: SizedBox(height: composerHeight)), SliverToBoxAdapter(child: SizedBox(height: composerHeight)),
SuperSliverList.builder( SuperSliverList.builder(
listController: scroll.liveListController,
itemCount: scroll.liveItems.length, itemCount: scroll.liveItems.length,
itemBuilder: (_, index) => eventRow( itemBuilder: (_, index) => eventRow(
scroll.liveItems[index], scroll.liveItems[index],
@ -68,7 +67,6 @@ class const ChatTimeline({
SuperSliverList.builder( SuperSliverList.builder(
key: scroll.centerKey, key: scroll.centerKey,
listController: scroll.historyListController,
itemCount: scroll.historyItems.length, itemCount: scroll.historyItems.length,
itemBuilder: (_, index) => eventRow( itemBuilder: (_, index) => eventRow(
scroll.historyItems[index], scroll.historyItems[index],