Commit Graph

1376 Commits

Author SHA1 Message Date
Chad Curtis fa0a88cc02 fix: preserve custom background when switching away from custom theme 2026-03-03 05:00:24 -06:00
Chad Curtis 57bf09a701 fix: match profile feed opacity to main feed 2026-03-03 04:58:02 -06:00
Chad Curtis 24307b9e9f Replace margin with padding on sticky page headers 2026-03-03 04:45:59 -06:00
Chad Curtis aa6dc754ff fix: update Feed settings description to distinguish from Content 2026-03-03 04:39:57 -06:00
Chad Curtis e14312bf1e Revert "feat: add lead image and updated description to Feed settings page"
This reverts commit 01c229add7.
2026-03-03 04:39:19 -06:00
Chad Curtis 01c229add7 feat: add lead image and updated description to Feed settings page 2026-03-03 04:38:38 -06:00
Chad Curtis 99704fed7f feat: rename Content to Feed, add Content settings page with muted/sensitive/theme prefs 2026-03-03 04:37:29 -06:00
Chad Curtis dee47c0907 fix: prevent bare dot from triggering NIP-05 redirect in search 2026-03-03 04:33:10 -06:00
Chad Curtis 3801b007e8 fix: sync lightbox index when sidebar opens media while tab is already active
When the media tab was already mounted, clicking a media item in the sidebar
set sidebarMediaUrl (initialOpenUrl) but flatIndex state didn't update because
useState only uses its initial value at mount time. Add a useEffect to sync
flatIndex whenever initialIndex (derived from initialOpenUrl) changes.
2026-03-03 01:49:29 -06:00
Chad Curtis 984fc2d869 Unify following-tab empty states with shared FeedEmptyState component 2026-03-03 01:42:57 -06:00
Chad Curtis bb55743ceb Fix mobile live stream layout: full-width video, scrollable chat
- Make main a flex container on mobile so chat flex-1 works correctly
- Add overflow-hidden to chat wrapper to complete flex scroll chain
- Remove horizontal padding and border-radius from video on mobile
- Apply xl:rounded-2xl to player component (main and error states)
2026-03-03 01:32:31 -06:00
Chad Curtis 4961cac19d fix: profile right sidebar persisting after navigation
The cleanup guard in useLayoutOptions compared store.getSnapshot() (a LayoutSnapshot spread copy) against prev.current (the original LayoutOptions reference), which are always different objects. The guard was never true, so store.reset() never fired on unmount and the ProfileRightSidebar leaked to other pages. Added getOptions() to expose the raw options reference for a correct identity comparison.
2026-03-03 01:21:02 -06:00
Chad Curtis 7f26bebc8d fix(fab): use fixed positioning so FAB hovers above nav bar regardless of scroll 2026-03-03 01:17:03 -06:00
Chad Curtis 6310c2d6bf fix(settings): scope min-h-screen to SettingsPage only, not shared layout 2026-03-03 01:15:11 -06:00
Chad Curtis a79bb72a23 fix(settings): stretch settings page to fill full remaining container height 2026-03-03 01:13:48 -06:00
Chad Curtis 0ab4d8faef fix(vines): hold thumbnail until video ready, add buffering spinner, hide UI until canplay 2026-03-03 01:11:17 -06:00
Chad Curtis 037b2ab16a Make client tag a link when value is a valid hostname 2026-03-03 01:07:10 -06:00
Chad Curtis aea1151537 Improve emoji reactions UX
- Resize reaction emojis to h-4 w-4 in stats row and reaction button
- Fix vertical alignment of emojis using inline-flex and leading-none
- Split reposts/quotes into separate stat buttons each opening correct tab
- Fix interactions modal tab sync when already open
- Un-react by clicking emoji button on already-reacted post
- Disable hover-to-open picker when already reacted
- Remove gap between triple emojis in stats row, suppress underline on hover
- Make client tag a link when value is a valid hostname
2026-03-03 01:06:29 -06:00
Chad Curtis b23a7b07f0 optimistically bump reply count after posting a comment 2026-03-03 00:48:12 -06:00
Chad Curtis 64c9936014 fix vine comments and toast visibility
- ComposeBox: invalidate the correct 'event-comments' cache key after
  posting a NIP-22 comment so CommentsSheet refreshes immediately
- toast: raise z-index to 300 so it renders above the CommentsSheet
  backdrop blur (which sits at z-200)
2026-03-03 00:45:31 -06:00
Chad Curtis 09271be935 add VineRepostButton: tap to repost/unrepost directly on vine
Replace RepostMenu popover with a dedicated VineRepostButton that works
like VineHeartButton — single tap to repost, tap again to undo — with
optimistic cache updates so the button color changes immediately.

The popover menu was invisible on the dark fullscreen video background
and provided no visible confirmation of the action.
2026-03-03 00:39:54 -06:00
Chad Curtis 530f5b4d0d fix vine reactions and kind 16 repost for addressable events
- VineHeartButton: add optimistic cache updates and query invalidation on
  reaction so the heart fills and count increments immediately without
  a page refresh
