Commit Graph

53 Commits

Author SHA1 Message Date
Derek Ross addbece173 Add NIP-30 custom emoji picker support (kind 10030)
Integrate custom emojis from the user's kind 10030 emoji list into
the emoji picker, compose flow, reactions, and DMs:

Hook:
- useCustomEmojis: query kind 10030, extract emoji shortcode/url pairs

EmojiPicker:
- Accept customEmojis prop, render as dedicated 'Custom' tab via
  emoji-mart's custom categories feature
- Changed onSelect from string to EmojiSelection union type
  (native unicode | custom shortcode+url)

ComposeBox:
- Pass custom emojis to picker, insert :shortcode: on selection
- Scan content on publish for :shortcode: patterns, cross-reference
  against user's emoji list, add ['emoji', name, url] tags (NIP-30)

QuickReactMenu:
- Custom emoji reactions: content=':shortcode:', with emoji tag
- Optimistic cache update includes custom emoji URL/name

DMChatArea:
- Pass custom emojis to picker, insert :shortcode: text

Settings:
- Registered as 'Custom Emojis' in Other Stuff > Whimsy section
- showCustomEmojis toggle (default true) gates all custom emoji
  features — when disabled, no kind 10030 queries are made
- Fix pre-existing Bot icon missing import in sidebarItems
2026-03-01 20:28:08 -05:00
Alex Gleason 477257325c mew -> ditto 2026-03-01 17:50:50 -06:00
Chad Curtis 708dd23fc4 Add follows feed reply filter and fix feedSettings deep-merge for new keys 2026-02-28 20:27:03 -06:00
Alex Gleason fcd32f1bd4 Replace Twitter widgets.js with direct iframe embed, remove CSP exception 2026-02-28 18:46:25 -06:00
Mary Kate Fain 6598a0363a Fix lint errors: remove unused useEffect import, prefix unused schema
- ThemeSelector.tsx: remove unused useEffect import
- useBookInfo.ts: prefix OpenLibraryBookSchema with _ (only used for type inference)
2026-02-28 18:30:47 -06:00
Alex Gleason 7afe8efa21 Add profile preview at top of comment threads on person profiles
When viewing a kind 1111 comment thread where the root is a person
(kind 0 profile), show a compact profile preview card with avatar,
name, and NIP-05 at the top of the page, similar to how external
content previews are shown for URLs/books/countries.
2026-02-28 18:14:28 -06:00
Chad Curtis da1533bccf Unify sidebar icon/label sources of truth and rename items
- Create extraKindIcons.ts as single source of truth for extra-kind icons
- BUILTIN_ICON_COMPONENTS in SidebarNavItem covers system items only
- sidebarItemIcon() merges both maps; all pages/routes use it
- EXTRA_KINDS is now source of truth for labels and kind numbers in AppRouter, page titles, and onboarding (CONTENT_KINDS derived from EXTRA_KINDS)
- Remove themes from BUILTIN_SIDEBAR_ITEMS (it lives in EXTRA_KINDS)
- Delete dead SIDEBAR_ITEM_ICONS export
- Rename 'Theme' → 'Vibe', 'Colors' → 'Color Moments'
- Articles icon: FileText → BookOpen; Settings icon: Settings → Scroll
- Hide Vibe settings back button on non-mobile (md:hidden)
- Settings and Bookmarks page headers aligned to same structure
- Codex of Configuration opacity 40% → 60%
2026-02-28 03:12:51 -06:00
Alex Gleason 874c374434 Make flag emojis in post content clickable, linking to /i/iso3166:<CODE> pages 2026-02-28 00:19:36 -06:00
Chad Curtis f8acb1b630 Sync sidebar order, feed tabs, and advanced URLs to encrypted settings; remove sidebar column from content settings 2026-02-28 00:12:37 -06:00
Alex Gleason 1302f5933c Replace regex manifest.toml parsing with smol-toml for correct TOML handling 2026-02-27 19:27:56 -06:00
Mary Kate Fain adceba5a54 Add 7 Y2K aesthetic theme presets with bundled display fonts
Add Skater, Kawaii, Grunge, MS Paint, Retro Pop, Bubblegum, and Gamer
theme presets derived from the ditto-1 aesthetic designs. Each preset
includes tailored CoreThemeColors, a display font, and a Blossom-hosted
background image.

