Change the event counter from a single global counter to per-filter
tracking using Filter.match(). Each filter's limit is now respected
individually - fulfilled filters are excluded from subsequent pages,
and pagination stops when all filters with limits are satisfied.
https://claude.ai/code/session_01Baaira4xoEHEsaSQCX52Sy
Extract the paginated relay download into a reusable INostrClient
extension (NostrClientDownloadFromRelayExt.kt) in the Quartz
commonMain accessories package. Uses Channel-based event collection
for KMP compatibility (no JVM-only atomics).
EventSyncViewModel.downloadFromRelay now delegates to the Quartz
extension, keeping the ViewModel thin.
Add NostrClientDownloadFromRelayTest integration test against
wss://nos.lol with Filter(kinds = [MetadataEvent.KIND], limit = 10)
to verify paginated downloads return correctly-typed events.
https://claude.ai/code/session_01U8qF9mK4UBvXsXP1zNMXfX
- Convert filteredTransactions from cold Flow to StateFlow via stateIn()
to ensure reliable state updates with collectAsState()
- Add 30s timeout to NWC requests (fetchBalance, fetchTransactions,
loadMoreTransactions) so loading state resets if wallet doesn't respond
https://claude.ai/code/session_01CdNY7qYDRHJr1jhAFvVgzj
Replace aspectRatio modifier with BoxWithConstraints that manually
calculates height from aspect ratio and clamps it to the max height
constraint. Video now stays within its allocated space in the card,
so controls are accessible and content below is not overlapped.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove fillMaxWidth before aspectRatio so the caller's heightIn(max)
constraint is respected. Video now sizes to fit within the NoteCard
without overlapping the author header or overflowing the card.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Single hover zone on entire video — no more flickering from competing
zones. Play button always visible when paused, bottom controls appear
on hover (works in fullscreen too)
- Media height capped to 50% of window (min 200dp) so post text is
never pushed off-screen by large media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Center play button always visible when paused
- Pause button appears on center hover when playing
- Bottom controls bar only appears when hovering the bottom area
- Controls also show when paused for discoverability
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Controls (play button, seek bar, volume) are hidden by default and
appear when the mouse enters the video area. They auto-hide 2s after
the mouse leaves.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add VideoThumbnailCache that grabs the first rendered frame from VLC
and caches it in memory. Videos in the feed now show a thumbnail
preview instead of a blank background before the user clicks play.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace plain-text NotePreviewCard with full NoteCard in search results
so images, videos, and author avatars are visible inline without having
to open the note.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove maxLines/TextOverflow from RichTextContent so post text is
never truncated
- Media height = window height minus 200dp chrome, so each image/video
fits in the visible area without scrolling
- Use ContentScale.Fit for images to scale down while keeping aspect
ratio instead of filling width and overflowing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove maxLines=10 on post text so content is never truncated
- Profile header/card/tabs now scroll with content instead of staying
sticky — scrolls away naturally as you browse posts
- Floating compact header (back + avatar + name) slides in when
scrolling up and the full header is out of view
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded 400.dp max with window-relative height so media
(images and videos) never overflow the visible area and controls
are always accessible without scrolling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace WindowPlacement.Fullscreen (macOS maximize-only) with
GraphicsDevice.setFullScreenWindow() for true exclusive fullscreen that
hides menu bar and dock. Split single cycling view mode button into two
distinct toggles (theater + fullscreen). Hide all navigation chrome
(sidebar, nav rail, dividers, arrows, overlay menus) during fullscreen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Bundle VLC via ir.mahozad.vlc-setup plugin (all plugins for network playback)
- BundledVlcDiscoverer (Win/Linux) and MacOsVlcDiscoverer for bundled VLC discovery
- Lazy player activation — no VLC calls during composition, only on play click
- Pre-init VLC on background thread at startup
- Video controls: seek slider, volume, mute, fullscreen (two-row layout, no clipping)
- Buffering indicator (CircularProgressIndicator) while loading
- ActiveMediaManager enforces single-player — pauses others when new video plays
- Fullscreen passes seek position so lightbox resumes from current playback point
- LightboxOverlay renders videos (DesktopVideoPlayer) or images (ZoomableImage)
- Gitignore downloaded VLC binaries (appResources/{linux,macos,windows}/)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>