Commit Graph

33 Commits

Author SHA1 Message Date
Chad Curtis 79c143fab1 fix: replace image URLs with newline in disableEmbeds preview mode 2026-02-26 05:37:01 -06:00
Chad Curtis 0576775a57 fix: suppress image URLs in triple-dot menu post preview
When disableEmbeds is true, image-embed tokens now return null instead of
rendering the raw URL as a link. This fixes the triple-dot (more menu)
preview showing bare blossom/image URLs instead of clean post text.
2026-02-26 05:36:27 -06:00
Chad Curtis 6f5a07c0a9 Render images inline at their position in post content
- Images now render inline via NoteContent at the position of their URL
  rather than collected into a gallery block below the text
- Clicking an inline image opens a full lightbox with navigation across
  all images in the post; lightbox index is tracked by position so
  duplicate URLs open at the correct index
- Removed separate ImageGallery/extractImages from NoteCard,
  PostDetailPage, and ComposeBox to prevent double-rendering
- Added disableEmbeds to NoteMoreMenu clamped preview to avoid block
  embeds inside a line-clamp-3 container
- Fixed hasPreviewableContent in ComposeBox to detect image-only posts
  so the Preview tab appears correctly
- Removed mp3/ogg/wav/pdf from MEDIA_URL_REGEX suppression list; those
  URLs now render as clickable links instead of being silently dropped
- Added avif to IMAGE_URL_REGEX; added cursor-pointer to InlineImage
2026-02-26 04:35:03 -06:00
Alex Gleason 439ab94ea3 Merge branch 'main' of gitlab.com:soapbox-pub/ditto-mew 2026-02-23 20:19:22 -06:00
Alex Gleason 64cf10f381 Fix useProfileUrl to call useNip05Verify directly instead of peeking cache
The cache-peek approach always returned npub because the cache was empty
at render time. Replace it with a proper hook that calls useNip05Verify,
relying on TanStack Query's deduplication to avoid redundant requests.

Also fix the dot separator in NoteCard to hide when NIP-05 is unverified,
and refactor ProfileSearchDropdown to pass the verified URL through
onClick rather than recomputing it in an event handler.
2026-02-23 19:39:13 -06:00
Mary Kate Fain 379282ecea Fix horizontal overflow on posts with links when reposting
- Add overflow-hidden to NoteCard article elements in both normal and
  threaded layouts to clip content that exceeds card width
- Add overflow-hidden to NoteContent root div to prevent link preview
  cards and embedded content from pushing beyond container bounds
- Strip .xdc URLs in EmbeddedNote content preview (was missing from
  the media URL regex, causing raw long URLs to render in quote embeds)
- Add overflow-hidden to EmbedContentPreview paragraph for defense
  against long unbreakable strings
- Use disableEmbeds on NoteContent inside ReplyComposeModal's embedded
  post preview so URLs render as plain links instead of full preview
  cards that overflow the clamped container
- Add attachment indicator chips to EmbeddedNote (images, videos, apps,
  links) so stripped media URLs still have a visible presence
2026-02-23 16:46:49 -06:00
Chad Curtis 580b5ae46e Fix whitespace stripped around URLs containing naddr1 identifiers
URLs like https://following.party/naddr1... were having all surrounding
whitespace removed because naddr-embed tokens from URLs were treated as
block-level elements. Only bare naddr1 identifiers (without a URL) should
strip surrounding whitespace; URL-sourced ones are inline and need their
spacing preserved.
2026-02-22 01:49:38 -06:00
Chad Curtis bba57e83e4 Fix compose preview to match real note rendering
Mentions now trigger the Edit/Preview toggle. Compose preview uses
NoteContent directly for link previews and embeds instead of rendering
them separately, matching how real notes display. LinkPreview falls back
to a domain+favicon card when OEmbed data is unavailable. Added
disableEmbeds prop to NoteContent for future use.
2026-02-21 17:27:08 -06:00
Alex Gleason 13f05936dd Add webxdc support: attach .xdc files as stateful mini apps with kind 4079 state sync
- Create useWebxdc hook bridging the Webxdc API with Nostr kind 4079 state updates
- Create WebxdcEmbed component with launch-on-click UX for sandboxed iframe rendering
- Update ComposeBox to accept .xdc files and generate imeta tags with webxdc UUID
- Update NoteCard and PostDetailPage to detect and render webxdc attachments
- Skip .xdc URLs in NoteContent to avoid rendering them as raw links
2026-02-21 04:57:05 -06:00
Alex Gleason 6180bbf0c3 Fix 30 ESLint errors: remove unused imports/variables, replace any types, use const 2026-02-19 20:14:01 -06:00
Alex Gleason be7cfbab67 Render NIP-30 custom emoji in display names, post text, and bios
Add emojify/EmojifiedText utilities that replace :shortcode: patterns with
inline images using emoji tags from kind 0 and kind 1 events. Applied to
display names across NoteCard, PostDetailPage, ProfilePage, ProfileHoverCard,
InteractionsModal, NotificationsPage, and NoteContent @mentions. Also
emojifies about/bio text in ProfilePage and ProfileHoverCard.

