From b166253fe32f1167c85ae93f9188a9b7c5528e6b Mon Sep 17 00:00:00 2001 From: EastArctica Date: Fri, 21 Jul 2023 22:03:32 -0400 Subject: [PATCH 01/39] Add transparent window feature --- src/main/index.ts | 23 ++++++++++++++++++- .../coremods/settings/pages/General.tsx | 6 +++++ src/types/settings.ts | 2 ++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/index.ts b/src/main/index.ts index 4a2098744..25ba7ff6e 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,9 +1,24 @@ +import { readFileSync } from "fs"; import { dirname, join } from "path"; - import electron from "electron"; import type { RepluggedWebContents } from "../types"; import { CONFIG_PATHS } from "src/util.mjs"; +// TODO: This shouldn't be here, it should be in it's own module +// like src/main/ipc/settings.ts, except that's specifically for +// ipc transactions(which are async); So not there. Perhaps +// it should be in util? +const SETTINGS_DIR = CONFIG_PATHS.settings; +function readSettingsSync(namespace: string): Map { + try { + const data = readFileSync(join(SETTINGS_DIR, `${namespace}.json`), "utf8"); + return new Map(Object.entries(JSON.parse(data))); + } catch { + return new Map(); + } +} +const settings = readSettingsSync("dev.replugged.Settings"); + const electronPath = require.resolve("electron"); const discordPath = join(dirname(require.main!.filename), "..", "app.orig.asar"); // require.main!.filename = discordMain; @@ -50,6 +65,12 @@ class BrowserWindow extends electron.BrowserWindow { // Discord Client opts.webPreferences.preload = join(__dirname, "./preload.js"); // opts.webPreferences.contextIsolation = false; // shrug + + if (settings.get("transparentWindow")) { + opts.transparent = true; + opts.frame = process.platform === "win32" ? false : opts.frame; + delete opts.backgroundColor; + } } else { // Splash Screen on macOS (Host 0.0.262+) & Windows (Host 0.0.293 / 1.0.17+) // opts.webPreferences.preload = join(__dirname, './preloadSplash.js'); diff --git a/src/renderer/coremods/settings/pages/General.tsx b/src/renderer/coremods/settings/pages/General.tsx index 0d79a97e5..47047d1ea 100644 --- a/src/renderer/coremods/settings/pages/General.tsx +++ b/src/renderer/coremods/settings/pages/General.tsx @@ -113,6 +113,12 @@ export const General = (): React.ReactElement => { {Messages.REPLUGGED_SETTINGS_QUICKCSS_AUTO_APPLY} + + {Messages.REPLUGGED_SETTINGS_TRANSPARENT} + + = { @@ -21,4 +22,5 @@ export const defaultSettings: Partial = { badges: true, autoApplyQuickCss: false, showWelcomeNoticeOnOpen: true, + transparentWindow: false, }; From 0fb2d3bcdf4bebee250a1e9c2d28e106b9656b69 Mon Sep 17 00:00:00 2001 From: EastArctica Date: Tue, 22 Aug 2023 14:15:25 -0400 Subject: [PATCH 02/39] Require discord restart for transparency change --- src/renderer/coremods/settings/pages/General.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/renderer/coremods/settings/pages/General.tsx b/src/renderer/coremods/settings/pages/General.tsx index cdbad1062..aeebb1188 100644 --- a/src/renderer/coremods/settings/pages/General.tsx +++ b/src/renderer/coremods/settings/pages/General.tsx @@ -55,6 +55,10 @@ export const General = (): React.ReactElement => { generalSettings, "reactDevTools", ); + const { value: transValue, onChange: transOnChange } = util.useSetting( + generalSettings, + "transparentWindow", + ); const [kKeys, setKKeys] = React.useState([]); @@ -175,7 +179,11 @@ export const General = (): React.ReactElement => { { + transOnChange(value); + restartModal(true); + }} note={Messages.REPLUGGED_SETTINGS_TRANSPARENT_DESC}> {Messages.REPLUGGED_SETTINGS_TRANSPARENT} From 71a57e879cfe761852f60a62a3b63dd4fbf04f84 Mon Sep 17 00:00:00 2001 From: EastArctica Date: Tue, 22 Aug 2023 16:48:29 -0400 Subject: [PATCH 03/39] Move transparency button --- .../coremods/settings/pages/General.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/renderer/coremods/settings/pages/General.tsx b/src/renderer/coremods/settings/pages/General.tsx index aeebb1188..3934aa880 100644 --- a/src/renderer/coremods/settings/pages/General.tsx +++ b/src/renderer/coremods/settings/pages/General.tsx @@ -118,6 +118,16 @@ export const General = (): React.ReactElement => { {Messages.REPLUGGED_SETTINGS_QUICKCSS_AUTO_APPLY} + { + transOnChange(value); + restartModal(true); + }} + note={Messages.REPLUGGED_SETTINGS_TRANSPARENT_DESC}> + {Messages.REPLUGGED_SETTINGS_TRANSPARENT} + + @@ -177,16 +187,6 @@ export const General = (): React.ReactElement => { }}> {Messages.REPLUGGED_SETTINGS_DEV_COMPANION} - - { - transOnChange(value); - restartModal(true); - }} - note={Messages.REPLUGGED_SETTINGS_TRANSPARENT_DESC}> - {Messages.REPLUGGED_SETTINGS_TRANSPARENT} - {/* Sleeping? Wake up. */} From 895e002e5f5139daedbb443e29bbf9c03e149ddb Mon Sep 17 00:00:00 2001 From: EastArctica Date: Tue, 22 Aug 2023 16:57:44 -0400 Subject: [PATCH 04/39] move readSettingsSync to src/util.mts --- src/main/index.ts | 17 +---------------- src/util.mts | 12 +++++++++++- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 80c49d7c2..7b5b75ca0 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,25 +1,10 @@ -import { readFileSync } from "fs"; import { dirname, join } from "path"; import electron from "electron"; -import { CONFIG_PATHS } from "src/util.mjs"; +import { CONFIG_PATHS, readSettingsSync } from "src/util.mjs"; import type { RepluggedWebContents } from "../types"; import { getSetting } from "./ipc/settings"; -// TODO: This shouldn't be here, it should be in it's own module -// like src/main/ipc/settings.ts, except that's specifically for -// ipc transactions(which are async); So not there. Perhaps -// it should be in util? -const SETTINGS_DIR = CONFIG_PATHS.settings; -function readSettingsSync(namespace: string): Map { - try { - const data = readFileSync(join(SETTINGS_DIR, `${namespace}.json`), "utf8"); - return new Map(Object.entries(JSON.parse(data))); - } catch { - return new Map(); - } -} const settings = readSettingsSync("dev.replugged.Settings"); - const electronPath = require.resolve("electron"); const discordPath = join(dirname(require.main!.filename), "..", "app.orig.asar"); // require.main!.filename = discordMain; diff --git a/src/util.mts b/src/util.mts index 1fe485cd7..299b9d642 100644 --- a/src/util.mts +++ b/src/util.mts @@ -1,5 +1,5 @@ import { execSync } from "child_process"; -import { chownSync, existsSync, mkdirSync, statSync, writeFileSync } from "fs"; +import { chownSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs"; import { join } from "path"; const REPLUGGED_FOLDER_NAME = "replugged"; @@ -79,3 +79,13 @@ if (!existsSync(QUICK_CSS_FILE)) { chownSync(QUICK_CSS_FILE, REAL_UID, REAL_GID); } } + +const SETTINGS_DIR = CONFIG_PATHS.settings; +export function readSettingsSync(namespace: string): Map { + try { + const data = readFileSync(join(SETTINGS_DIR, `${namespace}.json`), "utf8"); + return new Map(Object.entries(JSON.parse(data))); + } catch { + return new Map(); + } +} From 27e0e9fbd08a670896a2d915692e3648c13708cf Mon Sep 17 00:00:00 2001 From: EastArctica Date: Tue, 22 Aug 2023 23:03:49 -0400 Subject: [PATCH 05/39] At platform specific notices --- src/globals.d.ts | 3 +++ src/renderer/coremods/settings/pages/General.tsx | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/globals.d.ts b/src/globals.d.ts index f40d51cf5..f8ac22a83 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -37,6 +37,9 @@ declare global { paste: () => void; read: () => string; }; + process: { + platform: string; + }; }; export const _: typeof Lodash; diff --git a/src/renderer/coremods/settings/pages/General.tsx b/src/renderer/coremods/settings/pages/General.tsx index 3934aa880..d38713e0f 100644 --- a/src/renderer/coremods/settings/pages/General.tsx +++ b/src/renderer/coremods/settings/pages/General.tsx @@ -7,6 +7,7 @@ import { Divider, Flex, FormItem, + Notice, SwitchItem, Text, TextInput, @@ -118,13 +119,23 @@ export const General = (): React.ReactElement => { {Messages.REPLUGGED_SETTINGS_QUICKCSS_AUTO_APPLY} +
+ {(DiscordNative.process.platform === "linux" || + DiscordNative.process.platform === "win32") && ( + + {DiscordNative.process.platform === "linux" + ? Messages.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_LINUX.format() + : Messages.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_WINDOWS.format()} + + )} +
{ transOnChange(value); restartModal(true); }} - note={Messages.REPLUGGED_SETTINGS_TRANSPARENT_DESC}> + note={Messages.REPLUGGED_SETTINGS_TRANSPARENT_DESC.format()}> {Messages.REPLUGGED_SETTINGS_TRANSPARENT} From db444eb855af1ac7fe402f455948c09558b13faf Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 23 Aug 2023 03:39:06 -0400 Subject: [PATCH 06/39] Fix transparency on Windows --- src/main/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/index.ts b/src/main/index.ts index 7b5b75ca0..a19681eb8 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -55,7 +55,7 @@ class BrowserWindow extends electron.BrowserWindow { if (settings.get("transparentWindow")) { opts.transparent = true; opts.frame = process.platform === "win32" ? false : opts.frame; - delete opts.backgroundColor; + opts.backgroundColor = "#00000000"; } } else { // Splash Screen on macOS (Host 0.0.262+) & Windows (Host 0.0.293 / 1.0.17+) From 4846af3869a3323cbfa1e8bd8ef8e6c52907d13f Mon Sep 17 00:00:00 2001 From: EastArctica Date: Thu, 24 Aug 2023 22:14:59 -0400 Subject: [PATCH 07/39] BrowserWindow rework --- src/main/index.ts | 59 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index a19681eb8..c95f0dd64 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -22,6 +22,37 @@ Object.defineProperty(global, "appSettings", { configurable: true, }); +enum DiscordWindowType { + POP_OUT, + SPLASH_SCREEN, + OVERLAY, + DISCORD_CLIENT, +} + +function windowTypeFromOpts( + opts: electron.BrowserWindowConstructorOptions & { + webContents: electron.WebContents; + webPreferences: { + nativeWindowOpen: boolean; + }; + }, +): DiscordWindowType { + if (opts.webContents) { + return DiscordWindowType.POP_OUT; + } else if (opts.webPreferences?.nodeIntegration) { + return DiscordWindowType.SPLASH_SCREEN; + } else if (opts.webPreferences?.offscreen) { + return DiscordWindowType.OVERLAY; + } else if (opts.webPreferences?.preload) { + if (opts.webPreferences.nativeWindowOpen) { + return DiscordWindowType.DISCORD_CLIENT; + } else { + return DiscordWindowType.SPLASH_SCREEN; + } + } + return opts.webContents; +} + // This class has to be named "BrowserWindow" exactly // https://github.com/discord/electron/blob/13-x-y/lib/browser/api/browser-window.ts#L60-L62 // Thank you, Ven, for pointing this out! @@ -36,30 +67,26 @@ class BrowserWindow extends electron.BrowserWindow { ) { const originalPreload = opts.webPreferences.preload; - if (opts.webContents) { - // General purpose pop-outs used by Discord - } else if (opts.webPreferences?.nodeIntegration) { - // Splash Screen - // opts.webPreferences.preload = join(__dirname, './preloadSplash.js'); - } else if (opts.webPreferences?.offscreen) { - // Overlay - // originalPreload = opts.webPreferences.preload; - // opts.webPreferences.preload = join(__dirname, './preload.js'); - } else if (opts.webPreferences?.preload) { - // originalPreload = opts.webPreferences.preload; - if (opts.webPreferences.nativeWindowOpen) { - // Discord Client + const currentWindow = windowTypeFromOpts(opts); + + switch (currentWindow) { + case DiscordWindowType.DISCORD_CLIENT: { opts.webPreferences.preload = join(__dirname, "./preload.js"); - // opts.webPreferences.contextIsolation = false; // shrug if (settings.get("transparentWindow")) { opts.transparent = true; opts.frame = process.platform === "win32" ? false : opts.frame; opts.backgroundColor = "#00000000"; } - } else { - // Splash Screen on macOS (Host 0.0.262+) & Windows (Host 0.0.293 / 1.0.17+) + break; + } + case DiscordWindowType.SPLASH_SCREEN: { // opts.webPreferences.preload = join(__dirname, './preloadSplash.js'); + break; + } + case DiscordWindowType.OVERLAY: { + // opts.webPreferences.preload = join(__dirname, './preload.js'); + break; } } From c528f007f1872a7fa204547d6697438dac206740 Mon Sep 17 00:00:00 2001 From: EastArctica Date: Thu, 24 Aug 2023 22:15:24 -0400 Subject: [PATCH 08/39] MacOS Auto-Maximize --- src/main/index.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/index.ts b/src/main/index.ts index c95f0dd64..4f60e48e4 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -76,6 +76,7 @@ class BrowserWindow extends electron.BrowserWindow { if (settings.get("transparentWindow")) { opts.transparent = true; opts.frame = process.platform === "win32" ? false : opts.frame; + // TODO: Figure out what background color each OS needs. opts.backgroundColor = "#00000000"; } break; @@ -91,6 +92,20 @@ class BrowserWindow extends electron.BrowserWindow { } super(opts); + + if ( + currentWindow === DiscordWindowType.DISCORD_CLIENT && + settings.get("transparentWindow") && + process.platform === "darwin" + ) { + this.on("ready-to-show", () => { + // TODO: As far as I know, this is only needed on some macOS versions. + // This automatically maximizes the window on all displays the window is dragged to + this.maximize(); + this.setResizable(false); + }); + } + (this.webContents as RepluggedWebContents).originalPreload = originalPreload; } } From f496111cd1cb76d62e966adc7cd96a0e4dadc252 Mon Sep 17 00:00:00 2001 From: EastArctica Date: Fri, 21 Jul 2023 22:03:32 -0400 Subject: [PATCH 09/39] Add transparent window feature Require discord restart for transparency change Move transparency button move readSettingsSync to src/util.mts At platform specific notices Fix transparency on Windows BrowserWindow rework MacOS Auto-Maximize --- src/globals.d.ts | 3 + src/main/index.ts | 86 +++++++++++++++---- .../coremods/settings/pages/General.tsx | 31 +++++++ src/types/settings.ts | 2 + src/util.mts | 12 ++- 5 files changed, 114 insertions(+), 20 deletions(-) diff --git a/src/globals.d.ts b/src/globals.d.ts index f40d51cf5..f8ac22a83 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -37,6 +37,9 @@ declare global { paste: () => void; read: () => string; }; + process: { + platform: string; + }; }; export const _: typeof Lodash; diff --git a/src/main/index.ts b/src/main/index.ts index acbb2dc45..2ed18523e 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,10 +1,10 @@ import { dirname, join } from "path"; - import electron from "electron"; -import { CONFIG_PATHS } from "src/util.mjs"; +import { CONFIG_PATHS, readSettingsSync } from "src/util.mjs"; import type { RepluggedWebContents } from "../types"; import { getSetting } from "./ipc/settings"; +const settings = readSettingsSync("dev.replugged.Settings"); const electronPath = require.resolve("electron"); const discordPath = join(dirname(require.main!.filename), "..", "app.orig.asar"); // require.main!.filename = discordMain; @@ -22,6 +22,37 @@ Object.defineProperty(global, "appSettings", { configurable: true, }); +enum DiscordWindowType { + POP_OUT, + SPLASH_SCREEN, + OVERLAY, + DISCORD_CLIENT, +} + +function windowTypeFromOpts( + opts: electron.BrowserWindowConstructorOptions & { + webContents: electron.WebContents; + webPreferences: { + nativeWindowOpen: boolean; + }; + }, +): DiscordWindowType { + if (opts.webContents) { + return DiscordWindowType.POP_OUT; + } else if (opts.webPreferences?.nodeIntegration) { + return DiscordWindowType.SPLASH_SCREEN; + } else if (opts.webPreferences?.offscreen) { + return DiscordWindowType.OVERLAY; + } else if (opts.webPreferences?.preload) { + if (opts.webPreferences.nativeWindowOpen) { + return DiscordWindowType.DISCORD_CLIENT; + } else { + return DiscordWindowType.SPLASH_SCREEN; + } + } + return opts.webContents; +} + // This class has to be named "BrowserWindow" exactly // https://github.com/discord/electron/blob/13-x-y/lib/browser/api/browser-window.ts#L60-L62 // Thank you, Ven, for pointing this out! @@ -36,28 +67,45 @@ class BrowserWindow extends electron.BrowserWindow { ) { const originalPreload = opts.webPreferences?.preload; - if (opts.webContents) { - // General purpose pop-outs used by Discord - } else if (opts.webPreferences?.nodeIntegration) { - // Splash Screen - // opts.webPreferences.preload = join(__dirname, './preloadSplash.js'); - } else if (opts.webPreferences?.offscreen) { - // Overlay - // originalPreload = opts.webPreferences.preload; - // opts.webPreferences.preload = join(__dirname, './preload.js'); - } else if (opts.webPreferences?.preload) { - // originalPreload = opts.webPreferences.preload; - if (opts.webPreferences.nativeWindowOpen) { - // Discord Client - opts.webPreferences.preload = join(__dirname, "./preload.js"); - // opts.webPreferences.contextIsolation = false; // shrug - } else { - // Splash Screen on macOS (Host 0.0.262+) & Windows (Host 0.0.293 / 1.0.17+) + const currentWindow = windowTypeFromOpts(opts); + + switch (currentWindow) { + case DiscordWindowType.DISCORD_CLIENT: { opts.webPreferences.preload = join(__dirname, "./preload.js"); + + if (settings.get("transparentWindow")) { + opts.transparent = true; + opts.frame = process.platform === "win32" ? false : opts.frame; + // TODO: Figure out what background color each OS needs. + opts.backgroundColor = "#00000000"; + } + break; + } + case DiscordWindowType.SPLASH_SCREEN: { + // opts.webPreferences.preload = join(__dirname, "./preloadSplash.js"); + break; + } + case DiscordWindowType.OVERLAY: { + // opts.webPreferences.preload = join(__dirname, "./preload.js"); + break; } } super(opts); + + if ( + currentWindow === DiscordWindowType.DISCORD_CLIENT && + settings.get("transparentWindow") && + process.platform === "darwin" + ) { + this.on("ready-to-show", () => { + // TODO: As far as I know, this is only needed on some macOS versions. + // This automatically maximizes the window on all displays the window is dragged to + this.maximize(); + this.setResizable(false); + }); + } + (this.webContents as RepluggedWebContents).originalPreload = originalPreload; } } diff --git a/src/renderer/coremods/settings/pages/General.tsx b/src/renderer/coremods/settings/pages/General.tsx index daf6165f8..8f2f123c1 100644 --- a/src/renderer/coremods/settings/pages/General.tsx +++ b/src/renderer/coremods/settings/pages/General.tsx @@ -7,6 +7,7 @@ import { Divider, Flex, FormItem, + Notice, SwitchItem, Text, TextInput, @@ -55,6 +56,10 @@ export const General = (): React.ReactElement => { generalSettings, "reactDevTools", ); + const { value: transValue, onChange: transOnChange } = util.useSetting( + generalSettings, + "transparentWindow", + ); const [kKeys, setKKeys] = React.useState([]); @@ -114,6 +119,26 @@ export const General = (): React.ReactElement => { {Messages.REPLUGGED_SETTINGS_QUICKCSS_AUTO_APPLY} +
+ {(DiscordNative.process.platform === "linux" || + DiscordNative.process.platform === "win32") && ( + + {DiscordNative.process.platform === "linux" + ? Messages.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_LINUX.format() + : Messages.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_WINDOWS.format()} + + )} +
+ { + transOnChange(value); + restartModal(true); + }} + note={Messages.REPLUGGED_SETTINGS_TRANSPARENT_DESC.format()}> + {Messages.REPLUGGED_SETTINGS_TRANSPARENT} + + @@ -165,6 +190,12 @@ export const General = (): React.ReactElement => { {Messages.REPLUGGED_SETTINGS_REACT_DEVTOOLS} + + {Messages.REPLUGGED_SETTINGS_TRANSPARENT} + + ; diff --git a/src/util.mts b/src/util.mts index 99a1f8a85..ce621290b 100644 --- a/src/util.mts +++ b/src/util.mts @@ -1,6 +1,6 @@ import esbuild from "esbuild"; import { execSync } from "child_process"; -import { chownSync, existsSync, mkdirSync, statSync, writeFileSync } from "fs"; +import { chownSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs"; import path, { join } from "path"; import chalk from "chalk"; @@ -145,3 +145,13 @@ export const logBuildPlugin: esbuild.Plugin = { }); }, }; + +const SETTINGS_DIR = CONFIG_PATHS.settings; +export function readSettingsSync(namespace: string): Map { + try { + const data = readFileSync(join(SETTINGS_DIR, `${namespace}.json`), "utf8"); + return new Map(Object.entries(JSON.parse(data))); + } catch { + return new Map(); + } +} From f57657aee8a4580b342eb0de7ffeb131487c1ed0 Mon Sep 17 00:00:00 2001 From: EastArctica Date: Wed, 31 Jan 2024 15:01:42 -0500 Subject: [PATCH 10/39] I'm impressively bad at rebasing --- src/main/index.ts | 31 ------------------------------- src/types/settings.ts | 1 - 2 files changed, 32 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 1618a7a7e..697dc7986 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -53,37 +53,6 @@ function windowTypeFromOpts( return opts.webContents; } -enum DiscordWindowType { - POP_OUT, - SPLASH_SCREEN, - OVERLAY, - DISCORD_CLIENT, -} - -function windowTypeFromOpts( - opts: electron.BrowserWindowConstructorOptions & { - webContents: electron.WebContents; - webPreferences: { - nativeWindowOpen: boolean; - }; - }, -): DiscordWindowType { - if (opts.webContents) { - return DiscordWindowType.POP_OUT; - } else if (opts.webPreferences?.nodeIntegration) { - return DiscordWindowType.SPLASH_SCREEN; - } else if (opts.webPreferences?.offscreen) { - return DiscordWindowType.OVERLAY; - } else if (opts.webPreferences?.preload) { - if (opts.webPreferences.nativeWindowOpen) { - return DiscordWindowType.DISCORD_CLIENT; - } else { - return DiscordWindowType.SPLASH_SCREEN; - } - } - return opts.webContents; -} - // This class has to be named "BrowserWindow" exactly // https://github.com/discord/electron/blob/13-x-y/lib/browser/api/browser-window.ts#L60-L62 // Thank you, Ven, for pointing this out! diff --git a/src/types/settings.ts b/src/types/settings.ts index 70d3b5d35..127da0c77 100644 --- a/src/types/settings.ts +++ b/src/types/settings.ts @@ -25,5 +25,4 @@ export const defaultSettings = { transparentWindow: false, reactDevTools: false, addonEmbeds: true, - transparentWindow: false, } satisfies Partial; From f0b6a475f5ecfee6e4919f9eb9b9612d51626a6e Mon Sep 17 00:00:00 2001 From: EastArctica Date: Sun, 4 Feb 2024 15:33:42 -0500 Subject: [PATCH 11/39] Add vibe for transparency --- package.json | 3 +- pnpm-lock.yaml | 246 ++++++++++++++++++++++++++++++++++++++++------ scripts/build.mts | 5 +- src/main/index.ts | 31 ++---- src/vibe.node | Bin 0 -> 188928 bytes 5 files changed, 229 insertions(+), 56 deletions(-) create mode 100644 src/vibe.node diff --git a/package.json b/package.json index 3568361c5..bb3cb6692 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@electron/asar": "^3.2.7", "@lezer/highlight": "^1.1.6", "@octokit/rest": "^20.0.2", + "@pyke/vibe": "^0.4.0", "adm-zip": "^0.5.10", "chalk": "^5.3.0", "codemirror": "^6.0.1", @@ -106,4 +107,4 @@ "semver@<7.5.2": ">=7.5.2" } } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d4ad3d15..8fe294107 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: '@octokit/rest': specifier: ^20.0.2 version: 20.0.2 + '@pyke/vibe': + specifier: ^0.4.0 + version: 0.4.0(electron@28.2.1) adm-zip: specifier: ^0.5.10 version: 0.5.10 @@ -582,6 +585,23 @@ packages: minimatch: 3.1.2 dev: false + /@electron/get@2.0.3: + resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} + engines: {node: '>=12'} + dependencies: + debug: 4.3.4 + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 11.8.6 + progress: 2.0.3 + semver: 7.5.4 + sumchecker: 3.0.1 + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: false + /@esbuild/android-arm64@0.18.20: resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -1209,6 +1229,16 @@ packages: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 + /@pyke/vibe@0.4.0(electron@28.2.1): + resolution: {integrity: sha512-EUfoGqglwpuTuL3/lBq1eWzOL1HE9XwkDXvsq8mwSSGrw3lFCzKL2dyD/NFBiobjqIqN93ut45gRS51LbE0gpw==} + requiresBuild: true + peerDependencies: + electron: '>=11.0' + dependencies: + cargo-cp-artifact: 0.1.8 + electron: 28.2.1 + dev: false + /@samverschueren/stream-to-observable@0.3.1(rxjs@6.6.7): resolution: {integrity: sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==} engines: {node: '>=6'} @@ -1230,7 +1260,6 @@ packages: /@sindresorhus/is@4.6.0: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} - dev: true /@sindresorhus/is@5.6.0: resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} @@ -1241,7 +1270,6 @@ packages: engines: {node: '>=10'} dependencies: defer-to-connect: 2.0.1 - dev: true /@szmarczak/http-timer@5.0.1: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} @@ -1262,7 +1290,6 @@ packages: '@types/keyv': 3.1.4 '@types/node': 18.18.6 '@types/responselike': 1.0.2 - dev: true /@types/configstore@6.0.1: resolution: {integrity: sha512-ML2U2xzN6PwCh1I6QgWI3TdzS7CRLsv5DSCLX4/Wfg+f30JF60WgS9ZbVOOrTk+N67WTCSUKm6Q7k6M/BjbXQw==} @@ -1287,7 +1314,6 @@ packages: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: '@types/node': 18.18.6 - dev: true /@types/lodash@4.14.200: resolution: {integrity: sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==} @@ -1342,7 +1368,6 @@ packages: resolution: {integrity: sha512-/4YQT5Kp6HxUDb4yhRkm0bJ7TbjvTddqX7PZ5hz6qV3pxSo72f/6YPRo+Mu2DU307tm9IioO69l7uAwn5XNcFA==} dependencies: '@types/node': 18.18.6 - dev: true /@types/scheduler@0.16.5: resolution: {integrity: sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==} @@ -1382,6 +1407,14 @@ packages: '@types/yargs-parser': 21.0.2 dev: true + /@types/yauzl@2.10.3: + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + requiresBuild: true + dependencies: + '@types/node': 18.18.6 + dev: false + optional: true + /@typescript-eslint/eslint-plugin@6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2): resolution: {integrity: sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1770,6 +1803,12 @@ packages: readable-stream: 3.6.2 dev: true + /boolean@3.2.0: + resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} + requiresBuild: true + dev: false + optional: true + /boxen@7.1.1: resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} engines: {node: '>=14.16'} @@ -1808,6 +1847,10 @@ packages: dependencies: fill-range: 7.0.1 + /buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: false + /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: false @@ -1833,7 +1876,6 @@ packages: /cacheable-lookup@5.0.4: resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} engines: {node: '>=10.6.0'} - dev: true /cacheable-lookup@7.0.0: resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} @@ -1862,7 +1904,6 @@ packages: lowercase-keys: 2.0.0 normalize-url: 6.1.0 responselike: 2.0.1 - dev: true /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} @@ -1885,6 +1926,11 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} + /cargo-cp-artifact@0.1.8: + resolution: {integrity: sha512-3j4DaoTrsCD1MRkTF2Soacii0Nx7UHCce0EwUf4fHnggwiE4fbmF2AbnfzayR36DF8KGadfh7M/Yfy625kgPlA==} + hasBin: true + dev: false + /chalk-template@1.1.0: resolution: {integrity: sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==} engines: {node: '>=14.16'} @@ -2020,7 +2066,6 @@ packages: resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} dependencies: mimic-response: 1.0.1 - dev: true /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} @@ -2301,7 +2346,6 @@ packages: optional: true dependencies: ms: 2.1.2 - dev: true /decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} @@ -2352,7 +2396,6 @@ packages: get-intrinsic: 1.2.1 gopd: 1.0.1 has-property-descriptors: 1.0.0 - dev: true /define-lazy-prop@3.0.0: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} @@ -2366,7 +2409,6 @@ packages: define-data-property: 1.1.1 has-property-descriptors: 1.0.0 object-keys: 1.1.1 - dev: true /del@7.1.0: resolution: {integrity: sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==} @@ -2386,6 +2428,12 @@ packages: resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} dev: false + /detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + requiresBuild: true + dev: false + optional: true + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -2430,6 +2478,19 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + /electron@28.2.1: + resolution: {integrity: sha512-wlzXf+OvOiVlBf9dcSeMMf7Q+N6DG+wtgFbMK0sA/JpIJcdosRbLMQwLg/LTwNVKIbmayqFLDp4FmmFkEMhbYA==} + engines: {node: '>= 12.20.55'} + hasBin: true + requiresBuild: true + dependencies: + '@electron/get': 2.0.3 + '@types/node': 18.18.6 + extract-zip: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + /elegant-spinner@1.0.1: resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} engines: {node: '>=0.10.0'} @@ -2445,7 +2506,11 @@ packages: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: once: 1.4.0 - dev: true + + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: false /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -2541,6 +2606,12 @@ packages: is-symbol: 1.0.4 dev: true + /es6-error@4.1.1: + resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + requiresBuild: true + dev: false + optional: true + /esbuild-sass-plugin@2.16.0(esbuild@0.19.5): resolution: {integrity: sha512-mGCe9MxNYvZ+j77Q/QFO+rwUGA36mojDXkOhtVmoyz1zwYbMaNrtVrmXwwYDleS/UMKTNU3kXuiTtPiAD3K+Pw==} peerDependencies: @@ -2628,7 +2699,6 @@ packages: /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - dev: true /escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} @@ -2845,6 +2915,20 @@ packages: tmp: 0.0.33 dev: true + /extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + dependencies: + debug: 4.3.4 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + dev: false + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2883,6 +2967,12 @@ packages: reusify: 1.0.4 dev: true + /fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + dependencies: + pend: 1.2.0 + dev: false + /fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -2995,6 +3085,15 @@ packages: fetch-blob: 3.2.0 dev: false + /fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: false + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -3008,7 +3107,6 @@ packages: /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true /function.prototype.name@1.1.6: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} @@ -3041,7 +3139,6 @@ packages: has: 1.0.4 has-proto: 1.0.1 has-symbols: 1.0.3 - dev: true /get-stdin@9.0.0: resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} @@ -3053,7 +3150,6 @@ packages: engines: {node: '>=8'} dependencies: pump: 3.0.0 - dev: true /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} @@ -3100,6 +3196,20 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 + /global-agent@3.0.0: + resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} + engines: {node: '>=10.0'} + requiresBuild: true + dependencies: + boolean: 3.2.0 + es6-error: 4.1.1 + matcher: 3.0.0 + roarr: 2.15.4 + semver: 7.5.4 + serialize-error: 7.0.1 + dev: false + optional: true + /global-dirs@3.0.1: resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} engines: {node: '>=10'} @@ -3118,7 +3228,6 @@ packages: engines: {node: '>= 0.4'} dependencies: define-properties: 1.2.1 - dev: true /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -3147,7 +3256,6 @@ packages: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.1 - dev: true /got@11.8.6: resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} @@ -3164,7 +3272,6 @@ packages: lowercase-keys: 2.0.0 p-cancelable: 2.1.1 responselike: 2.0.1 - dev: true /got@12.6.1: resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} @@ -3222,17 +3329,14 @@ packages: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: get-intrinsic: 1.2.1 - dev: true /has-proto@1.0.1: resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} engines: {node: '>= 0.4'} - dev: true /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} - dev: true /has-tostringtag@1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} @@ -3272,7 +3376,6 @@ packages: dependencies: quick-lru: 5.1.1 resolve-alpn: 1.2.1 - dev: true /http2-wrapper@2.2.0: resolution: {integrity: sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==} @@ -3810,10 +3913,22 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + requiresBuild: true + dev: false + optional: true + /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: false + /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -3990,7 +4105,6 @@ packages: /lowercase-keys@2.0.0: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} - dev: true /lowercase-keys@3.0.0: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} @@ -4017,6 +4131,15 @@ packages: hasBin: true dev: true + /matcher@3.0.0: + resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} + engines: {node: '>=10'} + requiresBuild: true + dependencies: + escape-string-regexp: 4.0.0 + dev: false + optional: true + /meow@12.1.1: resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} engines: {node: '>=16.10'} @@ -4057,7 +4180,6 @@ packages: /mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} - dev: true /mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} @@ -4088,7 +4210,6 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true /mute-stream@0.0.7: resolution: {integrity: sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==} @@ -4158,7 +4279,6 @@ packages: /normalize-url@6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} - dev: true /normalize-url@8.0.0: resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} @@ -4258,7 +4378,6 @@ packages: /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - dev: true /object.assign@4.1.4: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} @@ -4391,7 +4510,6 @@ packages: /p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} - dev: true /p-cancelable@3.0.0: resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} @@ -4554,6 +4672,10 @@ packages: engines: {node: '>=8'} dev: true + /pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + dev: false + /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -4586,7 +4708,6 @@ packages: /progress@2.0.3: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} - dev: true /prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} @@ -4612,7 +4733,6 @@ packages: dependencies: end-of-stream: 1.4.4 once: 1.4.0 - dev: true /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} @@ -4792,7 +4912,6 @@ packages: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} dependencies: lowercase-keys: 2.0.0 - dev: true /responselike@3.0.0: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} @@ -4828,6 +4947,20 @@ packages: glob: 7.2.3 dev: true + /roarr@2.15.4: + resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} + engines: {node: '>=8.0'} + requiresBuild: true + dependencies: + boolean: 3.2.0 + detect-node: 2.1.0 + globalthis: 1.0.3 + json-stringify-safe: 5.0.1 + semver-compare: 1.0.0 + sprintf-js: 1.1.3 + dev: false + optional: true + /run-applescript@5.0.0: resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} engines: {node: '>=12'} @@ -4905,6 +5038,12 @@ packages: engines: {node: '>=12'} dev: true + /semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + requiresBuild: true + dev: false + optional: true + /semver-diff@4.0.0: resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} engines: {node: '>=12'} @@ -4918,6 +5057,15 @@ packages: dependencies: lru-cache: 6.0.0 + /serialize-error@7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} + requiresBuild: true + dependencies: + type-fest: 0.13.1 + dev: false + optional: true + /set-function-name@2.0.1: resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} engines: {node: '>= 0.4'} @@ -5023,6 +5171,12 @@ packages: resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} dev: true + /sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + requiresBuild: true + dev: false + optional: true + /standalone-electron-types@1.0.0: resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} dependencies: @@ -5162,6 +5316,15 @@ packages: /style-mod@4.1.0: resolution: {integrity: sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==} + /sumchecker@3.0.1: + resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} + engines: {node: '>= 8.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} @@ -5276,6 +5439,13 @@ packages: prelude-ls: 1.2.1 dev: true + /type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + requiresBuild: true + dev: false + optional: true + /type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -5403,6 +5573,11 @@ packages: resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} dev: false + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: false + /untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} @@ -5647,6 +5822,13 @@ packages: yargs-parser: 21.1.1 dev: false + /yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + dev: false + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/scripts/build.mts b/scripts/build.mts index a879f74c0..c53ce716b 100644 --- a/scripts/build.mts +++ b/scripts/build.mts @@ -84,6 +84,9 @@ const contexts = await Promise.all([ target: `node${NODE_VERSION}`, outfile: `${distDir}/main.js`, external: ["electron", "original-fs"], + loader: { + ".node": "file", + } }), // Preload esbuild.context({ @@ -109,7 +112,7 @@ await Promise.all( if (watch) { await context.watch(); } else { - await context.rebuild().catch(() => {}); + await context.rebuild().catch(() => { }); context.dispose(); } }), diff --git a/src/main/index.ts b/src/main/index.ts index 697dc7986..01d703c6d 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -3,6 +3,9 @@ import electron from "electron"; import { CONFIG_PATHS, readSettingsSync } from "src/util.mjs"; import type { RepluggedWebContents } from "../types"; import { getSetting } from "./ipc/settings"; +import vibePath from "../vibe.node"; +const vibe = require(vibePath) as unknown as typeof import('@pyke/vibe'); +vibe.setup(electron.app); const settings = readSettingsSync("dev.replugged.Settings"); const electronPath = require.resolve("electron"); @@ -74,8 +77,10 @@ class BrowserWindow extends electron.BrowserWindow { opts.webPreferences.preload = join(__dirname, "./preload.js"); if (settings.get("transparentWindow")) { - opts.transparent = true; - opts.frame = process.platform === "win32" ? false : opts.frame; + opts.show = false; + // Menu bar needs to be remade -_- + opts.autoHideMenuBar = true; + // opts.frame = process.platform === "win32" ? false : opts.frame; // TODO: Figure out what background color each OS needs. opts.backgroundColor = "#00000000"; } @@ -95,28 +100,10 @@ class BrowserWindow extends electron.BrowserWindow { if ( currentWindow === DiscordWindowType.DISCORD_CLIENT && - settings.get("transparentWindow") && - process.platform === "darwin" + settings.get("transparentWindow") ) { this.on("ready-to-show", () => { - // TODO: As far as I know, this is only needed on some macOS versions. - // This automatically maximizes the window on all displays the window is dragged to - this.maximize(); - this.setResizable(false); - }); - } - - - if ( - currentWindow === DiscordWindowType.DISCORD_CLIENT && - settings.get("transparentWindow") && - process.platform === "darwin" - ) { - this.on("ready-to-show", () => { - // TODO: As far as I know, this is only needed on some macOS versions. - // This automatically maximizes the window on all displays the window is dragged to - this.maximize(); - this.setResizable(false); + vibe.applyEffect(this, 'acrylic'); }); } diff --git a/src/vibe.node b/src/vibe.node new file mode 100644 index 0000000000000000000000000000000000000000..dd6fbe432e55948d87dd742361755e6731b73ada GIT binary patch literal 188928 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

|`4PY0E2snfjCu(=V;8!;2 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 Date: Sat, 10 Feb 2024 16:19:20 -0500 Subject: [PATCH 12/39] Use unified acrylic and auto set theme + background color --- src/main/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/index.ts b/src/main/index.ts index 01d703c6d..c45fb6e07 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -103,7 +103,9 @@ class BrowserWindow extends electron.BrowserWindow { settings.get("transparentWindow") ) { this.on("ready-to-show", () => { - vibe.applyEffect(this, 'acrylic'); + vibe.applyEffect(this, 'unified-acrylic'); + vibe.forceTheme(this, 'dark'); + this.setBackgroundColor("#00000000"); }); } From bfe5f72f0b7710bf6218885694339a836d96f24c Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Fri, 16 Feb 2024 20:43:53 -0500 Subject: [PATCH 13/39] Add transparency IPC --- src/main/ipc/transparency.ts | 4 ++++ src/preload.ts | 5 +++++ src/types/index.ts | 1 + 3 files changed, 10 insertions(+) create mode 100644 src/main/ipc/transparency.ts diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts new file mode 100644 index 000000000..1ba757bdb --- /dev/null +++ b/src/main/ipc/transparency.ts @@ -0,0 +1,4 @@ +import { ipcMain } from "electron"; +import { RepluggedIpcChannels } from "../../types"; + +ipcMain.handle(RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, () => {}); diff --git a/src/preload.ts b/src/preload.ts index 1a611af16..e68c7ae08 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -108,6 +108,11 @@ const RepluggedNative = { ipcRenderer.invoke(RepluggedIpcChannels.DOWNLOAD_REACT_DEVTOOLS), }, + transparency: { + applyEffect: (): Promise => + ipcRenderer.invoke(RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT), + }, + getVersion: () => version, // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/src/types/index.ts b/src/types/index.ts index e614b2c92..127b92ebf 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -33,6 +33,7 @@ export enum RepluggedIpcChannels { OPEN_QUICKCSS_FOLDER = "REPLUGGED_OPEN_QUICKCSS_FOLDER", GET_REPLUGGED_VERSION = "REPLUGGED_GET_REPLUGGED_VERSION", DOWNLOAD_REACT_DEVTOOLS = "REPLUGGED_DOWNLOAD_REACT_DEVTOOLS", + APPLY_TRANSPARENCY_EFFECT = "REPLUGGED_APPLY_TRANSPARENCY_EFFECT", } export interface RepluggedAnnouncement { From 445e4dfa01aaa11aa65d59903034dfe9ccf20730 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Fri, 16 Feb 2024 20:44:38 -0500 Subject: [PATCH 14/39] Linux support(ish) & Clean up errors --- cspell.json | 3 ++- package.json | 6 +++-- pnpm-lock.yaml | 27 ++++++++++++++++------ src/main/index.ts | 57 +++++++++++++++++++++++++---------------------- 4 files changed, 56 insertions(+), 37 deletions(-) diff --git a/cspell.json b/cspell.json index 2e4895344..606ef70fd 100644 --- a/cspell.json +++ b/cspell.json @@ -67,7 +67,8 @@ "Vendicated", "Webauthn", "weblate", - "XLARGE" + "XLARGE", + "pyke" ], "ignoreWords": [], "import": [], diff --git a/package.json b/package.json index e6f49c0c2..ed95569b6 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,6 @@ "@electron/asar": "^3.2.7", "@lezer/highlight": "^1.1.6", "@octokit/rest": "^20.0.2", - "@pyke/vibe": "^0.4.0", "adm-zip": "^0.5.10", "chalk": "^5.3.0", "codemirror": "^6.0.1", @@ -99,6 +98,9 @@ "yargs": "^17.7.2", "zod": "^3.22.4" }, + "optionalDependencies": { + "@pyke/vibe": "^0.4.0" + }, "bin": { "replugged": "bin.mjs" }, @@ -107,4 +109,4 @@ "semver@<7.5.2": ">=7.5.2" } } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f160dc7ab..17e0f5620 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,9 +29,6 @@ dependencies: '@octokit/rest': specifier: ^20.0.2 version: 20.0.2 - '@pyke/vibe': - specifier: ^0.4.0 - version: 0.4.0(electron@28.2.1) adm-zip: specifier: ^0.5.10 version: 0.5.10 @@ -78,6 +75,11 @@ dependencies: specifier: ^3.22.4 version: 3.22.4 +optionalDependencies: + '@pyke/vibe': + specifier: ^0.4.0 + version: 0.4.0(electron@28.2.1) + devDependencies: '@types/adm-zip': specifier: ^0.5.3 @@ -601,6 +603,7 @@ packages: transitivePeerDependencies: - supports-color dev: false + optional: true /@esbuild/android-arm64@0.18.20: resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} @@ -1238,6 +1241,7 @@ packages: cargo-cp-artifact: 0.1.8 electron: 28.2.1 dev: false + optional: true /@samverschueren/stream-to-observable@0.3.1(rxjs@6.6.7): resolution: {integrity: sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==} @@ -1850,10 +1854,7 @@ packages: /buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} dev: false - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: false + optional: true /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -1929,7 +1930,9 @@ packages: /cargo-cp-artifact@0.1.8: resolution: {integrity: sha512-3j4DaoTrsCD1MRkTF2Soacii0Nx7UHCce0EwUf4fHnggwiE4fbmF2AbnfzayR36DF8KGadfh7M/Yfy625kgPlA==} hasBin: true + requiresBuild: true dev: false + optional: true /chalk-template@1.1.0: resolution: {integrity: sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==} @@ -2490,6 +2493,7 @@ packages: transitivePeerDependencies: - supports-color dev: false + optional: true /elegant-spinner@1.0.1: resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} @@ -2511,6 +2515,7 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} dev: false + optional: true /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -2928,6 +2933,7 @@ packages: transitivePeerDependencies: - supports-color dev: false + optional: true /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2972,6 +2978,7 @@ packages: dependencies: pend: 1.2.0 dev: false + optional: true /fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} @@ -3093,6 +3100,7 @@ packages: jsonfile: 4.0.0 universalify: 0.1.2 dev: false + optional: true /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -3928,6 +3936,7 @@ packages: optionalDependencies: graceful-fs: 4.2.11 dev: false + optional: true /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} @@ -4675,6 +4684,7 @@ packages: /pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} dev: false + optional: true /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -5312,6 +5322,7 @@ packages: transitivePeerDependencies: - supports-color dev: false + optional: true /supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} @@ -5565,6 +5576,7 @@ packages: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} dev: false + optional: true /untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} @@ -5816,6 +5828,7 @@ packages: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 dev: false + optional: true /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} diff --git a/src/main/index.ts b/src/main/index.ts index c45fb6e07..604b24e49 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -3,9 +3,14 @@ import electron from "electron"; import { CONFIG_PATHS, readSettingsSync } from "src/util.mjs"; import type { RepluggedWebContents } from "../types"; import { getSetting } from "./ipc/settings"; +// @ts-expect-error Type defs are obtained through @pyke/vibe import vibePath from "../vibe.node"; -const vibe = require(vibePath) as unknown as typeof import('@pyke/vibe'); -vibe.setup(electron.app); + +let vibe: typeof import("@pyke/vibe"); +if (process.platform === "win32") { + vibe = require(vibePath) as unknown as typeof import("@pyke/vibe"); + vibe.setup(electron.app); +} const settings = readSettingsSync("dev.replugged.Settings"); const electronPath = require.resolve("electron"); @@ -26,20 +31,21 @@ Object.defineProperty(global, "appSettings", { }); enum DiscordWindowType { + UNKNOWN, POP_OUT, SPLASH_SCREEN, OVERLAY, DISCORD_CLIENT, } -function windowTypeFromOpts( - opts: electron.BrowserWindowConstructorOptions & { - webContents: electron.WebContents; - webPreferences: { - nativeWindowOpen: boolean; - }; - }, -): DiscordWindowType { +type InternalBrowserWindowConstructorOptions = electron.BrowserWindowConstructorOptions & { + webContents?: electron.WebContents; + webPreferences?: { + nativeWindowOpen: boolean; + }; +}; + +function windowTypeFromOpts(opts: InternalBrowserWindowConstructorOptions): DiscordWindowType { if (opts.webContents) { return DiscordWindowType.POP_OUT; } else if (opts.webPreferences?.nodeIntegration) { @@ -53,28 +59,22 @@ function windowTypeFromOpts( return DiscordWindowType.SPLASH_SCREEN; } } - return opts.webContents; + + return DiscordWindowType.UNKNOWN; } // This class has to be named "BrowserWindow" exactly // https://github.com/discord/electron/blob/13-x-y/lib/browser/api/browser-window.ts#L60-L62 // Thank you, Ven, for pointing this out! class BrowserWindow extends electron.BrowserWindow { - public constructor( - opts: electron.BrowserWindowConstructorOptions & { - webContents?: electron.WebContents; - webPreferences?: { - nativeWindowOpen: boolean; - }; - }, - ) { + public constructor(opts: InternalBrowserWindowConstructorOptions) { const originalPreload = opts.webPreferences?.preload; const currentWindow = windowTypeFromOpts(opts); switch (currentWindow) { case DiscordWindowType.DISCORD_CLIENT: { - opts.webPreferences.preload = join(__dirname, "./preload.js"); + opts.webPreferences!.preload = join(__dirname, "./preload.js"); if (settings.get("transparentWindow")) { opts.show = false; @@ -82,7 +82,11 @@ class BrowserWindow extends electron.BrowserWindow { opts.autoHideMenuBar = true; // opts.frame = process.platform === "win32" ? false : opts.frame; // TODO: Figure out what background color each OS needs. - opts.backgroundColor = "#00000000"; + opts.backgroundColor = "#0000000"; + + if (process.platform === "linux") { + opts.transparent = true; + } } break; } @@ -98,13 +102,12 @@ class BrowserWindow extends electron.BrowserWindow { super(opts); - if ( - currentWindow === DiscordWindowType.DISCORD_CLIENT && - settings.get("transparentWindow") - ) { + if (currentWindow === DiscordWindowType.DISCORD_CLIENT && settings.get("transparentWindow")) { this.on("ready-to-show", () => { - vibe.applyEffect(this, 'unified-acrylic'); - vibe.forceTheme(this, 'dark'); + if (process.platform === "win32") { + vibe.applyEffect(this, "unified-acrylic"); + vibe.forceTheme(this, "dark"); + } this.setBackgroundColor("#00000000"); }); } From cd70df7977fc03621edb7b2c2ed019256ac00339 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Fri, 16 Feb 2024 20:52:11 -0500 Subject: [PATCH 15/39] Fix Prettier --- scripts/build.mts | 4 ++-- src/renderer/apis/settings.ts | 4 ++-- src/renderer/coremods/commands/commands.ts | 8 ++++---- src/renderer/coremods/commands/index.ts | 4 ++-- src/renderer/coremods/settings/pages/Updater.tsx | 5 +++-- src/renderer/util.ts | 13 +++++++------ 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/scripts/build.mts b/scripts/build.mts index c53ce716b..4762514c7 100644 --- a/scripts/build.mts +++ b/scripts/build.mts @@ -86,7 +86,7 @@ const contexts = await Promise.all([ external: ["electron", "original-fs"], loader: { ".node": "file", - } + }, }), // Preload esbuild.context({ @@ -112,7 +112,7 @@ await Promise.all( if (watch) { await context.watch(); } else { - await context.rebuild().catch(() => { }); + await context.rebuild().catch(() => {}); context.dispose(); } }), diff --git a/src/renderer/apis/settings.ts b/src/renderer/apis/settings.ts index 93708dd52..2cdfd9a51 100644 --- a/src/renderer/apis/settings.ts +++ b/src/renderer/apis/settings.ts @@ -57,8 +57,8 @@ export class SettingsManager, D extends ke ): K extends D ? NonNullable : F extends null | undefined - ? T[K] | undefined - : NonNullable | F { + ? T[K] | undefined + : NonNullable | F { if (typeof this.#settings === "undefined") { throw new Error(`Settings not loaded for namespace ${this.namespace}`); } diff --git a/src/renderer/coremods/commands/commands.ts b/src/renderer/coremods/commands/commands.ts index 7665c1f12..7377fe0f0 100644 --- a/src/renderer/coremods/commands/commands.ts +++ b/src/renderer/coremods/commands/commands.ts @@ -351,8 +351,8 @@ export function loadCommands(): void { listType === "enabled" ? enabledString : listType === "disabled" - ? disabledString - : `${enabledString}\n\n${disabledString}`; + ? disabledString + : `${enabledString}\n\n${disabledString}`; return { send, @@ -383,8 +383,8 @@ export function loadCommands(): void { listType === "enabled" ? enabledString : listType === "disabled" - ? disabledString - : `${enabledString}\n\n${disabledString}`; + ? disabledString + : `${enabledString}\n\n${disabledString}`; return { send, diff --git a/src/renderer/coremods/commands/index.ts b/src/renderer/coremods/commands/index.ts index 3db259d1e..4836625d0 100644 --- a/src/renderer/coremods/commands/index.ts +++ b/src/renderer/coremods/commands/index.ts @@ -217,8 +217,8 @@ async function injectApplicationCommandSearchStore(): Promise { ); if (!commandAndSectionsArray.length) return; if ( - !commandAndSectionsArray.every((commandAndSection) => - res?.some((section) => section.id === commandAndSection.section.id), + !commandAndSectionsArray.every( + (commandAndSection) => res?.some((section) => section.id === commandAndSection.section.id), ) ) { const sectionsToAdd = commandAndSectionsArray diff --git a/src/renderer/coremods/settings/pages/Updater.tsx b/src/renderer/coremods/settings/pages/Updater.tsx index 9473d39c7..f56d2b97d 100644 --- a/src/renderer/coremods/settings/pages/Updater.tsx +++ b/src/renderer/coremods/settings/pages/Updater.tsx @@ -22,8 +22,9 @@ const logger = Logger.coremod("Settings:Updater"); export const Updater = (): React.ReactElement => { const [checking, setChecking] = React.useState(false); - const [updatesAvailable, setUpdatesAvailable] = - React.useState>(getAvailableUpdates()); + const [updatesAvailable, setUpdatesAvailable] = React.useState< + Array + >(getAvailableUpdates()); const [updatePromises, setUpdatePromises] = React.useState>>({}); const [didInstallAll, setDidInstallAll] = React.useState(false); const [lastChecked, setLastChecked] = useSettingArray(updaterSettings, "lastChecked"); diff --git a/src/renderer/util.ts b/src/renderer/util.ts index b086517fc..e3bd99c2b 100644 --- a/src/renderer/util.ts +++ b/src/renderer/util.ts @@ -197,8 +197,8 @@ export function useSetting< value: K extends D ? NonNullable : F extends null | undefined - ? T[K] | undefined - : NonNullable | F; + ? T[K] | undefined + : NonNullable | F; onChange: (newValue: ValType) => void; } { const initial = settings.get(key, fallback); @@ -237,8 +237,8 @@ export function useSettingArray< K extends D ? NonNullable : F extends null | undefined - ? T[K] | undefined - : NonNullable | F, + ? T[K] | undefined + : NonNullable | F, (newValue: ValType) => void, ] { const { value, onChange } = useSetting(settings, key, fallback); @@ -256,8 +256,9 @@ type UnionToIntersection = (U extends never ? never : (k: U) => void) extends type ObjectType = Record; -type ExtractObjectType = - O extends Array ? UnionToIntersection : never; +type ExtractObjectType = O extends Array + ? UnionToIntersection + : never; export function virtualMerge(...objects: O): ExtractObjectType { const fallback = {}; From 51c4d2dde60e958b91f693575808bce1c162a2fe Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 21 Feb 2024 16:46:27 -0500 Subject: [PATCH 16/39] Vibrancy & win32 effect IPC --- src/main/ipc/index.ts | 1 + src/main/ipc/transparency.ts | 54 ++++++++++++++++++++++++++++++++++-- src/preload.ts | 15 ++++++++-- src/types/index.ts | 3 ++ 4 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/main/ipc/index.ts b/src/main/ipc/index.ts index c664f0cb4..f28b2e8e8 100644 --- a/src/main/ipc/index.ts +++ b/src/main/ipc/index.ts @@ -6,6 +6,7 @@ import "./settings"; import "./installer"; import "./i18n"; import "./react-devtools"; +import "./transparency"; import { RepluggedIpcChannels, type RepluggedWebContents } from "../../types"; ipcMain.on(RepluggedIpcChannels.GET_DISCORD_PRELOAD, (event) => { diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index 1ba757bdb..103e9a6ff 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -1,4 +1,54 @@ -import { ipcMain } from "electron"; +import { BrowserWindow, ipcMain } from "electron"; import { RepluggedIpcChannels } from "../../types"; +// @ts-expect-error Type defs are obtained through @pyke/vibe +import vibePath from "../../vibe.node"; -ipcMain.handle(RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, () => {}); +let vibe: typeof import("@pyke/vibe"); +if (process.platform === "win32") { + vibe = require(vibePath) as unknown as typeof import("@pyke/vibe"); +} + +let currentEffect: Parameters[1] | null = null; +ipcMain.handle( + RepluggedIpcChannels.GET_TRANSPARENCY_EFFECT, + (): Parameters[1] | null => { + if (DiscordNative.process.platform !== "win32") { + console.warn("GET_TRANSPARENCY_EFFECT only works on Windows"); + } + + return currentEffect; + }, +); + +ipcMain.handle( + RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, + (_, effect: Parameters[1]) => { + if (DiscordNative.process.platform !== "win32") { + console.warn("RepluggedNative.transparency.applyEffect only works on Windows"); + return; + } + + let windows = BrowserWindow.getAllWindows(); + console.log(windows); + // TODO: Is it a bad idea to apply this to all active windows? + windows.forEach((window) => vibe.applyEffect(window, effect)); + currentEffect = effect; + }, +); + +let currentVibrancy: Parameters[0] = null; +ipcMain.handle( + RepluggedIpcChannels.GET_VIBRANCY, + (): Parameters[0] => currentVibrancy, +); + +ipcMain.handle( + RepluggedIpcChannels.SET_VIBRANCY, + (_, vibrancy: Parameters[0]) => { + let windows = BrowserWindow.getAllWindows(); + + // TODO: Is it a bad idea to apply this to all active windows? + windows.forEach((window) => window.setVibrancy(vibrancy)); + currentVibrancy = vibrancy; + }, +); diff --git a/src/preload.ts b/src/preload.ts index e68c7ae08..32a5eb3fe 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -3,6 +3,7 @@ import { contextBridge, ipcRenderer, webFrame, + BrowserWindow, } from "electron"; import { RepluggedIpcChannels } from "./types"; @@ -17,6 +18,8 @@ import type { RepluggedTheme, RepluggedTranslations, } from "./types"; +// Note that this may ONLY be used for types. +import vibe from "@pyke/vibe"; let version = ""; void ipcRenderer.invoke(RepluggedIpcChannels.GET_REPLUGGED_VERSION).then((v) => { @@ -109,8 +112,16 @@ const RepluggedNative = { }, transparency: { - applyEffect: (): Promise => - ipcRenderer.invoke(RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT), + getEffect: (): Promise[1]> => + ipcRenderer.invoke(RepluggedIpcChannels.GET_TRANSPARENCY_EFFECT), + applyEffect: (effect: Parameters[1]): Promise => + ipcRenderer.invoke(RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, effect), + getVibrancy: (): Promise[0]> => + ipcRenderer.invoke(RepluggedIpcChannels.GET_VIBRANCY), + setVibrancy: ( + vibrancy: Parameters[0], + ): Promise => ipcRenderer.invoke(RepluggedIpcChannels.SET_VIBRANCY, vibrancy), + // visualEffectState does not need to be implemented until https://github.com/electron/electron/issues/25513 is implemented. }, getVersion: () => version, diff --git a/src/types/index.ts b/src/types/index.ts index 127b92ebf..e9347f576 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -33,7 +33,10 @@ export enum RepluggedIpcChannels { OPEN_QUICKCSS_FOLDER = "REPLUGGED_OPEN_QUICKCSS_FOLDER", GET_REPLUGGED_VERSION = "REPLUGGED_GET_REPLUGGED_VERSION", DOWNLOAD_REACT_DEVTOOLS = "REPLUGGED_DOWNLOAD_REACT_DEVTOOLS", + GET_TRANSPARENCY_EFFECT = "REPLUGGED_GET_TRANSPARENCY_EFFECT", APPLY_TRANSPARENCY_EFFECT = "REPLUGGED_APPLY_TRANSPARENCY_EFFECT", + GET_VIBRANCY = "REPLUGGED_GET_VIBRANCY", + SET_VIBRANCY = "REPLUGGED_SET_VIBRANCY", } export interface RepluggedAnnouncement { From 90c0e39eaeb58c2bcf18b56aad925b870c8b34f9 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 21 Feb 2024 16:47:07 -0500 Subject: [PATCH 17/39] Transparency coremod --- src/renderer/coremods/transparency/index.ts | 67 +++++++++++++++++++++ src/renderer/managers/coremods.ts | 2 + 2 files changed, 69 insertions(+) create mode 100644 src/renderer/coremods/transparency/index.ts diff --git a/src/renderer/coremods/transparency/index.ts b/src/renderer/coremods/transparency/index.ts new file mode 100644 index 000000000..761ae8a8f --- /dev/null +++ b/src/renderer/coremods/transparency/index.ts @@ -0,0 +1,67 @@ +import { Logger } from "@replugged"; + +const logger = Logger.coremod("Transparency"); +let observer: MutationObserver; + +export function start(): void { + let html = document.body.parentElement!; + // RepluggedNative.transparency.applyEffect(); + observer = new MutationObserver(async (mutations) => { + let cssModified = false; + for (const mutation of mutations) { + if (mutation.target instanceof HTMLLinkElement && mutation.type === "attributes") { + cssModified = true; + break; + } + + if (mutation.type !== "childList") continue; + + // Check for both added or removed css(like) nodes + let changedNodes = Array.from(mutation.addedNodes).concat(Array.from(mutation.removedNodes)); + let cssLikeNodes = changedNodes.filter( + (node) => node instanceof HTMLStyleElement || node instanceof HTMLLinkElement, + ); + if (cssLikeNodes.length > 0) { + cssModified = true; + break; + } + } + + if (cssModified) { + switch (DiscordNative.process.platform) { + case "win32": { + const transparencyEffect = getComputedStyle(html).getPropertyValue("--window-win-blur"); + if (transparencyEffect === (await RepluggedNative.transparency.getEffect())) { + return; + } + + // @ts-expect-error TODO: Check if the vibrancy is valid? + await RepluggedNative.transparency.applyEffect(transparencyEffect); + break; + } + case "darwin": { + const vibrancy = getComputedStyle(html).getPropertyValue("--window-vibrancy"); + if (vibrancy === (await RepluggedNative.transparency.getVibrancy())) { + return; + } + + // @ts-expect-error TODO: Check if the vibrancy is valid? + await RepluggedNative.transparency.setVibrancy(vibrancy); + break; + } + } + } + }); + + observer.observe(html, { + subtree: true, + childList: true, + // To handle any instances where a link has it's href changed. + attributes: true, + attributeFilter: ["href"], + }); +} + +export function stop(): void { + observer.disconnect(); +} diff --git a/src/renderer/managers/coremods.ts b/src/renderer/managers/coremods.ts index cafd75fb7..fdc406cd2 100644 --- a/src/renderer/managers/coremods.ts +++ b/src/renderer/managers/coremods.ts @@ -34,6 +34,7 @@ export namespace coremods { export let watcher: Coremod; export let commands: Coremod; export let welcome: Coremod; + export let transparency: Coremod; } export async function start(name: keyof typeof coremods): Promise { @@ -59,6 +60,7 @@ export async function startAll(): Promise { coremods.watcher = await import("../coremods/watcher"); coremods.commands = await import("../coremods/commands"); coremods.welcome = await import("../coremods/welcome"); + coremods.transparency = await import("../coremods/transparency"); await Promise.all( Object.entries(coremods).map(async ([name, mod]) => { From 91db00f83752d226af38cfc8ad93354ebc80e1c1 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 21 Feb 2024 16:49:30 -0500 Subject: [PATCH 18/39] Platform specific transparency in BrowserWindow --- src/main/index.ts | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 604b24e49..9a35ef7c3 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -77,16 +77,18 @@ class BrowserWindow extends electron.BrowserWindow { opts.webPreferences!.preload = join(__dirname, "./preload.js"); if (settings.get("transparentWindow")) { - opts.show = false; - // Menu bar needs to be remade -_- - opts.autoHideMenuBar = true; - // opts.frame = process.platform === "win32" ? false : opts.frame; - // TODO: Figure out what background color each OS needs. - opts.backgroundColor = "#0000000"; - - if (process.platform === "linux") { - opts.transparent = true; + switch (process.platform) { + case "win32": + // TODO: Menu bar will need to be remade + opts.autoHideMenuBar = true; + opts.show = false; // TODO: Unsure if this is needed everywhere + break; + case "linux": + opts.transparent = true; + break; } + // TODO: Determine what `frame` value is needed on each platform + // TODO: Determine what `backgroundColor` is needed on each platform } break; } @@ -104,10 +106,11 @@ class BrowserWindow extends electron.BrowserWindow { if (currentWindow === DiscordWindowType.DISCORD_CLIENT && settings.get("transparentWindow")) { this.on("ready-to-show", () => { - if (process.platform === "win32") { - vibe.applyEffect(this, "unified-acrylic"); - vibe.forceTheme(this, "dark"); - } + // if (process.platform === "win32") { + // vibe.applyEffect(this, "unified-acrylic"); + // vibe.forceTheme(this, "dark"); + // } + // TODO: unsure if this is needed this.setBackgroundColor("#00000000"); }); } From 8520f45d3e92dcda61e29b56ba9f40c4bd78fa03 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 21 Feb 2024 16:52:52 -0500 Subject: [PATCH 19/39] Unity todo messages and general cleaning --- src/globals.d.ts | 2 +- src/main/index.ts | 10 +++++----- src/main/ipc/transparency.ts | 4 ++-- src/preload.ts | 4 ++-- src/renderer/coremods/badges/index.tsx | 2 +- src/renderer/coremods/experiments/plaintextPatches.ts | 2 +- src/renderer/coremods/transparency/index.ts | 9 +++------ src/renderer/modules/components/Clickable.tsx | 2 +- src/renderer/modules/components/Text.tsx | 2 +- 9 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/globals.d.ts b/src/globals.d.ts index 45d8f7101..2a112b02a 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -1,6 +1,6 @@ /// -// TODO: Scope global types to each component +// @todo: Scope global types to each component import type { WebpackChunkGlobal } from "./types/discord"; import * as replugged from "./renderer/replugged"; diff --git a/src/main/index.ts b/src/main/index.ts index 9a35ef7c3..b4128c473 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -79,16 +79,16 @@ class BrowserWindow extends electron.BrowserWindow { if (settings.get("transparentWindow")) { switch (process.platform) { case "win32": - // TODO: Menu bar will need to be remade + // @todo: Menu bar will need to be remade opts.autoHideMenuBar = true; - opts.show = false; // TODO: Unsure if this is needed everywhere + opts.show = false; // @todo: Unsure if this is needed everywhere break; case "linux": opts.transparent = true; break; } - // TODO: Determine what `frame` value is needed on each platform - // TODO: Determine what `backgroundColor` is needed on each platform + // @todo: Determine what `frame` value is needed on each platform + // @todo: Determine what `backgroundColor` is needed on each platform } break; } @@ -110,7 +110,7 @@ class BrowserWindow extends electron.BrowserWindow { // vibe.applyEffect(this, "unified-acrylic"); // vibe.forceTheme(this, "dark"); // } - // TODO: unsure if this is needed + // @todo: unsure if this is needed this.setBackgroundColor("#00000000"); }); } diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index 103e9a6ff..68099d53f 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -30,7 +30,7 @@ ipcMain.handle( let windows = BrowserWindow.getAllWindows(); console.log(windows); - // TODO: Is it a bad idea to apply this to all active windows? + // @todo: Is it a bad idea to apply this to all active windows? windows.forEach((window) => vibe.applyEffect(window, effect)); currentEffect = effect; }, @@ -47,7 +47,7 @@ ipcMain.handle( (_, vibrancy: Parameters[0]) => { let windows = BrowserWindow.getAllWindows(); - // TODO: Is it a bad idea to apply this to all active windows? + // @todo: Is it a bad idea to apply this to all active windows? windows.forEach((window) => window.setVibrancy(vibrancy)); currentVibrancy = vibrancy; }, diff --git a/src/preload.ts b/src/preload.ts index 32a5eb3fe..e2df5240c 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -1,9 +1,9 @@ import { + BrowserWindow, type BrowserWindowConstructorOptions, contextBridge, ipcRenderer, webFrame, - BrowserWindow, } from "electron"; import { RepluggedIpcChannels } from "./types"; @@ -129,7 +129,7 @@ const RepluggedNative = { // eslint-disable-next-line @typescript-eslint/no-unused-vars openBrowserWindow: (opts: BrowserWindowConstructorOptions) => {}, // later - // @todo We probably want to move these somewhere else, but I'm putting them here for now because I'm too lazy to set anything else up + // @todo: We probably want to move these somewhere else, but I'm putting them here for now because I'm too lazy to set anything else up }; export type RepluggedNativeType = typeof RepluggedNative; diff --git a/src/renderer/coremods/badges/index.tsx b/src/renderer/coremods/badges/index.tsx index d7e935b26..6bc1b5657 100644 --- a/src/renderer/coremods/badges/index.tsx +++ b/src/renderer/coremods/badges/index.tsx @@ -60,7 +60,7 @@ export async function start(): Promise { if (!cache.has(id) || cache.get(id)!.lastFetch < Date.now() - REFRESH_INTERVAL) { cache.set( id, - // TODO: new backend + // @todo: new backend await fetch(`${generalSettings.get("apiUrl")}/api/v1/users/${id}`) .then(async (res) => { const body = (await res.json()) as Record & { diff --git a/src/renderer/coremods/experiments/plaintextPatches.ts b/src/renderer/coremods/experiments/plaintextPatches.ts index 6d18e8c6e..c3b08ada1 100644 --- a/src/renderer/coremods/experiments/plaintextPatches.ts +++ b/src/renderer/coremods/experiments/plaintextPatches.ts @@ -1,7 +1,7 @@ import { init } from "src/renderer/apis/settings"; import { type GeneralSettings, type PlaintextPatch, defaultSettings } from "src/types"; -// TODO: see if we can import this from General.tsx +// @todo: see if we can import this from General.tsx const generalSettings = await init( "dev.replugged.Settings", defaultSettings, diff --git a/src/renderer/coremods/transparency/index.ts b/src/renderer/coremods/transparency/index.ts index 761ae8a8f..1786a2458 100644 --- a/src/renderer/coremods/transparency/index.ts +++ b/src/renderer/coremods/transparency/index.ts @@ -1,11 +1,8 @@ -import { Logger } from "@replugged"; - -const logger = Logger.coremod("Transparency"); let observer: MutationObserver; export function start(): void { let html = document.body.parentElement!; - // RepluggedNative.transparency.applyEffect(); + observer = new MutationObserver(async (mutations) => { let cssModified = false; for (const mutation of mutations) { @@ -35,7 +32,7 @@ export function start(): void { return; } - // @ts-expect-error TODO: Check if the vibrancy is valid? + // @ts-expect-error @todo: Check if the vibrancy is valid? await RepluggedNative.transparency.applyEffect(transparencyEffect); break; } @@ -45,7 +42,7 @@ export function start(): void { return; } - // @ts-expect-error TODO: Check if the vibrancy is valid? + // @ts-expect-error @todo: Check if the vibrancy is valid? await RepluggedNative.transparency.setVibrancy(vibrancy); break; } diff --git a/src/renderer/modules/components/Clickable.tsx b/src/renderer/modules/components/Clickable.tsx index f840448ec..b10c8fd0d 100644 --- a/src/renderer/modules/components/Clickable.tsx +++ b/src/renderer/modules/components/Clickable.tsx @@ -1,7 +1,7 @@ import type React from "react"; import components from "../common/components"; -// TODO: generic type for tags? +// @todo: generic type for tags? type ClickableProps = React.ComponentPropsWithoutRef<"div"> & { tag?: keyof JSX.IntrinsicElements; ignoreKeyPress?: boolean; diff --git a/src/renderer/modules/components/Text.tsx b/src/renderer/modules/components/Text.tsx index c9f37167c..67179dbdf 100644 --- a/src/renderer/modules/components/Text.tsx +++ b/src/renderer/modules/components/Text.tsx @@ -64,7 +64,7 @@ export type Variant = | "display-lg" | "code"; -// TODO: generic type for tags? +// @todo: generic type for tags? interface TextProps extends React.ComponentPropsWithoutRef<"div"> { variant?: Variant; tag?: keyof JSX.IntrinsicElements; From 0f121a502b35fd621afbe25d1e31728f8816eaa4 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 21 Feb 2024 17:09:06 -0500 Subject: [PATCH 20/39] Fix Transparency IPC --- src/main/ipc/transparency.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index 68099d53f..b8f2505d9 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -12,7 +12,7 @@ let currentEffect: Parameters[1] | null = null; ipcMain.handle( RepluggedIpcChannels.GET_TRANSPARENCY_EFFECT, (): Parameters[1] | null => { - if (DiscordNative.process.platform !== "win32") { + if (process.platform !== "win32") { console.warn("GET_TRANSPARENCY_EFFECT only works on Windows"); } @@ -23,14 +23,12 @@ ipcMain.handle( ipcMain.handle( RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, (_, effect: Parameters[1]) => { - if (DiscordNative.process.platform !== "win32") { + if (process.platform !== "win32") { console.warn("RepluggedNative.transparency.applyEffect only works on Windows"); return; } let windows = BrowserWindow.getAllWindows(); - console.log(windows); - // @todo: Is it a bad idea to apply this to all active windows? windows.forEach((window) => vibe.applyEffect(window, effect)); currentEffect = effect; }, @@ -47,7 +45,6 @@ ipcMain.handle( (_, vibrancy: Parameters[0]) => { let windows = BrowserWindow.getAllWindows(); - // @todo: Is it a bad idea to apply this to all active windows? windows.forEach((window) => window.setVibrancy(vibrancy)); currentVibrancy = vibrancy; }, From b1658b34e766374e2fd3292b6c328737e83c99a7 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 21 Feb 2024 17:15:17 -0500 Subject: [PATCH 21/39] Fix comment issues --- src/main/ipc/transparency.ts | 2 +- src/renderer/coremods/transparency/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index b8f2505d9..570d07e2e 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -24,7 +24,7 @@ ipcMain.handle( RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, (_, effect: Parameters[1]) => { if (process.platform !== "win32") { - console.warn("RepluggedNative.transparency.applyEffect only works on Windows"); + console.warn("APPLY_TRANSPARENCY_EFFECT only works on Windows"); return; } diff --git a/src/renderer/coremods/transparency/index.ts b/src/renderer/coremods/transparency/index.ts index 1786a2458..0edd2ad73 100644 --- a/src/renderer/coremods/transparency/index.ts +++ b/src/renderer/coremods/transparency/index.ts @@ -32,7 +32,7 @@ export function start(): void { return; } - // @ts-expect-error @todo: Check if the vibrancy is valid? + // @ts-expect-error @todo: Check if the transparency effect is valid? await RepluggedNative.transparency.applyEffect(transparencyEffect); break; } From 7f9e614b90f31df17197859caad62063957b8681 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 21 Feb 2024 22:00:50 -0500 Subject: [PATCH 22/39] Fix reading of transparency styles --- src/renderer/coremods/transparency/index.ts | 49 +++++++++++++-------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/renderer/coremods/transparency/index.ts b/src/renderer/coremods/transparency/index.ts index 0edd2ad73..543b2fdcb 100644 --- a/src/renderer/coremods/transparency/index.ts +++ b/src/renderer/coremods/transparency/index.ts @@ -1,5 +1,12 @@ let observer: MutationObserver; +function getRootStringProperty(property: string): string { + const computedStyle = getComputedStyle(document.body); + const value = computedStyle.getPropertyValue(property); + + return value.split('"')[1]; +} + export function start(): void { let html = document.body.parentElement!; @@ -25,28 +32,34 @@ export function start(): void { } if (cssModified) { - switch (DiscordNative.process.platform) { - case "win32": { - const transparencyEffect = getComputedStyle(html).getPropertyValue("--window-win-blur"); - if (transparencyEffect === (await RepluggedNative.transparency.getEffect())) { - return; - } + // Originally this used requestAnimationFrame but it took to long + // so instead we setTimeout and pray. The setTimeout could be + // shorter if we wanted, but it's hard to say if it would + // work as consistently. + setTimeout(async () => { + switch (DiscordNative.process.platform) { + case "win32": { + const transparencyEffect = getRootStringProperty("--window-win-blur"); + if (transparencyEffect === (await RepluggedNative.transparency.getEffect())) { + return; + } - // @ts-expect-error @todo: Check if the transparency effect is valid? - await RepluggedNative.transparency.applyEffect(transparencyEffect); - break; - } - case "darwin": { - const vibrancy = getComputedStyle(html).getPropertyValue("--window-vibrancy"); - if (vibrancy === (await RepluggedNative.transparency.getVibrancy())) { - return; + // @ts-expect-error @todo: Check if the transparency effect is valid? + await RepluggedNative.transparency.applyEffect(transparencyEffect); + break; } + case "darwin": { + const vibrancy = getRootStringProperty("--window-vibrancy"); + if (vibrancy === (await RepluggedNative.transparency.getVibrancy())) { + return; + } - // @ts-expect-error @todo: Check if the vibrancy is valid? - await RepluggedNative.transparency.setVibrancy(vibrancy); - break; + // @ts-expect-error @todo: Check if the vibrancy is valid? + await RepluggedNative.transparency.setVibrancy(vibrancy); + break; + } } - } + }, 100); } }); From a62f1b43b5d6ef18c8f93b5a9b95d53fbdf5c195 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Fri, 1 Mar 2024 15:24:52 -0500 Subject: [PATCH 23/39] Fix advanced settings crash --- src/renderer/coremods/settings/pages/General.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/renderer/coremods/settings/pages/General.tsx b/src/renderer/coremods/settings/pages/General.tsx index 8f2f123c1..3967fe652 100644 --- a/src/renderer/coremods/settings/pages/General.tsx +++ b/src/renderer/coremods/settings/pages/General.tsx @@ -190,12 +190,6 @@ export const General = (): React.ReactElement => { {Messages.REPLUGGED_SETTINGS_REACT_DEVTOOLS} - - {Messages.REPLUGGED_SETTINGS_TRANSPARENT} - - Date: Fri, 1 Mar 2024 15:25:39 -0500 Subject: [PATCH 24/39] Use built in electron blur if available. --- cspell.json | 5 +++-- src/main/ipc/transparency.ts | 37 +++++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/cspell.json b/cspell.json index 606ef70fd..8196a5de4 100644 --- a/cspell.json +++ b/cspell.json @@ -10,6 +10,7 @@ "Automod", "autosize", "backoff", + "blurbehind", "blurple", "Chunkdiscord", "codemirror", @@ -48,6 +49,7 @@ "popout", "postpublish", "Promisable", + "pyke", "quickcss", "ratelimited", "rauenzi", @@ -67,8 +69,7 @@ "Vendicated", "Webauthn", "weblate", - "XLARGE", - "pyke" + "XLARGE" ], "ignoreWords": [], "import": [], diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index 570d07e2e..bba97f4e9 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -1,11 +1,27 @@ import { BrowserWindow, ipcMain } from "electron"; import { RepluggedIpcChannels } from "../../types"; -// @ts-expect-error Type defs are obtained through @pyke/vibe -import vibePath from "../../vibe.node"; +import os from "os"; let vibe: typeof import("@pyke/vibe"); -if (process.platform === "win32") { - vibe = require(vibePath) as unknown as typeof import("@pyke/vibe"); +let release = os.release().split(".").map(Number); +let usesVibe = + // Windows + process.platform === "win32" && + // Before Electron 24 + Number(process.versions.electron.split(".")[0]) < 24 && + // Before Windows 11 22H2+ + release[0] <= 10 && // 11 doesn't exist yet but it could. + release[1] < 22621; + +if (usesVibe) { + // @ts-expect-error Type defs are obtained through @pyke/vibe + import("../../vibe.node") + .then((module) => { + vibe = module as unknown as typeof import("@pyke/vibe"); + }) + .catch((error) => { + console.error("Failed to load vibe.", error); + }); } let currentEffect: Parameters[1] | null = null; @@ -29,7 +45,18 @@ ipcMain.handle( } let windows = BrowserWindow.getAllWindows(); - windows.forEach((window) => vibe.applyEffect(window, effect)); + windows.forEach((window) => { + if (usesVibe) { + // The valid options for setBackgroundMaterial are "auto" | "none" | "mica" | "acrylic" | "tabbed". + // This goes against vibe which allows for "unified-acrylic" and "blurbehind". + // Also, vibe does not allow for "auto", "none" or "tabbed" + + // @ts-expect-error Only exists in electron 24+, our types don't have this. + window.setBackgroundMaterial(effect === NULL ? "none" : effect); // NULL is used to disable. + } else { + vibe.applyEffect(window, effect); + } + }); currentEffect = effect; }, ); From a5451bf553fbeb264607fdb0702d4a5d040830db Mon Sep 17 00:00:00 2001 From: EastArctica Date: Sun, 10 Mar 2024 15:34:52 -0400 Subject: [PATCH 25/39] Fix applyEffect --- src/main/ipc/transparency.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index bba97f4e9..ac06dce9d 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -38,7 +38,7 @@ ipcMain.handle( ipcMain.handle( RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, - (_, effect: Parameters[1]) => { + (_, effect: Parameters[1] | null) => { if (process.platform !== "win32") { console.warn("APPLY_TRANSPARENCY_EFFECT only works on Windows"); return; @@ -52,7 +52,9 @@ ipcMain.handle( // Also, vibe does not allow for "auto", "none" or "tabbed" // @ts-expect-error Only exists in electron 24+, our types don't have this. - window.setBackgroundMaterial(effect === NULL ? "none" : effect); // NULL is used to disable. + window.setBackgroundMaterial(effect === null ? "none" : effect); // NULL is used to disable. + } else if (effect === null) { + vibe.clearEffects(window); } else { vibe.applyEffect(window, effect); } From 9d0e1bdc7b3c0fa456f90318c75a07b26881b818 Mon Sep 17 00:00:00 2001 From: EastArctica Date: Sun, 10 Mar 2024 15:46:42 -0400 Subject: [PATCH 26/39] Fix vibe import --- src/main/ipc/transparency.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index ac06dce9d..bc5123369 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -1,6 +1,8 @@ import { BrowserWindow, ipcMain } from "electron"; import { RepluggedIpcChannels } from "../../types"; import os from "os"; +// @ts-expect-error Type defs are obtained through @pyke/vibe +import vibePath from "../../vibe.node"; let vibe: typeof import("@pyke/vibe"); let release = os.release().split(".").map(Number); @@ -14,8 +16,7 @@ let usesVibe = release[1] < 22621; if (usesVibe) { - // @ts-expect-error Type defs are obtained through @pyke/vibe - import("../../vibe.node") + import(vibePath) .then((module) => { vibe = module as unknown as typeof import("@pyke/vibe"); }) From c047b443a4ee9e5a6ab239cec5c62c608d197eec Mon Sep 17 00:00:00 2001 From: EastArctica Date: Sun, 10 Mar 2024 15:52:42 -0400 Subject: [PATCH 27/39] Move from import to require --- src/main/ipc/transparency.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index bc5123369..02e861506 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -16,13 +16,11 @@ let usesVibe = release[1] < 22621; if (usesVibe) { - import(vibePath) - .then((module) => { - vibe = module as unknown as typeof import("@pyke/vibe"); - }) - .catch((error) => { - console.error("Failed to load vibe.", error); - }); + try { + vibe = require(vibePath) as unknown as typeof import("@pyke/vibe"); + } catch (error) { + console.error("Failed to load vibe.", error); + } } let currentEffect: Parameters[1] | null = null; From aa5d8e5485f5d3b1e1c5144ac9b661aaacc921f5 Mon Sep 17 00:00:00 2001 From: EastArctica Date: Sun, 10 Mar 2024 15:57:25 -0400 Subject: [PATCH 28/39] Fix inverted if --- src/main/ipc/transparency.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index 02e861506..9e6567dba 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -45,7 +45,7 @@ ipcMain.handle( let windows = BrowserWindow.getAllWindows(); windows.forEach((window) => { - if (usesVibe) { + if (!usesVibe) { // The valid options for setBackgroundMaterial are "auto" | "none" | "mica" | "acrylic" | "tabbed". // This goes against vibe which allows for "unified-acrylic" and "blurbehind". // Also, vibe does not allow for "auto", "none" or "tabbed" From 04c3c4a2ada87ddd27b378dd304fb9d7c671028f Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Tue, 14 Jan 2025 22:46:41 -0500 Subject: [PATCH 29/39] Remove vibe and implement setBackgroundMaterial --- package.json | 5 +- pnpm-lock.yaml | 8 +- scripts/build.mts | 3 - src/main/index.ts | 58 ++++++++----- src/main/ipc/index.ts | 9 +- src/main/ipc/transparency.ts | 80 ++++++++---------- src/preload.ts | 16 ++-- .../coremods/settings/pages/General.tsx | 8 +- src/renderer/coremods/transparency/index.ts | 31 +++++-- src/types/index.ts | 6 +- src/vibe.node | Bin 188928 -> 0 bytes 11 files changed, 118 insertions(+), 106 deletions(-) delete mode 100644 src/vibe.node diff --git a/package.json b/package.json index eaaee1f63..fa17d4667 100644 --- a/package.json +++ b/package.json @@ -97,10 +97,7 @@ "yargs": "^17.7.2", "zod": "^3.23.8" }, - "optionalDependencies": { - "@pyke/vibe": "^0.4.0" - }, "bin": { "replugged": "bin.mjs" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 540a51753..a5aa3194d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1019,8 +1019,8 @@ packages: '@types/methods@1.1.4': resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} - '@types/node@18.19.64': - resolution: {integrity: sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ==} + '@types/node@18.19.70': + resolution: {integrity: sha512-RE+K0+KZoEpDUbGGctnGdkrLFwi1eYKTlIHNl2Um98mUkGsm1u2Ff6Ltd0e8DktTtC98uy7rSj+hO8t/QuLoVQ==} '@types/node@20.17.6': resolution: {integrity: sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==} @@ -3904,7 +3904,7 @@ snapshots: '@types/methods@1.1.4': {} - '@types/node@18.19.64': + '@types/node@18.19.70': dependencies: undici-types: 5.26.5 @@ -5815,7 +5815,7 @@ snapshots: standalone-electron-types@1.0.0: dependencies: - '@types/node': 18.19.64 + '@types/node': 18.19.70 string-width@1.0.2: dependencies: diff --git a/scripts/build.mts b/scripts/build.mts index 5f2fd90e0..5e54d370e 100644 --- a/scripts/build.mts +++ b/scripts/build.mts @@ -51,9 +51,6 @@ const contexts = await Promise.all([ target: `node${NODE_VERSION}`, outfile: `${distDir}/main.js`, external: ["electron", "original-fs"], - loader: { - ".node": "file", - }, }), // Preload esbuild.context({ diff --git a/src/main/index.ts b/src/main/index.ts index 6f234c404..16b63a291 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -3,14 +3,6 @@ import electron from "electron"; import { CONFIG_PATHS, readSettingsSync } from "src/util.mjs"; import type { RepluggedWebContents } from "../types"; import { getSetting } from "./ipc/settings"; -// @ts-expect-error Type defs are obtained through @pyke/vibe -import vibePath from "../vibe.node"; - -let vibe: typeof import("@pyke/vibe"); -if (process.platform === "win32") { - vibe = require(vibePath) as unknown as typeof import("@pyke/vibe"); - vibe.setup(electron.app); -} const settings = readSettingsSync("dev.replugged.Settings"); const electronPath = require.resolve("electron"); @@ -57,7 +49,8 @@ function windowTypeFromOpts(opts: InternalBrowserWindowConstructorOptions): Disc if (opts.webPreferences.nativeWindowOpen) { return DiscordWindowType.DISCORD_CLIENT; } else { - return DiscordWindowType.SPLASH_SCREEN; + // Splash Screen on macOS (Host 0.0.262+) & Windows (Host 0.0.293 / 1.0.17+) + return DiscordWindowType.DISCORD_CLIENT; } } @@ -80,16 +73,13 @@ class BrowserWindow extends electron.BrowserWindow { if (settings.get("transparentWindow")) { switch (process.platform) { case "win32": - // @todo: Menu bar will need to be remade - opts.autoHideMenuBar = true; - opts.show = false; // @todo: Unsure if this is needed everywhere + opts.transparent = true; + opts.backgroundColor = "#00000000"; break; case "linux": opts.transparent = true; break; } - // @todo: Determine what `frame` value is needed on each platform - // @todo: Determine what `backgroundColor` is needed on each platform } break; } @@ -105,19 +95,41 @@ class BrowserWindow extends electron.BrowserWindow { super(opts); - if (currentWindow === DiscordWindowType.DISCORD_CLIENT && settings.get("transparentWindow")) { - this.on("ready-to-show", () => { - // if (process.platform === "win32") { - // vibe.applyEffect(this, "unified-acrylic"); - // vibe.forceTheme(this, "dark"); - // } - // @todo: unsure if this is needed - this.setBackgroundColor("#00000000"); - }); + // Center the unmaximized location + if (settings.get("transparentWindow")) { + const currentDisplay = electron.screen.getDisplayNearestPoint(electron.screen.getCursorScreenPoint()) + this.repluggedPreviousBounds.x = currentDisplay.workArea.width / 2 - this.repluggedPreviousBounds.width / 2; + this.repluggedPreviousBounds.y = currentDisplay.workArea.height / 2 - this.repluggedPreviousBounds.height / 2; + this.maximize = this.repluggedToggleMaximize; + this.unmaximize = this.repluggedToggleMaximize; } (this.webContents as RepluggedWebContents).originalPreload = originalPreload; } + + + private repluggedPreviousBounds: Electron.Rectangle = { + width: 1400, + height: 900, + x: 0, + y: 0 + }; + + public repluggedToggleMaximize(): void { + // Determine whether the display is actually maximized already + let currentBounds = this.getBounds(); + const currentDisplay = electron.screen.getDisplayNearestPoint(electron.screen.getCursorScreenPoint()); + const workAreaSize = currentDisplay.workArea; + if (currentBounds.width === workAreaSize.width && currentBounds.height === workAreaSize.height) { + // Un-maximize + this.setBounds(this.repluggedPreviousBounds) + return; + } + + + this.repluggedPreviousBounds = this.getBounds() + this.setBounds({ x: workAreaSize.x + 1, y: workAreaSize.y + 1, width: workAreaSize.width, height: workAreaSize.height }) + } } Object.defineProperty(BrowserWindow, "name", { diff --git a/src/main/ipc/index.ts b/src/main/ipc/index.ts index f33dfb63e..102c9e8d9 100644 --- a/src/main/ipc/index.ts +++ b/src/main/ipc/index.ts @@ -1,19 +1,12 @@ import { ipcMain } from "electron"; import { RepluggedIpcChannels, type RepluggedWebContents } from "../../types"; -import "./plugins"; -import "./themes"; -import "./quick-css"; -import "./settings"; -import "./installer"; -import "./i18n"; -import "./react-devtools"; -import "./transparency"; import "./installer"; import "./plugins"; import "./quick-css"; import "./react-devtools"; import "./settings"; import "./themes"; +import './transparency'; ipcMain.on(RepluggedIpcChannels.GET_DISCORD_PRELOAD, (event) => { event.returnValue = (event.sender as RepluggedWebContents).originalPreload; diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index 9e6567dba..01ba4ea3d 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -1,64 +1,32 @@ import { BrowserWindow, ipcMain } from "electron"; import { RepluggedIpcChannels } from "../../types"; -import os from "os"; -// @ts-expect-error Type defs are obtained through @pyke/vibe -import vibePath from "../../vibe.node"; -let vibe: typeof import("@pyke/vibe"); -let release = os.release().split(".").map(Number); -let usesVibe = - // Windows - process.platform === "win32" && - // Before Electron 24 - Number(process.versions.electron.split(".")[0]) < 24 && - // Before Windows 11 22H2+ - release[0] <= 10 && // 11 doesn't exist yet but it could. - release[1] < 22621; - -if (usesVibe) { - try { - vibe = require(vibePath) as unknown as typeof import("@pyke/vibe"); - } catch (error) { - console.error("Failed to load vibe.", error); - } -} - -let currentEffect: Parameters[1] | null = null; +let backgroundMaterial: "auto" | "none" | "mica" | "acrylic" | "tabbed" | null = null; ipcMain.handle( - RepluggedIpcChannels.GET_TRANSPARENCY_EFFECT, - (): Parameters[1] | null => { + RepluggedIpcChannels.GET_BACKGROUND_MATERIAL, + (): "auto" | "none" | "mica" | "acrylic" | "tabbed" | null => { if (process.platform !== "win32") { - console.warn("GET_TRANSPARENCY_EFFECT only works on Windows"); + console.warn("GET_BACKGROUND_MATERIAL only works on Windows"); } - return currentEffect; + return backgroundMaterial; }, ); ipcMain.handle( - RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, - (_, effect: Parameters[1] | null) => { + RepluggedIpcChannels.SET_BACKGROUND_MATERIAL, + (_, material: "auto" | "none" | "mica" | "acrylic" | "tabbed" | null) => { if (process.platform !== "win32") { - console.warn("APPLY_TRANSPARENCY_EFFECT only works on Windows"); + console.warn("SET_BACKGROUND_MATERIAL only works on Windows"); return; } let windows = BrowserWindow.getAllWindows(); windows.forEach((window) => { - if (!usesVibe) { - // The valid options for setBackgroundMaterial are "auto" | "none" | "mica" | "acrylic" | "tabbed". - // This goes against vibe which allows for "unified-acrylic" and "blurbehind". - // Also, vibe does not allow for "auto", "none" or "tabbed" - - // @ts-expect-error Only exists in electron 24+, our types don't have this. - window.setBackgroundMaterial(effect === null ? "none" : effect); // NULL is used to disable. - } else if (effect === null) { - vibe.clearEffects(window); - } else { - vibe.applyEffect(window, effect); - } + // @ts-expect-error standalone-electron-types is not updated to have this. + window.setBackgroundMaterial(typeof material === "string" ? material : "none"); }); - currentEffect = effect; + backgroundMaterial = material; }, ); @@ -77,3 +45,29 @@ ipcMain.handle( currentVibrancy = vibrancy; }, ); + +let currentBackgroundColor = "#00000000"; +ipcMain.handle( + RepluggedIpcChannels.GET_BACKGROUND_COLOR, + (): string => { + if (process.platform !== "win32") { + console.warn("SET_BACKGROUND_COLOR only works on Windows"); + } + + return currentBackgroundColor; + } +) + +ipcMain.handle( + RepluggedIpcChannels.SET_BACKGROUND_COLOR, + (_, color: string | undefined) => { + if (process.platform !== "win32") { + console.warn("SET_BACKGROUND_COLOR only works on Windows"); + return; + } + + let windows = BrowserWindow.getAllWindows(); + windows.forEach((window) => window.setBackgroundColor(color || "#00000000")); + currentBackgroundColor = color || "#00000000"; + }, +); diff --git a/src/preload.ts b/src/preload.ts index a7560ec52..37dc5778a 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -17,8 +17,6 @@ import type { RepluggedPlugin, RepluggedTheme, } from "./types"; -// Note that this may ONLY be used for types. -import vibe from "@pyke/vibe"; let version = ""; void ipcRenderer.invoke(RepluggedIpcChannels.GET_REPLUGGED_VERSION).then((v) => { @@ -106,10 +104,14 @@ const RepluggedNative = { }, transparency: { - getEffect: (): Promise[1]> => - ipcRenderer.invoke(RepluggedIpcChannels.GET_TRANSPARENCY_EFFECT), - applyEffect: (effect: Parameters[1]): Promise => - ipcRenderer.invoke(RepluggedIpcChannels.APPLY_TRANSPARENCY_EFFECT, effect), + getBackgroundMaterial: (): Promise<"auto" | "none" | "mica" | "acrylic" | "tabbed"> => + ipcRenderer.invoke(RepluggedIpcChannels.GET_BACKGROUND_MATERIAL), + setBackgroundMaterial: (effect: "auto" | "none" | "mica" | "acrylic" | "tabbed"): Promise => + ipcRenderer.invoke(RepluggedIpcChannels.SET_BACKGROUND_MATERIAL, effect), + getBackgroundColor: (): Promise => + ipcRenderer.invoke(RepluggedIpcChannels.GET_BACKGROUND_COLOR), + setBackgroundColor: (color: string): Promise => + ipcRenderer.invoke(RepluggedIpcChannels.SET_BACKGROUND_COLOR, color), getVibrancy: (): Promise[0]> => ipcRenderer.invoke(RepluggedIpcChannels.GET_VIBRANCY), setVibrancy: ( @@ -121,7 +123,7 @@ const RepluggedNative = { getVersion: () => version, // eslint-disable-next-line @typescript-eslint/no-unused-vars - openBrowserWindow: (opts: BrowserWindowConstructorOptions) => {}, // later + openBrowserWindow: (opts: BrowserWindowConstructorOptions) => { }, // later // @todo: We probably want to move these somewhere else, but I'm putting them here for now because I'm too lazy to set anything else up }; diff --git a/src/renderer/coremods/settings/pages/General.tsx b/src/renderer/coremods/settings/pages/General.tsx index d07f0aa48..e687191f8 100644 --- a/src/renderer/coremods/settings/pages/General.tsx +++ b/src/renderer/coremods/settings/pages/General.tsx @@ -120,8 +120,8 @@ export const General = (): React.ReactElement => { DiscordNative.process.platform === "win32") && ( {DiscordNative.process.platform === "linux" - ? Messages.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_LINUX.format() - : Messages.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_WINDOWS.format()} + ? intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_LINUX, {}) + : intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_WINDOWS, {})} )} @@ -131,8 +131,8 @@ export const General = (): React.ReactElement => { transOnChange(value); restartModal(true); }} - note={Messages.REPLUGGED_SETTINGS_TRANSPARENT_DESC.format()}> - {Messages.REPLUGGED_SETTINGS_TRANSPARENT} + note={intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_DESC, {})}> + {intl.string(t.REPLUGGED_SETTINGS_TRANSPARENT)} { switch (DiscordNative.process.platform) { case "win32": { - const transparencyEffect = getRootStringProperty("--window-win-blur"); - if (transparencyEffect === (await RepluggedNative.transparency.getEffect())) { - return; + const backgroundMaterial = getRootStringProperty("--window-background-material"); + if (backgroundMaterial !== (await RepluggedNative.transparency.getBackgroundMaterial())) { + logger.log('Setting background material to:', backgroundMaterial); + // @ts-expect-error @todo: Check if the transparency effect is valid? + await RepluggedNative.transparency.setBackgroundMaterial(backgroundMaterial); } - // @ts-expect-error @todo: Check if the transparency effect is valid? - await RepluggedNative.transparency.applyEffect(transparencyEffect); + const backgroundColor = getRootProperty("--window-background-color"); + if (backgroundColor !== (await RepluggedNative.transparency.getBackgroundColor())) { + logger.log('Setting background color to:', backgroundColor); + await RepluggedNative.transparency.setBackgroundColor(backgroundColor); + } break; } case "darwin": { const vibrancy = getRootStringProperty("--window-vibrancy"); if (vibrancy === (await RepluggedNative.transparency.getVibrancy())) { - return; + break; } + logger.log('Setting vibrancy effect to:', vibrancy); // @ts-expect-error @todo: Check if the vibrancy is valid? await RepluggedNative.transparency.setVibrancy(vibrancy); break; diff --git a/src/types/index.ts b/src/types/index.ts index 83eb351d4..e4bf46528 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -32,10 +32,12 @@ export enum RepluggedIpcChannels { OPEN_QUICKCSS_FOLDER = "REPLUGGED_OPEN_QUICKCSS_FOLDER", GET_REPLUGGED_VERSION = "REPLUGGED_GET_REPLUGGED_VERSION", DOWNLOAD_REACT_DEVTOOLS = "REPLUGGED_DOWNLOAD_REACT_DEVTOOLS", - GET_TRANSPARENCY_EFFECT = "REPLUGGED_GET_TRANSPARENCY_EFFECT", - APPLY_TRANSPARENCY_EFFECT = "REPLUGGED_APPLY_TRANSPARENCY_EFFECT", + GET_BACKGROUND_MATERIAL = "REPLUGGED_GET_BACKGROUND_MATERIAL", + SET_BACKGROUND_MATERIAL = "REPLUGGED_SET_BACKGROUND_MATERIAL", GET_VIBRANCY = "REPLUGGED_GET_VIBRANCY", SET_VIBRANCY = "REPLUGGED_SET_VIBRANCY", + GET_BACKGROUND_COLOR = "REPLUGGED_GET_BACKGROUND_COLOR", + SET_BACKGROUND_COLOR = "REPLUGGED_SET_BACKGROUND_COLOR", } export interface RepluggedAnnouncement { diff --git a/src/vibe.node b/src/vibe.node deleted file mode 100644 index dd6fbe432e55948d87dd742361755e6731b73ada..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188928 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

|`4PY0E2snfjCu(=V;8!;2 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 Date: Tue, 14 Jan 2025 22:49:03 -0500 Subject: [PATCH 30/39] Remove old cspell definitions --- cspell.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/cspell.json b/cspell.json index 16e1f64d1..f3441177c 100644 --- a/cspell.json +++ b/cspell.json @@ -8,7 +8,6 @@ "asar", "automod", "autosize", - "backoff", "blurbehind", "blurple", "channeltextarea", @@ -50,7 +49,6 @@ "outfile", "popout", "Promisable", - "pyke", "quickcss", "RATELIMITED", "rauenzi", From aa992d01adbdccca6add3e4bdd124c56a94904e2 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Tue, 14 Jan 2025 22:49:29 -0500 Subject: [PATCH 31/39] Remove cspell blurbehind definition --- cspell.json | 1 - 1 file changed, 1 deletion(-) diff --git a/cspell.json b/cspell.json index f3441177c..bfdff9467 100644 --- a/cspell.json +++ b/cspell.json @@ -8,7 +8,6 @@ "asar", "automod", "autosize", - "blurbehind", "blurple", "channeltextarea", "Chunkdiscord", From b2a80663566bd2673fac35e8e32d02841bf4dec2 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Tue, 14 Jan 2025 22:53:14 -0500 Subject: [PATCH 32/39] Add unmaximize cspell and prettier --- cspell.json | 2 ++ src/main/index.ts | 34 ++++++++++++------ src/main/ipc/index.ts | 2 +- src/main/ipc/transparency.ts | 36 ++++++++----------- src/preload.ts | 7 ++-- src/renderer/apis/settings.ts | 4 +-- src/renderer/coremods/commands/commands.ts | 8 ++--- src/renderer/coremods/commands/index.ts | 12 +++---- .../coremods/settings/pages/Updater.tsx | 5 ++- src/renderer/coremods/transparency/index.ts | 10 +++--- src/renderer/util.ts | 13 ++++--- 11 files changed, 71 insertions(+), 62 deletions(-) diff --git a/cspell.json b/cspell.json index bfdff9467..ac5cc5a59 100644 --- a/cspell.json +++ b/cspell.json @@ -64,6 +64,8 @@ "uninject", "uninjector", "uninjectors", + "unmaximize", + "unmaximized", "Vendicated", "webauthn", "weblate", diff --git a/src/main/index.ts b/src/main/index.ts index 16b63a291..26465752d 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -97,9 +97,13 @@ class BrowserWindow extends electron.BrowserWindow { // Center the unmaximized location if (settings.get("transparentWindow")) { - const currentDisplay = electron.screen.getDisplayNearestPoint(electron.screen.getCursorScreenPoint()) - this.repluggedPreviousBounds.x = currentDisplay.workArea.width / 2 - this.repluggedPreviousBounds.width / 2; - this.repluggedPreviousBounds.y = currentDisplay.workArea.height / 2 - this.repluggedPreviousBounds.height / 2; + const currentDisplay = electron.screen.getDisplayNearestPoint( + electron.screen.getCursorScreenPoint(), + ); + this.repluggedPreviousBounds.x = + currentDisplay.workArea.width / 2 - this.repluggedPreviousBounds.width / 2; + this.repluggedPreviousBounds.y = + currentDisplay.workArea.height / 2 - this.repluggedPreviousBounds.height / 2; this.maximize = this.repluggedToggleMaximize; this.unmaximize = this.repluggedToggleMaximize; } @@ -107,28 +111,36 @@ class BrowserWindow extends electron.BrowserWindow { (this.webContents as RepluggedWebContents).originalPreload = originalPreload; } - private repluggedPreviousBounds: Electron.Rectangle = { width: 1400, height: 900, x: 0, - y: 0 + y: 0, }; public repluggedToggleMaximize(): void { // Determine whether the display is actually maximized already let currentBounds = this.getBounds(); - const currentDisplay = electron.screen.getDisplayNearestPoint(electron.screen.getCursorScreenPoint()); + const currentDisplay = electron.screen.getDisplayNearestPoint( + electron.screen.getCursorScreenPoint(), + ); const workAreaSize = currentDisplay.workArea; - if (currentBounds.width === workAreaSize.width && currentBounds.height === workAreaSize.height) { + if ( + currentBounds.width === workAreaSize.width && + currentBounds.height === workAreaSize.height + ) { // Un-maximize - this.setBounds(this.repluggedPreviousBounds) + this.setBounds(this.repluggedPreviousBounds); return; } - - this.repluggedPreviousBounds = this.getBounds() - this.setBounds({ x: workAreaSize.x + 1, y: workAreaSize.y + 1, width: workAreaSize.width, height: workAreaSize.height }) + this.repluggedPreviousBounds = this.getBounds(); + this.setBounds({ + x: workAreaSize.x + 1, + y: workAreaSize.y + 1, + width: workAreaSize.width, + height: workAreaSize.height, + }); } } diff --git a/src/main/ipc/index.ts b/src/main/ipc/index.ts index 102c9e8d9..6878491b7 100644 --- a/src/main/ipc/index.ts +++ b/src/main/ipc/index.ts @@ -6,7 +6,7 @@ import "./quick-css"; import "./react-devtools"; import "./settings"; import "./themes"; -import './transparency'; +import "./transparency"; ipcMain.on(RepluggedIpcChannels.GET_DISCORD_PRELOAD, (event) => { event.returnValue = (event.sender as RepluggedWebContents).originalPreload; diff --git a/src/main/ipc/transparency.ts b/src/main/ipc/transparency.ts index 01ba4ea3d..d582c2cc0 100644 --- a/src/main/ipc/transparency.ts +++ b/src/main/ipc/transparency.ts @@ -47,27 +47,21 @@ ipcMain.handle( ); let currentBackgroundColor = "#00000000"; -ipcMain.handle( - RepluggedIpcChannels.GET_BACKGROUND_COLOR, - (): string => { - if (process.platform !== "win32") { - console.warn("SET_BACKGROUND_COLOR only works on Windows"); - } - - return currentBackgroundColor; +ipcMain.handle(RepluggedIpcChannels.GET_BACKGROUND_COLOR, (): string => { + if (process.platform !== "win32") { + console.warn("SET_BACKGROUND_COLOR only works on Windows"); } -) -ipcMain.handle( - RepluggedIpcChannels.SET_BACKGROUND_COLOR, - (_, color: string | undefined) => { - if (process.platform !== "win32") { - console.warn("SET_BACKGROUND_COLOR only works on Windows"); - return; - } + return currentBackgroundColor; +}); - let windows = BrowserWindow.getAllWindows(); - windows.forEach((window) => window.setBackgroundColor(color || "#00000000")); - currentBackgroundColor = color || "#00000000"; - }, -); +ipcMain.handle(RepluggedIpcChannels.SET_BACKGROUND_COLOR, (_, color: string | undefined) => { + if (process.platform !== "win32") { + console.warn("SET_BACKGROUND_COLOR only works on Windows"); + return; + } + + let windows = BrowserWindow.getAllWindows(); + windows.forEach((window) => window.setBackgroundColor(color || "#00000000")); + currentBackgroundColor = color || "#00000000"; +}); diff --git a/src/preload.ts b/src/preload.ts index 37dc5778a..42f4e2cbd 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -106,8 +106,9 @@ const RepluggedNative = { transparency: { getBackgroundMaterial: (): Promise<"auto" | "none" | "mica" | "acrylic" | "tabbed"> => ipcRenderer.invoke(RepluggedIpcChannels.GET_BACKGROUND_MATERIAL), - setBackgroundMaterial: (effect: "auto" | "none" | "mica" | "acrylic" | "tabbed"): Promise => - ipcRenderer.invoke(RepluggedIpcChannels.SET_BACKGROUND_MATERIAL, effect), + setBackgroundMaterial: ( + effect: "auto" | "none" | "mica" | "acrylic" | "tabbed", + ): Promise => ipcRenderer.invoke(RepluggedIpcChannels.SET_BACKGROUND_MATERIAL, effect), getBackgroundColor: (): Promise => ipcRenderer.invoke(RepluggedIpcChannels.GET_BACKGROUND_COLOR), setBackgroundColor: (color: string): Promise => @@ -123,7 +124,7 @@ const RepluggedNative = { getVersion: () => version, // eslint-disable-next-line @typescript-eslint/no-unused-vars - openBrowserWindow: (opts: BrowserWindowConstructorOptions) => { }, // later + openBrowserWindow: (opts: BrowserWindowConstructorOptions) => {}, // later // @todo: We probably want to move these somewhere else, but I'm putting them here for now because I'm too lazy to set anything else up }; diff --git a/src/renderer/apis/settings.ts b/src/renderer/apis/settings.ts index 2cdfd9a51..93708dd52 100644 --- a/src/renderer/apis/settings.ts +++ b/src/renderer/apis/settings.ts @@ -57,8 +57,8 @@ export class SettingsManager, D extends ke ): K extends D ? NonNullable : F extends null | undefined - ? T[K] | undefined - : NonNullable | F { + ? T[K] | undefined + : NonNullable | F { if (typeof this.#settings === "undefined") { throw new Error(`Settings not loaded for namespace ${this.namespace}`); } diff --git a/src/renderer/coremods/commands/commands.ts b/src/renderer/coremods/commands/commands.ts index af1c18bab..26a5f34c5 100644 --- a/src/renderer/coremods/commands/commands.ts +++ b/src/renderer/coremods/commands/commands.ts @@ -352,8 +352,8 @@ export function loadCommands(): void { listType === "enabled" ? enabledString : listType === "disabled" - ? disabledString - : `${enabledString}\n\n${disabledString}`; + ? disabledString + : `${enabledString}\n\n${disabledString}`; return { send, @@ -384,8 +384,8 @@ export function loadCommands(): void { listType === "enabled" ? enabledString : listType === "disabled" - ? disabledString - : `${enabledString}\n\n${disabledString}`; + ? disabledString + : `${enabledString}\n\n${disabledString}`; return { send, diff --git a/src/renderer/coremods/commands/index.ts b/src/renderer/coremods/commands/index.ts index 86d167a4d..ec168606b 100644 --- a/src/renderer/coremods/commands/index.ts +++ b/src/renderer/coremods/commands/index.ts @@ -136,9 +136,9 @@ async function injectApplicationCommandIndexStore(): Promise { } else { res.commands = Array.isArray(res.commands) ? [ - ...commandsToAdd, - ...res.commands.filter((command) => !commandsToAdd.includes(command)), - ] + ...commandsToAdd, + ...res.commands.filter((command) => !commandsToAdd.includes(command)), + ] : commandsToAdd; } } @@ -211,9 +211,9 @@ async function injectApplicationCommandIndexStore(): Promise { .flat(10); res.commands = Array.isArray(res.commands) ? [ - ...commandsToAdd, - ...res.commands.filter((command) => !commandsToAdd.includes(command)), - ] + ...commandsToAdd, + ...res.commands.filter((command) => !commandsToAdd.includes(command)), + ] : commandsToAdd; } diff --git a/src/renderer/coremods/settings/pages/Updater.tsx b/src/renderer/coremods/settings/pages/Updater.tsx index c6eae1ab1..a799f8250 100644 --- a/src/renderer/coremods/settings/pages/Updater.tsx +++ b/src/renderer/coremods/settings/pages/Updater.tsx @@ -24,9 +24,8 @@ const logger = Logger.coremod("Settings:Updater"); export const Updater = (): React.ReactElement => { const [checking, setChecking] = React.useState(false); - const [updatesAvailable, setUpdatesAvailable] = React.useState< - Array - >(getAvailableUpdates()); + const [updatesAvailable, setUpdatesAvailable] = + React.useState>(getAvailableUpdates()); const [updatePromises, setUpdatePromises] = React.useState>>({}); const [didInstallAll, setDidInstallAll] = React.useState(false); const [lastChecked, setLastChecked] = useSettingArray(updaterSettings, "lastChecked"); diff --git a/src/renderer/coremods/transparency/index.ts b/src/renderer/coremods/transparency/index.ts index af7b0912d..4c582877b 100644 --- a/src/renderer/coremods/transparency/index.ts +++ b/src/renderer/coremods/transparency/index.ts @@ -49,15 +49,17 @@ export function start(): void { switch (DiscordNative.process.platform) { case "win32": { const backgroundMaterial = getRootStringProperty("--window-background-material"); - if (backgroundMaterial !== (await RepluggedNative.transparency.getBackgroundMaterial())) { - logger.log('Setting background material to:', backgroundMaterial); + if ( + backgroundMaterial !== (await RepluggedNative.transparency.getBackgroundMaterial()) + ) { + logger.log("Setting background material to:", backgroundMaterial); // @ts-expect-error @todo: Check if the transparency effect is valid? await RepluggedNative.transparency.setBackgroundMaterial(backgroundMaterial); } const backgroundColor = getRootProperty("--window-background-color"); if (backgroundColor !== (await RepluggedNative.transparency.getBackgroundColor())) { - logger.log('Setting background color to:', backgroundColor); + logger.log("Setting background color to:", backgroundColor); await RepluggedNative.transparency.setBackgroundColor(backgroundColor); } break; @@ -68,7 +70,7 @@ export function start(): void { break; } - logger.log('Setting vibrancy effect to:', vibrancy); + logger.log("Setting vibrancy effect to:", vibrancy); // @ts-expect-error @todo: Check if the vibrancy is valid? await RepluggedNative.transparency.setVibrancy(vibrancy); break; diff --git a/src/renderer/util.ts b/src/renderer/util.ts index fadacfec5..5818500e4 100644 --- a/src/renderer/util.ts +++ b/src/renderer/util.ts @@ -197,8 +197,8 @@ export function useSetting< value: K extends D ? NonNullable : F extends null | undefined - ? T[K] | undefined - : NonNullable | F; + ? T[K] | undefined + : NonNullable | F; onChange: (newValue: ValType) => void; } { const initial = settings.get(key, fallback); @@ -237,8 +237,8 @@ export function useSettingArray< K extends D ? NonNullable : F extends null | undefined - ? T[K] | undefined - : NonNullable | F, + ? T[K] | undefined + : NonNullable | F, (newValue: ValType) => void, ] { const { value, onChange } = useSetting(settings, key, fallback); @@ -256,9 +256,8 @@ type UnionToIntersection = (U extends never ? never : (k: U) => void) extends type ObjectType = Record; -type ExtractObjectType = O extends Array - ? UnionToIntersection - : never; +type ExtractObjectType = + O extends Array ? UnionToIntersection : never; export function virtualMerge(...objects: O): ExtractObjectType { const fallback = {}; From ff063ca71c49f696ce591f9c96c2796a6bc46ed3 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Wed, 15 Jan 2025 20:37:51 -0500 Subject: [PATCH 33/39] "hook" (un)maximize more cleanly --- src/main/index.ts | 90 +++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 26465752d..8f5242bbb 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -74,7 +74,6 @@ class BrowserWindow extends electron.BrowserWindow { switch (process.platform) { case "win32": opts.transparent = true; - opts.backgroundColor = "#00000000"; break; case "linux": opts.transparent = true; @@ -97,50 +96,57 @@ class BrowserWindow extends electron.BrowserWindow { // Center the unmaximized location if (settings.get("transparentWindow")) { - const currentDisplay = electron.screen.getDisplayNearestPoint( - electron.screen.getCursorScreenPoint(), - ); - this.repluggedPreviousBounds.x = - currentDisplay.workArea.width / 2 - this.repluggedPreviousBounds.width / 2; - this.repluggedPreviousBounds.y = - currentDisplay.workArea.height / 2 - this.repluggedPreviousBounds.height / 2; - this.maximize = this.repluggedToggleMaximize; - this.unmaximize = this.repluggedToggleMaximize; - } - - (this.webContents as RepluggedWebContents).originalPreload = originalPreload; - } - - private repluggedPreviousBounds: Electron.Rectangle = { - width: 1400, - height: 900, - x: 0, - y: 0, - }; + let lastBounds = this.getBounds(); + // Default to the center of the screen at 1440x810 scale for a 1080p monitor (75%) + let primaryDisplaySize = electron.screen.getPrimaryDisplay().workAreaSize; + let lastLastBounds = { + width: primaryDisplaySize.width * 0.75, + height: primaryDisplaySize.height * 0.75, + x: primaryDisplaySize.width / 2 - primaryDisplaySize.width * 0.75 / 2, + y: primaryDisplaySize.height / 2 - primaryDisplaySize.height * 0.75 / 2, + }; + let lastResize = Date.now(); + this.on('resize', () => { + const bounds = this.getBounds(); + lastLastBounds = lastBounds; + lastBounds = bounds; + lastResize = Date.now(); + }); + + this.on('maximize', () => { + // Get the display at the center of the window + const screenBounds = this.getBounds(); + const windowDisplay = electron.screen.getDisplayNearestPoint({ x: screenBounds.x + screenBounds.width / 2, y: screenBounds.y + screenBounds.height / 2 }); + const workAreaSize = windowDisplay.workArea; + + const isSizeMaximized = lastBounds.width === workAreaSize.width && lastBounds.height === workAreaSize.height; + const isPositionMaximized = (lastBounds.x === workAreaSize.x + 1 && lastBounds.y === workAreaSize.y + 1); + + // if we haven't resized in the last few ms, we probably didn't actually maximize and should instead unmaximize + if (lastResize < Date.now() - 10 || (isSizeMaximized && isPositionMaximized)) { + // Calculate new x, y to be in the center of the monitor + this.setBounds({ + x: workAreaSize.width / 2 - lastLastBounds.width / 2 + workAreaSize.x, + y: workAreaSize.height / 2 - lastLastBounds.height / 2 + workAreaSize.y, + width: lastLastBounds.width, + height: lastLastBounds.height, + }); + + lastResize = Date.now(); + return; + } - public repluggedToggleMaximize(): void { - // Determine whether the display is actually maximized already - let currentBounds = this.getBounds(); - const currentDisplay = electron.screen.getDisplayNearestPoint( - electron.screen.getCursorScreenPoint(), - ); - const workAreaSize = currentDisplay.workArea; - if ( - currentBounds.width === workAreaSize.width && - currentBounds.height === workAreaSize.height - ) { - // Un-maximize - this.setBounds(this.repluggedPreviousBounds); - return; + // Move the window to 1,1 to mitigate the window going grey when maximized + this.setBounds({ + x: workAreaSize.x + 1, + y: workAreaSize.y + 1, + width: screenBounds.width, + height: screenBounds.height, + }); + }); } - this.repluggedPreviousBounds = this.getBounds(); - this.setBounds({ - x: workAreaSize.x + 1, - y: workAreaSize.y + 1, - width: workAreaSize.width, - height: workAreaSize.height, - }); + (this.webContents as RepluggedWebContents).originalPreload = originalPreload; } } From 3551af4068a9a77d013820dd0f1ea21b997af111 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Thu, 16 Jan 2025 13:45:22 -0500 Subject: [PATCH 34/39] Add note about maximization --- src/main/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/index.ts b/src/main/index.ts index 8f5242bbb..4d26f57a3 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -137,6 +137,7 @@ class BrowserWindow extends electron.BrowserWindow { } // Move the window to 1,1 to mitigate the window going grey when maximized + // Note that the window doesn't seem to visually be at 1,1, but that's enough to prevent the greying this.setBounds({ x: workAreaSize.x + 1, y: workAreaSize.y + 1, From 36932d9ea4b07d666554ffa4b5bae3a8fb79f605 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Thu, 16 Jan 2025 13:48:24 -0500 Subject: [PATCH 35/39] Add ColorPicker component --- src/renderer/modules/common/components.ts | 6 ++++ .../modules/components/ColorPicker.ts | 32 +++++++++++++++++++ .../components/ColorPickerCustomButton.ts | 15 +++++++++ .../components/ColorPickerDefaultButton.ts | 15 +++++++++ 4 files changed, 68 insertions(+) create mode 100644 src/renderer/modules/components/ColorPicker.ts create mode 100644 src/renderer/modules/components/ColorPickerCustomButton.ts create mode 100644 src/renderer/modules/components/ColorPickerDefaultButton.ts diff --git a/src/renderer/modules/common/components.ts b/src/renderer/modules/common/components.ts index 8d3484076..455882013 100644 --- a/src/renderer/modules/common/components.ts +++ b/src/renderer/modules/common/components.ts @@ -19,6 +19,9 @@ import type { TextInputType } from "../components/TextInput"; import type { OriginalTooltipType } from "../components/Tooltip"; import { waitForProps } from "../webpack"; import type { CreateToast, ShowToast } from "./toast"; +import { ColorPickerType } from "@components/ColorPicker"; +import { ColorPickerCustomButtonType } from "@components/ColorPickerCustomButton"; +import { ColorPickerDefaultButtonType } from "@components/ColorPickerDefaultButton"; // Expand this as needed interface DiscordComponents { @@ -56,6 +59,9 @@ interface DiscordComponents { TextArea: TextAreaType; TextInput: TextInputType; Tooltip: OriginalTooltipType; + ColorPicker: ColorPickerType; + ColorPickerCustomButton: ColorPickerCustomButtonType; + ColorPickerDefaultButton: ColorPickerDefaultButtonType; } export default await waitForProps("FormText", "MenuItem"); diff --git a/src/renderer/modules/components/ColorPicker.ts b/src/renderer/modules/components/ColorPicker.ts new file mode 100644 index 000000000..3d298ab28 --- /dev/null +++ b/src/renderer/modules/components/ColorPicker.ts @@ -0,0 +1,32 @@ +import type React from "react"; +import components from "../common/components"; + +// From Tooltip.tsx +const Positions = { + TOP: "top", + BOTTOM: "bottom", + LEFT: "left", + RIGHT: "right", + CENTER: "center", + WINDOW_CENTER: "window_center", +} as const; + +interface ColorPickerProps { + className?: string, + defaultColor?: number, + customColor?: number, + colors: number[], + value?: number, + disabled?: boolean, + onChange?: (value: number, name: string) => void; + renderDefaultButton: (props: object) => React.ReactElement, + renderCustomButton: (props: object) => React.ReactElement, + colorContainerClassName?: string + customPickerPosition?: (typeof Positions)[keyof typeof Positions]; +} + +export type ColorPickerType = React.ComponentClass & { + defaultProps: ColorPickerProps; +}; + +export default components.ColorPicker; diff --git a/src/renderer/modules/components/ColorPickerCustomButton.ts b/src/renderer/modules/components/ColorPickerCustomButton.ts new file mode 100644 index 000000000..08feff634 --- /dev/null +++ b/src/renderer/modules/components/ColorPickerCustomButton.ts @@ -0,0 +1,15 @@ +import type React from "react"; +import components from "../common/components"; + +interface ColorPickerCustomButtonProps { + color?: number, + value?: number, + disabled?: boolean, + onChange?: (value: number, name: string) => void; +} + +export type ColorPickerCustomButtonType = React.ComponentClass & { + defaultProps: ColorPickerCustomButtonProps; +}; + +export default components.ColorPickerCustomButton; diff --git a/src/renderer/modules/components/ColorPickerDefaultButton.ts b/src/renderer/modules/components/ColorPickerDefaultButton.ts new file mode 100644 index 000000000..5d05807ab --- /dev/null +++ b/src/renderer/modules/components/ColorPickerDefaultButton.ts @@ -0,0 +1,15 @@ +import type React from "react"; +import components from "../common/components"; + +interface ColorPickerDefaultButtonProps { + customColor?: number, + value?: number, + disabled?: boolean, + "aria-label"?: string; +} + +export type ColorPickerDefaultButtonType = React.ComponentClass & { + defaultProps: ColorPickerDefaultButtonProps; +}; + +export default components.ColorPickerDefaultButton; From b0bd3a828f0e6963d2ad442e1202cced161b0546 Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Thu, 16 Jan 2025 13:48:58 -0500 Subject: [PATCH 36/39] Abstract transparency coremod functions --- src/renderer/coremods/transparency/index.ts | 61 ++++++++++++--------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/src/renderer/coremods/transparency/index.ts b/src/renderer/coremods/transparency/index.ts index 4c582877b..ef2405fd3 100644 --- a/src/renderer/coremods/transparency/index.ts +++ b/src/renderer/coremods/transparency/index.ts @@ -1,4 +1,5 @@ import { Logger } from "@replugged"; +import { generalSettings } from "../settings/pages/General"; let observer: MutationObserver; @@ -16,6 +17,38 @@ function getRootStringProperty(property: string): string { const logger = Logger.coremod("Transparency"); +async function updateBackgroundMaterial(): Promise { + if (generalSettings.get("overrideWindowBackgroundMaterial")) return; + + const backgroundMaterial = getRootStringProperty("--window-background-material"); + if (backgroundMaterial !== (await RepluggedNative.transparency.getBackgroundMaterial())) { + logger.log("Setting background material to:", backgroundMaterial); + // @ts-expect-error @todo: Check if the transparency effect is valid? + await RepluggedNative.transparency.setBackgroundMaterial(backgroundMaterial); + } +} + +async function updateBackgroundColor(): Promise { + if (generalSettings.get("overrideWindowBackgroundColor")) return; + + const backgroundColor = getRootProperty("--window-background-color"); + if (backgroundColor !== (await RepluggedNative.transparency.getBackgroundColor())) { + logger.log("Setting background color to:", backgroundColor); + await RepluggedNative.transparency.setBackgroundColor(backgroundColor); + } +} + +async function updateVibrancy(): Promise { + if (generalSettings.get("overrideWindowBackgroundMaterial")) return; + + const vibrancy = getRootStringProperty("--window-vibrancy"); + if (vibrancy !== (await RepluggedNative.transparency.getVibrancy())) { + logger.log("Setting vibrancy effect to:", vibrancy); + // @ts-expect-error @todo: Check if the vibrancy is valid? + await RepluggedNative.transparency.setVibrancy(vibrancy); + } +} + export function start(): void { let html = document.body.parentElement!; @@ -41,38 +74,14 @@ export function start(): void { } if (cssModified) { - // Originally this used requestAnimationFrame but it took too long - // so instead we setTimeout and pray. The setTimeout could be - // shorter if we wanted, but it's hard to say if it would - // work as consistently. setTimeout(async () => { switch (DiscordNative.process.platform) { case "win32": { - const backgroundMaterial = getRootStringProperty("--window-background-material"); - if ( - backgroundMaterial !== (await RepluggedNative.transparency.getBackgroundMaterial()) - ) { - logger.log("Setting background material to:", backgroundMaterial); - // @ts-expect-error @todo: Check if the transparency effect is valid? - await RepluggedNative.transparency.setBackgroundMaterial(backgroundMaterial); - } - - const backgroundColor = getRootProperty("--window-background-color"); - if (backgroundColor !== (await RepluggedNative.transparency.getBackgroundColor())) { - logger.log("Setting background color to:", backgroundColor); - await RepluggedNative.transparency.setBackgroundColor(backgroundColor); - } + await Promise.all([updateBackgroundMaterial(), updateBackgroundColor()]); break; } case "darwin": { - const vibrancy = getRootStringProperty("--window-vibrancy"); - if (vibrancy === (await RepluggedNative.transparency.getVibrancy())) { - break; - } - - logger.log("Setting vibrancy effect to:", vibrancy); - // @ts-expect-error @todo: Check if the vibrancy is valid? - await RepluggedNative.transparency.setVibrancy(vibrancy); + await updateVibrancy(); break; } } From e18ff13edc0d36710e496548e8e79222d85ec7dc Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Thu, 16 Jan 2025 15:35:26 -0500 Subject: [PATCH 37/39] Export transparency coremod functions --- src/renderer/coremods/transparency/index.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/renderer/coremods/transparency/index.ts b/src/renderer/coremods/transparency/index.ts index ef2405fd3..181f0953d 100644 --- a/src/renderer/coremods/transparency/index.ts +++ b/src/renderer/coremods/transparency/index.ts @@ -1,5 +1,11 @@ import { Logger } from "@replugged"; -import { generalSettings } from "../settings/pages/General"; +import { type GeneralSettings, defaultSettings } from "src/types"; +import * as settings from "../../apis/settings"; + +const generalSettings = await settings.init( + "dev.replugged.Settings", + defaultSettings, +); let observer: MutationObserver; @@ -17,7 +23,7 @@ function getRootStringProperty(property: string): string { const logger = Logger.coremod("Transparency"); -async function updateBackgroundMaterial(): Promise { +export async function updateBackgroundMaterial(): Promise { if (generalSettings.get("overrideWindowBackgroundMaterial")) return; const backgroundMaterial = getRootStringProperty("--window-background-material"); @@ -28,7 +34,7 @@ async function updateBackgroundMaterial(): Promise { } } -async function updateBackgroundColor(): Promise { +export async function updateBackgroundColor(): Promise { if (generalSettings.get("overrideWindowBackgroundColor")) return; const backgroundColor = getRootProperty("--window-background-color"); @@ -38,7 +44,7 @@ async function updateBackgroundColor(): Promise { } } -async function updateVibrancy(): Promise { +export async function updateVibrancy(): Promise { if (generalSettings.get("overrideWindowBackgroundMaterial")) return; const vibrancy = getRootStringProperty("--window-vibrancy"); From 744e991640350677111173c727c9d32982bc7c4a Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Thu, 16 Jan 2025 16:13:49 -0500 Subject: [PATCH 38/39] Implement override settings for transparency --- .../coremods/settings/pages/General.tsx | 322 ++++++++++++++++-- src/types/settings.ts | 12 + 2 files changed, 310 insertions(+), 24 deletions(-) diff --git a/src/renderer/coremods/settings/pages/General.tsx b/src/renderer/coremods/settings/pages/General.tsx index e687191f8..adebd44da 100644 --- a/src/renderer/coremods/settings/pages/General.tsx +++ b/src/renderer/coremods/settings/pages/General.tsx @@ -9,6 +9,7 @@ import { Flex, FormItem, Notice, + SelectItem, SwitchItem, Text, TextInput, @@ -19,6 +20,14 @@ import { type GeneralSettings, defaultSettings } from "src/types"; import * as settings from "../../../apis/settings"; import * as util from "../../../util"; import { initWs, socket } from "../../devCompanion"; +import ColorPicker from "@components/ColorPicker"; +import ColorPickerCustomButton from "@components/ColorPickerCustomButton"; +import ColorPickerDefaultButton from "@components/ColorPickerDefaultButton"; +import { + updateBackgroundColor, + updateBackgroundMaterial, + updateVibrancy, +} from "../../transparency"; export const generalSettings = await settings.init( "dev.replugged.Settings", @@ -50,18 +59,30 @@ function restartModal(doRelaunch = false, onConfirm?: () => void, onCancel?: () } export const General = (): React.ReactElement => { - const { value: expValue, onChange: expOnChange } = util.useSetting( + const [expValue, expOnChange] = util.useSettingArray(generalSettings, "experiments"); + const [rdtValue, rdtOnChange] = util.useSettingArray(generalSettings, "reactDevTools"); + const [transValue, transOnChange] = util.useSettingArray(generalSettings, "transparentWindow"); + const [overrideBgColValue, overrideBgColOnChange] = util.useSettingArray( + generalSettings, + "overrideWindowBackgroundColor", + ); + const [bgColValue, bgColOnChange] = util.useSettingArray( + generalSettings, + "windowBackgroundColor", + ); + const [overrideBgMatValue, overrideBgMatOnChange] = util.useSettingArray( generalSettings, - "experiments", + "overrideWindowBackgroundMaterial", ); - const { value: rdtValue, onChange: rdtOnChange } = util.useSetting( + const [bgMatValue, bgMatOnChange] = util.useSettingArray( generalSettings, - "reactDevTools", + "windowBackgroundMaterial", ); - const { value: transValue, onChange: transOnChange } = util.useSetting( + const [overrideVibrancyValue, overrideVibrancyOnChange] = util.useSettingArray( generalSettings, - "transparentWindow", + "overrideWindowVibrancy", ); + const [vibrancyValue, vibrancyOnChange] = util.useSettingArray(generalSettings, "windowVibrancy"); const [kKeys, setKKeys] = React.useState([]); @@ -115,25 +136,278 @@ export const General = (): React.ReactElement => { {intl.string(t.REPLUGGED_SETTINGS_QUICKCSS_AUTO_APPLY)} -

- {(DiscordNative.process.platform === "linux" || - DiscordNative.process.platform === "win32") && ( - - {DiscordNative.process.platform === "linux" - ? intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_LINUX, {}) - : intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_WINDOWS, {})} - + + note="Window transparency settings"> +
+ {(DiscordNative.process.platform === "linux" || + DiscordNative.process.platform === "win32") && ( + + {DiscordNative.process.platform === "linux" + ? intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_LINUX, {}) + : intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_ISSUES_WINDOWS, {})} + + )} +
+ { + transOnChange(value); + restartModal(true); + }} + note={intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_DESC, {})}> + {intl.string(t.REPLUGGED_SETTINGS_TRANSPARENT)} + + + {DiscordNative.process.platform === "win32" && ( + <> + { + overrideBgColOnChange(value); + + if (value) { + void RepluggedNative.transparency.setBackgroundColor(bgColValue); + } else { + void updateBackgroundColor(); + } + }} + disabled={!transValue}> + {/* {intl.string(t.REPLUGGED_SETTINGS_OVERRIDE_BG_COLOR)} */} + Override Window Background Color + + + { + const newValue = `#${value.toString(16).padStart(6, "0").padEnd(8, "0")}`; + bgColOnChange(newValue); + void RepluggedNative.transparency.setBackgroundColor(newValue); + }} + disabled={!generalSettings.get("overrideWindowBackgroundColor") || !transValue} + customPickerPosition="right" + renderCustomButton={React.useCallback((props: object) => { + const button = ; + // return disabled ? button : + return button; + }, [])} + renderDefaultButton={React.useCallback( + (props: object) => ( + // < + + ), + [], + )} + /> + + + { + overrideBgMatOnChange(value); + if (value) { + void RepluggedNative.transparency.setBackgroundMaterial( + bgMatValue as "none" | "acrylic" | "mica" | "tabbed", + ); + } else { + // If this line is uncommented, coremods kinda die + void updateBackgroundMaterial(); + } + }} + disabled={!transValue}> + {/* {intl.string(t.REPLUGGED_SETTINGS_OVERRIDE_BG_MATERIAL)} */} + Override Window Background Material + + { + bgMatOnChange(value); + void RepluggedNative.transparency.setBackgroundMaterial( + value as "none" | "acrylic" | "mica" | "tabbed", + ); + }} + disabled={!generalSettings.get("overrideWindowBackgroundMaterial") || !transValue} + options={[ + { + label: "None", + value: "none", + }, + { + label: "Acrylic", + value: "acrylic", + }, + { + label: "Mica", + value: "mica", + }, + { + label: "Tabbed", + value: "tabbed", + }, + ]}> + Background Material + + )} -
- { - transOnChange(value); - restartModal(true); - }} - note={intl.format(t.REPLUGGED_SETTINGS_TRANSPARENT_DESC, {})}> - {intl.string(t.REPLUGGED_SETTINGS_TRANSPARENT)} - + + {DiscordNative.process.platform === "darwin" && ( + <> + {/* @todo: This should trigger the SelectItem's onChange with it's current value to apply the overridden material */} + { + overrideVibrancyOnChange(overrideVibrancyValue); + if (value) { + void RepluggedNative.transparency.setVibrancy( + vibrancyValue as + | "appearance-based" + | "light" + | "dark" + | "titlebar" + | "selection" + | "menu" + | "popover" + | "sidebar" + | "medium-light" + | "ultra-dark" + | "header" + | "sheet" + | "window" + | "hud" + | "fullscreen-ui" + | "tooltip" + | "content" + | "under-window" + | "under-page", + ); + } else { + void updateVibrancy(); + } + }} + disabled={!transValue}> + {/* {intl.string(t.REPLUGGED_SETTINGS_OVERRIDE_VIBRANCY)} */} + Override Window Vibrancy + + { + vibrancyOnChange(value); + void RepluggedNative.transparency.setVibrancy( + value as + | "appearance-based" + | "light" + | "dark" + | "titlebar" + | "selection" + | "menu" + | "popover" + | "sidebar" + | "medium-light" + | "ultra-dark" + | "header" + | "sheet" + | "window" + | "hud" + | "fullscreen-ui" + | "tooltip" + | "content" + | "under-window" + | "under-page", + ); + }} + disabled={!generalSettings.get("overrideWindowVibrancy") || !transValue} + options={[ + { + label: "Appearance-based", + value: "appearance-based", + }, + { + label: "Light", + value: "light", + }, + { + label: "Dark", + value: "dark", + }, + { + label: "Titlebar", + value: "titlebar", + }, + { + label: "Selection", + value: "selection", + }, + { + label: "Menu", + value: "menu", + }, + { + label: "Popover", + value: "popover", + }, + { + label: "Sidebar", + value: "sidebar", + }, + { + label: "Medium Light", + value: "medium-light", + }, + { + label: "Ultra Dark", + value: "ultra-dark", + }, + { + label: "Header", + value: "header", + }, + { + label: "Sheet", + value: "sheet", + }, + { + label: "Window", + value: "window", + }, + { + label: "HUD", + value: "hud", + }, + { + label: "Fullscreen UI", + value: "fullscreen-ui", + }, + { + label: "Tooltip", + value: "tooltip", + }, + { + label: "Content", + value: "content", + }, + { + label: "Under Window", + value: "under-window", + }, + { + label: "Under Page", + value: "under-page", + }, + ]}> + Vibrancy + + + )} +
; From 693efd7272cd0794e766a10be95aed03e262da7f Mon Sep 17 00:00:00 2001 From: East_Arctica Date: Thu, 16 Jan 2025 16:16:56 -0500 Subject: [PATCH 39/39] Prettier --- src/main/index.ts | 19 ++++++++++++------- .../modules/components/ColorPicker.ts | 18 +++++++++--------- .../components/ColorPickerCustomButton.ts | 6 +++--- .../components/ColorPickerDefaultButton.ts | 6 +++--- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 4d26f57a3..0a9f3d9ee 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -102,25 +102,30 @@ class BrowserWindow extends electron.BrowserWindow { let lastLastBounds = { width: primaryDisplaySize.width * 0.75, height: primaryDisplaySize.height * 0.75, - x: primaryDisplaySize.width / 2 - primaryDisplaySize.width * 0.75 / 2, - y: primaryDisplaySize.height / 2 - primaryDisplaySize.height * 0.75 / 2, + x: primaryDisplaySize.width / 2 - (primaryDisplaySize.width * 0.75) / 2, + y: primaryDisplaySize.height / 2 - (primaryDisplaySize.height * 0.75) / 2, }; let lastResize = Date.now(); - this.on('resize', () => { + this.on("resize", () => { const bounds = this.getBounds(); lastLastBounds = lastBounds; lastBounds = bounds; lastResize = Date.now(); }); - this.on('maximize', () => { + this.on("maximize", () => { // Get the display at the center of the window const screenBounds = this.getBounds(); - const windowDisplay = electron.screen.getDisplayNearestPoint({ x: screenBounds.x + screenBounds.width / 2, y: screenBounds.y + screenBounds.height / 2 }); + const windowDisplay = electron.screen.getDisplayNearestPoint({ + x: screenBounds.x + screenBounds.width / 2, + y: screenBounds.y + screenBounds.height / 2, + }); const workAreaSize = windowDisplay.workArea; - const isSizeMaximized = lastBounds.width === workAreaSize.width && lastBounds.height === workAreaSize.height; - const isPositionMaximized = (lastBounds.x === workAreaSize.x + 1 && lastBounds.y === workAreaSize.y + 1); + const isSizeMaximized = + lastBounds.width === workAreaSize.width && lastBounds.height === workAreaSize.height; + const isPositionMaximized = + lastBounds.x === workAreaSize.x + 1 && lastBounds.y === workAreaSize.y + 1; // if we haven't resized in the last few ms, we probably didn't actually maximize and should instead unmaximize if (lastResize < Date.now() - 10 || (isSizeMaximized && isPositionMaximized)) { diff --git a/src/renderer/modules/components/ColorPicker.ts b/src/renderer/modules/components/ColorPicker.ts index 3d298ab28..1ee8910a5 100644 --- a/src/renderer/modules/components/ColorPicker.ts +++ b/src/renderer/modules/components/ColorPicker.ts @@ -12,16 +12,16 @@ const Positions = { } as const; interface ColorPickerProps { - className?: string, - defaultColor?: number, - customColor?: number, - colors: number[], - value?: number, - disabled?: boolean, + className?: string; + defaultColor?: number; + customColor?: number; + colors: number[]; + value?: number; + disabled?: boolean; onChange?: (value: number, name: string) => void; - renderDefaultButton: (props: object) => React.ReactElement, - renderCustomButton: (props: object) => React.ReactElement, - colorContainerClassName?: string + renderDefaultButton: (props: object) => React.ReactElement; + renderCustomButton: (props: object) => React.ReactElement; + colorContainerClassName?: string; customPickerPosition?: (typeof Positions)[keyof typeof Positions]; } diff --git a/src/renderer/modules/components/ColorPickerCustomButton.ts b/src/renderer/modules/components/ColorPickerCustomButton.ts index 08feff634..7cfc6694f 100644 --- a/src/renderer/modules/components/ColorPickerCustomButton.ts +++ b/src/renderer/modules/components/ColorPickerCustomButton.ts @@ -2,9 +2,9 @@ import type React from "react"; import components from "../common/components"; interface ColorPickerCustomButtonProps { - color?: number, - value?: number, - disabled?: boolean, + color?: number; + value?: number; + disabled?: boolean; onChange?: (value: number, name: string) => void; } diff --git a/src/renderer/modules/components/ColorPickerDefaultButton.ts b/src/renderer/modules/components/ColorPickerDefaultButton.ts index 5d05807ab..76a58dad7 100644 --- a/src/renderer/modules/components/ColorPickerDefaultButton.ts +++ b/src/renderer/modules/components/ColorPickerDefaultButton.ts @@ -2,9 +2,9 @@ import type React from "react"; import components from "../common/components"; interface ColorPickerDefaultButtonProps { - customColor?: number, - value?: number, - disabled?: boolean, + customColor?: number; + value?: number; + disabled?: boolean; "aria-label"?: string; }