Skip to content

Commit 0294f43

Browse files
committed
fix: scroll chat to bottom only on mounth and then disable autoscroll
AdminForth/1786/ability-to-edit-agent-prompt-a
1 parent 45fc6d3 commit 0294f43

2 files changed

Lines changed: 30 additions & 7 deletions

File tree

custom/CustomAutoScrollContainer.vue

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ const props = withDefaults(defineProps<{
2424
wrapperStyle?: Record<string, string>
2525
contentStyle?: Record<string, string>
2626
scrollBarAutoHide?: boolean
27-
scrollToBottomOnMount?: boolean
2827
debugMode?: boolean
28+
scrollToBottomOnMount?: boolean
2929
}>(), {
3030
enabled: true,
3131
threshold: 50,
3232
behavior: 'instant',
3333
scrollBarAutoHide: true,
34-
scrollToBottomOnMount: true,
35-
debugMode: false
34+
debugMode: false,
35+
scrollToBottomOnMount: true
3636
})
3737
3838
const containerRef = ref<HTMLDivElement | null>(null)
@@ -43,6 +43,18 @@ let lastScrollTop = 0
4343
let lastScrollHeight = 0
4444
let observer: MutationObserver | null = null
4545
46+
const INITIAL_SCROLL_DEBOUNCE = 200
47+
let initialScrollDone = false
48+
let initialScrollTimer: ReturnType<typeof setTimeout> | null = null
49+
50+
function scheduleInitialScrollEnd(): void {
51+
if (initialScrollTimer) clearTimeout(initialScrollTimer)
52+
initialScrollTimer = setTimeout(() => {
53+
initialScrollDone = true
54+
initialScrollTimer = null
55+
}, INITIAL_SCROLL_DEBOUNCE)
56+
}
57+
4658
const scrollParams = ref({
4759
scrollTop: 0,
4860
scrollHeight: 0,
@@ -71,26 +83,37 @@ onMounted(() => {
7183
if (!hasScrollbar()) {
7284
isUserScrolledUp.value = false
7385
}
74-
86+
7587
lastScrollHeight = containerRef.value.scrollEl.scrollHeight
7688
scrollParams.value.scrollTop = containerRef.value.scrollEl.scrollTop
7789
scrollParams.value.scrollHeight = containerRef.value.scrollEl.scrollHeight
7890
scrollParams.value.clientHeight = containerRef.value.scrollEl.clientHeight
79-
if (!isUserScrolledUp.value && props.scrollToBottomOnMount) {
91+
if (props.enabled && !isUserScrolledUp.value) {
8092
scrollToBottom()
93+
} else if (props.scrollToBottomOnMount && !initialScrollDone) {
94+
// Delayed content is still settling in the initial scroll phase: keep
95+
// pinning to the bottom and restart the quiet-period debounce.
96+
scrollToBottom(true)
97+
scheduleInitialScrollEnd()
8198
}
8299
})
83100
})
84-
101+
85102
observer.observe(containerRef.value?.scrollEl, {
86103
childList: true,
87104
subtree: true,
88105
characterData: true
89106
})
107+
108+
if (props.scrollToBottomOnMount) {
109+
nextTick(() => scrollToBottom(true))
110+
scheduleInitialScrollEnd()
111+
}
90112
})
91113
92114
onUnmounted(() => {
93115
observer?.disconnect()
116+
if (initialScrollTimer) clearTimeout(initialScrollTimer)
94117
})
95118
96119
function isNearBottom(customThreshold?: number): boolean {

custom/conversation_area/ConversationArea.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
<div ref="chatContainerRef" class="relative flex-1 min-h-0 overflow-hidden" @click="recalculateScroll()">
1212
<CustomAutoScrollContainer
1313
v-if="showScrollContainer"
14-
:enabled="false"
1514
class="relative h-full flex flex-col overflow-y-auto translate-x-[-50%] left-1/2"
1615
ref="scrollContainer"
16+
:enabled="false"
1717
:threshold="THRESHOLD_TO_SHOW_BUTTON"
1818
behavior="smooth"
1919
:wrapperStyle = "{

0 commit comments

Comments
 (0)