Remove string-level truncation from getDisplayName to avoid breaking
shortcodes mid-pattern (CSS truncate handles visual overflow). Use
em-relative sizing and align-text-bottom for proper inline alignment.
2026-02-19 19:06:14 -06:00
Chad Curtis 9f6022e5e9 Render link previews for end-of-line URLs, skeleton load notifications, use ImageGallery, match mobile tab heights
- Show link preview cards for URLs that end a line, not just standalone
  URLs; only suppress previews for URLs followed by more text on the
  same line
- Show skeleton placeholders on notifications page until the query has
  completed at least once instead of flashing 'No notifications yet'
- Add skeleton loading for author rows in notification cards while
  profile data loads
- Replace inline image <a> tags with ImageGallery component so clicking
  images opens the lightbox with navigation
- Match notification tab height/weight to feed tabs on mobile while
  preserving original desktop styling
2026-02-19 16:39:13 -06:00
Chad Curtis 35422ec6bb Fix optimistic updates, show user reaction emoji, compact embeds, and unify repost menu
- Add true optimistic updates for reactions and reposts via setQueryData
  instead of only invalidating queries after publish
- Track user's own reaction per event and display their emoji in place of
  the Heart icon across feed, post details, and notifications
- Strip whitespace around block embeds and skipped media URLs to eliminate
  blank lines caused by whitespace-pre-wrap
- Only render link preview cards for standalone URLs; inline URLs in
  sentences render as plain clickable links
- Remove border-b separators and use fixed-height object-cover on preview
  images to eliminate gaps
- Tighten padding on EmbeddedNote and EmbeddedNaddr cards
- Use fixed-height object-cover for ImageGallery grid images
- Unify RepostMenu to use Popover on all screen sizes instead of Drawer
  on mobile
