Commit Graph

581 Commits

Author SHA1 Message Date
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 bac31a5b6d Add profile theme sharing: publish kind 30203, scoped themes on profiles, feed cards, and content settings 2026-02-25 13:49:55 -06:00
Alex Gleason aaea5523b3 Merge branch 'main' of gitlab.com:soapbox-pub/ditto-mew 2026-02-25 13:47:14 -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 f342a266df Add drag-and-drop edit mode to mobile drawer Explore section
Replace the settings redirect with a full inline edit experience matching
the desktop sidebar:

- Pencil icon in Explore section header toggles edit mode (Done to exit)
- Edit mode shows drag handles (GripVertical) and remove buttons (X) on
  each item, with touch-friendly DnD via @dnd-kit TouchSensor (150ms
  delay to distinguish scroll from drag)
- Hidden items appear below with + buttons to add them back
- Normal mode shows navigation links as before
- Edit state resets when the drawer closes
- Consistent UX between desktop sidebar and mobile drawer
2026-02-25 09:30:50 -06:00
Mary Kate Fain 5eb6991f94 Fix right sidebar separators: use full opacity bg-border for visibility 2026-02-25 09:25:41 -06:00
Mary Kate Fain 0fdc24566c Move search bar to right sidebar at xl, add section separators, fix mobile edit button
- Search bar now appears in right sidebar at xl (1280px+) and stays in
  left sidebar at sidebar-to-xl range (900-1279px) via xl:hidden class
- Add horizontal separator lines between right sidebar sections (Trends,
  Hot Posts, New Accounts) for visual consistency with left sidebar
- Mobile drawer: replace 'Edit' text button at end of explore list with
  pencil icon inline in the Explore section header, matching the desktop
  sidebar pattern
2026-02-25 09:24:02 -06:00
Mary Kate Fain ebcae8ba58 Refine sidebar nav: bell in logo row, Feed/Trends built-ins, Settings under You
- Move notifications bell icon to top-right of logo row (compact, always
  visible when logged in) instead of a full nav item
- Add Feed and Trends as built-in Explore items that can be reordered and
  removed alongside content-type items (Feed links to /, Trends to
  /search?tab=trends)
- Default sidebar order for fresh installs: Feed, Trends, then enabled
  content types
- Move Settings into the 'You' section when logged in; standalone at
  bottom with separator when logged out
- Remove hover-to-remove X button on desktop (edit mode only now)
- Mobile Explore bottom sheet and drawer now include Feed and Trends
- Change mobile drawer 'Manage...' link text to 'Edit'
- Add dismissible prop to Explore bottom sheet Drawer for explicit
  close-on-overlay-tap behavior
- Extend useFeedSettings with built-in item support (__feed, __trends),
  hiddenItems list, and unified add/remove handling for both built-ins
  and extra-kind routes
2026-02-25 09:13:35 -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
Chad Curtis ea5ce58c7f Add info modal with blurb and external site links to all extra kind pages 2026-02-24 23:34:51 -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 de8211d27a Remove zap drawer; use Dialog modal on all screen sizes 2026-02-24 22:56:47 -06:00
Chad Curtis 6f583fd647 Probe image dimensions on load when dim tag is missing; hide media behind Read more truncation 2026-02-24 22:54:18 -06:00
Chad Curtis 582f92b208 Increase FAB plus icon stroke width 2026-02-24 22:41:59 -06:00
Alex Gleason 67f0dc32e7 Merge branch 'main' of gitlab.com:soapbox-pub/ditto-mew
# Conflicts:
#	src/components/AppProvider.tsx
#	src/hooks/useTheme.ts
2026-02-24 22:09:09 -06:00
Alex Gleason 72cf6bc6e8 Add extended theme presets (settings-only) and featured flag
Add 5 new presets: Midnight, Forest, Lavender, Ocean, and Sunset. These
appear only on the /settings/appearance page. The sidebar dropdown and
mobile drawer cycle continue to show only featured presets (Black and
Pink). Active preset detection searches all presets so the label and
emoji display correctly even for non-featured presets.
2026-02-24 22:03:32 -06:00
Chad Curtis 2e6beb3c23 Fix settings toggles being overwritten by stale sync
- Advance lastSyncedTimestamp when skipping due to recentlyWritten() so the
  same snapshot cannot be re-applied once the write window expires
- Use pendingSettings ref in useEncryptedSettings to accumulate rapid mutations
  instead of reading stale cache data
