Commit Graph

629 Commits

Author SHA1 Message Date
Alex Gleason 7aecb29e10 Merge branch 'main' of gitlab.com:soapbox-pub/ditto-mew 2026-02-21 12:48:29 -06:00
Alex Gleason f8774c7a6b Use standard imeta field names: 'summary' for app name, 'image' for icon 2026-02-21 12:20:21 -06:00
Alex Gleason 25a53e32cd Fix icon upload CSP violation: create File from raw bytes instead of fetching data URI 2026-02-21 12:16:40 -06:00
Alex Gleason 749900f853 Extract webxdc name and icon from .xdc manifest, display in embed card
- Add webxdcMeta.ts utility to extract name from manifest.toml and
  icon (icon.png/icon.jpg) from the .xdc ZIP using fflate
- Upload extracted icon to Blossom during file attach
- Add webxdc_name and webxdc_icon properties to imeta tags
- Parse webxdc_name/webxdc_icon in NoteCard and PostDetailPage
- Show app icon and name in WebxdcEmbed launch card, remove filename
  and 'Stateful · shared session' text
2026-02-21 12:15:26 -06:00
Chad Curtis c565050779 Build v2026.02.21: Update mew.apk (6.3M) 2026-02-21 05:34:24 -06:00
Chad Curtis 7b38637af5 Add 'shared a deck' action header for magic deck events in feed
Shows '<cards icon> <name> shared a deck' above magic deck cards in the
feed, matching the pattern of treasure/stream action headers. Suppressed
when the card is already showing a repost header to avoid double headers.
2026-02-21 05:27:56 -06:00
Chad Curtis 3d1ec85f77 Use Palette icon for visual toggle and render deck content on post detail page
Replace Image icon with Palette for the list/visual toggle button.
Add MagicDeckContent to PostDetailPage kind dispatch so deck events
show their full content when viewed as a post detail (naddr route).
2026-02-21 05:22:46 -06:00
Chad Curtis 3c4d6d0efc Fix scroll and add card lightbox gallery to magic deck content
Replace ScrollArea with overflow-y-auto for reliable scrolling in both
list and visual views. Clicking any card (in either view) opens a
full-screen lightbox showing the card image from Scryfall at large size,
with prev/next navigation via arrows, keyboard, and swipe gestures.
Shows card name and foil indicator in the lightbox header.
2026-02-21 05:19:38 -06:00
Chad Curtis b4e3e63a8f Add visual spoiler toggle for magic deck card lists
Decklist box now has a List/Visual toggle in the header. Visual mode
renders a 4-column grid of card images loaded from Scryfall's API using
set/collector_number for exact printings or card name as fallback.
Includes quantity badges, foil shimmer overlay, and graceful fallback
to card name text when images fail to load.
2026-02-21 05:17:11 -06:00
Chad Curtis d0135d1014 Rework MagicDeckContent: single-line meta row and scrollable card list
Merge format badges, card count, and sideboard count onto one line.
Replace expand/collapse with a ScrollArea box (max 240px) containing
the full decklist with sideboard inline below a separator header.
2026-02-21 05:10:08 -06:00
Chad Curtis b7596c1265 Add CardsIcon SVG and hide t:hidden events for magic decks and geocaches
Replace Layers icon with custom CardsIcon (stacked cards SVG) across all
navigation and settings UIs. Filter out events tagged t:unlisted for kind
37381 (magic decks) and t:hidden for kind 37516 (geocaches) in NoteCard.
2026-02-21 05:07:26 -06:00
Alex Gleason 6a9733452a Remove sandbox attr from webxdc iframe — unique subdomains provide isolation, sandbox breaks CORS 2026-02-21 05:05:23 -06:00
Chad Curtis ffc7672183 Add Magic: The Gathering deck lists as extra kind (NIP-MG, kind 37381)
Support kind 37381 addressable events for MTG deck sharing per NIP-MG spec.
Includes MagicDeckContent component with card list rendering, format/archetype
badges, commander/companion display, sideboard, foil indicators, and
expand/collapse for large decks. Adds /decks route and sidebar navigation.
2026-02-21 05:03:46 -06:00
Alex Gleason 8978aca463 Fix webxdc imeta: append .xdc extension to Blossom URLs so media detection and UUID tagging work 2026-02-21 05:02:12 -06:00
Alex Gleason 13f05936dd Add webxdc support: attach .xdc files as stateful mini apps with kind 4079 state sync
- Create useWebxdc hook bridging the Webxdc API with Nostr kind 4079 state updates
- Create WebxdcEmbed component with launch-on-click UX for sandboxed iframe rendering
- Update ComposeBox to accept .xdc files and generate imeta tags with webxdc UUID
- Update NoteCard and PostDetailPage to detect and render webxdc attachments
- Skip .xdc URLs in NoteContent to avoid rendering them as raw links
2026-02-21 04:57:05 -06:00
Chad Curtis 08787c542e Add stream card rendering in feeds with action headers and pause-on-scroll
Stream events (kind 30311) now render properly in mixed feeds via NoteCard
with inline LiveStreamPlayer for live streams, thumbnail for ended/planned,
title + summary clickable to open stream details, and 'is streaming' /
'streamed' action headers. LiveStreamPlayer pauses when scrolled out of view.
2026-02-21 04:54:00 -06:00
Chad Curtis 9ffe893d59 Remove client-side deletion filtering; rely on relays to handle kind 5 deletion 2026-02-21 04:40:25 -06:00
Chad Curtis 900608c265 Add post deletion support (NIP-09) with confirmation dialog and feed filtering 2026-02-21 04:35:47 -06:00
Chad Curtis d24f8c345a Add MutedContentGuard for post detail pages
Show a dismissible 'Muted Content' overlay instead of rendering muted
posts directly when navigating to their detail page. Follows the same
pattern as ContentWarningGuard — children are not mounted until the
user clicks 'Show Anyway', so media and nested queries are deferred.
2026-02-21 04:10:50 -06:00
Chad Curtis 21f7b3a1eb Persist decrypted mute list to localStorage for immediate availability on page load
Cache parsed mute items in localStorage (like the follow list pattern) so
muted content is filtered immediately on page refresh without waiting for
the relay fetch + decrypt cycle. The cache is written on initial sync,
after each successful decrypt, and eagerly on add/remove mutations.
2026-02-21 04:06:37 -06:00
Chad Curtis 24fb356eb1 Sync mute list (kind 10000) during initial login alongside relay list and settings
Fetches the user's encrypted mute list in parallel with the relay list
and encrypted settings during useInitialSync, then seeds both the raw
event and decrypted mute items into the TanStack Query cache. This
ensures muted content is filtered immediately on first login without
waiting for useMuteList's own delayed query.
2026-02-21 04:02:19 -06:00
Chad Curtis fe6e2065bc Implement mute user/conversation actions and apply mute filtering across all feeds
Wire up the previously stubbed 'Mute @user' and 'Mute Conversation' menu
actions in NoteMoreMenu and ProfilePage to call useMuteList().addMute,
with toggle support for unmuting. Apply mute filtering (via isEventMuted
from muteHelpers) across all feed surfaces: main feed, profile feed,
notifications, post detail replies, search/explore stream, hashtag page,
domain feed, trending posts, and right sidebar.
2026-02-21 03:57:59 -06:00
Chad Curtis 43e501ad74 Improve onboarding: add profile fields, fix sync gate for logged-out users, update profile cache
- Move 'New here?' link above extension login button
- Use profile-intro.png instead of MewLogo on profile step
- Add 'More details' collapsible with banner, website, and custom fields
- Skip sync/onboarding when logged out (guard in InitialSyncGate)
- Persist sync completion in localStorage instead of sessionStorage
- Initialize sync phase synchronously to prevent flash on refresh
- Invalidate author cache after profile publish for immediate updates
2026-02-21 03:42:02 -06:00
Chad Curtis c94fefd02e Add MewLogo at top of profile step in onboarding 2026-02-21 03:19:02 -06:00
Chad Curtis 63a54281d6 Replace hard border with rounded-full pill underline on settings section titles 2026-02-21 03:16:33 -06:00
Chad Curtis 28a9f13fc9 Fix post stats clearing during feed pagination
Rewrite useBatchEventStats as an incremental effect-based prefetcher
that only fetches uncached event IDs. The previous useQuery approach
used a query key containing all event IDs, which changed on every
pagination and raced against a 500ms NIP-85 timeout that overwrote
good cached stats with zeros.

