Commit Graph

581 Commits

Author SHA1 Message Date
Chad Curtis ff43177aa5 Decrypt and apply encrypted settings before releasing sync overlay
useInitialSync now fetches the kind 30078 event, decrypts it with the
user's NIP-44 signer, and applies theme/feedSettings/contentWarningPolicy
to the config before transitioning out of the sync screen. It also seeds
the TanStack query cache so useEncryptedSettings and NostrSync don't
redundantly re-fetch or re-decrypt the same event.
2026-02-20 21:49:44 -06:00
Chad Curtis 726af608a0 Add initial sync screen with setup questionnaire for new devices
When a user logs in, show a sync spinner while fetching their settings
from Nostr relays. If existing settings are found (returning user on a
new device), apply them and proceed. If no settings exist (fresh account),
walk through a brief questionnaire for theme, content preferences, and
content safety policy. Uses sessionStorage to avoid re-showing on refresh.
2026-02-20 21:47:25 -06:00
Chad Curtis 7bd397a68b Fix theme not applying to feed/tabs until refresh
The body had an inline background style from the preloader that
overrode CSS variables. Now main.tsx removes the inline style
after React mounts, letting Tailwind's bg-background class take
over so theme changes apply instantly.
2026-02-20 21:31:13 -06:00
Chad Curtis 916adf7fb6 Invert preloader logo to dark on light/pink themes 2026-02-20 21:29:05 -06:00
Chad Curtis 313b66f8fd Use saved theme for pre-React loading spinner
Read the user's theme from localStorage before first paint so the
preloader background and spinner colors match dark/light/black/pink.
Uses a small blocking script (public/theme.js) that runs before
the preloader is visible.
2026-02-20 21:28:01 -06:00
Chad Curtis 190a0dba9b Optimize feed load performance: caching, code splitting, and instant rendering
- Cache follow list and author profiles in localStorage for instant feed on return visits
- Prefetch profile images via <link rel=preload> for instant avatar rendering
- Replace Radix Avatar with lightweight component that renders <img> immediately
- Lazy-load route components (React.lazy) reducing main bundle from 1.7MB to 920KB
- Dynamic import hls.js (1.3MB) only when visiting stream pages
- Remove unused Buffer polyfill
- Add pre-React loading spinner in index.html outside #root for seamless handoff
- Fix 3-5s feed rerender caused by NostrSync relay/settings sync
- Fix Zod 4 strict mode rejecting feedSettings with extra/missing keys from localStorage
- Fix useLocalStorage skip update when value reference unchanged
- Reduce eoseTimeout from default to 600ms
2026-02-20 21:23:07 -06:00
Chad Curtis 87173f8432 Truncate long display names on profile page header 2026-02-20 18:28:29 -06:00
Chad Curtis 60a23aa0b3 Fix reply context overflow breaking sticky nav on mobile
Long unbroken names (raw npubs used as display names) in 'Replying to'
overflowed the container, pushing the page wider than the viewport and
making sticky/fixed nav elements scroll off-screen horizontally.

Truncate author names at 200px, add overflow-hidden on the container,
and shrink-0 on static text to prevent wrapping issues.
2026-02-20 17:59:06 -06:00
Chad Curtis 34a2cda6fd Add ACCESS_NETWORK_STATE permission for ConnectivityManager 2026-02-20 17:49:57 -06:00
Chad Curtis 8ba7c16958 Fix startup crash: call startForeground() immediately in onCreate
Android 12+ crashes the app if startForeground() isn't called within 5
seconds of startForegroundService(). Moved it from onStartCommand() to
the top of onCreate() to ensure the foreground notification is posted
before any other initialization.
2026-02-20 17:48:04 -06:00
Chad Curtis 6066b5ec49 Replace polling notification system with persistent WebSocket subscription
Replaces the AlarmManager-based polling (wake every 60s, open/close WebSocket
connections) with a persistent WebSocket subscription to a Nostr relay. Events
are delivered in real-time via the open connection. A partial WakeLock keeps
the connection alive through Doze mode (same approach as Signal without FCM).

- Add NotificationRelayService: foreground service with persistent WebSocket,
  exponential backoff reconnection, network-aware reconnect, relay rotation
  on failure, and SharedPreferences config listener
