| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
| |
vertical scrollbar: a short page has none, the history list filling in makes the page tall enough to get one, the viewport narrows ~15px, and the snapped card re-centers into the narrower width — a horizontal nudge right as history lands. scrollbar-gutter:stable reserves the gutter so growing content never changes the width. And the 'false start' — a boot render's alignment firing a scrollTo mid-drag — is guarded: alignment now bails while a finger/mouse is down
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
no longer reads layout (offsetLeft/scrollLeft) on every one of the many boot renders — an _alignedTo guard short-circuits before any layout touch once the card is in place, and the scroll's own settle marks itself aligned so it never re-aligns behind the user. The pass moved to rAF, and each slide gets layout containment so the history list building in below can't force it to reflow mid-scroll
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
button or finger is still down (release is the choice, shared settle logic for mouse, touch and glide) — and the coins table's dotted meta line becomes little labeled pills: an hourglass countdown, depth, and exit cost each in their own chip, the expired one wearing the warning color
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
one puts it away), every landing — login, account creation, an account snapped into the carousel — is the account's own timeline, and that timeline is now SCOPED: Savings shows the on-chain ledger and gift reservations, Spending shows the ark side. The carousel meanwhile learns mouse and mind-reading: desktop gets a real grab-and-pull drag (snap lifted mid-drag, restored on the glide), the peeking neighbor switches on a single click, and the strip wears grab cursors. And a thread's avatars and author names finally go somewhere: profiles stack on top of the conversation and back returns to it
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
riding a full-bleed strip — the neighbor card peeks in from the screen edge and snaps into place, instead of two faces crowding one card's chrome. The active card carries the move/top-up buttons and unfold panel; the peeking one stays a clean preview
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
faces with the neighbor peeking at the card's edge, dragged and snapped by native scroll-snap — settling on a face IS the account switch, programmatic switches glide the carousel to match, and the old swipe-to-flip gesture yields to the carousel's own drag (it still serves single-face wallets)
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
padding (11px/16px, asymmetric in a fixed 42px round) was shoving the ✕ off-center — flex-centered with the padding dropped
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
click event lands 100-250ms after the touch, and a tab has no scroll ambiguity to wait out — keyboard activation keeps the click path), every button takes touch-action:manipulation so double-tap-zoom arbitration stops taxing quick taps, and the sliding pane pre-promotes to its own compositor layer — a slow mid-slide re-render was letting Chrome expose unpainted gray tiles at the viewport edges
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
(pulling the avatar up inside its hat-wrap left the crown planted on the face), and the whole catalog rises 20 points — hats covered a quarter of every avatar and now kiss the top few pixels
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
the legacy avatar and banner and fills the kind 0's empty slots (fill, never overwrite — an existing nostr identity keeps its own look), the wizard's punk picker steps aside for a profile that already has a picture, and v3 finally wears cover photos — nostr's standard kind-0 banner renders full-bleed across the top of every profile card with the avatar overlapping it, settable by URL or upload in the profile editor
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
|
| |
|
|
|
|
|
| |
text (capped at five lines), Enter still sends, and a newline is one Shift+Enter or Ctrl+J away — bubbles already knew how to show them
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
|
| |
|
|
|
|
|
| |
goes purple
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
|
| |
|
|
|
|
|
| |
one, present from the static boot shell's very first paint so it never pops in
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
|
| |
|
|
|
|
|
| |
resolves on the first acceptance, DMs stop idling on the peer's inbox lookup, and the dimming departs — a sent message simply appears
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
|
| |
|
|
|
|
|
| |
flight, full strength once a relay has it
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
|
| |
|
|
|
|
|
| |
onto the screen as a dimmed bubble, crypto and relays catch up in the background, and one small tick marks the moment a relay takes it
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
|
| |
|
|
|
|
|
| |
the full forget, each keeping its own warnings
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
|
| |
|
|
|
|
|
| |
HAL_TARGET=staging stamps the brand, renames the PWA, and starts fresh wallets on Mutinynet — one master, no diverging branch
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
|
| |
|
|
|
|
|
| |
avatar everywhere it appears, from 21-sat beanie to 2.1M-sat top hat; the crown stays on the founder
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
|
| |
|
|
|
|
| |
and Move money appear once it's set up (or money's already there), and the tour is gone
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
| |
the tour stops flickering under a busy first scan and finds the balance card it lost
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
| |
and uploads just change it
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DbA53PJA8fgSvMcEzfuw22
|
| |
|
|
|
|
| |
address to land on becomes a gift only their key can open
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
| |
The header dot cleared only per-conversation, so a channel or thread you
never clicked into kept it lit forever. Now the list screen has its own
watermark: visiting it answers the header dot, while each DM and
community row shows an unread dot of its own until actually opened.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015QwAtBSpKvECqp1rHLHjJk
|
| |
|
|
|
|
|
|
| |
A recreated <img> decodes async — one blank frame per render, and boot
renders in bursts. A CSS background paints synchronously from cache, so
the profile page, chat rows, and send candidates all hold steady now.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
| |
The avatar img was recreated on every render — boot's render bursts made
it flash; there is exactly one header avatar, so the node is reused until
the profile actually changes.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The recipient candidate list was hiding under the on-screen keyboard:
scroll the field to the top on focus and when fresh candidates land,
give the list scroll room to get there, and let the keyboard resize the
viewport (interactive-widget) so the scroll has somewhere to go.
The wizard now shows whenever the device has no wallet — the one-time
onboarded flag is gone; deleting every wallet brings the wizard back.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
| |
A background repaint rebuilt the strip at scrollLeft 0 mid-swipe; render()
now carries scroll positions across the swap the same way it carries focus.
The onboarding column also sized itself to the strip's intrinsic width
(auto margins defeat flex stretch), overflowing phones below ~450px.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Paste, on the import and load-seed screens, was a bordered box floating
beside a small label — heavier than the label, detached from the field it
fills. It now sits inside the textarea, and only while that textarea is
empty: the only time it's wanted, and the only time it can't cover what
you typed. It's toggled on the node rather than through render(), since
re-rendering a textarea per keystroke rebuilds it under the caret. Beside
a one-line input (Send) the old placement was right and is untouched.
The footer measured 100dvh, which on a phone can resolve to the tall
viewport at first paint and leave the language picker just below the
fold. svh is the one that fits with the address bar showing. Short
screens also tighten their padding, which buys back the ~50px the
create/import screen was overflowing at 375x553.
And the wizard no longer asks every new user whether they have an old
coinos.io account before letting them have a name. Claiming the name is
the step; the people who do have an old account know it, and say so with
a link. That screen is a statement now, not a question they just
answered. The npub-shaped default address is no longer offered as a
button — a plain skip goes past without showing anyone that.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The sign-in screen stacked 'Connect a signer app' directly above a
bunker/nsec field, which reads as two steps rather than two ways in.
A divider says which it is.
The wizard's second step asked whether you have a nostr account, then
sent you to a screen that asks the same thing. Step one now offers both
paths directly — Get started, or sign in with Nostr — and the middle
step is gone, along with its strings. The welcome blurb goes too: the
screen is one decision, and prose above it is something to read before
you can make it.
The footer sinks to the bottom of the window rather than trailing the
content up the page. #app is a full-height column now; the chat card
sizes itself against the viewport, so the layout test covers it at
three sizes.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It looked like the dot was flickering on and off after a refresh. It
wasn't: measured over the first twelve seconds it appeared once and never
went away, while its entrance animation started seven separate times.
render() rebuilds the whole DOM, so the pop replayed on every repaint.
A dot that means 'someone is waiting' has nothing to animate about, so
the animation is gone rather than gated. tools/unread-dot-test.js counts
animation starts against real appear/disappear transitions, so a future
entrance effect here fails instead of shipping as a flicker.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The message log had a fixed 62vh height, so the card was head + panels +
log + composer tall and the input fell off the bottom of the screen. The
card is now sized to the viewport and the log is the only part that
flexes: opening the invite or member panel shrinks the scroll area
instead of pushing the composer out of reach.
Three header changes, all the same idea — don't show a control for a
choice nobody is making:
'+' becomes 'Add person', because a plus sign doesn't say what it adds.
A lone channel isn't named at all. '#general' next to a composer that
says 'Message #general' points at a choice of one; several channels
become a select, which is what a choice looks like.
The new-channel field hides behind a 'New channel' button. Sitting open
right after you create a community, it reads as something you're
supposed to fill in.
tools/chat-layout-test.js holds the line at three viewport sizes with
both panels open, and covers the header behaviour through actually
adding a second channel.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
A remote signer dropped by a reload now says so above the composer, with
a button that reconnects in place — rather than letting someone write a
message and only then be told it can't be sent as them. Failing that it
opens the nostr settings, where logging in again is the fallback.
Every remote-signer login made before sessions were persisted lands in
exactly this state once.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The header carries a message button again, left of the wallet selector,
with a red dot when a conversation is waiting. Unread is a per-thread
watermark on the newest message from someone else, kept in the rumor's
own created_at so it means the same thing on every device it syncs to.
Rooms subscribe at startup now, or the dot could not speak for a
community nobody was listening to.
Communities no longer buzz a phone by default: push registration only
carries the stream keys of communities you have opted in, per community,
from a bell in the room header. DMs and payments are unchanged.
Presence and typing ride the channel stream as 21059 wraps, so who is
around stays inside the community's encryption rather than becoming a
public status. Measured against relay.coinos.io and nos.lol, neither
actually drops NIP-01 ephemeral kinds, so beats carry a NIP-40
expiration and relay.coinos.io sweeps kind 21059 hourly — and presence
is dated by the beat, never by arrival, or a replayed beat would light
up the whole member list.
The member list follows Telegram: online, then last seen in minutes and
hours, then a vague 'recently' rather than advertising how long someone
has been gone.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
| |
The placeholder repeated a minimum the line below already states, and it
was clipped anyway — the amount field had 14px of usable width at 360px
because "Move to Spending" crushed it. The row wraps to two full-width
lines when it's tight and stays on one line when there's room.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
| |
"Instant · free to send" and "On-chain · mining fees apply" were one
line that swapped with the account; the card is just the balance now.
Strings, styles and stale translations removed with it, and the face's
reserved height comes down to match.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
| |
The dots were an indicator pressed into service as a control — fine
under a thumb that can just swipe, too small for a mouse. They're
replaced by a pill in the header row naming the account it takes you to
(⇄ Savings / ⇄ Spending), which is both a proper click target and a
clearer answer to "what's the other one?". Swiping the card still works.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Resolving a recipient (ark advert → BIP-353 → lightning) no longer
takes over the screen twice on the way: both steps keep the send form
in place and report progress as one inline line, so picking someone
goes straight to something actionable. The recipient chip on the zap
card gets a large variant — a 30px avatar and full-size name, since
it's who the money is going to.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Into Spending gains a Max (fee-aware — it asks the tx builder what a
sweep would actually deliver, so the mining fee can't make the board
fail), and both directions now carry Max as a small affordance inside
the input's right edge instead of a button eating a third of the row.
It only appears when there's a balance to max. Balance face height
trimmed to match its shorter content.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Replaces the segmented toggle and the always-visible second balance.
The card now shows the account you're in at full size with a plain-word
descriptor ("Instant · free to send" / "On-chain · mining fees apply"),
two dots to flip, and a sideways slide when it changes. A swipe that
starts on the card switches account instead of tab; swipes anywhere
else still move between Receive/Send/History.
Fixes a real mobile bug found while testing: a touch sequence still
fires a compatibility click at the release point, so every swipe was
ALSO pressing whatever sat under the finger (which is what kept
bouncing the test wallet back to the unlock screen). One click is now
swallowed after a recognized swipe.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
| |
72px, centered above the question (and the sign-in step), with a purple
glow and a slow float — the one place in the flow that isn't the coinos
brand, so it should look like nostr.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
coinos.io serves 502 for a third of the punk set (both the numbered and
hash endpoints), which is why a default avatar could come up blank. The
64 webps now ship with the app (53 salvaged, 11 gaps filled with
donors) and every reference is same-origin. Skipping the avatar step
publishes the deterministic punk as the kind-0 picture — your face is
the same on every nostr client. Success screen: checkmark now sits
below the title, bigger.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fresh devices land in a full-screen flow instead of the unlock screen:
welcome → "do you have a nostr account?" (sign in brings wallet, name,
and profile along; No mints a wallet on the spot) → claim a username
(the background npub-default only surfaces a Keep button; a custom
claim — or a restored login's recovered name — advances by itself) →
pick a punk or upload a photo (nostr.build), published as the kind-0
name+picture → confetti. "Enter coinos" drops into a three-stop tour:
the avatar menu, the Spending/Savings toggle, and the tabs with the
swipe tip — each highlighted by a measured gold ring over a dimmed
page. One time only (localStorage flag), with an "I already have a
wallet" escape to the classic screen.
New seams: names.namesClaimForm, messages.publishProfile.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Tab changes no longer flash the whole page: only the content pane below
the tab strip slides sideways with a soft cross-fade — swipe direction
when a gesture caused it, index order for taps — while the balance card
and strip stay planted. Full-page entrances remain for real page
changes (settings, chat, profile, takeovers).
After a nostr sign-in the header briefly wore the wallet key's face:
nostrLoginIdentity now reports a just-connected live signer immediately
instead of waiting for the persisted link that only lands after the
wallet opens.
The nostrconnect URI carries a callbackUrl hint (NIP-55 style) so
signer apps that honor it can bounce back to the PWA after approval —
apps that don't will still find the session signed in when the user
returns, since the handshake completes over the relay in the
background.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Horizontal-dominant quick swipes move through the main tabs, sliding
the page in from the swipe's direction (the nav animation picks a
directional variant when a gesture caused it). Gated to the wallet's
own tab pages — never chat, profiles, takeovers, or offline-forced
settings — with a vertical-dominance test so scrolling never
navigates, a touchcancel reset, and overscroll-behavior-x: none so the
browser's edge-back gesture doesn't fight ours.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The renderer rebuilds the DOM on every render, so naive CSS mount
animations would replay on every background repaint. Two primitives fix
that: uiChanged() gates one-shot animations to the render where the
thing actually happened, and animWindow() lets a rebuild that lands
mid-animation RESUME it via a negative animation-delay instead of
killing or restarting it.
On top of those: every real navigation rises in (screen/tab/subpage/
chat/profile — one keyed check in render()); the balance counts to its
new value and breathes green when money arrives; the avatar menu pops
from its corner; the move panel unfolds; the success check springs and
rings once when its page lands. Micro-transitions on buttons, tabs,
segs, inputs, list rows, avatars, and the settings chevrons.
One chromatic signature on the monochrome brand: a slow-drifting
bitcoin-gold ribbon across the top of the balance card, echoed by a
faint warm wash pooling at the top of the page, plus a film-grain
overlay for texture. All of it honors prefers-reduced-motion. The
nostr sign-in mark also gets a proper inset ostrich and a size bump.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
| |
A watch-only wallet has no nostr identity, and the whole avatar menu —
including Settings and Logout — vanished with it. The menu now shows a
neutral face and keeps the keyless items; Edit profile and Messages
appear only when an identity exists.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|