diff options
-rw-r--r-- | .github/workflows/build.yml | 2 | ||||
-rwxr-xr-x | scripts/build/build.mjs | 48 | ||||
-rw-r--r-- | src/Vencord.ts | 12 | ||||
-rw-r--r-- | src/components/VencordSettings/Updater.tsx | 3 | ||||
-rw-r--r-- | src/components/VencordSettings/VencordTab.tsx | 4 | ||||
-rw-r--r-- | src/globals.d.ts | 3 | ||||
-rw-r--r-- | src/main/index.ts | 108 | ||||
-rw-r--r-- | src/main/ipcMain.ts (renamed from src/ipcMain/index.ts) | 10 | ||||
-rw-r--r-- | src/main/patchWin32Updater.ts (renamed from src/patchWin32Updater.ts) | 0 | ||||
-rw-r--r-- | src/main/patcher.ts (renamed from src/patcher.ts) | 92 | ||||
-rw-r--r-- | src/main/updater/common.ts (renamed from src/ipcMain/updater/common.ts) | 0 | ||||
-rw-r--r-- | src/main/updater/git.ts (renamed from src/ipcMain/updater/git.ts) | 0 | ||||
-rw-r--r-- | src/main/updater/http.ts (renamed from src/ipcMain/updater/http.ts) | 24 | ||||
-rw-r--r-- | src/main/updater/index.ts (renamed from src/ipcMain/updater/index.ts) | 0 | ||||
-rw-r--r-- | src/main/utils/constants.ts (renamed from src/ipcMain/constants.ts) | 2 | ||||
-rw-r--r-- | src/main/utils/crxToZip.ts (renamed from src/ipcMain/crxToZip.ts) | 0 | ||||
-rw-r--r-- | src/main/utils/extensions.ts (renamed from src/ipcMain/extensions.ts) | 0 | ||||
-rw-r--r-- | src/main/utils/simpleGet.ts (renamed from src/ipcMain/simpleGet.ts) | 0 | ||||
-rw-r--r-- | src/plugins/consoleShortcuts.ts | 3 | ||||
-rw-r--r-- | src/plugins/settings.tsx | 1 | ||||
-rw-r--r-- | src/preload.ts | 4 | ||||
-rw-r--r-- | src/utils/native.ts | 24 | ||||
-rw-r--r-- | src/utils/settingsSync.ts | 42 | ||||
-rw-r--r-- | src/utils/updater.ts | 7 | ||||
-rw-r--r-- | src/webpack/webpack.ts | 2 |
25 files changed, 264 insertions, 127 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b7a95cf..f278707 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,7 @@ jobs: - name: Clean up obsolete files run: | - rm -rf dist/extension* Vencord.user.css + rm -rf dist/extension* Vencord.user.css vencordDesktopRenderer.css vencordDesktopRenderer.css.map - name: Get some values needed for the release id: release_values diff --git a/scripts/build/build.mjs b/scripts/build/build.mjs index 70a05cf..a4b06f5 100755 --- a/scripts/build/build.mjs +++ b/scripts/build/build.mjs @@ -48,6 +48,7 @@ const sourceMapFooter = s => watch ? "" : `//# sourceMappingURL=vencord://${s}.j const sourcemap = watch ? "inline" : "external"; await Promise.all([ + // common preload esbuild.build({ ...nodeCommonOpts, entryPoints: ["src/preload.ts"], @@ -55,12 +56,19 @@ await Promise.all([ footer: { js: "//# sourceURL=VencordPreload\n" + sourceMapFooter("preload") }, sourcemap, }), + + // Discord Desktop main & renderer esbuild.build({ ...nodeCommonOpts, - entryPoints: ["src/patcher.ts"], + entryPoints: ["src/main/index.ts"], outfile: "dist/patcher.js", footer: { js: "//# sourceURL=VencordPatcher\n" + sourceMapFooter("patcher") }, sourcemap, + define: { + ...defines, + IS_DISCORD_DESKTOP: true, + IS_VENCORD_DESKTOP: false + } }), esbuild.build({ ...commonOpts, @@ -77,7 +85,43 @@ await Promise.all([ ], define: { ...defines, - IS_WEB: false + IS_WEB: false, + IS_DISCORD_DESKTOP: true, + IS_VENCORD_DESKTOP: false + } + }), + + // Vencord Desktop main & renderer + esbuild.build({ + ...nodeCommonOpts, + entryPoints: ["src/main/index.ts"], + outfile: "dist/vencordDesktopMain.js", + footer: { js: "//# sourceURL=VencordDesktopMain\n" + sourceMapFooter("vencordDesktopMain") }, + sourcemap, + define: { + ...defines, + IS_DISCORD_DESKTOP: false, + IS_VENCORD_DESKTOP: true + } + }), + esbuild.build({ + ...commonOpts, + entryPoints: ["src/Vencord.ts"], + outfile: "dist/vencordDesktopRenderer.js", + format: "iife", + target: ["esnext"], + footer: { js: "//# sourceURL=VencordDesktopRenderer\n" + sourceMapFooter("vencordDesktopRenderer") }, + globalName: "Vencord", + sourcemap, + plugins: [ + globPlugins, + ...commonOpts.plugins + ], + define: { + ...defines, + IS_WEB: false, + IS_DISCORD_DESKTOP: false, + IS_VENCORD_DESKTOP: true } }), ]).catch(err => { diff --git a/src/Vencord.ts b/src/Vencord.ts index 00f8a58..73b53e8 100644 --- a/src/Vencord.ts +++ b/src/Vencord.ts @@ -30,7 +30,7 @@ import "./webpack/patchWebpack"; import { showNotification } from "./api/Notifications"; import { PlainSettings, Settings } from "./api/settings"; import { patches, PMLogger, startAllPlugins } from "./plugins"; -import { checkForUpdates, rebuild, update, UpdateLogger } from "./utils/updater"; +import { checkForUpdates, rebuild, update,UpdateLogger } from "./utils/updater"; import { onceReady } from "./webpack"; import { SettingsRouter } from "./webpack/common"; @@ -56,8 +56,12 @@ async function init() { permanent: true, noPersist: true, onClick() { - if (needsFullRestart) - window.DiscordNative.app.relaunch(); + if (needsFullRestart) { + if (IS_DISCORD_DESKTOP) + window.DiscordNative.app.relaunch(); + else + window.VencordDesktop.app.relaunch(); + } else location.reload(); } @@ -96,7 +100,7 @@ async function init() { init(); -if (!IS_WEB && Settings.winNativeTitleBar && navigator.platform.toLowerCase().startsWith("win")) { +if (IS_DISCORD_DESKTOP && Settings.winNativeTitleBar && navigator.platform.toLowerCase().startsWith("win")) { document.addEventListener("DOMContentLoaded", () => { document.head.append(Object.assign(document.createElement("style"), { id: "vencord-native-titlebar-style", diff --git a/src/components/VencordSettings/Updater.tsx b/src/components/VencordSettings/Updater.tsx index 3c3eb91..15a8c87 100644 --- a/src/components/VencordSettings/Updater.tsx +++ b/src/components/VencordSettings/Updater.tsx @@ -24,6 +24,7 @@ import { handleComponentFailed } from "@components/handleComponentFailed"; import { Link } from "@components/Link"; import { Margins } from "@utils/margins"; import { classes, useAwaiter } from "@utils/misc"; +import { relaunch } from "@utils/native"; import { changes, checkForUpdates, getRepo, isNewer, rebuild, update, updateError, UpdateLogger } from "@utils/updater"; import { Alerts, Button, Card, Forms, Parser, React, Switch, Toasts } from "@webpack/common"; @@ -133,7 +134,7 @@ function Updatable(props: CommonProps) { cancelText: "Not now!", onConfirm() { if (needFullRestart) - window.DiscordNative.app.relaunch(); + relaunch(); else location.reload(); r(); diff --git a/src/components/VencordSettings/VencordTab.tsx b/src/components/VencordSettings/VencordTab.tsx index 7113421..8b86968 100644 --- a/src/components/VencordSettings/VencordTab.tsx +++ b/src/components/VencordSettings/VencordTab.tsx @@ -26,6 +26,7 @@ import { ErrorCard } from "@components/ErrorCard"; import IpcEvents from "@utils/IpcEvents"; import { Margins } from "@utils/margins"; import { identity, useAwaiter } from "@utils/misc"; +import { relaunch } from "@utils/native"; import { Button, Card, Forms, React, Select, Slider, Switch } from "@webpack/common"; const cl = classNameFactory("vc-settings-"); @@ -100,7 +101,7 @@ function VencordSettings() { ) : ( <React.Fragment> <Button - onClick={() => window.DiscordNative.app.relaunch()} + onClick={relaunch} size={Button.Sizes.SMALL}> Restart Client </Button> @@ -111,6 +112,7 @@ function VencordSettings() { Open QuickCSS File </Button> <Button + // FIXME: Vencord Desktop support onClick={() => window.DiscordNative.fileManager.showItemInFolder(settingsDir)} size={Button.Sizes.SMALL} disabled={settingsDirPending}> diff --git a/src/globals.d.ts b/src/globals.d.ts index 7c494e2..98eccde 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -35,6 +35,8 @@ declare global { export var IS_WEB: boolean; export var IS_DEV: boolean; export var IS_STANDALONE: boolean; + export var IS_DISCORD_DESKTOP: boolean; + export var IS_VENCORD_DESKTOP: boolean; export var VencordNative: typeof import("./VencordNative").default; export var Vencord: typeof import("./Vencord"); @@ -54,6 +56,7 @@ declare global { * If you really must use it, mark your plugin as Desktop App only by naming it Foo.desktop.ts(x) */ export var DiscordNative: any; + export var VencordDesktop: any; interface Window { webpackChunkdiscord_app: { diff --git a/src/main/index.ts b/src/main/index.ts new file mode 100644 index 0000000..c35635e --- /dev/null +++ b/src/main/index.ts @@ -0,0 +1,108 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +import { app, protocol, session } from "electron"; +import { join } from "path"; + +import { getSettings } from "./ipcMain"; +import { IS_VANILLA } from "./utils/constants"; +import { installExt } from "./utils/extensions"; + +if (IS_VENCORD_DESKTOP || !IS_VANILLA) { + app.whenReady().then(() => { + // Source Maps! Maybe there's a better way but since the renderer is executed + // from a string I don't think any other form of sourcemaps would work + protocol.registerFileProtocol("vencord", ({ url: unsafeUrl }, cb) => { + let url = unsafeUrl.slice("vencord://".length); + if (url.endsWith("/")) url = url.slice(0, -1); + switch (url) { + case "renderer.js.map": + case "preload.js.map": + case "patcher.js.map": // doubt + cb(join(__dirname, url)); + break; + default: + cb({ statusCode: 403 }); + } + }); + + try { + if (getSettings().enableReactDevtools) + installExt("fmkadmapgofadopljbjfkapdkoienihi") + .then(() => console.info("[Vencord] Installed React Developer Tools")) + .catch(err => console.error("[Vencord] Failed to install React Developer Tools", err)); + } catch { } + + + // Remove CSP + type PolicyResult = Record<string, string[]>; + + const parsePolicy = (policy: string): PolicyResult => { + const result: PolicyResult = {}; + policy.split(";").forEach(directive => { + const [directiveKey, ...directiveValue] = directive.trim().split(/\s+/g); + if (directiveKey && !Object.prototype.hasOwnProperty.call(result, directiveKey)) { + result[directiveKey] = directiveValue; + } + }); + return result; + }; + const stringifyPolicy = (policy: PolicyResult): string => + Object.entries(policy) + .filter(([, values]) => values?.length) + .map(directive => directive.flat().join(" ")) + .join("; "); + + function patchCsp(headers: Record<string, string[]>, header: string) { + if (header in headers) { + const csp = parsePolicy(headers[header][0]); + + for (const directive of ["style-src", "connect-src", "img-src", "font-src", "media-src", "worker-src"]) { + csp[directive] = ["*", "blob:", "data:", "'unsafe-inline'"]; + } + // TODO: Restrict this to only imported packages with fixed version. + // Perhaps auto generate with esbuild + csp["script-src"] ??= []; + csp["script-src"].push("'unsafe-eval'", "https://unpkg.com", "https://cdnjs.cloudflare.com"); + headers[header] = [stringifyPolicy(csp)]; + } + } + + session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, resourceType }, cb) => { + if (responseHeaders) { + if (resourceType === "mainFrame") + patchCsp(responseHeaders, "content-security-policy"); + + // Fix hosts that don't properly set the css content type, such as + // raw.githubusercontent.com + if (resourceType === "stylesheet") + responseHeaders["content-type"] = ["text/css"]; + } + cb({ cancel: false, responseHeaders }); + }); + + // assign a noop to onHeadersReceived to prevent other mods from adding their own incompatible ones. + // For instance, OpenAsar adds their own that doesn't fix content-type for stylesheets which makes it + // impossible to load css from github raw despite our fix above + session.defaultSession.webRequest.onHeadersReceived = () => { }; + }); +} + +if (IS_DISCORD_DESKTOP) { + require("./patcher"); +} diff --git a/src/ipcMain/index.ts b/src/main/ipcMain.ts index 6fb31d1..b0f8fc3 100644 --- a/src/ipcMain/index.ts +++ b/src/main/ipcMain.ts @@ -28,7 +28,7 @@ import { join } from "path"; import monacoHtml from "~fileContent/../components/monacoWin.html;base64"; -import { ALLOWED_PROTOCOLS, QUICKCSS_PATH, SETTINGS_DIR, SETTINGS_FILE } from "./constants"; +import { ALLOWED_PROTOCOLS, QUICKCSS_PATH, SETTINGS_DIR, SETTINGS_FILE } from "./utils/constants"; mkdirSync(SETTINGS_DIR, { recursive: true }); @@ -44,6 +44,14 @@ export function readSettings() { } } +export function getSettings(): typeof import("@api/settings").Settings { + try { + return JSON.parse(readSettings()); + } catch { + return {} as any; + } +} + ipcMain.handle(IpcEvents.OPEN_QUICKCSS, () => shell.openPath(QUICKCSS_PATH)); ipcMain.handle(IpcEvents.OPEN_EXTERNAL, (_, url) => { diff --git a/src/patchWin32Updater.ts b/src/main/patchWin32Updater.ts index e08e37d..e08e37d 100644 --- a/src/patchWin32Updater.ts +++ b/src/main/patchWin32Updater.ts diff --git a/src/patcher.ts b/src/main/patcher.ts index b1f47b0..c45a299 100644 --- a/src/patcher.ts +++ b/src/main/patcher.ts @@ -17,12 +17,11 @@ */ import { onceDefined } from "@utils/onceDefined"; -import electron, { app, BrowserWindowConstructorOptions, Menu, protocol, session } from "electron"; +import electron, { app, BrowserWindowConstructorOptions, Menu } from "electron"; import { dirname, join } from "path"; -import { initIpc } from "./ipcMain"; -import { installExt } from "./ipcMain/extensions"; -import { readSettings } from "./ipcMain/index"; +import { getSettings, initIpc } from "./ipcMain"; +import { IS_VANILLA } from "./utils/constants"; console.log("[Vencord] Starting up..."); @@ -41,11 +40,8 @@ require.main!.filename = join(asarPath, discordPkg.main); // @ts-ignore Untyped method? Dies from cringe app.setAppPath(asarPath); -if (!process.argv.includes("--vanilla")) { - let settings: typeof import("@api/settings").Settings = {} as any; - try { - settings = JSON.parse(readSettings()); - } catch { } +if (!IS_VANILLA) { + const settings = getSettings(); // Repatch after host updates on Windows if (process.platform === "win32") { @@ -116,84 +112,6 @@ if (!process.argv.includes("--vanilla")) { ); process.env.DATA_DIR = join(app.getPath("userData"), "..", "Vencord"); - - app.whenReady().then(() => { - // Source Maps! Maybe there's a better way but since the renderer is executed - // from a string I don't think any other form of sourcemaps would work - protocol.registerFileProtocol("vencord", ({ url: unsafeUrl }, cb) => { - let url = unsafeUrl.slice("vencord://".length); - if (url.endsWith("/")) url = url.slice(0, -1); - switch (url) { - case "renderer.js.map": - case "preload.js.map": - case "patcher.js.map": // doubt - cb(join(__dirname, url)); - break; - default: - cb({ statusCode: 403 }); - } - }); - - try { - if (settings?.enableReactDevtools) - installExt("fmkadmapgofadopljbjfkapdkoienihi") - .then(() => console.info("[Vencord] Installed React Developer Tools")) - .catch(err => console.error("[Vencord] Failed to install React Developer Tools", err)); - } catch { } - - - // Remove CSP - type PolicyResult = Record<string, string[]>; - - const parsePolicy = (policy: string): PolicyResult => { - const result: PolicyResult = {}; - policy.split(";").forEach(directive => { - const [directiveKey, ...directiveValue] = directive.trim().split(/\s+/g); - if (directiveKey && !Object.prototype.hasOwnProperty.call(result, directiveKey)) { - result[directiveKey] = directiveValue; - } - }); - return result; - }; - const stringifyPolicy = (policy: PolicyResult): string => - Object.entries(policy) - .filter(([, values]) => values?.length) - .map(directive => directive.flat().join(" ")) - .join("; "); - - function patchCsp(headers: Record<string, string[]>, header: string) { - if (header in headers) { - const csp = parsePolicy(headers[header][0]); - - for (const directive of ["style-src", "connect-src", "img-src", "font-src", "media-src", "worker-src"]) { - csp[directive] = ["*", "blob:", "data:", "'unsafe-inline'"]; - } - // TODO: Restrict this to only imported packages with fixed version. - // Perhaps auto generate with esbuild - csp["script-src"] ??= []; - csp["script-src"].push("'unsafe-eval'", "https://unpkg.com", "https://cdnjs.cloudflare.com"); - headers[header] = [stringifyPolicy(csp)]; - } - } - - session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, resourceType }, cb) => { - if (responseHeaders) { - if (resourceType === "mainFrame") - patchCsp(responseHeaders, "content-security-policy"); - - // Fix hosts that don't properly set the css content type, such as - // raw.githubusercontent.com - if (resourceType === "stylesheet") - responseHeaders["content-type"] = ["text/css"]; - } - cb({ cancel: false, responseHeaders }); - }); - - // assign a noop to onHeadersReceived to prevent other mods from adding their own incompatible ones. - // For instance, OpenAsar adds their own that doesn't fix content-type for stylesheets which makes it - // impossible to load css from github raw despite our fix above - session.defaultSession.webRequest.onHeadersReceived = () => { }; - }); } else { console.log("[Vencord] Running in vanilla mode. Not loading Vencord"); } diff --git a/src/ipcMain/updater/common.ts b/src/main/updater/common.ts index 3729c6d..3729c6d 100644 --- a/src/ipcMain/updater/common.ts +++ b/src/main/updater/common.ts diff --git a/src/ipcMain/updater/git.ts b/src/main/updater/git.ts index 89c2d3c..89c2d3c 100644 --- a/src/ipcMain/updater/git.ts +++ b/src/main/updater/git.ts diff --git a/src/ipcMain/updater/http.ts b/src/main/updater/http.ts index cc10631..a2e2aad 100644 --- a/src/ipcMain/updater/http.ts +++ b/src/main/updater/http.ts @@ -25,7 +25,7 @@ import { join } from "path"; import gitHash from "~git-hash"; import gitRemote from "~git-remote"; -import { get } from "../simpleGet"; +import { get } from "../utils/simpleGet"; import { calculateHashes, serializeErrors } from "./common"; const API_BASE = `https://api.github.com/repos/${gitRemote}`; @@ -57,6 +57,13 @@ async function calculateGitChanges() { })); } +const FILES_TO_DOWNLOAD = [ + IS_DISCORD_DESKTOP ? "patcher.js" : "vencordDesktopMain.js", + "preload.js", + IS_DISCORD_DESKTOP ? "renderer.js" : "vencordDesktopRenderer.js", + "renderer.css" +]; + async function fetchUpdates() { const release = await githubGet("/releases/latest"); @@ -66,7 +73,7 @@ async function fetchUpdates() { return false; data.assets.forEach(({ name, browser_download_url }) => { - if (["patcher.js", "preload.js", "renderer.js", "renderer.css"].some(s => name.startsWith(s))) { + if (FILES_TO_DOWNLOAD.some(s => name.startsWith(s))) { PendingUpdates.push([name, browser_download_url]); } }); @@ -75,8 +82,17 @@ async function fetchUpdates() { async function applyUpdates() { await Promise.all(PendingUpdates.map( - async ([name, data]) => writeFile(join(__dirname, name), await get(data))) - ); + async ([name, data]) => writeFile( + join( + __dirname, + IS_VENCORD_DESKTOP + // vencordDesktopRenderer.js -> renderer.js + ? name.replace(/vencordDesktop(\w)/, (_, c) => c.toLowerCase()) + : name + ), + await get(data) + ) + )); PendingUpdates = []; return true; } diff --git a/src/ipcMain/updater/index.ts b/src/main/updater/index.ts index 7036112..7036112 100644 --- a/src/ipcMain/updater/index.ts +++ b/src/main/updater/index.ts diff --git a/src/ipcMain/constants.ts b/src/main/utils/constants.ts index 7133757..cc9f459 100644 --- a/src/ipcMain/constants.ts +++ b/src/main/utils/constants.ts @@ -33,3 +33,5 @@ export const ALLOWED_PROTOCOLS = [ "steam:", "spotify:" ]; + +export const IS_VANILLA = /* @__PURE__ */ process.argv.includes("--vanilla"); diff --git a/src/ipcMain/crxToZip.ts b/src/main/utils/crxToZip.ts index ca43890..ca43890 100644 --- a/src/ipcMain/crxToZip.ts +++ b/src/main/utils/crxToZip.ts diff --git a/src/ipcMain/extensions.ts b/src/main/utils/extensions.ts index d8f8437..d8f8437 100644 --- a/src/ipcMain/extensions.ts +++ b/src/main/utils/extensions.ts diff --git a/src/ipcMain/simpleGet.ts b/src/main/utils/simpleGet.ts index 1a8302c..1a8302c 100644 --- a/src/ipcMain/simpleGet.ts +++ b/src/main/utils/simpleGet.ts diff --git a/src/plugins/consoleShortcuts.ts b/src/plugins/consoleShortcuts.ts index 70a9875..056d246 100644 --- a/src/plugins/consoleShortcuts.ts +++ b/src/plugins/consoleShortcuts.ts @@ -17,6 +17,7 @@ */ import { Devs } from "@utils/constants"; +import { relaunch } from "@utils/native"; import definePlugin from "@utils/types"; import * as Webpack from "@webpack"; import { extract, filters, findAll, search } from "@webpack"; @@ -77,7 +78,7 @@ export default definePlugin({ Settings: Vencord.Settings, Api: Vencord.Api, reload: () => location.reload(), - restart: IS_WEB ? WEB_ONLY("restart") : window.DiscordNative.app.relaunch + restart: IS_WEB ? WEB_ONLY("restart") : relaunch }; }, diff --git a/src/plugins/settings.tsx b/src/plugins/settings.tsx index 67d1f8d..8db0a4e 100644 --- a/src/plugins/settings.tsx +++ b/src/plugins/settings.tsx @@ -168,6 +168,7 @@ export default definePlugin({ get additionalInfo() { if (IS_DEV) return " (Dev)"; if (IS_WEB) return " (Web)"; + if (IS_VENCORD_DESKTOP) return " (Vencord Desktop)"; if (IS_STANDALONE) return " (Standalone)"; return ""; }, diff --git a/src/preload.ts b/src/preload.ts index 820b655..b75574a 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -54,7 +54,9 @@ if (location.protocol !== "data:") { document.getElementById("vencord-css-core")!.textContent = readFileSync(rendererCss, "utf-8"); }); } - require(process.env.DISCORD_PRELOAD!); + + if (process.env.DISCORD_PRELOAD) + require(process.env.DISCORD_PRELOAD); } else { // Monaco Popout contextBridge.exposeInMainWorld("setCss", debounce(s => VencordNative.ipc.invoke(IpcEvents.SET_QUICK_CSS, s))); diff --git a/src/utils/native.ts b/src/utils/native.ts new file mode 100644 index 0000000..70e4c0e --- /dev/null +++ b/src/utils/native.ts @@ -0,0 +1,24 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +export function relaunch() { + if (IS_DISCORD_DESKTOP) + window.DiscordNative.app.relaunch(); + else + window.VencordDesktop.app.relaunch(); +} diff --git a/src/utils/settingsSync.ts b/src/utils/settingsSync.ts index 18e1854..781899f 100644 --- a/src/utils/settingsSync.ts +++ b/src/utils/settingsSync.ts @@ -47,7 +47,9 @@ export async function downloadSettingsBackup() { const backup = await exportSettings(); const data = new TextEncoder().encode(backup); - if (IS_WEB) { + if (IS_DISCORD_DESKTOP) { + DiscordNative.fileManager.saveWithDialog(data, filename); + } else { const file = new File([data], filename, { type: "application/json" }); const a = document.createElement("a"); a.href = URL.createObjectURL(file); @@ -59,8 +61,6 @@ export async function downloadSettingsBackup() { URL.revokeObjectURL(a.href); document.body.removeChild(a); }); - } else { - DiscordNative.fileManager.saveWithDialog(data, filename); } } @@ -77,7 +77,24 @@ const toastFailure = (err: any) => Toasts.show({ }); export async function uploadSettingsBackup(showToast = true): Promise<void> { - if (IS_WEB) { + if (IS_DISCORD_DESKTOP) { + const [file] = await DiscordNative.fileManager.openFiles({ + filters: [ + { name: "Vencord Settings Backup", extensions: ["json"] }, + { name: "all", extensions: ["*"] } + ] + }); + + if (file) { + try { + await importSettings(new TextDecoder().decode(file.data)); + if (showToast) toastSuccess(); + } catch (err) { + new Logger("SettingsSync").error(err); + if (showToast) toastFailure(err); + } + } + } else { const input = document.createElement("input"); input.type = "file"; input.style.display = "none"; @@ -102,22 +119,5 @@ export async function uploadSettingsBackup(showToast = true): Promise<void> { document.body.appendChild(input); input.click(); setImmediate(() => document.body.removeChild(input)); - } else { - const [file] = await DiscordNative.fileManager.openFiles({ - filters: [ - { name: "Vencord Settings Backup", extensions: ["json"] }, - { name: "all", extensions: ["*"] } - ] - }); - - if (file) { - try { - await importSettings(new TextDecoder().decode(file.data)); - if (showToast) toastSuccess(); - } catch (err) { - new Logger("SettingsSync").error(err); - if (showToast) toastFailure(err); - } - } } } diff --git a/src/utils/updater.ts b/src/utils/updater.ts index e13f5cf..d0b1fdc 100644 --- a/src/utils/updater.ts +++ b/src/utils/updater.ts @@ -20,6 +20,7 @@ import gitHash from "~git-hash"; import IpcEvents from "./IpcEvents"; import Logger from "./Logger"; +import { relaunch } from "./native"; import { IpcRes } from "./types"; export const UpdateLogger = /* #__PURE__*/ new Logger("Updater", "white"); @@ -90,8 +91,10 @@ export async function maybePromptToUpdate(confirmMessage: string, checkForDev = if (wantsUpdate) { await update(); const needFullRestart = await rebuild(); - if (needFullRestart) DiscordNative.app.relaunch(); - else location.reload(); + if (needFullRestart) + relaunch(); + else + location.reload(); } } } catch (err) { diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index 0d95587..a37fe6d 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -67,7 +67,7 @@ export function _initWebpack(instance: typeof window.webpackChunkdiscord_app) { instance.pop(); } -if (IS_DEV && !IS_WEB) { +if (IS_DEV && IS_DISCORD_DESKTOP) { var devToolsOpen = false; // At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed setTimeout(() => { |