2026-02-19 16:19:19 -06:00
Chad Curtis aa231797af Add NIP-05 domain feeds, profile hover cards, gallery lightbox, and NIP-05 profile URLs
- Domain feed page at /timeline/:domain fetches .well-known/nostr.json and queries events from domain users
- NIP-05 domains are clickable in usernames throughout the app (Nip05Badge, NoteCard, PostDetailPage, etc.)
- @_@domain.com renders as @domain.com (underscore prefix hidden)
- Profile hover cards on avatars, usernames, and mentions across all components
- Clicking avatar/banner on profile page opens image in gallery lightbox with safe-area support
- NIP-05 verified users get clean profile URLs (e.g. /user@domain.com) instead of /npub1...
- NIP19Page unified dispatcher handles NIP-19, NIP-05, and profile routing at /:param
- Removed /u/:npub and /d/:domain routes in favor of root-level routing
- CORS proxy fallback for NIP-05 resolution on non-CORS-compliant servers
- Mobile top bar logo links to home
- Safe area fixes for gallery lightbox, mobile drawer, and sheet close button
2026-02-19 15:37:53 -06:00
shakespeare.diy 510e7a76f2 Add multiple reply authors and emoji-only enlargement
- Show multiple reply authors like "Replying to @chad and @alex"
- Display up to 2 authors, with "and X others" for more
- Enlarge emojis when they're the only content (text-5xl)
- Detect emoji-only content (max 12 emoji chars)
- Update ReplyContext to accept array of pubkeys
- Extract all non-mention p tags for reply context
- Matches Ditto's reply author display behavior

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-18 20:40:54 -06:00
shakespeare.diy 3c4c84d255 Fix URL parsing with trailing punctuation and preserve whitespace formatting
- Strip trailing punctuation from URLs (.,;:!?)])  that are likely not part of the URL
- Fixes issue where (https://example.com) was parsed incorrectly
- Preserve newlines and formatting after embedded content
- Only collapse excessive whitespace (3+ newlines) instead of removing all whitespace
- Maintains proper text flow after link previews and embedded events

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-18 04:27:33 -06:00
shakespeare.diy 973064af99 Fix whitespace handling for naddr URLs with embedded events
- Preserve one newline after naddr-embed tokens when present
- Prevents text from flowing directly after URL without spacing
- Embedded event now properly displays with preserved formatting

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-18 04:25:38 -06:00
shakespeare.diy 724663f7dd Support mentions in all contexts including inside quotes and parentheses
- Removed lookahead that was preventing matches in certain contexts
- NIP-19 identifiers now render as mentions regardless of surrounding characters
- Maintains single @ display by consuming optional @ prefix

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-18 04:23:08 -06:00
shakespeare.diy d3d98a00bf Fix double @@ rendering for mentions and support mentions inside quotes
- Updated regex to optionally match @ before NIP-19 identifiers
- Removed word boundary requirement to allow mentions in quotes
- Mentions now render correctly with single @ symbol in all contexts

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-18 04:22:04 -06:00
shakespeare.diy 7ff554f8b6 Fix hashtag clicks navigating to post detail instead of hashtag page
Add e.stopPropagation() to hashtag, nostr-link, and mention Links
inside NoteContent so clicks don't bubble up to the parent card's
onClick handler that navigates to the post detail page.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-17 19:47:34 -06:00
shakespeare.diy 476e9bf177 fix: match bare NIP-19 identifiers (without nostr: prefix) in note content
The content parser regex only matched nostr:-prefixed identifiers like
`nostr:naddr1...`. Bare identifiers like `naddr1...` were rendered as
plain text. Added a \b word-boundary alternation to also match bare
npub1, note1, nprofile1, nevent1, and naddr1 identifiers, so they
render as proper embeds/mentions/links.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-17 19:16:24 -06:00
shakespeare.diy 9e71aea931 Fix raw image URL rendering in post details and improve skeleton
- Fix NoteContent fallback that incorrectly rendered raw media URLs as
  plain text when the entire content was a media URL. The parser would
  skip media URLs (handled by parent as embeds), but when all tokens
  were skipped, the empty-result fallback re-added the full content
  as text. Now tracks whether any regex matches occurred to distinguish
  "no matches at all" from "all matches were skipped media URLs".

- Restructure PostDetailSkeleton to match the actual PostDetailContent
  layout: proper article/replies separation (fixes double padding on
  reply skeletons), image placeholder, rounded action button circles,
  and -mx-4 action bar matching the real component.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-17 04:21:57 -06:00
shakespeare.diy 49917ec1a0 Preserve newlines between text and naddr URL in note content
The whitespace collapsing logic was stripping newlines before naddr-embed
tokens that have a URL, causing text and the URL to smash together.
Now only pure block embeds (no URL) trim preceding whitespace.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-17 02:34:50 -06:00
shakespeare.diy 7ca3587e1d Preserve original URL for naddr embeds and implement naddr detail page
- NoteContent now shows the original URL as a clickable link above the
  embedded naddr card when the naddr was extracted from a regular URL
- Replaced "Addressable event view coming soon" placeholder in NIP19Page
  with a full AddrDetailPage that shows hero image, author, title,
  description, image gallery, metadata fields, and tags
- AddrDetailPage extracts metadata from both event tags and JSON content

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-17 02:33:06 -06:00
shakespeare.diy b81aa6f2c8 Render naddr1 URLs as embedded Nostr events instead of broken link previews
- Added useAddrEvent hook for fetching addressable events by kind+pubkey+d-tag
- Created EmbeddedNaddr component that displays title, description, image, and author
  from addressable events (extracting metadata from tags and JSON content)
- Updated NoteContent to detect naddr1 identifiers in regular URLs (e.g.
  bitpopart.com/art/naddr1...) and render them as Nostr embeds
- Added naddr1 to the nostr: URI regex so nostr:naddr1... is also handled
- Added naddr-embed token type with proper whitespace collapsing

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-17 02:30:17 -06:00
shakespeare.diy d48d4dc8b6 Render nevent/note references as inline embedded post cards
- Create EmbeddedNote component with avatar, author name, timestamp,
  truncated content preview, and optional image thumbnail
- Update NoteContent tokenizer to detect note1 and nevent1 references
  and render them as embedded cards instead of plain text links
- Collapse whitespace around embedded note cards like link previews
- Clicking an embedded card navigates to the full post detail page

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 23:16:17 -06:00
shakespeare.diy 722202eede Increase link preview and YouTube embed spacing to my-2.5
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 23:05:45 -06:00
shakespeare.diy 9b2d26b6a0 Fix link preview spacing, bot headers, and add YouTube embeds
Spacing:
- Reduce link preview margins from my-2 to mt-1.5 mb-0.5
- Collapse whitespace on text tokens adjacent to block-level tokens
  (link-preview, youtube-embed) so newlines from the original content
  don't stack with the card's own spacing
- Filter out empty text tokens after trimming

Bot headers:
- Send proper User-Agent header ("Mew/1.0 Link Preview Bot") when
  fetching OG data so dynamic sites (SPAs, Twitter, etc.) return
  server-rendered HTML with OG meta tags instead of a JS shell
- Accept application/xhtml+xml in addition to text/html

YouTube embeds:
- Detect YouTube URLs (youtube.com/watch, youtu.be, /embed/, /shorts/)
  and extract video ID
- New YouTubeEmbed component renders a privacy-enhanced iframe player
  (youtube-nocookie.com) with proper 16:9 aspect ratio
- YouTube links render as playable inline embeds instead of OG cards

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 23:03:09 -06:00
shakespeare.diy dd02f2ff27 Render link previews inline where URLs appear in post content
Move LinkPreview rendering from a fixed position below the post into
NoteContent itself, so previews appear exactly where the URL was in
the original text.

- Rewrite NoteContent to use a token-based architecture: useMemo
  produces typed tokens (text, link-preview, mention, nostr-link,
  hashtag), then the render phase maps tokens to components
- Non-media URLs produce a `link-preview` token that renders an
  inline <LinkPreview> card at that position in the content flow
- Remove separate LinkPreview blocks from NoteCard and PostDetailPage
  since previews are now handled by NoteContent
- Remove unused extractPreviewUrl helper from useLinkPreview hook

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 23:00:58 -06:00
shakespeare.diy 00d5024218 Replace non-media link URLs with rich preview cards
- Add useLinkPreview hook that fetches Open Graph metadata (title,
  description, image, favicon, site name) via CORS proxy with 1hr
  stale time caching
- Add extractPreviewUrl helper to find the first non-media URL in
  note content
- Add LinkPreview component with a polished card UI showing OG image,
  title, description, domain favicon, and external link indicator
- Strip all URLs (both media and non-media) from NoteContent inline
  text — media URLs are rendered as image embeds, non-media URLs are
  rendered as LinkPreview cards
- Integrate LinkPreview into NoteCard and PostDetailPage between
  image attachments and action buttons

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 22:58:19 -06:00
shakespeare.diy ce90ded614 Strip embedded image URLs from NoteContent text display
Image URLs (jpg, jpeg, png, gif, webp, svg) are already rendered as
embedded image previews by NoteCard and PostDetailPage. This change
removes them from the inline text content to avoid duplication.

Also trims leading/trailing whitespace left behind after stripping
image URLs from the edges of content.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 22:55:11 -06:00
shakespeare.diy 4f1b4800d0 Build Mew: a full-featured kind 1 Nostr client
- Dark theme with purple accent colors matching the reference design
- Three-column layout: left sidebar, main feed, right sidebar
- Left sidebar: Mew logo, search, navigation (Home, Notifications, Search, Vines, Profile, Wallet, Settings, More), compose button, user profile/login
- Main feed: compose box, Follows/Global tabs, live note cards with avatars, author info, NIP-05 verification, relative timestamps, image attachments, and action buttons (reply, repost, like, zap, more)
- Right sidebar: trending hashtags with sparklines, latest accounts, footer
- Full routing: home, profile, notifications, search, hashtags, settings (profile/relays), placeholder pages
- NIP-19 routing with automatic profile redirect
- Custom hooks: useFeed, useTrendingTags, useLatestAccounts, useEventStats
- NoteContent renders mentions, links, and hashtags as clickable elements
- Inter Variable font, skeleton loading states, responsive layout

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 17:05:32 -06:00
shakespeare.diy 98ff1e09e0 New project created with Shakespeare
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 16:54:01 -06:00