aboutsummaryrefslogtreecommitdiffstats
path: root/tools
Commit message (Collapse)AuthorAgeFilesLines
...
* Discard canceled post draftsAdam Soltys2026-09-291-0/+17
|
* Fix public media uploads and feed tab navigationAdam Soltys2026-09-292-0/+61
|
* Cache notification note content locallyAdam Soltys2026-09-291-0/+128
|
* "Save feed" on someone's timeline adds it to your feeds at once, instead of ↵Adam Soltys2026-09-281-0/+14
| | | | | | | | | | | | | 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-0/+8
| | | | | 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-282-1/+95
| | | | | | | | | | | | | | 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-0/+8
| | | | | | | | | | | 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/+73
| | | | | | | | | | 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-3/+20
| | | | | | | | | | | | | | | 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 zap refused for an old expired coin goes again on the other coins instead ↵Adam Soltys2026-09-281-7/+16
| | | | | | | | | | | | | of showing the server error. Sub-dust coins skip the local expiry check, so the ASP can refuse one at cosign ("vtxo … expired at height …"). The coin was already marked excluded, but the error still surfaced and the user had to tap again. send() and payLnInvoice() now retry (up to 5 attempts) when that exact refusal marks an input, without a failed history row for the retried try. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
* Pinch to zoom a full-screen picture.Adam Soltys2026-09-281-0/+84
| | | | | | | | | Pinch zooms around the fingers (up to 5x), one finger pans a zoomed picture within its edges, double-tap zooms in at a spot and again to reset, and the wheel zooms on a desktop. A tap still closes an unzoomed picture (after a beat, so it can be the first half of a double-tap); a gesture never does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A reloaded thread paints whole, quoted posts included, with no spinner.Adam Soltys2026-09-281-1/+7
| | | | | | | | | 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-0/+74
| | | | | | | | | | | 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]>
* The chat list shows four conversations and four communities, the rest behind ↵Adam Soltys2026-09-281-3/+14
| | | | | | Show all. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The bottom nav rides every page: Feed, Messages, Notifications, Wallet.Adam Soltys2026-09-282-33/+40
| | | | | | | | | 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]>
* Restore public feed state when navigating Back from WalletAdam Soltys2026-09-281-0/+24
|
* Keep feed navigation visible and add a wallet shortcutAdam Soltys2026-09-281-5/+14
|
* Add scrolling feed navigation for home, messages and notificationsAdam Soltys2026-09-281-0/+73
|
* Merge remote-tracking branch 'prod/prod' into merge-tmpAdam Soltys2026-09-281-0/+51
|\
| * Fix video unmute after feed repaintsAdam Soltys2026-09-281-0/+51
| |
* | The feed header keeps its room on a phone: a ⋯ menu for the feed itself, a ↵Adam Soltys2026-09-282-3/+4
|/ | | | | | | | | | | 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
* A clip the reader turned the sound on for stays loud for the session, ↵Adam Soltys2026-09-281-0/+6
| | | | | | | | | | | | | 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
* The new-posts pill sits at the bottom; the sound button leaves once the ↵Adam Soltys2026-09-281-2/+2
| | | | | | | | | | | | | 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
* The default public feed is Popular, not the firehose: what people reacted ↵Adam Soltys2026-09-271-6/+6
| | | | | | | | | | | | | | | | | | | | | | 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
* Everything on the coinos relay is a feed of its own, and every feed can read ↵Adam Soltys2026-09-272-7/+8
| | | | | | | | | | | | | | | | | | | | 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
* Links in posts show as the cards their pages describe.Adam Soltys2026-09-271-0/+123
| | | | | | | | | | | | 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
* Accounts: tapping an identity signs in as it and opens its profile; the ↵Adam Soltys2026-09-273-23/+25
| | | | | | | | | | | | padlock moves from the header to this page. The identity chip used to put the npub in the URL and leave the list on screen (the profile only paints over the wallet screen). Lock/Unlock now sits with the other device-wide actions (log out, clear); the padlock tests reach it through the Accounts page and lose their stale "Wallets" button. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Amber (NIP-55) signs you in on Android: one intent per request, the answer ↵Adam Soltys2026-09-271-0/+93
| | | | | | | | | | | | | | | read off the clipboard or pasted. Closes #7. A "Sign in with Amber" door on Android opens nostrsigner: intents for get_public_key, sign_event and nip44 encrypt/decrypt, with a waiting card that reads the clipboard when the tab returns (or takes a paste). Requests queue one at a time — a sign-in fires the backup, relay list and follows together — and each answer is checked for its type so a stale clipboard is never mistaken for one. An interactive signer is not asked to decrypt DMs or private lists that arrive on their own; each trip through Amber is a deliberate one. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* moderation test: the mis-flagged person's post is unfolded (check the fold ↵Adam Soltys2026-09-271-1/+1
| | | | | | | row, not the revealed text) Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Reports: a person-level flag needs two follows to fold their posts; 'other' ↵Adam Soltys2026-09-271-3/+9
| | | | | | | | | | | never counts. One follow's mis-tapped "impersonation" on fiatjaf's key was folding his entire timeline. A flag on a specific post from one follow still folds that post. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Feed: the foot says when older posts are loading, and when there are none left.Adam Soltys2026-09-271-3/+16
| | | | | Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Media sources wait until the node is in the page; thumbnails use the cache.Adam Soltys2026-09-262-3/+8
| | | | | | | | | | | | | | | | | | | | | Every render builds a fresh tree to diff against the live one, and a media element starts downloading the moment its src is set, even off the document: a sixteen-second feed scroll built 204 <video> and 1,416 <img> elements whose loads the morph then threw away — 375 cancelled video range requests, and full re-downloads from hosts that send no cache headers. h() now puts the source on data-lazy-src and it becomes src only once the node is in the page (render promotes it; a MutationObserver covers nodes appended by hand); the morph treats the two as one attribute. The thumbnail maker fetched every original with cache: 'reload' (38 MB in one scroll); the face was just painted from that URL, so the cache serves. holdScroll now recovers an anchor row that a large insert above pushed out of the window, from the height cache. Tests: the YouTube test accepts the in-view players autoplay loads; the stability test watches the notice for the catch-up, since the new rows land inside the window's spacer. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Thread: the reply box appears on Reply, full width, with its tools on a row ↵Adam Soltys2026-09-263-6/+11
| | | | | | | | | | | | | | | | | beneath. A thread opened to read came with an empty field under its first post. The box now appears under the note whose Reply was tapped (or while a draft is pending), folds away once the reply is sent or Cancel is tapped, and takes Amethyst's shape: the field across the full width, attach and preview on a row beneath it with Cancel and Reply at the right. Tests: thread-reply's helper follows the new shape and expects the box to fold after sending; compose-preview and feed-list tap Reply before expecting a box (the thread card carries .thread-card as the marker). Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Notifications: the faces the page will paint are warmed before it opens.Adam Soltys2026-09-261-0/+100
| | | | | | | | | | | | | | | | The list was already cached locally and refreshed from the chat home, but each row only asked for its author's profile when painted, so the page opened as quiet circles filling in one by one. Now the actors' names are fetched in one batch and each picture decoded into a thumbnail the moment the list is read from disk or grows — which the chat home does before the page is ever opened. Test: notif-faces (stub relay answers the kind-0 batch; the pictures are fetched and cached from the chat home; every row has its face on the first frame). Note for tests: serve /verify-worker.js from dist, or every relay answer waits four seconds for the inline fallback. Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Feed: only the rows near the viewport are in the DOM, however far you scroll.Adam Soltys2026-09-263-3/+135
| | | | | | | | | | | | | | | | | | A long scroll left hundreds of rows mounted, and every repaint (a zap count, a profile landing, the thirty-second sync) rebuilt and diffed all of them — the slowdown deep in the feed. Rows beyond two and a half screens either side of the viewport are now replaced by a spacer at their measured height, so the page keeps its length (scrollbar, Back, arrival anchoring behave as before) while a repaint touches a few dozen rows. After svelte-virtual-list: measure after paint, estimate unmeasured rows at the running average, hold the reader's row still when a measurement corrects an estimate. Applies to the profile notes list too. Tests: feed-window-dom (120 posts, 27,800px page, 12–24 rows mounted, anchor held, spacers both sides); feed-live looks at the top after scrolling up; the moderation test's stub relay no longer lets real posts in. Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Feed: cached posts paint at once, never a spinner over them; the chat home ↵Adam Soltys2026-09-251-3/+6
| | | | | | | | | | | | | | prefetches the feed. The boot gate hid everything, cached posts included, until the opening page's faces and pictures had decoded — seconds of spinner on a feed we already held. Cached rows now paint immediately as they are and take their prepared presentation once the warm-up lands (the container carries data-booting meanwhile). The relay fetch starts at once instead of after the warm-up; arrivals still wait at the door. Opening the chat home warms and refreshes the current feed, so the Feed tap opens on the latest posts. Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Prefetch a smaller feed and bound its local cacheAdam Soltys2026-09-242-5/+50
|
* Preserve restored thread state across rapid refreshesAdam Soltys2026-09-242-7/+27
|
* Paint cached thread counts and header hat on refreshAdam Soltys2026-09-243-2/+46
|
* Keep thread avatars and viewport stable on refreshAdam Soltys2026-09-242-1/+23
|
* Videos play by themselves, muted, while on screen — with an Unmute button; ↵Adam Soltys2026-09-233-5/+115
| | | | | | | | | | | | | | | | | | | YouTube too. An inline video starts as it scrolls into view (muted, the only way a browser lets a page start one), pauses as it leaves, and a corner button turns the sound on; the native controls' own mute keeps the button honest. A YouTube box loads its player muted once in view (enablejsapi, so the same button can unmute it over the iframe API) and pauses out of view; a tap on the poster still means sound. One IntersectionObserver watches every player. Data Saver keeps tap-to-play. Tests adapted to the feed's new admission rule (a row waits for its author's face and pictures): the markdown and post-actions tests seed the poster's profile and serve their pictures locally; a picture that cannot be decoded is now a link, by design. Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Feed: threads cached locally, posts never inserted under the reader, rows ↵Adam Soltys2026-09-236-21/+407
| | | | | | | | | | | | | | | | | | | | | | | | | | | | keep their first look. Work by Codex, wrapped up and verified here. Threads: a viewed conversation is persisted (thread-cache.js, up to 12 threads / 160 events), so a refresh or a cached note link shows the root and ancestors at once instead of the selected reply and a spinner; relays are re-asked in the background and an empty answer keeps the cache. Feed window (feed-window.js): arrivals are merged without inserting between visible rows — a gap fill under the reader's eyes waits until that part of the feed is offscreen, prepends anchor the reading position, the notice counts what went in above, and only its tap goes to the top. Older pages are prepared a few screens ahead; a page's pictures and faces are decoded before it is shown. Rows keep the presentation they were admitted with (feedPaint): background profile and quote refreshes no longer rewrite text or swap faces mid-read; media dimensions are known before paint. Thumbnails queue instead of being dropped past the first three. Tests: thread-cache, feed-window, feed-stability; feed-live updated for the new arrival rules (the notice counts up while you read). Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Keep chat headers and composers pinned without page scrollingAdam Soltys2026-09-231-3/+51
|
* Moderation: the whole mute list everywhere, follows' reports fold posts, ↵Adam Soltys2026-09-232-2/+190
| | | | | | | | | | | | | | | | | | | | | | strangers' spam hidden. Mutes were only applied when the feed merged and painted. One predicate (hiddenWhy / hiddenPk) now gates the feed, thread replies, notifications, the who-reacted panel and counts, quote cards, rooms, the DM list and the DM push. The list itself is read in full — people, words, hashtags, whole threads, and the nip44 private half — and edited through one publish path (mute thread and hidden words from the ⋯ menu and a Settings → Nostr card). Reports (NIP-56) from the people you follow are read from their outbox relays every half hour; a post or author they flagged is folded behind who said so, with Show. Report… in the ⋯ menu publishes a kind 1984 and hides the post for you. Amethyst's stranger rules: a post of 60+ characters repeated under another id is a duplicate and five duplicates hide the author for the session; more than ten hashtags hides the post. Both switchable in Settings. Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Social: NIP-51 lists as feeds, posts and people in the address bar, the ⋯ ↵Adam Soltys2026-09-231-0/+176
| | | | | | | | | | | | | | | | | | | | | | menu on every screen. Lists: a feed of hand-picked people is published under your key as a kind-30000 follow set (title, p tags, t tags), so Coracle, Nostria and friends show it; your existing follow sets from other clients turn up as feeds (relay copy wins when newer; private nip44 members read and followed, never rewritten). "Keep as a nostr list" in the editor; unticking sends a NIP-09 deletion and the feed stays. "Add to a list" from a profile or a post's ⋯; someone's lists show on their profile and open as feeds (a kind-30000 naddr works as a pack too). Links: a thread puts its nevent in the address bar, a profile its npub — copy, share, reload; Copy link / Share in the ⋯ sheet. Boot-time renders after a reload share one history slot, so Back goes to the screen before. Fix: the ⋯ sheet and the reaction picker were only drawn by the feed and notification views, so the button did nothing on a thread or a profile. Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Payment detail: the unit is the tap-to-toggle tag; tests enter through the ↵Adam Soltys2026-09-2211-12/+12
| | | | | | | wizard's import line. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* Starter feeds: #gardenstr only until a Bitcoin follow pack is chosen.Adam Soltys2026-09-211-6/+5
| | | | | Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* New identities start with something to read: Adam and coinos followed, a ↵Adam Soltys2026-09-211-11/+15
| | | | | | | | | | | | | | | Bitcoin feed, and #gardenstr. A wallet the wizard made from fresh words, or a sign-in that found no wallet on its identity, gets one kind-3 update following the two coinos accounts (a sign-in identity only if it follows nobody yet), plus two starter feeds. The Bitcoin feed has a follow-pack slot (STARTER_BITCOIN_PACK) and reads the #bitcoin topic until a pack is chosen; #gardenstr shows what a topic feed is. Once per identity. The feed test now runs through the real first run, reading the words off the screen. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* First run: "Create a new wallet" shows the twelve words at once.Adam Soltys2026-09-2116-16/+16
| | | | | | | | | | | | No create/import tabs and no Generate button inside the wizard: the words appear the moment the button is tapped. Underneath, "Have an existing seed or entropy to import?" swaps to the import pane (which has its own entropy door), and "Create a new wallet instead" swaps back with fresh words. The create/import card elsewhere (adding an account) keeps its tabs. Tests that entered through the old tab go through the new line. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* Point of sale: a paid sale opens its payment detail, which now says bill and ↵Adam Soltys2026-09-211-1/+9
| | | | | | | | | | | | tip. The row finds the ln-receive movement by the invoice it recorded and opens the same detail screen the history page shows; the detail asks features for more (arkMoveDetailExtra) and the till adds Bills, Tips (with the percentage) and the note. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp