diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 4fa662c..09f039f 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -93,6 +93,10 @@ handle(IpcEvents.MAXIMIZE, e => { } }); +handle(IpcEvents.SET_ZOOM, (e, zoom: number) => { + mainWin.webContents.setZoomFactor(zoom); +}); + handleSync(IpcEvents.SPELLCHECK_GET_AVAILABLE_LANGUAGES, e => { e.returnValue = session.defaultSession.availableSpellCheckerLanguages; }); diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 1292449..b995bd7 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -9,6 +9,7 @@ import { BrowserWindow, BrowserWindowConstructorOptions, dialog, + globalShortcut, Menu, MenuItemConstructorOptions, nativeTheme, @@ -235,14 +236,14 @@ function initMenuBar(win: BrowserWindow) { click() { app.quit(); } - }, - // See https://github.com/electron/electron/issues/14742 and https://github.com/electron/electron/issues/5256 - { - label: "Zoom in (hidden, hack for Qwertz and others)", - accelerator: "CmdOrCtrl+=", - role: "zoomIn", - visible: false } + // See https://github.com/electron/electron/issues/14742 and https://github.com/electron/electron/issues/5256 + // { + // label: "Zoom in (hidden, hack for Qwertz and others)", + // accelerator: "CmdOrCtrl+=", + // role: "zoomIn", + // visible: false + // } ] satisfies MenuItemList; const menu = Menu.buildFromTemplate([ @@ -467,6 +468,36 @@ function createMainWindow() { const runVencordMain = once(() => require(join(VENCORD_FILES_DIR, "vencordDesktopMain.js"))); +const allowedZoomFactors = [0.5, 0.67, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2]; + +function handleZoomIn() { + const zoomFactor = Settings.store.zoomFactor ?? 1; + const currentIndex = allowedZoomFactors.indexOf(zoomFactor); + if (currentIndex < allowedZoomFactors.length - 1) { + const newZoomFactor = allowedZoomFactors[currentIndex + 1]; + Settings.setData({ zoomFactor: newZoomFactor }); + mainWin.webContents.setZoomFactor(newZoomFactor); + mainWin.webContents.send("zoomChanged", newZoomFactor); + } +} + +function handleZoomOut() { + const zoomFactor = Settings.store.zoomFactor ?? 1; + const currentIndex = allowedZoomFactors.indexOf(zoomFactor); + if (currentIndex > 0) { + const newZoomFactor = allowedZoomFactors[currentIndex - 1]; + Settings.setData({ zoomFactor: newZoomFactor }); + mainWin.webContents.setZoomFactor(newZoomFactor); + mainWin.webContents.send("zoomChanged", newZoomFactor); + } +} + +function resetZoom() { + Settings.setData({ zoomFactor: 1 }); + mainWin.webContents.setZoomFactor(1); + mainWin.webContents.send("zoomChanged", 1); +} + export async function createWindows() { const startMinimized = process.argv.includes("--start-minimized"); const splash = createSplashWindow(startMinimized); @@ -480,6 +511,8 @@ export async function createWindows() { mainWin.webContents.on("did-finish-load", () => { splash.destroy(); + mainWin.webContents.setZoomFactor(Settings.store.zoomFactor ?? 1); + if (!startMinimized) { mainWin!.show(); if (State.store.maximized && !isDeckGameMode) mainWin!.maximize(); @@ -497,6 +530,32 @@ export async function createWindows() { mainWin!.maximize(); } }); + + mainWin.on("focus", () => { + globalShortcut.register("CommandOrControl+0", () => { + resetZoom(); + }); + globalShortcut.register("CommandOrControl+plus", () => { + handleZoomIn(); + }); + globalShortcut.register("CommandOrControl+=", () => { + handleZoomIn(); + }); + globalShortcut.register("CommandOrControl+-", () => { + handleZoomOut(); + }); + globalShortcut.register("CommandOrControl+_", () => { + handleZoomOut(); + }); + }); + + mainWin.on("blur", () => { + globalShortcut.unregister("CommandOrControl+0"); + globalShortcut.unregister("CommandOrControl+plus"); + globalShortcut.unregister("CommandOrControl+="); + globalShortcut.unregister("CommandOrControl+-"); + globalShortcut.unregister("CommandOrControl+_"); + }); }); // evil hack to fix electron 32 regression that makes devtools always light theme diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index 7a8b977..572c310 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -55,7 +55,8 @@ export const VesktopNative = { focus: () => invoke(IpcEvents.FOCUS), close: (key?: string) => invoke(IpcEvents.CLOSE, key), minimize: () => invoke(IpcEvents.MINIMIZE), - maximize: () => invoke(IpcEvents.MAXIMIZE) + maximize: () => invoke(IpcEvents.MAXIMIZE), + zoom: (zoom: number) => invoke(IpcEvents.SET_ZOOM, zoom) }, capturer: { getLargeThumbnail: (id: string) => invoke(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id) diff --git a/src/preload/index.ts b/src/preload/index.ts index 75bf9cd..24a64f7 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -17,6 +17,10 @@ require(ipcRenderer.sendSync(IpcEvents.GET_VENCORD_PRELOAD_FILE)); webFrame.executeJavaScript(ipcRenderer.sendSync(IpcEvents.GET_VENCORD_RENDERER_SCRIPT)); webFrame.executeJavaScript(ipcRenderer.sendSync(IpcEvents.GET_RENDERER_SCRIPT)); +ipcRenderer.on("zoomChanged", (event, newZoomFactor) => { + window.dispatchEvent(new CustomEvent("zoomChanged", { detail: newZoomFactor })); +}); + // #region css const rendererCss = ipcRenderer.sendSync(IpcEvents.GET_RENDERER_CSS_FILE); diff --git a/src/renderer/components/settings/Settings.tsx b/src/renderer/components/settings/Settings.tsx index 81dfcc3..2c0bbe2 100644 --- a/src/renderer/components/settings/Settings.tsx +++ b/src/renderer/components/settings/Settings.tsx @@ -16,6 +16,7 @@ import { DiscordBranchPicker } from "./DiscordBranchPicker"; import { NotificationBadgeToggle } from "./NotificationBadgeToggle"; import { VencordLocationPicker } from "./VencordLocationPicker"; import { WindowsTransparencyControls } from "./WindowsTransparencyControls"; +import { WindowZoom } from "./WindowZoom"; interface BooleanSetting { key: keyof typeof Settings.store; @@ -65,7 +66,8 @@ const SettingsOptions: Record> description: "Adapt the splash window colors to your custom theme", defaultValue: false }, - WindowsTransparencyControls + WindowsTransparencyControls, + WindowZoom ], Behaviour: [ { diff --git a/src/renderer/components/settings/WindowZoom.tsx b/src/renderer/components/settings/WindowZoom.tsx new file mode 100644 index 0000000..16573e7 --- /dev/null +++ b/src/renderer/components/settings/WindowZoom.tsx @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vesktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { Margins } from "@vencord/types/utils"; +import { Forms, Slider, useEffect, useState } from "@vencord/types/webpack/common"; + +import { SettingsComponent } from "./Settings"; + +export const WindowZoom: SettingsComponent = ({ settings }) => { + const [zoomFactor, setZoomFactor] = useState(settings.zoomFactor ?? 1); + + useEffect(() => { + const handleZoomChange = event => { + console.log("zoom changed", event.detail); + setZoomFactor(event.detail); + }; + + window.addEventListener("zoomChanged", handleZoomChange); + + return () => { + window.removeEventListener("zoomChanged", handleZoomChange); + }; + }, []); + + return ( + <> + Zoom Level + { + settings.zoomFactor = v; + VesktopNative.win.zoom(v); + setZoomFactor(v); + }} + minValue={0.5} + maxValue={2} + markers={[0.5, 0.67, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2]} + stickToMarkers={true} + onMarkerRender={v => (v === 1 ? "100" : `${Math.round(v * 100)}`)} + > + + ); +}; diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index 51d2a28..a9f19e9 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -18,6 +18,7 @@ export const enum IpcEvents { FOCUS = "VCD_FOCUS", MINIMIZE = "VCD_MINIMIZE", MAXIMIZE = "VCD_MAXIMIZE", + SET_ZOOM = "VCD_ZOOM", SHOW_ITEM_IN_FOLDER = "VCD_SHOW_ITEM_IN_FOLDER", GET_SETTINGS = "VCD_GET_SETTINGS", diff --git a/src/shared/settings.d.ts b/src/shared/settings.d.ts index f100010..e348d5c 100644 --- a/src/shared/settings.d.ts +++ b/src/shared/settings.d.ts @@ -19,6 +19,7 @@ export interface Settings { arRPC?: boolean; appBadge?: boolean; disableMinSize?: boolean; + zoomFactor?: number; clickTrayToShowHide?: boolean; customTitleBar?: boolean;