diff --git a/app/common/config-schemata.ts b/app/common/config-schemata.ts index e2db7b80f..c61a63d7c 100644 --- a/app/common/config-schemata.ts +++ b/app/common/config-schemata.ts @@ -12,6 +12,7 @@ export const configSchemata = { autoHideMenubar: z.boolean(), autoUpdate: z.boolean(), badgeOption: z.boolean(), + useOneZoom: z.boolean(), betaUpdate: z.boolean(), // eslint-disable-next-line @typescript-eslint/naming-convention customCSS: z.string().or(z.literal(false)).nullable(), diff --git a/app/common/typed-ipc.ts b/app/common/typed-ipc.ts index 269f42984..7ca7ca776 100644 --- a/app/common/typed-ipc.ts +++ b/app/common/typed-ipc.ts @@ -15,6 +15,7 @@ export type MainMessage = { "reload-full-app": () => void; "save-last-tab": (index: number) => void; "switch-server-tab": (index: number) => void; + "sync-zooms": () => void; "toggle-app": () => void; "toggle-badge-option": (newValue: boolean) => void; "toggle-menubar": (showMenubar: boolean) => void; @@ -64,6 +65,7 @@ export type RendererMessage = { "show-keyboard-shortcuts": () => void; "show-notification-settings": () => void; "switch-server-tab": (index: number) => void; + "sync-zooms": () => void; "tab-devtools": () => void; "toggle-autohide-menubar": ( autoHideMenubar: boolean, diff --git a/app/main/index.ts b/app/main/index.ts index 5edc3ae79..682d6eb2c 100644 --- a/app/main/index.ts +++ b/app/main/index.ts @@ -259,6 +259,7 @@ function createMainWindow(): BrowserWindow { AppMenu.setMenu({ tabs: [], }); + mainWindow = createMainWindow(); // Auto-hide menu bar on Windows + Linux diff --git a/app/renderer/js/components/webview.ts b/app/renderer/js/components/webview.ts index e51e0af95..115f8e6bc 100644 --- a/app/renderer/js/components/webview.ts +++ b/app/renderer/js/components/webview.ts @@ -158,6 +158,14 @@ export default class WebView { this.show(); } + getZoomFactor(): number { + return this.getWebContents().getZoomFactor(); + } + + setZoomFactor(value: number): void { + this.getWebContents().setZoomFactor(value); + } + zoomIn(): void { this.getWebContents().zoomLevel += 0.5; } diff --git a/app/renderer/js/main.ts b/app/renderer/js/main.ts index 7c693ee58..c4b8254b2 100644 --- a/app/renderer/js/main.ts +++ b/app/renderer/js/main.ts @@ -176,6 +176,7 @@ export class ServerManagerView { // Default settings which should be respected const settingOptions: Partial = { autoHideMenubar: false, + useOneZoom: true, trayIcon: true, useManualProxy: false, useSystemProxy: false, @@ -886,18 +887,21 @@ export class ServerManagerView { "zoomIn", (webview) => { webview.zoomIn(); + this.syncZooms(webview.getZoomFactor()); }, ], [ "zoomOut", (webview) => { webview.zoomOut(); + this.syncZooms(webview.getZoomFactor()); }, ], [ "zoomActualSize", (webview) => { webview.zoomActualSize(); + this.syncZooms(webview.getZoomFactor()); }, ], [ @@ -1084,6 +1088,10 @@ export class ServerManagerView { }, ); + ipcRenderer.on("sync-zooms", () => { + this.syncZooms(); + }); + ipcRenderer.on("enter-fullscreen", () => { this.$fullscreenPopup.classList.add("show"); this.$fullscreenPopup.classList.remove("hidden"); @@ -1176,6 +1184,23 @@ export class ServerManagerView { await dingSound.play(); }); } + + private syncZooms(value = 1): void { + const shouldUseOneZoom = ConfigUtil.getConfigItem("useOneZoom", true); + if (shouldUseOneZoom) { + for (const tab of this.tabs) { + if (tab instanceof ServerTab) { + tab.webview + .then((webv) => { + webv.setZoomFactor(value); + }) + .catch((error) => { + console.error("Error syncing zoom factors:", error); + }); + } + } + } + } } window.addEventListener("load", async () => { diff --git a/app/renderer/js/pages/preference/general-section.ts b/app/renderer/js/pages/preference/general-section.ts index 782dde253..6fdaf80a8 100644 --- a/app/renderer/js/pages/preference/general-section.ts +++ b/app/renderer/js/pages/preference/general-section.ts @@ -126,6 +126,12 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void {
+
+
+ ${t.__("Use one zoom for all organization tabs")} +
+
+
${t.__("Enable spellchecker (requires restart)")} @@ -213,6 +219,7 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void { `.html; updateTrayOption(); + useOneZoom(); updateBadgeOption(); updateSilentOption(); autoUpdateOption(); @@ -263,6 +270,21 @@ export function initGeneralSection({$root}: GeneralSectionProperties): void { }); } + function useOneZoom(): void { + generateSettingOption({ + $element: $root.querySelector("#one-zoom-option .setting-control")!, + value: ConfigUtil.getConfigItem("useOneZoom", false), + clickHandler() { + const newValue = !ConfigUtil.getConfigItem("useOneZoom", false); + ConfigUtil.setConfigItem("useOneZoom", newValue); + useOneZoom(); + if (newValue) { + ipcRenderer.send("sync-zooms"); + } + }, + }); + } + function updateMenubarOption(): void { generateSettingOption({ $element: $root.querySelector("#menubar-option .setting-control")!, diff --git a/package-lock.json b/package-lock.json index 0789a5587..aeef63c22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11047,13 +11047,13 @@ } }, "node_modules/vite": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.3.tgz", - "integrity": "sha512-+i1oagbvkVIhEy9TnEV+fgXsng13nZM90JQbrcPrf6DvW2mXARlz+DK7DLiDP+qeKoD1FCVx/1SpFL1CLq9Mhw==", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz", + "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==", "dev": true, "dependencies": { "esbuild": "^0.20.1", - "postcss": "^8.4.36", + "postcss": "^8.4.38", "rollup": "^4.13.0" }, "bin": {