aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
Commit message (Collapse)AuthorAgeFilesLines
...
| * NIP-22 comments (kind 1111): shown in threads, sent when replying to a poll, ↵Adam Soltys2026-09-291-9/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | article or comment, and in notifications. Kind 1111 is the reply format for everything that isn't a kind 1 note: uppercase E/A + K + P name the root, lowercase e/a + k + p the parent. Threads now also ask for comments naming the root (#E, and #A for an addressable root like an article), place each under its parent, and draw them as posts. A reply to anything but a kind 1 note goes out as a 1111 with the root's scope and the parent's tags (copied from the comment when the root isn't loaded); replies to kind 1 notes stay kind 1. Comments that answer you show in Notifications. comments-test (a real article with 4 comments; events caught at the socket, nothing published): comments listed, reply to the article and to a comment tagged per NIP-22. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * Composers take pictures from the keyboard: the reply, post and chat fields ↵Adam Soltys2026-09-291-11/+33
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | are contenteditable. Android keyboards (Gboard GIFs, stickers) only offer images to fields that accept them, and Chrome says so for contenteditable, never <textarea> — hence the greyed-out GIF key and "This app does not support images here". <coinos-text> (src/rich-text.js) is a contenteditable that acts like a textarea to the code around it (value, selectionStart/End, setSelection- Range, placeholder), keeps text plain, and hands any pasted/dropped/ keyboard picture to onMedia — the paperclip's upload. The morph syncs its value like a field's and leaves its own editing attributes alone. composer-media-test: types like a textarea, strips pasted formatting, a pasted GIF uploads and lands in the reply, still editable after repaint. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * Quoted notes are found on more relays and never show as a bare "view note"; ↵Adam Soltys2026-09-291-17/+48
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Back from a post keeps the feed's place. - findNote: the reference's hints, its author's NIP-65 relays and ours, plus a wide net of big public relays, all at once, first answer wins. A real quote (SuiGenerisJohn → 0c5e0f08…) sat only on nostr.mom, named by neither the nevent nor its author's relay list. - A feed row whose quote isn't in yet shows the quote card with "Fetching note…" / "Couldn't find that note" instead of a link; the card replaces it once found. - Opening a post remembers the scroll position like opening a profile does; Back restores it instead of landing at the top of the feed. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * A face still being looked up shows its punk after a second at most; a ↵Adam Soltys2026-09-291-13/+29
| | | | | | | | | | | | | | | | | | | | | | | | picture found later replaces it. The quiet loading circle is capped at 1 s per face (a timer repaints when it runs out); one miss is enough to remember someone as faceless; and a room's warm-up adds members whose messages arrived after it first ran, instead of reusing a warm-up that covered only the early history. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * Someone with no profile picture paints as their punk from the first frame ↵Adam Soltys2026-09-291-4/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | after a reload, not a blank circle that turns into one. Faceless answers were never persisted (they'd evict real faces from the 150-row profile blob), so every reload re-asked and showed the loading circle until the relays said "nothing". A small pubkey->time list now remembers them: no kind 0 on two asks running (a cold relay isn't enough), or a kind 0 naming nothing; finding a face takes them off it. room-faces-test --refresh: reload inside the coinos room, faces keyed by author — 2 changed (wait→punk) before, 0 after. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * A community opens with its members' faces, not a beat of punks.Adam Soltys2026-09-291-2/+45
| | | | | | | | | | | | | | | | | | | | | | | | | | Faces (profile, then the picture decoded) are warmed when the pointer is over or presses a room's row, and while the chat list sits there; the tap waits for them, 1.5 s at most, before the room replaces the list. A face still loading in a room is the quiet circle, not a punk. room-faces-test (fresh wallet, real coinos community): 57 faces flipped punk → picture before, 0 after. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * Confirm discarding substantial post draftsAdam Soltys2026-09-291-1/+25
| |
| * Discard canceled post draftsAdam Soltys2026-09-291-12/+38
| |
| * Fix public media uploads and feed tab navigationAdam Soltys2026-09-291-5/+9
| |
| * Cache notification note content locallyAdam Soltys2026-09-291-4/+69
| |
| * "Save feed" on someone's timeline adds it to your feeds at once, instead of ↵Adam Soltys2026-09-281-17/+55
| | | | | | | | | | | | | | | | | | | | | | | | | | an editor listing every person they follow. The editor copied their whole follow list into the form, one row each — long enough to freeze the browser. A saved timeline now keeps only the person (of: pk); their follow list is read from the relays when it is opened, so it stays small in sync and follows who they follow. Its ⋯ offers Delete rather than Edit, and list pickers leave it out. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * Someone's timeline gets a labelled feed chip instead of a blank black pill.Adam Soltys2026-09-281-1/+3
| | | | | | | | | | Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * Polls (NIP-88): options with each one's share of the vote, votable from the ↵Adam Soltys2026-09-281-13/+119
| | | | | | | | | | | | | | | | | | | | | | | | | | | | feed and the thread. A kind 1068 poll showed as "an event this app doesn't show". Now its options are rows with the vote share behind them (kind 1018 votes, each person's latest counts, single/multiple choice, endsAt honored); a tap votes, marked as yours at once. A quoted poll is pictured in its card. Feeds and profiles list polls alongside notes, and a thread's root is looked up by id with any kind, so replies to a poll find it. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * A thread that starts from a poll (or any non-kind-1 post) is cached too, so ↵Adam Soltys2026-09-281-1/+1
| | | | | | | | | | | | | | | | | | | | | | a reload paints its replies at once. The thread store accepted only kind 1 and silently skipped saving a thread rooted in a kind 1068 poll — every refresh then waited on the relays behind a spinner. Also guard the profile Back listener for window-less tests. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * A face tapped in the feed opens that person's profile at its top; Back ↵Adam Soltys2026-09-281-0/+14
| | | | | | | | | | | | | | | | | | | | returns to the same place in the feed. The profile kept the feed's scroll offset, so the reader landed deep in the person's posts — which read as a thread opening. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * A quoted note that was slow to arrive turns into its card instead of staying ↵Adam Soltys2026-09-281-4/+21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | a "view note" link. A feed row keeps its first look, and a quote that missed the readiness gate froze as a link — with nothing asking for the note again. The frozen row now keeps asking (the existing 30s retry) and takes the card once the note and its own avatar/pictures are warm. quote-card-test: reach the feed through the bottom nav, seed the author's profile, and --slow drops the first ask for the quote to cover this. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
| * A reloaded thread paints whole, quoted posts included, with no spinner.Adam Soltys2026-09-281-1/+19
| | | | | | | | | | | | | | | | | | The thread cache kept the replies but not the posts quoted inside them, so every reload showed "Fetching note…" until a relay answered. Quotes (of any kind — the one that showed it was a poll) are now saved with the thread and restored before the first paint. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * New posts: the pill lands on the oldest one, and each wears a tint until ↵Adam Soltys2026-09-281-6/+77
| | | | | | | | | | | | | | | | | | | | | | you've seen it. The new-posts pill used to glide to the top of the feed; now it stops at the oldest post that came in, right above where you were reading, so you read on upward. Posts that arrive while you read are tinted until they've been in view about two seconds, then fade to the plain page (like Amethyst). Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * Zapping someone without Ark just works: Lightning first, then a locked gift ↵Adam Soltys2026-09-281-53/+75
| | | | | | | | | | | | | | | | | | | | | | | | | | | | that looks like any zap. No warning and no gift wording: when a person has no Ark address and no Lightning address, the ordinary amount + Zap form sends a gift locked to their nostr key and DMs it; the receipt screen is the usual Zapped!, with the link and code only if the DM couldn't be delivered. One-tap post zaps take the same path instead of failing. The Lightning button appears only for someone who has a Lightning address, and an Ark advert for another network no longer stops the lookup short of Lightning. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * The chat list shows four conversations and four communities, the rest behind ↵Adam Soltys2026-09-281-7/+14
| | | | | | | | | | | | Show all. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * The bottom nav spans the window; the chat list is just conversations.Adam Soltys2026-09-281-41/+9
| | | | | | | | | | | | | | | | | | Feed and Notifications leave the chat list (the nav reaches both; the bell carries the notifications dot now). On a wide screen the bar runs edge to edge with its buttons over the page column; quiet muted tabs, a pill for the current one. Feed gets a newspaper icon instead of a house. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * The bottom nav rides every page: Feed, Messages, Notifications, Wallet.Adam Soltys2026-09-281-14/+33
| | | | | | | | | | | | | | | | | | It now shows across the signed-in app and a visitor's public pages (never over sign-in, onboarding or the lock prompt), marks the current page, and carries the unread dot. Home is renamed Feed, and the Messages button leaves the header. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * Keep feed navigation visible and add a wallet shortcutAdam Soltys2026-09-281-4/+6
| |
| * Add scrolling feed navigation for home, messages and notificationsAdam Soltys2026-09-281-1/+26
| |
| * Enlarge post text and use full width below author headersAdam Soltys2026-09-281-4/+4
| |
* | Encrypted chat pictures get blossom.yakihonne.com as a third host; a small ↵Adam Soltys2026-09-301-2/+3
|/ | | | | | | | | | | | file stops at two copies. Benchmarked 18 public Blossom hosts: only ditto, nostr.download and yakihonne take opaque (application/octet-stream) blobs, which is what an encrypted attachment is. ditto is fastest; yakihonne is slow, so it is reached only when one of the first two fails. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01WMMwWYJkPQxLgfMsY7hWcU
* Merge remote-tracking branch 'prod/prod' into merge-tmpAdam Soltys2026-09-281-6/+11
|\
| * Fix video unmute after feed repaintsAdam Soltys2026-09-281-6/+11
| |
* | The feed header keeps its room on a phone: a ⋯ menu for the feed itself, a ↵Adam Soltys2026-09-281-14/+26
|/ | | | | | | | | | | pencil for a new post. Save feed, Relays, Share and New post sat in the title row and wrapped on a phone. Share, Relays and Save or Edit now live in the feed's ⋯ sheet, and New post is a pencil; the title has the width. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* The first-ever zap tap's amount screen keeps the reader's place too.Adam Soltys2026-09-281-1/+4
| | | | | Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Zap settings opened from a hold return the reader to their place in the feed.Adam Soltys2026-09-281-6/+16
| | | | | | | | | The settings screen replaces the page, and the page came back at its top; the scroll position is remembered on opening and put back on Save, Save and zap, and Back. The feed's windowing mounts the rows for that place. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* A clip the reader turned the sound on for stays loud for the session, ↵Adam Soltys2026-09-281-5/+16
| | | | | | | | | | | | | however its box is rebuilt. Pinning the box only protected it from a patch in place. A repaint that pairs children differently, the window unmounting the row and mounting it again, or a quoted note loading all rebuilt the player muted with the button back; the URL is remembered now, and a rebuilt box starts loud with no button. Muting again from the player's own control forgets it. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Master builds again, take two: the pill commit re-swept the other agent's ↵Adam Soltys2026-09-281-48/+10
| | | | | | | | | | | | feed-snapshot hunks. Same cause as aad978d (a shared working tree); same fix: messages.js in master is the last clean version plus this commit's own three changes (the sound button leaving once unmuted, the list action under the profile row). The working tree keeps the in-progress edits for their author. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* The new-posts pill sits at the bottom; the sound button leaves once the ↵Adam Soltys2026-09-281-20/+58
| | | | | | | | | | | | | sound is on; the list action moves under the profile row. The pill was at the top of the window, a stretch for a thumb. An unmuted video kept a Mute button the player's own controls already provide, and in a quoted note the box could be rebuilt muted; unmuting now pins the box and removes the button. The ☰ on the profile's action row wrapped onto a line of its own; it is now "Add to a list" beside "Their timeline". Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Master builds again: the kind-64 commit had swept in another agent's ↵Adam Soltys2026-09-271-48/+10
| | | | | | | | | | | | | unfinished feed-snapshot work. Commit 40bec6c carried, beside its own change, an import of src/popular-feed.js (not in git) and the /api/feed snapshot path from a concurrent worktree edit, so every deploy since has failed at the build step. This restores messages.js to that commit's own change on top of the last clean version; the working tree keeps the in-progress edits for their author to commit whole. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Browser Back leaves the Manage and exit pages: they are history entries now, ↵Adam Soltys2026-09-271-2/+2
| | | | | | | and their own Back pops one. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* The Manage and exit pages keep the top nav; they are pages of the wallet, ↵Adam Soltys2026-09-271-1/+5
| | | | | | | not takeovers. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* An event of a kind this app has no renderer for shows as what its author's ↵Adam Soltys2026-09-271-12/+57
| | | | | | | | | | client said it is (NIP-31 alt), not as raw content dressed as a post. A chess game (kind 64) reached through a reaction to it painted its PGN as a reply. Now it reads "♟ Daily chess game #11: …". Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Expired dust gets a quiet line and a Forget button, not a red warning.Adam Soltys2026-09-271-3/+12
| | | | | | | | | | | A coin past its expiry and under the 330-sat floor can be renewed by nobody and exited by nobody; the home page said "the server can still renew it" in red over 21 sats. Now a muted line points at Manage, where the coin's row offers Forget: held as spent, quietly, so it stops counting and stops warning. Larger expired coins keep the warning. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* A renewal the round would refuse is retired, not resubmitted every sync; ↵Adam Soltys2026-09-271-0/+7
| | | | | | | | | | | | | | | /feed opened before the wallet no longer doubles Popular. A refresh at the created step with an input past its expiry (only the server's backstop can renew it now), or whose fee leaves less than the 330-sat floor (a 21-sat coin with a 150-sat fee sat "in progress" for days), is failed quietly and its inputs go back to spendable. /feed read before the wallet restored made a visitor's session copy of Popular beside the built-in one; the wallet's arrival now folds it away. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Faces on hosts that refuse CORS are left alone after two quick refusals.Adam Soltys2026-09-271-1/+25
| | | | | | | | | | | The thumbnail maker fetches each face once to shrink it; a host that serves pictures without CORS headers (primal's blossom, cdn.nostrcheck.me, most personal sites) refuses the bytes and the browser prints a red line per face while the <img> paints fine. The host is now remembered for a week after a second quick refusal and not asked about every new face. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* A visitor who taps zap, reply, react or boost is shown the way in; the ↵Adam Soltys2026-09-271-7/+65
| | | | | | | | | | | | | | public header has Search and Sign in. Reading is free. A tap on an action without a wallet opens a sheet with the sign-in doors (Google, passkey, Nostr), Create a new wallet, and Not now; the missing-identity path lands there too instead of a toast, and zapping is never offered to a visitor as if it could go through. The header on a public page (a feed, a profile, a thread) carries Search and Sign in. The page is remembered, so a sign-in lands back on it. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* The default public feed is Popular, not the firehose: what people reacted ↵Adam Soltys2026-09-271-11/+97
| | | | | | | | | | | | | | | | | | | | | | to, in your language, with the machine posts gone. A brand-new post has no reactions yet (of 73 fresh English posts on the four relays, one had two), so Popular starts from the other end: the latest reactions, reposts and zaps, counted per post by distinct people, then the posts two or more people touched. Older pages walk the reactions back in time; new ones arrive by a two-minute poll. At the door, JSON and other machine output are dropped, and so is anything not in the reader's language (script first, then a vote of function words among the Latin-script languages the app speaks; unknown passes). The raw firehose stays at /feed/all. A language selector sits under every feed, and changing it rebuilds the curated ones. A tall video scrolled past used to let go of its media at once and collapse, shifting the page under a thumb; it now waits a moment and holds its height until the clip is back. A tap on a full-screen picture closes it. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Relays are picked from a list, the firehose reads four of them, and a reader ↵Adam Soltys2026-09-271-32/+126
| | | | | | | | | | | | | | | | | | | | | | | with no web of trust borrows coinos's. Each relay in a feed's list is a select over popular relays that answer a bare "everything" query, with Other… for one typed in; the firehose reads coinos, damus, nos.lol and primal by default. A relay chosen by hand or named in a link is tried even if it had been marked sick, which had made a hand-picked nos.lol fetch nothing. A visitor, or a wallet that follows fewer than five people, has no follows whose flags could fold anything, so the public feeds showed the relays raw. They now get the moderation the coinos account gets: its follows' reports (and, for visitors, its mute list), read every few hours and kept on the device. A wallet's own follows and flags always come first. The new-posts pill: the generic button press moved it half its width to the right (its centring transform was replaced), so the tap never landed, and the generic hover painted it light over light text. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Everything on the coinos relay is a feed of its own, and every feed can read ↵Adam Soltys2026-09-271-38/+126
| | | | | | | | | | | | | | | | | | | | from relays of your choosing. Plain /feed is the firehose: every post relay.coinos.io carries, no filter. It sits beside Following as a built-in chip for wallets and opens as a session feed for a visitor. A feed's relay list is independent of what it asks for. The Relays button in the header opens a panel to add to or take from the list; empty means the usual choice (each author's outbox, the wide relays for a topic, the coinos relay for the firehose). The list rides in the URL as ?r=…, on every kind of feed, so a shared link reads where you read. A feed state dropped while its fetch was still out used to swallow the answers meant for its replacement; a relay change showed nothing. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Every feed has a public URL, and anyone can read it without a wallet.Adam Soltys2026-09-271-12/+163
| | | | | | | | | | | | | | | | /feed/<npub> is the timeline that person sees: their follow list, read from the relays, as a feed. /feed/<naddr> is a follow pack or a follow set, /feed/t/<tag> a topic, and /feed?p=…&t=…&pack=…&name=… any mix. A visitor gets the feed over the front door, can open a post's thread and come back; the composer, chips and editing stay with a wallet. Every feed has a Share button (the built-in Following shares as your own timeline), a profile page has "Their timeline", and Back/Forward walk through feeds by id. Public pages used to miss their repaint: the scheduler only painted the wallet screen, so a visitor's feed filled up invisibly. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Links in posts show as the cards their pages describe.Adam Soltys2026-09-271-0/+80
| | | | | | | | | | | | A plain link becomes an Open Graph card: picture, title, a line, the site. The registrar fetches the page on the reader's behalf (names/preview.js, GET /preview?url=): only public hosts, at most half a megabyte of HTML, cached a day. The client warms the card with the rest of the post so the row arrives whole, keeps a few hundred cards across sessions, and leaves a page with nothing to say as a bare link. Pictures and YouTube keep their boxes. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Sending to a coinos.io name shows the person, not the ark address it became.Adam Soltys2026-09-273-5/+16
| | | | | | | | | The recipient box keeps the name, with their face beside it and "Sent instantly, no fee."; the review names them too. The ark1… the name resolved to is plumbing, and read as gibberish to anyone new to this. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Three fixes: orphaned pending coins settle with the server; a saved start ↵Adam Soltys2026-09-271-1/+1
| | | | | | | | | | | | | | | | | screen no longer shadows a restored wallet; stop() no longer throws. Reconcile now asks the server about a 'pending' coin no live action or standing renewal order holds: spendable again, or gone. Thirty zap-sized coins another device had already spent counted in a balance for weeks. A nav saved by a page with no wallet (the start screen) was restored over a wallet that had since been saved to the device, painting the start page. messages.stop() referenced feedAt, which no longer exists, so the rest of the teardown never ran on an account switch. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Copy: no more em dashes, anywhere people read.Adam Soltys2026-09-272-2/+2
| | | | | | | | | Every English string, the translations, the README and the messages the code shows people now break with a full stop, a colon or a comma instead. Only console logs and the "—" placeholder for an empty cell keep the dash. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D