diff options
| author | Adam Soltys <[email protected]> | 2026-10-18 23:46:18 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-18 23:46:18 -0700 |
| commit | aa3fecd4f0dc39550c6ad44a19736f820201d0a3 (patch) | |
| tree | fac2819d695f881fbeb73264907445aed1e3e596 /src/live.js | |
| parent | 1f0b1cd2af2c2391d6706f6194bdb65c85f14ca6 (diff) | |
| download | coinosv3-aa3fecd4f0dc39550c6ad44a19736f820201d0a3.tar.gz coinosv3-aa3fecd4f0dc39550c6ad44a19736f820201d0a3.zip | |
A stream's chat is the app's chat: each comment is a bubble like a DM's or a group's — tap for the emoji row, reply, zap or copy; reactions (kind 7, tagged with the stream and the comment, one per person, deletable) and zap totals show on the comment for every viewer; the zap goes to the commenter, for that comment, on that stream. The composer is the one the other chats use (drafts kept per stream). A reaction no relay took is taken back. (Begun by Codex; finished here.)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013ZDf1cyCQLkfjftYhymZAg
Diffstat (limited to 'src/live.js')
| -rw-r--r-- | src/live.js | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/live.js b/src/live.js index da18f19..d31c548 100644 --- a/src/live.js +++ b/src/live.js @@ -80,3 +80,22 @@ export function zapLine(ev, decode) { const zapAddrs = new Map(); export const setZapAddr = (eventId, addr) => { if (eventId && addr) zapAddrs.set(eventId, addr); }; export const zapAddrOf = (eventId) => (eventId && zapAddrs.get(eventId)) || null; + +// One current reaction per person/message, independent of relay arrival order. +// A deletion only removes reactions signed by its own author. +export function liveReactions(events) { + const deleted = new Set(); + for (const ev of events) if (ev.kind === 5) + for (const tag of ev.tags || []) if (tag[0] === 'e') deleted.add(ev.pubkey + ':' + tag[1]); + const out = new Map(); + for (const ev of events) { + if (ev.kind !== 7 || deleted.has(ev.pubkey + ':' + ev.id)) continue; + const target = (ev.tags || []).filter(t => t[0] === 'e').at(-1)?.[1]; + if (!target) continue; + const by = out.get(target) || new Map(); + const old = by.get(ev.pubkey); + if (!old || ev.created_at > old.created_at || (ev.created_at === old.created_at && ev.id > old.id)) by.set(ev.pubkey, ev); + out.set(target, by); + } + return out; +} |
