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 filename = file.name
|
||||||
const mime = file.type || "text/plain"
|
const mime = file.type || "text/plain"
|
||||||
|
|
||||||
const attachment = createFileAttachment(path, filename, mime, undefined, props.instanceFolder)
|
const createAndStoreAttachment = (previewUrl?: string) => {
|
||||||
addAttachment(props.instanceId, props.sessionId, attachment)
|
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()
|
textareaRef?.focus()
|
||||||
@@ -772,7 +788,7 @@ export default function PromptInput(props: PromptInputProps) {
|
|||||||
{(attachment) => {
|
{(attachment) => {
|
||||||
const isImage = attachment.mediaType.startsWith("image/")
|
const isImage = attachment.mediaType.startsWith("image/")
|
||||||
return (
|
return (
|
||||||
<div class="attachment-chip">
|
<div class={`attachment-chip ${isImage ? "attachment-chip-image" : ""}`}>
|
||||||
<Show
|
<Show
|
||||||
when={isImage}
|
when={isImage}
|
||||||
fallback={
|
fallback={
|
||||||
@@ -831,6 +847,11 @@ export default function PromptInput(props: PromptInputProps) {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<Show when={isImage}>
|
||||||
|
<div class="attachment-chip-preview">
|
||||||
|
<img src={attachment.url} alt={attachment.filename} />
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -103,6 +103,35 @@
|
|||||||
ring-color: var(--attachment-chip-ring);
|
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 {
|
.attachment-remove {
|
||||||
@apply ml-0.5 flex h-4 w-4 items-center justify-center rounded transition-colors;
|
@apply ml-0.5 flex h-4 w-4 items-center justify-center rounded transition-colors;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user