浏览代码

enh: chat landing ui option

Timothy J. Baek 7 月之前
父节点
当前提交
8ad44cd690

+ 2 - 2
src/lib/components/chat/Chat.svelte

@@ -70,7 +70,7 @@
 	import Navbar from '$lib/components/layout/Navbar.svelte';
 	import ChatControls from './ChatControls.svelte';
 	import EventConfirmDialog from '../common/ConfirmDialog.svelte';
-	import Placeholder from './Messages/Placeholder.svelte';
+	import Placeholder from './Placeholder.svelte';
 
 	export let chatIdProp = '';
 
@@ -1954,7 +1954,7 @@
 				{/if}
 
 				<div class="flex flex-col flex-auto z-10 w-full">
-					{#if history.currentId}
+					{#if $settings?.landingPageMode === 'chat' || createMessagesList(history.currentId).length > 0}
 						<div
 							class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-0 max-w-full z-10 scrollbar-hidden"
 							id="messages-container"

+ 4 - 2
src/lib/components/chat/Messages/OldPlaceholder.svelte → src/lib/components/chat/ChatPlaceholder.svelte

@@ -7,7 +7,7 @@
 
 	import { blur, fade } from 'svelte/transition';
 
-	import Suggestions from '../MessageInput/Suggestions.svelte';
+	import Suggestions from './Suggestions.svelte';
 	import { sanitizeResponseContent } from '$lib/utils';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import EyeSlash from '$lib/components/icons/EyeSlash.svelte';
@@ -128,7 +128,9 @@
 				suggestionPrompts={models[selectedModelIdx]?.info?.meta?.suggestion_prompts ??
 					$config?.default_prompt_suggestions ??
 					[]}
-				{submitPrompt}
+				on:select={(e) => {
+					submitPrompt(e.detail);
+				}}
 			/>
 		</div>
 	</div>

+ 39 - 2
src/lib/components/chat/Messages.svelte

@@ -8,11 +8,12 @@
 	import { getChatList, updateChatById } from '$lib/apis/chats';
 	import { copyToClipboard, findWordIndices } from '$lib/utils';
 
-	import Placeholder from './Messages/Placeholder.svelte';
 	import Message from './Messages/Message.svelte';
 	import Loader from '../common/Loader.svelte';
 	import Spinner from '../common/Spinner.svelte';
 
+	import ChatPlaceholder from './ChatPlaceholder.svelte';
+
 	const i18n = getContext('i18n');
 
 	export let chatId = '';
@@ -311,7 +312,43 @@
 
 <div class="h-full flex pt-8">
 	{#if Object.keys(history?.messages ?? {}).length == 0}
-		<Placeholder {selectedModels} bind:prompt />
+		<ChatPlaceholder
+			modelIds={selectedModels}
+			submitPrompt={async (p) => {
+				let text = p;
+
+				if (p.includes('{{CLIPBOARD}}')) {
+					const clipboardText = await navigator.clipboard.readText().catch((err) => {
+						toast.error($i18n.t('Failed to read clipboard contents'));
+						return '{{CLIPBOARD}}';
+					});
+
+					text = p.replaceAll('{{CLIPBOARD}}', clipboardText);
+				}
+
+				prompt = text;
+
+				await tick();
+
+				const chatInputElement = document.getElementById('chat-textarea');
+				if (chatInputElement) {
+					prompt = p;
+
+					chatInputElement.style.height = '';
+					chatInputElement.style.height = Math.min(chatInputElement.scrollHeight, 200) + 'px';
+					chatInputElement.focus();
+
+					const words = findWordIndices(prompt);
+
+					if (words.length > 0) {
+						const word = words.at(0);
+						chatInputElement.setSelectionRange(word?.startIndex, word.endIndex + 1);
+					}
+				}
+
+				await tick();
+			}}
+		/>
 	{:else}
 		<div class="w-full pt-2">
 			{#key chatId}

+ 2 - 2
src/lib/components/chat/Messages/Placeholder.svelte → src/lib/components/chat/Placeholder.svelte

@@ -11,10 +11,10 @@
 	import { sanitizeResponseContent, findWordIndices } from '$lib/utils';
 	import { WEBUI_BASE_URL } from '$lib/constants';
 
-	import Suggestions from '../MessageInput/Suggestions.svelte';
+	import Suggestions from './Suggestions.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import EyeSlash from '$lib/components/icons/EyeSlash.svelte';
-	import MessageInput from '../MessageInput.svelte';
+	import MessageInput from './MessageInput.svelte';
 
 	const i18n = getContext('i18n');
 

+ 27 - 0
src/lib/components/chat/Settings/Interface.svelte

@@ -29,6 +29,7 @@
 	let defaultModelId = '';
 	let showUsername = false;
 
+	let landingPageMode = '';
 	let chatBubble = true;
 	let chatDirection: 'LTR' | 'RTL' = 'LTR';
 
@@ -56,6 +57,11 @@
 		saveSettings({ chatBubble: chatBubble });
 	};
 
+	const toggleLandingPageMode = async () => {
+		landingPageMode = landingPageMode === '' ? 'chat' : '';
+		saveSettings({ landingPageMode: landingPageMode });
+	};
+
 	const toggleShowUsername = async () => {
 		showUsername = !showUsername;
 		saveSettings({ showUsername: showUsername });
@@ -150,6 +156,7 @@
 		showEmojiInCall = $settings.showEmojiInCall ?? false;
 		voiceInterruption = $settings.voiceInterruption ?? false;
 
+		landingPageMode = $settings.landingPageMode ?? '';
 		chatBubble = $settings.chatBubble ?? true;
 		widescreenMode = $settings.widescreenMode ?? false;
 		splitLargeChunks = $settings.splitLargeChunks ?? false;
@@ -229,6 +236,26 @@
 		<div>
 			<div class=" mb-1.5 text-sm font-medium">{$i18n.t('UI')}</div>
 
+			<div>
+				<div class=" py-0.5 flex w-full justify-between">
+					<div class=" self-center text-xs">{$i18n.t('Landing Page Mode')}</div>
+
+					<button
+						class="p-1 px-3 text-xs flex rounded transition"
+						on:click={() => {
+							toggleLandingPageMode();
+						}}
+						type="button"
+					>
+						{#if landingPageMode === ''}
+							<span class="ml-2 self-center">{$i18n.t('Default')}</span>
+						{:else}
+							<span class="ml-2 self-center">{$i18n.t('Chat')}</span>
+						{/if}
+					</button>
+				</div>
+			</div>
+
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
 					<div class=" self-center text-xs">{$i18n.t('Chat Bubble UI')}</div>

+ 0 - 0
src/lib/components/chat/MessageInput/Suggestions.svelte → src/lib/components/chat/Suggestions.svelte