scrollToBottomChat method
Scrolls the chat list to the bottom (maxScrollExtent).
Forces a hard jumpTo on every attached position first and after animateTo,
plus several post-frame and delayed snaps so the offset matches the true extent
after slivers rebuild (streaming, slack animation).
minDistance of 0.0 (default) always scrolls. A positive value skips
scrolling when already within that distance of the bottom.
Implementation
void scrollToBottomChat({
bool withAnimation = false,
double minDistance = 0.0,
}) async {
if (!chatScrollController.hasClients) return;
final ScrollPosition? initialPosition =
chatScrollController.positions.lastOrNull;
if (initialPosition == null || initialPosition.maxScrollExtent <= 0.0) {
return;
}
if (minDistance > 0.0 && _isChatWithinMinDistanceOfBottom(minDistance)) {
return;
}
await Future<void>.delayed(const Duration(milliseconds: 80));
if (!chatScrollController.hasClients) return;
final ScrollPosition? position = chatScrollController.positions.lastOrNull;
if (position == null) return;
final double maxScrollExtent = position.maxScrollExtent;
if (maxScrollExtent <= 0.0) return;
final double distanceFromBottom = maxScrollExtent - position.pixels;
if (minDistance > 0.0 && distanceFromBottom <= minDistance) return;
const double largeScrollThreshold = 1500.0;
if (withAnimation && distanceFromBottom <= largeScrollThreshold) {
try {
await chatScrollController.animateTo(
maxScrollExtent,
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
);
} catch (_) {
if (minDistance > 0.0 &&
_isChatWithinMinDistanceOfBottom(minDistance)) {
return;
}
_forceSnapChatScrollToBottom();
}
} else {
_forceSnapChatScrollToBottom();
}
}