Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add zoom slider, match official client zoom #370

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
4 changes: 4 additions & 0 deletions src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ handle(IpcEvents.MAXIMIZE, e => {
}
});

handle(IpcEvents.SET_ZOOM, (e, zoom: number) => {
mainWin.webContents.setZoomFactor(zoom);
});

handle(IpcEvents.SPELLCHECK_SET_LANGUAGES, (_, languages: string[]) => {
const ses = session.defaultSession;

Expand Down
73 changes: 66 additions & 7 deletions src/main/mainWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
BrowserWindow,
BrowserWindowConstructorOptions,
dialog,
globalShortcut,
Menu,
MenuItemConstructorOptions,
nativeTheme,
Expand Down Expand Up @@ -229,14 +230,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([
Expand Down Expand Up @@ -440,6 +441,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);
Copy link
Member

Choose a reason for hiding this comment

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

if you just want to check for existence of an element, includes should be used over indexOf

Suggested change
const currentIndex = allowedZoomFactors.indexOf(zoomFactor);
const currentIndex = allowedZoomFactors.includes(zoomFactor);

if (currentIndex > 0) {
const newZoomFactor = allowedZoomFactors[currentIndex - 1];
Settings.setData({ zoomFactor: newZoomFactor });
Copy link
Member

@Vendicated Vendicated May 23, 2024

Choose a reason for hiding this comment

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

setData changes the entire underlying settings data. this will effectively reset all settings. what you instead want is to set the property on store

Suggested change
Settings.setData({ zoomFactor: newZoomFactor });
Settings.store.zoomFactor = newZoomFactor;

there are more locations with the same error, those also need fixing

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);
Expand All @@ -453,6 +484,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();
Expand All @@ -470,6 +503,32 @@ export async function createWindows() {
mainWin!.maximize();
}
});

mainWin.on("focus", () => {
Copy link
Member

Choose a reason for hiding this comment

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

this is a really bad way to do this. why not use menu items with accelerators like previously?

Copy link
Author

Choose a reason for hiding this comment

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

Because it refused to work with the menu items after hours of trying. If anyone is able to get it working that way instead that would be super helpful

Copy link
Member

Choose a reason for hiding this comment

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

it works very much the same. did you maybe forget to remove the default zoom handlers? they might take priority over your accelerators

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+_");
});
});

initArRPC();
Expand Down
3 changes: 2 additions & 1 deletion src/preload/VesktopNative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ export const VesktopNative = {
focus: () => invoke<void>(IpcEvents.FOCUS),
close: (key?: string) => invoke<void>(IpcEvents.CLOSE, key),
minimize: () => invoke<void>(IpcEvents.MINIMIZE),
maximize: () => invoke<void>(IpcEvents.MAXIMIZE)
maximize: () => invoke<void>(IpcEvents.MAXIMIZE),
zoom: (zoom: number) => invoke<void>(IpcEvents.SET_ZOOM, zoom)
},
capturer: {
getLargeThumbnail: (id: string) => invoke<string>(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id)
Expand Down
4 changes: 4 additions & 0 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
47 changes: 46 additions & 1 deletion src/renderer/components/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@
import "./settings.css";

import { Margins } from "@vencord/types/utils";
import { Button, Forms, Select, Switch, Text, Toasts, useState } from "@vencord/types/webpack/common";
import {
Button,
Forms,
Select,
Slider,
Switch,
Text,
Toasts,
useEffect,
useState
} from "@vencord/types/webpack/common";
import { setBadge } from "renderer/appBadge";
import { useSettings } from "renderer/settings";
import { isMac } from "renderer/utils";
Expand All @@ -19,6 +29,20 @@ export default function SettingsUi() {

const { autostart } = VesktopNative;
const [autoStartEnabled, setAutoStartEnabled] = useState(autostart.isEnabled());
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);
};
}, []);

const allSwitches: Array<false | [keyof typeof Settings, string, string, boolean?, (() => boolean)?]> = [
[
Expand Down Expand Up @@ -153,6 +177,27 @@ export default function SettingsUi() {
</>
)}

<>
<Forms.FormTitle className={Margins.top16 + " " + Margins.bottom8}>Zoom Level</Forms.FormTitle>
<Slider
className={Margins.top20}
initialValue={zoomFactor}
defaultValue={1}
onValueChange={v => {
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)}`)}
></Slider>
</>

<Forms.FormDivider className={Margins.top16 + " " + Margins.bottom16} />

<Forms.FormTitle>Vencord Location</Forms.FormTitle>
<Forms.FormText>
Vencord files are loaded from{" "}
Expand Down
1 change: 1 addition & 0 deletions src/shared/IpcEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const enum IpcEvents {
FOCUS = "VCD_FOCUS",
MINIMIZE = "VCD_MINIMIZE",
MAXIMIZE = "VCD_MAXIMIZE",
SET_ZOOM = "VCD_ZOOM",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
SET_ZOOM = "VCD_ZOOM",
SET_ZOOM = "VCD_SET_ZOOM",


SHOW_ITEM_IN_FOLDER = "VCD_SHOW_ITEM_IN_FOLDER",
GET_SETTINGS = "VCD_GET_SETTINGS",
Expand Down
1 change: 1 addition & 0 deletions src/shared/settings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface Settings {
arRPC?: boolean;
appBadge?: boolean;
disableMinSize?: boolean;
zoomFactor?: number;
Copy link
Member

Choose a reason for hiding this comment

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

wouldn't this make a lot more sense in State than in Settings?

Copy link
Author

Choose a reason for hiding this comment

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

Then how would it persist after restarting?

Copy link
Member

Choose a reason for hiding this comment

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

state is also persisted!


/** @deprecated use customTitleBar */
discordWindowsTitleBar?: boolean;
Expand Down