Install and register 7 new fontsource display fonts (Permanent Marker,
Cherry Bomb One, Creepster, Silkscreen, Bungee Shade, Luckiest Guy,
Press Start 2P) in the bundled font registry so they appear in the
FontPicker for custom theme building as well.
2026-02-27 15:55:40 -06:00
Alex Gleason 658c7d1dc1 Refactor Webxdc page to use standard Feed with tag filters
Replace the custom WebxdcFeedPage with KindFeedPage, powered by
a new tagFilters option on useFeed/Feed/KindFeedPage. The webxdc
page now uses the same follows/global tabs, pull-to-refresh, and
NoteCard rendering as every other feed.

- useFeed: accept optional tagFilters (e.g. { '#m': [...] })
- Feed/KindFeedPage: pass tagFilters through
- FloatingComposeButton: accept onFabClick callback override
- LayoutOptions: add onFabClick for custom FAB behavior
- Remove useWebxdcFeed (no longer needed)
2026-02-27 11:21:58 -06:00
Chad Curtis 4d83a6c934 Improve reply threading: show first sub-reply as hint, use text color for connector line 2026-02-26 19:44:05 -06:00
Alex Gleason cd6d5f7a7c Replace Comic Neue with Comic Relief in bundled fonts 2026-02-26 16:15:09 -06:00
Alex Gleason 3b15044919 Implement ThemeConfig type system with bundled fonts and NIP.md-compliant event parsing
- Add ThemeConfig wrapper type (colors + fonts + background) replacing bare CoreThemeColors
- Sync theme event parsing/building with NIP.md spec: colors in c tags (hex), fonts in f tags, background in bg tags (imeta-style), empty content field
- Legacy backward compat: parse old JSON-in-content format and bare CoreThemeColors in localStorage/encrypted settings
- Bundle 10 curated fonts via fontsource (Inter, DM Sans, Outfit, Montserrat, Lora, Merriweather, Playfair Display, JetBrains Mono, Comfortaa, Comic Neue) with lazy dynamic imports
- Create font loader (src/lib/fontLoader.ts) for @font-face injection from remote URLs and CSS override application for title/body roles
- Rewrite FontPicker as dual title/body picker using bundled fonts instead of Google Fonts CDN
- Remove Google Fonts integration (useGoogleFont.ts, GoogleFontLoader.tsx)
- Resolve bundled font family names to CDN URLs when publishing to Nostr
- Apply profile theme fonts when visiting other users' profiles
- Update all consumers: AppProvider, useTheme, usePublishTheme, useEncryptedSettings, ThemeSelector, ThemeBuilderPage, ProfilePage, EditProfileForm, InitialSyncGate, NostrSync
2026-02-26 14:46:30 -06:00
Chad Curtis 8e5b59c44e feat: use planet icon for feed nav item 2026-02-26 05:37:19 -06:00
Alex Gleason 808d44aeff Reconcile theme settings changes and add share toggle
Merge upstream changes with the theme settings refactor. Adds a
'Display my theme to others' toggle that publishes a kind 11667
active profile theme event when enabled and issues a kind 5 deletion
when disabled. Split /settings/appearance into /settings/theme and
/settings/content. Move theme builder to /settings/theme/edit.
2026-02-26 04:10:23 -06:00
Chad Curtis c4723ccd41 Reconcile upstream changes with mobile nav refactor 2026-02-26 03:53:15 -06:00
Alex Gleason 69875bd57a Split /settings/appearance into /settings/theme and /settings/content
Replace the tabbed Appearance settings page with two separate pages:
- /settings/theme for theme selection
- /settings/content for feed and content preferences

Move the theme builder from /settings/theme to /settings/theme/edit to
avoid the route conflict. Update all navigation links across the codebase.
2026-02-26 03:11:04 -06:00
Alex Gleason 29a9a0f36c Merge branch 'add-custom-theme-editor-ui' 2026-02-26 02:28:23 -06:00
Alex Gleason 8d03d32b0d Simplify theme system to 4 core colors (background, text, primary, secondary)
Replace the 19-token ThemeTokens interface with a 4-field CoreThemeColors
for config storage, Nostr events, and encrypted settings. All other
Tailwind CSS tokens (card, muted, border, etc.) are now derived
automatically via deriveTokensFromCore().

