diff --git a/components/settings/__tests__/settings-phone-deep-link.test.tsx b/components/settings/__tests__/settings-phone-deep-link.test.tsx index 2b0378e09..80f8e963f 100644 --- a/components/settings/__tests__/settings-phone-deep-link.test.tsx +++ b/components/settings/__tests__/settings-phone-deep-link.test.tsx @@ -7,6 +7,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; // settings", the OAuth redirect) must open that page, with the list one Back // below it. +const media = vi.hoisted(() => ({ desktop: false })); + vi.mock('next-intl', () => ({ useTranslations: (ns?: string) => (key: string) => (ns ? `${ns}.${key}` : key), useMessages: () => ({}), @@ -15,7 +17,7 @@ vi.mock('next-intl', () => ({ })); vi.mock('@/hooks/use-media-query', async (importOriginal) => ({ atLeast: (await importOriginal()).atLeast, - useIsDesktop: () => false, + useIsDesktop: () => media.desktop, useIsMobile: () => true, useMediaQuery: () => false, useDeviceDetection: () => ({ isMobile: true, isTablet: false, isDesktop: false }), @@ -44,6 +46,7 @@ beforeEach(() => { useThemeStore.setState({ syncServerThemes: vi.fn().mockResolvedValue(undefined) } as never); }); afterEach(() => { + media.desktop = false; vi.unstubAllGlobals(); vi.restoreAllMocks(); }); @@ -87,6 +90,18 @@ describe('Settings deep links on the phone', () => { expect(screen.queryByText('appearance pane')).toBeNull(); }); + it('keeps the open page when a desktop window narrows to the phone layout', () => { + window.history.replaceState(null, '', '/settings'); + media.desktop = true; + const { rerender } = render(); + expect(screen.getByText('appearance pane')).toBeTruthy(); + + media.desktop = false; + rerender(); + + expect(screen.getByText('appearance pane')).toBeTruthy(); + }); + 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 5ff290c4f..537497f63 100644 --- a/components/settings/settings-app.tsx +++ b/components/settings/settings-app.tsx @@ -310,6 +310,13 @@ export function SettingsApp({ linkSegments: routeSegments }: SettingsAppProps = const [searchQuery, setSearchQuery] = useState(''); const [pendingHighlight, setPendingHighlight] = useState<{ tab: SettingsTabId; label: string; pluginId?: string; advanced?: boolean } | null>(null); const isDesktop = useIsDesktop(); + // Narrowing the window (or turning a tablet) keeps the page that was open + // instead of dropping back to the page list. + const wasDesktop = useRef(isDesktop); + useEffect(() => { + if (wasDesktop.current && !isDesktop) setMobileShowContent(true); + wasDesktop.current = isDesktop; + }, [isDesktop]); const messages = useMessages() as Record; const installedPlugins = usePluginStore((s) => s.plugins);