* feat: Add Shosho as an external client for Live Events
Adds 'Shosho' to the list of external clients for kind 30311 (Live Event) events.
The link format is `https://shosho.live/live/<event_bech32>`.
* refactor: Reorder clients for Live Events
Based on feedback, this commit reorders the external clients for Live Events to place 'shosho' after 'zap.stream'.
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
NIP-04 encryption is deprecated due to security vulnerabilities.
This migrates MuteList (kind 10000) and PinnedUsers (kind 10010)
private entries to use NIP-44 encryption, with backward compatibility
for reading existing NIP-04 encrypted content. When NIP-04 content
is detected, it is automatically re-encrypted with NIP-44 and
republished to gradually migrate users.
Co-Authored-By: captain-stacks <201298974+captain-stacks@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reactions now render with a large emoji (matching emoji-only note sizing)
and a "reacted to" preview pill linking to the target event, following
the same pattern as comment parent previews.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Count total occurrences of medium signals in containsMarkdown instead of
only distinct types, so repeated patterns like multiple list items
correctly trigger markdown rendering. Add whitespace-normal to
MarkdownContent to prevent inherited whitespace-pre-wrap from parent
note content causing inconsistent line spacing in embedded notes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Block ws:// relay connections and http:// resource loading by default
to prevent browser mixed content warnings. When blocked, resources
show clickable URL links instead of error placeholders so users can
open them manually.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show emojis at a larger size when a note contains only emojis (≤3), similar to Telegram. Also remove the automatic space inserted after custom emoji in the post editor.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The userEmojiListEvents and emojiSetEvents stores were not included in
the cleanUp() method, causing their cached data to never expire. Add
both stores with a 7-day expiration period.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a Switch control next to the relay selector for users to explicitly
enable/disable NIP-70 protected events. Auto-enables when relay
conditions suggest it (no optimal relays), but respects user override.
Includes a help popover explaining protected events with a note that
not all relays support them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Display a subtle green "Protected" badge next to the username for
events with the `-` tag (NIP-70), indicating restricted distribution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The setInterval polling playerRef.current.isMuted() continued running
after the YouTube player was destroyed, causing repeated TypeErrors.
Now the interval self-clears when it detects the player is invalid.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
storedEvents from IndexedDB could contain the same event IDs as the
fetched events, causing duplicate notifications to appear. Use the
shared idSet to filter storedEvents so each event ID appears only once.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apply NFKD normalization to both indexed text and search queries so
that stylized Unicode characters (e.g. 𝚋𝚊𝚝𝚜𝚒𝚚) are decomposed to
their ASCII equivalents and can be matched by search.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use overflow-wrap: anywhere instead of break-words so long URLs
break properly without splitting normal words mid-character.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded SEARCHABLE_RELAY_URLS with user-configurable search
relays stored in localStorage. Add SearchRelaysSetting UI in System
settings page with add/remove/reset functionality.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add remarkInlineContent plugin to detect hashtags, custom emojis, and
lightning invoices in text nodes. Handle YouTube/X URLs in the link
component. Fix bug where a text node fully matching a single pattern
was not replaced due to segments.length === 1 check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detect markdown-formatted posts (from bots etc.) and render them
with react-markdown instead of plain text, with feed-friendly
styles (flattened headings, compact lists, scrollable tables).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When reconnecting a bunker signer (e.g. Amber) after page reload, skip
the getPublicKey() call since the pubkey is already known from storage.
This prevents the app from hanging indefinitely when the remote signer
is unreachable. Also add a 10s timeout to getPublicKey() for safety.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use compareEvents (which considers both created_at and id) instead of
simple created_at comparison for sorting events in timeline subscription
and load-more logic. This ensures consistent ordering with mergeTimelines
and handleNewEvent deduplication, preventing duplicates when events share
the same timestamp. Also add Set-based dedup in notification list memo
as an additional safety net.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a toggle in General Settings to enable/disable video loop playback,
following the same pattern as the existing autoplay setting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: show 'Encrypted direct messages not supported' for kind 4 events (#753)
Co-authored-by: The Daniel <dmnyc@users.noreply.github.com>
* i18n: add translations for 'Encrypted direct messages not supported'
Also use kinds.EncryptedDirectMessage constant instead of magic number 4.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: The Daniel 🖖 <3638467+dmnyc@users.noreply.github.com>
Co-authored-by: The Daniel <dmnyc@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Two issues prevented multiple YouTube URLs from rendering:
1. YOUTUBE_URL_REGEX and X_URL_REGEX had the global flag, causing
stateful lastIndex to skip matches on alternating calls.
2. Each YouTube Player overwrote window.onYouTubeIframeAPIReady,
so only the last mounted player received the callback. Replace
with a shared callback queue via ensureYTApi().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add flex-wrap to the relay tags container so tags wrap to the next line
instead of overflowing horizontally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a "Copy note content" option to the note options menu that copies the
event's content field to clipboard. Merge AGENTS.md into CLAUDE.md with
enhanced i18n rules emphasizing append-only locale key ordering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>