Commit Graph

474 Commits

Author SHA1 Message Date
Alejandro Gómez
48ce35cbea feat: nip-5a nsites 2026-03-27 14:27:28 +01:00
Alejandro Gómez
4a501634c5 chore: sync NIPs 2026-03-26 09:58:07 +01:00
Alejandro Gómez
5d22403235 ai: sync-nips command 2026-03-26 09:22:32 +01:00
Alejandro Gómez
b14dce2d55 fix: center spellbook dropdown 2026-03-25 11:23:35 +01:00
Alejandro Gómez
9ded99420f feat: favorite spells 2026-03-24 17:37:20 +01:00
Alejandro Gómez
5ff9bbd5c2 fix: use aggregator relays as NIP-65 fallback and show accurate per-relay counts
- Use AGGREGATOR_RELAYS as fallback for follows without kind:10002,
  not the user's personal relays. Personal inbox/write relays were
  being assigned as outbox for hundreds of unknown follows, inflating
  counts and sending unnecessary queries to niche relays.
- Per-relay REQ badges now show assigned count (from reasoning) as
  the primary number, with unassigned users shown dimmed as +N.
  Tooltips show the full breakdown.
- Switch to useStableRelayFilterMap for structural comparison.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:49:46 +01:00
Alejandro Gómez
b25c2db89d feat: add useStableRelayFilterMap with structural filter comparison
Stabilizes relay filter map references using isFilterEqual per relay
instead of JSON.stringify. Avoids serialization overhead for large
filter maps with many relays and pubkeys.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:49:39 +01:00
Alejandro Gómez
0851cb03e9 perf: reduce Map allocations and subscription churn in REQ timeline hook
- Skip duplicate events in setEventsMap (return prev if event.id exists)
- Only create new relayStates Map on actual state transitions (waiting→receiving),
  not on every event — counter increments applied in-place
- Don't add unknown relays to the state map (skip defensive init)
- Cap streaming eventsMap at 2000 with 25% batch eviction of oldest events
- Decouple relay filter map from subscription lifecycle: store in ref,
  only tear down subscriptions when the relay SET changes (not filter content)