Also stabilize useEventInteractions query key by replacing the
nip85Stats.data object reference with a boolean to prevent
unnecessary refetches on every NIP-85 staleTime cycle.
2026-02-21 02:47:09 -06:00
Chad Curtis 031f35495a Fix checkerboard pattern rendering on iOS by replacing SVG background with CSS grid 2026-02-21 01:43:41 -06:00
Chad Curtis cebded8383 Fix infinite tab loop on SearchPage by deriving tab from URL params
The activeTab state and searchParams were synced bidirectionally via two
competing useEffect hooks. When navigating between tabs via sidebar links
(e.g., 'View All'), setSearchParams produced a new reference, re-triggering
the URL→state effect with a stale closure, causing an infinite loop.

Fix: derive activeTab directly from searchParams (single source of truth)
and update the URL via a callback instead of a separate state variable.
2026-02-21 01:20:04 -06:00
Chad Curtis f36c9a67b5 Add markdown rendering for articles (kind 30023)
- Create ArticleContent component using react-markdown + rehype-sanitize
- Enable @tailwindcss/typography plugin for prose styling
- NoteCard shows article preview (title, image, summary)
- PostDetailPage renders full markdown article with prose typography
- Both views support header images and hashtag links
2026-02-21 01:13:51 -06:00
Chad Curtis b0d10546ca Add /articles route using KindFeedPage for kind 30023 2026-02-21 01:09:57 -06:00
Chad Curtis 3511621132 Move articles to Notes section with both sidebar and feed toggles 2026-02-21 01:07:55 -06:00
Chad Curtis 9074c9b763 Move articles to Media section with sidebar/page toggle
Articles (kind 30023) now have both a showArticles sidebar toggle and
feedIncludeArticles feed toggle, matching the pattern of other content
types like Vines and Streams. Added FileText icon to all icon maps.
2026-02-21 01:06:41 -06:00
Chad Curtis 1e9bd782aa Add Notes section for feed content organization (posts, reposts, articles)
- Add 'feed' section to EXTRA_KINDS for Posts (kind 1), Reposts (kind 6),
  and Articles (kind 30023) as feed-only toggles
