From 3227fa8ca1ef57fff3e2242dc84899482ea9b260 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 7 Oct 2026 11:25:39 -0700 Subject: Swiping to Savings opens its Receive pane (the deposit address, no extra tap); Enter on Send picks the top suggestion, and Enter walks amount → review → confirm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- src/app.js | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/app.js b/src/app.js index 56ab639..4f42529 100644 --- a/src/app.js +++ b/src/app.js @@ -696,6 +696,25 @@ function attachZoom(box, img) { } if (typeof window !== 'undefined') { window.addEventListener('keydown', (e) => { if (e.key === 'Escape' && ui.lightbox) goBack(() => { ui.lightbox = null; }); }); + // Enter walks the Send flow: from an amount (or any field) it presses the + // screen's main button — Review, Pay, Send — and with nothing focused it + // presses it again, so amount ⏎ reviews and ⏎ again confirms. A held key + // (auto-repeat) never presses anything: one deliberate tap per step. + window.addEventListener('keydown', (e) => { + if (e.key !== 'Enter' || e.repeat || e.isComposing || e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) return; + if (ui.screen !== 'wallet' || ui.tab !== 'send') return; + const pane = document.querySelector('[data-send-pane]'); + if (!pane) return; + const a = document.activeElement; + const onBody = !a || a === document.body || a === document.documentElement; + // buttons and links answer Enter themselves; the recipient field has its own + if (!onBody && !(a.tagName === 'INPUT' && pane.contains(a) && !/^(checkbox|radio|button|submit)$/.test(a.type))) return; + const btn = pane.querySelector('.btn-primary.btn-block:not(:disabled), .btn-primary.grow:not(:disabled)'); + if (!btn) return; + e.preventDefault(); + if (!onBody) a.blur(); // the next Enter belongs to the screen this one opens + btn.click(); + }); } function render() { @@ -4396,10 +4415,11 @@ function balanceCard() { ui.accountUserChosen = true; // a deliberate pick — no auto-select behind it ui.account = view; try { localStorage.setItem(ACCOUNT_KEY, view); } catch {} - // selecting an account lands on its history (home), any open - // payment detail belonged to the other account + // selecting Spending lands on its history (home); Savings opens on + // its Receive pane, the deposit address being what you swiped over + // for. Any open payment detail belonged to the other account. ui.txDetail = null; ui.arkMoveDetail = null; ui.arkReconDetail = null; ui.arkExitDetail = null; ui.giftDetail = null; - ui.tab = 'history'; + ui.tab = view === 'savings' ? 'receive' : 'history'; render(); }; // Where will a released touch flick land? Nearest card, pushed one over @@ -4603,7 +4623,7 @@ function balanceCard() { ui.account = v; try { localStorage.setItem(ACCOUNT_KEY, v); } catch {} ui.txDetail = null; ui.arkMoveDetail = null; ui.arkReconDetail = null; ui.arkExitDetail = null; ui.giftDetail = null; - ui.tab = 'history'; + ui.tab = v === 'savings' ? 'receive' : 'history'; // as commitAccount render(); }, }, faceFor(v), ...(v === 'spending' ? cardExtras(v) : [])))); @@ -4668,6 +4688,7 @@ function tabContent() { if (detailOpen) return hist; sendFocused = false; const pane = ui.tab === 'receive' ? receiveTab() : sendTab(); + if (ui.tab === 'send' && pane && pane.setAttribute) pane.setAttribute('data-send-pane', ''); // Past the recipient — an amount to enter, a payment to confirm — the // history is one more thing on screen while you're about to send. if (ui.tab === 'send' && sendFocused) return pane; @@ -5178,8 +5199,15 @@ function recipientRow(s, r, i) { class: 'mono-input grow send-dest', placeholder: i === 0 ? t('destPlaceholder') : 'bc1q…', rows: String(destRows(shown)), wrap: 'soft', autocapitalize: 'none', autocomplete: 'off', spellcheck: 'false', value: shown, - // one line of text: Enter doesn't break it - onKeydown: (e) => { if (e.key === 'Enter') e.preventDefault(); }, + // one line of text: Enter doesn't break it — it picks the top suggestion + // when the list is showing + onKeydown: (e) => { + if (e.key !== 'Enter') return; + e.preventDefault(); + if (e.isComposing || e.repeat) return; + const top = i === 0 && suggest && suggest._rows && suggest._rows[0]; + if (top) sendSearch.pick(top); + }, // pasted text is complete: it moves on at once, like the Paste button onPaste: () => { r._pasted = true; }, // the delay lets the keyboard start opening (and any render() swap of -- cgit v1.2.3