refactor: Adapt message child components to MessageEditContext
This commit is contained in:
parent
ed6ecf7747
commit
1d15e29185
|
|
@ -7,10 +7,11 @@
|
|||
ModelBadge,
|
||||
ModelsSelector
|
||||
} from '$lib/components/app';
|
||||
import { getMessageEditContext } from '$lib/contexts';
|
||||
import { useProcessingState } from '$lib/hooks/use-processing-state.svelte';
|
||||
import { isLoading, isChatStreaming } from '$lib/stores/chat.svelte';
|
||||
import { agenticStreamingToolCall } from '$lib/stores/agentic.svelte';
|
||||
import { autoResizeTextarea, copyToClipboard } from '$lib/utils';
|
||||
import { autoResizeTextarea, copyToClipboard, isIMEComposing } from '$lib/utils';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { Check, X } from '@lucide/svelte';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
|
|
@ -32,25 +33,17 @@
|
|||
assistantMessages: number;
|
||||
messageTypes: string[];
|
||||
} | null;
|
||||
editedContent?: string;
|
||||
isEditing?: boolean;
|
||||
message: DatabaseMessage;
|
||||
messageContent: string | undefined;
|
||||
onCancelEdit?: () => void;
|
||||
onCopy: () => void;
|
||||
onConfirmDelete: () => void;
|
||||
onContinue?: () => void;
|
||||
onDelete: () => void;
|
||||
onEdit?: () => void;
|
||||
onEditKeydown?: (event: KeyboardEvent) => void;
|
||||
onEditedContentChange?: (content: string) => void;
|
||||
onNavigateToSibling?: (siblingId: string) => void;
|
||||
onRegenerate: (modelOverride?: string) => void;
|
||||
onSaveEdit?: () => void;
|
||||
onShowDeleteDialogChange: (show: boolean) => void;
|
||||
onShouldBranchAfterEditChange?: (value: boolean) => void;
|
||||
showDeleteDialog: boolean;
|
||||
shouldBranchAfterEdit?: boolean;
|
||||
siblingInfo?: ChatMessageSiblingInfo | null;
|
||||
textareaElement?: HTMLTextAreaElement;
|
||||
}
|
||||
|
|
@ -58,29 +51,37 @@
|
|||
let {
|
||||
class: className = '',
|
||||
deletionInfo,
|
||||
editedContent = '',
|
||||
isEditing = false,
|
||||
message,
|
||||
messageContent,
|
||||
onCancelEdit,
|
||||
onConfirmDelete,
|
||||
onContinue,
|
||||
onCopy,
|
||||
onDelete,
|
||||
onEdit,
|
||||
onEditKeydown,
|
||||
onEditedContentChange,
|
||||
onNavigateToSibling,
|
||||
onRegenerate,
|
||||
onSaveEdit,
|
||||
onShowDeleteDialogChange,
|
||||
onShouldBranchAfterEditChange,
|
||||
showDeleteDialog,
|
||||
shouldBranchAfterEdit = false,
|
||||
siblingInfo = null,
|
||||
textareaElement = $bindable()
|
||||
}: Props = $props();
|
||||
|
||||
// Get edit context
|
||||
const editCtx = getMessageEditContext();
|
||||
|
||||
// Local state for assistant-specific editing
|
||||
let shouldBranchAfterEdit = $state(false);
|
||||
|
||||
function handleEditKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter' && !event.shiftKey && !isIMEComposing(event)) {
|
||||
event.preventDefault();
|
||||
editCtx.save();
|
||||
} else if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
editCtx.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
const hasAgenticMarkers = $derived(
|
||||
messageContent?.includes(AGENTIC_TAGS.TOOL_CALL_START) ?? false
|
||||
);
|
||||
|
|
@ -104,7 +105,7 @@
|
|||
}
|
||||
|
||||
$effect(() => {
|
||||
if (isEditing && textareaElement) {
|
||||
if (editCtx.isEditing && textareaElement) {
|
||||
autoResizeTextarea(textareaElement);
|
||||
}
|
||||
});
|
||||
|
|
@ -131,16 +132,16 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
{#if isEditing}
|
||||
{#if editCtx.isEditing}
|
||||
<div class="w-full">
|
||||
<textarea
|
||||
bind:this={textareaElement}
|
||||
bind:value={editedContent}
|
||||
value={editCtx.editedContent}
|
||||
class="min-h-[50vh] w-full resize-y rounded-2xl px-3 py-2 text-sm {INPUT_CLASSES}"
|
||||
onkeydown={onEditKeydown}
|
||||
onkeydown={handleEditKeydown}
|
||||
oninput={(e) => {
|
||||
autoResizeTextarea(e.currentTarget);
|
||||
onEditedContentChange?.(e.currentTarget.value);
|
||||
editCtx.setContent(e.currentTarget.value);
|
||||
}}
|
||||
placeholder="Edit assistant message..."
|
||||
></textarea>
|
||||
|
|
@ -150,19 +151,24 @@
|
|||
<Checkbox
|
||||
id="branch-after-edit"
|
||||
bind:checked={shouldBranchAfterEdit}
|
||||
onCheckedChange={(checked) => onShouldBranchAfterEditChange?.(checked === true)}
|
||||
onCheckedChange={(checked) => (shouldBranchAfterEdit = checked === true)}
|
||||
/>
|
||||
<Label for="branch-after-edit" class="cursor-pointer text-sm text-muted-foreground">
|
||||
Branch conversation after edit
|
||||
</Label>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<Button class="h-8 px-3" onclick={onCancelEdit} size="sm" variant="outline">
|
||||
<Button class="h-8 px-3" onclick={editCtx.cancel} size="sm" variant="outline">
|
||||
<X class="mr-1 h-3 w-3" />
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button class="h-8 px-3" onclick={onSaveEdit} disabled={!editedContent?.trim()} size="sm">
|
||||
<Button
|
||||
class="h-8 px-3"
|
||||
onclick={editCtx.save}
|
||||
disabled={!editCtx.editedContent?.trim()}
|
||||
size="sm"
|
||||
>
|
||||
<Check class="mr-1 h-3 w-3" />
|
||||
Save
|
||||
</Button>
|
||||
|
|
@ -239,7 +245,7 @@
|
|||
{/if}
|
||||
</div>
|
||||
|
||||
{#if message.timestamp && !isEditing}
|
||||
{#if message.timestamp && !editCtx.isEditing}
|
||||
<ChatMessageActions
|
||||
role={MessageRole.ASSISTANT}
|
||||
justify="start"
|
||||
|
|
|
|||
|
|
@ -3,50 +3,23 @@
|
|||
import { Button } from '$lib/components/ui/button';
|
||||
import { Switch } from '$lib/components/ui/switch';
|
||||
import { ChatForm, DialogConfirmation } from '$lib/components/app';
|
||||
import { getMessageEditContext } from '$lib/contexts';
|
||||
import { chatStore } from '$lib/stores/chat.svelte';
|
||||
import { processFilesToChatUploaded } from '$lib/utils/browser-only';
|
||||
|
||||
interface Props {
|
||||
editedContent: string;
|
||||
editedExtras?: DatabaseMessageExtra[];
|
||||
editedUploadedFiles?: ChatUploadedFile[];
|
||||
originalContent: string;
|
||||
originalExtras?: DatabaseMessageExtra[];
|
||||
showSaveOnlyOption?: boolean;
|
||||
onCancelEdit: () => void;
|
||||
onSaveEdit: () => void;
|
||||
onSaveEditOnly?: () => void;
|
||||
onEditedContentChange: (content: string) => void;
|
||||
onEditedExtrasChange?: (extras: DatabaseMessageExtra[]) => void;
|
||||
onEditedUploadedFilesChange?: (files: ChatUploadedFile[]) => void;
|
||||
}
|
||||
|
||||
let {
|
||||
editedContent,
|
||||
editedExtras = [],
|
||||
editedUploadedFiles = [],
|
||||
originalContent,
|
||||
originalExtras = [],
|
||||
showSaveOnlyOption = false,
|
||||
onCancelEdit,
|
||||
onSaveEdit,
|
||||
onSaveEditOnly,
|
||||
onEditedContentChange,
|
||||
onEditedExtrasChange,
|
||||
onEditedUploadedFilesChange
|
||||
}: Props = $props();
|
||||
const editCtx = getMessageEditContext();
|
||||
|
||||
let inputAreaRef: ChatForm | undefined = $state(undefined);
|
||||
let saveWithoutRegenerate = $state(false);
|
||||
let showDiscardDialog = $state(false);
|
||||
|
||||
let hasUnsavedChanges = $derived.by(() => {
|
||||
if (editedContent !== originalContent) return true;
|
||||
if (editedUploadedFiles.length > 0) return true;
|
||||
if (editCtx.editedContent !== editCtx.originalContent) return true;
|
||||
if (editCtx.editedUploadedFiles.length > 0) return true;
|
||||
|
||||
const extrasChanged =
|
||||
editedExtras.length !== originalExtras.length ||
|
||||
editedExtras.some((extra, i) => extra !== originalExtras[i]);
|
||||
editCtx.editedExtras.length !== editCtx.originalExtras.length ||
|
||||
editCtx.editedExtras.some((extra, i) => extra !== editCtx.originalExtras[i]);
|
||||
|
||||
if (extrasChanged) return true;
|
||||
|
||||
|
|
@ -54,11 +27,11 @@
|
|||
});
|
||||
|
||||
let hasAttachments = $derived(
|
||||
(editedExtras && editedExtras.length > 0) ||
|
||||
(editedUploadedFiles && editedUploadedFiles.length > 0)
|
||||
(editCtx.editedExtras && editCtx.editedExtras.length > 0) ||
|
||||
(editCtx.editedUploadedFiles && editCtx.editedUploadedFiles.length > 0)
|
||||
);
|
||||
|
||||
let canSubmit = $derived(editedContent.trim().length > 0 || hasAttachments);
|
||||
let canSubmit = $derived(editCtx.editedContent.trim().length > 0 || hasAttachments);
|
||||
|
||||
function handleGlobalKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') {
|
||||
|
|
@ -71,47 +44,40 @@
|
|||
if (hasUnsavedChanges) {
|
||||
showDiscardDialog = true;
|
||||
} else {
|
||||
onCancelEdit();
|
||||
editCtx.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
if (!canSubmit) return;
|
||||
|
||||
if (saveWithoutRegenerate && onSaveEditOnly) {
|
||||
onSaveEditOnly();
|
||||
if (saveWithoutRegenerate && editCtx.showSaveOnlyOption) {
|
||||
editCtx.saveOnly();
|
||||
} else {
|
||||
onSaveEdit();
|
||||
editCtx.save();
|
||||
}
|
||||
|
||||
saveWithoutRegenerate = false;
|
||||
}
|
||||
|
||||
function handleAttachmentRemove(index: number) {
|
||||
if (!onEditedExtrasChange) return;
|
||||
|
||||
const newExtras = [...editedExtras];
|
||||
const newExtras = [...editCtx.editedExtras];
|
||||
newExtras.splice(index, 1);
|
||||
onEditedExtrasChange(newExtras);
|
||||
editCtx.setExtras(newExtras);
|
||||
}
|
||||
|
||||
function handleUploadedFileRemove(fileId: string) {
|
||||
if (!onEditedUploadedFilesChange) return;
|
||||
|
||||
const newFiles = editedUploadedFiles.filter((f) => f.id !== fileId);
|
||||
onEditedUploadedFilesChange(newFiles);
|
||||
const newFiles = editCtx.editedUploadedFiles.filter((f) => f.id !== fileId);
|
||||
editCtx.setUploadedFiles(newFiles);
|
||||
}
|
||||
|
||||
async function handleFilesAdd(files: File[]) {
|
||||
if (!onEditedUploadedFilesChange) return;
|
||||
|
||||
const processed = await processFilesToChatUploaded(files);
|
||||
|
||||
onEditedUploadedFilesChange([...editedUploadedFiles, processed].flat());
|
||||
editCtx.setUploadedFiles([...editCtx.editedUploadedFiles, ...processed]);
|
||||
}
|
||||
|
||||
function handleUploadedFilesChange(files: ChatUploadedFile[]) {
|
||||
onEditedUploadedFilesChange?.(files);
|
||||
editCtx.setUploadedFiles(files);
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
|
|
@ -128,11 +94,11 @@
|
|||
<div class="relative w-full max-w-[80%]">
|
||||
<ChatForm
|
||||
bind:this={inputAreaRef}
|
||||
value={editedContent}
|
||||
attachments={editedExtras}
|
||||
uploadedFiles={editedUploadedFiles}
|
||||
value={editCtx.editedContent}
|
||||
attachments={editCtx.editedExtras}
|
||||
uploadedFiles={editCtx.editedUploadedFiles}
|
||||
placeholder="Edit your message..."
|
||||
onValueChange={onEditedContentChange}
|
||||
onValueChange={editCtx.setContent}
|
||||
onAttachmentRemove={handleAttachmentRemove}
|
||||
onUploadedFileRemove={handleUploadedFileRemove}
|
||||
onUploadedFilesChange={handleUploadedFilesChange}
|
||||
|
|
@ -142,7 +108,7 @@
|
|||
</div>
|
||||
|
||||
<div class="mt-2 flex w-full max-w-[80%] items-center justify-between">
|
||||
{#if showSaveOnlyOption && onSaveEditOnly}
|
||||
{#if editCtx.showSaveOnlyOption}
|
||||
<div class="flex items-center gap-2">
|
||||
<Switch id="save-only-switch" bind:checked={saveWithoutRegenerate} class="scale-75" />
|
||||
|
||||
|
|
@ -169,6 +135,6 @@
|
|||
cancelText="Keep editing"
|
||||
variant="destructive"
|
||||
icon={AlertTriangle}
|
||||
onConfirm={onCancelEdit}
|
||||
onConfirm={editCtx.cancel}
|
||||
onCancel={() => (showDiscardDialog = false)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { ChatMessageActions, ChatMessageMcpPromptContent } from '$lib/components/app';
|
||||
import { getMessageEditContext } from '$lib/contexts';
|
||||
import { MessageRole, McpPromptVariant } from '$lib/enums';
|
||||
import type { DatabaseMessageExtraMcpPrompt } from '$lib/types';
|
||||
import ChatMessageEditForm from './ChatMessageEditForm.svelte';
|
||||
|
|
@ -8,10 +9,6 @@
|
|||
class?: string;
|
||||
message: DatabaseMessage;
|
||||
mcpPrompt: DatabaseMessageExtraMcpPrompt;
|
||||
isEditing: boolean;
|
||||
editedContent: string;
|
||||
editedExtras?: DatabaseMessageExtra[];
|
||||
editedUploadedFiles?: ChatUploadedFile[];
|
||||
siblingInfo?: ChatMessageSiblingInfo | null;
|
||||
showDeleteDialog: boolean;
|
||||
deletionInfo: {
|
||||
|
|
@ -20,12 +17,6 @@
|
|||
assistantMessages: number;
|
||||
messageTypes: string[];
|
||||
} | null;
|
||||
onCancelEdit: () => void;
|
||||
onSaveEdit: () => void;
|
||||
onSaveEditOnly?: () => void;
|
||||
onEditedContentChange: (content: string) => void;
|
||||
onEditedExtrasChange?: (extras: DatabaseMessageExtra[]) => void;
|
||||
onEditedUploadedFilesChange?: (files: ChatUploadedFile[]) => void;
|
||||
onCopy: () => void;
|
||||
onEdit: () => void;
|
||||
onDelete: () => void;
|
||||
|
|
@ -38,19 +29,9 @@
|
|||
class: className = '',
|
||||
message,
|
||||
mcpPrompt,
|
||||
isEditing,
|
||||
editedContent,
|
||||
editedExtras = [],
|
||||
editedUploadedFiles = [],
|
||||
siblingInfo = null,
|
||||
showDeleteDialog,
|
||||
deletionInfo,
|
||||
onCancelEdit,
|
||||
onSaveEdit,
|
||||
onSaveEditOnly,
|
||||
onEditedContentChange,
|
||||
onEditedExtrasChange,
|
||||
onEditedUploadedFilesChange,
|
||||
onCopy,
|
||||
onEdit,
|
||||
onDelete,
|
||||
|
|
@ -58,6 +39,9 @@
|
|||
onNavigateToSibling,
|
||||
onShowDeleteDialogChange
|
||||
}: Props = $props();
|
||||
|
||||
// Get edit context
|
||||
const editCtx = getMessageEditContext();
|
||||
</script>
|
||||
|
||||
<div
|
||||
|
|
@ -65,21 +49,8 @@
|
|||
class="group flex flex-col items-end gap-3 md:gap-2 {className}"
|
||||
role="group"
|
||||
>
|
||||
{#if isEditing}
|
||||
<ChatMessageEditForm
|
||||
{editedContent}
|
||||
{editedExtras}
|
||||
{editedUploadedFiles}
|
||||
originalContent={message.content}
|
||||
originalExtras={message.extra}
|
||||
showSaveOnlyOption={!!onSaveEditOnly}
|
||||
{onCancelEdit}
|
||||
{onSaveEdit}
|
||||
{onSaveEditOnly}
|
||||
{onEditedContentChange}
|
||||
{onEditedExtrasChange}
|
||||
{onEditedUploadedFilesChange}
|
||||
/>
|
||||
{#if editCtx.isEditing}
|
||||
<ChatMessageEditForm />
|
||||
{:else}
|
||||
<ChatMessageMcpPromptContent
|
||||
prompt={mcpPrompt}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
import { Card } from '$lib/components/ui/card';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { MarkdownContent } from '$lib/components/app';
|
||||
import { getMessageEditContext } from '$lib/contexts';
|
||||
import { INPUT_CLASSES } from '$lib/constants/css-classes';
|
||||
import { config } from '$lib/stores/settings.svelte';
|
||||
import { isIMEComposing } from '$lib/utils';
|
||||
import ChatMessageActions from './ChatMessageActions.svelte';
|
||||
import { MessageRole } from '$lib/enums';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
message: DatabaseMessage;
|
||||
isEditing: boolean;
|
||||
editedContent: string;
|
||||
siblingInfo?: ChatMessageSiblingInfo | null;
|
||||
showDeleteDialog: boolean;
|
||||
deletionInfo: {
|
||||
|
|
@ -21,10 +21,6 @@
|
|||
assistantMessages: number;
|
||||
messageTypes: string[];
|
||||
} | null;
|
||||
onCancelEdit: () => void;
|
||||
onSaveEdit: () => void;
|
||||
onEditKeydown: (event: KeyboardEvent) => void;
|
||||
onEditedContentChange: (content: string) => void;
|
||||
onCopy: () => void;
|
||||
onEdit: () => void;
|
||||
onDelete: () => void;
|
||||
|
|
@ -37,15 +33,9 @@
|
|||
let {
|
||||
class: className = '',
|
||||
message,
|
||||
isEditing,
|
||||
editedContent,
|
||||
siblingInfo = null,
|
||||
showDeleteDialog,
|
||||
deletionInfo,
|
||||
onCancelEdit,
|
||||
onSaveEdit,
|
||||
onEditKeydown,
|
||||
onEditedContentChange,
|
||||
onCopy,
|
||||
onEdit,
|
||||
onDelete,
|
||||
|
|
@ -55,10 +45,25 @@
|
|||
textareaElement = $bindable()
|
||||
}: Props = $props();
|
||||
|
||||
const editCtx = getMessageEditContext();
|
||||
|
||||
function handleEditKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter' && !event.shiftKey && !isIMEComposing(event)) {
|
||||
event.preventDefault();
|
||||
|
||||
editCtx.save();
|
||||
} else if (event.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
|
||||
editCtx.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
let isMultiline = $state(false);
|
||||
let messageElement: HTMLElement | undefined = $state();
|
||||
let isExpanded = $state(false);
|
||||
let contentHeight = $state(0);
|
||||
|
||||
const MAX_HEIGHT = 200; // pixels
|
||||
const currentConfig = config();
|
||||
|
||||
|
|
@ -98,24 +103,29 @@
|
|||
class="group flex flex-col items-end gap-3 md:gap-2 {className}"
|
||||
role="group"
|
||||
>
|
||||
{#if isEditing}
|
||||
{#if editCtx.isEditing}
|
||||
<div class="w-full max-w-[80%]">
|
||||
<textarea
|
||||
bind:this={textareaElement}
|
||||
bind:value={editedContent}
|
||||
value={editCtx.editedContent}
|
||||
class="min-h-[60px] w-full resize-none rounded-2xl px-3 py-2 text-sm {INPUT_CLASSES}"
|
||||
onkeydown={onEditKeydown}
|
||||
oninput={(e) => onEditedContentChange(e.currentTarget.value)}
|
||||
onkeydown={handleEditKeydown}
|
||||
oninput={(e) => editCtx.setContent(e.currentTarget.value)}
|
||||
placeholder="Edit system message..."
|
||||
></textarea>
|
||||
|
||||
<div class="mt-2 flex justify-end gap-2">
|
||||
<Button class="h-8 px-3" onclick={onCancelEdit} size="sm" variant="outline">
|
||||
<Button class="h-8 px-3" onclick={editCtx.cancel} size="sm" variant="outline">
|
||||
<X class="mr-1 h-3 w-3" />
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button class="h-8 px-3" onclick={onSaveEdit} disabled={!editedContent.trim()} size="sm">
|
||||
<Button
|
||||
class="h-8 px-3"
|
||||
onclick={editCtx.save}
|
||||
disabled={!editCtx.editedContent.trim()}
|
||||
size="sm"
|
||||
>
|
||||
<Check class="mr-1 h-3 w-3" />
|
||||
Save
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { Card } from '$lib/components/ui/card';
|
||||
import { ChatAttachmentsList, MarkdownContent } from '$lib/components/app';
|
||||
import { getMessageEditContext, getChatActionsContext } from '$lib/contexts';
|
||||
import { config } from '$lib/stores/settings.svelte';
|
||||
import ChatMessageActions from './ChatMessageActions.svelte';
|
||||
import ChatMessageEditForm from './ChatMessageEditForm.svelte';
|
||||
|
|
@ -9,56 +10,39 @@
|
|||
interface Props {
|
||||
class?: string;
|
||||
message: DatabaseMessage;
|
||||
isEditing: boolean;
|
||||
editedContent: string;
|
||||
editedExtras?: DatabaseMessageExtra[];
|
||||
editedUploadedFiles?: ChatUploadedFile[];
|
||||
siblingInfo?: ChatMessageSiblingInfo | null;
|
||||
showDeleteDialog: boolean;
|
||||
deletionInfo: {
|
||||
totalCount: number;
|
||||
userMessages: number;
|
||||
assistantMessages: number;
|
||||
messageTypes: string[];
|
||||
} | null;
|
||||
onCancelEdit: () => void;
|
||||
onSaveEdit: () => void;
|
||||
onSaveEditOnly?: () => void;
|
||||
onEditedContentChange: (content: string) => void;
|
||||
onEditedExtrasChange?: (extras: DatabaseMessageExtra[]) => void;
|
||||
onEditedUploadedFilesChange?: (files: ChatUploadedFile[]) => void;
|
||||
onCopy: () => void;
|
||||
showDeleteDialog: boolean;
|
||||
onEdit: () => void;
|
||||
onDelete: () => void;
|
||||
onConfirmDelete: () => void;
|
||||
onNavigateToSibling?: (siblingId: string) => void;
|
||||
onShowDeleteDialogChange: (show: boolean) => void;
|
||||
onNavigateToSibling?: (siblingId: string) => void;
|
||||
onCopy: () => void;
|
||||
}
|
||||
|
||||
let {
|
||||
class: className = '',
|
||||
message,
|
||||
isEditing,
|
||||
editedContent,
|
||||
editedExtras = [],
|
||||
editedUploadedFiles = [],
|
||||
siblingInfo = null,
|
||||
showDeleteDialog,
|
||||
deletionInfo,
|
||||
onCancelEdit,
|
||||
onSaveEdit,
|
||||
onSaveEditOnly,
|
||||
onEditedContentChange,
|
||||
onEditedExtrasChange,
|
||||
onEditedUploadedFilesChange,
|
||||
onCopy,
|
||||
showDeleteDialog,
|
||||
onEdit,
|
||||
onDelete,
|
||||
onConfirmDelete,
|
||||
onShowDeleteDialogChange,
|
||||
onNavigateToSibling,
|
||||
onShowDeleteDialogChange
|
||||
onCopy
|
||||
}: Props = $props();
|
||||
|
||||
// Get contexts
|
||||
const editCtx = getMessageEditContext();
|
||||
|
||||
let isMultiline = $state(false);
|
||||
let messageElement: HTMLElement | undefined = $state();
|
||||
const currentConfig = config();
|
||||
|
|
@ -93,21 +77,8 @@
|
|||
class="group flex flex-col items-end gap-3 md:gap-2 {className}"
|
||||
role="group"
|
||||
>
|
||||
{#if isEditing}
|
||||
<ChatMessageEditForm
|
||||
{editedContent}
|
||||
{editedExtras}
|
||||
{editedUploadedFiles}
|
||||
originalContent={message.content}
|
||||
originalExtras={message.extra}
|
||||
showSaveOnlyOption={!!onSaveEditOnly}
|
||||
{onCancelEdit}
|
||||
{onSaveEdit}
|
||||
{onSaveEditOnly}
|
||||
{onEditedContentChange}
|
||||
{onEditedExtrasChange}
|
||||
{onEditedUploadedFilesChange}
|
||||
/>
|
||||
{#if editCtx.isEditing}
|
||||
<ChatMessageEditForm />
|
||||
{:else}
|
||||
{#if message.extra && message.extra.length > 0}
|
||||
<div class="mb-2 max-w-[80%]">
|
||||
|
|
|
|||
Loading…
Reference in New Issue