Files
Vitor PamplonaandClaude Opus 5 68c1e4d1fe docs(changelog): credit the translators Crowdin recorded without a language
scripts/translators.sh buckets contributors whose sinceLastTag entry carries
an empty languages list under "(unknown language)". Dropping that bucket, as
the first draft did, silently uncredited 18 people who did translate this
cycle — the language is what is missing, not the contribution.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gs2gi3sZfQ7SHrVm2njLMw
2026-08-22 13:04:48 -04:00

17 KiB
Raw Permalink Blame History

v1.14.0: Highlights, Relay Login, and a Much Faster Start

Highlights:

  • Improves NIP-84 Highlights — composer, feed, and share intent.
  • Redesigns relay login (NIP-42) and ends the per-relay prompt storm.
  • Adds Share targets to Pictures, Videos, Shorts and Torrents feeds.
  • Adds a screen that explains why every relay subscription exists.
  • Fixes the cold-start out-of-memory kill and cuts time to first paint.
  • Brings Desktop to parity on profiles, DMs, settings and key backup.
  • Adds Trusted Lists (kinds 30392–30395) to Quartz.

New Features

Highlights (NIP-84)

  • Adds a Highlight composer, with an annotation field, a passage editor, and a source reference that can be a Nostr event or a web URL.
  • Adds a Highlights feed, filterable by authors, follows, hashtags and geohashes.
  • Accepts shared text from any app as a new highlight.

Feeds and Composing

  • Adds four home feed content types: Pictures (NIP-68), Videos and Shorts (NIP-71), and Torrents (NIP-35), each with its own toggle.
  • Adds "New Picture", "New Short" and "New Video" share targets, so media shared into Amethyst opens the matching composer instead of a text note with a link.
  • Adds a bulk audience picker to the short-note composer: search people lists and follow packs, review the members, then add them all at once.
  • Adds a poll results page with per-option vote counts and a filterable voter list, replacing the feed card's four-avatar preview.
  • Shows rich previews for comments scoped to external content (NIP-73), both in the "replying to" line and as the thread's title.
  • Offers a "Copy Original / Copy Translated" chooser when copying a note that has been translated.
  • Opens the edit screen when a draft reply is tapped in a thread.

Relay Login (NIP-42)

  • Redesigns the relay login permissions screen. Explicit exceptions, relays blocked by your block list, and recent logins are now three separate sections.
  • Starts new accounts on "always log in" instead of deciding per relay.
  • Remembers a login for the rest of the session when you answer without ticking "remember", so a reconnect stops asking again.
  • Honors "always log in" for relays your own account does not publish to.
  • Makes the "reading someone I follow" toggle reachable — it sat behind a first-party gate that could never be true.
  • Counts NIP-29 groups and Concord communities as rooms you joined, so their host relays authenticate under "my relays and venues".
  • Waits for an auth challenge to resolve rather than letting the fetch time out.

Relay Traffic, Explained

  • Records why every relay-bound filter exists — its purpose, the entities it serves and the account that asked — and renders that back on a new screen.
  • Fixes the multi-account subscriptions that screen exposed as never running.
  • Breaks the resource ledger down by cause, so it reports why relay data was spent, not just how much.
  • Stops the automatic "High resource usage detected" dialog on app open. The ledger keeps recording and Settings still shows the report.

Chats, Groups and Communities

  • Mutes a public chat from a long press in Messages or from the channel menu.
  • Deletes (kind 9008) and archives NIP-29 channels, with the Buzz community UI to match.
  • Keeps a channel invite's replies, reactions and zaps inside the relay that sent the invite, instead of broadcasting them to your outbox.
  • Derives Buzz channel invites from cached membership notices, so they stop appearing and disappearing.
  • Redesigns channel invite cards as feed rows, with the person who added you as the row's author.
  • Shows the hosting relay's name chip on relay group message headers.
  • Splits the Concord Control Plane's stream key so a staff-held control_root write-gates it (CORD-02 §2).
  • Closes the Concord CORD-05/06 invite lifecycle: an Invite List, a re-mint on Refounding, and revocation.
  • Stops pinning Concord entities whose chain crosses a Refounding, which was discarding their newer state on every refold.
  • Closes seven Concord soft-ban holes — a banned member kept control_root, half the Control Plane never read the banlist, and the invite button still worked.

