From b9987703de8b3ca89f93dbd9995412c9f47f7de2 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 4 Sep 2026 15:25:06 -0700 Subject: The tap-a-bubble action sheet works in DMs too: reactions + Reply + Copy (no Delete — a gift-wrapped DM can't be retracted from the peer's relays). DM reactions ride the kind-7-in-a-gift-wrap shape 0xchat uses (makeDMReaction in dm.js), sent to the peer and echoed to our own inbox so other devices fold them in; inbound kind-7 rumors land in dmReacts keyed by the reacted message's id — no thread lookup, so a reaction arriving before its message still sticks. Replies e-tag the quoted kind-14 (makeDMRumor grew extraTags) and render the same accent-bar quote as community chat; the composer gets the same replying-to bar. Chips are joinable and your own reaction is highlighted/replaceable, all optimistic with rollback. Round-trip verified: reply and reaction rumors wrap/unwrap with tags intact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz --- src/dm.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'src/dm.js') diff --git a/src/dm.js b/src/dm.js index caf6fbf..000e63c 100644 --- a/src/dm.js +++ b/src/dm.js @@ -57,12 +57,27 @@ export async function wrapDM(skOrSigner, receiverPk, rumor, extraTags = []) { // The kind 14 rumor alone, id included — synchronous, so a sender can put // the message on screen before any signing or encryption has run. Wrapping // the same rumor later yields the same id, so the sent-copy echo dedupes. -export function makeDMRumor(senderPk, peerPk, text) { +// extraTags: e.g. [['e', ]] marks a reply to another message. +export function makeDMRumor(senderPk, peerPk, text, extraTags = []) { const rumor = { kind: 14, pubkey: senderPk, content: text, - tags: [['p', peerPk]], + tags: [['p', peerPk], ...extraTags], + created_at: now(), + }; + rumor.id = getEventHash(rumor); + return rumor; +} + +// A reaction to a DM: a kind 7 rumor riding the same gift-wrap envelope +// (the shape 0xchat and friends use), e-tagging the reacted message. +export function makeDMReaction(senderPk, peerPk, targetId, emoji) { + const rumor = { + kind: 7, + pubkey: senderPk, + content: emoji, + tags: [['p', peerPk], ['e', targetId]], created_at: now(), }; rumor.id = getEventHash(rumor); -- cgit v1.2.3