feat: stop loading new messages while autoscroll is on and stop loading old messages if there are no new results

This commit is contained in:
Freek van de Ven 2025-02-21 10:33:51 +01:00 committed by Bart Ribbers
parent 02469f715e
commit c1c3aab808
3 changed files with 26 additions and 9 deletions

View file

@ -22,6 +22,7 @@
- Added senderTitleResolver to the ChatOptions to resolve the title of the sender in the chat message - 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 imageProviderResolver to the ChatOptions to resolve ImageProvider for all images in the userstory
- Added enabled boolean to the messageInputBuilder and made parameters named - 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 ## 4.0.0
- Move to the new user story architecture - Move to the new user story architecture

View file

@ -294,6 +294,7 @@ class ChatPaginationControls {
/// The chat pagination controls constructor /// The chat pagination controls constructor
const ChatPaginationControls({ const ChatPaginationControls({
this.scrollOffset = 50.0, this.scrollOffset = 50.0,
this.autoScrollTriggerOffset = 50.0,
this.loadingIndicatorForNewMessages = true, this.loadingIndicatorForNewMessages = true,
this.loadingIndicatorForOldMessages = true, this.loadingIndicatorForOldMessages = true,
this.loadingNewMessageMinDuration = Duration.zero, this.loadingNewMessageMinDuration = Duration.zero,
@ -304,6 +305,10 @@ class ChatPaginationControls {
/// on both sides of the chat. Defaults to 50.0 /// on both sides of the chat. Defaults to 50.0
final double scrollOffset; 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 /// Whether to show a loading indicator for new messages loading
final bool loadingIndicatorForNewMessages; final bool loadingIndicatorForNewMessages;

View file

@ -256,6 +256,9 @@ class _ChatBody extends HookWidget {
var isLoadingOlder = useState(false); var isLoadingOlder = useState(false);
var isLoadingNewer = useState(false); var isLoadingNewer = useState(false);
var hasMoreOlder = useState(true);
var autoScrollEnabled = useState(true); var autoScrollEnabled = useState(true);
var messagesStream = useMemoized( var messagesStream = useMemoized(
@ -268,7 +271,9 @@ class _ChatBody extends HookWidget {
var scrollController = useScrollController(); var scrollController = useScrollController();
Future<void> loadOlderMessages() async { Future<void> loadOlderMessages() async {
if (messages.isEmpty || isLoadingOlder.value) return; if (!hasMoreOlder.value || messages.isEmpty || isLoadingOlder.value) {
return;
}
isLoadingOlder.value = true; isLoadingOlder.value = true;
var oldestMsg = messages.first; var oldestMsg = messages.first;
@ -292,7 +297,9 @@ class _ChatBody extends HookWidget {
return; return;
} }
var newCount = messages.length; var newCount = messages.length;
if (newCount > oldCount) { if (newCount == oldCount) {
hasMoreOlder.value = false;
} else {
var newMaxScroll = scrollController.position.maxScrollExtent; var newMaxScroll = scrollController.position.maxScrollExtent;
var diff = newMaxScroll - oldMaxScroll; var diff = newMaxScroll - oldMaxScroll;
scrollController.jumpTo(oldOffset + diff); scrollController.jumpTo(oldOffset + diff);
@ -329,22 +336,26 @@ class _ChatBody extends HookWidget {
var offset = scrollController.offset; var offset = scrollController.offset;
var maxScroll = scrollController.position.maxScrollExtent; var maxScroll = scrollController.position.maxScrollExtent;
var threshold = options.paginationControls.scrollOffset; var threshold = options.paginationControls.scrollOffset;
var autoScrollThreshold =
options.paginationControls.autoScrollTriggerOffset;
var distanceFromBottom = maxScroll - offset; var distanceFromBottom = maxScroll - offset;
if (distanceFromBottom > 50) {
autoScrollEnabled.value = false;
} else {
autoScrollEnabled.value = true;
}
if (offset <= threshold && !isLoadingOlder.value) { if (offset <= threshold && !isLoadingOlder.value) {
unawaited(loadOlderMessages()); unawaited(loadOlderMessages());
} }
if (distanceFromBottom <= threshold && !isLoadingNewer.value) { if (distanceFromBottom <= threshold &&
!isLoadingNewer.value &&
!autoScrollEnabled.value) {
unawaited(loadNewerMessages()); unawaited(loadNewerMessages());
} }
if (distanceFromBottom > autoScrollThreshold) {
autoScrollEnabled.value = false;
} else {
autoScrollEnabled.value = true;
}
} }
scrollController.addListener(onScroll); scrollController.addListener(onScroll);