fix: Save draft message in Chat Form when adding System Prompt from new chat view

This commit is contained in:
Aleksander Grygier 2026-01-24 13:32:49 +01:00
parent 0fe25847ff
commit 16aa6fae0a
4 changed files with 49 additions and 7 deletions

View File

@ -12,7 +12,7 @@
onFileUpload?: (files: File[]) => void;
onSend?: (message: string, files?: ChatUploadedFile[]) => Promise<boolean>;
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}
/>
</div>

View File

@ -39,7 +39,7 @@
onMcpPromptArgumentsChange?: (fileId: string, args: Record<string, string>) => 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}
/>
</div>

View File

@ -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
/>

View File

@ -41,6 +41,10 @@ class ChatStore {
private addFilesHandler: ((files: File[]) => void) | null = $state(null);
pendingEditMessageId = $state<string | null>(null);
// Draft preservation for navigation (e.g., when adding system prompt from welcome page)
private _pendingDraftMessage = $state<string>('');
private _pendingDraftFiles = $state<ChatUploadedFile[]>([]);
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());
}