diff options
| author | Adam Soltys <[email protected]> | 2026-10-10 10:28:12 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-10 10:28:12 -0700 |
| commit | e253cbd16d502cd382a6f7632d2851db4ae1a6ae (patch) | |
| tree | bfb8caefb7dc4853e334e955fd915b38e2432274 /src | |
| parent | 0262af2885831f67b7025fff84d4987fed4857c6 (diff) | |
| download | coinosv3-e253cbd16d502cd382a6f7632d2851db4ae1a6ae.tar.gz coinosv3-e253cbd16d502cd382a6f7632d2851db4ae1a6ae.zip | |
Notifications: a custom-emoji reaction shows its picture. djmeistro's :peepoClap: read as the bare text "reacted :peepoClap:" — the notification row kept the reaction's content but not its NIP-30 emoji tag (and cut shortcodes at 12 characters). Rows now keep the tag's picture and the whole :name:, draw it like the reaction chips do, and a row saved the old way gets its picture when the relay hands the reaction again. tools/notif-custom-emoji-test.js.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Vps2H27rhbG9ZqseGfMrc3
Diffstat (limited to 'src')
| -rw-r--r-- | src/features/messages.js | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 0a14b9c..cedd8db 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -13706,8 +13706,11 @@ export function messagesFeature(ctx) { if (my.includes(ev.pubkey)) return null; if (ev.kind === 7) { if (!lastE) return null; - const emoji = !ev.content || ev.content === '+' ? '\u2764\ufe0f' : ev.content.slice(0, 12); - return { id: ev.id, what: 'react', actor: ev.pubkey, target: lastE, hint, emoji, ts: ev.created_at }; + // a :shortcode: keeps its whole name and the picture its NIP-30 tag names + const code = shortcodeOf(ev.content || ''); + const tag = code && (ev.tags || []).find((x) => x[0] === 'emoji' && x[1] === code && /^https?:\/\//.test(x[2] || '')); + const emoji = !ev.content || ev.content === '+' ? '\u2764\ufe0f' : code ? ev.content.slice(0, 64) : ev.content.slice(0, 12); + return { id: ev.id, what: 'react', actor: ev.pubkey, target: lastE, hint, emoji, emojiUrl: tag ? tag[2] : undefined, ts: ev.created_at }; } if (ev.kind === 6) return lastE ? { id: ev.id, what: 'boost', actor: ev.pubkey, target: lastE, hint, ts: ev.created_at } : null; if (ev.kind === COMMENT) { @@ -13727,9 +13730,16 @@ export function messagesFeature(ctx) { const c = notifNow(); const known = new Set(c.items.map((x) => x.id)); for (const ev of evs) noteForSpam(ev); - const add = evs.map((ev) => ((ev.kind === 1 || ev.kind === COMMENT) && hidden(ev) ? null : notifItem(ev))) - .filter((x) => x && !hiddenPk(x.actor) && !known.has(x.id) && known.add(x.id)); - if (!add.length) return false; + const items = evs.map((ev) => ((ev.kind === 1 || ev.kind === COMMENT) && hidden(ev) ? null : notifItem(ev))); + // a custom-emoji reaction saved before rows kept its picture gets it now + let healed = false; + for (const x of items) { + if (!x || !x.emojiUrl || !known.has(x.id)) continue; + const old = c.items.find((y) => y.id === x.id); + if (old && !old.emojiUrl) { old.emojiUrl = x.emojiUrl; old.emoji = x.emoji; healed = true; } + } + const add = items.filter((x) => x && !hiddenPk(x.actor) && !known.has(x.id) && known.add(x.id)); + if (!add.length) { if (healed) persistNotifs(); return healed; } warmNotifFaces(add); // One zap, two receipts: a coinos zap publishes its own (9737) beside the // LNURL server's (9735). The same person, post and amount within a few @@ -13822,7 +13832,13 @@ export function messagesFeature(ctx) { } function notifLabel(x) { if (x.what === 'zap') return t('alertZap', { sats: fmtSats(x.sats) + ' sats' }); - if (x.what === 'react') return t('alertReact', { emoji: x.emoji }); + if (x.what === 'react') { + const code = shortcodeOf(x.emoji); + const url = code && (x.emojiUrl || emojiUrl(code)); + if (!url) return t('alertReact', { emoji: x.emoji }); + const [a, b = ''] = t('alertReact', { emoji: '\u0000' }).split('\u0000'); + return h('span', {}, a, reactImg(code, url), b); + } if (x.what === 'boost') return t('alertBoost'); if (x.what === 'reply') return t('alertReply'); return t('alertMention'); |
