Compare commits

..
1 Commits
Author SHA1 Message Date
sneak a186372877 fix: Back from Settings no longer lands on a delete wallet screen left by the gear (closes #480)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
Leaving the delete wallet or lost-password screen drops its wallet
selection, but the settings gear had just pushed the screen onto the Back
stack, so Back from Settings showed a screen whose button could only
answer "No wallet selected for deletion." Each screen's leave handler now
also takes it off the top of the stack, as the private key export and
recovery phrase screens do since
#461. Back from Settings then
stays on Settings once, as it does for the recovery phrase screen.

Jest tests drive the gear and then Back on both screens, and the delete
screen's own Back.

Model: opus-5-5
2026-10-07 01:09:58 +00:00
4 changed files with 78 additions and 5 deletions
+6
View File
@@ -1838,6 +1838,9 @@ view would leave a wallet one click from deletion.
try again." on the error line, nothing deleted
- "I have lost my password" → **DeleteWalletLostPassword**
- "Back" → previous screen (Settings)
- Settings gear → **Settings**, whose "Back" never lands back on this
screen: leaving drops the wallet the screen was showing, so it also takes
the screen off the Back stack
#### DeleteWalletLostPassword (`delete-wallet-lost-password`)
@@ -1876,6 +1879,9 @@ view would leave a wallet one click from deletion.
selection comes back with it. The two delete screens are siblings rather
than parent and child: nothing is pushed on the way here, so both have
Settings as their Back target.
- Settings gear → **Settings**, whose "Back" never lands back on this
screen: leaving drops the wallet the screen was showing, so it also takes
the screen off the Back stack
- **Deliberately not password-gated.** A password in front of _discarding_ a
secret protects nobody: an attacker at the popup who wants the wallet gone can
uninstall the extension, so the only person such a gate stops is the owner who
+9
View File
@@ -45,6 +45,15 @@ but the review is broader than any of them.
# Completed Steps
- 2026-10-06: Back from Settings no longer lands on the delete wallet or
lost-password screen after either was left by the settings gear
([#480](https://git.eeqj.de/sneak/AutistMask/issues/480)), the defect
[#461](https://git.eeqj.de/sneak/AutistMask/issues/461) fixed for the two
secret screens. Leaving drops the screen's wallet selection, so its leave
handler now also takes it off the Back stack, as a reopened popup already
does. `tests/deleteWalletLostPassword.test.js` drives the gear and then Back
on both screens.
- 2026-10-06: `script/bootstrap` no longer reports success while node cannot
find a package listed in `dependencies` or `devDependencies` of `package.json`
([#263](https://git.eeqj.de/sneak/AutistMask/issues/263)). After the install
+22 -5
View File
@@ -49,9 +49,9 @@ function confirmKey(name) {
}
// Drop the password from the DOM and the wallet selection from the
// closure. Registered as the view-leave handler as well as run on entry,
// so the typed password does not sit in the hidden view after the user
// navigates away by any route, including the Settings gear.
// closure. Run by the view-leave handler as well as on entry, so the typed
// password does not sit in the hidden view after the user navigates away
// by any route, including the Settings gear.
function clear() {
deleteWalletIndex = null;
$("delete-wallet-password").value = "";
@@ -147,8 +147,25 @@ async function finishDelete(walletIdx) {
function init(_ctx) {
ctx = _ctx;
onViewLeave("delete-wallet-confirm", clear);
onViewLeave("delete-wallet-lost-password", clearLostPassword);
// Leaving drops the wallet selection, so each screen also comes off the
// Back stack, where the settings gear has just put it: Back from
// Settings must not land on a screen whose button can only answer "No
// wallet selected for deletion." A reopened popup drops them from the
// stack the same way (https://git.eeqj.de/sneak/AutistMask/issues/480).
onViewLeave("delete-wallet-confirm", () => {
clear();
const stack = state.viewStack;
if (stack[stack.length - 1] === "delete-wallet-confirm") {
stack.pop();
}
});
onViewLeave("delete-wallet-lost-password", () => {
clearLostPassword();
const stack = state.viewStack;
if (stack[stack.length - 1] === "delete-wallet-lost-password") {
stack.pop();
}
});
// No wipe here: goBack() routes through showView(), which runs the
// leave hook.
+41
View File
@@ -615,3 +615,44 @@ describe("the password route's confirm button", () => {
]);
});
});
// https://git.eeqj.de/sneak/AutistMask/issues/480: leaving either delete
// screen drops its wallet selection, so Back onto one showed a screen whose
// button could only answer "No wallet selected for deletion."
describe("Back from Settings after leaving by the settings gear", () => {
test("does not land on the delete screen", () => {
const { helpers, deleteWallet, state } = load();
deleteWallet.show(1);
// The settings gear: push the current view, then show Settings.
helpers.pushCurrentView();
helpers.showView("settings");
expect(state.viewStack).toEqual(["main", "settings"]);
helpers.goBack();
expect(state.currentView).not.toBe("delete-wallet-confirm");
});
test("does not land on the lost-password screen", async () => {
const { helpers, deleteWallet, state } = load();
await openLostPassword(deleteWallet, 1);
// The settings gear: push the current view, then show Settings.
helpers.pushCurrentView();
helpers.showView("settings");
expect(state.viewStack).toEqual(["main", "settings"]);
helpers.goBack();
expect(state.currentView).not.toBe(VIEW);
});
// The lost-password screen's own Back is "Back returns to the delete
// screen with its wallet still chosen", above.
test("the delete screen's own Back leaves the rest of the stack alone", async () => {
const { deleteWallet, state } = load();
deleteWallet.show(1);
await click("btn-delete-wallet-back");
expect(state.currentView).toBe("settings");
expect(state.viewStack).toEqual(["main"]);
});
});