fix: filter the restored view stack against RESTORABLE_VIEWS (closes #224)
Some checks failed
check / check (push) Has been cancelled
Some checks failed
check / check (push) Has been cancelled
The persisted view stack was restored verbatim. RESTORABLE_VIEWS stopped the popup opening ONTO a view it will not re-render, but nothing kept such a view out of the stack, so Back could land on a screen whose content was deliberately never restored. No secret leaks -- those views are blank precisely because nothing is restored into them; this is a navigation defect. loadState() now truncates the stored stack at the first entry outside RESTORABLE_VIEWS, dropping it and everything above it. Truncating rather than splicing keeps the result a prefix of what was stored, so every surviving entry keeps the Back target it had; splicing would silently re-point the entry above the hole at a different screen. Filtering on load rather than on save is what makes it retroactive for stacks already in storage, and leaves the live in-session stack whole, which it should be. The general case where Back lands on a blank screen even for restorable views, because goBack() re-renders nothing, is separate and tracked at #268.
This commit was merged in pull request #266.
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
const { DEFAULT_RPC_URL, DEFAULT_BLOCKSCOUT_URL } = require("./constants");
|
||||
const { networkById } = require("./networks");
|
||||
// Dependency-free constant module; safe to pull into a background bundle.
|
||||
const { RESTORABLE_VIEWS } = require("../popup/restorableViews");
|
||||
|
||||
const storageApi =
|
||||
typeof browser !== "undefined"
|
||||
@@ -43,6 +45,39 @@ const state = {
|
||||
viewStack: [],
|
||||
};
|
||||
|
||||
// Keep only the leading run of stored views the popup is willing to render.
|
||||
//
|
||||
// restoreView() refuses to reopen ONTO a non-restorable view, but the stack
|
||||
// behind it used to be restored verbatim, so Back could walk onto a screen
|
||||
// whose content is deliberately never re-rendered — and "show-phrase" has no
|
||||
// Back control to leave by. Truncating at the first such entry instead of
|
||||
// splicing it out keeps the result a prefix of the stored stack, so every
|
||||
// surviving entry's Back target is exactly the one it had; splicing would
|
||||
// silently re-point the entry above the hole at a different screen.
|
||||
//
|
||||
// Filtering happens here on load rather than in saveState(): the live
|
||||
// in-session stack is legitimate (the screen really is rendered while the
|
||||
// popup is open), and only a load-side filter also repairs the stacks
|
||||
// already in storage, including ones written before a view left the set.
|
||||
function restorableStack(stored, currentView) {
|
||||
// A stored stack that is missing or not an array keeps nothing, but it
|
||||
// still goes through the never-empty rule below rather than returning
|
||||
// early: otherwise a corrupt stack would depend on exactly the goBack()
|
||||
// fallback that the explicit ["main"] exists in order not to depend on.
|
||||
const source = Array.isArray(stored) ? stored : [];
|
||||
const cut = source.findIndex((view) => !RESTORABLE_VIEWS.has(view));
|
||||
const kept = cut === -1 ? source.slice() : source.slice(0, cut);
|
||||
// A view restored below the root still needs somewhere for Back to go.
|
||||
if (
|
||||
kept.length === 0 &&
|
||||
currentView !== "main" &&
|
||||
RESTORABLE_VIEWS.has(currentView)
|
||||
) {
|
||||
return ["main"];
|
||||
}
|
||||
return kept;
|
||||
}
|
||||
|
||||
// Return the network configuration for the currently selected network.
|
||||
function currentNetwork() {
|
||||
return networkById(state.networkId);
|
||||
@@ -150,7 +185,7 @@ async function loadState() {
|
||||
saved.selectedAddress !== undefined ? saved.selectedAddress : null;
|
||||
state.selectedToken = saved.selectedToken || null;
|
||||
state.viewData = saved.viewData || {};
|
||||
state.viewStack = Array.isArray(saved.viewStack) ? saved.viewStack : [];
|
||||
state.viewStack = restorableStack(saved.viewStack, state.currentView);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user