diff options
| author | Adam Soltys <[email protected]> | 2026-09-02 20:09:46 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-02 20:09:46 -0700 |
| commit | 1053b92accee1d52050067d75f36c74a5fa4ca87 (patch) | |
| tree | f293e481eb3606af4c407dd860d9d04d83e99f2f /src | |
| parent | 35891af2bcf4f0d2e73fecf6558513bc1ecaeb2e (diff) | |
| download | coinosv3-1053b92accee1d52050067d75f36c74a5fa4ca87.tar.gz coinosv3-1053b92accee1d52050067d75f36c74a5fa4ca87.zip | |
The single-file wallet returns as a first-class artifact: every build now emits standalone.html (~950KB, everything inlined, boots from a bare file:// with no server), How it works grows a 'Keep a copy' card linking the download, and the tab strip's phantom double-tap dies β the pointerdown's paired click was arriving after the render had already swapped in fresh handlers, and with toggling tabs that ghost click un-did the tap it belonged to. The timestamp guard now lives on the DOM node, which survives the morph
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.js | 18 | ||||
| -rw-r--r-- | src/i18n.js | 3 |
2 files changed, 18 insertions, 3 deletions
@@ -783,6 +783,15 @@ function howItWorksScreen() { h('div', { class: 'card col', style: 'gap:14px' }, h('h3', {}, 'π ' + t('hiwGiftsTitle')), para('hiwGifts1')), + // The standalone file: the whole app inlined into one HTML β the + // save-and-open-offline story the split build gave up. Only offered when + // there's a server to download it from (on file:// you already have it). + location.protocol.startsWith('http') + ? h('div', { class: 'card col', style: 'gap:14px' }, + h('h3', {}, 'πΎ ' + t('hiwStandaloneTitle')), + para('hiwStandalone1'), + h('a', { href: '/standalone.html', download: 'coinos.html' }, t('hiwStandaloneLink'))) + : null, h('button', { class: 'btn-block', onClick: back }, t('back')) ); } @@ -821,7 +830,10 @@ function tabBtn(label, active, onClick) { // state waited for the whole pane to build. Flip the strip's classes with // a direct DOM write (paints this frame), then run the real render after // that paint β double-rAF is the "after the next paint" idiom. - let downAt = 0; + // The down-timestamp lives ON THE NODE, not in this closure: the + // pointerdown's own render replaces these handlers (fresh closure, zero + // timestamp) before the browser delivers the paired click, and with tabs + // that TOGGLE, letting that click through un-did the tap it belonged to. const select = (btn) => { if (btn && btn.parentElement) { for (const b of btn.parentElement.children) b.classList.toggle('active', b === btn); @@ -832,10 +844,10 @@ function tabBtn(label, active, onClick) { class: active ? 'active' : '', onPointerdown: (e) => { if (e.button !== 0) return; - downAt = performance.now(); + e.currentTarget._downAt = performance.now(); select(e.currentTarget); }, - onClick: (e) => { if (performance.now() - downAt > 500) select(e.currentTarget); }, + onClick: (e) => { if (performance.now() - (e.currentTarget._downAt || 0) > 500) select(e.currentTarget); }, }, label); } diff --git a/src/i18n.js b/src/i18n.js index 1d0a9d3..f2803ad 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -149,6 +149,9 @@ const STR = { hiwLn1: 'Your money can sit in two accounts. Savings is ordinary Bitcoin on the blockchain β safest for money youβre keeping, but each move costs a mining fee and waits for a confirmation. Spending sends and arrives instantly, free or nearly free, and is still only yours: it runs on Ark, a newer layer on top of Bitcoin where every coin stays locked to your key, and it speaks Lightning, so you can pay and be paid by any bitcoin app or shop.', hiwGiftsTitle: 'Gifts', hiwGifts1: 'You can gift bitcoin with a link: whoever opens it claims the coins into their own wallet β no app, no signup, works even for someone brand new to bitcoin. Until a gift is claimed, you can cancel it and take the coins back.', + hiwStandaloneTitle: 'Keep a copy', + hiwStandalone1: 'The whole wallet fits in one file. Download it, keep it on a hard drive or USB stick, and open it in any browser β it runs from there with no server and no install, and your twelve words bring your money with you.', + hiwStandaloneLink: 'Download the standalone wallet', moveMoney: 'Move money', moveToSpending: 'Into Spending', moveToSpendingDesc: 'Make money instantly spendable, with no fees to send it.', |