- Add feedIncludePosts, feedIncludeReposts, feedIncludeArticles to FeedSettings
  (posts and reposts default to enabled, articles disabled)
- Add 'Notes' collapsible section in ContentSettings above 'Other Stuff'
- Feed kinds are now fully dynamic from settings instead of hardcoded
- Repost unwrapping accepts any event kind, not just kind 1
- Add article (kind 30023) card rendering with title, image, and summary
- Update all feed hooks for consistency (useFeed, useProfileFeed,
  useStreamPosts, DomainFeedPage, HashtagPage)
2026-02-21 00:36:58 -06:00
Chad Curtis 017b568100 Reorder EXTRA_KINDS by section and align onboarding to match
Array order is now media (Vines, Streams), social (Polls, Packs),
whimsy (Colors, Treasures). Sidebar and mobile drawer inherit this
order automatically. Onboarding CONTENT_KINDS updated to match.
2026-02-21 00:21:09 -06:00
Chad Curtis c95fbf1da5 Restore border separators on content type rows 2026-02-21 00:20:10 -06:00
Chad Curtis 5c89dc8ea0 Organize Other Stuff into Media / Social / Whimsy sections
Add a 'section' field to ExtraKindDef and group content types in both
FeedSettingsForm and ContentSettings with labeled section headers.
2026-02-21 00:19:08 -06:00
Chad Curtis 151ea6ab75 Fix missing Radio icon for streams in feed settings
Both FeedSettingsForm and ContentSettings were missing the 'streams'
entry in their ICONS map, causing it to fall back to a Palette icon
instead of the Radio icon used everywhere else.
2026-02-21 00:15:31 -06:00
Chad Curtis 99e864f815 Hide auth-only UI elements when logged out
Hide bookmarks, profile nav links, profile settings tab, wallet,
and network settings (relays, blossom servers) from logged-out users.
2026-02-21 00:11:40 -06:00
Chad Curtis 4707b37ad7 Fix emoji picker flashing quick select after deeper picker selection
Close the popover via onClose callback when an emoji is selected from
the full picker. Add a 300ms cooldown (justClosedRef) to prevent the
popover from immediately reopening via hover when the picker disappears
and the cursor lands on the trigger button.
2026-02-20 23:49:02 -06:00
Chad Curtis 58d7511545 Apply theme immediately on selection during onboarding 2026-02-20 22:21:02 -06:00
Chad Curtis 1d967b98d0 Integrate signup into onboarding flow, replace SignupDialog
Sign up now triggers the full onboarding overlay instead of a dialog.
The flow starts with keygen -> download key (logs in) -> profile setup
(kind 0) -> then continues with the existing settings questionnaire
(theme, content, safety, follows, outro).

