From 3108de7c79e3fd3fef1f0d1f51a428687dbb8e0d Mon Sep 17 00:00:00 2001 From: V Date: Mon, 7 Aug 2023 00:23:27 +0200 Subject: [PATCH] Port Discord's windows title bar (#86) --- src/main/ipc.ts | 14 ++++++++++- src/main/mainWindow.ts | 7 ++++-- src/preload/VesktopNative.ts | 5 +++- src/renderer/components/Settings.tsx | 13 ++++++---- src/renderer/patches/index.ts | 1 + src/renderer/patches/platformClass.tsx | 9 ++++++- src/renderer/patches/windowsTitleBar.tsx | 30 ++++++++++++++++++++++++ src/shared/IpcEvents.ts | 2 ++ src/shared/settings.d.ts | 16 +++++++------ 9 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 src/renderer/patches/windowsTitleBar.tsx diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 648c34c..d52a243 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -73,7 +73,19 @@ ipcMain.handle(IpcEvents.FOCUS, () => { }); ipcMain.handle(IpcEvents.CLOSE, e => { - e.sender.close(); + mainWin.close(); +}); + +ipcMain.handle(IpcEvents.MINIMIZE, e => { + mainWin.minimize(); +}); + +ipcMain.handle(IpcEvents.MAXIMIZE, e => { + if (mainWin.isMaximized()) { + mainWin.unmaximize(); + } else { + mainWin.maximize(); + } }); ipcMain.handle(IpcEvents.SPELLCHECK_SET_LANGUAGES, (_, languages: string[]) => { diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 279daba..aab75de 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -315,8 +315,11 @@ function createMainWindow() { removeSettingsListeners(); removeVencordSettingsListeners(); - const { staticTitle, transparencyOption, enableMenu } = Settings.store; + const { staticTitle, transparencyOption, enableMenu, discordWindowsTitleBar } = Settings.store; const { frameless, macosTranslucency } = VencordSettings.store; + + const noFrame = frameless === true || (process.platform === "win32" && discordWindowsTitleBar === true); + const win = (mainWin = new BrowserWindow({ show: false, webPreferences: { @@ -328,7 +331,7 @@ function createMainWindow() { spellcheck: true }, icon: ICON_PATH, - frame: frameless !== true, + frame: !noFrame, ...(transparencyOption && transparencyOption !== "none" ? { backgroundColor: "#00000000", diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index 6a4415a..1706bed 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -51,7 +51,10 @@ export const VesktopNative = { addToDictionary: (word: string) => invoke(IpcEvents.SPELLCHECK_ADD_TO_DICTIONARY, word) }, win: { - focus: () => invoke(IpcEvents.FOCUS) + focus: () => invoke(IpcEvents.FOCUS), + close: () => invoke(IpcEvents.CLOSE), + minimize: () => invoke(IpcEvents.MINIMIZE), + maximize: () => invoke(IpcEvents.MAXIMIZE) }, capturer: { getLargeThumbnail: (id: string) => invoke(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id) diff --git a/src/renderer/components/Settings.tsx b/src/renderer/components/Settings.tsx index 14b33c8..c712350 100644 --- a/src/renderer/components/Settings.tsx +++ b/src/renderer/components/Settings.tsx @@ -10,7 +10,7 @@ import { Margins } from "@vencord/types/utils"; import { Button, Forms, Select, Switch, Text, useState } from "@vencord/types/webpack/common"; import { setBadge } from "renderer/appBadge"; import { useSettings } from "renderer/settings"; -import { isMac } from "renderer/utils"; +import { isMac, isWindows } from "renderer/utils"; import { isTruthy } from "shared/utils/guards"; export default function SettingsUi() { @@ -21,6 +21,11 @@ export default function SettingsUi() { const [autoStartEnabled, setAutoStartEnabled] = useState(autostart.isEnabled()); const allSwitches: Array boolean)?]> = [ + isWindows && [ + "discordWindowsTitleBar", + "Discord Titlebar", + "Use Discord's custom title bar instead of the Windows one. Requires a full restart." + ], !isMac && ["tray", "Tray Icon", "Add a tray icon for Vesktop", true], !isMac && [ "minimizeToTray", @@ -35,13 +40,13 @@ export default function SettingsUi() { "Disable minimum window size", "Allows you to make the window as small as your heart desires" ], + ["staticTitle", "Static Title", 'Makes the window title "Vesktop" instead of changing to the current page'], + ["enableMenu", "Enable Menu Bar", "Enables the application menu bar. Press ALT to toggle visibility."], [ "openLinksWithElectron", "Open Links in app (experimental)", "Opens links in a new Vesktop window instead of your web browser" - ], - ["staticTitle", "Static Title", 'Makes the window title "Vesktop" instead of changing to the current page'], - ["enableMenu", "Enable Menu Bar", "Enables the application menu bar. Press ALT to toggle visibility."] + ] ]; const switches = allSwitches.filter(isTruthy); diff --git a/src/renderer/patches/index.ts b/src/renderer/patches/index.ts index d2bd536..e33c00f 100644 --- a/src/renderer/patches/index.ts +++ b/src/renderer/patches/index.ts @@ -7,3 +7,4 @@ // TODO: Possibly auto generate glob if we have more patches in the future import "./spellCheck"; import "./platformClass"; +import "./windowsTitleBar"; diff --git a/src/renderer/patches/platformClass.tsx b/src/renderer/patches/platformClass.tsx index da71127..5605ab8 100644 --- a/src/renderer/patches/platformClass.tsx +++ b/src/renderer/patches/platformClass.tsx @@ -4,6 +4,9 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ +import { Settings } from "renderer/settings"; +import { isMac, isWindows } from "renderer/utils"; + import { addPatch } from "./shared"; addPatch({ @@ -18,5 +21,9 @@ addPatch({ } ], - getPlatformClass: () => (navigator.platform.toLowerCase().startsWith("mac") ? "platform-osx" : "platform-web") + getPlatformClass() { + if (isMac) return "platform-osx"; + if (isWindows && Settings.store.discordWindowsTitleBar) return "platform-windows"; + return "platform-web"; + } }); diff --git a/src/renderer/patches/windowsTitleBar.tsx b/src/renderer/patches/windowsTitleBar.tsx new file mode 100644 index 0000000..708ec60 --- /dev/null +++ b/src/renderer/patches/windowsTitleBar.tsx @@ -0,0 +1,30 @@ +/* + * 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 { Settings } from "renderer/settings"; + +import { addPatch } from "./shared"; + +if (Settings.store.discordWindowsTitleBar) + addPatch({ + patches: [ + { + find: ".wordmarkWindows", + replacement: [ + { + // TODO: Fix eslint rule + // eslint-disable-next-line no-useless-escape + match: /case \i\.\i\.WINDOWS:/, + replace: 'case "WEB":' + }, + ...["close", "minimize", "maximize"].map(op => ({ + match: new RegExp(String.raw`\i\.default\.${op}\b`), + replace: `VesktopNative.win.${op}` + })) + ] + } + ] + }); diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index 3a171ec..2d453e3 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -16,6 +16,8 @@ export const enum IpcEvents { RELAUNCH = "VCD_RELAUNCH", CLOSE = "VCD_CLOSE", FOCUS = "VCD_FOCUS", + MINIMIZE = "VCD_MINIMIZE", + MAXIMIZE = "VCD_MAXIMIZE", 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 e387351..a9a0dec 100644 --- a/src/shared/settings.d.ts +++ b/src/shared/settings.d.ts @@ -7,21 +7,23 @@ import type { Rectangle } from "electron"; export interface Settings { - transparencyOption?: "none" | "mica" | "tabbed" | "acrylic"; - maximized?: boolean; - minimized?: boolean; - windowBounds?: Rectangle; discordBranch?: "stable" | "canary" | "ptb"; - openLinksWithElectron?: boolean; vencordDir?: string; - disableMinSize?: boolean; + transparencyOption?: "none" | "mica" | "tabbed" | "acrylic"; tray?: boolean; minimizeToTray?: boolean; - skippedUpdate?: string; + openLinksWithElectron?: boolean; staticTitle?: boolean; enableMenu?: boolean; arRPC?: boolean; appBadge?: boolean; + discordWindowsTitleBar?: boolean; + maximized?: boolean; + minimized?: boolean; + windowBounds?: Rectangle; + disableMinSize?: boolean; + + skippedUpdate?: string; firstLaunch?: boolean; }