<oembed><type>rich</type><version>1.0</version><title>amethyst wrote</title><author_name>amethyst (npub142…3xrj0)</author_name><author_url>https://nostr.now/npub142gywvjkq0dv6nupggyn2euhx4nduwc7yz5f24ah9rpmunr2s39se3xrj0</author_url><provider_name>njump</provider_name><provider_url>https://nostr.now</provider_url><html>#Amethyst v1.16.0: My Fitness, BOLT12 Payments, and a Leaner Core&#xA;&#xA;Highlights:&#xA;&#xA;- Adds **My Fitness**, a dashboard over everything you have trained.&#xA;- Moves **BOLT12 offers** into the profile payment rail, and zaps over BOLT11&#xA;  when a wallet refuses one.&#xA;- Opens the **zapped note** from wallet history.&#xA;- Fixes **Blossom uploads**, broken on most servers since 1.15.0.&#xA;- Takes **~40 MB off every `amy` distribution**.&#xA;- Stops counting a relay that hung up as connected.&#xA;- Updates **Arti to 2.6.0** for two medium-severity fixes.&#xA;&#xA;## New Features&#xA;&#xA;### My Fitness&#xA;&#xA;- Adds a training dashboard, reached from the drawer or a pinned bottom-bar slot.&#xA;- Builds it from both sources: Health Connect, and the kind 1301 workouts you&#xA;  published. Neither is required.&#xA;- Summarises four weeks: this week against last, weekly averages, a breakdown by&#xA;  activity, best efforts, active days and a day streak.&#xA;- Shows distance, calories, steps, climb and heart rate only when a workout&#xA;  carries them.&#xA;- Offers to share a workout only when it is not already published.&#xA;- Prefers the Health Connect copy when the same effort appears in both sources —&#xA;  it carries the heart rate, steps and climb the published event drops.&#xA;- Filters the Workouts feed by **Mine** from the top nav.&#xA;- Reads workouts in the POWR dialect, which carry `start`/`end` and no `duration`.&#xA;&#xA;### Payments&#xA;&#xA;- Renders each BOLT12 offer as a chip in the profile payment rail. Offers were&#xA;  already payable, but only through a small button in the profile header.&#xA;- Removes both header wallet buttons. The rail lists everything they reached.&#xA;- Shows the zap bolt to recipients who publish an offer and no lightning address.&#xA;  The send path already paid them; the picker just never offered it.&#xA;- Falls back to a BOLT11 zap when a wallet refuses an offer and the recipient also&#xA;  publishes a lightning address.&#xA;- Retries only refusals that mean nothing was attempted. A `PAYMENT_FAILED` can&#xA;  still settle later, so retrying it could pay twice.&#xA;- Reports a timeout when a wallet never answers, instead of hanging the zap.&#xA;- Opens the zapped note when you tap a zap in wallet history.&#xA;&#xA;## Performance&#xA;&#xA;- Stops emptying the media connection pool on every client rebuild. Both HTTP&#xA;  clients share one pool, so the proxy check misread every rebuild as a route&#xA;  change.&#xA;- Drops pooled connections once per real Tor route change instead.&#xA;- Stops `debugState()` walking the whole cache on every backgrounding. Its nine&#xA;  scans were built eagerly and then discarded unread.&#xA;- Signs one Blossom read-auth token per server, not one per racing caller.&#xA;&#xA;## Improvements and Bug fixes&#xA;&#xA;- Sends the Blossom authorization token as standard padded Base64 again. Deployed&#xA;  servers reject 1.15.0&#39;s unpadded base64url, so roughly two uploads in three&#xA;  failed.&#xA;- Points the Sovbit default Blossom server at `files.sovbit.host`.&#xA;- Answers a relay&#39;s WebSocket CLOSE frame, in both the shared and the Android&#xA;  socket. Without it a closed socket looked connected for up to four minutes,&#xA;  silently discarding everything sent.&#xA;- Counts connected relays from the pool&#39;s connected flow, which the pool now&#xA;  clears itself whenever it drops a relay.&#xA;- Renders a GIF with no `imeta` as a loading placeholder. It used to collapse the&#xA;  whole note to a gap in the feed until the fetch finished.&#xA;- Drains the event-sync outbox before closing the client. Events from the final&#xA;  page were reported Done and never delivered.&#xA;- Fixes 34 bugs found auditing `commons` and `commonsUI`. Among them: AES-GCM&#xA;  initialised with a spec every JDK rejects; an `Onion-Location` header from any&#xA;  host re-pointing Tor traffic for 24 hours; a bundled insert wedged after one&#xA;  exception; a URL validator backtracking exponentially per keystroke.&#xA;- Uses `https` in preview data and image-URL placeholders.&#xA;&#xA;## Desktop&#xA;&#xA;- Stops a silent account wipe on macOS. One Deny on the Keychain prompt rotated&#xA;  the encryption key and orphaned every saved account.&#xA;- Consolidates the keychain into a single `vault-v1` item, so a cold boot prompts&#xA;  once.&#xA;- Allows first-launch key bootstrap on Linux and Windows.&#xA;&#xA;## Cli&#xA;&#xA;- Ships ~40 MB lighter, now that `amy` no longer drags Compose UI and Skiko behind&#xA;  `commons`.&#xA;- Fails fast when a buzz-agent wrapper cannot be made executable.&#xA;&#xA;## Quartz&#xA;&#xA;- Answers a duplicate `EVENT` with `OK true`, per NIP-01, and a superseded&#xA;  replaceable the same way. Clients used to get raw SQLite text they could not&#xA;  classify, and retried forever.&#xA;- Gives each socket adapter its own session, removing the pool&#39;s locking and&#xA;  identity checks.&#xA;&#xA;## Build &amp; Documentation&#xA;&#xA;- Updates Arti 2.3.0 → 2.6.0, the JNI crate to 0.22, the NDK to r30 and Rust to&#xA;  1.98.1. Picks up TROVE-2026-24 and TROVE-2026-27, both reachable in normal use.&#xA;- Splits Compose UI out of `commons` into a new `commonsUI` module. 236 files&#xA;  moved and no consumer import changed.&#xA;- Bumps LightCompressor-enhanced to 2.2.3.&#xA;- Drops the unused Guardian Project Maven repository.&#xA;- Runs relay-backed tests against geode instead of external relays.&#xA;- Clears the compiler, Android Lint and Gradle 10 deprecation warnings.&#xA;- Bumps `appCode` to 461.&#xA;&#xA;## Contributors&#xA;&#xA;- nostr:nprofile1qqsyvrp9u6p0mfur9dfdru3d853tx9mdjuhkphxuxgfwmryja7zsvhqpzamhxue69uhhv6t5daezumn0wd68yvfwvdhk6tcpzpmhxue69uhkummnw3ezumt0d5hszythwden5te0dehhxarj9emkjmn99uwfvhl6&#xA;- nostr:nprofile1qqsv4zwtz8cuwh2mvc3zdrl5853g365t9j6mn25edlul7uz0eyzt0zcpzpmhxue69uhkummnw3ezumt0d5hszxnhwden5te0wf5kymewv46jumn0wd68y6tp9eshqup0qyd8wumn8ghj7um9dejxjapwdehhxenvv9ex2tnrdakj7nrm3sx&#xA;- mstrofnone&#xA;&#xA;## Translations&#xA;&#xA;- Polish by nostr:nprofile1qqsdyfz0ewdhmgp3a4r3pxvezx5r8yalrgvjn38v2ml5qrusnv7yywgpzemhxue69uhkummnw3ezucm6v9ejuurvw4ej7qg0waehxw309a3h5ctn9e6x7up0qyg8wumn8ghj7cm6v9ejuurvw4ej79s8c53&#xA;- Hindi by nostr:nprofile1qqs88dt78wgnzvaph6fcstfvsd98xc2qs8eg8tllwv2zlutu8ehec2cppemhxue69uhkummn9ekx7mp0qythwumn8ghj7un9d3shjtnswf5k6ctv9ehx2ap0qyt8wumn8ghj7un9d3shjtnyd968gmewwp6kytcmlz0lu&#xA;- Hungarian by nostr:nprofile1qqsxekg0s8kxpcrka8ccwztv2m73kz6jy0ur8f7jc04rwr5p44w5acspzamhxue69uhhyetvv9ujumn0wd68ytnzv9hxgtcppemhxue69uhkummn9ekx7mp0qyg8wumn8ghj7mn0wd68ytnddakj7c0ns2l</html></oembed>