mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
fix(desktop): persist zoom level via renderer localStorage (#41747)
Desktop zoom shortcuts (Cmd/Ctrl +/-/0) and the View menu only called webContents.setZoomLevel(), which mutates the live renderer but persists nothing. On reload, renderer crash/restart, or page recreation the app snapped back to the default zoom, so the shortcuts felt broken for users who need larger text. Persist the selected zoom in the renderer's own localStorage rather than a main-process JSON file. localStorage is per-origin and survives the renderer lifecycle automatically, so there's no atomic-write/userData file machinery to maintain. The main process still owns setZoomLevel: every zoom change is mirrored into localStorage via executeJavaScript, and the value is read back and re-applied on did-finish-load (covering reloads and crash recovery). Clamping to Electron's [-9, 9] range now happens once in setAndPersistZoomLevel instead of at each call site.
This commit is contained in:
parent
d65b513f23
commit
b5a457c033
1 changed files with 39 additions and 10 deletions
|
|
@ -3137,7 +3137,7 @@ function buildApplicationMenu() {
|
|||
label: 'Actual Size',
|
||||
accelerator: 'CommandOrControl+0',
|
||||
click: () => {
|
||||
if (mainWindow && !mainWindow.isDestroyed()) mainWindow.webContents.setZoomLevel(0)
|
||||
setAndPersistZoomLevel(mainWindow, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -3145,8 +3145,7 @@ function buildApplicationMenu() {
|
|||
accelerator: 'CommandOrControl+Plus',
|
||||
click: () => {
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
const next = Math.min(mainWindow.webContents.getZoomLevel() + 0.1, 9)
|
||||
mainWindow.webContents.setZoomLevel(next)
|
||||
setAndPersistZoomLevel(mainWindow, mainWindow.webContents.getZoomLevel() + 0.1)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3155,8 +3154,7 @@ function buildApplicationMenu() {
|
|||
accelerator: 'CommandOrControl+-',
|
||||
click: () => {
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
const next = Math.max(mainWindow.webContents.getZoomLevel() - 0.1, -9)
|
||||
mainWindow.webContents.setZoomLevel(next)
|
||||
setAndPersistZoomLevel(mainWindow, mainWindow.webContents.getZoomLevel() - 0.1)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3218,6 +3216,38 @@ function installPreviewShortcut(window) {
|
|||
})
|
||||
}
|
||||
|
||||
// Zoom level is persisted in the renderer's own localStorage (per-origin,
|
||||
// survives reloads/restarts) rather than a main-process JSON file. The main
|
||||
// process owns setZoomLevel, so we mirror each change into localStorage and
|
||||
// read it back on did-finish-load to re-apply after reloads or crash recovery.
|
||||
const ZOOM_STORAGE_KEY = 'hermes:desktop:zoomLevel'
|
||||
|
||||
function clampZoomLevel(value) {
|
||||
if (!Number.isFinite(value)) return 0
|
||||
return Math.min(Math.max(value, -9), 9)
|
||||
}
|
||||
|
||||
function setAndPersistZoomLevel(window, zoomLevel) {
|
||||
if (!window || window.isDestroyed()) return
|
||||
const next = clampZoomLevel(zoomLevel)
|
||||
window.webContents.setZoomLevel(next)
|
||||
window.webContents
|
||||
.executeJavaScript(`try { localStorage.setItem(${JSON.stringify(ZOOM_STORAGE_KEY)}, ${JSON.stringify(String(next))}) } catch {}`)
|
||||
.catch(error => rememberLog(`[zoom] persist failed: ${error?.message || error}`))
|
||||
}
|
||||
|
||||
function restorePersistedZoomLevel(window) {
|
||||
if (!window || window.isDestroyed()) return
|
||||
window.webContents
|
||||
.executeJavaScript(`(() => { try { return localStorage.getItem(${JSON.stringify(ZOOM_STORAGE_KEY)}) } catch { return null } })()`)
|
||||
.then(stored => {
|
||||
if (stored == null || !window || window.isDestroyed()) return
|
||||
const level = clampZoomLevel(Number(stored))
|
||||
window.webContents.setZoomLevel(level)
|
||||
})
|
||||
.catch(error => rememberLog(`[zoom] restore failed: ${error?.message || error}`))
|
||||
}
|
||||
|
||||
function installZoomShortcuts(window) {
|
||||
// Override Ctrl/Cmd + +/-/0 with half the default zoom step (0.1 vs 0.2).
|
||||
// The menu items handle this on macOS (where the menu is always present),
|
||||
|
|
@ -3231,15 +3261,13 @@ function installZoomShortcuts(window) {
|
|||
const key = input.key
|
||||
if (key === '0') {
|
||||
event.preventDefault()
|
||||
window.webContents.setZoomLevel(0)
|
||||
setAndPersistZoomLevel(window, 0)
|
||||
} else if (key === '=' || key === '+') {
|
||||
event.preventDefault()
|
||||
const next = Math.min(window.webContents.getZoomLevel() + ZOOM_STEP, 9)
|
||||
window.webContents.setZoomLevel(next)
|
||||
setAndPersistZoomLevel(window, window.webContents.getZoomLevel() + ZOOM_STEP)
|
||||
} else if (key === '-') {
|
||||
event.preventDefault()
|
||||
const next = Math.max(window.webContents.getZoomLevel() - ZOOM_STEP, -9)
|
||||
window.webContents.setZoomLevel(next)
|
||||
setAndPersistZoomLevel(window, window.webContents.getZoomLevel() - ZOOM_STEP)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -4730,6 +4758,7 @@ function createWindow() {
|
|||
}
|
||||
|
||||
mainWindow.webContents.once('did-finish-load', () => {
|
||||
restorePersistedZoomLevel(mainWindow)
|
||||
broadcastBootProgress()
|
||||
sendWindowStateChanged()
|
||||
startHermes().catch(error => rememberLog(error.stack || error.message))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue