scrollToBottomChat method

void scrollToBottomChat({
  1. bool withAnimation = false,
  2. double minDistance = 0.0,
})

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();
  }
}