- Add CoreThemeColors interface: { background, text, primary, secondary }
- Keep ThemeTokens as internal type for CSS variable injection
- Update builtinThemes and themePresets to store CoreThemeColors
- Add backward-compatible parsing for legacy 19-token format in Nostr
  events, encrypted settings, and localStorage
- Simplify ThemeBuilderPage: remove Surface/UI color sections, just 4
  color pickers with auto-derivation always on
- Update all consumers: ThemeSelector, ScopedTheme, ThemeUpdateCard,
  MobileDrawer, LeftSidebar, ProfilePage, InitialSyncGate, etc.
2026-02-25 22:46:27 -06:00
Chad Curtis a2f0397c0c Scale down adaptive icon foreground to 70% for proper safe-zone fit 2026-02-25 21:28:01 -06:00
Mary Kate Fain b8d7d8a730 Redesign sidebar navigation with section grouping, customization, and mobile consistency
- Desktop: Remove redundant Home/Search nav items (logo serves as Home, inline
  search covers both quick lookup and full search page navigation)
- Add visual section grouping with labeled separators (Explore, You, Settings)
- Replace ugly dashed 'Add' button with subtle 'More...' inline link
- Add edit mode with drag-and-drop reordering (@dnd-kit) and remove buttons
  for content-type items in the Explore section
- Hover-to-remove on desktop content-type items outside edit mode
- Mobile: Replace avatar menu trigger with standard hamburger icon
- Mobile: Add search icon to top bar right side
- Mobile: Redesign bottom nav as 4-tab layout (Home, Explore, Notifications, You)
- Mobile: Explore tab opens bottom sheet with content type links (vaul Drawer)
- Mobile drawer: Replace profile header with logo, restructure to match desktop
  sections, add 'Manage...' link for settings, remove redundant Profile link
- Add sidebarOrder to AppConfig for persisting custom item order
- Extend useFeedSettings hook with orderedRoutes, addToSidebar, removeFromSidebar
2026-02-25 08:54:37 -06:00
Alex Gleason 7a85ec73ed Refactor theme system: separate builtin themes from custom presets
Restructure the theme architecture so 'light', 'dark', and 'system' are
builtin themes with build-time colors (customizable by self-hosters),
while 'black', 'pink', and future themes become presets that apply to a
single 'custom' theme slot.

Key changes:
- Theme type is now 'light' | 'dark' | 'system' | 'custom'
- builtinThemes (light/dark) and themePresets (black/pink/etc.) are
  separate maps in themes.ts
- AppConfig gains optional customTheme (ThemeTokens) field
- useTheme exposes applyCustomTheme(tokens) for applying presets
- Custom theme tokens sync across devices via encrypted settings
- Backward compat: legacy 'black'/'pink' values in localStorage and
  encrypted settings auto-migrate to custom + preset tokens
- All UI surfaces updated: ThemeSelector, LeftSidebar dropdown,
  MobileDrawer cycle, and onboarding ThemeStep
2026-02-24 21:46:28 -06:00
Chad Curtis 42a9535761 fix: remove lazy loading to prevent endless spinner on direct event load
The endless spinner issue was caused by lazy loading pages without a Suspense
fallback. When users navigated to nevent URLs or other NIP-19 identifiers, the
Suspense boundary had no fallback, causing a blank screen or stuck preloader.

Changes:
- Removed all lazy() imports from AppRouter
- Removed Suspense boundary (no longer needed without lazy loading)
- All pages now load eagerly for instant rendering
- Kept the HexIdentifierPage loading skeleton fix from previous commit

