Replace the standalone emoji bubble with the user's normal avatar plus a
small reaction emoji badge at the bottom-right corner. This keeps the
avatar column aligned with other threaded posts while still making the
reaction visually distinct.
Reaction events now display with a prominent emoji bubble, small inline
avatar, author name, and 'reacted' label — making them visually distinct
from regular posts in both thread ancestors and standalone detail views.
Registers 'ai-chat' in SIDEBAR_ITEMS with the Bot icon, linking to
/ai-chat. Requires authentication since the Shakespeare API needs a
logged-in Nostr account.
The tool now accepts the complete theme configuration:
- Colors (required): background, text, primary as HSL strings
- Font (optional): any of the 17 bundled font families
- Background image (optional): URL with cover/tile mode
The system prompt, tool executor, and badge UI are all updated to
reflect the richer theme capabilities.
The tool now accepts background, text, and primary as HSL color strings
and calls applyCustomTheme to set a fully custom theme, rather than
just switching between light/dark/system presets.
Adds /ai-chat route with a Shakespeare AI chat interface that supports
OpenAI-compatible tool calling. Includes a set_theme tool that lets the
AI switch between light, dark, and system themes on the user's behalf.
Kind 1222 (voice reply to kind 1) was missing from useReplies, and
kind 1244 (NIP-22 voice reply) was missing from useComments. Voice
messages were published correctly but never appeared because query
filters didn't include their kinds.
- useReplies: [1] -> [1, 1222]
- useComments: [1111] -> [1111, 1244]
- useWallComments: [1111] -> [1111, 1244]
- VinesFeedPage: [1111] -> [1111, 1244]
- useNotifications: added 1222, 1244
- useHasUnreadNotifications: added 1222, 1244
- useNativeNotifications: added 1222, 1244 with 'New voice message' title
The avatar was confusing as a dual-purpose element. Now uses a clean
circular play/pause button with primary color theming, separate from
the author info already shown by NoteCard's header.
Implement recording, publishing, and rendering of NIP-A0 voice messages:
- VoiceMessagePlayer: compact waveform bar player when imeta waveform
data is available, falls back to existing AudioVisualizer sinewave
- useVoiceRecorder: MediaRecorder hook with real-time amplitude capture,
60s max duration, and waveform sampling for NIP-A0 imeta tags
- ComposeBox: mic button in toolbar with recording UI (live waveform,
timer, cancel/send controls), publishes kind 1222 (root) or 1244
(NIP-22 reply) with imeta waveform and duration fields
- NoteCard + PostDetailPage: render kind 1222/1244 via VoiceMessagePlayer
- Feed settings: voice messages registered in Other Stuff > Media with
feed toggle (feedIncludeVoiceMessages), defaults to off
Cap the dialog at 85dvh with overflow-y-auto so it scrolls when
content is tall. Also add a hard max-h on the post preview text
to prevent line-clamp-3 failures with nested block elements from
NoteContent.
Replace the manual thumbnail <img> overlay with the browser-native
poster= attribute on the <video> element. The browser renders the
poster immediately before any video data is fetched, even on cards
with preload=none, eliminating black frames during fast scrolling.
Also changes the card background from pure black to neutral-900 as
a subtle fallback for vines with no thumbnail.
- Remove defaultZapComment config; derive from appName instead
- Add appId (string) for NIP-78 d-tag prefixes (e.g. ${appId}/metadata)
- Add client (optional NIP-89 addr) as third element of client tags
- Update useNostrPublish and useEncryptedSettings to use config.appName
and config.client for client tags instead of location.hostname
- Replace hardcoded 'ditto-metadata' d-tag with ${config.appId}/metadata
- Remove Default Zap Comment setting from AdvancedSettings UI
- Add .vine-slide-height CSS utility that subtracts env(safe-area-inset-top/bottom) so slides don't bleed under the bottom nav on PWA/APK with home indicator
- Replace all hardcoded calc(100dvh-9.5rem) vine heights with the new utility
- Preload active video with 'auto', adjacent (±1) with 'metadata', and far-away cards with 'none' to speed up video playback on swipe without wasting mobile bandwidth
When replying to your own post, the compose box excludes your pubkey
from p tags. This left self-replies with no 'Replying to' context,
making them look like top-level posts. Now falls back to the parent
e-tag author hint or the event author itself so self-replies always
show thread context.
Closes#3
Replace the dual-registry system (BUILTIN_SIDEBAR_ITEMS in useFeedSettings
+ EXTRA_KINDS in extraKinds) with a single SIDEBAR_ITEMS array in
sidebarItems.tsx. Every sidebar-capable item now has a consistent shape:
id, label, path, icon, and optional requiresAuth.
- Delete extraKindIcons.ts; icons now live in the SIDEBAR_ITEMS registry
- Remove BUILTIN_SIDEBAR_ITEMS, isBuiltinItem, getBuiltinItem, EXTRA_KIND_IDS
from useFeedSettings.ts; validation uses SIDEBAR_ITEM_IDS
- Remove HiddenSidebarItem.builtin field (was never read by consumers)
- Simplify SidebarNavItem.tsx (no more dual icon map lookup)
- All consumers now import sidebarItemIcon from @/lib/sidebarItems
- ExtraKindDef/EXTRA_KINDS unchanged (still used for feed/content settings)
Previously, extra-kind items in sidebarOrder were silently dropped
unless their corresponding feedSettings showKey was also enabled.
This made it impossible to add items like 'webxdc' to the sidebar
via build config alone.
Now computeOrderedItems uses sidebarOrder directly — any recognized
item (built-in or extra-kind with a route) present in the array is
shown. addToSidebar/removeFromSidebar no longer toggle feedSettings
showKey values, keeping sidebar config and feed settings independent.