aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-11-15 14:13:08 -0700
committerAdam Soltys <[email protected]>2026-11-15 14:13:08 -0700
commitf7fe37ef75836715580e3097c7e7bc75df819bef (patch)
treed43f38574e54da723d1224ea01a479e92abf8680 /src/features
parent5c94e68ba962bab6b219b71985d49247a1e0ac48 (diff)
downloadcoinosv3-f7fe37ef75836715580e3097c7e7bc75df819bef.tar.gz
coinosv3-f7fe37ef75836715580e3097c7e7bc75df819bef.zip
Ways back in: Passkey auth, Google auth, Nostr auth, Pen and paper. "Let's call recovery phrase 'Pen and paper' with a suitable icon and no need to show it twice just make it similar to the other buttons. Instead of saying Add... for everything let's try 'Passkey auth', Google auth, Nostr auth" (Adam, 2026-11-15). The card's buttons drop Add…; the recovery phrase is the fourth button (a pen over a sheet, ✓ once the words have been seen) instead of a row with Show, and the separate Recovery phrase card under it appears only when Pen and paper asks for it (scrolled to, words masked first). Accounts without the card (watch-only, imported keys) keep the phrase card as before. signup-quick-test, onboard-backup, balance-settings-row and features-smoke pass
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMan6SwkivduFDDkMmnXjZ
Diffstat (limited to 'src/features')
-rw-r--r--src/features/nostrlogin.js16
1 files changed, 9 insertions, 7 deletions
diff --git a/src/features/nostrlogin.js b/src/features/nostrlogin.js
index e48e9a2..6f700b1 100644
--- a/src/features/nostrlogin.js
+++ b/src/features/nostrlogin.js
@@ -750,6 +750,8 @@ export function nostrLoginFeature(ctx) {
render();
}
}
+ // pen over a sheet of paper, in the line style of the passkey mark
+ const PAPER_MARK = '<svg width="19" height="19" style="display:block" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><path d="M13 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5"/><path d="M8 9h4"/><path d="M8 13h3"/><path d="M8 17h6"/><path d="M18.4 2.6a2 2 0 0 1 2.8 2.8L14 12.6l-3.6.9.9-3.6z"/></svg>';
const fmtDay = (ms) => { try { return new Date(ms).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }); } catch { return ''; } };
function waysBackCard() {
if (wallet.watchOnly || !wallet.mnemonic) return null;
@@ -780,13 +782,6 @@ export function nostrLoginFeature(ctx) {
else rows.push(done(OSTRICH, 'Nostr', (npubOf(m.id) || '').slice(0, 20) + '…', 'nostr'));
}
const seen = ctx.seedSeen();
- rows.push(h('div', { class: 'row gap6 ways-back-row', 'data-way': 'phrase', style: 'align-items:center;padding:8px 2px' },
- h('span', { style: 'display:flex;flex-shrink:0;width:23px;justify-content:center;font-size:17px' }, '🔑'),
- h('span', { class: 'col', style: 'flex:1;gap:1px' },
- h('span', { style: 'font-weight:600' }, t('recoveryPhrase')),
- h('span', { class: 'small muted' }, t(seen ? 'waysBackPhraseSeen' : 'waysBackPhraseUnseen'))),
- seen ? h('span', { class: 'ways-back-check' }, '✓')
- : h('button', { class: 'btn-sm', onClick: () => ctx.showRecoveryPhrase() }, t('waysBackShow'))));
const have = (via) => methods.some((m) => m.via === via) || (via !== 'nostr' && st.via === via);
const adds = [
hasPasskey && !have('passkey') ? add(PASSKEY_MARK, t('waysBackAddPasskey'), 'passkey', () => passkeyRecovery()) : null,
@@ -798,6 +793,13 @@ export function nostrLoginFeature(ctx) {
h('span', { class: 'linklike small', onClick: () => { ui.waysBackNostr = false; ui.waysBackError = ''; render(); } }, t('cancel'))),
signerButtons((make) => addRecovery(make, 'nostr'), { nostrOnly: true }))
: add(OSTRICH, t('waysBackAddNostr'), 'nostr', () => { ui.waysBackNostr = true; ui.waysBackError = ''; ui.nostrLoginError = ''; render(); }),
+ // the recovery phrase, as one more button (Adam, 2026-11-15): it opens
+ // the masked words below, ticked once they've been seen
+ h('button', { class: 'btn-block ways-back-add', 'data-way': 'phrase', disabled: !!busyVia, onClick: () => ctx.showRecoveryPhrase() },
+ h('span', { style: 'display:flex;align-items:center;justify-content:center;gap:8px' },
+ h('span', { style: 'display:flex;flex-shrink:0', html: PAPER_MARK }),
+ t('waysBackPaper'),
+ seen ? h('span', { class: 'ways-back-check', 'aria-label': t('waysBackOn') }, '✓') : null)),
].filter(Boolean);
return h('div', { class: 'card col ways-back', style: 'gap:6px' },
h('h3', {}, t('waysBackTitle')),