fix: scroll button direction follows scroll position
Single button instead of two mutually exclusive ones. Arrow direction is based on proximity to bottom: near bottom → arrow up (scroll to top), not near bottom → arrow down (scroll to end). Updates instantly as the user scrolls. Hidden when already at the target end. Old logic had an if/else that always showed ArrowUp first (because !atTop was always true when scrolled down), making ArrowDown unreachable in most scroll positions.
This commit is contained in:
parent
f855a26b31
commit
fd684fff2e
1 changed files with 22 additions and 25 deletions
|
|
@ -908,15 +908,18 @@ fun ChatScreen(
|
|||
}
|
||||
|
||||
if (!isStreaming) {
|
||||
val atTop by remember { derivedStateOf { listState.firstVisibleItemIndex <= 1 } }
|
||||
val atBottom by remember { derivedStateOf {
|
||||
val info = listState.layoutInfo
|
||||
info.visibleItemsInfo.lastOrNull()?.index == info.totalItemsCount - 1
|
||||
}}
|
||||
val canScrollUp by remember { derivedStateOf { listState.canScrollBackward } }
|
||||
val canScrollDown by remember { derivedStateOf { listState.canScrollForward } }
|
||||
val showButton = canScrollUp || canScrollDown
|
||||
val nearBottom by remember { derivedStateOf {
|
||||
val info = listState.layoutInfo
|
||||
val lastVisible = info.visibleItemsInfo.lastOrNull()?.index ?: 0
|
||||
val total = info.totalItemsCount
|
||||
if (total <= 0) true else lastVisible >= total - 2
|
||||
}}
|
||||
val pointsUp = !nearBottom && canScrollUp
|
||||
|
||||
if (!atTop && canScrollUp) {
|
||||
if (showButton && !(canScrollUp && !canScrollDown && nearBottom)) {
|
||||
GlassSurface(
|
||||
shape = KaizenShapes.circle,
|
||||
tintAlpha = GlassTiers.pill(isSystemInDarkTheme()),
|
||||
|
|
@ -924,28 +927,22 @@ fun ChatScreen(
|
|||
cornerRadius = 18.dp,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.padding(end = 8.dp, bottom = 24.dp)
|
||||
.padding(end = 8.dp)
|
||||
.size(36.dp)
|
||||
.clickable { scope.launch { listState.animateScrollToItem(0) } },
|
||||
.clickable {
|
||||
scope.launch {
|
||||
if (pointsUp) listState.animateScrollToItem(0)
|
||||
else listState.animateScrollToItem(messages.size - 1)
|
||||
}
|
||||
},
|
||||
) {
|
||||
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Icon(KaizenIcons.ArrowUp, null, tint = MaterialTheme.colorScheme.onBackground, modifier = Modifier.size(20.dp))
|
||||
}
|
||||
}
|
||||
} else if (!atBottom && canScrollDown) {
|
||||
GlassSurface(
|
||||
shape = KaizenShapes.circle,
|
||||
tintAlpha = GlassTiers.pill(isSystemInDarkTheme()),
|
||||
shadowStack = KaizenShadows.level1,
|
||||
cornerRadius = 18.dp,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.padding(end = 8.dp, top = 24.dp)
|
||||
.size(36.dp)
|
||||
.clickable { scope.launch { listState.animateScrollToItem(messages.size - 1) } },
|
||||
) {
|
||||
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Icon(KaizenIcons.ArrowDown, null, tint = MaterialTheme.colorScheme.onBackground, modifier = Modifier.size(20.dp))
|
||||
Icon(
|
||||
if (pointsUp) KaizenIcons.ArrowUp else KaizenIcons.ArrowDown,
|
||||
null,
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue