Skip to content

Commit 4a7128f

Browse files
committed
fix(stage-ui): improved the policy and strategy for chat history auto scrolling
Close #1568 Co-authored-by-agent: Codex <267193182+codex@users.noreply.github.com>
1 parent b603b9b commit 4a7128f

3 files changed

Lines changed: 877 additions & 23 deletions

File tree

packages/stage-ui/src/components/scenarios/chat/components/history.vue

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
<script setup lang="ts">
22
import type { ChatAssistantMessage, ChatHistoryItem, ContextMessage } from '../../../../types/chat'
33
4-
import { computed, onMounted, provide, ref, watch } from 'vue'
4+
import { computed, provide, ref } from 'vue'
55
import { useI18n } from 'vue-i18n'
66
77
import ChatAssistantItem from './assistant-item.vue'
88
import ChatErrorItem from './error-item.vue'
99
import ChatUserItem from './user-item.vue'
1010
11+
import { useChatHistoryScroll } from '../composables/use-chat-history-scroll'
1112
import { chatScrollContainerKey } from '../constants'
1213
import { getChatHistoryItemKey } from '../utils'
1314
@@ -39,21 +40,6 @@ const labels = computed(() => ({
3940
error: props.errorLabel ?? t('stage.chat.message.character-name.core-system'),
4041
}))
4142
42-
function scrollToBottom() {
43-
requestAnimationFrame(() => {
44-
requestAnimationFrame(() => {
45-
if (!chatHistoryRef.value)
46-
return
47-
48-
chatHistoryRef.value.scrollTop = chatHistoryRef.value.scrollHeight
49-
})
50-
})
51-
}
52-
53-
watch([() => props.messages, () => props.streamingMessage], scrollToBottom, { deep: true, flush: 'post' })
54-
watch(() => props.sending, scrollToBottom, { flush: 'post' })
55-
onMounted(scrollToBottom)
56-
5743
const streaming = computed<ChatAssistantMessage & { context?: ContextMessage } & { createdAt?: number }>(() => props.streamingMessage ?? { role: 'assistant', content: '', slices: [], tool_results: [], createdAt: Date.now() })
5844
const showStreamingPlaceholder = computed(() => (streaming.value.slices?.length ?? 0) === 0 && !streaming.value.content)
5945
const streamingTs = computed(() => streaming.value?.createdAt)
@@ -79,6 +65,12 @@ const renderMessages = computed<ChatHistoryItem[]>(() => {
7965
return [...props.messages, streaming.value]
8066
})
8167
68+
useChatHistoryScroll({
69+
containerRef: chatHistoryRef,
70+
messages: renderMessages,
71+
getKey: getChatHistoryItemKey,
72+
})
73+
8274
function emitCopyMessage(message: ChatHistoryItem, index: number) {
8375
emit('copyMessage', {
8476
message,
@@ -99,30 +91,31 @@ function emitDeleteMessage(message: ChatHistoryItem, index: number) {
9991
<template>
10092
<div ref="chatHistoryRef" v-auto-animate flex="~ col" relative h-full w-full overflow-y-auto rounded-xl px="<sm:2" py="<sm:2" :class="variant === 'mobile' ? 'gap-1' : 'gap-2'">
10193
<template v-for="(message, index) in renderMessages" :key="getChatHistoryItemKey(message, index)">
102-
<div v-if="message.role === 'error'">
94+
<div
95+
:data-chat-message-index="index"
96+
:data-chat-message-key="String(getChatHistoryItemKey(message, index))"
97+
:data-chat-message-role="message.role"
98+
>
10399
<ChatErrorItem
100+
v-if="message.role === 'error'"
104101
:message="message"
105102
:label="labels.error"
106103
:show-placeholder="sending && index === renderMessages.length - 1"
107104
:variant="variant"
108105
@copy="emitCopyMessage(message, index)"
109106
@delete="emitDeleteMessage(message, index)"
110107
/>
111-
</div>
112-
113-
<div v-else-if="message.role === 'assistant'">
114108
<ChatAssistantItem
109+
v-else-if="message.role === 'assistant'"
115110
:message="message"
116111
:label="labels.assistant"
117112
:show-placeholder="shouldShowPlaceholder(message) && showStreamingPlaceholder"
118113
:variant="variant"
119114
@copy="emitCopyMessage(message, index)"
120115
@delete="emitDeleteMessage(message, index)"
121116
/>
122-
</div>
123-
124-
<div v-else-if="message.role === 'user'">
125117
<ChatUserItem
118+
v-else-if="message.role === 'user'"
126119
:message="message"
127120
:label="labels.user"
128121
:variant="variant"

0 commit comments

Comments
 (0)