Everything Else

  • Makes the left drawer configurable, so entries you don't use can be hidden.
  • Adds ngit-specific search to the Git Repositories screen.
  • Supports IPv6 overlay relays (Yggdrasil) with RFC 5952 canonical addresses, fixing one relay counting as two and Tor-proxying an unreachable overlay.
  • Adds a Nostr badge watermark to the notification icons, reshapes the mention icon, and adds dedicated reply and mark-as-read action icons.
  • Runs verified NIP-5D artifacts in an opaque srcdoc sandbox behind a first-head CSP, and advertises only the NAP domains actually implemented.

Performance

  • Scans NIP-19 entities, hashtags and legacy #[n] references without ICU. On Android, Regex.matchAt copied the whole note content into native memory per candidate, which grew a cold start to ~1.9 GB and got the app killed.
  • Scans note content by literal instead of restarting the regex engine at every position in every note.
  • AOT-compiles the relay ingest path with a baseline profile. Release cold-start ingest was spending 36× more CPU interpreting bytecode than verifying signatures.
  • Demotes the ~650 relay and ingest worker threads below the UI thread, so the connect storm cannot starve the first frames (~40% faster first paint).
  • Reclaims memory under heap pressure and stops leaking sandboxed WebView Activities.
  • Bounds the duplicate-frame decoder cache in both size and age.
  • Stops blocking coroutine workers on synchronous OkHttp calls, which released their CPU permits and starved the dispatcher.
  • Stops the outbox getting slower with every publish — it rebuilt an immutable map per send, copying every pending entry.
  • Stripes the subscription-state lock per relay, ending the ANR convoy that had 37 of 52 workers spinning on one lock.
  • Memoizes Concord guestbook envelope opens, so the fold stops re-decrypting the whole buffer on every arrival.
  • Caches the painter on its first miss in painterRes.
  • Optimizes the proof-of-work mining hot loop for the Android runtime.
  • Skips the ~220 ms system call when the app locale has not actually changed.
  • Confines the Blossom cache probe and server resolver to the IO dispatcher, and re-probes it when the toggle flips.
  • Releases dead subscription rows, so connect and disconnect stop scanning every subscription ever created.
  • Prefetches NIP-73 external-content preview URLs so those cards stop popping in mid-scroll.
  • Adds fixed-size hex codecs for 32- and 64-byte values.

Improvements and Bug fixes

  • Settles the keyboard inside navigation, so leaving a screen mid-animation stops stranding imePadding across the whole app.
  • Routes the draft-saving editors through KeyboardAwareBackHandler, so a predictive back gesture no longer races the IME close.
  • Raises the keyboard again when you tap a field in an embedded tab that was already focused.
  • Pads for the soft keyboard in full-screen napplet hosts on Android 15+.
  • Fixes the crash when switching between two pinned web-app tabs.
  • Stops drawing a blank parent card above a top-level community post.
  • Fixes Cashu wallet balances reading low: proofs are now backfilled past the relay's page cap and history is paged.
  • Keeps PDF previews stable — the page ratio is cached, so scrolling back no longer collapses the card and replays the grow-in animation.
  • Stops rendering non-media NIP-94 files as video.
  • Repairs imeta MIME types written as a bare subtype, so those images can be shared again.
  • Works around a fatal media3 crash on Low-Latency HLS streams.
  • Drives the "Can't reach this relay over Tor" banner from live socket state instead of a bare six-second timer.
  • Stops a lone repost from being bundled into the always-on service notification, where it inherited the ongoing flag and refused to swipe away.
  • Fails push registration loudly on an HTTP error, instead of caching a token for a device that will never receive anything.
  • Listens for location only while foregrounded, and fixes the meter that reported 7 hours of listening against 9 seconds of foreground.
  • Excludes quote characters from parsed URLs.
  • Fixes the OpenGraph meta parser losing every tag after an apostrophe inside a comment or script, which broke link previews on some sites.
  • Requests the follower-count provider's kind 30382 cards, so the count stops rendering as --.
  • Gives the invite roster line's member count its unit, so a bare number no longer reads as counting the avatars beside it.
  • Removes the recent-poster facepile from Concord and Buzz channel rows.
  • Renders every NIP-71 video subtype through the shared interface.
  • Reworks the chat bubble reply swipe on lower-level pointer APIs, so it only claims the gesture once the motion is clearly horizontal.
  • Turns the default log into a boot narrative instead of a firehose.
  • Converts the drawer's hidden-count to a plural, fills the untranslated backlog for Czech, German, Swedish and Brazilian Portuguese, restores placeholders dropped from German and Polish plurals, and drops an unused plural.