- RepostMenu: include NIP-18 'a' tag (kind:pubkey:d-tag) when reposting
  addressable events (30000–39999) so kind 16 events are properly linked
  back to the original vine
2026-03-03 00:36:55 -06:00
Chad Curtis 2ecd89b368 add pinch/wheel zoom and pan to lightbox images with double-tap to zoom 2026-03-03 00:15:28 -06:00
Chad Curtis 1a2489455f clean up lightbox pagination: sentinel URL approach removes hasMore/springBackRef props 2026-03-03 00:12:10 -06:00
Chad Curtis 1bcdbd4b12 auto-advance lightbox when page loads, spring back only if fetch yields no new items 2026-03-03 00:08:56 -06:00
Chad Curtis c715d53903 swipe past last media item shows loading slot and triggers pagination 2026-03-03 00:05:33 -06:00
Chad Curtis efa0955ed2 trigger pagination from lightbox on photos feed page 2026-03-03 00:00:58 -06:00
Chad Curtis 609cddab1e trigger media pagination when lightbox reaches last item 2026-03-02 23:59:59 -06:00
Chad Curtis 39bf5915fc fix lightbox spinner persisting after swipe by tracking loaded state per URL 2026-03-02 23:57:18 -06:00
Chad Curtis 771b3df9d8 fix lightbox: stable image keys prevent reload, dialog z-index above lightbox, media tab auto-open 2026-03-02 23:56:06 -06:00
Chad Curtis bcbb89163a render consecutive inline images as gallery grid in kind 1 notes 2026-03-02 23:44:53 -06:00
Derek Ross 6abe9fade0 Hide FAB while ComposeBox is visible, fade in on scroll
Use IntersectionObserver on the ComposeBox wrapper in Feed.tsx to track
its visibility. When visible, hide the FAB to avoid redundancy. When the
user scrolls past the compose area, the FAB smoothly fades in with an
upward slide animation. Extends LayoutStore with fabHidden state that
is part of the snapshot so useSyncExternalStore triggers re-renders.
2026-03-02 21:35:36 -05:00
Derek Ross 3c733b58bd Fix lightbox image clipping, passive touchmove warning, and swipe loading
Add responsive padding to lightbox swipe slots to clear the top bar and
bottom bar overlays. Change LightboxImage from w-full/h-full to
max-w-full/max-h-full so images scale within the padded area instead of
stretching behind the UI controls.

Register touchmove handler via addEventListener with passive:false
instead of React's onTouchMove prop, fixing the 'Unable to
preventDefault inside passive event listener' console warning.

Fix swiped images never appearing by checking img.complete on mount —
cached images from the pre-rendered prev/next slots may not fire onLoad,
leaving them stuck at opacity-0.
2026-03-02 21:10:05 -05:00
Chad Curtis aa643fb8d7 fix(media): kind-1 comment button navigates to post instead of opening sheet
Eliminates the stale-replies problem entirely for kind-1 events by linking
to the post detail page rather than showing an inline comments overlay.
2026-03-02 18:18:00 -06:00
Chad Curtis 529761f409 fix(comments): key CommentsSheet on event.id to force remount on image change
Keying on event.id ensures the component fully unmounts and remounts when
swiping to a new image, clearing stale replies instantly.
2026-03-02 18:14:17 -06:00
Chad Curtis 7cef7aafaa fix(comments): show skeleton while fetching new event's replies
React Query serves cached data instantly for the previous event while the
new fetch is in-flight, causing stale replies to flash. Track the event id
the current data belongs to and treat any in-flight fetch for a different
event as a loading state, showing skeletons instead of stale replies.
2026-03-02 18:13:07 -06:00
Chad Curtis b8170bc971 fix(comments): clear stale replies immediately on event change
Previously the query was gated on 'open', so when swiping to a new image
the old event's replies stayed visible until the new query resolved.
Now the event is always passed so the query key updates instantly.
2026-03-02 18:11:41 -06:00
Chad Curtis 4bcc589e94 feat(media): video/audio support, profile sidebar click, kind-1 reply handling
- MediaGrid/Lightbox: support video (VideoPlayer) and audio (AudioVisualizer)
  with proper per-type rendering in grid thumbs and lightbox strip slots
- Audio thumb shows author avatar with idle-ring animation instead of plain icon
- LightboxSlot renders VideoPlayer/AudioVisualizer constrained to max-w-lg
  matching the audio visualizer width; resolves author avatar for audio via useAuthor
- useProfileMedia: add audio kinds 36787, 34139, 30054, 30055 to query
- CommentsSheet: kind-1 events query only kind-1 replies (not 1111), show
  'Replies' header and 'Add a reply…' placeholder; all other events use 1111
- PhotoBottomBar: simplified back to single CommentsSheet; removed ReplyComposeModal
- CommentsSheet z-index raised to z-[200] so it appears above the Lightbox (z-[100])
- ProfileRightSidebar: onMediaClick callback; ProfilePage wires it to switch
  to media tab and open lightbox at the clicked URL via initialOpenUrl prop
