فهرست منبع

webui: minor settings reorganization and add disable autoscroll option (#17452)

* webui: added a dedicated 'Display' settings section that groups visualization options

* webui: added a Display setting to toggle automatic chat scrolling

* chore: update webui build output
Pascal 1 ماه پیش
والد
کامیت
0c7220db56

BIN
tools/server/public/index.html.gz


+ 29 - 8
tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte

@@ -29,6 +29,7 @@
 		sendMessage,
 		sendMessage,
 		stopGeneration
 		stopGeneration
 	} from '$lib/stores/chat.svelte';
 	} from '$lib/stores/chat.svelte';
+	import { config } from '$lib/stores/settings.svelte';
 	import {
 	import {
 		supportsVision,
 		supportsVision,
 		supportsAudio,
 		supportsAudio,
@@ -47,6 +48,7 @@
 
 
 	let { showCenteredEmpty = false } = $props();
 	let { showCenteredEmpty = false } = $props();
 
 
+	let disableAutoScroll = $derived(Boolean(config().disableAutoScroll));
 	let autoScrollEnabled = $state(true);
 	let autoScrollEnabled = $state(true);
 	let chatScrollContainer: HTMLDivElement | undefined = $state();
 	let chatScrollContainer: HTMLDivElement | undefined = $state();
 	let dragCounter = $state(0);
 	let dragCounter = $state(0);
@@ -149,7 +151,7 @@
 	}
 	}
 
 
 	function handleScroll() {
 	function handleScroll() {
-		if (!chatScrollContainer) return;
+		if (disableAutoScroll || !chatScrollContainer) return;
 
 
 		const { scrollTop, scrollHeight, clientHeight } = chatScrollContainer;
 		const { scrollTop, scrollHeight, clientHeight } = chatScrollContainer;
 		const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
 		const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
@@ -194,8 +196,10 @@
 		const extras = result?.extras;
 		const extras = result?.extras;
 
 
 		// Enable autoscroll for user-initiated message sending
 		// Enable autoscroll for user-initiated message sending
-		userScrolledUp = false;
-		autoScrollEnabled = true;
+		if (!disableAutoScroll) {
+			userScrolledUp = false;
+			autoScrollEnabled = true;
+		}
 		await sendMessage(message, extras);
 		await sendMessage(message, extras);
 		scrollChatToBottom();
 		scrollChatToBottom();
 
 
@@ -241,6 +245,8 @@
 	}
 	}
 
 
 	function scrollChatToBottom(behavior: ScrollBehavior = 'smooth') {
 	function scrollChatToBottom(behavior: ScrollBehavior = 'smooth') {
+		if (disableAutoScroll) return;
+
 		chatScrollContainer?.scrollTo({
 		chatScrollContainer?.scrollTo({
 			top: chatScrollContainer?.scrollHeight,
 			top: chatScrollContainer?.scrollHeight,
 			behavior
 			behavior
@@ -248,14 +254,27 @@
 	}
 	}
 
 
 	afterNavigate(() => {
 	afterNavigate(() => {
-		setTimeout(() => scrollChatToBottom('instant'), INITIAL_SCROLL_DELAY);
+		if (!disableAutoScroll) {
+			setTimeout(() => scrollChatToBottom('instant'), INITIAL_SCROLL_DELAY);
+		}
 	});
 	});
 
 
 	onMount(() => {
 	onMount(() => {
-		setTimeout(() => scrollChatToBottom('instant'), INITIAL_SCROLL_DELAY);
+		if (!disableAutoScroll) {
+			setTimeout(() => scrollChatToBottom('instant'), INITIAL_SCROLL_DELAY);
+		}
 	});
 	});
 
 
 	$effect(() => {
 	$effect(() => {
+		if (disableAutoScroll) {
+			autoScrollEnabled = false;
+			if (scrollInterval) {
+				clearInterval(scrollInterval);
+				scrollInterval = undefined;
+			}
+			return;
+		}
+
 		if (isCurrentConversationLoading && autoScrollEnabled) {
 		if (isCurrentConversationLoading && autoScrollEnabled) {
 			scrollInterval = setInterval(scrollChatToBottom, AUTO_SCROLL_INTERVAL);
 			scrollInterval = setInterval(scrollChatToBottom, AUTO_SCROLL_INTERVAL);
 		} else if (scrollInterval) {
 		} else if (scrollInterval) {
@@ -289,9 +308,11 @@
 			class="mb-16 md:mb-24"
 			class="mb-16 md:mb-24"
 			messages={activeMessages()}
 			messages={activeMessages()}
 			onUserAction={() => {
 			onUserAction={() => {
-				userScrolledUp = false;
-				autoScrollEnabled = true;
-				scrollChatToBottom();
+				if (!disableAutoScroll) {
+					userScrolledUp = false;
+					autoScrollEnabled = true;
+					scrollChatToBottom();
+				}
 			}}
 			}}
 		/>
 		/>
 
 

+ 29 - 25
tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettings.svelte

@@ -3,7 +3,6 @@
 		Settings,
 		Settings,
 		Funnel,
 		Funnel,
 		AlertTriangle,
 		AlertTriangle,
-		Brain,
 		Code,
 		Code,
 		Monitor,
 		Monitor,
 		Sun,
 		Sun,
@@ -58,6 +57,33 @@
 					label: 'Paste long text to file length',
 					label: 'Paste long text to file length',
 					type: 'input'
 					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',
 					key: 'showMessageStats',
 					label: 'Show message generation statistics',
 					label: 'Show message generation statistics',
@@ -79,25 +105,14 @@
 					type: 'checkbox'
 					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'
 					type: 'checkbox'
 				},
 				},
 				{
 				{
 					key: 'renderUserContentAsMarkdown',
 					key: 'renderUserContentAsMarkdown',
 					label: 'Render user content as Markdown',
 					label: 'Render user content as Markdown',
 					type: 'checkbox'
 					type: 'checkbox'
-				},
-				{
-					key: 'askForTitleConfirmation',
-					label: 'Ask for confirmation before changing conversation title',
-					type: 'checkbox'
 				}
 				}
 			]
 			]
 		},
 		},
@@ -208,17 +223,6 @@
 				}
 				}
 			]
 			]
 		},
 		},
