Improvements for VencordDesktop (#847)

This commit is contained in:
V 2023-04-09 04:04:02 +02:00 committed by GitHub
parent bfa20f2634
commit 08822dd190
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 85 additions and 147 deletions

@ -27,6 +27,8 @@ export { PlainSettings, Settings };
import "./utils/quickCss"; import "./utils/quickCss";
import "./webpack/patchWebpack"; import "./webpack/patchWebpack";
import { relaunch } from "@utils/native";
import { showNotification } from "./api/Notifications"; import { showNotification } from "./api/Notifications";
import { PlainSettings, Settings } from "./api/settings"; import { PlainSettings, Settings } from "./api/settings";
import { patches, PMLogger, startAllPlugins } from "./plugins"; import { patches, PMLogger, startAllPlugins } from "./plugins";
@ -75,23 +77,14 @@ async function init() {
if (Settings.autoUpdate) { if (Settings.autoUpdate) {
await update(); await update();
const needsFullRestart = await rebuild(); await rebuild();
if (Settings.autoUpdateNotification) if (Settings.autoUpdateNotification)
setTimeout(() => showNotification({ setTimeout(() => showNotification({
title: "Vencord has been updated!", title: "Vencord has been updated!",
body: "Click here to restart", body: "Click here to restart",
permanent: true, permanent: true,
noPersist: true, noPersist: true,
onClick() { onClick: relaunch
if (needsFullRestart) {
if (IS_DISCORD_DESKTOP)
window.DiscordNative.app.relaunch();
else
window.VencordDesktop.app.relaunch();
}
else
location.reload();
}
}), 10_000); }), 10_000);
return; return;
} }

@ -125,7 +125,7 @@ function Updatable(props: CommonProps) {
onClick={withDispatcher(setIsUpdating, async () => { onClick={withDispatcher(setIsUpdating, async () => {
if (await update()) { if (await update()) {
setUpdates([]); setUpdates([]);
const needFullRestart = await rebuild(); await rebuild();
await new Promise<void>(r => { await new Promise<void>(r => {
Alerts.show({ Alerts.show({
title: "Update Success!", title: "Update Success!",
@ -133,10 +133,7 @@ function Updatable(props: CommonProps) {
confirmText: "Restart", confirmText: "Restart",
cancelText: "Not now!", cancelText: "Not now!",
onConfirm() { onConfirm() {
if (needFullRestart)
relaunch(); relaunch();
else
location.reload();
r(); r();
}, },
onCancel: r onCancel: r

1
src/globals.d.ts vendored

@ -57,6 +57,7 @@ declare global {
*/ */
export var DiscordNative: any; export var DiscordNative: any;
export var VencordDesktop: any; export var VencordDesktop: any;
export var VencordDesktopNative: any;
interface Window { interface Window {
webpackChunkdiscord_app: { webpackChunkdiscord_app: {

@ -32,9 +32,10 @@ if (IS_VENCORD_DESKTOP || !IS_VANILLA) {
if (url.endsWith("/")) url = url.slice(0, -1); if (url.endsWith("/")) url = url.slice(0, -1);
switch (url) { switch (url) {
case "renderer.js.map": case "renderer.js.map":
case "vencordDesktopRenderer.js.map":
case "preload.js.map": case "preload.js.map":
case "patcher.js.map": // doubt case "patcher.js.map":
case "main.js.map": case "vencordDesktopMain.js.map":
cb(join(__dirname, url)); cb(join(__dirname, url));
break; break;
default: default:

@ -16,28 +16,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { createHash } from "crypto";
import { createReadStream } from "fs";
import { join } from "path";
export async function calculateHashes() { export const VENCORD_FILES = [
const hashes = {} as Record<string, string>; IS_DISCORD_DESKTOP ? "patcher.js" : "vencordDesktopMain.js",
"preload.js",
await Promise.all( IS_DISCORD_DESKTOP ? "renderer.js" : "vencordDesktopRenderer.js",
[IS_DISCORD_DESKTOP ? "patcher.js" : "main.js", "preload.js", "renderer.js", "renderer.css"].map(file => new Promise<void>(r => { "renderer.css"
const fis = createReadStream(join(__dirname, file)); ];
const hash = createHash("sha1", { encoding: "hex" });
fis.once("end", () => {
hash.end();
hashes[file] = hash.read();
r();
});
fis.pipe(hash);
}))
);
return hashes;
}
export function serializeErrors(func: (...args: any[]) => any) { export function serializeErrors(func: (...args: any[]) => any) {
return async function () { return async function () {

@ -22,7 +22,7 @@ import { ipcMain } from "electron";
import { join } from "path"; import { join } from "path";
import { promisify } from "util"; import { promisify } from "util";
import { calculateHashes, serializeErrors } from "./common"; import { serializeErrors } from "./common";
const VENCORD_SRC_DIR = join(__dirname, ".."); const VENCORD_SRC_DIR = join(__dirname, "..");
@ -76,7 +76,6 @@ async function build() {
return !res.stderr.includes("Build failed"); return !res.stderr.includes("Build failed");
} }
ipcMain.handle(IpcEvents.GET_HASHES, serializeErrors(calculateHashes));
ipcMain.handle(IpcEvents.GET_REPO, serializeErrors(getRepo)); ipcMain.handle(IpcEvents.GET_REPO, serializeErrors(getRepo));
ipcMain.handle(IpcEvents.GET_UPDATES, serializeErrors(calculateGitChanges)); ipcMain.handle(IpcEvents.GET_UPDATES, serializeErrors(calculateGitChanges));
ipcMain.handle(IpcEvents.UPDATE, serializeErrors(pull)); ipcMain.handle(IpcEvents.UPDATE, serializeErrors(pull));

@ -26,7 +26,7 @@ import gitHash from "~git-hash";
import gitRemote from "~git-remote"; import gitRemote from "~git-remote";
import { get } from "../utils/simpleGet"; import { get } from "../utils/simpleGet";
import { calculateHashes, serializeErrors } from "./common"; import { serializeErrors, VENCORD_FILES } from "./common";
const API_BASE = `https://api.github.com/repos/${gitRemote}`; const API_BASE = `https://api.github.com/repos/${gitRemote}`;
let PendingUpdates = [] as [string, string][]; let PendingUpdates = [] as [string, string][];
@ -57,13 +57,6 @@ 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() { async function fetchUpdates() {
const release = await githubGet("/releases/latest"); const release = await githubGet("/releases/latest");
@ -73,7 +66,7 @@ async function fetchUpdates() {
return false; return false;
data.assets.forEach(({ name, browser_download_url }) => { data.assets.forEach(({ name, browser_download_url }) => {
if (FILES_TO_DOWNLOAD.some(s => name.startsWith(s))) { if (VENCORD_FILES.some(s => name.startsWith(s))) {
PendingUpdates.push([name, browser_download_url]); PendingUpdates.push([name, browser_download_url]);
} }
}); });
@ -83,13 +76,7 @@ async function fetchUpdates() {
async function applyUpdates() { async function applyUpdates() {
await Promise.all(PendingUpdates.map( await Promise.all(PendingUpdates.map(
async ([name, data]) => writeFile( async ([name, data]) => writeFile(
join( join(__dirname, name),
__dirname,
IS_VENCORD_DESKTOP
// vencordDesktopRenderer.js -> renderer.js
? name.replace(/vencordDesktop(\w)/, (_, c) => c.toLowerCase())
: name
),
await get(data) await get(data)
) )
)); ));
@ -97,7 +84,6 @@ async function applyUpdates() {
return true; return true;
} }
ipcMain.handle(IpcEvents.GET_HASHES, serializeErrors(calculateHashes));
ipcMain.handle(IpcEvents.GET_REPO, serializeErrors(() => `https://github.com/${gitRemote}`)); ipcMain.handle(IpcEvents.GET_REPO, serializeErrors(() => `https://github.com/${gitRemote}`));
ipcMain.handle(IpcEvents.GET_UPDATES, serializeErrors(calculateGitChanges)); ipcMain.handle(IpcEvents.GET_UPDATES, serializeErrors(calculateGitChanges));
ipcMain.handle(IpcEvents.UPDATE, serializeErrors(fetchUpdates)); ipcMain.handle(IpcEvents.UPDATE, serializeErrors(fetchUpdates));

@ -71,66 +71,63 @@ export default definePlugin({
makeSettingsCategories({ ID }: { ID: Record<string, unknown>; }) { makeSettingsCategories({ ID }: { ID: Record<string, unknown>; }) {
const makeOnClick = (tab: string) => () => SettingsRouter.open(tab); const makeOnClick = (tab: string) => () => SettingsRouter.open(tab);
const cats = [ return [
{ {
section: ID.HEADER, section: ID.HEADER,
label: "Vencord" label: "Vencord"
}, { },
{
section: "VencordSettings", section: "VencordSettings",
label: "Vencord", label: "Vencord",
element: () => <SettingsComponent tab="VencordSettings" />, element: () => <SettingsComponent tab="VencordSettings" />,
onClick: makeOnClick("VencordSettings") onClick: makeOnClick("VencordSettings")
}, { },
{
section: "VencordPlugins", section: "VencordPlugins",
label: "Plugins", label: "Plugins",
element: () => <SettingsComponent tab="VencordPlugins" />, element: () => <SettingsComponent tab="VencordPlugins" />,
onClick: makeOnClick("VencordPlugins") onClick: makeOnClick("VencordPlugins")
}, { },
{
section: "VencordThemes", section: "VencordThemes",
label: "Themes", label: "Themes",
element: () => <SettingsComponent tab="VencordThemes" />, element: () => <SettingsComponent tab="VencordThemes" />,
onClick: makeOnClick("VencordThemes") onClick: makeOnClick("VencordThemes")
} },
] as Array<{ !IS_WEB && {
section: unknown,
label?: string;
element?: React.ComponentType;
onClick?(): void;
}>;
if (!IS_WEB)
cats.push({
section: "VencordUpdater", section: "VencordUpdater",
label: "Updater", label: "Updater",
element: () => <SettingsComponent tab="VencordUpdater" />, element: () => <SettingsComponent tab="VencordUpdater" />,
onClick: makeOnClick("VencordUpdater") onClick: makeOnClick("VencordUpdater")
}); },
{
cats.push({
section: "VencordCloud", section: "VencordCloud",
label: "Cloud", label: "Cloud",
element: () => <SettingsComponent tab="VencordCloud" />, element: () => <SettingsComponent tab="VencordCloud" />,
onClick: makeOnClick("VencordCloud") onClick: makeOnClick("VencordCloud")
}); },
{
cats.push({
section: "VencordSettingsSync", section: "VencordSettingsSync",
label: "Backup & Restore", label: "Backup & Restore",
element: () => <SettingsComponent tab="VencordSettingsSync" />, element: () => <SettingsComponent tab="VencordSettingsSync" />,
onClick: makeOnClick("VencordSettingsSync") onClick: makeOnClick("VencordSettingsSync")
}); },
IS_DEV && {
if (IS_DEV)
cats.push({
section: "VencordPatchHelper", section: "VencordPatchHelper",
label: "Patch Helper", label: "Patch Helper",
element: PatchHelper!, element: PatchHelper!,
onClick: makeOnClick("VencordPatchHelper") onClick: makeOnClick("VencordPatchHelper")
}); },
IS_VENCORD_DESKTOP && {
cats.push({ section: ID.DIVIDER }); section: "VencordDesktop",
label: "Desktop Settings",
return cats; element: VencordDesktop.Components.Settings,
onClick: makeOnClick("VencordDesktop")
},
{
section: ID.DIVIDER
}
].filter(Boolean);
}, },
options: { options: {
@ -149,14 +146,6 @@ export default definePlugin({
}, },
}, },
tabs: {
vencord: () => <SettingsComponent tab="VencordSettings" />,
plugins: () => <SettingsComponent tab="VencordPlugins" />,
themes: () => <SettingsComponent tab="VencordThemes" />,
updater: () => <SettingsComponent tab="VencordUpdater" />,
sync: () => <SettingsComponent tab="VencordSettingsSync" />
},
get electronVersion() { get electronVersion() {
return VencordNative.getVersions().electron || window.armcord?.electron || null; return VencordNative.getVersions().electron || window.armcord?.electron || null;
}, },
@ -175,7 +164,7 @@ export default definePlugin({
get additionalInfo() { get additionalInfo() {
if (IS_DEV) return " (Dev)"; if (IS_DEV) return " (Dev)";
if (IS_WEB) return " (Web)"; if (IS_WEB) return " (Web)";
if (IS_VENCORD_DESKTOP) return " (Vencord Desktop)"; if (IS_VENCORD_DESKTOP) return ` (VencordDesktop v${VencordDesktopNative.app.getVersion()})`;
if (IS_STANDALONE) return " (Standalone)"; if (IS_STANDALONE) return " (Standalone)";
return ""; return "";
}, },

@ -44,11 +44,18 @@ export default definePlugin({
execute() { execute() {
const { RELEASE_CHANNEL } = window.GLOBAL_ENV; const { RELEASE_CHANNEL } = window.GLOBAL_ENV;
const client = (() => {
if (IS_DISCORD_DESKTOP) return `Desktop v${DiscordNative.app.getVersion()}`;
if (IS_VENCORD_DESKTOP) return `Vencord Desktop v${VencordDesktopNative.app.getVersion()}`;
if ("armcord" in window) return `ArmCord v${window.armcord.version}`;
return `Web (${navigator.userAgent})`;
})();
const debugInfo = ` const debugInfo = `
**Vencord Debug Info** **Vencord Debug Info**
> Discord Branch: ${RELEASE_CHANNEL} > Discord Branch: ${RELEASE_CHANNEL}
> Client: ${typeof DiscordNative === "undefined" ? window.armcord ? "Armcord" : `Web (${navigator.userAgent})` : `Desktop (Electron v${settings.electronVersion})`} > Client: ${client}
> Platform: ${window.navigator.platform} > Platform: ${window.navigator.platform}
> Vencord Version: ${gitHash}${settings.additionalInfo} > Vencord Version: ${gitHash}${settings.additionalInfo}
> Outdated: ${isOutdated} > Outdated: ${isOutdated}

@ -26,15 +26,14 @@ import VencordNative from "./VencordNative";
contextBridge.exposeInMainWorld("VencordNative", VencordNative); contextBridge.exposeInMainWorld("VencordNative", VencordNative);
if (location.protocol !== "data:") {
// Discord // Discord
webFrame.executeJavaScript(readFileSync(join(__dirname, "renderer.js"), "utf-8")); if (location.protocol !== "data:") {
// #region cssInsert
const rendererCss = join(__dirname, "renderer.css"); const rendererCss = join(__dirname, "renderer.css");
function insertCss(css: string) {
const style = document.createElement("style"); const style = document.createElement("style");
style.id = "vencord-css-core"; style.id = "vencord-css-core";
style.textContent = css; style.textContent = readFileSync(rendererCss, "utf-8");
if (document.readyState === "complete") { if (document.readyState === "complete") {
document.documentElement.appendChild(style); document.documentElement.appendChild(style);
@ -43,10 +42,7 @@ if (location.protocol !== "data:") {
once: true once: true
}); });
} }
}
const css = readFileSync(rendererCss, "utf-8");
insertCss(css);
if (IS_DEV) { if (IS_DEV) {
// persistent means keep process running if watcher is the only thing still running // persistent means keep process running if watcher is the only thing still running
// which we obviously don't want // which we obviously don't want
@ -54,11 +50,14 @@ if (location.protocol !== "data:") {
document.getElementById("vencord-css-core")!.textContent = readFileSync(rendererCss, "utf-8"); document.getElementById("vencord-css-core")!.textContent = readFileSync(rendererCss, "utf-8");
}); });
} }
// #endregion
if (process.env.DISCORD_PRELOAD) if (process.env.DISCORD_PRELOAD) {
webFrame.executeJavaScript(readFileSync(join(__dirname, "renderer.js"), "utf-8"));
require(process.env.DISCORD_PRELOAD); require(process.env.DISCORD_PRELOAD);
} else { }
// Monaco Popout } // Monaco popout
else {
contextBridge.exposeInMainWorld("setCss", debounce(s => VencordNative.ipc.invoke(IpcEvents.SET_QUICK_CSS, s))); contextBridge.exposeInMainWorld("setCss", debounce(s => VencordNative.ipc.invoke(IpcEvents.SET_QUICK_CSS, s)));
contextBridge.exposeInMainWorld("getCurrentCss", () => VencordNative.ipc.invoke(IpcEvents.GET_QUICK_CSS)); contextBridge.exposeInMainWorld("getCurrentCss", () => VencordNative.ipc.invoke(IpcEvents.GET_QUICK_CSS));
// shrug // shrug

@ -40,7 +40,6 @@ export default strEnum({
OPEN_QUICKCSS: "VencordOpenQuickCss", OPEN_QUICKCSS: "VencordOpenQuickCss",
GET_UPDATES: "VencordGetUpdates", GET_UPDATES: "VencordGetUpdates",
GET_REPO: "VencordGetRepo", GET_REPO: "VencordGetRepo",
GET_HASHES: "VencordGetHashes",
UPDATE: "VencordUpdate", UPDATE: "VencordUpdate",
BUILD: "VencordBuild", BUILD: "VencordBuild",
OPEN_MONACO_EDITOR: "VencordOpenMonacoEditor", OPEN_MONACO_EDITOR: "VencordOpenMonacoEditor",

@ -20,12 +20,12 @@ export function relaunch() {
if (IS_DISCORD_DESKTOP) if (IS_DISCORD_DESKTOP)
window.DiscordNative.app.relaunch(); window.DiscordNative.app.relaunch();
else else
window.VencordDesktop.app.relaunch(); window.VencordDesktopNative.app.relaunch();
} }
export function showItemInFolder(path: string) { export function showItemInFolder(path: string) {
if (IS_DISCORD_DESKTOP) if (IS_DISCORD_DESKTOP)
window.DiscordNative.fileManager.showItemInFolder(path); window.DiscordNative.fileManager.showItemInFolder(path);
else else
window.VencordDesktop.fileManager.showItemInFolder(path); window.VencordDesktopNative.fileManager.showItemInFolder(path);
} }

@ -62,24 +62,9 @@ export function getRepo() {
return Unwrap(VencordNative.ipc.invoke<IpcRes<string>>(IpcEvents.GET_REPO)); return Unwrap(VencordNative.ipc.invoke<IpcRes<string>>(IpcEvents.GET_REPO));
} }
type Hashes = Record<"patcher.js" | "main.js" | "preload.js" | "renderer.js" | "renderer.css", string>;
/**
* @returns true if hard restart is required
*/
export async function rebuild() { export async function rebuild() {
const oldHashes = await Unwrap(VencordNative.ipc.invoke<IpcRes<Hashes>>(IpcEvents.GET_HASHES));
if (!await Unwrap(VencordNative.ipc.invoke<IpcRes<boolean>>(IpcEvents.BUILD))) if (!await Unwrap(VencordNative.ipc.invoke<IpcRes<boolean>>(IpcEvents.BUILD)))
throw new Error("The Build failed. Please try manually building the new update"); throw new Error("The Build failed. Please try manually building the new update");
const newHashes = await Unwrap(VencordNative.ipc.invoke<IpcRes<Hashes>>(IpcEvents.GET_HASHES));
if (oldHashes["preload.js"] !== newHashes["preload.js"]) return true;
if (IS_DISCORD_DESKTOP && oldHashes["patcher.js"] !== newHashes["patcher.js"]) return true;
if (IS_VENCORD_DESKTOP && oldHashes["main.js"] !== newHashes["main.js"]) return true;
return false;
} }
export async function maybePromptToUpdate(confirmMessage: string, checkForDev = false) { export async function maybePromptToUpdate(confirmMessage: string, checkForDev = false) {
@ -93,11 +78,8 @@ export async function maybePromptToUpdate(confirmMessage: string, checkForDev =
if (wantsUpdate && isNewer) return alert("Your local copy has more recent commits. Please stash or reset them."); if (wantsUpdate && isNewer) return alert("Your local copy has more recent commits. Please stash or reset them.");
if (wantsUpdate) { if (wantsUpdate) {
await update(); await update();
const needFullRestart = await rebuild(); await rebuild();
if (needFullRestart)
relaunch(); relaunch();
else
location.reload();
} }
} }
} catch (err) { } catch (err) {