| Commit message (Collapse) | Author | Age | Files | Lines |
| ... | |
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
| |
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 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
|
| |
|
|
|
|
|
|
|
|
| |
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 "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
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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 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]>
|
| |
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
| |
Show all.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
| |
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]>
|
| | |
|
| | |
|
| | |
|
| |\ |
|
| | | |
|
| |/
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
| |
row, not the revealed text)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
|
| |
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
|
| |
wizard's import line.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|