Commit Graph

4447 Commits

Author SHA1 Message Date
Chad Curtis ada87468cc Merge branch 'main' of gitlab.com:soapbox-pub/ditto into fix/feed-header-ordering
# Conflicts:
#	src/pages/BadgesPage.tsx
2026-03-28 05:00:19 -05:00
Chad Curtis aa257b34ec Fix bottom nav flashing during vine swipe transitions
Remove the activeVinePlaying reset on index change. The old card's
onPlayingChange is already undefined after re-render, and the new
card's autoplay fires onPlay directly, so the state stays consistent
through transitions without a brief false→true flash.
2026-03-28 04:43:52 -05:00
Chad Curtis c48e6c7123 Add safe area insets to vine card overlay UI
Offset the bottom info strip, action sidebar, and mute button by
env(safe-area-inset-bottom) so they clear the home indicator on
notch/island devices. Applied to both the live UI and loading
skeleton.
2026-03-28 04:43:14 -05:00
Chad Curtis 827bc4b836 Show bottom nav when vine is paused, hide during playback
Lift playing state from VineCard to VinesFeedPage via onPlayingChange
callback. hideBottomNav is now driven by whether the active vine is
playing, so users can navigate when paused. Reset playing state on
swipe so the nav briefly appears while the next vine loads. Remove
noArcs so the bottom nav renders with its normal arc appearance.
2026-03-28 04:41:40 -05:00
Chad Curtis c7d115f873 Make vines page fully immersive on mobile
Hide the mobile top bar and bottom nav entirely on the vines page,
replacing them with a floating TikTok-style tab bar that overlays
directly on the video. The menu button (hamburger) is embedded in
the floating bar so users can still access navigation.

- Add hideTopBar and hideBottomNav layout options
- Add DrawerContext so pages can open the mobile drawer directly
- Move floating tab bar outside the scroll container to fix
  IntersectionObserver index tracking (autoplay on next video)
- Simplify vine-slide-height CSS to use full 100dvh
2026-03-28 04:36:41 -05:00
Alex Gleason 45c585a27d fix: add Vines feed section header with info link to divine.video
Fixes #154
2026-03-28 04:20:30 -05:00
Alex Gleason 30bd73f8f9 Replace import.meta.glob with inlined SVG constants for Shakespeare compatibility
import.meta.glob is Vite-only and crashes in Shakespeare's esbuild bundler.
Generated baby-svg-data.ts and adult-svg-data.ts with SVG content as template
literal constants, keeping the existing resolver API unchanged.
2026-03-28 02:18:26 -05:00
Lemon 9d8a30f678 Add badge awards push notification template and pref key mapping 2026-03-28 00:13:21 -07:00
Lemon 2b0b99d598 Fix letters push toggle not propagating to nostr-push server 2026-03-28 00:07:28 -07:00
Lemon 8551852c9d Add badges and letters kinds to shared notificationKinds helper 2026-03-28 00:00:20 -07:00
Lemon 7ade0eaeb1 Clean up notification follow-filter code: remove dead ref, fix filter typing 2026-03-27 23:58:31 -07:00
Lemon debdbf770b Respect 'only from people I follow' in web push notifications
Send authors: ['$contacts'] in the nostr-push subscription filter
when onlyFollowing is enabled. The nostr-push server resolves this
macro to the user's kind 3 follow list. Toggling the setting off
removes the authors filter so all notifications are delivered again.
2026-03-27 23:58:31 -07:00
Lemon 01976685e8 Respect 'only from people I follow' in unread notification dot
Apply the same authors filter as useNotifications so the nav dot
won't appear for notifications from non-followed accounts.
2026-03-27 23:58:31 -07:00
Lemon bac5d71480 Respect 'only from people I follow' in native Android notifications
Pass followed pubkeys through the Capacitor plugin to the native
polling service. When onlyFollowing is enabled, the relay query
includes an authors filter so only events from followed accounts
trigger native Android notifications.
2026-03-27 23:58:31 -07:00
Lemon 0ad655d1cf Fix notification preferences not filtering push notifications or unread dot
Disabled notification types (e.g. reactions) still triggered push
notifications and showed the unread dot indicator, even though the
notification tab correctly filtered them out.

Three root causes fixed:
- useHasUnreadNotifications now uses getEnabledNotificationKinds to
  only query for enabled types, preventing phantom unread dots
- NotificationSettings now syncs type preference changes to the
  nostr-push server via updateSubscription (is_active toggle)
- Native Android poller now receives enabled kinds from the JS layer
  and uses them in the relay filter instead of hardcoded kinds
