From f885be72665196b4b66752f6af84dc2a64de200f Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 11 Sep 2026 14:10:58 +0200 Subject: [PATCH] feat: persist maximize state so Restore button shows after reopen --- src/main.ts | 15 ++++++++++----- src/ui.tsx | 14 +++++++++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/main.ts b/src/main.ts index ea9352d..c18e529 100644 --- a/src/main.ts +++ b/src/main.ts @@ -42,7 +42,7 @@ export default function () { const PLACEMENT_KEY = 'figma-ai-plugin:placement' type Placement = | { mode: 'dock'; position: DockPosition } - | { mode: 'free'; x: number; y: number; w: number; h: number } + | { mode: 'free'; x: number; y: number; w: number; h: number; maximized?: boolean } let saveTimer: ReturnType | null = null function savePlacement (p: Placement) { try { @@ -56,7 +56,7 @@ export default function () { // Persist the CURRENT window as a free placement (real canvas-space x/y + size). // Used by maximize and corner docks, which must remember the EXACT size/position // rather than re-deriving it from a dock formula (which would reset the size). - function saveFreeFromCurrent () { + function saveFreeFromCurrent (maximized?: boolean) { try { const pos = (figma.ui as any).getPosition() savePlacement({ @@ -64,7 +64,8 @@ export default function () { x: Math.round(pos.canvasSpace.x), y: Math.round(pos.canvasSpace.y), w: lastSize.width, - h: lastSize.height + h: lastSize.height, + maximized: maximized === true }) } catch (e) { /* getPosition unavailable — skip */ } } @@ -379,10 +380,10 @@ export default function () { // UI asks to persist the CURRENT window as a free placement (used by Maximize, // which is not a held dock — it must remember the exact size+position across restart). - on('SAVE_FREE', function () { + on('SAVE_FREE', function (payload?: { maximized?: boolean }) { dockedPosition = null // maximize is not held; clear any stale dock state lastBoundsKey = '' - saveFreeFromCurrent() + saveFreeFromCurrent(payload != null ? payload.maximized === true : false) }) // Останавливаем поллинг при закрытии плагина, чтобы не висел в памяти. @@ -514,6 +515,10 @@ export default function () { figma.ui.resize(saved.w, saved.h) figma.ui.reposition(saved.x, saved.y) lastSize = { width: saved.w, height: saved.h } + // If it was maximized, tell UI to show the Restore button on next open. + if (saved.maximized === true) { + emit('SET_MAXIMIZED', { maximized: true }) + } } }) } catch (e) { /* storage unavailable → default center below */ } diff --git a/src/ui.tsx b/src/ui.tsx index 4e2e083..e7ace71 100644 --- a/src/ui.tsx +++ b/src/ui.tsx @@ -167,6 +167,17 @@ function Plugin () { return function () { off() } }, []) + // Main tells UI the restored placement was maximized → show the Restore button. + useEffect(function () { + const off = on('SET_MAXIMIZED', function (payload: { maximized: boolean }) { + if (payload.maximized) { + maximizedRef.current = true + setIsMaxToggled(true) + } + }) + return function () { off() } + }, []) + // Request fresh window data from main (after any action / on start). // Pass the REAL iframe size (window.innerWidth/innerHeight) — what Figma actually // rendered, not the requested lastSize. Otherwise gaps would be tautological. @@ -217,7 +228,8 @@ function Plugin () { }) // Maximize is NOT a held dock — persist the exact size+position so re-open // restores it (overrides the edge-dock save done by DOCK_REFINE above). - emit('SAVE_FREE') + // 'maximized: true' so the Restore button shows on next open. + emit('SAVE_FREE', { maximized: true }) refreshInfo() }) })