From 7060b8aece32dcd56a1af1baf3ca6cfcf12ce0e7 Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Mon, 20 Jul 2026 08:46:55 +0300 Subject: [PATCH 1/5] fix(code): preserve zoom across task navigation Generated-By: PostHog Code Task-Id: 33078092-6d41-45e8-8375-157f66bcea43 --- apps/code/src/main/zoom.test.ts | 30 ++++++++++++++++++++++++++++++ apps/code/src/main/zoom.ts | 7 +++++++ 2 files changed, 37 insertions(+) diff --git a/apps/code/src/main/zoom.test.ts b/apps/code/src/main/zoom.test.ts index a7b5792377..c1f28bece6 100644 --- a/apps/code/src/main/zoom.test.ts +++ b/apps/code/src/main/zoom.test.ts @@ -85,6 +85,36 @@ describe("window zoom", () => { expect(window.webContents.zoomLevel).toBe(0.5); }); + it("restores the persisted level after task navigation", () => { + const window = createWindow(); + setupWindowZoom(window); + window.webContents.zoomLevel = 0; + + window.webContents.emit( + "did-navigate-in-page", + {}, + "file:///app/tasks/next-task", + true, + ); + + expect(window.webContents.zoomLevel).toBe(0.5); + }); + + it("ignores in-page navigation inside subframes", () => { + const window = createWindow(); + setupWindowZoom(window); + window.webContents.zoomLevel = 0; + + window.webContents.emit( + "did-navigate-in-page", + {}, + "file:///embedded-content", + false, + ); + + expect(window.webContents.zoomLevel).toBe(0); + }); + it.each([ ["in", 1], ["out", 0], diff --git a/apps/code/src/main/zoom.ts b/apps/code/src/main/zoom.ts index af4e49ddba..0a6626b392 100644 --- a/apps/code/src/main/zoom.ts +++ b/apps/code/src/main/zoom.ts @@ -7,6 +7,10 @@ const ZOOM_MAX = 3; interface ZoomWebContents { on(event: "did-finish-load", listener: () => void): void; + on( + event: "did-navigate-in-page", + listener: (event: unknown, url: string, isMainFrame: boolean) => void, + ): void; on( event: "zoom-changed", listener: ( @@ -105,6 +109,9 @@ export function setupWindowZoom(window: ZoomWindow): void { }; window.webContents.on("did-finish-load", () => restoreWindowZoom(window)); + window.webContents.on("did-navigate-in-page", (_event, _url, isMainFrame) => { + if (isMainFrame) restoreWindowZoom(window); + }); window.webContents.on("zoom-changed", (event, zoomDirection) => { event.preventDefault(); state.wheelZoomDelta += zoomDirection === "in" ? ZOOM_STEP : -ZOOM_STEP; From 56bc4d32897673ba3e9c72c2d7211a0bd5548b88 Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Mon, 20 Jul 2026 08:51:50 +0300 Subject: [PATCH 2/5] fix(code): restore zoom after external resize Generated-By: PostHog Code Task-Id: 33078092-6d41-45e8-8375-157f66bcea43 --- apps/code/src/main/zoom.test.ts | 39 ++++++++++++++------------------- apps/code/src/main/zoom.ts | 9 ++------ 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/apps/code/src/main/zoom.test.ts b/apps/code/src/main/zoom.test.ts index c1f28bece6..e5f14ada1b 100644 --- a/apps/code/src/main/zoom.test.ts +++ b/apps/code/src/main/zoom.test.ts @@ -85,34 +85,29 @@ describe("window zoom", () => { expect(window.webContents.zoomLevel).toBe(0.5); }); - it("restores the persisted level after task navigation", () => { + it("restores the current level after an external window resize", () => { const window = createWindow(); setupWindowZoom(window); - window.webContents.zoomLevel = 0; - - window.webContents.emit( - "did-navigate-in-page", - {}, - "file:///app/tasks/next-task", - true, - ); - - expect(window.webContents.zoomLevel).toBe(0.5); - }); - it("ignores in-page navigation inside subframes", () => { - const window = createWindow(); - setupWindowZoom(window); + window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in"); + vi.runAllTimers(); + vi.advanceTimersByTime(5 * 60 * 1000); window.webContents.zoomLevel = 0; - window.webContents.emit( - "did-navigate-in-page", - {}, - "file:///embedded-content", - false, - ); + window.emit("resize"); + vi.runAllTimers(); + const restoredZoomLevel = window.webContents.zoomLevel; + adjustWindowZoom(window, 0.5); - expect(window.webContents.zoomLevel).toBe(0); + expect({ + restoredZoomLevel, + zoomLevel: window.webContents.zoomLevel, + saved: store.save.mock.calls, + }).toEqual({ + restoredZoomLevel: 1, + zoomLevel: 1.5, + saved: [[1], [1.5]], + }); }); it.each([ diff --git a/apps/code/src/main/zoom.ts b/apps/code/src/main/zoom.ts index 0a6626b392..3b33e4a0bc 100644 --- a/apps/code/src/main/zoom.ts +++ b/apps/code/src/main/zoom.ts @@ -7,10 +7,6 @@ const ZOOM_MAX = 3; interface ZoomWebContents { on(event: "did-finish-load", listener: () => void): void; - on( - event: "did-navigate-in-page", - listener: (event: unknown, url: string, isMainFrame: boolean) => void, - ): void; on( event: "zoom-changed", listener: ( @@ -27,6 +23,7 @@ interface ZoomWindow { | "enter-full-screen" | "leave-full-screen" | "maximize" + | "resize" | "resized" | "unmaximize", listener: () => void, @@ -109,9 +106,6 @@ export function setupWindowZoom(window: ZoomWindow): void { }; window.webContents.on("did-finish-load", () => restoreWindowZoom(window)); - window.webContents.on("did-navigate-in-page", (_event, _url, isMainFrame) => { - if (isMainFrame) restoreWindowZoom(window); - }); window.webContents.on("zoom-changed", (event, zoomDirection) => { event.preventDefault(); state.wheelZoomDelta += zoomDirection === "in" ? ZOOM_STEP : -ZOOM_STEP; @@ -127,6 +121,7 @@ export function setupWindowZoom(window: ZoomWindow): void { window.on("maximize", scheduleRestore); window.on("unmaximize", scheduleRestore); + window.on("resize", scheduleRestore); window.on("resized", scheduleRestore); window.on("enter-full-screen", scheduleRestore); window.on("leave-full-screen", scheduleRestore); From fd5ca1b1c85540fd6656d7d959009ec7acdaffd3 Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Mon, 20 Jul 2026 08:59:18 +0300 Subject: [PATCH 3/5] test(code): cover zoom resize edge cases Generated-By: PostHog Code Task-Id: 33078092-6d41-45e8-8375-157f66bcea43 --- apps/code/src/main/zoom.test.ts | 55 ++++++++++++++++++++++++++++++--- apps/code/src/main/zoom.ts | 3 ++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/apps/code/src/main/zoom.test.ts b/apps/code/src/main/zoom.test.ts index e5f14ada1b..8ce5052c9e 100644 --- a/apps/code/src/main/zoom.test.ts +++ b/apps/code/src/main/zoom.test.ts @@ -20,9 +20,16 @@ vi.mock("./utils/store", () => ({ import { adjustWindowZoom, restoreWindowZoom, setupWindowZoom } from "./zoom"; class FakeWebContents extends EventEmitter { + public destroyed = false; + public readonly setZoomLevelCalls: number[] = []; public zoomLevel = 0; + public isDestroyed(): boolean { + return this.destroyed; + } + public setZoomLevel(level: number): void { + this.setZoomLevelCalls.push(level); this.zoomLevel = level; } } @@ -135,20 +142,58 @@ describe("window zoom", () => { }, ); - it("keeps wheel zoom after resizing", () => { + it.each(["resize", "resized"] as const)( + "keeps wheel zoom after %s", + (resizeEvent) => { + const window = createWindow(); + setupWindowZoom(window); + + window.webContents.emit( + "zoom-changed", + { preventDefault: vi.fn() }, + "in", + ); + window.emit(resizeEvent); + vi.runAllTimers(); + + expect({ + zoomLevel: window.webContents.zoomLevel, + saved: store.save.mock.calls, + }).toEqual({ + zoomLevel: 1, + saved: [[1]], + }); + }, + ); + + it("debounces repeated resize restorations", () => { const window = createWindow(); setupWindowZoom(window); + window.webContents.zoomLevel = 0; - window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in"); + window.emit("resize"); + window.emit("resize"); window.emit("resized"); vi.runAllTimers(); + expect(window.webContents.setZoomLevelCalls).toEqual([0.5]); + }); + + it("ignores queued zoom work after the window is destroyed", () => { + const window = createWindow(); + setupWindowZoom(window); + + window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in"); + window.emit("resize"); + window.webContents.destroyed = true; + vi.runAllTimers(); + expect({ - zoomLevel: window.webContents.zoomLevel, + zoomLevelCalls: window.webContents.setZoomLevelCalls, saved: store.save.mock.calls, }).toEqual({ - zoomLevel: 1, - saved: [[1]], + zoomLevelCalls: [], + saved: [], }); }); diff --git a/apps/code/src/main/zoom.ts b/apps/code/src/main/zoom.ts index 3b33e4a0bc..41e84ed0c8 100644 --- a/apps/code/src/main/zoom.ts +++ b/apps/code/src/main/zoom.ts @@ -6,6 +6,7 @@ const ZOOM_MIN = -3; const ZOOM_MAX = 3; interface ZoomWebContents { + isDestroyed(): boolean; on(event: "did-finish-load", listener: () => void): void; on( event: "zoom-changed", @@ -63,6 +64,7 @@ function runAfterWheelZoom(window: ZoomWindow, action: () => void): void { } export function setWindowZoom(window: ZoomWindow, level: number): void { + if (window.webContents.isDestroyed()) return; const nextLevel = clampZoomLevel(level); const state = zoomStates.get(window); if (state) state.currentZoomLevel = nextLevel; @@ -83,6 +85,7 @@ export function adjustWindowZoom( export function restoreWindowZoom(window: ZoomWindow): void { runAfterWheelZoom(window, () => { + if (window.webContents.isDestroyed()) return; window.webContents.setZoomLevel(getCurrentZoomLevel(window)); }); } From a9c668f3cc9f30f0335341d5a443a18e14fb69e2 Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Mon, 20 Jul 2026 09:08:16 +0300 Subject: [PATCH 4/5] fix(code): avoid redundant zoom restoration Generated-By: PostHog Code Task-Id: 33078092-6d41-45e8-8375-157f66bcea43 --- apps/code/src/main/zoom.test.ts | 25 ++++++++++++++++++++----- apps/code/src/main/zoom.ts | 6 +++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/apps/code/src/main/zoom.test.ts b/apps/code/src/main/zoom.test.ts index 8ce5052c9e..3798c6766d 100644 --- a/apps/code/src/main/zoom.test.ts +++ b/apps/code/src/main/zoom.test.ts @@ -28,6 +28,10 @@ class FakeWebContents extends EventEmitter { return this.destroyed; } + public getZoomLevel(): number { + return this.zoomLevel; + } + public setZoomLevel(level: number): void { this.setZoomLevelCalls.push(level); this.zoomLevel = level; @@ -98,7 +102,6 @@ describe("window zoom", () => { window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in"); vi.runAllTimers(); - vi.advanceTimersByTime(5 * 60 * 1000); window.webContents.zoomLevel = 0; window.emit("resize"); @@ -166,17 +169,29 @@ describe("window zoom", () => { }, ); - it("debounces repeated resize restorations", () => { + it("skips redundant restoration during a resize storm", () => { const window = createWindow(); setupWindowZoom(window); - window.webContents.zoomLevel = 0; + window.webContents.zoomLevel = 0.5; window.emit("resize"); + vi.runAllTimers(); + vi.advanceTimersByTime(16); window.emit("resize"); - window.emit("resized"); vi.runAllTimers(); + const callsBeforeReset = [...window.webContents.setZoomLevelCalls]; - expect(window.webContents.setZoomLevelCalls).toEqual([0.5]); + window.webContents.zoomLevel = 0; + window.emit("resize"); + vi.runAllTimers(); + + expect({ + callsBeforeReset, + callsAfterReset: window.webContents.setZoomLevelCalls, + }).toEqual({ + callsBeforeReset: [], + callsAfterReset: [0.5], + }); }); it("ignores queued zoom work after the window is destroyed", () => { diff --git a/apps/code/src/main/zoom.ts b/apps/code/src/main/zoom.ts index 41e84ed0c8..db845cd78f 100644 --- a/apps/code/src/main/zoom.ts +++ b/apps/code/src/main/zoom.ts @@ -6,6 +6,7 @@ const ZOOM_MIN = -3; const ZOOM_MAX = 3; interface ZoomWebContents { + getZoomLevel(): number; isDestroyed(): boolean; on(event: "did-finish-load", listener: () => void): void; on( @@ -86,7 +87,10 @@ export function adjustWindowZoom( export function restoreWindowZoom(window: ZoomWindow): void { runAfterWheelZoom(window, () => { if (window.webContents.isDestroyed()) return; - window.webContents.setZoomLevel(getCurrentZoomLevel(window)); + const zoomLevel = getCurrentZoomLevel(window); + if (window.webContents.getZoomLevel() !== zoomLevel) { + window.webContents.setZoomLevel(zoomLevel); + } }); } From 0f7864e01e194c30b60af97a75570e8b1fdf35f5 Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2026 12:11:20 +0000 Subject: [PATCH 5/5] chore(visual): update storybook baselines 1 updated Run: 2ef00186-bf99-4380-a1a0-a510133e43c2 Co-authored-by: richardsolomou <2622273+richardsolomou@users.noreply.github.com> --- apps/code/snapshots.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/code/snapshots.yml b/apps/code/snapshots.yml index cfbdd290b1..26cb8c4587 100644 --- a/apps/code/snapshots.yml +++ b/apps/code/snapshots.yml @@ -27,7 +27,7 @@ snapshots: archive-archivedtasksview--many-tasks--dark: hash: v1.k4693efd2.40d24f07a24c6400c32ae68b39fd908a056beb5dc6df8bcb237ec2ab2b494f4a.l2vjfSQDalCPRtDNV7pbfTKGlMsQoI81jI-UdJfLHWE archive-archivedtasksview--many-tasks--light: - hash: v1.k4693efd2.52ec9963bfe6f248ffcdaa4c26945d2b7e303115825b65d978aa5aefd4af1007.ZLtOfTZUrznhYeB-N2SIHzQWRzF6TDSaipNkfd8uzjM + hash: v1.k4693efd2.74c25b303262f2d4c0f22890d351e76f482827548548f7c023bc309327c927b8.DP9VVrvBz1naIJMwHORkfqm69BlO785ulOt4o6zFs94 archive-archivedtasksview--mixed-modes--dark: hash: v1.k4693efd2.d94039b8cc17a4ad1b720364f41fee58a4843aa9a901443997ba62602f698794.441LWZhT-2WQZJHni4LoOgQsOSr2O103NZOk1pF8ME4 archive-archivedtasksview--mixed-modes--light: