Prevent the compose modal from being accidentally dismissed when the user
taps the emoji/GIF picker overlay to close it. On mobile this was very
easy to trigger, causing the draft to be lost.
Add onInteractOutside and onEscapeKeyDown handlers to the compose modal's
DialogContent that detect when a nested dialog (emoji picker) is open and
prevent the dismiss event from propagating to the parent modal.
Notifications now say 'reacted to your badge', 'reposted your theme',
'commented on your nsite', etc. instead of always saying 'your post'
or 'your note'. Uses the referenced event's kind to look up a
human-readable noun from a comprehensive kind-to-label map.
The BadgeDetailContent action bar had reactions, reposts, and comments
but was missing the zap button that NoteCard renders for the same
events in the feed.
Extract shared useInsertText hook to DRY up the duplicated text
insertion logic across ComposeBox, DMChatArea, and ZapDialog.
Add EmojiPicker (GUI) and EmojiShortcodeAutocomplete (:shortcode
typing) to the zap comment textarea, and also add shortcode
autocomplete to the DM chat input which was previously missing it.
Closes#176
On mobile, toasts enter from the top but previously could only be swiped
right to dismiss. Now swipe direction is responsive: swipe up on mobile
(top-positioned), swipe right on desktop (bottom-right positioned). Exit
animations also match the swipe direction at each breakpoint.
Kind 16767 events previously hardcoded description to undefined, so the
theme description never appeared on 'updated their theme' posts in the
feed or detail view.
Three changes:
- buildActiveThemeTags now accepts and includes a description tag, so
future kind 16767 events carry the description directly
- setActiveTheme accepts description to thread it through publishing
- ThemeContent extracts the description tag from kind 16767 events, and
for older events without one, falls back to querying the source theme
definition via the a-tag reference
@capacitor/filesystem and @capacitor/share are dynamically imported
behind a Capacitor.isNativePlatform() guard, but Vite's import analysis
plugin still tries to resolve them at transform time in dev mode. This
causes a 'Failed to resolve import' error when running the dev server.
Excluding them from optimizeDeps prevents Vite from pre-bundling these
packages, letting the dynamic imports resolve naturally at runtime.
On the feed, theme descriptions are truncated to a single line. On the
post detail page, the full description is now displayed so users can
read long descriptions that don't fit in the thumbnail card.
Closes#124
The <a download> and <a target="_blank"> patterns don't work in
WKWebView. Add downloadTextFile() and openUrl() utilities in
src/lib/downloadFile.ts that use @capacitor/filesystem and
@capacitor/share on native platforms, falling back to standard
browser behavior on web.
Update all call sites: onboarding key download (InitialSyncGate,
SignupDialog), image lightbox buttons (ImageGallery, ProfilePage).
Document Capacitor compatibility constraints in AGENTS.md.
Closes#186. Badge award notifications now display a visual preview
card with the badge image, name, and description for both single and
grouped badge notifications.
Show the sender's profile pic via the EnvelopeCard component (the same
Wii-Mail-inspired envelope tile used in the letters inbox). The card
auto-decrypts to display stationery colors and the sender's avatar as a
wax seal. Clicking the envelope navigates to /letters.
Letters were completely absent from the notification pipeline — users had
to visit the Letters page to discover incoming letters. This integrates
kind 8211 into every layer of the notification system:
- useNotifications: query, grouping, and referenced-event exclusion
- useHasUnreadNotifications: unread dot indicator
- NotificationsPage: LetterNotification component with link to /letters
- NotificationSettings: toggleable Letters row
- notificationTemplates: web push template
- Android NotificationRelayService + NostrPoller: native push support
- EncryptedSettings + schema: letters preference field
Closes#188
The useBadgeFeed hook required a logged-in user before enabling the query,
causing the follows tab to show loading skeletons forever when logged out.
Now fetches the Team Soapbox follow pack (kind 39089) and uses its members
as the authors filter, giving logged-out users a curated badge feed.
- MobileTopBar: changed from sticky to fixed positioning with scroll-hide
transform animation (mirrors bottom nav behavior via useScrollDirection)
- MainLayout: replaced -mt-mobile-bar overlap trick with pt-mobile-bar
padding since the top bar is now fixed; added data-nav-hidden attribute
to drive CSS transitions on sticky sub-headers
- SubHeaderBar/top-mobile-bar: sticky top offset transitions to 0 when
the top bar hides, keeping sub-headers flush with the viewport top
- NotificationsPage, ProfilePage: added arc overhang spacer after
SubHeaderBar to match Feed's spacing
Expose COMMIT_SHA and COMMIT_TAG via import.meta.env at build time.
In CI, these come from GitLab env vars; locally they fall back to git.
The changelog page now shows:
- A pre-release banner when the build is untagged, with a link to
the GitLab diff between the latest release and main
- An external link icon on each version card header linking to the
GitLab release page for that version