-		{
-			title: 'Reasoning',
-			icon: Brain,
-			fields: [
-				{
-					key: 'showThoughtInProgress',
-					label: 'Show thought in progress',
-					type: 'checkbox'
-				}
-			]
-		},
 		{
 		{
 			title: 'Import/Export',
 			title: 'Import/Export',
 			icon: Database,
 			icon: Database,

+ 3 - 0
tools/server/webui/src/lib/constants/settings-config.ts

@@ -14,6 +14,7 @@ export const SETTING_CONFIG_DEFAULT: Record<string, string | number | boolean> =
 	pasteLongTextToFileLen: 2500,
 	pasteLongTextToFileLen: 2500,
 	pdfAsImage: false,
 	pdfAsImage: false,
 	showModelInfo: false,
 	showModelInfo: false,
+	disableAutoScroll: false,
 	renderUserContentAsMarkdown: false,
 	renderUserContentAsMarkdown: false,
 	modelSelectorEnabled: false,
 	modelSelectorEnabled: false,
 	// make sure these default values are in sync with `common.h`
 	// make sure these default values are in sync with `common.h`
@@ -93,6 +94,8 @@ export const SETTING_CONFIG_INFO: Record<string, string> = {
 		'Ask for confirmation before automatically changing conversation title when editing the first message.',
 		'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).',
 	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.',
 	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.',
 	renderUserContentAsMarkdown: 'Render user messages using markdown formatting in the chat.',
 	modelSelectorEnabled:
 	modelSelectorEnabled:
 		'Enable the model selector in the chat input to choose the inference model. Sends the associated model field in API requests.',
 		'Enable the model selector in the chat input to choose the inference model. Sends the associated model field in API requests.',