fix: dock position uses real (post-clamp) window size, not requested canon

This commit is contained in:
Hermes Agent committed 2026-09-10 13:40:34 +02:00
1 parent 6901c5e0cd
commit 6624805449
2 files changed
+41 -11

No files matched your search

+24 -8
View File
@@ -213,21 +213,37 @@ export default function () {
})
// Эмуляция докинга: растянуть окно на зону и прижать к её краю (9 позиций).
// Двухэтапно, чтобы позиция считалась от РЕАЛЬНОГО размера, который Figma
// фактически отрисовала (она клампит resize до своего лимита при видимом UI).
// 1) DOCK_WINDOW: resize(канон) — попытка растяжения + запоминаем режим. reposition НЕ делаем.
// 2) UI через 2 кадра шлёт DOCK_REFINE с реальным размером (window.innerWidth/Height
// после клампа Figma) -> applyDock(..., false) только reposition от реального размера.
// Без этого этапа окно позиционировалось бы от запрошенного канона (906) и прижималось
// к левому/верхнему краю вместо центра (баг relX=0 на top-center).
on('DOCK_WINDOW', function (payload: { position: DockPosition; width: number; height: number }) {
const { position, width, height } = payload
const { position } = payload
// Центр — это one-shot: применяем 50% по центру ОДИН раз, НЕ включаем поллинг
// (окно не "приклеено"), но включаем centerLocked — ручной ресайз держит центр.
if (position === 'center') {
dockedPosition = null
centerLocked = true
applyDock('center', width, height, true)
return
} else {
// Остальные позиции — удерживаем прижатым (поллинг пересчитывает при зуме/пане).
centerLocked = false
dockedPosition = position
lastBoundsKey = '' // форсируем пересчёт на ближайшем тике
}
// Остальные позиции — удерживаем прижатым (поллинг пересчитывает при зуме/пане).
centerLocked = false
dockedPosition = position
lastBoundsKey = '' // форсируем пересчёт на ближайшем тике
applyDock(position, width, height, true)
// Попытка растяжения до канона (Figma клампит до лимита при видимом UI).
const state = computeDock(position, payload.width, payload.height, true)
figma.ui.resize(state.width, state.height)
lastSize = { width: clampWindowSize(state).width, height: clampWindowSize(state).height }
// reposition откладываем на DOCK_REFINE (UI пришлёт реальный размер после клампа).
})
// Точная прижимка от РЕАЛЬНОГО размера окна (после клампа Figma).
on('DOCK_REFINE', function (payload: { position: DockPosition; width: number; height: number }) {
const { position, width, height } = payload
applyDock(position, width, height, false)
})
// Останавливаем поллинг при закрытии плагина, чтобы не висел в памяти.
+17 -3
View File
@@ -243,12 +243,26 @@ function Plugin () {
| 'bottom-left' | 'bottom-center' | 'bottom-right'
function dockWindow (position: DockPosition) {
// Этап 1: просим main растянуть (попытка до канона) и запомнить режим.
// main НЕ позиционирует сразу — позиция считается на этапе 2 от РЕАЛЬНОГО
// размера, который Figma отрисует после клампа (видимый UI режет запрос).
emit('DOCK_WINDOW', {
position,
width: currentWindowSize.width,
height: currentWindowSize.height
width: window.innerWidth,
height: window.innerHeight
})
// Этап 2: через 2 кадра Figma уже применила resize и кламп — читаем реальный
// размер из iframe и шлём на точную прижимку (reposition от реального размера).
requestAnimationFrame(function () {
requestAnimationFrame(function () {
emit('DOCK_REFINE', {
position,
width: window.innerWidth,
height: window.innerHeight
})
refreshInfo()
})
})
refreshInfo()
}
const max = windowInfo != null ? windowInfo.maxViewport : null