- Fix ContentSettings handleToggle to not merge against stale nostrSettings
2026-02-24 22:01:33 -06:00
Alex Gleason 5b23d0a656 Simplify theme dropdown 'More...' link: remove cog icon 2026-02-24 21:58:19 -06:00
Alex Gleason d6803cba04 Add 'More' link to theme dropdown and remove title
Navigate to /settings/appearance from the theme picker dropdown.
Drop the 'Choose theme' label to keep it compact.
2026-02-24 21:58:05 -06:00
Alex Gleason 6328c6f6ae Remove builtin/custom labels from theme UI and add preset emojis
Drop the 'Builtin' and 'Custom' section headers from the ThemeSelector
grid and the LeftSidebar dropdown so the distinction is invisible to
users. Add emoji metadata to theme presets (ThemePreset interface) and
display them in the sidebar dropdown and mobile drawer cycle button
instead of the generic Palette icon.
2026-02-24 21:54:44 -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 3c91952e5c Fix theme flicker by using useLayoutEffect for CSS var injection
useEffect fires after paint, causing a one-frame flash of old colors when switching themes. useLayoutEffect fires synchronously before paint, eliminating the flicker. Also keep document.documentElement.className in sync with the active theme.
2026-02-24 21:36:30 -06:00
Alex Gleason 02697385eb Merge branch 'main' of gitlab.com:soapbox-pub/ditto-mew 2026-02-24 21:10:14 -06:00
Chad Curtis dad8dc5040 Remove duplicate border-l from live stream chat sidebar 2026-02-24 20:57:11 -06:00
Chad Curtis 66a0388c0a Move column borders to MainLayout wrapper to fix top border gap
Borders were on each page's <main> element, causing them to start below the top of the column. Moving sidebar:border-l and xl:border-r to the wrapper div in MainLayout ensures borders span the full column height from the very top.
2026-02-24 20:57:11 -06:00
Chad Curtis 984bada0a4 Add middle-click to open posts in new tab, fix word breaking in compose box
- Add useOpenPost hook to centralize left/middle-click navigation logic
- Apply middle-click (aux click) support to NoteCard, hot posts sidebar, and streams feed
- Fix ComposeBox textarea using break-all instead of break-words
2026-02-24 20:57:11 -06:00
Alex Gleason b42ca9434a Add 'system' theme option that follows OS prefers-color-scheme 2026-02-24 20:56:17 -06:00
Alex Gleason fb2e2e6678 Add pointer cursor and hover underline to 'Replying to' label 2026-02-24 20:47:41 -06:00
Alex Gleason d4f2f05090 Scope reply hover card trigger to only the 'Replying to' text
The HoverCard trigger now wraps only the 'Replying to' label, not the
@username mentions. This prevents the post preview hover card from
conflicting with the profile hover cards on usernames.
2026-02-24 20:46:42 -06:00
Alex Gleason 64768ffafe Disable nested hover cards inside reply context preview
ProfileHoverCards on avatar, name, and @mentions inside EmbeddedNote
are now suppressed when rendered within the reply context hover card,
preventing nested hover card nesting.
2026-02-24 20:43:14 -06:00
Alex Gleason eb51f24d48 Add hover card preview of parent post on 'Replying to' line
Hovering over the 'Replying to @user' context on reply posts now shows
an embedded preview of the parent event, making it easy to see what is
being replied to without navigating away.

- Extract getParentEventId to shared utility (src/lib/nostrEvents.ts)
- Pass parentEventId from NoteCard to ReplyContext
- Wrap the reply context line in a HoverCard with EmbeddedNote preview
2026-02-24 20:40:28 -06:00
Chad Curtis e8fe66f91c Fix settings toggles resetting due to sync race conditions
Three bugs caused settings toggles to get stuck or reset:

1. useEncryptedSettings: onSuccess was updating the parsedSettings cache
   under the old event ID, causing NostrSync to re-apply the stale remote
   event when the new one arrived with a different ID. Fixed by using the
   signed event's ID for both cache entries.

2. ContentTypeRow/SubKindRow: handleToggle was building the Nostr payload
   from the local React feedSettings state, which lags behind on rapid
   successive toggles. Fixed by merging against the Nostr-cached settings
   (nostrSettings?.feedSettings) as the base instead.

3. NostrSync: lastSyncedTimestamp ref reset to 0 on every page reload, so
   the 10-second recentlyWritten() guard was the only protection against
   stale relay events overwriting local changes. Fixed by seeding the ref
   with the current remote lastSync on first settings load, skipping
   application of any event that isn't strictly newer than what was
   already in the cache.
2026-02-24 20:24:43 -06:00
Alex Gleason 6d4714f2c9 Merge branch 'settings-reorganize' into 'main'
Reorganize Settings into menu-based navigation with sub-pages

See merge request soapbox-pub/ditto-mew!13
2026-02-25 02:02:31 +00:00
Mary Kate Fain 2ac9960b31 Reorganize Settings into menu-based navigation with sub-pages
Replace the single tabbed Settings page with a landing menu that navigates
to dedicated sub-pages, following the Agora pattern:

