diff --git a/CHANGELOG.md b/CHANGELOG.md index 5692a29..f578879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - Added senderTitleResolver to the ChatOptions to resolve the title of the sender in the chat message - Added imageProviderResolver to the ChatOptions to resolve ImageProvider for all images in the userstory - Added enabled boolean to the messageInputBuilder and made parameters named +- Added autoScrollTriggerOffset to the ChatPaginationControls to adjust when the auto scroll should be enabled ## 4.0.0 - Move to the new user story architecture diff --git a/packages/flutter_chat/lib/src/config/chat_options.dart b/packages/flutter_chat/lib/src/config/chat_options.dart index 647ed79..7760256 100644 --- a/packages/flutter_chat/lib/src/config/chat_options.dart +++ b/packages/flutter_chat/lib/src/config/chat_options.dart @@ -294,6 +294,7 @@ class ChatPaginationControls { /// The chat pagination controls constructor const ChatPaginationControls({ this.scrollOffset = 50.0, + this.autoScrollTriggerOffset = 50.0, this.loadingIndicatorForNewMessages = true, this.loadingIndicatorForOldMessages = true, this.loadingNewMessageMinDuration = Duration.zero, @@ -304,6 +305,10 @@ class ChatPaginationControls { /// on both sides of the chat. Defaults to 50.0 final double scrollOffset; + /// The minimum scroll offset to trigger the auto scroll to the bottom of the + /// chat. Defaults to 50.0 + final double autoScrollTriggerOffset; + /// Whether to show a loading indicator for new messages loading final bool loadingIndicatorForNewMessages; diff --git a/packages/flutter_chat/lib/src/screens/chat_detail/chat_detail_screen.dart b/packages/flutter_chat/lib/src/screens/chat_detail/chat_detail_screen.dart index d7eb15e..e604c82 100644 --- a/packages/flutter_chat/lib/src/screens/chat_detail/chat_detail_screen.dart +++ b/packages/flutter_chat/lib/src/screens/chat_detail/chat_detail_screen.dart @@ -256,6 +256,9 @@ class _ChatBody extends HookWidget { var isLoadingOlder = useState(false); var isLoadingNewer = useState(false); + + var hasMoreOlder = useState(true); + var autoScrollEnabled = useState(true); var messagesStream = useMemoized( @@ -268,7 +271,9 @@ class _ChatBody extends HookWidget { var scrollController = useScrollController(); Future loadOlderMessages() async { - if (messages.isEmpty || isLoadingOlder.value) return; + if (!hasMoreOlder.value || messages.isEmpty || isLoadingOlder.value) { + return; + } isLoadingOlder.value = true; var oldestMsg = messages.first; @@ -292,7 +297,9 @@ class _ChatBody extends HookWidget { return; } var newCount = messages.length; - if (newCount > oldCount) { + if (newCount == oldCount) { + hasMoreOlder.value = false; + } else { var newMaxScroll = scrollController.position.maxScrollExtent; var diff = newMaxScroll - oldMaxScroll; scrollController.jumpTo(oldOffset + diff); @@ -329,22 +336,26 @@ class _ChatBody extends HookWidget { var offset = scrollController.offset; var maxScroll = scrollController.position.maxScrollExtent; var threshold = options.paginationControls.scrollOffset; + var autoScrollThreshold = + options.paginationControls.autoScrollTriggerOffset; var distanceFromBottom = maxScroll - offset; - if (distanceFromBottom > 50) { - autoScrollEnabled.value = false; - } else { - autoScrollEnabled.value = true; - } - if (offset <= threshold && !isLoadingOlder.value) { unawaited(loadOlderMessages()); } - if (distanceFromBottom <= threshold && !isLoadingNewer.value) { + if (distanceFromBottom <= threshold && + !isLoadingNewer.value && + !autoScrollEnabled.value) { unawaited(loadNewerMessages()); } + + if (distanceFromBottom > autoScrollThreshold) { + autoScrollEnabled.value = false; + } else { + autoScrollEnabled.value = true; + } } scrollController.addListener(onScroll);