返回 DeepSeek-Reasonix
dpiScale.ts
根目录 / desktop / frontend / src / lib / dpiScale.ts
1 /**
2 * DPI zoom scale service.
3 *
4 * Uses the WebView2 ZoomFactor (Go side) for reliable, layout-safe zooming.
5 * The frontend only saves the user's preference and lets the Go binding persist
6 * it to desktop-zoom.json; on next startup main.go reads the file and applies
7 * ZoomFactor to the WebView2 window options.
8 *
9 * Range: 0.50 – 2.00 (50% – 200%), step 0.05.
10 */
11
12 export const MIN_ZOOM = 0.5;
13 export const MAX_ZOOM = 2.0;
14 export const ZOOM_STEP = 0.05;
15
16 export type ZoomLevel = number; // 0.5 – 2.0
17
18 export const DEFAULT_ZOOM: ZoomLevel = 1.0;
19
20 const ZOOM_KEY = "reasonix-zoom-restart";
21
22 // ─── helpers ────────────────────────────────────────────────────────
23
24 /** Snap a number to the nearest valid step within [MIN, MAX]. */
25 export function snapZoom(value: number): ZoomLevel {
26 const clamped = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, value));
27 const steps = Math.round((clamped - MIN_ZOOM) / ZOOM_STEP);
28 return parseFloat((MIN_ZOOM + steps * ZOOM_STEP).toFixed(2));
29 }
30
31 /** Convert a zoom value (0.5-2.0) to a percentage integer (50-200). */
32 export function zoomToPercent(zoom: ZoomLevel): number {
33 return Math.round(zoom * 100);
34 }
35
36 /** Convert a percentage integer (50-200) back to a zoom value (0.5-2.0). */
37 export function percentToZoom(pct: number): ZoomLevel {
38 return snapZoom(pct / 100);
39 }
40
41 function readZoom(fallback: ZoomLevel): ZoomLevel {
42 const stored = typeof localStorage !== "undefined" ? localStorage.getItem(ZOOM_KEY) : null;
43 if (stored === null) return fallback;
44 const parsed = parseFloat(stored);
45 if (isNaN(parsed)) return fallback;
46 return snapZoom(parsed);
47 }
48
49 function writeZoom(value: ZoomLevel): void {
50 try {
51 localStorage.setItem(ZOOM_KEY, String(value));
52 } catch {
53 /* private mode / no storage */
54 }
55 }
56
57 // ─── public API ─────────────────────────────────────────────────────
58
59 /** Read the saved zoom level that will be applied on next restart. */
60 export function getRestartZoom(): ZoomLevel {
61 return readZoom(DEFAULT_ZOOM);
62 }
63
64 /**
65 * Save a zoom factor that will be picked up by Go on next startup and
66 * applied as the WebView2 `ZoomFactor`. Takes effect after the app is
67 * restarted (no layout issues — ZoomFactor is engine-level).
68 */
69 export function saveRestartZoom(userZoom: ZoomLevel): void {
70 writeZoom(snapZoom(userZoom));
71 }
72
73 /**
74 * Init: no-op for zoom (the Go-side ZoomFactor is applied at WebView2
75 * creation time).
76 */
77 export function initDpiScale(): void {
78 /* zoom is handled entirely by the Go side (ZoomFactor) */
79 }
80
80 lines TYPESCRIPT