fix: Save draft message in Chat Form when adding System Prompt from new chat view
This commit is contained in:
parent
a647edfc0b
commit
2601bf0f59
|
|
@ -6,12 +6,13 @@
|
|||
interface Props {
|
||||
class?: string;
|
||||
disabled?: boolean;
|
||||
initialMessage?: string;
|
||||
isLoading?: boolean;
|
||||
onFileRemove?: (fileId: string) => void;
|
||||
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[];
|
||||
}
|
||||
|
|
@ -19,6 +20,7 @@
|
|||
let {
|
||||
class: className,
|
||||
disabled = false,
|
||||
initialMessage = '',
|
||||
isLoading = false,
|
||||
onFileRemove,
|
||||
onFileUpload,
|
||||
|
|
@ -30,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));
|
||||
|
||||
|
|
@ -99,7 +114,7 @@
|
|||
onFilesAdd={handleFilesAdd}
|
||||
{onStop}
|
||||
onSubmit={handleSubmit}
|
||||
onSystemPromptClick={onSystemPromptAdd}
|
||||
onSystemPromptClick={handleSystemPromptClick}
|
||||
onUploadedFileRemove={handleUploadedFileRemove}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@
|
|||
|
||||
let emptyFileNames = $state<string[]>([]);
|
||||
|
||||
let initialMessage = $state('');
|
||||
|
||||
let isEmpty = $derived(
|
||||
showCenteredEmpty && !activeConversation() && activeMessages().length === 0 && !isLoading()
|
||||
);
|
||||
|
|
@ -215,6 +217,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function handleSystemPromptAdd(draft: { message: string; files: ChatUploadedFile[] }) {
|
||||
if (draft.message || draft.files.length > 0) {
|
||||
chatStore.savePendingDraft(draft.message, draft.files);
|
||||
}
|
||||
|
||||
await chatStore.addSystemPrompt();
|
||||
}
|
||||
|
||||
function handleScroll() {
|
||||
autoScroll.handleScroll();
|
||||
}
|
||||
|
|
@ -301,6 +311,12 @@
|
|||
if (!disableAutoScroll) {
|
||||
setTimeout(() => autoScroll.scrollToBottom('instant'), INITIAL_SCROLL_DELAY);
|
||||
}
|
||||
|
||||
const pendingDraft = chatStore.consumePendingDraft();
|
||||
if (pendingDraft) {
|
||||
initialMessage = pendingDraft.message;
|
||||
uploadedFiles = pendingDraft.files;
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
|
|
@ -377,12 +393,13 @@
|
|||
<div class="conversation-chat-form pointer-events-auto rounded-t-3xl pb-4">
|
||||
<ChatForm
|
||||
disabled={hasPropsError || isEditing()}
|
||||
{initialMessage}
|
||||
isLoading={isCurrentConversationLoading}
|
||||
onFileRemove={handleFileRemove}
|
||||
onFileUpload={handleFileUpload}
|
||||
onSend={handleSendMessage}
|
||||
onStop={() => chatStore.stopGeneration()}
|
||||
onSystemPromptAdd={() => chatStore.addSystemPrompt()}
|
||||
onSystemPromptAdd={handleSystemPromptAdd}
|
||||
showHelperText={false}
|
||||
bind:uploadedFiles
|
||||
/>
|
||||
|
|
@ -436,12 +453,13 @@
|
|||
<div in:fly={{ y: 10, duration: 250, delay: hasPropsError ? 0 : 300 }}>
|
||||
<ChatForm
|
||||
disabled={hasPropsError}
|
||||
{initialMessage}
|
||||
isLoading={isCurrentConversationLoading}
|
||||
onFileRemove={handleFileRemove}
|
||||
onFileUpload={handleFileUpload}
|
||||
onSend={handleSendMessage}
|
||||
onStop={() => chatStore.stopGeneration()}
|
||||
onSystemPromptAdd={() => chatStore.addSystemPrompt()}
|
||||
onSystemPromptAdd={handleSystemPromptAdd}
|
||||
showHelperText={true}
|
||||
bind:uploadedFiles
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue