fix: render the view "Back" lands on after the popup is reopened (closes #268)
All checks were successful
check / check (push) Successful in 55s
All checks were successful
check / check (push) Successful in 55s
goBack() only unhid its target. A reopened popup renders the wallet list and the one view restoreView() lands on, so every other view is still the blank static template from index.html: pressing Back from Settings onto an address showed an empty address line and no balances, and the same held for address-token, receive, confirm-tx and transaction. The per-view dispatch and its data guards move out of restoreView() into src/popup/viewRouter.js, and goBack() now routes a popped view through the same code by way of a renderer index.js registers with setBackRenderer(). A view whose backing state is gone falls back to Home the way the restore does, rather than showing an empty template. The Back path renders only a view this page load has not rendered yet. viewRouter.js keeps a page-load-scoped set of rendered views, written by showView() — the last thing every render path runs, forward navigation and the restore alike, so a view added later registers itself rather than needing to be remembered. Back onto a view already in that set unhides it and nothing more, exactly as it does for a view outside RESTORABLE_VIEWS: rendering a second time would re-fetch and overwrite what the view holds, such as an edit typed into Settings and not yet saved. Home stays the exception and is re-rendered on every Back, as it was when goBack() called the renderWalletList() registered through setRenderMain(), so the wallet list reflects what changed while the user was away from it. tests/backNavigation.test.js drives the real goBack() over the reproduction and over each of address-token, receive, confirm-tx, transaction, success-tx and error-tx, with and without their backing state, and pins that a view this page load already rendered — a live-session view, or Settings revisited — is only unhidden, while Home still re-renders. tests/e2e/run.js adds three cases against the real popup in a real browser, because make check cannot see a blank view: a real close and reopen then Back onto the address screen and onto Receive, and an in-session Back onto Settings that must keep unsaved input. All three were demonstrated failing first.
This commit is contained in:
@@ -7,6 +7,7 @@ const {
|
||||
getAddressValueUsd,
|
||||
} = require("../../shared/prices");
|
||||
const { state, saveState, currentNetwork } = require("../../shared/state");
|
||||
const { markViewRendered } = require("../viewRouter");
|
||||
|
||||
// When views are added, removed, or transitions between them change,
|
||||
// update the view-navigation documentation in README.md to match.
|
||||
@@ -76,6 +77,10 @@ function showView(name) {
|
||||
}
|
||||
clearFlash();
|
||||
state.currentView = name;
|
||||
// A view's show() ends here, so this is where the Back path learns the
|
||||
// view is no longer the blank template from index.html and must not be
|
||||
// rendered a second time. See viewRouter.js.
|
||||
markViewRendered(name);
|
||||
saveState();
|
||||
updateDebugBanner(name);
|
||||
}
|
||||
@@ -111,12 +116,19 @@ function updateDebugBanner(viewName) {
|
||||
}
|
||||
}
|
||||
|
||||
// Callback to re-render the main/home view when navigating back to it.
|
||||
// Set once by index.js via setRenderMain().
|
||||
let _renderMain = null;
|
||||
// Callback that renders a view being navigated BACK onto. Set once by
|
||||
// index.js via setBackRenderer(), which routes the view through the same
|
||||
// per-view render and data guards restoreView() uses.
|
||||
//
|
||||
// It answers true when it took the navigation — the view is rendered and
|
||||
// shown, or its backing data was gone and it fell back — and false for a
|
||||
// view the popup does not render from persisted state. Those can only be
|
||||
// on the stack from this page load, because the stack is filtered on load,
|
||||
// so they have already been rendered and only need unhiding.
|
||||
let _renderBack = null;
|
||||
|
||||
function setRenderMain(fn) {
|
||||
_renderMain = fn;
|
||||
function setBackRenderer(fn) {
|
||||
_renderBack = fn;
|
||||
}
|
||||
|
||||
// Push the current view onto the navigation stack so goBack() can
|
||||
@@ -136,9 +148,11 @@ function goBack() {
|
||||
} else {
|
||||
target = "main";
|
||||
}
|
||||
if (target === "main" && _renderMain) {
|
||||
_renderMain();
|
||||
}
|
||||
// A popped view is landed on, not navigated to. If the popup has been
|
||||
// closed and reopened since the view was pushed, nothing has ever
|
||||
// rendered it in this page load and its template is still blank, so it
|
||||
// has to be rendered here rather than merely unhidden.
|
||||
if (_renderBack && _renderBack(target)) return;
|
||||
showView(target);
|
||||
}
|
||||
|
||||
@@ -470,7 +484,7 @@ module.exports = {
|
||||
showView,
|
||||
onViewLeave,
|
||||
updateDebugBanner,
|
||||
setRenderMain,
|
||||
setBackRenderer,
|
||||
pushCurrentView,
|
||||
goBack,
|
||||
clearViewStack,
|
||||
|
||||
Reference in New Issue
Block a user