Fix scroll bug(#568) (#570)

* Automated update of relay data - Sun Sep 21 06:21:05 UTC 2025

* Automated update of relay data - Sun Sep 28 06:20:40 UTC 2025

* refactor: new close button like ios(but not liquid glass)

* Automated update of relay data - Sun Oct  5 06:20:09 UTC 2025

* Automated update of relay data - Sun Oct 12 06:20:12 UTC 2025

* Automated update of relay data - Sun Oct 19 06:21:51 UTC 2025

* Automated update of relay data - Sun Oct 26 06:21:31 UTC 2025

* Automated update of relay data - Sun Nov  2 06:22:16 UTC 2025

* Automated update of relay data - Sun Nov  9 06:21:43 UTC 2025

* Automated update of relay data - Sun Nov 16 06:22:37 UTC 2025

* Automated update of relay data - Sun Nov 23 06:22:51 UTC 2025

* Automated update of relay data - Sun Nov 30 06:24:08 UTC 2025

* Automated update of relay data - Sun Dec  7 06:22:59 UTC 2025

* Automated update of relay data - Sun Dec 14 06:24:33 UTC 2025

* Automated update of relay data - Sun Dec 21 06:24:49 UTC 2025

* Automated update of relay data - Sun Dec 28 06:25:38 UTC 2025

* Automated update of relay data - Sun Jan  4 06:26:28 UTC 2026

* fix bug(568): Improve scroll-to-bottom logic

Replaced the "smart scroll" mechanism with a simpler "follow" behavior. The message list now automatically scrolls to the latest message unless the user has scrolled up.

- A new `followIncomingMessages` state tracks whether to auto-scroll.
- Scrolling now uses `scrollToItem` instead of `animateScrollToItem` for immediate updates.

---------

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
yet300
2026-01-12 14:43:28 +07:00
committed by GitHub
co-authored by GitHub Action
parent fbcc289e92
commit cbe7a2fc95
@@ -71,19 +71,14 @@ fun MessagesList(
// Track if this is the first time messages are being loaded // Track if this is the first time messages are being loaded
var hasScrolledToInitialPosition by remember { mutableStateOf(false) } var hasScrolledToInitialPosition by remember { mutableStateOf(false) }
var followIncomingMessages by remember { mutableStateOf(true) }
// Smart scroll: auto-scroll to bottom for initial load, then only when user is at or near the bottom // Smart scroll: auto-scroll to bottom for initial load, then follow unless user scrolls away
LaunchedEffect(messages.size) { LaunchedEffect(messages.size) {
if (messages.isNotEmpty()) { if (messages.isNotEmpty()) {
val layoutInfo = listState.layoutInfo
val firstVisibleIndex = layoutInfo.visibleItemsInfo.firstOrNull()?.index ?: -1
// With reverseLayout=true and reversed data, index 0 is the latest message at the bottom
val isFirstLoad = !hasScrolledToInitialPosition val isFirstLoad = !hasScrolledToInitialPosition
val isNearLatest = firstVisibleIndex <= 2 if (isFirstLoad || followIncomingMessages) {
listState.scrollToItem(0)
if (isFirstLoad || isNearLatest) {
listState.animateScrollToItem(0)
if (isFirstLoad) { if (isFirstLoad) {
hasScrolledToInitialPosition = true hasScrolledToInitialPosition = true
} }
@@ -99,6 +94,7 @@ fun MessagesList(
} }
} }
LaunchedEffect(isAtLatest) { LaunchedEffect(isAtLatest) {
followIncomingMessages = isAtLatest
onScrolledUpChanged?.invoke(!isAtLatest) onScrolledUpChanged?.invoke(!isAtLatest)
} }
@@ -106,7 +102,8 @@ fun MessagesList(
LaunchedEffect(forceScrollToBottom) { LaunchedEffect(forceScrollToBottom) {
if (messages.isNotEmpty()) { if (messages.isNotEmpty()) {
// With reverseLayout=true and reversed data, latest is at index 0 // With reverseLayout=true and reversed data, latest is at index 0
listState.animateScrollToItem(0) followIncomingMessages = true
listState.scrollToItem(0)
} }
} }