- Refactor NostrPoller into notification dispatcher with metadata caching
  (SharedPreferences-based, avoids redundant WebSocket connections for
  repeat authors)
- Remove NotificationService (AlarmManager scheduler) and PollAlarmReceiver
  (WakeLock-based polling)
- Remove SCHEDULE_EXACT_ALARM permission (no longer needed)
- Disable web-layer background refetch on native (persistent connection
  handles it)
2026-02-20 17:43:26 -06:00
Chad Curtis 0ff2ea4198 Untrack generated mipmap PNGs and ignore android/downloads/ 2026-02-20 17:09:22 -06:00
Chad Curtis afa7ede1c9 Respect content warning policy in profile media grid
CW media squares show a blurred placeholder with a shield icon instead
of loading the actual image/video. When policy is 'hide', CW media is
excluded from the grid entirely.
2026-02-20 17:01:26 -06:00
Chad Curtis 9b0313f83f Match CW settings layout to other settings rows: label left, radio right 2026-02-20 16:57:42 -06:00
Chad Curtis 469dd406d7 Contain blur within rounded box, don't let it bleed outside 2026-02-20 16:55:18 -06:00
Chad Curtis e41ce2e10b Fix content warning overlay: move overlay outside overflow-hidden container and check NIP-32 l tags for CW reason 2026-02-20 16:54:09 -06:00
Chad Curtis eb483469bb Add NIP-36 content warning support with blur/hide/show settings
Respect content-warning tags on events. Users can choose how to handle
them in Settings > Content > Sensitive Content:

- Blur (default): Shows a grey placeholder overlay with the warning
  reason in quotes. Media is not loaded until the user clicks reveal.
- Hide: Removes content-warned posts from the feed entirely.
- Show: Ignores content warnings and displays everything normally.

The setting syncs across devices via encrypted NIP-78 settings.
2026-02-20 16:45:33 -06:00
Chad Curtis b0347e213b Ignore Android launcher icons regenerated by build 2026-02-20 16:33:36 -06:00
Chad Curtis 1881e3cde9 Build v2026.02.20: Update mew.apk (6.2M) 2026-02-20 15:30:11 -06:00
Chad Curtis 3314f01b5e Fix failing tests and ESLint config
- Update NoteContent tests to use inline URLs (mid-sentence) instead of
  end-of-line URLs that render as LinkPreview cards without accessible links
- Update mention styling assertion from text-gray-500 to text-muted-foreground
  to match the actual NostrMention component classes
