Commit Graph

4447 Commits

Author SHA1 Message Date
filemon 9797fcd95a fix(blobbi): canonicalize patterns and fix duplicate name display
Pattern canonicalization:
- Changed VALID_PATTERNS from ['gradient', 'solid', 'speckled', 'striped']
  to ['solid', 'spotted', 'striped', 'gradient'] to match domain model
- 'spotted' is the canonical value (used by BlobbiPattern type, BLOBBI_PATTERNS,
  derivePatternFromSeed, normalizePatternTag, and PATTERN_MAP)

Duplicate name fix:
- Removed title from toEggGraphicVisualBlobbi() adapter - the EggGraphic
  'title' field is for special designations (e.g., 'Divine'), not pet names
- The duplicate was: input field above egg + title display below egg
- Now only the input field exists, plus a new styled name display

Name styling:
- Added styled name display above the egg using the egg's baseColor
- Styling matches the former bottom title: bg-black/20, backdrop-blur-sm,
  font-semibold, text-shadow, and color from preview.visualTraits.baseColor
2026-03-15 19:14:52 -03:00
filemon 5d3841d6a7 fix(blobbi): cleanup egg validation inconsistencies
- Fix getColorRarity() to properly merge both base color palettes by
  creating MERGED_BASE_COLORS_BY_RARITY that combines colors per rarity
  tier (previous spread syntax overwrote keys instead of merging arrays)
- Update validation error messages to match actual validation logic:
  colors now accept any valid hex format, not just specification palettes
- Add Rarity type for better type safety in rarity functions
- Add JSDoc clarifying that getColorRarity returns null for domain model
  colors (BLOBBI_BASE_COLORS) which are not in the legacy palettes