- Use useStableRelayFilterMap for structural comparison instead of JSON.stringify

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:49:33 +01:00
Alejandro Gómez
62785fa336 feat: add inbox (#p) chunking to relay filter splitting and clean up logging
Extend relay filter chunking to route #p tags to inbox/read relays,
matching the existing outbox/write routing for authors. Remove debug
console.log statements across the codebase while preserving error-level
logging. Delete unused logger utility. Expand test coverage for all
chunking scenarios.
2026-03-23 09:59:24 +01:00
Alejandro Gómez
9af896127e wip: relay filter chunking for REQ subscriptions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:59:24 +01:00
Alejandro Gómez
92ea6e347b fix: convert potential numbers (cached NIP-11 supported_nips) to strings 2026-03-20 10:52:34 +01:00
Alejandro Gómez
40c02cdac7 fix: track all auth events, avoid race condition 2026-03-20 10:44:14 +01:00
Alejandro Gómez
ff4f5f322b fix: tweak relay link text and icon size 2026-03-19 16:12:38 +01:00
Alejandro Gómez
d709d5d5d8 feat: rich relay links in chat 2026-03-19 12:31:02 +01:00
Alejandro Gómez
d3d038929e ui: show relay name if available instead of host 2026-03-19 12:17:42 +01:00
Alejandro Gómez
3261b2a36a feat: render keypackage relay lists as relay lists 2026-03-19 12:14:50 +01:00
Alejandro Gómez
5161c3a799 feat: add kind 10051 (KeyPackage Relays) to relay list settings
Uncomment kind 10051 in kinds registry with NIP-EE attribution and add
it to the relay list editor so users can manage MLS KeyPackage relays.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:11:54 +01:00
Alejandro Gómez
329265645b docs: full command refernce 2026-03-18 11:23:44 +01:00
Alejandro Gómez
cd889d70cb feat: add outbox relay resolution to spellbook loading
Spellbook URLs only queried hardcoded aggregator relays, missing events
published to other relays. Now fetches the author's kind:10002 relay list
and includes their outbox relays when loading kind:30777 spellbook events.

Extract useUserRelays hook from inline pattern and refactor
useRepositoryRelays to use it.
2026-03-18 11:07:46 +01:00
Alejandro Gómez
400e60107f fix: don't transition away from eose state 2026-03-17 10:25:25 +01:00
Alejandro Gómez
c283313bb8 fix: clean reply state synchronously and cleanly 2026-03-17 09:22:02 +01:00
Alejandro Gómez
364dc48247 fix: disable rich syntax in chat and poast composers 2026-03-16 16:42:52 +01:00
Alejandro Gómez
437313b7ff ux: focus input after reply selection 2026-03-16 16:31:54 +01:00
Alejandro Gómez
ce7b2478cd fix: show only chat kinds as replies 2026-03-16 16:29:37 +01:00
Alejandro Gómez
02ec642be6 fix: avoid stale closure in keyboard submit handler 2026-03-16 16:14:47 +01:00
Alejandro Gómez
0aecdd6894 ui: change kind 11 icon 2026-03-16 13:48:09 +01:00
Steffen Rörtgen
5619122b80 feat: add Educational Resource (kind 30142) with AMB metadata support (#260)
* feat: add Educational Resource (kind 30142) with AMB metadata support

- Add feed and detail renderers for AMB Educational Resource events
- Add amb-helpers library with cached helper functions and tests
- Handle broken thumbnail images with BookOpen placeholder fallback
- Surface primary resource URL prominently in both renderers (bookmark-style)
- Register kind 30142 with GraduationCap icon in kind registry
- Link NIP-AMB badge to community NIP event (kind 30817)

* fix: address PR #260 review comments for Educational Resource renderers

- Rename Kind30142*Renderer to EducationalResource*Renderer (human-friendly names)
- Localize language names with Intl.DisplayNames via shared locale-utils
- Use ExternalLink component for license and reference URLs
- Localize ISO dates with formatISODate, fixing UTC timezone shift bug
- Remove # prefix from keyword labels in both feed and detail renderers
- Remove image/thumbnail from feed renderer
- Extract getBrowserLanguage to shared locale-utils, reuse in amb-helpers

* fix: mock getBrowserLanguage in tests for Node < 21 compat

Tests were directly mutating navigator.language which doesn't exist
as a global in Node < 21, causing ReferenceError in CI.
2026-03-16 09:34:29 +01:00
Alejandro Gómez
8e11139c5d fix: skip max check on 0 maxSendable 2026-03-10 11:08:42 +01:00
Alejandro Gómez
80bd6c4e72 fix: normalize supported NIPs to strings 2026-03-06 15:09:02 +01:00
Alejandro Gómez
a7c70fa0a6 fix: simplify nip-29 group message and metadata fetching and avoid inconsistencies 2026-03-06 13:25:58 +01:00
Alejandro
80a421b9fe Centralize relay publishing via PublishService (#211)
* feat: centralize publish flow with RxJS-based PublishService

Create a unified PublishService that:
- Provides consistent relay selection (outbox + state + hints + fallbacks)
- Emits RxJS observables for per-relay status updates
- Handles EventStore integration automatically
- Supports both fire-and-forget and observable-based publishing

Refactor all publish locations to use the centralized service:
- hub.ts: Use PublishService for ActionRunner publish
- delete-event.ts: Use PublishService (fixes missing eventStore.add)
- publish-spell.ts: Use PublishService with relay hint support
- PostViewer.tsx: Use publishWithUpdates() for per-relay UI tracking

This lays the groundwork for the event log feature by providing
observable hooks into all publish operations.

* feat: add LOG command for relay event introspection

Add an ephemeral event log system that tracks relay operations:

- EventLogService (src/services/event-log.ts):
  - Subscribes to PublishService for PUBLISH events with per-relay status
  - Monitors relay pool for CONNECT/DISCONNECT events
  - Tracks AUTH challenges and results
  - Captures NOTICE messages from relays
  - Uses RxJS BehaviorSubject for reactive updates
  - Circular buffer with configurable max entries (default 500)

- useEventLog hook (src/hooks/useEventLog.ts):
  - React hook for filtering and accessing log entries
  - Filter by type, relay, or limit
  - Retry failed relays directly from the hook

- EventLogViewer component (src/components/EventLogViewer.tsx):
  - Tab-based filtering (All/Publish/Connect/Auth/Notice)
  - Expandable PUBLISH entries showing per-relay status
  - Click to retry failed relays
  - Auto-scroll to new entries (pause on scroll)
  - Clear log button

- LOG command accessible via Cmd+K palette

* fix: prevent duplicate log entries and check relay OK response

- EventLogService: Check for existing entry before creating new one
  when handling publish events (prevents duplicates from start/complete)
- PublishService: Check response.ok from pool.publish() to detect
  relay rejections instead of assuming success on resolve
- Update test mock to return proper publish response format

* feat: keep relay selection in call site, compact logs

* chore: cleanup

* fix: make Timestamp component locale-aware via formatTimestamp

Timestamp was hardcoded to "es" locale. Now uses formatTimestamp()
from useLocale.ts for consistent locale-aware time formatting.
Added Timestamp to CLAUDE.md shared components documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: improve event-log reliability, add ERROR type and per-relay timing

Service improvements:
- Fix notice$ duplicate logging with per-relay dedup tracking
- Remove dead Array.isArray code path (notice$ emits strings)
- Increase relay poll interval from 1s to 5s
- Clean publishIdToEntryId map on terminal state, not just overflow
- Immutable entry updates (spread instead of in-place mutation)
- Extract NewEntry<T>/AddEntryInput helper types for clean addEntry signature
- Clear lastNoticePerRelay on log clear

New capabilities:
- ERROR log type: subscribes to relay.error$ for connection failure reasons
- RelayStatusEntry with updatedAt timestamp for per-relay response timing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: improve EventLogViewer with virtualization, timing, and error display

- Virtualize log list with react-virtuoso for 500-entry buffer performance
- Add ErrorEntry renderer for new ERROR log type (AlertTriangle icon)
- Show per-relay response time (e.g. "142ms", "2.3s") in publish details
- Make all entry types expandable (connect/disconnect now have details)
- Show absolute timestamp in all expanded detail views
- Group ERROR events under Connect tab filter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: prevent duplicate PUBLISH log entries from completion event

PublishService emits publish$ twice: once at start, once on completion.
The eager publishIdToEntryId cleanup in handleStatusUpdate fired before
the completion emission, causing handlePublishEvent to create a second
entry. Removed eager cleanup — overflow eviction is sufficient.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 17:35:44 +01:00
Alejandro Gómez
ee09cac2e0 fix: emoji and profile suggestion UX/UI fixes 2026-03-03 22:29:17 +01:00
Alejandro Gómez
15fe8b6c59 fix: parse address 2026-03-03 22:22:35 +01:00
Alejandro Gómez
772e1b1404 refactor: extract useRepositoryRelays hook from NIP-34 renderers
Removes ~45 lines of identical relay resolution boilerplate duplicated
across 6 renderers (Issue, Patch, PR - feed and detail views).

The hook encapsulates the 3-tier fallback: repo relays → owner outbox →
aggregators, and also returns the repository event needed for
getValidStatusAuthors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 21:58:11 +01:00
Alejandro Gómez
bcd58e40dd fix: prettify scrollbar, tweak height 2026-03-03 21:57:00 +01:00
Alejandro
8c9ecd574c refactor(editor): replace DOM manipulation with React node views and floating-ui (#253)
* refactor(editor): replace DOM manipulation with React node views and floating-ui

- Convert all inline node views (emoji, blob attachment, event preview) from
  imperative document.createElement() to React components via ReactNodeViewRenderer
- Replace tippy.js with @floating-ui/react-dom for suggestion popup positioning
- Create useSuggestionRenderer hook bridging Tiptap suggestion callbacks to React state
- Extract shared EmojiMention, SubmitShortcut, and inline node extensions to separate files
- Extract types (EmojiTag, BlobAttachment, SerializedContent) to editor/types.ts
- Extract serialization logic to editor/utils/serialize.ts
- Remove redundant DOM keydown listener from RichEditor (handled by SubmitShortcut extension)
- Remove tippy.js dependency (-1045 lines net, RichEditor 632→297, MentionEditor 1038→354)

https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u

* fix(editor): fix suggestion popover positioning, scrolling, and profile click behavior

- Replace UserName component in ProfileSuggestionList with plain text display
  so clicking a suggestion autocompletes instead of opening their profile
  (UserName has an onClick that calls addWindow and stopPropagation)
- Add react-virtuoso to ProfileSuggestionList for efficient lazy rendering
  of up to 20 search results with fixed item height scrolling
- Add profile avatars with lazy loading and initial-letter fallback
- Fix SuggestionPopover positioning with autoUpdate for scroll/resize tracking
- Add size middleware to constrain popover max-height to available viewport space

https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u

* refactor(editor): convert emoji suggestion from grid to scrollable list with Virtuoso

Replace the 8-column grid layout with a vertical list matching the profile
suggestion style — each row shows the emoji preview alongside its :shortcode:
name. Uses react-virtuoso with fixedItemHeight for lazy rendering and smooth
keyboard-driven scrolling through large emoji sets.

https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u

* fix(editor): set mentionSuggestionChar to ':' for emoji nodes

When backspacing over a mention-based node, Tiptap inserts the node's
mentionSuggestionChar attribute as undo text. The EmojiMention extension
inherits Mention's default of '@', so deleting an emoji left '@' instead
of ':'. Fix by explicitly setting mentionSuggestionChar: ':' in the emoji
command's attrs for both RichEditor and MentionEditor.

https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u

* test(editor): add comprehensive test suite for custom TipTap extensions

Tests all 8 custom extensions using headless TipTap Editor instances in
jsdom environment (TipTap has no official testing package):

- EmojiMention: schema, renderText (unicode vs custom), mentionSuggestionChar
  attribute handling, backspace behavior regression test
- BlobAttachmentRichNode/InlineNode: schema (block vs inline), attributes,
  renderText URL serialization, parseHTML selectors
- NostrEventPreviewRichNode/InlineNode: schema, renderText encoding for
  note/nevent/naddr back to nostr: URIs
- SubmitShortcut: Mod-Enter always submits, Enter behavior with
  enterSubmits flag
- FilePasteHandler: media type filtering (image/video/audio), non-media
  rejection, mixed paste filtering, edge cases (no files, no callback)
- NostrPasteHandler: bech32 regex matching (npub/note/nevent/naddr/nprofile),
  nostr: prefix handling, URL exclusion, node creation (mention vs preview),
  surrounding text preservation, multiple entities
- Serialization: formatBlobSize, serializeRichContent (emoji tag extraction,
  blob dedup, address refs), serializeInlineContent (mention→nostr: URI,
  emoji→shortcode, blob→URL, event preview encoding)

90 new tests total.

https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u

* fix(editor): paste handler and serialization bugs found via adversarial testing

NostrPasteHandler fixes:
- Punctuation after bech32 now matches (npub1..., npub1...! etc.)
  Changed trailing lookahead from (?=$|\s) to (?=$|\s|[.,!?;:)\]}>])
- Fixed double-space between entities — unconditional " " after every
  entity caused doubled spaces. Now only adds trailing space when entity
  is at the very end of pasted text (for cursor positioning).
- Tightened regex character class from [\w] to [a-z0-9] to match actual
  bech32 charset (rejects uppercase, underscore)
- Wrapped dispatch in try/catch to handle block-node-at-inline-position
  errors gracefully (falls back to default paste)

Serialization fix:
- serializeRichContent now guards blob collection with `url && sha256`
  matching the defensive checks already in serializeInlineContent.
  Previously null sha256 would corrupt the dedup Set and null url would
  produce invalid BlobAttachment entries.

Added 22 new edge case tests:
- Paste handler: punctuation boundaries, double-space regression,
  malformed bech32 fallback, uppercase rejection, error resilience
- Serialization: empty editor, null sha256/url blobs, invalid pubkey
  fallback, missing mention attrs, inline dedup, multi-paragraph

https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u

* fix(editor): raise suggestion search limits for profiles and emojis

Both suggestion dropdowns use Virtuoso for virtualized rendering, so
they can handle large result sets without performance issues. The
previous limits (20 profiles, 24 emojis) were too restrictive — users
with many custom emojis sharing a substring or large contact lists
couldn't scroll to find the right match.

Raised both limits to 200 to allow thorough browsing while still
bounding the result set.

https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u

* refactor(chat): rework emoji picker to scrollable list with search

Replace the fixed 1-row grid (8 emojis) with a scrollable virtualized
list matching the editor's EmojiSuggestionList look & feel:

- Search box at top with magnifying glass icon
- Virtuoso-backed scrollable list (8 visible items, unlimited results)
- Each row shows emoji icon + :shortcode: label
- Keyboard navigation: arrow keys to select, Enter to confirm
- Mouse hover highlights, click selects
- Frequently used emojis still shown first when no search query
- Narrower dialog (max-w-xs) for a compact picker feel

https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u

* fix: add address field to EmojiTag in editor types, fix GroupMessageOptions

- Add optional `address` field to EmojiTag in editor/types.ts to match
  NIP-30 changes from main (30030 emoji set address)
- Extend GroupMessageOptions with MetaTagOptions to fix type error in
  GroupMessageBlueprint's setMetaTags call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(editor): restore address attr, fix serialization, UserName, no-scroll

- Restore `address` attribute in shared EmojiMention extension (emoji.ts)
  that was dropped during refactor — required for NIP-30 emoji set tracking
- Extract `address` from emoji nodes in both serializeRichContent and
  serializeInlineContent so it makes it into published events
- Fix MentionEditorProps.onSubmit signature: use EmojiTag[] (not the narrower
  inline type) so address field flows through to callers
- Restore UserName component in ProfileSuggestionList for proper display
  with Grimoire member badges and supporter flame
- Remove scrollbar when all items fit: set overflow:hidden on Virtuoso when
  items.length <= MAX_VISIBLE (profile list, emoji list, emoji picker dialog)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-03 21:50:32 +01:00
Alejandro Gómez
cffb981ad1 feat: add emoji set address as 4th param in NIP-30 emoji tags
NIP-30 allows an optional 4th tag parameter specifying the source emoji
set address (e.g. "30030:pubkey:identifier"). This threads that address
through the full emoji pipeline so it appears in posts, replies, reactions,
and zap requests.

- Add local blueprints.ts with patched NoteBlueprint, NoteReplyBlueprint,
  GroupMessageBlueprint, and ReactionBlueprint that emit the 4th param;
  marked TODO to revert once applesauce-common supports it upstream
- Add address? to EmojiWithAddress, EmojiTag, EmojiSearchResult, and
  EmojiTag in create-zap-request
- Store address in EmojiSearchService.addEmojiSet (30030:pubkey:identifier)
- Thread address through both editor serializers (MentionEditor, RichEditor)
  and the emoji node TipTap attributes
- Fix EmojiPickerDialog to pass address when calling onEmojiSelect and
  when re-indexing context emojis
- Update SendMessageOptions.emojiTags and sendReaction customEmoji param
  to use EmojiTag throughout the adapter chain

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 21:06:58 +01:00
Alejandro Gómez
5c1d7c0c63 fix: improve reliability of NWC service by isolating its pool 2026-03-02 09:38:29 +01:00
Alejandro Gómez
53add37fab fix: align reply preview text baselines in kind 1 renderer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:52:26 +01:00
Alejandro Gómez
0b132624ff fix: pluralization 2026-02-27 17:14:00 +01:00
Alejandro Gómez
6d3d225b47 feat: show nip-29 role if specified 2026-02-27 16:50:15 +01:00
Alejandro Gómez
2d1f266216 fix: add missing relative timestamps 2026-02-27 12:12:19 +01:00
Alejandro Gómez
0818219ace fix: typo 2026-02-27 12:08:19 +01:00
Alejandro Gómez
b59afbaee3 docs: first draft of NIP 2026-02-27 12:07:02 +01:00
Alejandro Gómez
36d321649d ui: show hashtags as labels, not metadata 2026-02-26 22:51:53 +01:00
Alejandro Gómez
aef0eb820c fix: embed trakcs in playlist detail view 2026-02-26 22:47:38 +01:00
Alejandro Gómez
66a422d3f8 feat: add track and playlist rendering 2026-02-26 17:19:38 +01:00
Alejandro Gómez
41a1009166 fix: avoid unnecesary re-renders 2026-02-26 16:23:47 +01:00
Alejandro
d630a72409 Add relay list management UI and settings integration (#254)
* feat(settings): add relay lists management section

- Fetch additional relay list kinds (10006, 10007, 10050) on login
- Add "Relays" tab to Settings with accordion UI for each relay list kind
- Support NIP-65 relay list (kind 10002) with read/write markers
- Support blocked relays (10006), search relays (10007), DM relays (10050)
- Add/remove relays with URL sanitization and normalization
- Explicit save button publishes only modified lists as replaceable events

https://claude.ai/code/session_01JHirYU56sKDKYhRx6aCQ54

* docs: add plan for honoring blocked & search relay lists

Detailed implementation plan for:
- Kind 10006: filter blocked relays from all connection paths
- Kind 10007: use search relays for NIP-50 queries

https://claude.ai/code/session_01JHirYU56sKDKYhRx6aCQ54

* refactor(settings): extract relay list logic into tested lib, fix UX issues

Extract parseRelayEntries, buildRelayListTags, sanitizeRelayInput, and
comparison/mode helpers into src/lib/relay-list-utils.ts with 52 tests
covering roundtrips, normalization, edge cases, and mode conversions.

UX fixes:
- Replace RelayLink (navigates away on click) with static RelaySettingsRow
- Remove redundant inbox/outbox icons (mode dropdown is sufficient)
- Always-visible delete button instead of hover-only opacity
- Per-accordion dirty indicator (CircleDot icon) for modified lists
- Discard button to reset all changes
- Read-only account explanation text
- Human-friendly descriptions (no NIP references or kind numbers)
- Separator between relay list and add input
- Larger relay icons and text for readability

https://claude.ai/code/session_01JHirYU56sKDKYhRx6aCQ54

* feat(settings): use KindBadge and NIPBadge in relay list accordions

Replace plain text kind names with KindBadge (full variant showing icon,
name, and kind number) and add NIPBadge next to each list description.
This gives power users the protocol context they expect.

Also document KindBadge and NIPBadge as shared components in CLAUDE.md.

https://claude.ai/code/session_01JHirYU56sKDKYhRx6aCQ54

* feat(settings): add favorite relays list (kind 10012) to relay settings

Add kind 10012 (Favorite Relays / Relay Feeds) to the settings UI and
account sync fetching. Uses "relay" tags like other NIP-51 lists.

https://claude.ai/code/session_01JHirYU56sKDKYhRx6aCQ54

* fix(kinds): use semantic icons for blocked and search relay lists

- Kind 10006 (Blocked Relays): Radio → ShieldBan
- Kind 10007 (Search Relays): Radio → Search

These icons propagate to KindBadge, settings accordions, and event
renderers via getKindInfo(). Generic relay kinds (10002, 30002, etc.)
keep the Radio icon.

https://claude.ai/code/session_01JHirYU56sKDKYhRx6aCQ54

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 13:11:27 +01:00
Alejandro
96d3d5bab6 Refactor assertion subject rendering to use QuotedEvent component (#255)
* Use QuotedEvent for event/address assertion subjects

Replace opaque hex IDs and kind:pubkey:d-tag strings with inline
QuotedEvent rendering for event assertions (30383) and address
assertions (30384). Feed renderer uses depth=2 (collapsible) and
detail renderer uses depth=1 (inline expanded).

https://claude.ai/code/session_01L4Kwg3Ad4C2S1cvkvwACH1

* Update package-lock.json

https://claude.ai/code/session_01L4Kwg3Ad4C2S1cvkvwACH1

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 09:28:42 +01:00