Guard all LaunchedEffect { requestFocus() } calls against the race
where the FocusRequester node is not yet attached — particularly in
Scaffold subcomposition (SearchScreen) and dialog content.
Reported on HONOR DNY-NX9, Android 36.
countedReplyIds was a ConcurrentHashMap that never evicted, while
replyCounts was an LruCache. When replyCounts evicted an entry, the
permanent dedup set prevented re-counting on re-fetch. Align
countedReplyIds with the same LruCache pattern used by
countedReactionIds and countedZapIds so both evict together.
Bump to 0.17.5 (71).
Track emoji usage counts in SharedPreferences and sort the reaction
picker by most-used first. Both unicode and custom image emojis are
included in the unified sorted list, so frequently used custom emojis
appear before less-used unicode ones.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move reply/react/zap icons into the username/timestamp header row
so they're always visible without tapping. Removes the tap-to-reveal
action bar and its 5s auto-dismiss timer. Zero extra vertical space.
Hide reply/react/zap action bar behind a tap gesture with 5s auto-dismiss
to reduce visual clutter in group and live stream chats. Assign each chat
member a deterministic color based on their pubkey for easier distinction,
keeping the user's own name in the theme primary color.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
getEvent() and findAddressableEvent() served events from blocked pubkeys
without checking the mute list. Quoted/embedded notes from blocked users
were visible because getEvent() reloaded purged events from ObjectBox
persistence. Add block checks to both methods and to seedFromObjectBox().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Some clients use "name" instead of "title" for relay sets, follow sets,
bookmark sets, and interest sets. Fall back to "name" when "title" is
absent before using the d-tag identifier.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Only play notification sounds for enabled notification types (reactions, reposts, mentions, votes)
- Fetch and display profile pictures/names for muted users on the safety screen
- Render nostr entity references (nevent, nprofile, naddr) as rich cards in article view
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the optimistic status cache update before the signer null-check so
the UI always responds, and stamp userStatusTimestamps in setUserStatus
so relay re-fetches of stale events cannot overwrite the local update.
Change emoji set fetching to always re-fetch all referenced sets instead
of only missing ones, ensuring sets are up-to-date after reconnect.
fillMaxWidth() on the video Box pinned both min and max width, preventing
aspectRatio() from narrowing portrait videos to fit within the 500dp
height cap. Wrap in a centering Box so the inner container can freely
size to the correct aspect ratio.
Replace separate npub and lightning QR dialogs with a single
ProfileQrSheet bottom sheet. Nostr and Lightning tabs are swipeable,
with the Lightning tab only shown when the user has a lud16.
Removes the separate lightning address icon from the drawer header,
cleaning up the icon row to just tor, theme, and QR.
- Round QR code corners (16dp) on both npub and lightning dialogs
- Use high error correction (Level H) to support center overlays
- Npub QR: show user avatar in center (wisp logo fallback)
- Lightning QR: show bolt or bitcoin icon based on user preference
- Pass avatar URL through from profile and drawer call sites
- Replace QrCode2 with simpler QrCodeScanner icon on profile screen
- Move "24h" from stats row into title bar as "Notifications | 24h"
- Tap any stat to filter notifications to that type; tap again to
reset. Uses atomic isolateType() to avoid empty-state flash.
- Zap icon in stats bar and filter sheet respects bolt/bitcoin toggle
- Improve off-state switch contrast with explicit thumb/track/border
colors in the notification filter sheet
Add reset() to InterfacePreferences that clears accent color, theme,
dark mode, large text, bolt icon, balance hidden, and new notes button
preferences. Called when the last account logs out so the splash
screen returns to default appearance.
The navigateSafe() guard requires RESUMED lifecycle state, but
ActivityResultLauncher callbacks fire during STARTED. Defer the
onAuthenticated call via LaunchedEffect so navigation runs after
the composable is fully resumed.
Prevent the device from sleeping during fullscreen video playback with
FLAG_KEEP_SCREEN_ON. Add a MediaSessionService so Android shows media
controls in the notification shade and lock screen when the app is
backgrounded, covering both fullscreen and PiP video modes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fullscreen video state was stored in per-item remember state inside
LazyColumn items (RichContent, GalleryCard). On rotation the
LazyColumn can dispose items, losing that state and dismissing the
Dialog. Hoist the state into a FullScreenVideoState singleton
observed at the Navigation level where it survives recomposition.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The play button overlay in InlineVideoPlayerWithFullscreen used
fillMaxSize on the parent Box which had no aspect ratio constraint,
causing the overlay to not respect video proportions. Moved heightIn
and aspectRatio from the AndroidView to the outer Box so both the
video and overlay share the same correctly-proportioned container.