Add inline previews for prompt attachments
This commit is contained in:
@@ -720,8 +720,24 @@ export default function PromptInput(props: PromptInputProps) {
|
||||
const filename = file.name
|
||||
const mime = file.type || "text/plain"
|
||||
|
||||
const attachment = createFileAttachment(path, filename, mime, undefined, props.instanceFolder)
|
||||
addAttachment(props.instanceId, props.sessionId, attachment)
|
||||
const createAndStoreAttachment = (previewUrl?: string) => {
|
||||
const attachment = createFileAttachment(path, filename, mime, undefined, props.instanceFolder)
|
||||
if (previewUrl && mime.startsWith("image/")) {
|
||||
attachment.url = previewUrl
|
||||
}
|
||||
addAttachment(props.instanceId, props.sessionId, attachment)
|
||||
}
|
||||
|
||||
if (mime.startsWith("image/") && typeof FileReader !== "undefined") {
|
||||
const reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
const result = typeof reader.result === "string" ? reader.result : undefined
|
||||
createAndStoreAttachment(result)
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
} else {
|
||||
createAndStoreAttachment()
|
||||
}
|
||||
}
|
||||
|
||||
textareaRef?.focus()
|
||||
@@ -772,7 +788,7 @@ export default function PromptInput(props: PromptInputProps) {
|
||||
{(attachment) => {
|
||||
const isImage = attachment.mediaType.startsWith("image/")
|
||||
return (
|
||||
<div class="attachment-chip">
|
||||
<div class={`attachment-chip ${isImage ? "attachment-chip-image" : ""}`}>
|
||||
<Show
|
||||
when={isImage}
|
||||
fallback={
|
||||
@@ -831,6 +847,11 @@ export default function PromptInput(props: PromptInputProps) {
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<Show when={isImage}>
|
||||
<div class="attachment-chip-preview">
|
||||
<img src={attachment.url} alt={attachment.filename} />
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
|
||||
@@ -103,6 +103,35 @@
|
||||
ring-color: var(--attachment-chip-ring);
|
||||
}
|
||||
|
||||
.attachment-chip-image {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.attachment-chip-preview {
|
||||
display: none;
|
||||
position: absolute;
|
||||
bottom: calc(100% + 6px);
|
||||
left: 0;
|
||||
padding: 8px;
|
||||
background-color: var(--surface-base);
|
||||
border: 1px solid var(--border-base);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 16px 40px rgba(15, 23, 42, 0.25);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.attachment-chip-preview img {
|
||||
display: block;
|
||||
max-width: 320px;
|
||||
max-height: 320px;
|
||||
border-radius: 8px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.attachment-chip-image:hover .attachment-chip-preview {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.attachment-remove {
|
||||
@apply ml-0.5 flex h-4 w-4 items-center justify-center rounded transition-colors;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user