diff --git a/src/main.ts b/src/main.ts index 66ff526..e044e19 100644 --- a/src/main.ts +++ b/src/main.ts @@ -165,27 +165,31 @@ export default function () { let lastNativePosKey = '' // canvas-space key of last native-drag position (to detect titlebar drags) const dockInterval = setInterval(function () { if (dockedPosition !== null) { - // Keep the docked window pinned to its edge. Re-pin whenever it has drifted - // from the computed target — this catches zoom/pan (figma.viewport.bounds - // change) AND a Figma UI panel resize (Figma shifts the plugin window to - // stay visible, but viewport.bounds may not change, so a bounds-key check - // alone misses it). A docked window is meant to stay put, so snapping a - // stray drift back to the edge is the desired behaviour. - const target = computeDockPos(dockedPosition, lastSize.width, lastSize.height) + // Keep the docked window pinned to its edge, adapting BOTH position and size + // to the current visible canvas. Recompute from figma.viewport.bounds every + // tick so a Figma UI panel resize (which may not change viewport.bounds, but + // does shift the window) is caught — re-pin position on drift and re-apply the + // bounds-derived size when the viewport shrinks/grows (e.g. top/bottom dock + // width = full viewport width, side dock height = full viewport height). + const state = computeDock(dockedPosition, lastSize.width, lastSize.height, false) + const b = figma.viewport.bounds + const zoom = figma.viewport.zoom || 1 + const maxW = Math.round(b.width * zoom) + const maxH = Math.round(b.height * zoom) - PLUGIN_HEADER_PX + // Never overflow the visible canvas (e.g. a very wide side panel). + state.width = Math.min(state.width, Math.max(1, maxW)) + state.height = Math.min(state.height, Math.max(1, maxH)) + if (state.width !== lastSize.width || state.height !== lastSize.height) { + figma.ui.resize(Math.max(1, state.width), Math.max(1, state.height)) + lastSize = { width: state.width, height: state.height } + } + let drift = Infinity try { const pos = (figma.ui as any).getPosition() - const drift = Math.abs(Math.round(pos.canvasSpace.x) - Math.round(target.x)) + - Math.abs(Math.round(pos.canvasSpace.y) - Math.round(target.y)) - if (drift > 2) figma.ui.reposition(target.x, target.y) - } catch (e) { - // getPosition unavailable — fall back to the bounds-key trigger. - const b = figma.viewport.bounds - const key = `${b.x}|${b.y}|${b.width}|${b.height}` - if (key !== lastBoundsKey) { - lastBoundsKey = key - applyDock(dockedPosition, lastSize.width, lastSize.height, false) - } - } + drift = Math.abs(Math.round(pos.canvasSpace.x) - Math.round(state.x)) + + Math.abs(Math.round(pos.canvasSpace.y) - Math.round(state.y)) + } catch (e) { /* getPosition unavailable — force re-pin below */ } + if (drift > 2) figma.ui.reposition(state.x, state.y) return } // Not docked: track native drag (moving the window by its Figma titlebar is invisible