Desktop

  • Enriches the DM composer and message list: emoji picker with custom emoji, @mentions, reply-quoting with jump-to-original, Nostr-native GIF search, rich message rendering, per-message image quality, and encrypted file uploads.
  • Redesigns Settings as a searchable accordion of labeled cards, with expand/collapse-all and a filter over titles and keywords.
  • Brings the profile screen to parity: banner, rich-text bio, a CLINK offer field, six new tabs (Followers, Following, Relays, Bookmarks, Yours, Zaps received) and header actions.
  • Adds a guided "save your keys" step on first run and a key backup in Settings. Android gets a soft nudge after signup.
  • Loads metadata and reactions only for what is on screen, through the shared finders in commons, and unsubscribes when it leaves.
  • Enables the master notification switch when the OS permission is already granted.
  • Publishes Windows arm64 and Linux arm64 desktop builds.

Cli

  • Gives amy the Concord key lifecycle it was missing: accept a promotion, follow a Refounding, perform one, and recover when left out of it.
  • Publishes Windows and Linux arm64 assets for amy and geode.
  • Reports "no relays" only when there really were none, and pins the buzz wrapper copies against the argument surface they call.

Quartz

  • Adds Trusted Lists (kinds 30392–30395), the aggregate counterpart to NIP-85 Trusted Assertions, and indexes their labels for NIP-50 search.
  • Fixes a SharedKeyCache collision that could return one peer's shared secret for another peer's message, and compares MACs in constant time.
  • Measures NIP-66 relay health from traffic the client already makes, streams probe verdicts as relays answer, checks read and write separately, lets a monitor publish what it learned without dialling, and merges verdicts into the record they replace instead of overwriting it.
  • Measures rtt-open as the transport handshake, not the time the call spent queued in the dispatcher.
  • Records sync coverage per kind rather than one interval per filter, keys its persistence with a typed band, closes a drained leg, and terminates a paged walk against a relay that ignores until.
  • Strikes a host out and tracks its unreachability with publish-safe semantics, so a dead host stops being retried at the same rate as a live one.
  • Sizes negentropy reconcile windows from the caller's own index, states the relay's cap, and lets a caller decline an id before its body crosses the wire.
  • Normalizes every accessory timeout to an idle window, drops the maxTotalMs ceiling that cut healthy fetches, and stops fetchAllPages cropping a streaming page.
  • Stops COUNT inheriting the REQ page size, which capped a count at 500.
  • Suspends the incoming-message chain down to SubscriptionListener.onEvent, so a consumer that cannot keep up no longer blocks every shared worker.
  • Compares every filter in FiltersChanged, not just the first.
  • Fixes an InProcessWebSocket race that delivered a connect-time AUTH challenge before onOpen.
  • Adds StoreQueryContext, carrying the NIP-42-authenticated caller identity into observer-relative stores.
  • Adds a NIP-50 search grammar (quoted phrases, negation) with weighted field extraction, and shares the store-semantics rules across implementations.
  • Parses metadata leniently everywhere, and recovers blank, single-element and malformed kind-0 content instead of dropping the profile.
  • Parses ServiceType without splitting on a separator that may not be there.
  • Declares pointer hints on Report, ChatMessage, Classifieds and ChannelCreate.
  • Refreshes created_at while mining, so a post that takes minutes to mine does not publish stale.
  • Decouples the LocalCache and Account god classes into single-purpose collaborators, 3,800 lines lighter, with no behavior change.

Build & Documentation

  • Adds a :baselineprofile module that records a real startup journey, replacing the hand-authored profile's wildcards.
  • Notarizes the macOS DMG and verifies it, adds libegl1 to the arm64 .deb dependencies, and moves the Homebrew and Winget bumps onto a maintainer machine.
  • Shrinks the mirror-sync throughput corpus on CI, which had been timing out the test-geode job for weeks.
  • Confines the QUIC stream drainer to the producer's event loop, deflaking it under parallel test load.
  • Hardens workflow-ship.sh and pins it with a regression harness.
  • Adds three store-implementer skills: event store semantics, NIP-85 trusted assertions and searchable events.
  • Bumps 30+ dependencies plus Gradle, Compose, Firebase, Media3, Ktor and OkHttp.

