changes
This commit is contained in:
@@ -10,3 +10,7 @@
|
|||||||
.chatBubbleAssistant {
|
.chatBubbleAssistant {
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chatScrollViewport {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import { getInstalledModels, type OllamaModel } from '@/app/actions/ollama';
|
|||||||
import { useThemeContext } from '@/components/DynamicThemeProvider';
|
import { useThemeContext } from '@/components/DynamicThemeProvider';
|
||||||
import { SettingsModal } from '@/components/Settings/SettingsModal';
|
import { SettingsModal } from '@/components/Settings/SettingsModal';
|
||||||
import { MarkdownMessage } from './MarkdownMessage';
|
import { MarkdownMessage } from './MarkdownMessage';
|
||||||
|
import classes from './ChatLayout.module.css';
|
||||||
|
|
||||||
interface Message {
|
interface Message {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -96,30 +97,27 @@ export default function ChatLayout() {
|
|||||||
// Scroll state
|
// Scroll state
|
||||||
const scrollViewportRef = useRef<HTMLDivElement>(null);
|
const scrollViewportRef = useRef<HTMLDivElement>(null);
|
||||||
const isUserScrolledUp = useRef(false);
|
const isUserScrolledUp = useRef(false);
|
||||||
|
const isStreaming = useRef(false);
|
||||||
|
|
||||||
// Check if user is at bottom of scroll area
|
// Handle scroll events to track if user scrolled up (only when not streaming)
|
||||||
const checkIfAtBottom = () => {
|
const handleScroll = () => {
|
||||||
|
if (isStreaming.current) {
|
||||||
|
return; // Ignore scroll position checks during streaming
|
||||||
|
}
|
||||||
const viewport = scrollViewportRef.current;
|
const viewport = scrollViewportRef.current;
|
||||||
if (!viewport) {
|
if (!viewport) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
const threshold = 50; // pixels from bottom to consider "at bottom"
|
const threshold = 50;
|
||||||
return viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight < threshold;
|
isUserScrolledUp.current =
|
||||||
|
viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight > threshold;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle scroll events to track if user scrolled up
|
// Scroll to bottom using CSS scroll-behavior for smooth animation
|
||||||
const handleScroll = () => {
|
|
||||||
isUserScrolledUp.current = !checkIfAtBottom();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Scroll to bottom smoothly
|
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = () => {
|
||||||
const viewport = scrollViewportRef.current;
|
const viewport = scrollViewportRef.current;
|
||||||
if (viewport && !isUserScrolledUp.current) {
|
if (viewport && !isUserScrolledUp.current) {
|
||||||
viewport.scrollTo({
|
viewport.scrollTop = viewport.scrollHeight;
|
||||||
top: viewport.scrollHeight,
|
|
||||||
behavior: 'smooth',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,11 +128,14 @@ export default function ChatLayout() {
|
|||||||
}
|
}
|
||||||
}, [messages, streamingMessageId]);
|
}, [messages, streamingMessageId]);
|
||||||
|
|
||||||
// Scroll to bottom when user sends a message
|
// Track streaming state and scroll to bottom when streaming starts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (streamingMessageId) {
|
if (streamingMessageId) {
|
||||||
|
isStreaming.current = true;
|
||||||
isUserScrolledUp.current = false;
|
isUserScrolledUp.current = false;
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
|
} else {
|
||||||
|
isStreaming.current = false;
|
||||||
}
|
}
|
||||||
}, [streamingMessageId]);
|
}, [streamingMessageId]);
|
||||||
|
|
||||||
@@ -433,6 +434,7 @@ export default function ChatLayout() {
|
|||||||
offsetScrollbars
|
offsetScrollbars
|
||||||
viewportRef={scrollViewportRef}
|
viewportRef={scrollViewportRef}
|
||||||
onScrollPositionChange={handleScroll}
|
onScrollPositionChange={handleScroll}
|
||||||
|
classNames={{ viewport: classes.chatScrollViewport }}
|
||||||
>
|
>
|
||||||
<Stack gap="xl" px="md" py="lg">
|
<Stack gap="xl" px="md" py="lg">
|
||||||
{messages.map((message) => (
|
{messages.map((message) => (
|
||||||
|
|||||||
Reference in New Issue
Block a user