sendMessage,
stopGeneration
} from '$lib/stores/chat.svelte';
+ import { config } from '$lib/stores/settings.svelte';
import {
supportsVision,
supportsAudio,
let { showCenteredEmpty = false } = $props();
+ let disableAutoScroll = $derived(Boolean(config().disableAutoScroll));
let autoScrollEnabled = $state(true);
let chatScrollContainer: HTMLDivElement | undefined = $state();
let dragCounter = $state(0);
}
function handleScroll() {
- if (!chatScrollContainer) return;
+ if (disableAutoScroll || !chatScrollContainer) return;
const { scrollTop, scrollHeight, clientHeight } = chatScrollContainer;
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
const extras = result?.extras;
// Enable autoscroll for user-initiated message sending
- userScrolledUp = false;
- autoScrollEnabled = true;
+ if (!disableAutoScroll) {
+ userScrolledUp = false;
+ autoScrollEnabled = true;
+ }
await sendMessage(message, extras);
scrollChatToBottom();
}
function scrollChatToBottom(behavior: ScrollBehavior = 'smooth') {
+ if (disableAutoScroll) return;
+
chatScrollContainer?.scrollTo({
top: chatScrollContainer?.scrollHeight,
behavior
}
afterNavigate(() => {
- setTimeout(() => scrollChatToBottom('instant'), INITIAL_SCROLL_DELAY);
+ if (!disableAutoScroll) {
+ setTimeout(() => scrollChatToBottom('instant'), INITIAL_SCROLL_DELAY);
+ }
});
onMount(() => {
- setTimeout(() => scrollChatToBottom('instant'), INITIAL_SCROLL_DELAY);
+ if (!disableAutoScroll) {
+ setTimeout(() => scrollChatToBottom('instant'), INITIAL_SCROLL_DELAY);
+ }
});
$effect(() => {
+ if (disableAutoScroll) {
+ autoScrollEnabled = false;
+ if (scrollInterval) {
+ clearInterval(scrollInterval);
+ scrollInterval = undefined;
+ }
+ return;
+ }
+
if (isCurrentConversationLoading && autoScrollEnabled) {
scrollInterval = setInterval(scrollChatToBottom, AUTO_SCROLL_INTERVAL);
} else if (scrollInterval) {
class="mb-16 md:mb-24"
messages={activeMessages()}
onUserAction={() => {
- userScrolledUp = false;
- autoScrollEnabled = true;
- scrollChatToBottom();
+ if (!disableAutoScroll) {
+ userScrolledUp = false;
+ autoScrollEnabled = true;
+ scrollChatToBottom();
+ }
}}
/>
Settings,
Funnel,
AlertTriangle,
- Brain,
Code,
Monitor,
Sun,
label: 'Paste long text to file length',
type: 'input'
},
+ {
+ key: 'enableContinueGeneration',
+ label: 'Enable "Continue" button',
+ type: 'checkbox',
+ isExperimental: true
+ },
+ {
+ key: 'pdfAsImage',
+ label: 'Parse PDF as image',
+ type: 'checkbox'
+ },
+ {
+ key: 'askForTitleConfirmation',
+ label: 'Ask for confirmation before changing conversation title',
+ type: 'checkbox'
+ }
+ ]
+ },
+ {
+ title: 'Display',
+ icon: Monitor,
+ fields: [
+ {
+ key: 'showThoughtInProgress',
+ label: 'Show thought in progress',
+ type: 'checkbox'
+ },
{
key: 'showMessageStats',
label: 'Show message generation statistics',
type: 'checkbox'
},
{
- key: 'enableContinueGeneration',
- label: 'Enable "Continue" button',
- type: 'checkbox',
- isExperimental: true
- },
- {
- key: 'pdfAsImage',
- label: 'Parse PDF as image',
+ key: 'disableAutoScroll',
+ label: 'Disable automatic scroll',
type: 'checkbox'
},
{
key: 'renderUserContentAsMarkdown',
label: 'Render user content as Markdown',
type: 'checkbox'
- },
- {
- key: 'askForTitleConfirmation',
- label: 'Ask for confirmation before changing conversation title',
- type: 'checkbox'
}
]
},
}
]
},
- {
- title: 'Reasoning',
- icon: Brain,
- fields: [
- {
- key: 'showThoughtInProgress',
- label: 'Show thought in progress',
- type: 'checkbox'
- }
- ]
- },
{
title: 'Import/Export',
icon: Database,
pasteLongTextToFileLen: 2500,
pdfAsImage: false,
showModelInfo: false,
+ disableAutoScroll: false,
renderUserContentAsMarkdown: false,
modelSelectorEnabled: false,
// make sure these default values are in sync with `common.h`
'Ask for confirmation before automatically changing conversation title when editing the first message.',
pdfAsImage: 'Parse PDF as image instead of text (requires vision-capable model).',
showModelInfo: 'Display the model name used to generate each message below the message content.',
+ disableAutoScroll:
+ 'Disable automatic scrolling while messages stream so you can control the viewport position manually.',
renderUserContentAsMarkdown: 'Render user messages using markdown formatting in the chat.',
modelSelectorEnabled:
'Enable the model selector in the chat input to choose the inference model. Sends the associated model field in API requests.',