diff options
| author | Adam Soltys <[email protected]> | 2026-08-26 22:08:06 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-26 22:08:06 -0700 |
| commit | e0df50201e71868d9aad375db66cb217938c0c1c (patch) | |
| tree | d9d60625a8fc0142c7c2ba3aacd57c8550c53b15 /src/features | |
| parent | 2eff4689a48da32f70fa2d6d15346a881bf9d1fc (diff) | |
| download | coinosv3-e0df50201e71868d9aad375db66cb217938c0c1c.tar.gz coinosv3-e0df50201e71868d9aad375db66cb217938c0c1c.zip | |
All three doors on the porch: Google, passkey, and Nostr sign-in stand directly on the welcome screen — Google and passkey act in place, the Nostr button steps into the signer list as before
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/nostrlogin.js | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/src/features/nostrlogin.js b/src/features/nostrlogin.js index fdab973..fa6627b 100644 --- a/src/features/nostrlogin.js +++ b/src/features/nostrlogin.js @@ -263,11 +263,11 @@ export function nostrLoginFeature(ctx) { } } - // The ways in, as buttons. `run` receives a signer factory. - function signerButtons(run) { - const hasExt = typeof window !== 'undefined' && !!window.nostr; + // Google + passkey, with their transient status rows — shared between the + // collapsed front-door card and the expanded signer list. + function externalButtons(run) { const hasPasskey = typeof window !== 'undefined' && !!window.PublicKeyCredential && !!navigator.credentials; - return h('div', { class: 'col', style: 'gap:8px' }, + return [ h('button', { class: 'btn-block', disabled: ui.nostrLoginBusy, onClick: () => googleLogin(run) }, t('nlGoogle')), ui.nostrLoginStatus ? h('div', { class: 'row gap6', style: 'align-items:center;justify-content:center' }, @@ -282,6 +282,14 @@ export function nostrLoginFeature(ctx) { h('button', { class: 'btn-sm', disabled: ui.nostrLoginBusy, onClick: () => passkeyCreateLogin(run) }, t('nlPasskeyCreate')), h('button', { class: 'btn-sm btn-ghost', onClick: () => { ui.passkeyOffer = null; render(); } }, t('cancel'))) : null, + ]; + } + + // The ways in, as buttons. `run` receives a signer factory. + function signerButtons(run) { + const hasExt = typeof window !== 'undefined' && !!window.nostr; + return h('div', { class: 'col', style: 'gap:8px' }, + ...externalButtons(run), hasExt ? h('button', { class: 'btn-block', disabled: ui.nostrLoginBusy, onClick: () => run(() => extensionSigner()) }, t('nlExtension')) @@ -331,16 +339,20 @@ export function nostrLoginFeature(ctx) { h('button', { class: 'btn-primary grow', disabled: ui.nostrLoginBusy, onClick: createForSigner }, ui.nostrLoginBusy ? h('span', { class: 'spinner' }) : t('nlCreateBtn')))); } - // Collapsed by default: one button, expanded only when asked for. + // Collapsed by default: Google, passkey, and Nostr right on the front + // door; the Nostr button expands into the full signer list. if (!ui.nostrLoginOpen) { - // NB .btn-block forces display:block, so the flex centering lives on an - // inner wrapper rather than the button itself. - return h('button', { - class: 'btn-block', - onClick: () => { ui.nostrLoginOpen = true; ui.nostrLoginError = ''; render(); }, - }, h('span', { style: 'display:flex;align-items:center;justify-content:center;gap:8px' }, - h('span', { style: 'display:flex;flex-shrink:0', html: OSTRICH }), - t('nlSignIn'))); + return h('div', { class: 'col', style: 'gap:8px' }, + ...externalButtons(loginWith), + // NB .btn-block forces display:block, so the flex centering lives on + // an inner wrapper rather than the button itself. + h('button', { + class: 'btn-block', + onClick: () => { ui.nostrLoginOpen = true; ui.nostrLoginError = ''; render(); }, + }, h('span', { style: 'display:flex;align-items:center;justify-content:center;gap:8px' }, + h('span', { style: 'display:flex;flex-shrink:0', html: OSTRICH }), + t('nlSignInNostr'))), + ui.nostrLoginError ? h('div', { class: 'notice err' }, ui.nostrLoginError) : null); } return h('div', { class: 'card col', style: 'gap:10px' }, h('div', { class: 'row between' }, @@ -563,6 +575,21 @@ export function nostrLoginFeature(ctx) { } finally { resuming = null; } }, unlockExtra() { return unlockExtra(); }, + // The welcome screen's sign-in block: Google and passkey act right there; + // the Nostr button steps into the wizard's signer list. + frontDoorSignin() { + return h('div', { class: 'col', style: 'gap:8px' }, + ...externalButtons(loginWith), + h('button', { class: 'btn-block', style: 'padding:14px', onClick: () => { + if (ui.onb) ui.onb.step = 'signin'; + ui.nostrLoginOpen = true; + ui.nostrLoginError = ''; + render(); + } }, h('span', { style: 'display:flex;align-items:center;justify-content:center;gap:8px' }, + h('span', { style: 'display:flex;flex-shrink:0', html: OSTRICH }), + t('nlSignInNostr'))), + ui.nostrLoginError ? h('div', { class: 'notice err' }, ui.nostrLoginError) : null); + }, nostrSettingsCards() { return [settingsCard()]; }, }; } |
