更新
This commit is contained in:
Generated
+1
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|||||||
@@ -418,9 +418,16 @@ private fun MessagesArea(
|
|||||||
}.collect { nearBottom -> autoScroll = nearBottom }
|
}.collect { nearBottom -> autoScroll = nearBottom }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instant scroll (not animated) so it doesn't fight with user drag gestures
|
||||||
LaunchedEffect(state.streamContent, state.streamReasoning, messages.size, state.isStreaming) {
|
LaunchedEffect(state.streamContent, state.streamReasoning, messages.size, state.isStreaming) {
|
||||||
if (autoScroll && totalItems > 0) {
|
if (autoScroll && totalItems > 0) {
|
||||||
listState.animateScrollToItem(totalItems - 1)
|
if (state.streamContent.isNotBlank()) {
|
||||||
|
// Content phase: scroll to bottom of the streaming message
|
||||||
|
listState.scrollToItem(totalItems - 1, 100000)
|
||||||
|
} else {
|
||||||
|
// Reasoning phase: keep streaming message header visible
|
||||||
|
listState.scrollToItem(totalItems - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,7 +491,7 @@ private fun MessagesArea(
|
|||||||
.border(1.dp, c.border, CircleShape)
|
.border(1.dp, c.border, CircleShape)
|
||||||
.clickable {
|
.clickable {
|
||||||
autoScroll = true
|
autoScroll = true
|
||||||
scope.launch { listState.animateScrollToItem(totalItems - 1) }
|
scope.launch { listState.animateScrollToItem(totalItems - 1, 100000) }
|
||||||
},
|
},
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
@@ -633,6 +640,13 @@ private fun StreamingMessage(content: String, reasoning: String, onCopy: () -> U
|
|||||||
private fun ReasoningCard(reasoning: String, isStreaming: Boolean) {
|
private fun ReasoningCard(reasoning: String, isStreaming: Boolean) {
|
||||||
val c = LocalAppColors.current
|
val c = LocalAppColors.current
|
||||||
var collapsed by remember { mutableStateOf(false) }
|
var collapsed by remember { mutableStateOf(false) }
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
// Auto-scroll reasoning text to bottom as new content arrives
|
||||||
|
LaunchedEffect(reasoning) {
|
||||||
|
if (isStreaming && !collapsed) {
|
||||||
|
scrollState.animateScrollTo(scrollState.maxValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -663,7 +677,7 @@ private fun ReasoningCard(reasoning: String, isStreaming: Boolean) {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.heightIn(max = 320.dp)
|
.heightIn(max = 320.dp)
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(scrollState)
|
||||||
.padding(horizontal = 12.dp, vertical = 8.dp)
|
.padding(horizontal = 12.dp, vertical = 8.dp)
|
||||||
) {
|
) {
|
||||||
SelectionContainer {
|
SelectionContainer {
|
||||||
@@ -763,15 +777,14 @@ private fun ComposerBar(state: ChatUiState, onSend: (String) -> Unit, onStop: ()
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(44.dp)
|
.size(44.dp)
|
||||||
.clip(RoundedCornerShape(12.dp))
|
.shadow(6.dp, RoundedCornerShape(12.dp), clip = true)
|
||||||
.background(c.accentBrush)
|
.background(c.accentBrush)
|
||||||
.shadow(6.dp, RoundedCornerShape(12.dp), clip = false)
|
|
||||||
.clickable(enabled = input.isNotBlank()) {
|
.clickable(enabled = input.isNotBlank()) {
|
||||||
onSend(input); input = ""
|
onSend(input); input = ""
|
||||||
},
|
},
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
Icon(Icons.AutoMirrored.Filled.Send, contentDescription = "发送", tint = Color.White)
|
Icon(Icons.AutoMirrored.Filled.Send, contentDescription = "发送", tint = Color.White, modifier = Modifier.size(22.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user