From 7138fb4e230f2f186327c6ea2d86d4e74efba6e7 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Fri, 24 Oct 2025 01:19:00 +0100 Subject: [PATCH] Implement long paste handling with text attachments - Detect pastes >150 chars or >3 lines - Convert long pastes to text attachments - Show clipboard icon for text attachments - Display summary (e.g., 'pasted #1 (10 lines)') - Auto-increment paste counter - Reset counter on message send - Short pastes insert normally --- src/components/prompt-input.tsx | 61 ++++++++++++++++--- .../{todo => done}/015-keyboard-shortcuts.md | 0 2 files changed, 51 insertions(+), 10 deletions(-) rename tasks/{todo => done}/015-keyboard-shortcuts.md (100%) diff --git a/src/components/prompt-input.tsx b/src/components/prompt-input.tsx index dd7c7382..00cf165b 100644 --- a/src/components/prompt-input.tsx +++ b/src/components/prompt-input.tsx @@ -4,7 +4,7 @@ import ModelSelector from "./model-selector" import FilePicker from "./file-picker" import { addToHistory, getHistory } from "../stores/message-history" import { getAttachments, addAttachment, clearAttachments, removeAttachment } from "../stores/attachments" -import { createFileAttachment } from "../types/attachment" +import { createFileAttachment, createTextAttachment } from "../types/attachment" import type { Attachment } from "../types/attachment" import Kbd from "./kbd" import HintRow from "./hint-row" @@ -33,6 +33,7 @@ export default function PromptInput(props: PromptInputProps) { const [atPosition, setAtPosition] = createSignal(null) const [isDragging, setIsDragging] = createSignal(false) const [ignoredAtPositions, setIgnoredAtPositions] = createSignal>(new Set()) + const [pasteCount, setPasteCount] = createSignal(0) let textareaRef: HTMLTextAreaElement | undefined let containerRef: HTMLDivElement | undefined @@ -56,6 +57,30 @@ export default function PromptInput(props: PromptInputProps) { } } + function handlePaste(e: ClipboardEvent) { + const pastedText = e.clipboardData?.getData("text/plain") + if (!pastedText) return + + const lineCount = pastedText.split("\n").length + const charCount = pastedText.length + + const isLongPaste = charCount > 150 || lineCount > 3 + + if (isLongPaste) { + e.preventDefault() + + const count = pasteCount() + 1 + setPasteCount(count) + + const summary = lineCount > 1 ? `${lineCount} lines` : `${charCount} chars` + const display = `pasted #${count} (${summary})` + const filename = `paste-${count}.txt` + + const attachment = createTextAttachment(pastedText, display, filename) + addAttachment(props.instanceId, props.sessionId, attachment) + } + } + onMount(async () => { const loaded = await getHistory(props.instanceFolder) setHistory(loaded) @@ -121,6 +146,7 @@ export default function PromptInput(props: PromptInputProps) { setPrompt("") clearAttachments(props.instanceId, props.sessionId) setIgnoredAtPositions(new Set()) + setPasteCount(0) if (textareaRef) { textareaRef.style.height = "auto" @@ -293,15 +319,29 @@ export default function PromptInput(props: PromptInputProps) { {(attachment) => (
- - - - {attachment.filename} + + + + } + > + + + + + {attachment.source.type === "text" ? attachment.display : attachment.filename}