This ensures users see immediate visual feedback when loading any page,
especially when navigating directly to event URLs via nevent identifiers.
2026-02-24 23:48:09 +00:00
Chad Curtis b02b2a9e56 Rebrand Android app icons to Ditto logo with purple background 2026-02-24 01:03:53 -06:00
Alex Gleason 8febb405e5 Use imeta dim/blurhash for media placeholders before load
- Parse NIP-94 dim and blurhash fields in parseImetaMap (NoteCard + PostDetailPage)
- ImageGallery/GridImage: use dim for correct aspect-ratio skeleton sizing; render Blurhash canvas placeholder when available
- VideoPlayer: set aspect-ratio container from dim; show Blurhash canvas before first frame/poster loads
- Install react-blurhash (+ blurhash) for canvas rendering
2026-02-23 22:58:56 -06:00
Alex Gleason 5986a13639 Simplify client tag (no fake names) 2026-02-23 16:21:57 -06:00
Mary Kate Fain 5a569c3ddd Remove floating Join button on mobile when logged out
The FloatingComposeButton now returns null for logged-out users,
removing the floating Join CTA from mobile. The topbar Join and
other login CTAs are unchanged.
2026-02-23 14:16:52 -06:00
Alex Gleason cc74443010 Render DittoLogo using CSS mask with primary color 2026-02-23 13:10:47 -06:00
Mary Kate Fain c046e33f6b Replace hardcoded emoji picker with emoji-mart for full emoji support 2026-02-23 12:05:21 -06:00
Alex Gleason 1f035f4a6e Rename Mew to Ditto across entire codebase
- Update all branding: titles, meta tags, OG tags, manifest
- Rename MewLogo component to DittoLogo
- Update Capacitor config: appId to pub.ditto.app, hostname to ditto.pub
- Migrate Android Java package from com.mew.app to pub.ditto.app
- Rename MewNotificationPlugin to DittoNotificationPlugin
- Update all localStorage keys from mew: to ditto: prefix
- Update Nostr encrypted settings d-tag from mew-metadata to ditto-metadata
- Update all page titles, zap comments, and UI strings
- Rename ic_stat_mew.xml drawable to ic_stat_ditto.xml
- Update build script references (mew.apk -> ditto.apk)
- Update all domain references (mew.shakespeare.wtf -> ditto.pub)
2026-02-23 11:50:00 -06:00
Chad Curtis 79d366b240 Add virtual gamepad controls and fullscreen toggle for webxdc games 2026-02-23 01:17:35 -06:00
Alex Gleason 75585b2c42 Remove nostr-wasm 2026-02-22 18:05:36 -06:00
Chad Curtis e459583a08 Remove unused pubkey prop from ProfileRightSidebar 2026-02-21 23:37:34 -06:00
Alex Gleason 77f699acc2 Verify events with nostr-wasm 2026-02-21 21:45:39 -06:00
Alex Gleason 408ccc72e7 Upgrade Nostrify 2026-02-21 21:15:06 -06:00
Alex Gleason e0932b38d7 Add NostrBatcher to automatically batch Nostr queries
NostrBatcher is a transparent proxy that wraps NPool and intercepts
.query() calls. When it detects a batchable single-item filter pattern,
the request is held for a microtask. If more queries with the same
pattern arrive in the same frame, they're combined into one REQ.

Client code doesn't need to know batching exists -- it calls
nostr.query() as usual. The proxy is provided as the 'nostr' object
in NostrContext, so all existing hooks get automatic batching.

Batchable patterns:
- { kinds: [0], authors: [pubkey] } -> profiles
- { ids: [id] } -> events by ID
- { kinds: [7], authors: [user], '#e': [id] } -> reactions
- { kinds: [k], authors: [a], '#d': [d] } -> NIP-85 stats, etc.
- { kinds: [...], '#e': [id] } -> interaction events (zaps, etc.)
- Multi-filter arrays where all filters reference the same #e/#q ID

Also removes manual pre-caching from useFeed (fetchAndCacheAuthors,
fetchAndCacheEventStats) which is no longer needed, and fixes
useComments queryKey instability.
2026-02-21 20:00:07 -06:00
Chad Curtis 47e89f52d0 package-lock 2026-02-21 16:58:40 -06:00
Alex Gleason cfb5659020 Replace DomainFavicon with ExternalFavicon using configurable favicon URL template
The old DomainFavicon component had a multi-step fallback chain (HTML scraping,
direct URL guessing, then the configured provider) which meant the configurable
setting was almost never reached. The new ExternalFavicon component uses the
configured favicon URL template directly via RFC 6570 URI templates.

