From 1b608fb96061016c998aeec0ddfef3f5cd600345 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Jan 2026 19:27:04 +0000 Subject: [PATCH] refactor(editor): improve nostr preview display with kind icons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates the nostr event preview chips to show more meaningful information: Changes: - Add getKindIcon() helper function with 15+ kind mappings - Display format: kind-icon + author/id (e.g., "📄 a1b2c3d4") - For naddr: show kind icon + author pubkey (first 8 chars) - For nevent: show kind icon + author if available, else event ID - For note: show 📝 + event ID (first 8 chars) - For npub/nprofile: show 👤 + pubkey (first 8 chars) - Removed verbose type labels (NPUB, NEVENT, etc.) - Increased label max-width to 120px for better readability Kind icon mappings: - 👤 Profile (kind 0) - 📝 Note (kind 1) - 👥 Contacts (kind 3) - 🔁 Repost (kind 6) - ❤️ Reaction (kind 7) - ⚡ Zap (kind 9735) - 📄 Long-form (kind 30023) - 🎙️ Live event (kind 30311) - 📦 File metadata (kind 1063) - 📌 Addressable events (30000-39999) - 🔄 Replaceable events (10000-19999) Result: More compact, visually intuitive previews that immediately convey the content type and author without requiring event fetching. --- src/components/editor/MentionEditor.tsx | 77 +++++++++++++++---------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/src/components/editor/MentionEditor.tsx b/src/components/editor/MentionEditor.tsx index 1353bad..ebd96b7 100644 --- a/src/components/editor/MentionEditor.tsx +++ b/src/components/editor/MentionEditor.tsx @@ -337,43 +337,60 @@ const NostrEventPreview = Node.create({ "nostr-event-preview inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-primary/10 border border-primary/30 text-xs align-middle"; dom.contentEditable = "false"; - // Icon based on type + // Helper to get kind icon + const getKindIcon = (kind?: number): string => { + if (!kind) return "📝"; + if (kind === 0) return "👤"; // Profile + if (kind === 1) return "📝"; // Note + if (kind === 3) return "👥"; // Contacts + if (kind === 6) return "🔁"; // Repost + if (kind === 7) return "❤️"; // Reaction + if (kind === 9735) return "⚡"; // Zap + if (kind === 30023) return "📄"; // Long-form + if (kind === 30311) return "🎙️"; // Live event + if (kind === 1063) return "📦"; // File metadata + if (kind >= 30000 && kind < 40000) return "📌"; // Addressable + if (kind >= 10000 && kind < 20000) return "🔄"; // Replaceable + return "📝"; // Default + }; + + // Icon based on type and kind const icon = document.createElement("span"); icon.className = "text-primary flex-shrink-0"; - if (type === "npub" || type === "nprofile") { - icon.textContent = "👤"; - } else if (type === "note" || type === "nevent") { - icon.textContent = "📝"; - } else if (type === "naddr") { - icon.textContent = "📄"; - } else { - icon.textContent = "🔗"; - } - dom.appendChild(icon); - // Type label - const typeLabel = document.createElement("span"); - typeLabel.className = "text-primary font-mono font-medium"; - typeLabel.textContent = type.toUpperCase(); - dom.appendChild(typeLabel); + // Content label + const label = document.createElement("span"); + label.className = "text-muted-foreground truncate max-w-[120px]"; - // ID preview (truncated) - const idLabel = document.createElement("span"); - idLabel.className = "text-muted-foreground truncate max-w-[80px]"; if (type === "npub") { - idLabel.textContent = `${data.slice(0, 8)}...`; - } else if (type === "note") { - idLabel.textContent = `${data.slice(0, 8)}...`; - } else if (type === "nevent") { - idLabel.textContent = `${data.id.slice(0, 8)}...`; - } else if (type === "naddr") { - idLabel.textContent = data.identifier - ? `${data.identifier.slice(0, 12)}...` - : `kind:${data.kind}`; + // npub: 👤 pubkey + icon.textContent = "👤"; + label.textContent = data.slice(0, 8); } else if (type === "nprofile") { - idLabel.textContent = `${data.pubkey.slice(0, 8)}...`; + // nprofile: 👤 pubkey + icon.textContent = "👤"; + label.textContent = data.pubkey.slice(0, 8); + } else if (type === "note") { + // note: 📝 event-id + icon.textContent = "📝"; + label.textContent = data.slice(0, 8); + } else if (type === "nevent") { + // nevent: kind-icon event-id (or author if available) + icon.textContent = getKindIcon(data.kind); + // nevent can optionally include author + if (data.author) { + label.textContent = data.author.slice(0, 8); + } else { + label.textContent = data.id.slice(0, 8); + } + } else if (type === "naddr") { + // naddr: kind-icon author + icon.textContent = getKindIcon(data.kind); + label.textContent = data.pubkey.slice(0, 8); } - dom.appendChild(idLabel); + + dom.appendChild(icon); + dom.appendChild(label); return { dom }; };