Added OnboardingContext with useOnboarding().startSignup() hook so any
component can trigger the signup flow. Updated LoginArea, Feed,
LeftSidebar, and FloatingComposeButton to use it instead of
SignupDialog. SignupDialog is no longer imported by any component.
2026-02-20 22:18:51 -06:00
Chad Curtis a88a44d59e Preload feed behind outro when user followed a pack
If the user followed at least one pack during onboarding, render the
app tree (invisible) behind the outro overlay so React Query starts
fetching the follows feed in the background. When they tap 'Let's go',
content is already loaded. Users who skipped follows don't preload
since they'll land on the global feed which loads fast enough.
2026-02-20 22:11:43 -06:00
Chad Curtis f64ef2aed7 Fix outro wording: weird -> fun 2026-02-20 22:08:19 -06:00
Chad Curtis d5772de200 Revise outro text to be warmer and more playful 2026-02-20 22:06:50 -06:00
Chad Curtis f279b456c0 Shorten outro text 2026-02-20 22:06:37 -06:00
Chad Curtis c17815ea0b Add follow packs step and sentimental outro to onboarding
After saving settings, onboarding now checks the user's kind 3 follow
list. If empty, it shows suggested follow packs (starting with
naddr1qvzqqqyckypzpyexz3t34l966ngh5xg7u2q788hthdqmj0av3lv8s2tz9t43zt6d)
with member avatars and a Follow All button. Users with an existing
follow list skip this step.

The final step is now a warm outro thanking the user and inviting them
into the app, replacing the old spinner-only done screen.
2026-02-20 22:06:04 -06:00
Chad Curtis 1c640e3202 Use ChestIcon for treasures in onboarding content picker 2026-02-20 21:56:20 -06:00
Chad Curtis 3bcbd53100 Use lucide icons in onboarding and disable follow packs by default
Replace emoji icons with lucide-react components (Clapperboard, BarChart3,
MapPin, Palette, Users, Radio) in the content type picker. Remove follow
packs from the default selection for new users.
2026-02-20 21:53:29 -06:00
Chad Curtis ff43177aa5 Decrypt and apply encrypted settings before releasing sync overlay
useInitialSync now fetches the kind 30078 event, decrypts it with the
user's NIP-44 signer, and applies theme/feedSettings/contentWarningPolicy
to the config before transitioning out of the sync screen. It also seeds
the TanStack query cache so useEncryptedSettings and NostrSync don't
redundantly re-fetch or re-decrypt the same event.
2026-02-20 21:49:44 -06:00
Chad Curtis 726af608a0 Add initial sync screen with setup questionnaire for new devices
When a user logs in, show a sync spinner while fetching their settings
from Nostr relays. If existing settings are found (returning user on a
new device), apply them and proceed. If no settings exist (fresh account),
walk through a brief questionnaire for theme, content preferences, and
content safety policy. Uses sessionStorage to avoid re-showing on refresh.
2026-02-20 21:47:25 -06:00