Build tags JSON directly into the StringBuilder instead of allocating
an intermediate JsonArray and calling toString(), which created three
copies of the data (JsonArray objects + toString string + StringBuilder).
Add NavController.navigateSafe() extension that checks the current
back stack entry lifecycle is RESUMED before navigating. Prevents
"Cannot transition entry that is not in the back stack" crash caused
by rapid successive navigate() calls during transitions.
repostAuthors stored plain LinkedHashSet instances that were written to
from relay IO coroutines and iterated from the feed filter coroutine on
Dispatchers.Default. Replace with ConcurrentHashMap.newKeySet() at all
four creation sites so concurrent add/iterate is safe.
Fixes crash on Samsung SM-A546U (Android 13) at
EventRepository.isRepostedByAny.
The drawer was reading user status with a one-shot call that only
updated on unrelated recompositions. Collect statusVersion so the
optimistic update in setUserStatus triggers an immediate recompose.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The newline trimming before URLs was stripping line breaks from
profile bios, smushing text and links together. Add trimBlankLines
parameter to parseContent, disabled when plainLinks is true (which
indicates profile/bio rendering).
- Tap any stat in the 24h summary bar to filter notifications to
that type (replies, reactions, zaps, reposts, mentions, DMs).
Active filter highlighted with primary color. Tap again to reset.
- Zap stat icon respects the bolt/bitcoin toggle from Interface
settings, matching the rest of the app.
Add setUserStatus() to EventRepository for direct cache updates.
Call it in publishUserStatus() before the relay round-trip so the
status change appears immediately in the drawer and on posts.
Add debounced auto-search that fires 500ms after the user stops
typing (minimum 2 characters). Results populate below the search
box without needing to press Enter. Each keystroke resets the timer
to avoid spamming the relay. Search refs are seeded on screen init
so auto-search works immediately.
- Add bright center flash and expanding ring on zap confirmation
- Add 12-20 spark particles (white dots with orange glow) alongside
bolt particles for more energy
- Increase canvas from 120dp to 160dp for wider spread
- Extend duration to 1.1s for more dramatic effect
- Extract duplicate NIP-38 status processing into shared helper method
- Add timestamp tracking so out-of-order status events don't regress
- Fix reply attribution to use reply target event's pubkey instead of
first p-tag (which may be an unrelated mention)
- Make replyToName reactive via profileVersion so it updates when
profiles load instead of showing hex permanently
- Remove debug Log.d calls from ThreadViewModel (ran on every rebuild)
- Wrap emojiRemoveCallback in DisposableEffect for proper lifecycle cleanup
- Fix recovery phrase TalkBack leak: conditionally render mnemonic words
instead of overlaying on top of real text
- Add ERROR state to Nip05Badge with retry-on-tap and refresh icon
- Restore live stream zap functionality removed in prior commits:
recipient override, a-tag for addressable events, chat relay hints,
zap error dialog, and stream-level zap action
- Revert follow indicator to avatar badge (circle with checkmark on
profile picture) instead of inline checkmark next to display name
- Add ic_wisp_logo vector drawable with radial gradient from official SVG
- Replace bitmap ic_launcher_foreground with vector on splash and auth screens
- Add radial gradient glow behind logo for contrast on profile grid
- Animate wisp icon with gentle bob and sway on splash screen
- Match web font style: SansSerif W500, white on splash, no letter spacing
- Fix thread scroll-to-reply with NIP-10 fallback and layout-aware retry
- Auto-scroll drawer when Settings expands
- Add statusBarsPadding to drawer so profile doesn't overlap phone UI
- Fix bottom nav bar gap with NavigationBarDefaults.windowInsets
- Zero out contentWindowInsets on all screens inside NavHost (Profile,
Thread, Notifications, Search, Hashtag Feed, Article, Bookmarks)
to eliminate duplicate bottom padding from parent's bottom nav bar
- Extend bolt/bitcoin toggle to drawer wallet icon, drawer lightning
address icon, and profile zap/lightning address icons
- Hide recovery phrase behind full-opacity tap-to-reveal overlay
- Persist balance hidden state to SharedPreferences
- Fix balance unit pills wrapping on small screens
- Add squircle shape to sign-in logo for non-black themes
- Remove quotation marks from zap messages in TopZapperBanner
Save pending reaction callback when opening emoji library from popup.
Invoke with first selected emoji when library sheet completes.
Applied across all EmojiLibrarySheet call sites.
- Replace hand-drawn bolt paths with ic_bolt vector in both animations
- LightningAnimation: smooth pulse instead of jittery flicker
- ZapBurstEffect: bolt particles with staggered ease-out
- Fix bolt aspect ratio to 14x22dp
- Replace reply arrow with comment bubble (ModeComment) at 22dp
- Fix case-sensitive JSON key lookup (e.g. Blockstream)
- Extract shared Nip05Badge composable with self-contained state
- Impersonator: grey text + red cancel icon; Error: faded grey, no icon
- Pass nip05Repo to all NoteActions constructors (6 missing sites)
- Replace follow badge on avatar with inline checkmark next to name
- Hide nip05 field for blank identifiers
- Remove message text from preset chips, show small message icon instead
- Pre-fill message field when selecting a preset, clear when switching
- Move save button into custom amount flow
- Sort presets by amount ascending
- Flatten chip layout to single Row for consistent height
Subscribe to kind 30315 events alongside profile metadata in
OutboxRouter, MetadataFetcher, and self-data startup subscription.
Process status events in both addEvent and cacheEvent paths in
EventRepository to avoid seenEventIds dedup race. Route kind 30315
from EventRouter to addEvent for events from unknown subscriptions.
Display status in italic faded text under the display name in
PostCard, matching the style used by Amethyst and Damus.
Add status editor in the navigation drawer — tap "Set status..."
below the nip05 to open a dialog. Publishes kind 30315 with d-tag
"general" to write relays. Empty content clears the status.
Show "replying to [name]" below the display name when a post is a
reply. The reply-to author is resolved from the first p-tag via
eventRepo. Tapping the name navigates to their profile.
- Add "Zap this stream" button in stream info bar with pending/success states
- Insert zap announcement messages in chat when someone zaps the stream
- Track and display total stream zap sats next to the zap button
- Fix zap recipient to target the actual streamer (p-tag Host), not the
stream provider (event author)
- Use NIP-57 "a" tag for addressable events in zap requests so receipts
are properly associated with the stream
- Include stream chat relays in zap request relay hints so receipts reach
the streamer and chat room subscribers
- Fix EventRouter to route live-react and live-zap subscriptions to
LiveStreamRepository for proper reaction/zap tracking
- Show zap error dialog on failure
- Bump version to v0.17.1 (code 67)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The since-based filtering was causing visibility bugs for users due to
clock skew and stale timestamps. Always fetch the last 100 messages,
500 reactions, and 200 zaps fresh from the relay when opening a chat room.
Fix dedup race between live-chat-discovery and per-stream live-chat
subscriptions that silently dropped messages. Register "live-chat-" as
a dedup bypass prefix so both subs independently reach EventRouter.
Make ephemeral relay connections for live chat writable and
auto-reconnecting so streams survive transient connection drops.
- Add play/pause button to PiP overlay
- Tap to show/hide controls with 2s auto-hide timeout
- Disable feed video auto-play while PiP is active
- Wire up fullscreen callback for livestream player
- Use TextureView instead of PlayerView to fix SurfaceView z-ordering
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous "Free Poll"/"Zap Poll" FilterChip was confusing since it
defaulted to showing "Text Poll" label. Replace with a clear two-pill
segmented selector (Standard / Zap) above the poll options.
When expanding PiP to fullscreen, the same ExoPlayer is reused. The
fullscreen view now has a mini player button to return to PiP. Pressing
back or closing the fullscreen also returns to PiP instead of stopping
playback entirely.
Remove the Dialog-based approach which caused multiple issues. Restore
the original AnimatedVisibility Box overlay which was stable, adding only
the drag gesture for repositioning. The PiP may go behind inline video
AndroidViews but is otherwise reliable.
Fullscreen now expands the PiP dialog to full screen instead of opening a
separate FullScreenVideoPlayer with a new ExoPlayer. Back button or the
mini player button returns to PiP mode. This keeps the same player instance
throughout, so playback never interrupts or orphans.
translationZ doesn't work across different Android ViewGroup parents.
Switch to an Android Dialog which creates its own window layer, ensuring
the PiP player always renders above inline video views in the feed.
Drag repositioning uses window attribute manipulation instead of Compose
offset for reliable positioning within the Dialog window.
The Popup-based approach caused the PiP to vanish. Revert to the original
Box overlay with AnimatedVisibility, using a FrameLayout wrapper with high
translationZ to ensure the PiP PlayerView renders above inline video
AndroidViews in the feed.
Use a Popup window so the floating player renders in its own window layer,
guaranteeing it stays above inline video AndroidViews in the feed. Add drag
gesture support with screen-edge clamping so users can reposition the mini
player anywhere on screen.