Commit Graph

45 Commits

Author SHA1 Message Date
filemon e3412fac46 Merge branch 'main' into feat-blobbi 2026-03-24 12:20:40 -03:00
Lemon 6e9c971dd0 Extend drawer background image into the vertical arc
Moves the arc from the generic Sheet component into MobileDrawer
so it can inherit the theme background image. Uses clip-path
ellipse on an HTML div instead of SVG fill, with the same
bg-background/70 overlay applied when a background image is set.
2026-03-22 23:33:06 -07:00
Lemon cf8e60aaa1 Make drawer arc more dramatic and match sidebar background
Increases the arc width from 20px to 36px with a deeper curve,
and changes fill from background/80 to solid background to
match the drawer's actual background color.
2026-03-22 23:33:06 -07:00
Lemon 893a7dfb8a Add vertical semi-ellipse arc to left-side drawer edge
Removes the flat right border from the left sheet variant and
adds an SVG arc that curves outward along the right edge,
matching the curved styling used on the horizontal nav bars.
2026-03-22 23:33:06 -07:00
Lemon a90191ac61 Add decorative semi-ellipse arc to right edge of mobile drawer
Replaces the flat right border with an SVG arc that curves
outward along the full height of the drawer, matching the
curved design language used on the nav bars.
2026-03-22 23:33:06 -07:00
filemon 96356eb804 fix: render Blobbi masks to PNG via canvas for reliable CSS mask-image
CSS mask-image with SVG data URLs doesn't work reliably for complex SVGs
with transforms in some browsers. The picker preview works because it renders
inline SVG directly, but the avatar mask-image was failing for shapes like
droppi, flammi, leafy, mushie, owli, rocky, and rosey.

Changes:
- Rewrite getBlobbiMaskUrl() to render SVG to canvas and export PNG
- Use Blob URL for SVG loading (more reliable than data URL)
- Add async mask generation with proper caching and deduplication
- Update Avatar component to load masks asynchronously via useEffect
- Add getAvatarMaskUrlAsync() for async mask URL retrieval

The picker preview continues to use inline SVG (which works fine),
while the avatar mask now uses rasterized PNG (which works everywhere).
2026-03-18 10:36:27 -03:00
filemon d962d7952b fix: remove hardcoded white stroke from catti tail and fix avatar mask updates
1. Remove stroke="white" from catti shape - let the styling apply colors
2. Fix Avatar component to properly update mask when shape changes:
   - Compute maskUrl outside useMemo so it's always fresh
   - Use maskUrl directly in dependencies instead of shape string
   - This ensures the mask updates immediately when selecting a new shape
2026-03-18 10:21:39 -03:00
filemon a7c29c4a85 feat: add Blobbi shapes as avatar masks
New feature allowing users to select Blobbi character silhouettes as
avatar masks, in addition to existing emoji shapes.

New files:
- src/lib/blobbiShapes.ts: Shape definitions with SVG paths for all
  Blobbi forms (egg, baby, 16 adults)
- src/components/BlobbiShapePicker.tsx: Grid picker with category tabs

Changes:
- Extended avatarShape.ts to support 'blobbi:' prefixed shape values
- Added getAvatarMaskUrl() unified function for both shape types
- Updated Avatar component to render Blobbi masks
- Added tabbed UI in ProfileCard (Emoji/Blobbi tabs)
- Renamed emojiAvatarBorderStyle to shapedAvatarBorderStyle

Shape format: 'blobbi:<id>' (e.g., 'blobbi:baby', 'blobbi:catti')
Stored in kind-0 metadata as 'shape' property, same as emojis.

Available shapes:
- Egg (simple egg silhouette)
- Baby Blobbi (water droplet)
- Adults: catti, owli, froggi, droppi, flammi, crysti, cloudi,
  mushie, starri, pandi, cacti, breezy, leafy, rocky, rosey, bloomi
2026-03-17 12:32:46 -03:00
Alex Gleason 10bb16abfb Clean up avatar shape code: remove magic strings, type casts, and inconsistencies
- avatar.tsx: consolidate to single isEmojiShape boolean, fix AvatarFallback using same logic as Avatar
- avatarShape.ts: accept NostrMetadata directly in getAvatarShape (no cast needed)
- Remove 'as Record<string, unknown>' casts from all ~50 call sites
- Replace 'circle' magic string with empty string in form defaults and parseShape
- Use isValidAvatarShape instead of string comparison in save logic
- ProfileCard: extract IIFE overlay style into useMemo, use isEmojiShape throughout
2026-03-13 21:14:03 -05:00
Alex Gleason b661e9be9b Remove predefined shape dead code: delete AvatarShapePicker, UserAvatar, and geometric shape utilities 2026-03-13 20:57:09 -05:00
Alex Gleason 55e8075542 Support emoji as avatar shape: use any emoji as a mask over the avatar
Extend the kind-0 'shape' field to accept any emoji string in addition to
the predefined geometric shapes (circle, triangle, hexagon, star, etc.).
When an emoji is chosen, its native OS glyph is rendered onto a canvas,
the alpha channel extracted as a PNG mask, and applied via CSS mask-image.