- Rename config field faviconProvider -> faviconUrl
- Add faviconUrl() utility with uri-templates for RFC 6570 support
- Remove local Favicon component from ProfileRightSidebar
- Update all consumers to use ExternalFavicon
2026-02-21 15:14:30 -06:00
Alex Gleason 749900f853 Extract webxdc name and icon from .xdc manifest, display in embed card
- Add webxdcMeta.ts utility to extract name from manifest.toml and
  icon (icon.png/icon.jpg) from the .xdc ZIP using fflate
- Upload extracted icon to Blossom during file attach
- Add webxdc_name and webxdc_icon properties to imeta tags
- Parse webxdc_name/webxdc_icon in NoteCard and PostDetailPage
- Show app icon and name in WebxdcEmbed launch card, remove filename
  and 'Stateful · shared session' text
2026-02-21 12:15:26 -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
Chad Curtis f36c9a67b5 Add markdown rendering for articles (kind 30023)
- Create ArticleContent component using react-markdown + rehype-sanitize
- Enable @tailwindcss/typography plugin for prose styling
- NoteCard shows article preview (title, image, summary)
- PostDetailPage renders full markdown article with prose typography
- Both views support header images and hashtag links
2026-02-21 01:13:51 -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
Chad Curtis 64726d2cf7 Add local WebSocket notification polling and Mew splash/notification icons
- Implement Signal-like local-only notifications via direct WebSocket relay polling
- Poll every 60s foreground, 15min background, no external push server
- Resolve NIP-05 display names for notification body (e.g. 'alice@nostr.com reacted to your post')
- Add Capacitor LocalNotifications plugin with POST_NOTIFICATIONS permission
- Replace default Capacitor splash with Mew logo PNG on dark background using Android 12 Theme.SplashScreen
- Add ic_stat_mew vector drawable for notification small icon
- Regenerate splash PNGs with #14161f background
2026-02-19 10:40:38 -06:00
Chad Curtis a293128176 Add mobile safe area support for status bar
- Install @capacitor/app and @capacitor/status-bar as dependencies
- Initialize StatusBar in App.tsx with dark style and overlay mode
- Add safe-area-top utility class to index.css
- Apply safe-area-top to MobileTopBar component
- Apply safe-area-top to toast notifications on mobile
- Ensures content is not hidden behind device notches/status bars
2026-02-19 06:31:18 -06:00
Chad Curtis 2f02e65ab6 Add Android Capacitor build system
- Install Capacitor dependencies (@capacitor/cli, @capacitor/core, @capacitor/android, @capacitor/app, @capacitor/status-bar, sharp)
- Create capacitor.config.ts with app configuration
- Update .gitignore to exclude Android build outputs and keystore files
- Generate icon-512.png from logo.svg
- Add scripts for icon generation, APK building, and keystore creation
- Initialize Capacitor Android platform
- Configure build.gradle with signing support
- Generate Android app icons in all required densities
- Add npm scripts: 'icons' and 'build:apk'
2026-02-19 06:18:02 -06:00
shakespeare.diy bdf189481e Revert to e693589: Increase top padding for search inputs from pt-4 to pt-5
This reverts the codebase back to the state at commit e693589.

Reverted 1 commit(s):
- 052aca5: Add support for Articles and Recipes (kind 30023)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 06:02:49 -06:00
shakespeare.diy 052aca55cb Add support for Articles and Recipes (kind 30023)
- Added ArticleCard component for displaying long-form content in feeds
- Added ArticleDetail component with markdown rendering for article detail pages
- Created ArticlesFeedPage with optional tag filtering for recipes
- Added /articles and /recipes routes
- Updated PostDetailPage to use ArticleDetail for kind 30023 events
- Added Articles and Recipes to settings toggles (sidebar & feed visibility)
- Integrated articles into Feed component - kind 30023 events now use ArticleCard
- Added react-markdown and remark-gfm for proper markdown rendering
- Articles and Recipes now visible by default in sidebar navigation

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 05:59:37 -06:00