| Commit message (Collapse) | Author | Age | Files | Lines |
| ... | |
| |
|
|
|
|
|
|
|
|
|
|
| |
nostr.download, nostr.build.
A 2026-09-30 benchmark (4 MB mp4, 110 KB jpeg; upload then fetch, twice):
ditto took the mp4 in ~0.6 s and serves from ~120 ms; primal ~1.5 s;
nostr.download ~1-2 s but rejects a JPEG with data after its end marker
(motion photos); blossom.nostr.build ~5 s with ~600 ms first byte.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WMMwWYJkPQxLgfMsY7hWcU
|
| |\ |
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
A pill with the pencil and "Post", fixed above the bottom nav inside the
page column, wherever the reader is in the feed; the tap scrolls to the
top, opens the composer and focuses it. Hidden while the composer is
open (it has its own Post button) and for visitors.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
then uploading; the pencil reads "New post".
ui.mediaProgress { stage, pct } (a render per whole percent) drawn as a
labelled bar under the reply and post composers, instead of only the
paperclip turning into a spinner. Upload progress comes from
XMLHttpRequest upload events (fetch() has none) in uploadPublicMedia's
new onProgress; injected fetchers (tests) keep the fetch path.
upload-progress-test: 1.2 MB at 400 KB/s climbs 0→100 in steps.
video-compress-test: the bar counts the shrink, then the upload.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
host.
No public Blossom host transcodes (nostr.build's and primal's BUD-05 /media
return the same bitrate), so a 15-20 Mbps phone clip stalled on playback.
src/video-compress.js re-encodes on the device with WebCodecs via
Mediabunny (a lazily loaded chunk, left out of the SW precache and the
standalone file): H.264, short edge 720, ~2.5 Mbps, moov first, audio
passed through, rotation baked in. Anything short of a clear win uploads
the original. A toast counts the shrinking down.
Media hosts: blossom.nostr.build first, nostr.download second (it was
unreachable for hours); a HEAD probe skips a host that doesn't answer
within 5 s instead of waiting out the whole upload timeout.
video-compress-test: 1080p 20 Mbps 5 s (landscape and rotated portrait) →
1.6 MB H.264 720p 2.49 Mbps with audio, moov first, in 2-3 s.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
up" after a handful.
#gardenstr: 5 posts across damus/primal/nos.lol/ours (they prune), 774 once
archive-keeping relays are asked too (ditto, nostr.mom, oxtr, nostrplebs,
nostr21, offchain) — topic feeds now read those. And a page whose posts
were all filtered out (replies, muted, spam) no longer ends the feed:
paging goes on from the oldest event the relays returned, up to three
asks per scroll. The quoted-note wide net gains ditto/nostrplebs/nostr21.
topic-depth-test (/feed/t/gardenstr): 9 posts then "caught up" before,
73+ and still going after.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
your own feed again.
The Feed tab reopened whichever feed was last on — the session timeline —
and ‹ on it went to the chat list, so there was no way back to your own
feed. The tab now opens the last of your own feeds; ‹ on a feed opened
from somewhere (a timeline, a #tag, a pack link) steps back in history.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
instead of "signal is aborted without reason".
[email protected]: the lnurlp endpoint answers in 0.15 s but its invoice
callback hangs 30 s then 502s; our 8 s timeout surfaced as the browser's
raw AbortError text. Errors now name the host, a timeout says their
address may be down, and an error response's LNURL reason is shown.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
other page.
goHome cleared a hand-kept list of pages and the vtxo list (arkCoinsPage)
wasn't on it — nor a transaction's detail, the hat shop, the till. It now
clears every page the history tracks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
| | | |
|
| | | |
|
| | | |
|
| | | |
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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]>
|
| | |
| |
| |
| | |
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
flickers.
The panel was swapped for fresh nodes on every background render, which
dropped :hover each time. Now it's one node for the page's life and its
rows are rebuilt only when the results change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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]>
|
| | |
| |
| |
| |
| |
| | |
Show all.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| | |
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]>
|
| | |
| |
| |
| |
| |
| |
| |
| |
| | |
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]>
|
| | | |
|
| | | |
|
| | | |
|
| | | |
|
| |/
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |\ |
|
| | | |
|
| |/
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
|
| |
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
colour follows the app's.
One dark colour for both bars gave white navigation icons over a light page
under gesture navigation. The wrapper (1.9, versionCode 10) now uses the
page background in light mode and the dark theme colour in dark mode, for
the status bar and the navigation bar alike. The page updates its
theme-color meta when its own theme is applied, so a PWA's status bar and
the wrapper's follow the same switch.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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
|