mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
fix(desktop): persist zoom state across vault locks (#17217)
* fix(desktop): persist zoom state across vault locks Replace role-based zoom menu items with custom click handlers to fix zoom persistence issue where keyboard shortcuts (Ctrl+/-/0, Cmd+/-/0) weren't saving zoom changes after vault lock. Changes: - Add custom click handlers for zoomIn/zoomOut/resetZoom menu items - Add WindowMain.saveZoomFactor() method for immediate persistence - Pass WindowMain dependency to ViewMenu constructor - Update zoom-changed event comment to clarify coverage - Maintain existing mouse wheel zoom persistence via zoom-changed event Fixes: PM-791 Fixes: https://github.com/bitwarden/clients/issues/4675 * chore: update to macos-15 runners * review: downgrade macos build runner to 14 * review: align step with min zoom level * cleanup from merge
This commit is contained in:
@@ -6,6 +6,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
|
||||
import { isDev } from "../../utils";
|
||||
import { WindowMain } from "../window.main";
|
||||
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
@@ -42,11 +43,18 @@ export class ViewMenu implements IMenubarMenu {
|
||||
private readonly _i18nService: I18nService;
|
||||
private readonly _messagingService: MessagingService;
|
||||
private readonly _isLocked: boolean;
|
||||
private readonly _windowMain: WindowMain;
|
||||
|
||||
constructor(i18nService: I18nService, messagingService: MessagingService, isLocked: boolean) {
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
messagingService: MessagingService,
|
||||
isLocked: boolean,
|
||||
windowMain: WindowMain,
|
||||
) {
|
||||
this._i18nService = i18nService;
|
||||
this._messagingService = messagingService;
|
||||
this._isLocked = isLocked;
|
||||
this._windowMain = windowMain;
|
||||
}
|
||||
|
||||
private get searchVault(): MenuItemConstructorOptions {
|
||||
@@ -86,7 +94,12 @@ export class ViewMenu implements IMenubarMenu {
|
||||
return {
|
||||
id: "zoomIn",
|
||||
label: this.localize("zoomIn"),
|
||||
role: "zoomIn",
|
||||
click: async () => {
|
||||
const currentZoom = this._windowMain.win.webContents.zoomFactor;
|
||||
const newZoom = currentZoom + 0.1;
|
||||
this._windowMain.win.webContents.zoomFactor = newZoom;
|
||||
await this._windowMain.saveZoomFactor(newZoom);
|
||||
},
|
||||
accelerator: "CmdOrCtrl+=",
|
||||
};
|
||||
}
|
||||
@@ -95,7 +108,12 @@ export class ViewMenu implements IMenubarMenu {
|
||||
return {
|
||||
id: "zoomOut",
|
||||
label: this.localize("zoomOut"),
|
||||
role: "zoomOut",
|
||||
click: async () => {
|
||||
const currentZoom = this._windowMain.win.webContents.zoomFactor;
|
||||
const newZoom = Math.max(0.2, currentZoom - 0.1);
|
||||
this._windowMain.win.webContents.zoomFactor = newZoom;
|
||||
await this._windowMain.saveZoomFactor(newZoom);
|
||||
},
|
||||
accelerator: "CmdOrCtrl+-",
|
||||
};
|
||||
}
|
||||
@@ -104,7 +122,11 @@ export class ViewMenu implements IMenubarMenu {
|
||||
return {
|
||||
id: "resetZoom",
|
||||
label: this.localize("resetZoom"),
|
||||
role: "resetZoom",
|
||||
click: async () => {
|
||||
const newZoom = 1.0;
|
||||
this._windowMain.win.webContents.zoomFactor = newZoom;
|
||||
await this._windowMain.saveZoomFactor(newZoom);
|
||||
},
|
||||
accelerator: "CmdOrCtrl+0",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ export class Menubar {
|
||||
updateRequest?.restrictedCipherTypes,
|
||||
),
|
||||
new EditMenu(i18nService, messagingService, isLocked),
|
||||
new ViewMenu(i18nService, messagingService, isLocked),
|
||||
new ViewMenu(i18nService, messagingService, isLocked, windowMain),
|
||||
new AccountMenu(
|
||||
i18nService,
|
||||
messagingService,
|
||||
|
||||
@@ -303,7 +303,9 @@ export class WindowMain {
|
||||
this.win.webContents.zoomFactor = this.windowStates[mainWindowSizeKey].zoomFactor ?? 1.0;
|
||||
});
|
||||
|
||||
// Persist zoom changes immediately when user zooms in/out or resets zoom
|
||||
// Persist zoom changes from mouse wheel and programmatic zoom operations
|
||||
// NOTE: This event does NOT fire for keyboard shortcuts (Ctrl+/-/0, Cmd+/-/0)
|
||||
// which are handled by custom menu click handlers in ViewMenu
|
||||
// We can't depend on higher level web events (like close) to do this
|
||||
// because locking the vault resets window state.
|
||||
this.win.webContents.on("zoom-changed", async () => {
|
||||
@@ -432,6 +434,11 @@ export class WindowMain {
|
||||
await this.desktopSettingsService.setAlwaysOnTop(this.enableAlwaysOnTop);
|
||||
}
|
||||
|
||||
async saveZoomFactor(zoomFactor: number) {
|
||||
this.windowStates[mainWindowSizeKey].zoomFactor = zoomFactor;
|
||||
await this.desktopSettingsService.setWindow(this.windowStates[mainWindowSizeKey]);
|
||||
}
|
||||
|
||||
private windowStateChangeHandler(configKey: string, win: BrowserWindow) {
|
||||
global.clearTimeout(this.windowStateChangeTimer);
|
||||
this.windowStateChangeTimer = global.setTimeout(async () => {
|
||||
|
||||
Reference in New Issue
Block a user