2026-03-27 23:58:31 -07:00
Chad Curtis a526e301da Fix MobileTopBar arc lingering when hidden on pages without tabs
The hide transform was missing the 20px arc overhang, so the bottom
curve remained visible after the bar slid up. Match the nav-hidden-slide
approach used by SubHeaderBar.
2026-03-28 00:46:29 -05:00
Chad Curtis 9c16c6df40 Fix MobileTopBar arc position with safe-area inset on native
The ArcBackground was positioned over the entire header including the
safe-area padding, causing the arc curve to sit too high on native apps.
Wrap content in a relative container so the arc only covers the content
area, and add bg-background/85 on the header to fill the safe-area region.
2026-03-28 00:46:29 -05:00
Chad Curtis 3220e9482b Fix profile and compose letter tabs hiding with mobile top bar
Add 'pinned' prop to SubHeaderBar that transitions top to 0 instead
of sliding off-screen when the nav hides. Applied to ProfilePage tabs
and ComposeLetterSheet toolbar.
2026-03-28 00:46:29 -05:00
Alex Gleason 9a033d7f91 Merge branch 'main' of gitlab.com:soapbox-pub/ditto 2026-03-28 00:38:33 -05:00
Chad Curtis 2329458a84 Fix settings letters section, drawer background/z-index, and top nav scroll hide
- Remove letters section from settings page (accessible from letters page)
- Add background to letter editor drawer panel
- Fix drawer z-index so letter content doesn't bleed through
- Fix compose sheet SubHeaderBar top offset in overlay context
- Hide top bar and sub-header tabs together on scroll down
2026-03-28 00:36:07 -05:00
Alex Gleason 7f37f16c7b Upgrade React from 18.3 to 19.2
- Upgrade react, react-dom to ^19.2.4 and @types/react, @types/react-dom to v19
- Upgrade @nostrify/react to 0.4.0 (peer deps fix for React 19)
- Upgrade vaul to 1.1.2 and react-day-picker to 9.14.0 for React 19 compatibility
- Fix useRef() calls to pass explicit initial values (required in React 19)
- Update RefObject types to include null (React 19 type change)
- Rewrite Calendar component for react-day-picker v9 classNames API
- Add npm overrides for @emoji-mart/react (only remaining React 18 holdout)
2026-03-28 00:29:37 -05:00
Chad Curtis a67d007435 Merge branch 'fix/badge-profile-and-give-badge' into 'main'
Add top badges to profile and 'Give badge' to profile menu

Closes #189 and #185

See merge request soapbox-pub/ditto!121
2026-03-28 05:19:02 +00:00
Chad Curtis a5c6645d2d Fix GiveBadgeDialog bugs and DRY up ProfileMoreMenu handlers 2026-03-28 00:16:18 -05:00
Alex Gleason cbe50a0232 Merge branch 'main' of gitlab.com:soapbox-pub/ditto 2026-03-28 00:01:19 -05:00
Alex Gleason a48ac48202 Trim Sentry bundle by tree-shaking unused replay/feedback/canvas modules
Use named imports in the dynamic import of @sentry/react so the bundler
can drop re-exported modules we never reference (replay 207K, feedback 67K,
replay-canvas 25K). Also set defaultIntegrations: undefined to prevent
Sentry from pulling those modules at runtime.

