diff options
| author | Adam Soltys <[email protected]> | 2026-09-02 19:03:19 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-02 19:03:19 -0700 |
| commit | a2069d6ad1423b1788428b93b6bbb4531c551572 (patch) | |
| tree | 5000f9a25b508e3febaea6921ba85c679f35f213 /src/features | |
| parent | 15d8c6f3dab19c7f51ad00b2fc377bf6eaa7f819 (diff) | |
| download | coinosv3-a2069d6ad1423b1788428b93b6bbb4531c551572.tar.gz coinosv3-a2069d6ad1423b1788428b93b6bbb4531c551572.zip | |
nevent and nprofile references come alive: nprofile mentions render as clickable @names beside their npub siblings, and note/nevent references become 'view note' links that fetch the event by id (relay hints first) and open its thread right in the app — the dim truncated stubs survive only for what genuinely can't resolve
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/messages.js | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index ca56335..1daa5bc 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -14,7 +14,7 @@ import { subscribeOn, publishOn, queryOn, fetchNostrProfile, fetchInboxRelays, - npubOf, parseNostrPubkey, generateSecretKey, getPublicKey, finalizeEvent, nip44, + npubOf, parseNostrPubkey, parseNostrRef, generateSecretKey, getPublicKey, finalizeEvent, nip44, PROFILE_RELAYS, } from '../nostr.js'; import { @@ -1517,10 +1517,18 @@ export function messagesFeature(ctx) { out.push(h('a', { href: part, target: '_blank', rel: 'noopener noreferrer' }, part.length > 64 ? part.slice(0, 61) + '…' : part)); } - } else if (/^nostr:npub1/i.test(part)) { - const mpk = parseNostrPubkey(part.slice(6)); - if (mpk) out.push(h('a', { href: '#', onClick: (e) => { e.preventDefault(); openProfile(mpk); } }, '@' + displayName(mpk))); - else out.push(part); + } else if (/^nostr:(npub|nprofile)1/i.test(part)) { + const ref = parseNostrRef(part.slice(6)); + if (ref && ref.type === 'pubkey') out.push(h('a', { href: '#', onClick: (e) => { e.preventDefault(); openProfile(ref.pk); } }, '@' + displayName(ref.pk))); + else out.push(h('span', { class: 'faint' }, part.slice(6, 18) + '…')); + } else if (/^nostr:(note|nevent)1/i.test(part)) { + // a referenced note opens right here as a thread — fetched by id + // (with the reference's relay hints) when tapped + const ref = parseNostrRef(part.slice(6)); + if (ref && ref.type === 'event') out.push(h('a', { + href: '#', onClick: (e) => { e.preventDefault(); openNoteRef(ref); }, + }, t('noteRefLink'))); + else out.push(h('span', { class: 'faint' }, part.slice(6, 18) + '…')); } else if (/^nostr:/i.test(part)) { out.push(h('span', { class: 'faint' }, part.slice(6, 18) + '…')); } else out.push(part); @@ -1637,6 +1645,17 @@ export function messagesFeature(ctx) { ui.noteThread = { rootId: rootIdOf(ev), focusId: ev.id, seed: ev }; render(); } + // A nostr:nevent / nostr:note reference: the thread loader needs the real + // event (its tags name the root, its author names the home relays), so + // fetch it by id — the reference's relay hints first — then open. + async function openNoteRef(ref) { + toast(t('noteRefLoading')); + const relays = [...new Set([...(ref.relays || []), ...NOTE_RELAYS])]; + const evs = await queryOn(relays, { ids: [ref.id] }, 4000).catch(() => []); + const ev = (evs || [])[0]; + if (ev) openNoteThread(ev); + else toast(t('noteRefNotFound')); + } // Publish a kind-1 reply to the focused note (NIP-10 markers), addressed to // the conversation's own relays plus ours, and shown optimistically. async function publishReply(c, s, text) { |
