When enabled in Settings → Safety → Filters, events from pubkeys
outside the user's qualified social graph (self + follows + extended
network) are silently dropped at the EventRepository and
NotificationRepository ingestion layer. This covers notes, reactions,
zaps, and reposts.
Exempt kinds: profiles (0), contact lists (3), relay lists (10002),
DM-related kinds (4, 1059, 13, 14), and DM relay lists (10050).
The filter fails open when the social graph is not computed or stale.
Toggling the filter triggers an immediate feed rebuild.
Ports the nspam v0.9 logistic regression model (~937KB) to pure Kotlin
for on-device classification of likely-bot authors. The model runs
MurmurHash3 feature hashing over character and word n-grams plus
structural note features — no ML runtime needed.
Spam filtering is applied only to replies from non-followed authors in
threads and notifications. Suspected spam replies appear at the bottom
of threads behind a toggle. Users can mark authors as "not spam" to
permanently safelist them. The classifier improves over time by
rescoring authors when more of their notes become available.
Adds a new Filters tab to Safety settings with toggles for the spam
filter (on by default) and Web of Trust filter (off, gated by social
graph — implementation in follow-up PR).
- Introduce `BlurHashDecoder` for decoding BlurHash strings into blurred placeholder bitmaps.
- Update `parseImetaTags` to extract `dimension` and `blurhash` from NIP-92 tags.
- Refactor `RichContent` segments to use a new `MediaMeta` data class instead of raw URL strings.
- Implement blurred placeholders and aspect-ratio-aware loading states in `RichContent`, `PostCard`, and `GalleryCard`.
- Add buffering indicators to `InlineVideoPlayerWithFullscreen`.
- Ensure `imeta` and emoji tags are correctly parsed and passed to `RichContent` in `DraftsScreen` and `UserProfileScreen`.
The lifecycle RESUMED check silently swallowed navigation calls when
the back stack entry hadn't reached RESUMED state yet, making the
entire interface unresponsive — especially on older/slower devices.
Reverts the blanket navigateSafe wrapper from #425. The original
double-tap crash was a narrow edge case; this revert restores reliable
navigation for all users.
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.