2026-03-02 18:09:44 -06:00
Chad Curtis 83fae3bfea fix(lightbox): show per-event image counter, smooth swipe commit, lower threshold
- MediaGrid flat entries now carry indexInEvent + countInEvent; counter in
  top bar shows '2 / 4' for the current event only, hidden when single image
- swipeCommitted ref + rAF reset so strip snaps invisibly after commit
- Commit threshold lowered from 30% to 20% viewport width
2026-03-02 17:52:36 -06:00
Chad Curtis ad0efdff60 fix(lightbox): smoother swipe and consistent top/bottom padding
Swipe: replace React state-driven translation (caused re-renders + jarring
snap-back) with direct DOM mutation via ref. Axis is locked on first
significant movement; at edges resistance is 20% rubber-band. On release,
if past the 30% threshold the next/prev fires and the position resets
without animation; otherwise it springs back with a single cubic-bezier
transition.

Bottom bar: matches top bar rhythm (px-4 py-3 + safe-area-bottom).
Gradient scrim is now a fixed h-32 pseudo-element that extends upward from
the bottom of the bar, independent of the content height, so it fades
cleanly over the image without needing extra pt-10 padding on the strip.
2026-03-02 17:40:42 -06:00
Chad Curtis 1cb05e4212 refactor: extract MediaGrid + PhotoBottomBar; wire profile media tab to grid view
- Extract PhotoBottomBar into its own component; remove the bottom-nav clearance
  padding (the full-screen lightbox overlay covers the nav bar, only safe-area
  inset is needed)
- Create MediaGrid: generic 3-col square-thumbnail grid that handles imeta tags
  (NIP-68/94 native kinds) and kind-1 inline image URLs; self-contains overlay
  state and opens Lightbox with PhotoBottomBar + cross-event navigation
- PhotosFeedPage now delegates entirely to MediaGrid + MediaGridSkeleton
- Profile media tab replaced: was a NoteCard list, now renders MediaGrid for a
  proper Instagram-style grid experience matching the /photos page
2026-03-02 17:35:54 -06:00
Chad Curtis 485e7cd1c9 refactor(photos): DRY up PhotosFeedPage by extending Lightbox instead of custom overlay
Replace the bespoke PhotoSlide / PhotoCard / PhotoDetailOverlay stack (~250 lines) with a
thin extension of the existing Lightbox component. Lightbox gains bottomBar, onNextEvent,
and onPrevEvent props; ImageGallery forwards them through. PhotosFeedPage now opens a plain
Lightbox with author info + reactions injected via bottomBar, and cross-event swipe/keyboard
navigation wired through onNextEvent/onPrevEvent. Page shrinks from 626 → ~300 lines.
2026-03-02 17:30:46 -06:00
Alex Gleason 9da62f46cf Change wall compose placeholder to 'Write on {user}'s wall' 2026-03-02 14:16:02 -06:00
Alex Gleason 5657c0d7cd Improve NIP-72 community context for comments: show 'Posted in' with community preview 2026-03-02 13:30:22 -06:00
Alex Gleason d8dd662380 Add NIP-72 community detail view for kind 34550 events 2026-03-02 13:19:42 -06:00
Alex Gleason 98459638db Fix sidebar search input width with min-w-0 instead of spacer div
Remove the invisible spacer div hack (w-8 shrink-0) and restore gap-3
on the search row. The actual fix is min-w-0 on the input, which lets
it shrink below its intrinsic minimum width in the flex container.
2026-03-02 12:18:09 -06:00
Alex Gleason d10d87bcb4 Fix sidebar More menu search input pushing content out of bounds
The search input with flex-1 extended ~32px further right than item
labels below (which have a Plus button consuming that space). Added a
matching w-8 spacer and min-w-0 so the input aligns with item labels
and cannot force the row wider than the dropdown.
2026-03-02 12:15:46 -06:00
Alex Gleason 37b16e4332 Remove bg-muted from sidebar More menu search bar to fix visual clipping
The bg-muted/50 background on the search row extended wider than the
item rows below (which have a Plus button consuming right-side space),
creating a visible purple block and visual misalignment that made
content appear truncated on the left.
2026-03-02 12:13:45 -06:00
Alex Gleason 6c3fb905d9 Open sidebar More menu upward to prevent bottom clipping
The More... trigger sits at the bottom of the sidebar, so the dropdown
was opening downward into very little available space, getting clipped.
Use side="top" so it opens upward where there is ample room, and add
collisionPadding for a safety margin from viewport edges.
2026-03-02 12:12:30 -06:00
Alex Gleason 28507550de Restore border-b to NoteCard, remove compensating divide-y from containers
The original border-b border-border was removed from NoteCard in 9bd646b
for a photos overlay feature that no longer uses NoteCard. This forced
every container to add divide-y divide-border as a workaround, but
several pages were missed (Bookmarks, Events, Trends, Search, etc).

Restore NoteCard's self-bordering and remove the now-redundant divide-y
wrappers. Existing overrides (EmbeddedNaddr !border-b, Notifications
border-0) continue to work correctly.
2026-03-02 12:00:13 -06:00