Skip to content

Polish desktop Pulse and Home views#764

Open
wesbillman wants to merge 34 commits into
mainfrom
desktop-polish
Open

Polish desktop Pulse and Home views#764
wesbillman wants to merge 34 commits into
mainfrom
desktop-polish

Conversation

@wesbillman
Copy link
Copy Markdown
Collaborator

@wesbillman wesbillman commented May 27, 2026

Summary

Polish pass on the desktop Pulse and Home views. The throughline: the Pulse path was stripping note tags and never querying existing kind:7 reactions, which cascaded into reply-context, upvote-state, and count bugs. Fixing the data path then opened up a series of UX touch-ups (heart, follow controls, profile sidebar, Liked tab) that are all built on the same plumbing.

What changed

Pulse note state plumbing

  • UserNoteInfo now carries tags end-to-end (Rust → Tauri → TS). Required to read NIP-10 reply markers we already emit on write.
  • Reply parent context renders inline (avatar + display name + snippet). NIP-10 marked-reply, marked-root fallback, and legacy positional last-e all handled. getReplyParent priority: reply → unmarked → root.
  • New get_note_reactions Tauri command — {kinds:[7], #e: ids} over-fetch, {kinds:[5], authors:[…], #e: reaction_ids} deletion exclusion, last-e NIP-25 target resolution, server-side fold by (target, pubkey, emoji). Single source of truth: dropped local upvotedNoteIds set.
  • Heart icon + tabular-nums count. NIP-25 wire format stays "+" (heart is icon-only — keeps counts unified across clients).
  • "duplicate: reaction already exists" treated as a no-op success; real network failures still toast.

Profiles + Follow

  • Pulse author avatars + names wired through UserProfilePopover. Hover → popover, click → sidebar.
  • New shared useThreadPanelWidth hook extracted from ChannelPane; PulseScreen mounts ProfilePanelProvider + side panel slot.
  • Follow / Unfollow lifted out of NoteCard and into UserProfilePanel. Follow now works anywhere a profile opens (channel messages, Pulse, forum). Sonner toast on errors. useContactListQuery / useFollowMutation / useUnfollowMutation moved @/features/pulse/hooks@/features/profile/hooks.
  • Pulse profile DM action wired (onOpenDm → channel routing).

Tabs

  • Following ("People") now excludes self.
  • Agents falls back to managed agents when relay agent discovery is empty; honest empty state when neither has published kind:1.
  • Liked — new tab. New get_liked_notes Tauri command: kind:7 over-fetch (4×, cap 1000) → kind:5 deletion exclusion → last-e resolution → dedup → kind:1 fetch → sort by like recency. Cache invalidates on like/unlike for the current user.
  • Composer header shows current user's avatar + display name (mentionPubkeys includes self even though Following query doesn't).

Other polish

  • Active heart uses text-primary (matches MessageReactions accent).
  • Tooltips on icon-only Pulse action buttons.
  • MAX_NOTE_IDS = 200 cap + hex64 validation on commands taking id arrays.
  • Shared reaction-tag helpers between get_note_reactions and get_liked_notes (Summer's structural pass).

Tests

New unit tests + harness wiring:

  • TS node:test for getReplyParent (incl. NIP-10 marked-root + reply-then-root precedence), applyReactionState, isDuplicateReactionError. Added pnpm test script in desktop/package.json, wired through just desktop-test into lefthook (pre-commit + pre-push) and CI.
  • Rust #[cfg(test)] for shared social helpers (e_tag_id, last_event_tag_id, last_matching_event_tag_id, deleted_event_ids, reaction_emoji, validate_note_id). New just desktop-tauri-test recipe wired into pre-push and CI.

Verification

Green on every commit: pnpm typecheck, pnpm check, pnpm build, just desktop-tauri-check, just desktop-test (314 passed), just desktop-tauri-test (408 + 3 passed), pnpm test:e2e:smoke (114 passed), full pre-push (rust-tests, clippy, web-build, mobile, desktop-build).

Process

Multi-pass pipeline (Meeseeks brief → Morty → Beth → Morty fixes → Beth verify → Summer behavior-preserving pass) for the larger batches. Closing alignment audit against VISION.md / NOSTR.md was clean — verdict: ship. Two low-sev fixes + the test wiring landed in this PR rather than as followups.

Followups (post-merge)

  • build_note should emit ["e", root, "", "root"] for non-root replies (NIP-10 SHOULD). Out of scope this round (write-side change we didn't touch).

wesbillman added 30 commits May 27, 2026 15:33
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
The icon-only action buttons under each Pulse note (upvote, reply,
share, start DM) had no visible label, so users had to hover or guess
their function. Wrap each in the shared Tooltip primitive so the
existing aria-label text is also surfaced visually on hover/focus.

Follow/Unfollow already have text labels and are left as-is.

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
The active heart was using text-foreground, which was barely
distinguishable from a plain hover state. Switch to text-primary to
match the convention already used by MessageReactions for the
reacted-by-current-user state, so a liked note reads as 'liked' at a
glance and the visual language is consistent across the app.

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
@wesbillman wesbillman marked this pull request as ready for review May 28, 2026 05:00
@wesbillman wesbillman requested a review from a team as a code owner May 28, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant