diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.js | 3 | ||||
| -rw-r--r-- | src/features/names.js | 15 | ||||
| -rw-r--r-- | src/features/nostrlogin.js | 9 |
3 files changed, 26 insertions, 1 deletions
@@ -1129,6 +1129,9 @@ async function activateAccount(acc, opts = {}) { if (acc.type !== 'watch' && !acc.provisional) acc.xpub = wallet.accountXpub(); persistAccounts(); autoSave(acc); + // A name fetched during sign-in seeds the names state BEFORE features init + // and the first paint — the Receive pane opens showing its QR. + if (opts.nameHint) { try { featureHook('namesSeed', opts.nameHint); } catch {} } for (const f of FEATURES) { try { f.init && f.init(); } catch {} } // per-feature wallet lifecycle _featuresInited = true; // a deferred feature landing after this point gets its init() on arrival // A freshly generated identity provably has no profile yet — let features diff --git a/src/features/names.js b/src/features/names.js index 235b834..5b2f856 100644 --- a/src/features/names.js +++ b/src/features/names.js @@ -650,6 +650,21 @@ export function namesFeature(ctx) { namesAdoptIdentity(signer, npub) { return adoptIdentity(signer, npub); }, // the claimed payment address, for anyone prefilling a lightning address namesAddress() { const st = load(); return st.name ? `${st.name}@${st.domain || DOMAIN()}` : null; }, + // Sign-in races this lookup against the seed work: by the time the + // wallet opens, the answer is usually already in hand… + namesLookupByPk(pk) { + if (!pk) return null; + return fetch(`${REGISTRAR}/pubkey/${pk}?domain=${encodeURIComponent(DOMAIN())}`) + .then((x) => x.json()).catch(() => null); + }, + // …and this seeds it into state just before the first paint, so the + // Receive pane opens with the QR instead of "setting up your address". + namesSeed(rec) { + if (!rec || !rec.name) return null; + const st = load(); + if (!st.name) save({ name: rec.name, domain: rec.domain || DOMAIN(), uri: rec.uri }); + return true; + }, // 'pending' while the restore/claim pass is still running — the wallet // screen holds spending-setup prompts until the name question is settled. namesSettled() { return checked ? 'yes' : 'pending'; }, diff --git a/src/features/nostrlogin.js b/src/features/nostrlogin.js index 6c0889b..cef1628 100644 --- a/src/features/nostrlogin.js +++ b/src/features/nostrlogin.js @@ -89,6 +89,8 @@ export function nostrLoginFeature(ctx) { // warm the identity's profile + avatar in parallel with the seed work, // so the home screen's first paint already has the picture ctx.hook('warmProfile', signer.pubkey); + // and the payment name too — the Receive pane should open with its QR + const nameHintP = ctx.hook('namesLookupByPk', signer.pubkey); const res = await walletForSigner(signer); if (res.mode === 'new') { // No wallet on this identity yet — make one and walk straight in. @@ -111,7 +113,12 @@ export function nostrLoginFeature(ctx) { // re-animated the welcome screen for a beat before the wallet appeared ctx.onbNostrLogin(res.mode === 'restored'); ui.navAnimSkip = true; // the handover swaps instantly, no fade - await ctx.openMnemonic(res.mnemonic, res.passphrase || '', { nostrPubkey: signer.pubkey, spendingHint }); + // usually resolved long ago; the race caps a slow registrar at 1.5s + const nameHint = await Promise.race([ + Promise.resolve(nameHintP).catch(() => null), + new Promise((r) => setTimeout(() => r(null), 1500)), + ]); + await ctx.openMnemonic(res.mnemonic, res.passphrase || '', { nostrPubkey: signer.pubkey, spendingHint, nameHint }); save({ ...load(), pubkey: signer.pubkey, linked: Date.now(), ...sessionOf(signer) }); attaching = false; // claim the real npub as the payment address while this signer is live |
