From 94ad5e1e0066a050f8d25c52e5571d805ac19dfd Mon Sep 17 00:00:00 2001 From: Andrew Beal Date: Thu, 2 Oct 2025 20:52:43 +0100 Subject: [PATCH] Implement scrolling behavior in ChatArea and remove unused chat padding logic in ChatWindow --- Components/ChatArea.svelte | 51 +++++++++++++++++++++++++++--------- Components/ChatWindow.svelte | 8 +----- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/Components/ChatArea.svelte b/Components/ChatArea.svelte index c6ef8ac..91fb1c4 100644 --- a/Components/ChatArea.svelte +++ b/Components/ChatArea.svelte @@ -4,17 +4,18 @@ import type { StreamingMarkdownService } from "Services/StreamingMarkdownService"; import ChatAreaThought from "./ChatAreaThought.svelte"; import StreamingIndicator from "./StreamingIndicator.svelte"; - import { slide } from "svelte/transition"; import { Greeting } from "Enums/Greeting"; export let messages: Array<{id: string, content: string, isUser: boolean, isStreaming: boolean}> = []; - export let showChatPadding: boolean = false; export let chatContainer: HTMLDivElement; - + let streamingMarkdownService: StreamingMarkdownService = Resolve(Services.StreamingMarkdownService); let messageElements = new Map(); let lastProcessedContent = new Map(); + let scrollInterval: number | null = null; + let userScrolledUp = false; + let lastScrollTop = 0; function getGreetingByTime(): string { const hour = new Date().getHours(); @@ -42,9 +43,13 @@ messages.forEach((message) => { if (!message.isUser) { const lastContent = lastProcessedContent.get(message.id) || ''; - + // Only update if content has changed if (message.content !== lastContent) { + if (message.isStreaming && lastContent === '') { + userScrolledUp = false; + } + updateMessageContent(message); lastProcessedContent.set(message.id, message.content); } @@ -52,6 +57,33 @@ }); } + function handleScroll() { + if (!chatContainer) return; + + if (chatContainer.scrollTop < lastScrollTop) { + userScrolledUp = true; + } + + lastScrollTop = chatContainer.scrollTop; + } + + function startScrolling() { + if (scrollInterval || userScrolledUp) return; + + scrollInterval = window.setInterval(() => { + if (chatContainer && !userScrolledUp) { + chatContainer.scrollTop = chatContainer.scrollHeight; + } + }, 50); + + setTimeout(() => { + if (scrollInterval) { + clearInterval(scrollInterval); + scrollInterval = null; + } + }, 500); + } + function updateMessageContent(message: {id: string, content: string, isUser: boolean, isStreaming: boolean}) { const element = messageElements.get(message.id); if (!element) return; @@ -61,6 +93,7 @@ } else { streamingMarkdownService.finalizeStream(message.id, message.content); } + startScrolling(); } function initializeMessageElement(messageId: string, element: HTMLElement) { @@ -112,7 +145,7 @@ } -
+
{#each messages as message (message.id)}
@@ -125,9 +158,6 @@
- {#if showChatPadding} -
- {/if} {:else} {@html getStaticHTML(message)} @@ -160,11 +190,6 @@ display: none; } - .chat-padding { - height: 40vh; - width: 100%; - } - .message-container { display: flex; margin: 0; diff --git a/Components/ChatWindow.svelte b/Components/ChatWindow.svelte index dd68f23..2531ec8 100644 --- a/Components/ChatWindow.svelte +++ b/Components/ChatWindow.svelte @@ -18,8 +18,6 @@ let userRequest = ""; let isSubmitting = false; - let userHasScrolled = false; - let showChatPadding = false; let messages: Array<{ id: string, @@ -54,9 +52,7 @@ await conversationService.saveConversation(messages); - showChatPadding = true; scrollToBottom(); - userHasScrolled = false; try { // Create AI message placeholder @@ -102,10 +98,8 @@ ); await conversationService.saveConversation(messages); } - showChatPadding = false; } } finally { - showChatPadding = false; semaphore.release(); isSubmitting = false; } @@ -143,7 +137,7 @@
- +