- Add safe area top padding to Sheet close button (X icon)
- Add safe area bottom padding to theme toggle section
- Ensures UI elements don't overlap with device notches/navigation bars
- Make headers sticky on all screen sizes (not just desktop)
- Add sticky positioning to settings tabs
- Add webkit-playsinline and x-webkit-airplay attributes for better mobile video support
- Added safe-area-top to user profile header in mobile drawer
- Prevents content from being clipped behind status bar in APK
- Only applies to logged-in state header
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Created top-mobile-bar utility class for sticky elements below mobile top bar
- Accounts for 48px bar height + safe-area-inset-top
- Updated Feed component tabs to use top-mobile-bar on mobile
- Updated NotificationsPage tabs to use top-mobile-bar on mobile
- Tabs now stick below the top bar instead of behind it
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Wrapped content in inner div to separate safe area padding from content height
- safe-area-top now adds padding to outer header
- Inner flex container maintains h-12 for actual content
- Prevents content from being pushed into status bar area
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Reduced text size from text-sm to text-xs
- Reduced padding from py-2.5 to py-2
- Reduced margin from mt-3 to mt-2
- Makes stats row take up less vertical space
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Removed Nip05Badge component usage in PostDetailPage
- Replaced with direct inline rendering like NoteCard does
- Ensures consistent truncation behavior across all views
- All NIP-05 displays now use the same DRY pattern
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Added min-w-0 and overflow-hidden to parent container
- Fixed Nip05Badge component to properly support truncation
- Made favicon shrink-0 to prevent it from being truncated
- Wrapped Nip05Badge in min-w-0 container in PostDetailPage
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Created getDisplayName utility to DRY up display name logic with automatic truncation
- Updated NoteCard and PostDetailPage to use getDisplayName utility
- Fixed top bar positioning in Capacitor APK with proper safe area insets
- Fixed FAB positioning to sit above bottom nav with safe area compensation
- Added safe-area-inset utilities for better mobile positioning control
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Added pr-2 to make truncation happen earlier
- Creates better visual balance with left padding
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- NIP-05 text, favicon, dot, and timestamp all on same line
- Only NIP-05 text truncates, favicon and timestamp never cut off
- Added whitespace-nowrap to timestamp
- Removed Nip05Badge component, using inline layout instead
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Brought back Nip05Badge component with favicon
- NIP-05 still truncates properly with overflow-hidden on parent
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Display name and NIP-05 on separate lines (matching Ditto)
- NIP-05 now truncates properly with overflow-hidden
- Added truncate to repost and treasure headers
- Removed favicon from inline NIP-05 display
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Added break-words and overflow-hidden to content containers
- Long URLs, mentions, and unbroken strings now wrap properly
- Applied fix to both regular note content and vine titles
- Prevents horizontal overflow breaking card layout
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Added timeout-based hover management for reaction quick menu
- Menu now closes smoothly when mouse leaves both button and menu
- 150ms delay allows user to move from button to menu seamlessly
- FAB now only appears on the feed page (Index)
- Added showFAB prop to MainLayout for conditional rendering
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Preview toggle now appears at top-right when in feed view
- Removed toggle from bottom toolbar
- Cleaner layout with toggle positioned above compose area
- Only shown when content has previewable elements
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Avatar now hidden when compact=true (mobile feed view)
- Removes leading space on mobile compose area
- Avatar still shows in expanded/modal views
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Moved Edit/Preview toggle from toolbar to modal header
- Added controlled preview mode to ComposeBox component
- Toggle now appears next to close button in modal header
- Added border-bottom to header for visual separation
- ComposeBox can be controlled externally or use internal state
- Fixes layout issues and improves UX in modal
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Added overflow-hidden to preview container to prevent content breaking out
- Added horizontal margins (mx-2) to Edit/Preview toggle for better spacing
- Increased button padding (px-3.5 py-1.5) for better click targets
- Fixes link preview cards overflowing to the right in modal
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Added onWheel event handler to stop propagation
- Fixes issue where aggressive scrolling in emoji picker scrolls the page
- Scroll events now stay contained within the emoji picker
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Clicking "..." now replaces quick menu with full emoji picker
- Removed nested Popover that was causing the menu to close
- Full picker stays open and functional within the same popover
- Simplified state management with showFullPicker boolean
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Created useEmojiUsage hook to track user's most-used emojis
- QuickReactMenu now shows user's top 6 emojis, falling back to defaults
- Default emojis: ❤️, 👍, 👎, 😂, 😮, 😢
- ReactionButton triggers menu on hover for faster access
- Menu aligns to start (left) to begin from the heart icon
- Emoji usage persists per user in localStorage
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Created QuickReactMenu component with horizontal emoji bar
- Quick access to 6 common emojis (❤️, 😂, 💯, 🔥, 👍, 📌)
- "..." button opens full EmojiPicker for more options
- Updated ReactionButton to use QuickReactMenu instead of full picker
- Matches Ditto UX: click shows quick react menu, ... reveals full picker
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- 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
- Change icon background from white (#ffffff) to dark theme (#14161f)
- Update capacitor.config.ts backgroundColor to match
- Update generate-icons.sh to use dark theme color
- Regenerate all Android icons with new background
- Prevents white-on-white icon appearance
- Check for ANDROID_HOME or ANDROID_SDK_ROOT environment variables
- Auto-create android/local.properties if missing
- Provide helpful error messages for SDK configuration
- Added new mew_logo_2.svg to public directory
- Updated MewLogo component to use SVG instead of PNG
- Updated index.html favicon references to use SVG format
- Updated manifest.webmanifest icon references to use SVG with 'any' size
- SVG provides better scalability and smaller file size (3.5KB vs 4.2KB PNG)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Added dynamic field array management with add/remove functionality
- Extended form schema to support custom fields array
- Parse existing fields from kind 0 event content
- Store fields in NIP-compliant format: [["label", "value"], ...]
- UI includes label/value input pairs with trash icon to remove
- Fields are properly saved and loaded from metadata
- Integrates with existing ProfileRightSidebar display
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Wrapped mute conversation, mention, mute user, and report options with !isOwnPost checks
- Only show these options when viewing someone else's post
- Pin to profile option remains available only on own posts
- Fixes issue where inappropriate moderation options were shown on user's own content
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
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>
- 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>
- Add icons to media type filters (Images, Videos, Vines)
- Add Languages icon to language filter
- Remove icons from "All media", "No media", and platform checkboxes
- Increase radio button and checkbox size from 16px to 18px
- Remove text-sm classes for better readability
- Increase icon sizes from 3.5px to 4px
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Use font-medium instead of font-semibold for cleaner hierarchy
- Restore original spacing (space-y-4, gap-3)
- Remove explicit text-foreground to let theme handle it naturally
- Keep consistent label spacing
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Changed from single toggle to dual checkboxes
- Users can select Nostr only, Mastodon only, or both platforms
- Nostr is checked by default, Mastodon unchecked by default
- Both checkboxes can be unchecked (shows no results)
- More flexible filtering with AND/OR logic
- Added 'Show Mastodon posts' toggle in search filters
- Detects Mastodon/ActivityPub bridge posts via proxy tag
- Posts with proxy tag containing 'activitypub' are filtered out by default
- Toggle allows users to include or exclude bridged posts from results
- Removed 'Show Post Details' option (redundant on detail page)
- Added 'Copy Event ID' to copy hex event ID
- Added 'Copy Event JSON' to copy full event as formatted JSON
- Replaced ArrowUpDown icon with FileJson for JSON copy option
- Re-enabled language and media search filters for initial query
- Added console logging to track initial batch fetch
- Initial query fetches 40 events with NIP-50 filters applied
- Streaming subscription then continues from relay.ditto.pub for new events
The root cause: NPool.req() aborts subscriptions 500ms after the first EOSE
due to eoseTimeout configuration. This is intended for queries but breaks
streaming subscriptions.
Solution: Use relay() directly for streaming instead of the pool. This
bypasses the pool's eoseTimeout logic and allows subscriptions to stay
open indefinitely after EOSE.
- Use nostr.relay('wss://relay.ditto.pub') for streaming subscription
- Keep using the pool for initial query (benefits from multi-relay speed)
- Added detailed logging to track subscription lifecycle
- Re-enabled search filters for initial query only
The search page was broken because it tried to use NIP-50 search filters
in the streaming subscription. Relays don't support streaming search queries
because search requires full-text indexing.
Changes:
- Split filters into initialFilter (with search) and streamFilter (kinds only)
- Initial query uses relay-level NIP-50 search extensions (language, media, video)
- Streaming subscription only filters by kinds
- Re-added client-side filtering for streaming events (search text, media type)
- Language filtering remains relay-level only (can't detect language client-side)
Now the search page correctly:
1. Fetches initial results using relay search filters
2. Streams new events by kind
3. Filters streaming events client-side as they arrive
- Add language filtering using NIP-50 language: extension
- Add media filtering using NIP-50 media: and video: extensions
- Move media filtering from client-side to relay-level for better performance
- Support filtering by images (media:true video:false), videos (video:true), or no media (media:false)
- Language filter supports all existing language options (en, es, fr, de, ja, zh, etc.)
- Filters are now applied at the relay level via search query extensions rather than client-side filtering