Implementation:
- Widen AvatarShape type to accept emoji strings alongside predefined names
- isEmoji() detects any short non-ASCII string (avoids fragile Unicode regex)
- getEmojiMaskUrl() renders emoji at 512px, crops to tight bounding box
  (with alpha threshold to ignore shadows/glows), squares the crop, scales
  to 256px output, converts to white+alpha mask PNG. Cached per emoji.
- Avatar component applies mask-image for emoji, clip-path for geometric
- ProfileCard uses ring-4 instead of border-4 for emoji shapes to avoid
  mask/content misalignment (border is inside the element; ring is outside)
- AvatarShapePicker adds emoji-mart picker in a popover
- Form schemas use z.string() to accommodate both predefined and emoji values
- NIP.md documents emoji shape support
2026-03-13 20:27:14 -05:00
Alex Gleason 0781b1a87c Merge origin/main and re-apply avatar shape changes to conflicted files 2026-03-13 17:23:30 -05:00
Alex Gleason 3b79b384e5 Add avatar shapes: users can set a shape (circle, triangle, hexagon, star, etc.) for their avatar via kind 0 metadata
- New 'shape' property on kind 0 profile metadata with 7 predefined shapes:
  circle, triangle, inverted-triangle, hexagon, star, inverted-star, hexagram
- Avatar component updated with clip-path support for non-circle shapes
- Visual shape picker added to both EditProfileForm and ProfileSettings
- Shape applied across all 49 avatar render sites in the app
- New UserAvatar wrapper component for future simplified avatar rendering
- Unknown shape values gracefully fall back to circle (forward compatible)
2026-03-13 16:14:40 -05:00
Lemon 7e19a7f773 New Theme Modal Mobile Fixes 2026-03-13 20:33:23 +00:00
Mary Kate Fain b60b2c131f Add help tips to more UI surfaces and fix search filter dropdown z-index
- Add 'How do I report harmful content?' help tip to Muted Content and Sensitive Content sections
- Add 'For You page' help tip to Home Feed settings header
- Move wallet help tip from NWC section to Wallet page header
- Add 'What are zaps?' help tip to Zap dialog title
- Add 'Mastodon/Bluesky comparison' help tip to Platform filter in search
- Fix Select dropdown z-index (250->270) so dropdowns render above filter popover (260)
2026-03-07 20:14:17 -06:00
Mary Kate Fain b045fb53b9 Fix color pickers and font selector rendering behind theme edit dialog 2026-03-07 16:57:31 -06:00
Alex Gleason 60e3ead6ed Merge branch 'main' of gitlab.com:soapbox-pub/ditto 2026-03-07 11:52:48 -06:00
Alex Gleason bed84c6285 Fix iOS Safari auto-zoom on input focus by ensuring 16px minimum font size on mobile 2026-03-07 11:42:54 -06:00
Lemon 5a0bc346b7 fix: make emoji/GIF picker dialog dismiss on iOS tap-outside
- Raised dialog z-index from z-[150] to z-[250] so the overlay sits above
  CommentsSheet's backdrop (z-[200]) and receives touch events
- Removed stopPropagation from DialogOverlay/DialogContent onClick handlers
  which was preventing Radix DismissableLayer's deferred click listener from
  reaching document on iOS Safari

On iOS touch, Radix registers a one-time click listener on document after
pointerdown. The stopPropagation was intercepting that click before it could
reach document, so the dismiss callback never fired. Z-index stacking now
handles isolation between the dialog and the CommentsSheet backdrop.
2026-03-06 23:16:30 -08:00
Lemon 54c4d7e47c Fix GIF picker scroll inside dialogs by portaling into modal container
Radix Dialog's RemoveScroll blocks wheel events on elements outside the
Dialog's DOM tree. The GIF picker Popover was portaling to document.body,
placing it outside the RemoveScroll boundary. Trackpad scrolling was
blocked while scrollbar dragging still worked.

Added PortalContainerContext so PopoverContent can portal into the modal
element instead of document.body when rendered inside a dialog/modal.
2026-03-06 23:16:30 -08:00
Mary Kate Fain ff3d99f205 Fix search filter dropdown z-index rendering behind popover
SelectContent used z-50 while PopoverContent used z-[200]. Both are
portaled to the body, so when a Select inside a Popover is opened,
the Select dropdown rendered behind the Popover panel. Raised
SelectContent to z-[250] so it always appears above popovers.

