fix view mode toggle

This commit is contained in:
Eduard Gert
2026-05-28 16:36:15 +02:00
parent 51b243bdfa
commit 4556d52a60

View File

@@ -1,4 +1,12 @@
import { createContext, useCallback, useContext, useEffect, useState, type ReactNode } from "react";
import {
createContext,
useCallback,
useContext,
useEffect,
useRef,
useState,
type ReactNode,
} from "react";
import { Window } from "@wailsio/runtime";
import { Preferences } from "@bindings/services";
import { ViewMode as ViewModePref } from "@bindings/preferences/models.js";
@@ -26,6 +34,10 @@ const ViewModeContext = createContext<ViewModeContextValue | null>(null);
export const ViewModeProvider = ({ children }: { children: ReactNode }) => {
const [viewMode, setMode] = useState<ViewMode>("default");
// Mirror of viewMode for dedup inside the async setViewMode without
// adding the state to the callback's dep array (which would re-create
// the callback on every change).
const modeRef = useRef<ViewMode>("default");
// Hydrate from the persisted preference. The Go side has already sized
// the main window to match (see main.go), so this only catches the
@@ -37,6 +49,7 @@ export const ViewModeProvider = ({ children }: { children: ReactNode }) => {
if (cancelled) return;
const saved = prefs?.viewMode as ViewMode | undefined;
if (saved === "default" || saved === "advanced") {
modeRef.current = saved;
setMode(saved);
}
})
@@ -46,25 +59,26 @@ export const ViewModeProvider = ({ children }: { children: ReactNode }) => {
};
}, []);
const setViewMode = useCallback(
(mode: ViewMode) => {
setMode((prev) => {
if (prev === mode) return prev;
void (async () => {
// Reuse the live frame height instead of asserting a
// constant — keeps content area stable across switches
// (see VIEW_WIDTH comment above).
const size = await Window.Size().catch(() => null);
const width = VIEW_WIDTH[mode];
const height = size?.height ?? 640;
await Window.SetSize(width, height).catch(() => {});
})();
void Preferences.SetViewMode(mode as unknown as ViewModePref).catch(() => {});
return mode;
});
},
[],
);
// Resize the window BEFORE flipping React state — otherwise the new
// layout (e.g., advanced-mode right panel mounting) paints into a
// window that hasn't grown yet, causing a brief flex-overflow that
// wobbles the connect toggle's position. Cost: one IPC roundtrip
// (~30ms) before the dropdown checkmark updates.
const setViewMode = useCallback((mode: ViewMode) => {
if (modeRef.current === mode) return;
modeRef.current = mode;
void (async () => {
// Reuse the live frame height instead of asserting a
// constant — keeps content area stable across switches
// (see VIEW_WIDTH comment above).
const size = await Window.Size().catch(() => null);
const width = VIEW_WIDTH[mode];
const height = size?.height ?? 640;
await Window.SetSize(width, height).catch(() => {});
setMode(mode);
void Preferences.SetViewMode(mode as unknown as ViewModePref).catch(() => {});
})();
}, []);
return (
<ViewModeContext.Provider value={{ viewMode, setViewMode }}>
{children}