Ready on the zap store
Amethyst's avatar Amethyst
#Amethyst v1.14.0: New Share Intents, 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 - @Vitor Pamplona - @npub1e2yu...3eef - @npub12cfj...y76c - @npub1aeh2...4nwx - @npub1uac6...99rx - @npub1q3sl...d26p - @npub1gvv9...xchs ## Translations - Czech by @npub1e2yu...3eef - Dutch by @npub1w4la...txcd - German by @npub1e2yu...3eef - Hindi by @npub1ww6h...w5e6 - Hungarian by @npub1dnvs...h0tp - Latvian by @npub1l60s...w6av - Polish by @npub16gjy...wyrm - Brazilian Portuguese by @npub1e2yu...3eef - Swedish by @npub1e2yu...3eef
View quoted note →