Closes #55
2026-03-04 23:56:04 -06:00
Derek Ross 3eaee4d560 fix: emoji/gif picker hidden behind modal dialogs
Bump z-index from z-50 to z-[200] on PopoverContent, TooltipContent,
and DropdownMenuContent so they render above dialog overlays (z-[150]).
2026-03-03 11:20:09 -05:00
Chad Curtis e82c4642c9 Portal HoverCardContent to document body so it escapes overflow-hidden containers 2026-03-03 05:42:08 -06:00
Chad Curtis 64c9936014 fix vine comments and toast visibility
- ComposeBox: invalidate the correct 'event-comments' cache key after
  posting a NIP-22 comment so CommentsSheet refreshes immediately
- toast: raise z-index to 300 so it renders above the CommentsSheet
  backdrop blur (which sits at z-200)
2026-03-03 00:45:31 -06:00
Chad Curtis 771b3df9d8 fix lightbox: stable image keys prevent reload, dialog z-index above lightbox, media tab auto-open 2026-03-02 23:56:06 -06:00
Alex Gleason dd2f7af3d3 Don't put black overlay over color picker items 2026-02-26 16:22:39 -06:00
Alex Gleason 1a17a3a068 Show pencil icon on color swatches always, not just on hover 2026-02-26 11:59:13 -06:00
Alex Gleason 970c0119b1 Replace hint text with pencil overlay on color swatches for intuitive editability 2026-02-26 11:53:59 -06:00
Alex Gleason 1c8761440c Improve theme color editor discoverability with circle swatches and hint text 2026-02-26 11:51:15 -06:00
Chad Curtis 01e190476b fix: theme page mobile layout, remove white from quick theme toggle, use SwatchBook icon for theme nav item 2026-02-26 06:02:39 -06:00
Chad Curtis 68f0dd742a Refactor mobile nav with shared sidebar components and improved drawer UX 2026-02-26 03:51:33 -06:00
Mary Kate Fain 69ec0e4c8d Merge sidebar-redesign: new mobile nav tabs, hamburger drawer, onboarding theme presets 2026-02-25 19:48:55 -06:00
Mary Kate Fain 757f417aae Merge remote-tracking branch 'origin/main' into add-custom-theme-editor-ui 2026-02-25 13:50:58 -06:00
Mary Kate Fain 80b8b97858 Add custom theme builder UI with color picker, auto-derive, and live preview 2026-02-25 13:27:27 -06:00
Mary Kate Fain fa422c21ee Fix Explore drawer not closing on overlay tap
Remove stopPropagation from DrawerOverlay onClick handler which was
blocking vaul's dismiss-on-overlay-click behavior on touch devices.
2026-02-25 09:37:53 -06:00
Alex Gleason ee08760a93 Remove unused sidebar CSS variables, Tailwind mappings, and shadcn sidebar components 2026-02-24 23:13:00 -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 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 49c493d2fa Fix safe area padding in mobile drawer
- 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
2026-02-19 07:54:34 -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
shakespeare.diy 1001ea8161 Improve search filters readability with larger inputs and icons
- 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>
2026-02-19 05:46:30 -06:00
shakespeare.diy 45d1f878f4 Prevent dialog and drawer overlay clicks from bubbling to parent elements
Add stopPropagation to dialog and drawer overlay/content click handlers to prevent clicks on modals from triggering click events on underlying elements like NoteCard.

This fixes the issue where clicking outside the zap modal would still register as a note click and navigate to the post detail page.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-18 17:19:04 -06:00
shakespeare.diy f0728d1737 Implement remote signer login option with nostrconnect
- Add nostrconnect method to useLoginActions for NIP-46 client-initiated connections
- Add helper functions generateNostrConnectParams and generateNostrConnectURI
- Create QRCodeCanvas component wrapper for displaying QR codes
- Update LoginDialog to support remote signer login with QR code scanning
- Add "Use remote signer" button when extension is available
- Display QR code on desktop, "Open Signer App" button on mobile
- Support manual bunker URI input as fallback option
- Add connection retry on error
- Use existing useIsMobile hook for responsive behavior

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-18 04:31:51 -06:00
shakespeare.diy 858ec3beaa Add post preview to More menu, blur modal backdrops, polish compose modal
- NoteMoreMenu now shows a compact post preview at the top (avatar,
  author name, timestamp, and 3-line-clamped content) before menu items
- Dialog overlay updated globally: bg-black/60 + backdrop-blur-sm for a
  frosted-glass effect behind all modals
- FloatingComposeButton modal reworked to match the same presentation
  pattern: rounded-2xl, hidden default close button replaced with a
  centered header (X / "New post" title), separator, compose area

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-16 17:50:46 -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