aboutsummaryrefslogtreecommitdiffstats
path: root/src/app.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-10 22:08:26 -0700
committerAdam Soltys <[email protected]>2026-09-10 22:08:26 -0700
commitf0a5e0de3e68eee184b25ced2393329aec169f6d (patch)
treeb0d0450d93715a728f56f8fea3f6e533fc61f5d0 /src/app.js
parentdb5218ec83c1d84da5a2062e514b65132bcfe240 (diff)
downloadcoinosv3-f0a5e0de3e68eee184b25ced2393329aec169f6d.tar.gz
coinosv3-f0a5e0de3e68eee184b25ced2393329aec169f6d.zip
The padlock answers where you tap it, including on your profile page.
Feature screens (a profile, a chat thread, a search) are drawn ahead of the wallet screen — and the padlock's "Protect this device?" card was drawn BY the wallet screen. So tapping the padlock from a profile did nothing you could see: the card was waiting behind the page, and only appeared once you navigated back to the wallet. The ask now outranks feature screens (with onboarding still ahead of it), and declining leaves you exactly where you tapped, because nothing else moves. A lock that goes through does move: it drops the profile/chat/search the padlock was tapped from, so you land on the wallet wearing a closed padlock instead of reading a profile page with only a toast to say what happened. Logging out drops it too — a page belonging to the locked session had no business outliving it, or greeting whoever unlocks next. tools/padlock-ask-test.js covers the tap and the decline. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
Diffstat (limited to 'src/app.js')
-rw-r--r--src/app.js32
1 files changed, 25 insertions, 7 deletions
diff --git a/src/app.js b/src/app.js
index 697b664..b6dd0dc 100644
--- a/src/app.js
+++ b/src/app.js
@@ -508,8 +508,17 @@ function renderInner() {
for (const el of root.querySelectorAll('[data-keep-scroll]'))
if (el.scrollLeft || el.scrollTop)
scrolls[el.getAttribute('data-keep-scroll')] = { l: el.scrollLeft, t: el.scrollTop };
+ // The padlock's "protect this device?" ask is modal: it belongs over
+ // whatever page the tap happened on. A feature screen (your profile, a chat
+ // thread) used to swallow it — walletScreen paints the card, and
+ // screenView outranks walletScreen, so the padlock did nothing visible
+ // until you navigated back to the wallet and the card finally appeared
+ // there. Declining still lands back exactly where the tap happened,
+ // because nothing else moves. Onboarding keeps its precedence.
+ const lockAsk = ui.pw && ui.pw.purpose === 'lock' && !(ui.onb || onbInProgress());
const screen =
- featureHook('screenView')
+ (lockAsk && h('div', { class: 'col', style: 'gap:16px' }, brandHeader(false), pwPromptCard()))
+ || featureHook('screenView')
|| (ui.screen === 'wallet'
? walletScreen()
: ui.screen === 'accounts'
@@ -1374,13 +1383,22 @@ function identities() {
return out;
}
+// Page-level navigation owned by the features (a profile, a chat thread, a
+// search, the zap setup) — dropped whenever the session underneath it
+// changes, so the next paint is the app's own screen and not the page the
+// previous identity (or the unlocked wallet) was reading.
+function clearFeatureNav() {
+ ui.profilePk = null; ui.profEdit = null; ui.profEditFilled = false;
+ ui.chatOpen = false; ui.userSearch = null; ui.noteThread = null; ui.zapSetup = null;
+}
+
// Switch to another identity already signed in on this device: the wallet
// it opens lands on its own history, out of any profile or chat the previous
// identity had open.
function switchIdentity(id) {
const acc = accounts.find((a) => a.id === id);
if (!acc) return;
- ui.profilePk = null; ui.profEdit = null; ui.profEditFilled = false; ui.chatOpen = false;
+ clearFeatureNav();
switchToView(acc.id, viewsOf(acc)[0]);
}
// The working set of wallets you can switch between. Full (seed-bearing)
@@ -1979,6 +1997,7 @@ function lock({ offerPassword = false } = {}) {
ui.watchXpub = '';
ui.watchLabel = '';
ui.pw = null;
+ clearFeatureNav(); // a profile/chat from the locked session must not outlive it
ui.vaultPw = '';
ui.vaultError = '';
ui.confirmClear = false;
@@ -2088,6 +2107,10 @@ function softLock() {
}
}
const keepId = activeId;
+ // The lock is going through: leave whatever page the padlock was tapped
+ // from, so what you land on is the wallet wearing a closed padlock — from
+ // a profile page the toast was the only sign anything had happened.
+ clearFeatureNav();
_featuresInited = false;
for (const f of FEATURES) { try { f.stop && f.stop(); } catch {} }
vaultPassword = null;
@@ -3224,11 +3247,6 @@ function walletScreen() {
const s = onboardScreen();
if (s) return s; // null = the wizard just handed over; fall through
}
- // The padlock's set-a-password ask renders here, over the open wallet —
- // declining it must land back exactly where the tap happened.
- if (ui.pw && ui.pw.purpose === 'lock') {
- return h('div', { class: 'col', style: 'gap:16px' }, brandHeader(false), pwPromptCard());
- }
// A feature can hold the wallet behind a required onboarding step (picking
// a username). Imported wallets skip it once their name is recovered.
const ob = featureHook('onboardingView');