Skip to content

Commit 4b2703b

Browse files
committed
fix(pdf-server): refit to inline width after pinch-out exits fullscreen
handleHostContextChanged calls refitScale() before the iframe has actually shrunk, and the ResizeObserver's inline branch only refits on width *growth* (to avoid a requestFitToContent shrink-loop). So the fullscreen->inline shrink never triggered a refit and the page stayed at the fullscreen scale. Add a one-shot forceNextResizeRefit flag, set on fullscreen->inline (both the pinch-out path and handleHostContextChanged), consumed by the ResizeObserver on the next size change. One-shot keeps the shrink-loop guard intact for ordinary inline resizes.
1 parent 4ea893e commit 4b2703b

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

examples/pdf-server/src/mcp-app.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,24 @@ async function refitScale(): Promise<void> {
342342
// needs height changes too (rotation, browser chrome on mobile).
343343
let lastContainerW = 0;
344344
let lastContainerH = 0;
345+
/** One-shot: refit on the next resize even if it's a shrink in inline mode.
346+
* Set on fullscreen→inline so the page snaps to the new (smaller) width
347+
* once the host has actually resized the iframe — the inline `grewW` gate
348+
* would otherwise swallow that shrink. */
349+
let forceNextResizeRefit = false;
345350
const containerResizeObserver = new ResizeObserver(([entry]) => {
346351
const { width: w, height: h } = entry.contentRect;
347352
const grewW = w > lastContainerW + 1;
348353
const changed =
349354
Math.abs(w - lastContainerW) > 1 || Math.abs(h - lastContainerH) > 1;
350355
lastContainerW = w;
351356
lastContainerH = h;
352-
if (currentDisplayMode === "fullscreen" ? changed : grewW) refitScale();
357+
if (forceNextResizeRefit && changed) {
358+
forceNextResizeRefit = false;
359+
refitScale();
360+
} else if (currentDisplayMode === "fullscreen" ? changed : grewW) {
361+
refitScale();
362+
}
353363
});
354364
containerResizeObserver.observe(canvasContainerEl as HTMLElement);
355365

@@ -3811,6 +3821,7 @@ function commitPinch() {
38113821
) {
38123822
pageWrapperEl.style.transform = "";
38133823
userHasZoomed = false; // let refitScale() size the inline view
3824+
forceNextResizeRefit = true; // ResizeObserver inline path ignores shrinks
38143825
modeTransitionInFlight = true;
38153826
void toggleFullscreen().finally(() => {
38163827
setTimeout(() => (modeTransitionInFlight = false), 250);
@@ -4783,6 +4794,12 @@ function handleHostContextChanged(ctx: McpUiHostContext) {
47834794
if (panelState.open) {
47844795
setAnnotationPanelOpen(true);
47854796
}
4797+
if (!isFullscreen) {
4798+
// The iframe shrink lands after this handler; let the ResizeObserver
4799+
// do one refit on that shrink (its inline branch normally ignores
4800+
// shrinks to avoid a requestFitToContent feedback loop).
4801+
forceNextResizeRefit = true;
4802+
}
47864803
if (wasFullscreen !== isFullscreen) {
47874804
// Mode changed → refit. computeFitScale reads displayMode, so
47884805
// this scales UP to fill on enter and back DOWN to ≤1.0 on exit.

0 commit comments

Comments
 (0)