fix: Back from Settings no longer lands on a delete wallet screen left by the gear #484

Merged
clawbot merged 1 commits from issue-480-delete-screen-back into next 2026-10-07 03:43:08 +02:00
4 changed files with 78 additions and 5 deletions
Showing only changes of commit a186372877 - Show all commits
+6
View File
@@ -1838,6 +1838,9 @@ view would leave a wallet one click from deletion.
try again." on the error line, nothing deleted try again." on the error line, nothing deleted
- "I have lost my password" → **DeleteWalletLostPassword** - "I have lost my password" → **DeleteWalletLostPassword**
- "Back" → previous screen (Settings) - "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`) #### 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 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 than parent and child: nothing is pushed on the way here, so both have
Settings as their Back target. 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 - **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 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 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 # 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 - 2026-10-06: `script/bootstrap` no longer reports success while node cannot
find a package listed in `dependencies` or `devDependencies` of `package.json` find a package listed in `dependencies` or `devDependencies` of `package.json`
([#263](https://git.eeqj.de/sneak/AutistMask/issues/263)). After the install ([#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 // 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, // closure. Run by the view-leave handler as well as on entry, so the typed
// so the typed password does not sit in the hidden view after the user // password does not sit in the hidden view after the user navigates away
// navigates away by any route, including the Settings gear. // by any route, including the Settings gear.
function clear() { function clear() {
deleteWalletIndex = null; deleteWalletIndex = null;
$("delete-wallet-password").value = ""; $("delete-wallet-password").value = "";
@@ -147,8 +147,25 @@ async function finishDelete(walletIdx) {
function init(_ctx) { function init(_ctx) {
ctx = _ctx; ctx = _ctx;
onViewLeave("delete-wallet-confirm", clear); // Leaving drops the wallet selection, so each screen also comes off the
onViewLeave("delete-wallet-lost-password", clearLostPassword); // 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 // No wipe here: goBack() routes through showView(), which runs the
// leave hook. // 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"]);
});
});