Contributors

  • @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • @npub1e2yuky03caw4ke3zy68lg0fz3r4gkt94hx4fjmlelacyljgyk79svn3eef
  • @npub12cfje6nl2nuxplcqfvhg7ljt89fmpj0n0fd24zxsukja5qm9wmtqd7y76c
  • @npub1aeh2zw4elewy5682lxc6xnlqzjnxksq303gwu2npfaxd49vmde6qcq4nwx
  • @npub1uac67zc9er54ln0kl6e4qp2y6ta3enfcg7ywnayshvlw9r5w6ehsqq99rx
  • @npub1q3sle0kvfsehgsuexttt3ugjd8xdklxfwwkh559wxckmzddywnws6cd26p
  • @npub1gvv9ahktvavf9qjtrgm62le7gplmmchd5usp5wpfhr85hf79kncqj8xchs

Translations

  • Chinese Simplified by @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Czech by @npub1e2yuky03caw4ke3zy68lg0fz3r4gkt94hx4fjmlelacyljgyk79svn3eef and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Dutch by @npub1w4la29u3zv09r6crx5u8yxax0ffxgekzdm2egzjkjckef7xc83fs0ftxcd and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • German by @npub1e2yuky03caw4ke3zy68lg0fz3r4gkt94hx4fjmlelacyljgyk79svn3eef and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Hindi by @npub1ww6huwu3xye6r05n3qkjeq62wds5pq0jswhl7uc59lchc0n0ns4sdtw5e6 and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Hungarian by @npub1dnvslq0vvrs8d603suykc4harv94yglcxwna9sl2xu8grt2afm3qgfh0tp and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Latvian by @npub1l60stxkwwmkts76kv02vdjppka9uy6y3paztck7paau7g64l687saaw6av
  • Polish by @npub16gjyljum0ksrrm28zzvejydgxwfm7xse98zwc4hlgq8epxeuggushqwyrm and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Brazilian Portuguese by @npub1e2yuky03caw4ke3zy68lg0fz3r4gkt94hx4fjmlelacyljgyk79svn3eef and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Slovenian by @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Swedish by @npub1e2yuky03caw4ke3zy68lg0fz3r4gkt94hx4fjmlelacyljgyk79svn3eef and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z
  • Additional translations, with the language not recorded by Crowdin, by @npub106efcyntxc5qwl3w8krrhyt626m59ya2nk9f40px5s968u5xdwhsjsr8fz, @npub10ug9xs24ay5339agakaqk556t6zvq9qn5vm0vlhc4pu25cx0l32qxhrm9e, @npub13qtw3yu0uc9r4yj5x0rhgy8nj5q0uyeq0pavkgt9ly69uuzxgkfqwvx23t, @npub16gjyljum0ksrrm28zzvejydgxwfm7xse98zwc4hlgq8epxeuggushqwyrm, @npub19jk45jz45gczwfm22y9z69xhaex3nwg47dz84zw096xl6z62amkqj99rv7, @npub1cdy4mhznq7dex8u8ylnlws5vj0ckzgnxyyxq4h87pyk8m6s0pf3ssspdkl, @npub1cpazafytvafazxkjn43zjfwtfzatfz508r54f6z6a3rf2ws8223qc3xxpk, @npub1gd8e0xfkylc7v8c5a6hkpj4gelwwcy99jt90lqjseqjj2t253s2s6ch58h, @npub1luhyzgce7qtcs6r6v00ryjxza8av8u4dzh3avg0zks38tjktnmxspxq903, @npub1qqqqqqz7nhdqz3uuwmzlflxt46lyu7zkuqhcapddhgz66c4ddynswreecw, @npub1raspu6ag9kfcw9jz0rz4z693qwmqe5sx6jdhhuvkwz5zy8rygztqnwfhd7, @npub1tr66yvqghfdgwv9yxhmg7xx6pvgvu5uvdc42tgdhsys8vvzdt8msev06fl, @npub1ust7u0v3qffejwhqee45r49zgcyewrcn99vdwkednd356c9resyqtnn3mj, @npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e, @npub1w4uswmv6lu9yel005l3qgheysmr7tk9uvwluddznju3nuxalevvs2d0jr5, @npub1wujmwnq0we8qs44fhxsducavekk3r2y3ln3kplhstk99n4spaqpqpzamjm, @npub1ww8kjxz2akn82qptdpl7glywnchhkx3x04hez3d3rye397turrhssenvtp, @npub1x3azxuysp5vmfer4vgs4jn5tmfcx4ew8sh0qnev7gczljxsr7jwqa3g4el.