feat(events): real-time favoriting + live like count + post-purchase refresh #111

Merged
padreug merged 3 commits from feat/events-realtime into dev 2026-06-17 08:36:47 +00:00
Owner

Real-time / subscription bucket split out of #105.

  • Live like count on the favorite heart: useEventLikes keeps one batched #a subscription over visible events' coordinates; a like (NIP-51 kind-10003 bookmark — the same action the heart performs) published by anyone is pushed live and the count ticks up for everyone. Verified end-to-end against a relay (count 2→3 with no reload). The heart also pops on a live increment.
  • Optimistic favoriting: the heart fills instantly with rollback on failure, instead of waiting ~1s on the remote signer + relay round-trip.
  • Post-purchase refresh: refresh the shared owned-tickets state after a successful purchase so the new ticket appears in the feed/calendar "My tickets" filter without a reload.

Caveat (inherent to counting replaceable bookmark lists): another user's un-like only reflects on next load — a list that drops the coord stops matching #a, so the removal isn't pushed. Counts are correct on fresh load; the user's own un-like decrements instantly.

🤖 Generated with Claude Code

Real-time / subscription bucket split out of #105. - **Live like count on the favorite heart:** `useEventLikes` keeps one batched `#a` subscription over visible events' coordinates; a like (NIP-51 kind-10003 bookmark — the same action the heart performs) published by anyone is pushed live and the count ticks up for everyone. Verified end-to-end against a relay (count 2→3 with no reload). The heart also pops on a live increment. - **Optimistic favoriting:** the heart fills instantly with rollback on failure, instead of waiting ~1s on the remote signer + relay round-trip. - **Post-purchase refresh:** refresh the shared owned-tickets state after a successful purchase so the new ticket appears in the feed/calendar "My tickets" filter without a reload. Caveat (inherent to counting replaceable bookmark lists): another user's un-like only reflects on next load — a list that drops the coord stops matching `#a`, so the removal isn't pushed. Counts are correct on fresh load; the user's own un-like decrements instantly. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The heart took ~1s to fill because toggleBookmark awaited the remote
LNbits signer + relay publish before updating state. Flip local state
optimistically so the heart responds on tap, then sign/publish in the
background and roll back (with an error toast) if it fails. Add a brief
scale pop on the heart when a favorite is added for tactile feedback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After a successful ticket purchase, the feed/calendar "My tickets" filter
and EventCard owned badges didn't update until a full page reload — the
shared useOwnedTickets singleton was never refreshed. Its own docs note a
successful purchase should call refresh(); wire that in at the payment-
confirmed point in useTicketPurchase so every surface reflects the new
ticket immediately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Display how many people have favorited (liked) an event next to its
heart, updating in real time. A like == the event appearing in someone's
NIP-51 bookmark list (kind 10003) — the same action the heart performs.

New useEventLikes composable keeps ONE batched subscription over every
mounted heart's event coordinate (filtered by #a). It stays open after
EOSE, so a like published by anyone is pushed live and the count ticks
up for everyone — verified end-to-end against a relay (a like from a
fresh key bumped the shown count 2→3 with no reload). The heart also
pops on a live increment (gated past the initial historical-load
window), and the user's own like/un-like reflects instantly via the
optimistic heart state.

Caveat: an un-like by another user only reflects on next load — a
replaceable list that no longer contains the coord stops matching the #a
filter, so the removal isn't pushed. Counts are correct on fresh load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
padreug force-pushed feat/events-realtime from 373e52dd79 to b6d1626951 2026-06-17 08:36:30 +00:00 Compare
padreug deleted branch feat/events-realtime 2026-06-17 08:36:47 +00:00
Sign in to join this conversation.
No description provided.