- Add android/ to ESLint ignores to prevent linting build output artifacts
2026-02-20 15:20:18 -06:00
Chad Curtis 5bbbc5022a Fix mobile live stream layout: viewport-locked chat above bottom nav
Lock main element to viewport height on mobile with body scroll disabled,
collapsible description with author under details, zap button inline with
title, and chat input sitting directly above the bottom nav with no gaps.
2026-02-20 15:14:05 -06:00
Chad Curtis 4882a90403 Add NIP-53 live stream support with HLS player and live chat
Implement kind 30311 live streaming events: HLS video player (hls.js),
kind 1311 live chat with real-time subscriptions, stream detail page with
collapsible description on mobile, desktop sidebar chat, streams feed page,
and full extra-kinds integration with sidebar nav and settings.
2026-02-20 14:52:48 -06:00
Alex Gleason e2f2763d44 Upgrade nostrify 2026-02-20 00:11:49 -06:00
Alex Gleason ee9a1e34c3 Always route search queries to relay.ditto.pub (for now) 2026-02-20 00:11:03 -06:00
Alex Gleason 77ff88c2f6 Render NIP-30 custom emoji in all remaining display name locations
Apply EmojifiedText to mentions inside embedded/quote posts,
embedded note author names, and all other secondary UI locations
where display names were still rendered as plain text.
2026-02-19 21:43:56 -06:00
Alex Gleason 2b5df1c36b Remove slop file 2026-02-19 20:36:10 -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
Alex Gleason 7e3f104ace Fix NIP-30 custom emoji reactions rendering as raw :shortcode: text
Custom emoji reactions from kind 7 events with emoji tags were displaying
the raw shortcode text (e.g., ':soapbox:') instead of rendering the image.
Add custom emoji resolution throughout the reaction pipeline: data hooks
now extract emoji URLs from event tags, and all rendering locations
(ReactionButton, PostDetailPage stats, InteractionsModal, Notifications)
now display custom emojis as inline images.
2026-02-19 18:39:43 -06:00
Chad Curtis d58f4bb632 Resolve raw hex identifiers as event ID or pubkey in search and routing
Detect 64-char hex strings in the search bar and NIP19Page route.
Query relays to check if the hex is an event ID first, then fall back
to treating it as a pubkey if a kind-0 profile is found.
2026-02-19 18:17:56 -06:00
Chad Curtis 8fe07e65cc Add Nostr identifier detection in search and profile search, improve DomainFeedPage header
Detect NIP-19 and NIP-05 identifiers in the search bar and profile
search dropdown, navigating directly to the appropriate route instead
of performing a text search. Refactor DomainFeedPage header to use
back navigation, show user count inline, and match border styling.
2026-02-19 18:13:17 -06:00
Chad Curtis 223d8822a4 Fix NIP-05 resolution for leading @ prefix and case-insensitive name lookup 2026-02-19 18:08:01 -06:00
Chad Curtis 3e7ba143f9 Add user-configurable settings for Blossom servers, zap comment, favicon provider, CORS proxy, and NIP-46 relays
- Add blossomServers (array), defaultZapComment, faviconProvider, corsProxy to AppConfig
- Blossom servers: multi-server support with add/remove UI matching relay list pattern
- Default zap comment changed from 'Zapped with MKStack!' to 'Zapped with Mew!'
- NIP-46 nostrconnect now uses the user's write relay list instead of hardcoded relay
- CORS proxy and favicon provider use {href} URI template pattern
- New 'System' section in Advanced Settings for zap comment, favicon provider, CORS proxy
- Fix ghost button hover text color on light/pink themes across settings panels
- Fix pre-existing TSC errors: appRelays array typing, muteHelpers dead code, ProfilePage FeedItem type, EditProfileForm useFieldArray, FeedSettingsForm/ContentSettings feedKey narrowing, LeftSidebar icon type
2026-02-19 17:51:51 -06:00
Chad Curtis 325e1b9be1 Remove verified badge, use brain icon for difficulty, put terrain next to difficulty 2026-02-19 17:11:38 -06:00
Chad Curtis a8b8243868 Use NoteContent for rich text rendering in polls and fix word-break overflow 2026-02-19 17:10:23 -06:00
Chad Curtis 4fd50d545f Remove sticky positioning from extra kind page headers 2026-02-19 17:06:32 -06:00
Chad Curtis 54b27e4c09 Include extra kinds in profile media grid, extract vine URLs from imeta tags 2026-02-19 17:05:05 -06:00
Chad Curtis 448c051e33 Include media-native kinds like vines in profile media tab filter 2026-02-19 17:02:28 -06:00
Chad Curtis 09d722ddd2 Add object-cover to VideoPlayer to fill container without borders 2026-02-19 17:00:36 -06:00
Chad Curtis 95c3a5accc Fix desktop compose to open modal, cache right sidebar data, render vine videos on detail page 2026-02-19 16:54:16 -06:00
Chad Curtis f125abeef8 Restore avatar in compact ComposeBox feed view 2026-02-19 16:42:25 -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 a484c8b95c Delay stats invalidation after publish to preserve optimistic updates
The relay needs time to index newly published events. Immediate
invalidation caused a refetch that returned stale counts, overwriting
the optimistic +1 and making the count briefly appear then vanish.
2026-02-19 16:21:14 -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 7aad043734 Replace Repeat2 with custom RepostIcon, style repost/treasure action headers 2026-02-19 16:04:16 -06:00
Chad Curtis ec8e71cb70 Fix action header height — use w-11 instead of size-11 for icon container 2026-02-19 15:48:29 -06:00
Chad Curtis b0ac1180dd Align repost/treasure action text with username column, icon in avatar column 2026-02-19 15:46:57 -06:00
Chad Curtis 1bc069a7bd Fix sticky page titles on mobile for bookmarks and kind feed pages 2026-02-19 15:43:05 -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
Chad Curtis ea9821c16e Add IDE files to .gitignore 2026-02-19 12:12:21 -06:00