scrollToTopChat method

void scrollToTopChat({
  1. bool withAnimation = false,
})

Implementation

void scrollToTopChat({bool withAnimation = false}) {
  if (!chatScrollController.hasClients || conversation.value == null) {
    return;
  }

  void performScroll() async {
    await Future.delayed(const Duration(milliseconds: 150));
    if (!chatScrollController.hasClients) return;

    final position = chatScrollController.positions.lastOrNull;
    if (position == null) return;

    final minScrollExtent = position.minScrollExtent;
    final currentScrollPosition = position.pixels;

    // Don't scroll if there's no content to scroll
    if (minScrollExtent >= currentScrollPosition &&
        currentScrollPosition <= 0) {
      return;
    }

    // Don't scroll if already very close to top (within 50px) to prevent bounce
    const nearTopThreshold = 50.0;
    final distanceFromTop = currentScrollPosition - minScrollExtent;
    if (distanceFromTop <= nearTopThreshold) return;

    final scrollDistance = distanceFromTop.abs();

    // For large scroll distances (>1500px) or when animation is not requested,
    // use jumpTo for instant, lag-free scrolling
    // For small distances with animation requested, use animateTo for smooth UX
    const largeScrollThreshold = 1500.0;

    if (!withAnimation || scrollDistance > largeScrollThreshold) {
      // Instant jump - much faster for large content
      chatScrollController.jumpTo(minScrollExtent);
    } else {
      // Smooth animation only for small scrolls when explicitly requested
      // Use easeInOut to prevent bounce - it smoothly accelerates and decelerates
      chatScrollController.animateTo(
        minScrollExtent,
        duration: const Duration(milliseconds: 200),
        curve: Curves.easeInOut,
      );
    }
  }

  // Try immediately first
  performScroll();

  // Ensure it happens after layout if needed (for very large content)
  WidgetsBinding.instance.addPostFrameCallback((_) {
    performScroll();
  });
}