- Settings landing: card-based menu with icons and descriptions
- Profile: wraps EditProfileForm (auth-gated)
- Appearance: Theme sub-tab with visual theme selector (light/dark/black/pink
  + custom placeholder) and Content sub-tab with existing content settings
- Wallet: dedicated page for NWC wallet management (auth-gated)
- Notifications: push notification enable/disable toggle (auth-gated)
- Advanced: network relays, stats source, and system settings (wallet
  section removed since it has its own page now)
2026-02-24 19:42:40 -06:00
Alex Gleason e66222a7fc Remove descriptions from sidebar Add dropdown, keep only names 2026-02-24 19:31:59 -06:00
Alex Gleason 4c10c954c5 Use bottom-20 for mobile FAB position 2026-02-24 19:27:45 -06:00
Alex Gleason 7401022b05 Add spacing-22 to Tailwind config and use bottom-22 for mobile FAB 2026-02-24 19:27:34 -06:00
Alex Gleason 3b5f53eaa8 Fix FAB mobile position: use bottom-24 (valid Tailwind v3 spacing) 2026-02-24 19:26:10 -06:00
Alex Gleason 9d6eea7869 Fix FAB position on mobile to sit above bottom navigation bar 2026-02-24 19:25:25 -06:00
Alex Gleason 4fa5e391c7 Add floating compose button (+) to center column on all feed pages
- FloatingComposeButton accepts kind prop: kind=1 opens compose dialog, others show 'Coming soon'
- FAB positioned sticky bottom-right within center column (visible on all screen sizes)
- Center column gets bottom padding (pb-24) to account for FAB obstruction
- LayoutContext extended with fabKind option passed through layout system
- Home feed uses kind=1, KindFeedPage passes its kind, StreamsFeedPage uses 30311
2026-02-24 19:11:42 -06:00
Alex Gleason b5e813917c Replace Compose button with Add button to enable sidebar items from settings/content 2026-02-24 19:00:54 -06:00
Alex Gleason fb2e5cee91 Add Divine relay when looking up addressable short videos 2026-02-24 17:14:44 -06:00
Alex Gleason 386a2fec65 Use kind 16 (generic repost) for reposting non-kind-1 events
Per NIP-18, kind 6 is specifically for reposting kind 1 text notes,
while kind 16 should be used for all other event types. Added
isRepostKind() and getRepostKind() helpers to centralize the logic,
and updated all repost-related code paths: publishing, deletion,
status checks, interactions, feed processing, notifications, and
stream/search filtering.
2026-02-24 15:22:19 -06:00
Chad Curtis 1af6a45a77 Fix preloader flash and green logo on light/pink themes
Defer body inline style removal until CSS variables are injected by
useApplyTheme, preventing a one-frame flash of unstyled background.

Replace preloader logo <img> with CSS mask technique matching the React
DittoLogo component, so the logo uses the theme's primary color instead
of filter:invert() which turned purple into green.
2026-02-24 00:39:27 -06:00
Alex Gleason 805a35fea5 Add dim and blurhash to imeta tags for uploaded images
After a file uploads, decode it on a small canvas (64px wide) to
compute the natural dimensions (dim) and a 4x3 blurhash. Both are
injected into the NIP-94 tag array before storing in uploadedFileGroups,
so the published imeta tag includes them automatically.
2026-02-23 23:13:17 -06:00
Alex Gleason eabaaa3fd5 Fix VideoPlayer letterboxing when dim is known
When the container has an aspect-ratio from the dim tag, switch the
video to absolute inset-0 h-full to fill it cleanly. Fall back to
max-h-[70vh] object-cover for videos without dim data.
2026-02-23 23:08:32 -06:00
Alex Gleason fa7c141382 Add blurhash placeholders to profile Media widget
- Extract blurhash from imeta tags for all event kinds (non-kind-1
  via the first imeta tag; kind-1 by matching the URL against imeta)
- New MediaTile component renders Blurhash canvas before the image/video
  loads, falling back to a Skeleton when no blurhash is available
- Tile uses absolute positioning so the placeholder fills the square cell
2026-02-23 23:07:18 -06:00
Alex Gleason 15ae7c4735 Fix GridImage dim/blurhash placeholder sizing
- Move aspect-ratio and height constraints onto the button container so
  both placeholder and image can fill it with absolute inset-0
- Pass integer decode resolution to Blurhash and size the canvas via
  CSS width/height 100% instead of relying on string props
- Remove stale per-element skeletonStyle/heightStyle juggling
2026-02-23 23:02:41 -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 3a8903f8e0 Pass labelCreatedAt from useTrendingTags to useTagSparklines to avoid duplicate REQ 2026-02-23 21:51:20 -06:00