<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3.git/tools/post-actions-test.js, branch fdroid-v1.9</title>
<subtitle>coinos v3 — bitcoin, Ark, Lightning and nostr wallet (web + Android)</subtitle>
<id>https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.9</id>
<link rel='self' href='https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.9'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/'/>
<updated>2026-09-29T18:18:21Z</updated>
<entry>
<title>Composers take pictures from the keyboard: the reply, post and chat fields are contenteditable.</title>
<updated>2026-09-29T18:18:21Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-29T18:18:21Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=689e21d5e77765661c44d60c10b18134b995162a'/>
<id>urn:sha1:689e21d5e77765661c44d60c10b18134b995162a</id>
<content type='text'>
Android keyboards (Gboard GIFs, stickers) only offer images to fields that
accept them, and Chrome says so for contenteditable, never &lt;textarea&gt; —
hence the greyed-out GIF key and "This app does not support images here".
&lt;coinos-text&gt; (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 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
</content>
</entry>
<entry>
<title>Videos play by themselves, muted, while on screen — with an Unmute button; YouTube too.</title>
<updated>2026-09-24T06:00:31Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-24T06:00:31Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=f6fd9f998831330e3a8819e294cdd8d15c1a87f6'/>
<id>urn:sha1:f6fd9f998831330e3a8819e294cdd8d15c1a87f6</id>
<content type='text'>
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 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Moderation: the whole mute list everywhere, follows' reports fold posts, strangers' spam hidden.</title>
<updated>2026-09-23T19:58:40Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-23T19:58:40Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=2fbfe122ae0e7d59a6b1df08cccd091010bc94ec'/>
<id>urn:sha1:2fbfe122ae0e7d59a6b1df08cccd091010bc94ec</id>
<content type='text'>
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 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>First run: "Create a new wallet" shows the twelve words at once.</title>
<updated>2026-09-21T19:04:25Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-21T19:04:25Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=9b4fa70a978e3685c9bb2b9a68f855626ac6f39e'/>
<id>urn:sha1:9b4fa70a978e3685c9bb2b9a68f855626ac6f39e</id>
<content type='text'>
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 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
</content>
</entry>
<entry>
<title>Who reacted, and what happened to your posts.</title>
<updated>2026-09-14T21:44:05Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-14T21:44:05Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=1b41cb2bbd206367e2dbb591ec0f478e018ae849'/>
<id>urn:sha1:1b41cb2bbd206367e2dbb591ec0f478e018ae849</id>
<content type='text'>
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 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
</content>
</entry>
<entry>
<title>The front door points at your own keys.</title>
<updated>2026-09-13T16:48:54Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-13T16:48:54Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=38b3d091e8e1bece958c0d7e80a5ee78434de933'/>
<id>urn:sha1:38b3d091e8e1bece958c0d7e80a5ee78434de933</id>
<content type='text'>
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) &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
</content>
</entry>
<entry>
<title>A reply can carry a picture, and the WebView build has a name you can say.</title>
<updated>2026-09-12T22:37:48Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-12T22:37:48Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=9356684a78cddd106d82296a50a637406908cffd'/>
<id>urn:sha1:9356684a78cddd106d82296a50a637406908cffd</id>
<content type='text'>
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) &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
</content>
</entry>
<entry>
<title>Every answer to a post lives in one row beneath it.</title>
<updated>2026-09-12T16:52:06Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-12T16:52:06Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=1ca77a5999bc546f92ec7189acfba1dc8088a2a7'/>
<id>urn:sha1:1ca77a5999bc546f92ec7189acfba1dc8088a2a7</id>
<content type='text'>
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) &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
</content>
</entry>
<entry>
<title>Answer a post: like it, boost it, quote it, or stop seeing its author.</title>
<updated>2026-09-12T15:28:02Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-12T15:28:02Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=f34b5a155e7cb63e15eff7e7ba9559292b31c5e1'/>
<id>urn:sha1:f34b5a155e7cb63e15eff7e7ba9559292b31c5e1</id>
<content type='text'>
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) &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
</content>
</entry>
</feed>
