From 3687363d6e86f5084fe7a0116e5fcbbf9470b4c1 Mon Sep 17 00:00:00 2001
From: Linus Rath <139418639+rathlinus@users.noreply.github.com>
Date: Tue, 3 Nov 2026 15:12:06 +0100
Subject: [PATCH] fix: stop Back doing nothing in Settings after the window
crosses the phone width several times
---
.../settings-phone-deep-link.test.tsx | 31 +++++++++++++++++++
components/settings/settings-app.tsx | 7 ++++-
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/components/settings/__tests__/settings-phone-deep-link.test.tsx b/components/settings/__tests__/settings-phone-deep-link.test.tsx
index 80f8e963f..891eabe6d 100644
--- a/components/settings/__tests__/settings-phone-deep-link.test.tsx
+++ b/components/settings/__tests__/settings-phone-deep-link.test.tsx
@@ -102,6 +102,37 @@ describe('Settings deep links on the phone', () => {
expect(screen.getByText('appearance pane')).toBeTruthy();
});
+ it('adds one history entry however often the window crosses the phone breakpoint', () => {
+ window.history.replaceState(null, '', '/settings');
+ media.desktop = true;
+ const { rerender } = render();
+ const push = vi.spyOn(window.history, 'pushState');
+ const resize = (desktop: boolean) => {
+ media.desktop = desktop;
+ rerender();
+ };
+
+ resize(false);
+ expect(push).toHaveBeenCalledTimes(1);
+ resize(true);
+ resize(false);
+ resize(true);
+ resize(false);
+ expect(push).toHaveBeenCalledTimes(1);
+ expect(screen.getByText('appearance pane')).toBeTruthy();
+
+ // Back from the page lands on the list...
+ act(() => {
+ window.history.replaceState(null, '', '/settings');
+ window.dispatchEvent(new PopStateEvent('popstate'));
+ });
+ expect(screen.getByTestId('settings-tab-organize')).toBeTruthy();
+
+ // ...and a page opened from there has a Back of its own.
+ fireEvent.click(screen.getByTestId('settings-tab-organize'));
+ expect(push).toHaveBeenCalledTimes(2);
+ });
+
it('opens a page at its top and keeps the place in the list', () => {
window.history.replaceState(null, '', '/settings');
render();
diff --git a/components/settings/settings-app.tsx b/components/settings/settings-app.tsx
index dff751d71..a3ff3f826 100644
--- a/components/settings/settings-app.tsx
+++ b/components/settings/settings-app.tsx
@@ -517,7 +517,12 @@ export function SettingsApp({ linkSegments: routeSegments }: SettingsAppProps =
window.history.replaceState(window.history.state, '', listPath);
}
}
- window.history.pushState({ __settingsSubmenu: true }, '');
+ // Once per open page: this runs again each time the window crosses the
+ // phone breakpoint, and the entry from the last crossing is still there.
+ // Back leaves that entry, so opening a page afterwards adds a new one.
+ if (!(window.history.state as { __settingsSubmenu?: boolean } | null)?.__settingsSubmenu) {
+ window.history.pushState({ __settingsSubmenu: true }, '');
+ }
const handlePop = () => {
setMobileShowContent(false);