| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
| |
had grown to Post Β· π Β· GIF Β· Preview Β· Cancel; the reply box's likewise. The paperclip and GIF button are now small borderless tools inside the text field, bottom right (the field keeps room under its text so nothing runs beneath them), and the row under it is only what you do with the post: Post, Preview, Cancel (Preview, Cancel, Reply in a thread). Tests find the tools in .compose-box.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Vps2H27rhbG9ZqseGfMrc3
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
A suite run let ~90 throwaway test wallets subscribe and publish on public
relays from one home address, and nos.lol and relay.damus.io banned it.
tools/puppeteer.js wraps puppeteer-core: every socket to a non-local host
gets an in-page stand-in relay (EVENT -> OK, REQ -> EOSE). Tests that read
real content launch with { relays: 'read' } (real reads, publishes answered
in place); feed-live, chat-layout and cordn-ui launch with { relays: 'live' }.
LIVE_RELAYS=read|1|host,... overrides per run.
profile-key-qr: measure the QR again if a repaint swapped it out.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- feed tests reach the Feed from the bottom nav (the chat-home row is
gone) and seed this wallet's last feed as Following (new wallets open on
Popular, c89050e) plus the author's profile (readiness gate)
- post-actions: its picture is made locally (it read another session's
scratchpad), the post's own β― (not the feed header's), a real tap on the
DM picture (a tap beside a fitted picture is a tap on the post)
- composer-media / video-compress: intercept every public media host
(ditto is first now; the tests were uploading for real)
- compose-preview: Preview is one toggle button (aria-pressed)
- thread-reply: harness has a wallet (else visitor: Reply asks to sign in),
registers <coinos-text>, holds the root's id-only query; atomic send tap
- video-unmute: stubs what videoNode reaches outside its slice; preload
none means the in-view clip is told to load
- zap-deep-profile: zap button scrolled to mid-screen (the bottom nav
covered it)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A chevron on a post's action bar, shown once anyone has reacted, boosted
or zapped it, opens a panel that says who and with what: each zap on its
own line with the amount and any message, then each emoji with the faces
and names behind it, then the boosts. Every face opens the profile. The
zap tally now keeps who sent each receipt, not just the sum.
And a Notifications list on the chat home, under the feed: every like,
boost, zap, reply and mention that names you, one filter on the relays we
read, painted from last time while the relays are asked and live while
open. A row opens the post it is about β or the reply itself β and the
entry counts what arrived since you last looked.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Four buttons of equal weight, and only the sign-in ones said what they
did. "Get started" said nothing, so the concrete offer on that screen was
Google β which is a convenience wrapped around a seed phrase, not an
alternative to one.
Now the page says what the wallet is before it offers a button, the way
in reads "Create a new wallet" with the cost under it (a minute, twelve
words), and the three sign-ins sit below a line labelled "or, if you
already have an account".
And the second half of the same problem: a wallet that arrives by sign-in
has a recovery phrase its owner has never seen and nobody can reissue.
So the wizard shows it once, right after the first login, while it still
reads as setting up rather than as a warning out of nowhere. "I've
written it down" is the way on; "Later" is a real answer, and the wallet
then keeps one quiet line β not a modal, not dismissible, gone the moment
the phrase is actually seen, here or in settings.
seedSeen records that per account: creating shows the words, importing
means they typed them, revealing in settings counts. Only a derived seed
starts false, which is exactly the case worth asking about.
tools/onboard-backup-test.js covers both halves, including that "Later"
leaves a reminder that survives a reload and leads somewhere.
The sixteen tests that clicked the old button by its text are updated,
and it has an id now so its copy can change without breaking them again.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The reply box gets the same paperclip the post composer has: one uploader
now, handing the URL to whichever draft asked for it, and the reply's own
imeta tag describing what it carries.
And the UnifiedPush build is graphene.apk β what people will actually call
it, and short enough to read down a phone line.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Reply and zap have come down from the header to join boost, quote and the
heart, spread across the post's full width so each is a comfortable target
instead of five buttons huddled in a corner. Only the ellipsis stays up top.
Proper icons at a readable size, all the same weight: a speech bubble for
reply (a return arrow is what a keyboard does, not what a person does), the
repeat arrows for boost, quote marks, a heart, a bolt. Counts sit beside the
icon they count.
And the heart asks which feeling: tapping it opens the same six emoji the
chat sheet offers, and the one you pick is the one the post then shows β
NIP-25 takes any content, so there was never a reason to assume a heart.
Tapping your own reaction still takes it back.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
|
|
|
Under every post now: a heart with its count, a boost with its count, and a
quote. Behind an ellipsis beside reply and zap: quote, boost, copy the note's
reference, mute the author, or block them. Likes and boosts come back in the
SAME relay request the zap tallies already make β one round trip answers all
three β and each action paints before any relay does, the way the zap chip
learned to.
A like is kind 7 and a boost kind 6, published to the author's own write
relays as well as ours, so the person being answered actually sees it. A
quote opens the composer with a nostr:nevent reference already in the text
and tags the post on publish, so other clients render the embed. Taking a
like back is the only withdrawal nostr has β a deletion request naming the
reaction.
Mute is the NIP-51 list (kind 10000): their posts leave the feed at once and
the list is published, so it follows you to other clients. Block is the same
list plus an unfollow, which is why it says so.
And a bug the mute found, which the follow list had too: the optimistic paint
was being read back as fact. Both toggles paint the answer immediately and
then publish onto the newest list the relays will give them β but when the
relays had nothing newer, "the newest list" WAS the optimistic paint, so the
code saw the follow already present and published a list without it. Every
follow was a no-op that looked like it worked. The base is now the relays'
copy only when it's genuinely newer, and otherwise what we held before the
paint.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
|