Sentry chunk: 431K → 128K (-70%).
2026-03-28 00:00:21 -05:00
Mary Kate Fain 0a7aaca6e5 Move badges from sidebar to profile bio section
Display badge preview inline in the profile bio area (after the
about text) as a horizontal row of thumbnails, matching the style
used in the profile hover card. This works on both desktop and
mobile since it's part of the main profile content.
2026-03-27 23:47:01 -05:00
Mary Kate Fain 6e41ea3b42 Add badges to profile sidebar and 'Give badge' to profile menu
- Show accepted badges in the profile right sidebar (fixes #189)
- Add 'Give badge' option to the profile 3-dot overflow menu,
  allowing users to award their created badges directly from
  a user's profile (fixes #185)
2026-03-27 23:47:01 -05:00
Alex Gleason 12d578ff57 Improve bundle chunking: lazy-load emoji picker, markdown, and remove runtime tailwind config
- Hardcode md breakpoint in useIsMobile and toaster to eliminate runtime
  import of tailwind.config (was pulling in tailwindcss, postcss-selector-parser,
  and plugin code ~100KB)
- Lazy-load EmojiPicker in ComposeBox (emoji-mart + data ~500KB deferred)
- Dynamic import webxdcMeta.ts (smol-toml + fflate only loaded for .xdc uploads)
- Lazy-load ArticleContent, PullRequestCard, CustomNipCard in NoteCard and
  PostDetailPage (react-markdown + unified pipeline ~147KB deferred)
- Consolidate 60+ lucide-react icon micro-chunks into a single chunk via
  manualChunks, reducing HTTP request overhead
- ReplyComposeModal chunk: 808KB -> 296KB (-63%)
- JS file count: 226 -> 181 (-45 files)
2026-03-27 23:44:20 -05:00
Chad Curtis 3486b7f503 Merge remote-tracking branch 'origin/main' into fix/font-picker-click-through
# Conflicts:
#	src/components/FontPicker.tsx
2026-03-27 23:43:46 -05:00
Chad Curtis 0aed5e0f31 Merge branch 'fix/emoji-picker-contrast' into 'main'
Fix: Improve contrast on focused emoji category text in picker

Closes #174

See merge request soapbox-pub/ditto!116
2026-03-28 04:41:26 +00:00
Alex Gleason 34c40980e3 Merge branch 'remove-dev-buttons' into 'main'
Removing dev buttons

See merge request soapbox-pub/ditto!127
2026-03-28 03:09:08 +00:00
Alex Gleason b13eb6012c Merge branch 'main' of gitlab.com:soapbox-pub/ditto 2026-03-27 20:59:00 -05:00
Alex Gleason ecc3284a94 Improve code splitting: reduce index chunk from 1021K to 494K
- Lazy-load BlobbiCompanionLayer (~450K blobbi code off critical path)
- Split BlobbiActionsProvider into lightweight file to avoid pulling
  heavy blobbi action system into the index chunk
- Fix HomePage eagerly importing all 18 page components; use lazy()
  so only the configured homepage's chunk is loaded
- Lazy-load ReplyComposeModal in AppRouter and FloatingComposeButton
  to defer emoji-mart (~620K) until compose is opened
- Fix barrel import in App.tsx pulling BlobbiDevEditor into index;
  use direct import from EmotionDevContext instead
2026-03-27 20:56:36 -05:00
filemon b10c8ff182 Hide Blobbi dev controls on deployed environments
Add isLocalhostDev() helper that checks both import.meta.env.DEV AND
hostname (localhost/127.0.0.1/0.0.0.0). This ensures dev buttons only
appear during local development, never on deployed apps.

Dev controls now hidden in production:
- Dev Hatch/Evolve instant transition buttons
- Dev State Editor button
- Dev Emotion Tester button
2026-03-27 22:40:17 -03:00
Alex Gleason d96e222a15 Merge branch 'main' of gitlab.com:soapbox-pub/ditto 2026-03-27 20:40:02 -05:00
filemon ec63533108 Merge branch 'main' into remove-dev-buttons 2026-03-27 22:32:47 -03:00
Alex Gleason 6f74366dd9 Restore code splitting with React.lazy for all non-critical page routes
Convert 44 page imports from static to React.lazy() with dynamic imports.
Only HomePage, Index, and NotFound remain eagerly loaded as critical-path
pages. The existing Suspense boundary in MainLayout (with PageSkeleton
fallback) already wraps the content area, so lazy pages show a skeleton
while loading without affecting the sidebar or navigation.
2026-03-27 20:30:32 -05:00
filemon 4b5825790a Fix daily missions UI not updating after reroll/claim
Replace useLocalStorage with direct localStorage reads that re-trigger
when the 'daily-missions-updated' event fires. The previous approach
cached state internally and didn't see same-tab localStorage writes.

Now when mutations write to localStorage and dispatch the event:
- Version counter bumps
- useMemo re-reads from localStorage
- UI updates immediately without page refresh
2026-03-27 22:29:20 -03:00
filemon f7391c0e0b Rebalance daily mission rewards to match shop economy
- Increase easy mission rewards to 25-30 coins
- Increase medium mission rewards to 45-50 coins
- Increase high-effort missions (photo, multiple feeds) to 55-70 coins
- Increase medicine missions to 60-70 coins (since medicine costs coins)
- Increase Daily Champion bonus from 50 to 80 coins

Target daily economy: 130-180 coins normal day, 210-250 with bonus
2026-03-27 22:24:48 -03:00
Alex Gleason dce3d5b411 Merge branch 'feat-blobbi' into 'main'
Blobbi: add core pet system, interactions, missions, etc

See merge request soapbox-pub/ditto!104
2026-03-28 01:23:11 +00:00
Alex Gleason a2490da3b4 Add badge kinds (30009, 30008) to the Ditto tab feed 2026-03-27 20:22:02 -05:00
filemon 1aacc0073f Fix egg-compatible missions and add medicine missions for reroll
Mission pool changes:
- Add 'medicine' action type for giving medicine to Blobbi
- Add medicine_1 (30 coins) and medicine_2 (50 coins) missions
- Mark clean, sing, play_music, medicine as available for ALL stages (egg+baby+adult)
- Keep interact, feed, sleep, take_photo as baby/adult only

Egg users now have 8 valid missions:
- clean_1, clean_2
- sing_1, sing_2
- play_music_1, play_music_2
- medicine_1, medicine_2

This ensures egg-only users always have alternatives when rerolling
(need at least 4 missions for 3 daily + 1 reroll target)
2026-03-27 22:14:40 -03:00
Alex Gleason 6195ae6901 Merge branch 'main' of gitlab.com:soapbox-pub/ditto 2026-03-27 20:10:58 -05:00
filemon 6f2d80b99e Fix mission reroll - expand pool and add state migration
- Expand DAILY_MISSION_POOL from 7 to 15 missions with more variety
  - Multiple difficulty tiers for feed, clean, interact, sing, play_music, take_photo
  - Ensures always having alternatives when rerolling
- Fix selectReplacementMission to properly exclude only active missions
- Add state migration for rerollsRemaining in both hooks
  - Old localStorage states without rerollsRemaining now get 3 rerolls
- Improve getRerollsRemaining to handle undefined/null values
- Better error message when pool is exhausted
2026-03-27 22:10:40 -03:00
filemon a8e7901eac Add mission reroll feature for daily missions
- Add rerollsRemaining to DailyMissionsState (max 3 per day, resets daily)
- Add rerollMission() function with stage-aware replacement selection
- Replacement avoids duplicates and the mission being replaced
- Add useRerollMission hook for mutation with toast feedback
- Add reroll button (RefreshCw icon) to incomplete missions
- Show remaining rerolls count at top of mission list
- Disable reroll for completed/claimed missions
- Bonus mission still works correctly after rerolling
2026-03-27 22:01:50 -03:00
filemon d4ae9d9611 Add stage-based daily mission filtering and bonus mission reward
- Add requiredStages property to mission definitions (all current missions require baby/adult)
- Update selectDailyMissions() to filter by user's available Blobbi stages
- Show 'Hatch Your Blobbi First' message when user only has eggs
- Add 50-coin 'Daily Champion' bonus mission after completing all regular missions
- Bonus mission appears locked until all regular missions are completed
- Update useClaimMissionReward hook to support claiming bonus rewards
- Pass availableStages through modal props for proper filtering
2026-03-27 21:56:41 -03:00
filemon d82a3cffe8 Allow empty name input during Blobbi egg adoption editing
Previously, clearing the name input would immediately restore it to 'Egg',
which made for a frustrating UX when trying to fully clear and retype.

Now:
- Name input can be fully cleared while editing
- Validation error shows when name is empty
- Adopt button is disabled when name is empty/whitespace
- Only validate on submit, not on every keystroke
2026-03-27 21:43:06 -03:00
filemon 05e189b938 Fix SVG ID prefix to use full Blobbi ID instead of first 8 chars
The previous fix used instanceId.slice(0, 8) for the prefix, but since
Blobbi IDs have the format 'blobbi-{pubkeyPrefix12}-{petId10}', the first
8 characters are always 'blobbi-' for all Blobbis owned by the same user.

This caused gradient ID collisions between different Blobbis.

Now using the full sanitized instanceId as the prefix:
  b_blobbi-abc123456789-xyz1234567

This ensures each Blobbi gets truly unique SVG IDs.
2026-03-27 21:39:01 -03:00
filemon d32d0b17d0 Fix gradient ID collisions causing wrong colors in Blobbi modal list
When multiple Blobbis are rendered on the same page (like in the selector modal),
they all shared the same SVG gradient IDs (e.g., cattiBody3D, blobbiBodyGradient).
The browser only uses the first definition of each ID, so all subsequent Blobbis
would use the first one's colors instead of their own.

Fixed by:
- Adding uniquifySvgIds() function to both adult and baby SVG customizers
- Generating unique prefixes from each Blobbi's ID (first 8 characters)
- Prefixing all SVG IDs and updating all references (url(), href, xlink:href)
2026-03-27 21:28:04 -03:00
Alex Gleason 3a8282255c Revert "Hide top nav on scroll and unify top padding across pages"
This reverts commit 488ce5750d.

Restores sticky (non-fixed) mobile top bar, removes scroll-based
hide/show behavior, reverts pt-mobile-bar back to -mt-mobile-bar
negative margin approach, and removes ARC_OVERHANG_PX spacers from
NotificationsPage and ProfilePage.
2026-03-27 19:26:14 -05:00