2026-03-15 18:39:10 -03:00
filemon 9e5de53ad4 fix(blobbi): make egg colors update on reroll
Root cause: EggGraphic validation rejected derived colors because
isValidBaseColor() used a hardcoded allowlist that didn't include
the BLOBBI_BASE_COLORS palette (e.g., #F59E0B, #55C4A2, etc.).

Changes:
- Update isValidBaseColor/isValidSecondaryColor to accept any valid
  hex color format (palette enforcement at domain level)
- Add visual trait tags (base_color, secondary_color, eye_color,
  pattern, special_mark, size) to previewToEventTags for
  deterministic rendering
- Improve useMemo dependencies in BlobbiEggVisual to ensure
  re-render on preview change
2026-03-15 13:59:36 -03:00
filemon 13cdbc565c feat(blobbi): add 'Adopt another Blobbi' entry point from selector
Adds a dedicated CTA card in the Blobbi selector modal and page to allow
existing users to adopt additional Blobbies without going through full
onboarding.

Changes:
- Added AdoptAnotherBlobbiCard component with plus icon, tooltip, and
  distinct visual styling (dashed border, centered layout)
- Updated BlobbiOnboardingFlow to support adoptionOnly prop that skips
  profile creation and adoption question, going directly to egg preview
- Updated useBlobbiOnboarding hook with adoptionOnly mode support that:
  - Derives initial step as 'preview' when adoptionOnly is true
  - Generates preview immediately on mount in adoptionOnly mode
  - Skips auto-sync logic that would interfere with explicit control
- Added adoption flow modal to BlobbiDashboard with full callback wiring
- Added adoption flow modal to BlobbiSelectorPage (Cases G and H)
- Passed required adoption callbacks through BlobbiDashboard props

UX flow:
1. User clicks 'Adopt another Blobbi' card in selector
2. Selector closes, adoption flow modal opens
3. User sees egg preview directly (no profile/adoption question steps)
4. User can reroll, name, and adopt as normal
5. On completion, modal closes and new Blobbi is selected
2026-03-15 13:44:48 -03:00
filemon 5ea4b0f73d fix(blobbi): add pettingLevel, fix reroll visual, improve onboarding stability
1. pettingLevel support:
   - Added pettingLevel to BlobbonautProfile type and parsing
   - New profiles include pettingLevel: 0 by default
   - Created useBlobbonautProfileNormalization hook to auto-add
     pettingLevel to existing profiles that are missing it

2. Reroll visual fix:
   - Added key prop to BlobbiStageVisual to force remount on preview change
   - Added debug logging to track preview identity changes (d/seed/petId)
   - Reroll preserves typed name while generating new identity

3. Onboarding stability improvements:
   - Enhanced step sync logic in useBlobbiOnboarding to handle all edge cases
   - Added defensive checks for profile state changes
   - Better debug logging for state transitions

4. Verified invariants:
   - Preview remains single source of truth for adopted event
   - Name is editable, required for adoption, preserved on reroll
   - No any types introduced
2026-03-15 13:16:26 -03:00
filemon f3e262bd3a fix(blobbi): respect user profile state in onboarding flow
- Fixed useBlobbiOnboarding to derive initial step from profile state
- Added useEffect to sync step when profile loads from cache/relay
- Added egg name customization via updatePreviewName() function
- Removed 'Maybe Later' skip option from adoption step
- Refactored BlobbiPage with cleaner state logic and debug logging
- Fixed TypeScript errors (unused vars, empty interface)

Resolves issue where onboarding always started on 'profile' step
even when user already had a profile, and adds name input to
egg preview before adoption.
2026-03-15 12:48:58 -03:00
Alex Gleason 80a2d3d846 Remove 'View on njump.me' from profile dropdown menu 2026-03-15 04:33:14 -05:00
Alex Gleason 93c1d81c06 Add relay hint to 'a' tag in generic reposts of addressable events 2026-03-15 04:26:09 -05:00
Alex Gleason 53c1fb1090 Fix quote posts for addressable events: use naddr instead of nevent
Addressable events (kinds 30000-39999) like lists get new event IDs when
updated, causing nevent references to break. Use naddr coordinates
(kind:pubkey:d-tag) which remain stable across updates.
2026-03-15 04:24:48 -05:00
Alex Gleason f92f50d5e0 Fix quote posts not loading: include relay hints in nevent URIs and q tags 2026-03-15 04:19:02 -05:00
Alex Gleason 1fbdd2f729 Merge branch 'main' of gitlab.com:soapbox-pub/ditto 2026-03-15 04:13:56 -05:00
Alex Gleason eb0f4270b1 Show tombstone when quoted posts can't be loaded
Replace silent null returns in EmbeddedNote and EmbeddedNaddr with a
visible tombstone UI showing 'This post could not be loaded' with a
dashed border and icon, so users know a quote was referenced even when
the event can't be fetched from relays.
2026-03-15 03:41:21 -05:00
Chad Curtis 42ef548b0a Fix video not rendering in reply chains 2026-03-15 03:24:09 -05:00
Chad Curtis a5345f4c61 Add .qt video format support 2026-03-15 03:19:13 -05:00
Alex Gleason d2e1a10fd2 Merge branch 'main' of gitlab.com:soapbox-pub/ditto 2026-03-15 03:14:54 -05:00
Chad Curtis 05e1e05740 Add Ditto tab (enabled by default) and disable Global tab by default
- Add 'ditto' CoreFeedTab that renders the same hot-sorted curated feed
  (useInfiniteHotFeed) previously shown only to logged-out visitors
- Change Global tab default from enabled to disabled
- Update useFeedTab to default to 'ditto' instead of 'global' when logged out
- Add showDittoFeed localStorage toggle in Feed.tsx and ContentSettings.tsx
- Add Ditto Feed toggle row in ContentSettings FeedTabsSection
2026-03-15 02:55:08 -05:00
Alex Gleason 449723e25f Remove List icon from list cards in feeds and embeds
The icon next to the list title adds visual noise without helping. The
PartyPopper icon is kept for starter packs (kind 39089) where it has
distinct meaning.
2026-03-15 02:44:43 -05:00
Alex Gleason 7c83e42001 De-emphasize author on list/follow-pack cards in feeds and embeds
For kind 30000 (lists) and 39089 (starter packs), replace the prominent
avatar + bold name header with a content-first layout: the list title,
description, and member avatars are shown as the hero, followed by a
subtle small author attribution line (tiny avatar, muted text, timestamp).

This applies to both normal and threaded layouts, as well as compact/embed
mode used in quote posts and inline embeds.
2026-03-15 02:39:19 -05:00
Alex Gleason 434e4ad806 Fix lists not rendering in quote posts
When a kind 30000 list is quoted, ComposeBox encodes it as a nevent
which routes through EmbeddedNote. EmbeddedNote had no kind-specific
handling, so lists appeared as generic text cards instead of the rich
card with title, member avatars, and description.

Add the same NOTECARD_KINDS check (kind 30000, 39089) that EmbeddedNaddr
already uses, delegating to NoteCard compact for these kinds.
2026-03-15 02:32:13 -05:00
Alex Gleason a66211845f Add share/repost/quote dropdown to list page, rename Follow Sets to Lists
Replace the single Share button on the list detail page with a dropdown
menu offering Share (copy link / native share), Repost (kind 16 generic
repost), and Quote post (opens composer with quoted event).

Also rename all user-facing 'Follow Sets' terminology to 'Lists' across
the UI: UserListsPage, ListDetailPage, FollowPackDetailContent,
AddToListDialog, and SavedFeedFiltersEditor.
2026-03-15 02:15:01 -05:00
Chad Curtis 5a28692e55 Remove isPending disabled prop causing switch flicker on toggle 2026-03-14 19:13:32 -05:00
Chad Curtis e3cd2365c6 Fix toggle flicker: initialize local state once from settings, persist in background 2026-03-14 19:11:47 -05:00
Chad Curtis 801e966abe Fix toggle flicker with optimistic local state 2026-03-14 19:09:40 -05:00
Chad Curtis b76bf7b198 Condense notifications and add per-type notification preferences
- Group reactions, reposts, and zaps on the same post into a single condensed
  row with stacked actor avatars (up to 5 + overflow count); single-actor
  interactions use the original compact layout
- Deduplicate actors by pubkey within groups
- Sum zap totals across all actors in a zap group
- Add notificationPreferences per-type settings (reactions, reposts, zaps,
  mentions, comments, onlyFollowing) to EncryptedSettings and Zod schema
- Per-type kind toggles and onlyFollowing applied at relay query level (kinds
  array + authors filter), not client-side; query key includes kindsKey and
  authorsKey so preference changes trigger a fresh fetch
- Default push notifications to enabled
- Notification settings UI matches ContentSettings exactly: section headers
  with accent underline, p-4 wrapper, broken border rows (border-b on outer
  wrapper div), sub-section labels, w-[52px] switch column, KindBadges
- Add 'Only from people I follow' toggle under Filter sub-section
- Filter and push notification prefs also respected in useNativeNotifications
  web push subscription via stable ref
2026-03-14 19:06:31 -05:00
Chad Curtis 287b35d337 Use 2x2 grid layout for ScopeToggle when there are more than 3 options 2026-03-14 17:36:30 -05:00
Chad Curtis a3e5b94e69 Fix profile tab editor missing people filter and tab feed using paginated query
- ProfileTabEditModal: add 'People' scope option with AuthorFilterDropdown and
  ListPackPicker so users can pick specific pubkeys as tab authors, matching
  the filter options available on the normal search filter
- useProfileFeed: add useTabFeed hook that runs a paginated useInfiniteQuery
  with full NostrFilter support (kinds, authors, NIP-50 search)
- ProfileSavedFeedContent: replace useStreamPosts with useTabFeed so custom
  tab content uses cursor-based pagination (like the posts tab) instead of
  streaming, fixing search-keyed queries and enabling infinite scroll
2026-03-14 17:34:21 -05:00
Chad Curtis bf9cef5bb5 Allow adding app default servers/relays to personal lists 2026-03-14 16:19:23 -05:00
Alex Gleason b094e01337 Extract shared parseBlossomServerList into appBlossom.ts
Deduplicates the kind 10063 tag parsing logic that was repeated in both
NostrSync.tsx and useInitialSync.ts. Both now call the shared function
from lib/appBlossom.ts.
2026-03-14 15:55:29 -05:00
filemon 96b8288c5b feat(blobbi): implement new onboarding flow with egg preview
Add complete Blobbi onboarding flow:
- Profile creation step with name prefill from kind 0 metadata
- Adoption question step after profile creation
- Egg preview with reroll (10 coins) and adopt (100 coins) options
- Confirmation dialog before adoption
- New profiles start with 200 coins

Key components:
- BlobbiProfileOnboarding: Profile creation with name input
- BlobbiAdoptionStep: 'Ready to adopt?' prompt
- BlobbiEggPreviewCard: Egg preview with visual traits and actions
- BlobbiAdoptionConfirmDialog: Adoption cost confirmation
- useBlobbiOnboarding: State and action orchestration hook

Preview is the source of truth for adoption - same exact data is
used to create the final kind 31124 event. Coins are deducted
from profile before publishing events.
2026-03-14 16:44:14 -03:00
Chad Curtis f200359059 Implement BUD-03 kind 10063 Blossom server list management
Blossom servers now work exactly like relays:
- App default servers (APP_BLOSSOM_SERVERS) can be toggled on/off
- User's kind 10063 server list is fetched and synced from Nostr
- NostrSync fetches kind 10063 on login and applies it to config
- useInitialSync fetches kind 10063 in parallel on first login
- BlossomSettings UI mirrors RelayListManager with two sections:
  App Blossom Servers (with enable toggle) + Your Blossom Servers
- User changes publish a kind 10063 replaceable event to Nostr
- getEffectiveBlossomServers() merges app + user servers like getEffectiveRelays()
- Migration from old blossomServers[] to blossomServerMetadata handled in AppProvider
2026-03-14 12:34:59 -05:00
Chad Curtis c36174d9de Paginate FollowsList in search accounts tab to fix perf with 1000+ follows 2026-03-14 11:50:11 -05:00
Chad Curtis 396007d455 Remove unused eslint-disable directive in SearchPage 2026-03-14 11:45:06 -05:00
Chad Curtis a827744ddc Remove focus ring from reaction buttons and add double-click to heart react 2026-03-14 11:43:53 -05:00
Chad Curtis 4684491b9f fix: apply search query filter to all streamed event kinds
Non-kind-1 events (articles, photos, videos, etc.) bypassed the client-side
search check via an early return, so streamed events of any extra kind passed
through regardless of the search query. Remove the early return and apply the
query filter to all kinds, also checking title/summary/subject/alt tags for
non-text events. Reply filtering still only applies to kind 1/1111.
2026-03-14 11:29:39 -05:00
Chad Curtis b4f88ec448 fix: align filter grid labels and rename Platform to Protocol
The Protocol label used flex layout for the HelpTip icon while the other
three labels did not, causing vertical misalignment of the selects below
them. Give all four labels the same flex items-center gap-1 classes.
Also rename Platform to Protocol.
2026-03-14 11:22:00 -05:00
Chad Curtis 97fe74be07 fix: unwrap repost events before rendering in search feed
Kind 6/16 repost events were passed raw to NoteCard without extracting the
embedded original event, so reposts showed nothing. Mirrors the same
parseRepostContent + repostedBy pattern used in useFeed/Feed.tsx.
2026-03-14 11:19:15 -05:00
Chad Curtis 79ea07098d fix: use all picker kinds when kind filter is set to 'all'
parseKindFilter returned undefined for 'all', causing useStreamPosts to fall
back to the user's enabled feed-settings kinds instead of every kind in the
kind picker list. Now kindsOverride always contains explicit kind numbers:
all picker kinds when filter is 'all', or the specific selection otherwise.
2026-03-14 11:15:59 -05:00
Chad Curtis cf1edc3230 fix: always include kind 1 in default search kinds
getEnabledFeedKinds only returns user-toggled extra kinds, never kind 1.
The fallback paths for videos/images/all were missing kind 1 entirely,
so searches returned no results unless the user had explicitly enabled
extra feed kinds.
2026-03-14 11:13:11 -05:00
Chad Curtis b789c0e821 fix: resolve search input focus loss, lag, and add-to-feed button regressions
- Prevent focus steal on first keystroke: the add-to-feed bookmark button was
  conditionally mounted when searchQuery became non-empty, causing a DOM mutation
  mid-keystroke that stole focus from the input

- Eliminate searchParams feedback loop: the state→URL sync effect had searchParams
  in its dependency array, causing a cascade of extra re-renders on every keystroke
  after the debounce settled

- Eliminate per-keystroke re-renders: raw input state now lives in a dedicated
  SearchInput child component with its own internal debounce; SearchPage only
  holds the debounced value and re-renders when typing stops, not on every character
2026-03-14 11:11:33 -05:00
Alex Gleason 78cf05f623 Use lowercase 'k' for thousands in short number format 2026-03-14 02:39:52 -05:00
Alex Gleason 0ffe2de89d Use short number format for large stats (e.g. 1.7K, 314K, 2M) 2026-03-14 02:39:14 -05:00
Alex Gleason 09091441c6 Linkify URLs and hashtags in user bios on profile pages
Add BioContent component that tokenizes bio text to render URLs as
clickable links and hashtags as internal navigation links, while
preserving NIP-30 custom emoji support. Applied to ProfilePage,
ProfileHoverCard, and ProfileCard read-only bio displays.
2026-03-14 01:30:57 -05:00
Alex Gleason 71f9a6c354 Expand vine slides to fill screen when bottom nav hides on scroll
The vine-slide-height CSS class statically subtracted 3.5rem for the
bottom nav. Added a vine-slide-height-expanded class without that
subtraction, toggled by scroll direction so the video fills the full
viewport when the bottom nav slides away.
2026-03-14 01:18:08 -05:00
Alex Gleason f74d333d63 Fix mobile bottom nav not hiding on swipe in Vines page
The Vines page uses an internal snap-scroll container instead of window
scroll, so useScrollDirection (which listened to window.scrollY) never
detected any scroll movement. Add a scrollContainer option to
LayoutOptions so pages with custom scroll containers can communicate
the element to MobileBottomNav, which passes it to useScrollDirection.
2026-03-14 01:08:45 -05:00
Dirk Rost 33c95f6ace Merge branch 'fix/youtube-thumbnails-again' into 'main'
Fix YouTube thumbnail gray placeholder with off-screen probing

See merge request soapbox-pub/ditto!69
2026-03-14 05:59:03 +00:00
Lemon d3457f5868 Fix YouTube thumbnail gray placeholder with off-screen probing 2026-03-14 05:59:03 +00:00
Alex Gleason 8782d8e1bc Change mobile bottom nav items to Search, Notifications, and Profile
Replace Feed/Home button with Profile, which shows the user's avatar at
a small size. Search and Notifications remain. Logged-out users see a
generic User icon for Profile instead of the avatar.
2026-03-14 00:52:52 -05:00
Alex Gleason 59311e6b2c Restore mobile bottom nav with scroll-to-hide behavior
Bring back the mobile bottom navigation bar with Home, Notifications, and
Search buttons. The nav slides out of view when scrolling down and reappears
on upward scroll, keeping the viewport uncluttered while reading. Search
retains the popover account search sheet for fast profile lookup without
navigating away. Updated CSS height calculations for full-screen pages
(AI chat, vines, livestream) and FAB positioning to account for the nav.
2026-03-13 22:47:17 -05:00
Alex Gleason 3727975178 Move 'Set a status' into profile menu on mobile drawer 2026-03-13 22:30:17 -05:00
Alex Gleason e95a63fcf6 Fix emoji picker touch scrolling on mobile in avatar shape dialog 2026-03-13 22:16:59 -05:00