Skip to content

feat(desktop): add a zoom setting that persists - #59277

Merged
opencode-agent[bot] merged 2 commits into
devfrom
desktop-zoom-setting
Oct 26, 2026
Merged

opencode-agent[bot] merged 2 commits into
devfrom
desktop-zoom-setting

Conversation

@opencode-agent

@opencode-agent opencode-agent Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #50168

Also covers the zoom part of #55152 (fixed steps that persist); the resizable input box there is separate.

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds a Zoom select to Settings → Appearance, above Reduce motion. It's desktop only and offers Slack's zoom levels from 100% up: 100, 110, 125, 150, 175 and 200%. It does not add a font-size setting. The select changes the window zoom, so text, controls and layout scale together.

  • It persists. The level is saved in the desktop settings store (zoomLevel). Every new window and the early startup window open at that level, so it survives reloads and restarts. Before this, wireZoom reset every window to 100%.
  • Shortcuts use the same steps. Cmd/Ctrl +, - and 0, plus View → Zoom In / Zoom Out / Actual Size, move to the next level up or down and save it. They used to add or subtract 20% and didn't save anything.
  • macOS View menu. The zoom items used Electron's built-in zoomIn/zoomOut/resetZoom roles. Those step Chromium's zoom on their own and bypass our handler. They now run the same actions as Windows, with Cmd+=, Cmd+- and Cmd+0 as accelerators.
  • Pinch zoom stays temporary. With pinch to zoom on, a gesture still zooms freely without saving. Turning pinch zoom off, or Ctrl-scrolling while it's off, goes back to the saved level instead of 100%.
  • IPC. WindowGetZoomLevel and WindowSetZoomLevel only accept the six levels; the schema rejects anything else. WindowZoomChanged now also carries the saved level, so the select follows shortcut changes made in any window.

This overlaps with community PRs #56802 and #50169, which save whatever zoom factor was last used, including pinch zoom.

How did you verify your code works?

  • bun run typecheck in packages/app and packages/desktop.
  • bun test in packages/desktop (221 pass).
  • desktop-menu.test.ts (new table for level stepping, including Chromium factors that come back slightly off a level) and search-results.test.ts (the setting only shows up in desktop settings search).
  • Built the app (electron-vite build) and drove it on Linux under Xvfb with an isolated profile over CDP:
    • Picking 125% → devicePixelRatio 1.25, zoomLevel: 1.25 saved, select shows 125%.
    • Ctrl+= → 150%. Ctrl+- twice → 110%. Ctrl+= twice → 150%.
    • Quit and relaunch → the app opens at 150% and the select shows 150%.
    • Ctrl+0 → 100%, saved.
  • Not verified on macOS: the new View menu items and their accelerators. In-app keyboard zoom is handled in the renderer before the menu, the same way Cmd+, and Cmd+[ already coexist with their menu items.

Screenshots / recordings

GitHub image upload isn't available to the bot; a screenshot of the Zoom row and its options (Linux build) was shared in the requesting Slack thread.

Visual

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="72" viewBox="0 0 240 72" fill="none">
  <rect x="8" y="10" width="148" height="52" rx="8" stroke="currentColor" stroke-opacity=".25"/>
  <text x="82" y="44" text-anchor="middle" fill="currentColor" font-family="sans-serif" font-size="18" font-weight="600">Aa
    <animate attributeName="font-size" values="18;18;22;22;27;27;18" keyTimes="0;.2;.3;.5;.6;.85;1" dur="4s" repeatCount="indefinite"/>
  </text>
  <rect x="168" y="24" width="64" height="24" rx="6" fill="currentColor" fill-opacity=".08"/>
  <text x="192" y="40" text-anchor="middle" fill="currentColor" font-family="sans-serif" font-size="11">100%
    <animate attributeName="opacity" values="1;1;0;0;0;0;1" keyTimes="0;.2;.3;.5;.6;.85;1" dur="4s" repeatCount="indefinite"/>
  </text>
  <text x="192" y="40" text-anchor="middle" fill="currentColor" font-family="sans-serif" font-size="11" opacity="0">125%
    <animate attributeName="opacity" values="0;0;1;1;0;0;0" keyTimes="0;.2;.3;.5;.6;.85;1" dur="4s" repeatCount="indefinite"/>
  </text>
  <text x="192" y="40" text-anchor="middle" fill="currentColor" font-family="sans-serif" font-size="11" opacity="0">150%
    <animate attributeName="opacity" values="0;0;0;0;1;1;0" keyTimes="0;.2;.3;.5;.6;.85;1" dur="4s" repeatCount="indefinite"/>
  </text>
  <path d="M221 34l3 3 3-3" stroke="currentColor" stroke-opacity=".5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Requested by: @vimtor (victor via Slack)


Added by the opencode bot (AI-generated).

Related: #55152, #49375, #46958

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks sound. I couldn't run the desktop app here because Electron doesn't start in this sandbox, so I checked it by reading the code and running the tests and type checks. The desktop tests pass, the two changed packages/app test files pass, tsc -b is clean in packages/app and packages/desktop, and electron-vite build succeeds. Stepping between levels allows for the small error in factors read back from Chromium. Saved levels are applied to every window and to the startup window. Pinch zoom stays unsaved and returns to the saved level when turned off.

Public API: unchanged. The new WindowGetZoomLevel/WindowSetZoomLevel calls, the level field on WindowZoomChanged and the zoomLevel key in the desktop settings store are all internal to the desktop app and only add to it.

No blocking concerns. The macOS View menu accelerators are still unverified, as the description says; a quick check on a Mac before merging would cover that.

Related: #55152, #49375, #46958

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new commit is a behaviour-preserving cleanup, and I have nothing new to raise. The macOS/Windows frame options are now shared in platformFrame() and produce the same options as before, including the Windows titlebar overlay sized by zoom. The saved background colour is read through savedBackgroundColor(), and the rest are lint fixes. On the new head, tsc -b is clean in packages/desktop and packages/app, the desktop tests and the two changed app test files pass, and electron-vite build succeeds. I still couldn't drive the app itself because Electron doesn't start in this sandbox.

Public API: unchanged.

@opencode-agent
opencode-agent Bot merged commit 5bf3e82 into dev Oct 26, 2026
19 checks passed
@opencode-agent
opencode-agent Bot deleted the desktop-zoom-setting branch October 26, 2026 13:37
@amrkmn amrkmn mentioned this pull request Oct 27, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Desktop zoom resets to 100% after restarting the app

1 participant