From 16aa6fae0a803e23e25df1e253ddfa7b7c71b22a Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Sat, 24 Jan 2026 13:32:49 +0100 Subject: [PATCH] fix: Save draft message in Chat Form when adding System Prompt from new chat view --- .../app/chat/ChatForm/ChatForm.svelte | 19 ++++++++++-- .../chat/ChatForm/ChatFormInputArea.svelte | 4 +-- .../app/chat/ChatScreen/ChatScreen.svelte | 4 +-- .../webui/src/lib/stores/chat.svelte.ts | 29 +++++++++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatForm.svelte b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatForm.svelte index d2bf2afe49..3ed2987f97 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatForm.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatForm.svelte @@ -12,7 +12,7 @@ onFileUpload?: (files: File[]) => void; onSend?: (message: string, files?: ChatUploadedFile[]) => Promise; onStop?: () => void; - onSystemPromptAdd?: () => void; + onSystemPromptAdd?: (draft: { message: string; files: ChatUploadedFile[] }) => void; showHelperText?: boolean; uploadedFiles?: ChatUploadedFile[]; } @@ -32,8 +32,21 @@ }: Props = $props(); let inputAreaRef: ChatFormInputArea | undefined = $state(undefined); - let message = $state(''); + let message = $state(initialMessage); let previousIsLoading = $state(isLoading); + let previousInitialMessage = $state(initialMessage); + + // Sync message when initialMessage prop changes (e.g., after draft restoration) + $effect(() => { + if (initialMessage !== previousInitialMessage) { + message = initialMessage; + previousInitialMessage = initialMessage; + } + }); + + function handleSystemPromptClick() { + onSystemPromptAdd?.({ message, files: uploadedFiles }); + } let hasLoadingAttachments = $derived(uploadedFiles.some((f) => f.isLoading)); @@ -101,7 +114,7 @@ onFilesAdd={handleFilesAdd} {onStop} onSubmit={handleSubmit} - onSystemPromptClick={onSystemPromptAdd} + onSystemPromptClick={handleSystemPromptClick} onUploadedFileRemove={handleUploadedFileRemove} /> diff --git a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormInputArea.svelte b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormInputArea.svelte index f9ff52d03b..b023f0428e 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormInputArea.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormInputArea.svelte @@ -39,7 +39,7 @@ onMcpPromptArgumentsChange?: (fileId: string, args: Record) => void; onStop?: () => void; onSubmit?: () => void; - onSystemPromptClick?: () => void; + onSystemPromptClick?: (draft: { message: string; files: ChatUploadedFile[] }) => void; onUploadedFileRemove?: (fileId: string) => void; onUploadedFilesChange?: (files: ChatUploadedFile[]) => void; onValueChange?: (value: string) => void; @@ -422,7 +422,7 @@ onFileUpload={handleFileUpload} onMicClick={handleMicClick} {onStop} - {onSystemPromptClick} + onSystemPromptClick={() => onSystemPromptClick?.({ message: value, files: uploadedFiles })} onMcpPromptClick={showMcpPromptButton ? () => (isPromptPickerOpen = true) : undefined} /> diff --git a/tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte b/tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte index 5f23316be0..4311c22da1 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte @@ -400,7 +400,7 @@ onFileUpload={handleFileUpload} onSend={handleSendMessage} onStop={() => chatStore.stopGeneration()} - onSystemPromptAdd={() => chatStore.addSystemPrompt()} + onSystemPromptAdd={handleSystemPromptAdd} showHelperText={false} bind:uploadedFiles /> @@ -460,7 +460,7 @@ onFileUpload={handleFileUpload} onSend={handleSendMessage} onStop={() => chatStore.stopGeneration()} - onSystemPromptAdd={() => chatStore.addSystemPrompt()} + onSystemPromptAdd={handleSystemPromptAdd} showHelperText={true} bind:uploadedFiles /> diff --git a/tools/server/webui/src/lib/stores/chat.svelte.ts b/tools/server/webui/src/lib/stores/chat.svelte.ts index 7f26f30953..7e7c8fdfaf 100644 --- a/tools/server/webui/src/lib/stores/chat.svelte.ts +++ b/tools/server/webui/src/lib/stores/chat.svelte.ts @@ -41,6 +41,10 @@ class ChatStore { private addFilesHandler: ((files: File[]) => void) | null = $state(null); pendingEditMessageId = $state(null); + // Draft preservation for navigation (e.g., when adding system prompt from welcome page) + private _pendingDraftMessage = $state(''); + private _pendingDraftFiles = $state([]); + constructor() { if (browser) { chatClient.setStoreCallbacks({ @@ -219,6 +223,31 @@ class ChatStore { this.pendingEditMessageId = null; } + savePendingDraft(message: string, files: ChatUploadedFile[]): void { + this._pendingDraftMessage = message; + this._pendingDraftFiles = [...files]; + } + + consumePendingDraft(): { message: string; files: ChatUploadedFile[] } | null { + if (!this._pendingDraftMessage && this._pendingDraftFiles.length === 0) { + return null; + } + + const draft = { + message: this._pendingDraftMessage, + files: [...this._pendingDraftFiles] + }; + + this._pendingDraftMessage = ''; + this._pendingDraftFiles = []; + + return draft; + } + + hasPendingDraft(): boolean { + return Boolean(this._pendingDraftMessage) || this._pendingDraftFiles.length > 0; + } + getAllLoadingChats(): string[] { return Array.from(this.chatLoadingStates.keys()); }