Add visual attachment chips and fix empty query file search

This commit is contained in:
Shantur Rathore
2025-10-24 01:00:01 +01:00
parent 79fe1c4b7b
commit 4d468e278f
2 changed files with 54 additions and 15 deletions

View File

@@ -94,7 +94,7 @@ const FilePicker: Component<FilePickerProps> = (props) => {
isGitFile: false, isGitFile: false,
})) }))
const filteredGitFiles = searchQuery const filteredGitFiles = searchQuery.trim()
? gitFiles.filter((f) => f.path.toLowerCase().includes(searchQuery.toLowerCase())) ? gitFiles.filter((f) => f.path.toLowerCase().includes(searchQuery.toLowerCase()))
: gitFiles : gitFiles
const allFiles = [...filteredGitFiles, ...searchFiles] const allFiles = [...filteredGitFiles, ...searchFiles]

View File

@@ -1,9 +1,9 @@
import { createSignal, Show, onMount } from "solid-js" import { createSignal, Show, onMount, For } from "solid-js"
import AgentSelector from "./agent-selector" import AgentSelector from "./agent-selector"
import ModelSelector from "./model-selector" import ModelSelector from "./model-selector"
import FilePicker from "./file-picker" import FilePicker from "./file-picker"
import { addToHistory, getHistory } from "../stores/message-history" import { addToHistory, getHistory } from "../stores/message-history"
import { getAttachments, addAttachment, clearAttachments } from "../stores/attachments" import { getAttachments, addAttachment, clearAttachments, removeAttachment } from "../stores/attachments"
import { createFileAttachment } from "../types/attachment" import { createFileAttachment } from "../types/attachment"
import type { Attachment } from "../types/attachment" import type { Attachment } from "../types/attachment"
import Kbd from "./kbd" import Kbd from "./kbd"
@@ -38,6 +38,24 @@ export default function PromptInput(props: PromptInputProps) {
const attachments = () => getAttachments(props.instanceId, props.sessionId) const attachments = () => getAttachments(props.instanceId, props.sessionId)
function handleRemoveAttachment(attachmentId: string) {
removeAttachment(props.instanceId, props.sessionId, attachmentId)
const currentAttachments = attachments()
const attachment = currentAttachments.find((a) => a.id === attachmentId)
if (attachment && attachment.source.type === "file") {
const filename = attachment.filename
const currentPrompt = prompt()
const newPrompt = currentPrompt.replace(`@${filename}`, "").replace(/\s+/g, " ").trim()
setPrompt(newPrompt)
if (textareaRef) {
textareaRef.style.height = "auto"
textareaRef.style.height = Math.min(textareaRef.scrollHeight, 200) + "px"
}
}
}
onMount(async () => { onMount(async () => {
const loaded = await getHistory(props.instanceFolder) const loaded = await getHistory(props.instanceFolder)
setHistory(loaded) setHistory(loaded)
@@ -269,18 +287,39 @@ export default function PromptInput(props: PromptInputProps) {
/> />
</Show> </Show>
<textarea <div class="flex flex-1 flex-col gap-2">
ref={textareaRef} <Show when={attachments().length > 0}>
class="prompt-input" <div class="flex flex-wrap gap-1">
placeholder="Type your message, @file, or /command..." <For each={attachments()}>
value={prompt()} {(attachment) => (
onInput={handleInput} <div class="inline-flex items-center gap-1 rounded bg-blue-500 px-2 py-0.5 text-xs text-white">
onKeyDown={handleKeyDown} <span class="font-mono">@{attachment.filename}</span>
onFocus={() => setIsFocused(true)} <button
onBlur={() => setIsFocused(false)} onClick={() => handleRemoveAttachment(attachment.id)}
disabled={sending() || props.disabled} class="flex h-3.5 w-3.5 items-center justify-center rounded text-sm hover:bg-blue-600"
rows={1} aria-label="Remove attachment"
/> >
×
</button>
</div>
)}
</For>
</div>
</Show>
<textarea
ref={textareaRef}
class="prompt-input"
placeholder="Type your message, @file, or /command..."
value={prompt()}
onInput={handleInput}
onKeyDown={handleKeyDown}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
disabled={sending() || props.disabled}
rows={1}
/>
</div>
<button class="send-button" onClick={handleSend} disabled={!canSend()} aria-label="Send message"> <button class="send-button" onClick={handleSend} disabled={!canSend()} aria-label="Send message">
<Show when={sending()} fallback={<span class="send-icon"></span>}> <Show when={sending()} fallback={<span class="send-icon"></span>}>
<span class="spinner-small" /> <span class="spinner-small" />