aboutsummaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-03-06 23:48:37 -0800
committerAdam Soltys <[email protected]>2026-03-06 23:48:37 -0800
commita664eda6159fe98f8f93f368e94c7559a7aad0ad (patch)
tree00c24506e24d16bdd419529f14c0922c0cd71f5f /src/components
parent797d30c172fbec5e98e3a8d77d24f8e708aaa0bd (diff)
downloadcoinos-ui-a664eda6159fe98f8f93f368e94c7559a7aad0ad.tar.gz
coinos-ui-a664eda6159fe98f8f93f368e94c7559a7aad0ad.zip
render blossom images using MIME type from imeta tags
URLs without file extensions (like blossom hashes) are now detected as images when the imeta tag includes m image/*. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Diffstat (limited to 'src/components')
-rw-r--r--src/components/ChatMessage.svelte20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/components/ChatMessage.svelte b/src/components/ChatMessage.svelte
index dbdde5a0..91012f46 100644
--- a/src/components/ChatMessage.svelte
+++ b/src/components/ChatMessage.svelte
@@ -3,14 +3,24 @@
let { content, tags = [] }: { content: string; tags?: any[] } = $props();
- // Extract image URLs from imeta tags not already in content
- let imetaUrls = $derived(
+ // Parse imeta tags for URLs and MIME types
+ let imeta = $derived(
tags
.filter((t) => t[0] === "imeta")
- .map((t) => t.find((v) => v.startsWith("url "))?.slice(4))
- .filter((url): url is string => !!url && !content.includes(url)),
+ .map((t) => {
+ const url = t.find((v) => v.startsWith("url "))?.slice(4);
+ const mime = t.find((v) => v.startsWith("m "))?.slice(2) || "";
+ return { url, mime };
+ })
+ .filter((m): m is { url: string; mime: string } => !!m.url),
);
+ // URLs from imeta not already in content
+ let imetaUrls = $derived(imeta.filter((m) => !content.includes(m.url!)).map((m) => m.url));
+
+ // Set of URLs that imeta says are images (by MIME type or blossom-style hash URLs)
+ let imetaImageUrls = $derived(new Set(imeta.filter((m) => m.mime.startsWith("image/")).map((m) => m.url)));
+
let parts = $derived(parseContent({ content: [content, ...imetaUrls].join("\n"), tags }));
const truncUrl = (url: string) => {
@@ -36,7 +46,7 @@
{:else if type === "newline"}
<br />
{:else if type === "link"}
- {#if isImage(value.url)}
+ {#if isImage(value.url) || imetaImageUrls.has(value.url)}
<a href={value.url} target="_blank" rel="noopener noreferrer">
<img src={value.url} alt="" class="chat-img" />
</a>