aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.js41
-rw-r--r--src/i18n.js1
2 files changed, 39 insertions, 3 deletions
diff --git a/src/app.js b/src/app.js
index 3144e9b..99cf565 100644
--- a/src/app.js
+++ b/src/app.js
@@ -2199,6 +2199,7 @@ function loadWatchAccounts() {
// a sign-up's Spending-only shape and its ways back in outlive the session
...(d.spendingOnly ? { kind: 'spending', savingsLater: true } : {}),
...(d.signupAt ? { signupAt: d.signupAt } : {}),
+ ...(d.waysBackPrompted ? { waysBackPrompted: d.waysBackPrompted } : {}),
...(Array.isArray(d.recovery) && d.recovery.length ? { recovery: d.recovery } : {}) }));
} catch { return []; }
}
@@ -2219,6 +2220,7 @@ function saveDirectory() {
return { id: a.id, label: a.label, xpub: a.xpub, autoLock: a.autoLock || 0, network: a.network, nostrPk: a.nostrPk, seedSeen: !!a.seedSeen,
...(a.kind === 'spending' && a.savingsLater ? { spendingOnly: true } : {}),
...(a.signupAt ? { signupAt: a.signupAt } : {}),
+ ...(a.waysBackPrompted ? { waysBackPrompted: a.waysBackPrompted } : {}),
...(a.recovery && a.recovery.length ? { recovery: a.recovery } : {}) };
});
localStorage.setItem(WATCH_KEY, JSON.stringify(dir));
@@ -5061,10 +5063,43 @@ function addRecoveryMethod(m) {
}
wallet.registerCacheExtension({
mergeAlways: true,
- save: () => { const r = recoveryMethods(); return r.length ? { recovery: r } : {}; },
- load: (d) => { if (d && d.recovery) mergeRecovery(d.recovery); },
+ save: () => {
+ const a = activeAccount(), r = recoveryMethods();
+ return { ...(r.length ? { recovery: r } : {}), ...(a && a.waysBackPrompted ? { waysBackPrompted: a.waysBackPrompted } : {}) };
+ },
+ load: (d) => {
+ if (!d) return;
+ if (d.recovery) mergeRecovery(d.recovery);
+ // asked on another device: asked (only ever turns on)
+ const a = activeAccount();
+ if (d.waysBackPrompted && a && !a.waysBackPrompted) { a.waysBackPrompted = d.waysBackPrompted; persistAccounts(); }
+ },
});
+// A sign-up is asked for a way back in ONCE, and only when there's something
+// to lose (Adam, 2026-11-15: "only prompt to add a way back in after there's
+// some balance and only if we haven't prompted before"). The ask is recorded
+// the moment it first shows — on the account, the directory and the synced
+// snapshot — and stays up for that visit until Add one or Not now.
+function waysBackPrompt(a) {
+ if (recoveryMethods(a).length) { if (ui.waysBackPromptFor === a.id) ui.waysBackPromptFor = null; return null; }
+ if (ui.waysBackPromptFor !== a.id) {
+ if (a.waysBackPrompted || !wallet.loaded) return null;
+ const bal = (featureHook('spendingSat') || 0) + (wallet.spendable || 0) + (wallet.pendingIncoming || 0);
+ if (bal <= 0) return null;
+ a.waysBackPrompted = Date.now();
+ persistAccounts();
+ try { wallet.saveCache(); } catch {}
+ ui.waysBackPromptFor = a.id;
+ }
+ const done = () => { ui.waysBackPromptFor = null; };
+ return h('div', { class: 'notice info col ways-back-prompt', style: 'margin:12px 0 0;gap:10px' },
+ h('span', {}, t('waysBackPrompt')),
+ h('div', { class: 'row gap6' },
+ h('button', { class: 'btn-sm btn-primary', onClick: () => { done(); ui.tab = 'settings'; ui.settingsPage = 'wallet'; render(); } }, t('waysBackReminderGo')),
+ h('button', { class: 'btn-sm btn-ghost', onClick: () => { done(); render(); } }, t('onbNotNow'))));
+}
+
// A wallet whose recovery phrase has never been on screen keeps one quiet
// line about it. "Later" is a real answer, so this is a row and not a modal —
// but it doesn't dismiss, because the risk doesn't go away on its own. It
@@ -5076,7 +5111,7 @@ function backupNotice() {
// A sign-up never saw a phrase and wasn't asked to: what it needs is A way
// back in, any one — and once it has one, nothing to nag about.
const signup = !!a.signupAt;
- if (signup && recoveryMethods(a).length) return null;
+ if (signup) return waysBackPrompt(a);
return h('div', { class: 'small muted', style: 'margin:10px 0 0;text-align:center' },
t(signup ? 'waysBackReminder' : 'backupReminder'),
' ',
diff --git a/src/i18n.js b/src/i18n.js
index 97bb066..bb82ed2 100644
--- a/src/i18n.js
+++ b/src/i18n.js
@@ -1502,6 +1502,7 @@ const STR = {
onbNameTitle: 'Claim your name',
onbNameBody: "It's your username and your payment address: people pay you, follow you and message you with just your name.",
waysBackReminder: 'Add a way back into your account, in case you lose this device.',
+ waysBackPrompt: 'You have bitcoin in here now. Add a way back into your account, in case you lose this device.',
waysBackReminderGo: 'Add one',
addSavings: 'Add a savings account',
addSavingsDesc: 'On-chain bitcoin, for keeping. Same account, a second balance.',