Compare commits
29 commits
main
...
asar-bundl
Author | SHA1 | Date | |
---|---|---|---|
7781dface9 | |||
f9fb3bbba7 | |||
8c5217f9f2 | |||
5fab0207fa | |||
0cf6542f3c | |||
f4c19705d7 | |||
9f5dee00d4 | |||
63b359d970 | |||
090a9f5caf | |||
d48f52e8c3 | |||
7aeb884390 | |||
44cd30b23a | |||
22fdde6e39 | |||
8fa7d006a4 | |||
d84943a6d7 | |||
839b62c2d9 | |||
445dfce4a8 | |||
65e91cf22e | |||
b91cb742b1 | |||
611b94b6c7 | |||
ffb73107e6 | |||
d9c469755b | |||
fbfbe33c0a | |||
2ace675c00 | |||
7148c29ed1 | |||
5797506569 | |||
e119f092bf | |||
e8910615a7 | |||
6cf2e0c2a5 |
29
.github/workflows/build.yml
vendored
29
.github/workflows/build.yml
vendored
|
@ -40,9 +40,28 @@ jobs:
|
||||||
- name: Generate plugin list
|
- name: Generate plugin list
|
||||||
run: pnpm generatePluginJson dist/plugins.json dist/plugin-readmes.json
|
run: pnpm generatePluginJson dist/plugins.json dist/plugin-readmes.json
|
||||||
|
|
||||||
- name: Clean up obsolete files
|
- name: Collect files to be released
|
||||||
run: |
|
run: |
|
||||||
rm -rf dist/*-unpacked dist/monaco Vencord.user.css vencordDesktopRenderer.css vencordDesktopRenderer.css.map
|
cd dist
|
||||||
|
mkdir release
|
||||||
|
|
||||||
|
cp browser/browser.* release
|
||||||
|
cp Vencord.user.{js,js.LEGAL.txt} release
|
||||||
|
|
||||||
|
# copy the plugin data jsons, the extension zips and the desktop/vesktop asars
|
||||||
|
cp *.{json,zip,asar} release
|
||||||
|
|
||||||
|
# legacy un-asared files
|
||||||
|
# FIXME: remove at some point
|
||||||
|
cp desktop/* release
|
||||||
|
for file in vesktop/*; do
|
||||||
|
filename=$(basename "$file")
|
||||||
|
cp "$file" "release/vencordDesktop${filename^}"
|
||||||
|
done
|
||||||
|
|
||||||
|
find release -size 0 -delete
|
||||||
|
rm release/package.json
|
||||||
|
rm release/*.map
|
||||||
|
|
||||||
- name: Get some values needed for the release
|
- name: Get some values needed for the release
|
||||||
id: release_values
|
id: release_values
|
||||||
|
@ -50,16 +69,14 @@ jobs:
|
||||||
echo "release_tag=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
echo "release_tag=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Upload DevBuild as release
|
- name: Upload DevBuild as release
|
||||||
if: github.repository == 'Vendicated/Vencord'
|
|
||||||
run: |
|
run: |
|
||||||
gh release upload devbuild --clobber dist/*
|
gh release upload devbuild --clobber dist/release/*
|
||||||
gh release edit devbuild --title "DevBuild $RELEASE_TAG"
|
gh release edit devbuild --title "DevBuild $RELEASE_TAG"
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
RELEASE_TAG: ${{ env.release_tag }}
|
RELEASE_TAG: ${{ env.release_tag }}
|
||||||
|
|
||||||
- name: Upload DevBuild to builds repo
|
- name: Upload DevBuild to builds repo
|
||||||
if: github.repository == 'Vendicated/Vencord'
|
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "$USERNAME"
|
git config --global user.name "$USERNAME"
|
||||||
git config --global user.email actions@github.com
|
git config --global user.email actions@github.com
|
||||||
|
@ -69,7 +86,7 @@ jobs:
|
||||||
|
|
||||||
GLOBIGNORE=.git:.gitignore:README.md:LICENSE
|
GLOBIGNORE=.git:.gitignore:README.md:LICENSE
|
||||||
rm -rf *
|
rm -rf *
|
||||||
cp -r ../dist/* .
|
cp -r ../dist/release/* .
|
||||||
|
|
||||||
git add -A
|
git add -A
|
||||||
git commit -m "Builds for https://github.com/$GITHUB_REPOSITORY/commit/$GITHUB_SHA"
|
git commit -m "Builds for https://github.com/$GITHUB_REPOSITORY/commit/$GITHUB_SHA"
|
||||||
|
|
4
.github/workflows/publish.yml
vendored
4
.github/workflows/publish.yml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
|
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
|
||||||
|
|
||||||
- name: Use Node.js 19
|
- name: Use Node.js 20
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
|
@ -36,7 +36,7 @@ jobs:
|
||||||
|
|
||||||
- name: Publish extension
|
- name: Publish extension
|
||||||
run: |
|
run: |
|
||||||
cd dist/chromium-unpacked
|
cd dist/browser/chromium-unpacked
|
||||||
pnpx chrome-webstore-upload-cli@2.1.0 upload --auto-publish
|
pnpx chrome-webstore-upload-cli@2.1.0 upload --auto-publish
|
||||||
env:
|
env:
|
||||||
EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
|
EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
|
||||||
|
|
11
package.json
11
package.json
|
@ -14,9 +14,9 @@
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"author": "Vendicated",
|
"author": "Vendicated",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node --require=./scripts/suppressExperimentalWarnings.js scripts/build/build.mjs",
|
"build": "tsx scripts/build/build.mts",
|
||||||
"buildStandalone": "pnpm build --standalone",
|
"buildStandalone": "pnpm build --standalone",
|
||||||
"buildWeb": "node --require=./scripts/suppressExperimentalWarnings.js scripts/build/buildWeb.mjs",
|
"buildWeb": "tsx scripts/build/buildWeb.mts",
|
||||||
"buildWebStandalone": "pnpm buildWeb --standalone",
|
"buildWebStandalone": "pnpm buildWeb --standalone",
|
||||||
"buildReporter": "pnpm buildWebStandalone --reporter --skip-extension",
|
"buildReporter": "pnpm buildWebStandalone --reporter --skip-extension",
|
||||||
"buildReporterDesktop": "pnpm build --reporter",
|
"buildReporterDesktop": "pnpm build --reporter",
|
||||||
|
@ -46,6 +46,7 @@
|
||||||
"virtual-merge": "^1.0.1"
|
"virtual-merge": "^1.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@electron/asar": "^3.2.10",
|
||||||
"@types/chrome": "^0.0.246",
|
"@types/chrome": "^0.0.246",
|
||||||
"@types/diff": "^5.0.3",
|
"@types/diff": "^5.0.3",
|
||||||
"@types/lodash": "^4.14.194",
|
"@types/lodash": "^4.14.194",
|
||||||
|
@ -57,7 +58,7 @@
|
||||||
"@typescript-eslint/parser": "^5.59.1",
|
"@typescript-eslint/parser": "^5.59.1",
|
||||||
"diff": "^5.1.0",
|
"diff": "^5.1.0",
|
||||||
"discord-types": "^1.3.26",
|
"discord-types": "^1.3.26",
|
||||||
"esbuild": "^0.15.18",
|
"esbuild": "^0.23.0",
|
||||||
"eslint": "^8.46.0",
|
"eslint": "^8.46.0",
|
||||||
"eslint-import-resolver-alias": "^1.1.2",
|
"eslint-import-resolver-alias": "^1.1.2",
|
||||||
"eslint-plugin-path-alias": "^1.0.0",
|
"eslint-plugin-path-alias": "^1.0.0",
|
||||||
|
@ -71,7 +72,7 @@
|
||||||
"stylelint": "^15.6.0",
|
"stylelint": "^15.6.0",
|
||||||
"stylelint-config-standard": "^33.0.0",
|
"stylelint-config-standard": "^33.0.0",
|
||||||
"ts-patch": "^3.1.2",
|
"ts-patch": "^3.1.2",
|
||||||
"tsx": "^3.12.7",
|
"tsx": "^4.16.2",
|
||||||
"type-fest": "^3.9.0",
|
"type-fest": "^3.9.0",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"typescript-transform-paths": "^3.4.7",
|
"typescript-transform-paths": "^3.4.7",
|
||||||
|
@ -104,7 +105,7 @@
|
||||||
"sourceDir": "./dist/firefox-unpacked"
|
"sourceDir": "./dist/firefox-unpacked"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18",
|
"node": ">=20",
|
||||||
"pnpm": ">=9"
|
"pnpm": ">=9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
754
pnpm-lock.yaml
754
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
@ -17,31 +17,30 @@
|
||||||
* 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 esbuild from "esbuild";
|
import { createPackage } from "@electron/asar";
|
||||||
import { readdir } from "fs/promises";
|
import { BuildOptions, Plugin } from "esbuild";
|
||||||
|
import { existsSync, readdirSync } from "fs";
|
||||||
|
import { readdir, rm, writeFile } from "fs/promises";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
|
|
||||||
import { BUILD_TIMESTAMP, commonOpts, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, resolvePluginName, VERSION, watch } from "./common.mjs";
|
import { addBuild, BUILD_TIMESTAMP, buildOrWatchAll, commonOpts, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, resolvePluginName, VERSION, watch } from "./common.mjs";
|
||||||
|
|
||||||
const defines = {
|
const defines = {
|
||||||
IS_STANDALONE,
|
IS_STANDALONE: String(IS_STANDALONE),
|
||||||
IS_DEV,
|
IS_DEV: String(IS_DEV),
|
||||||
IS_REPORTER,
|
IS_REPORTER: String(IS_REPORTER),
|
||||||
IS_UPDATER_DISABLED,
|
IS_UPDATER_DISABLED: String(IS_UPDATER_DISABLED),
|
||||||
IS_WEB: false,
|
IS_WEB: "false",
|
||||||
IS_EXTENSION: false,
|
IS_EXTENSION: "false",
|
||||||
VERSION: JSON.stringify(VERSION),
|
VERSION: JSON.stringify(VERSION),
|
||||||
BUILD_TIMESTAMP
|
BUILD_TIMESTAMP: String(BUILD_TIMESTAMP)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (defines.IS_STANDALONE === false)
|
if (defines.IS_STANDALONE === "false")
|
||||||
// If this is a local build (not standalone), optimize
|
// If this is a local build (not standalone), optimize
|
||||||
// for the specific platform we're on
|
// for the specific platform we're on
|
||||||
defines["process.platform"] = JSON.stringify(process.platform);
|
defines["process.platform"] = JSON.stringify(process.platform);
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {esbuild.BuildOptions}
|
|
||||||
*/
|
|
||||||
const nodeCommonOpts = {
|
const nodeCommonOpts = {
|
||||||
...commonOpts,
|
...commonOpts,
|
||||||
format: "cjs",
|
format: "cjs",
|
||||||
|
@ -49,15 +48,12 @@ const nodeCommonOpts = {
|
||||||
target: ["esnext"],
|
target: ["esnext"],
|
||||||
external: ["electron", "original-fs", "~pluginNatives", ...commonOpts.external],
|
external: ["electron", "original-fs", "~pluginNatives", ...commonOpts.external],
|
||||||
define: defines
|
define: defines
|
||||||
};
|
} satisfies BuildOptions;
|
||||||
|
|
||||||
const sourceMapFooter = s => watch ? "" : `//# sourceMappingURL=vencord://${s}.js.map`;
|
const sourceMapFooter = (s: string) => watch ? "" : `//# sourceMappingURL=vencord://${s}.js.map`;
|
||||||
const sourcemap = watch ? "inline" : "external";
|
const sourcemap = watch ? "inline" : "external";
|
||||||
|
|
||||||
/**
|
const globNativesPlugin: Plugin = {
|
||||||
* @type {import("esbuild").Plugin}
|
|
||||||
*/
|
|
||||||
const globNativesPlugin = {
|
|
||||||
name: "glob-natives-plugin",
|
name: "glob-natives-plugin",
|
||||||
setup: build => {
|
setup: build => {
|
||||||
const filter = /^~pluginNatives$/;
|
const filter = /^~pluginNatives$/;
|
||||||
|
@ -104,26 +100,26 @@ const globNativesPlugin = {
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
// Discord Desktop main & renderer & preload
|
// Discord Desktop main & renderer & preload
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...nodeCommonOpts,
|
...nodeCommonOpts,
|
||||||
entryPoints: ["src/main/index.ts"],
|
entryPoints: ["src/main/index.ts"],
|
||||||
outfile: "dist/patcher.js",
|
outfile: "dist/desktop/patcher.js",
|
||||||
footer: { js: "//# sourceURL=VencordPatcher\n" + sourceMapFooter("patcher") },
|
footer: { js: "//# sourceURL=VencordPatcher\n" + sourceMapFooter("patcher") },
|
||||||
sourcemap,
|
sourcemap,
|
||||||
define: {
|
define: {
|
||||||
...defines,
|
...defines,
|
||||||
IS_DISCORD_DESKTOP: true,
|
IS_DISCORD_DESKTOP: "true",
|
||||||
IS_VESKTOP: false
|
IS_VESKTOP: "false"
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
...nodeCommonOpts.plugins,
|
...nodeCommonOpts.plugins,
|
||||||
globNativesPlugin
|
globNativesPlugin
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...commonOpts,
|
...commonOpts,
|
||||||
entryPoints: ["src/Vencord.ts"],
|
entryPoints: ["src/Vencord.ts"],
|
||||||
outfile: "dist/renderer.js",
|
outfile: "dist/desktop/renderer.js",
|
||||||
format: "iife",
|
format: "iife",
|
||||||
target: ["esnext"],
|
target: ["esnext"],
|
||||||
footer: { js: "//# sourceURL=VencordRenderer\n" + sourceMapFooter("renderer") },
|
footer: { js: "//# sourceURL=VencordRenderer\n" + sourceMapFooter("renderer") },
|
||||||
|
@ -135,47 +131,47 @@ await Promise.all([
|
||||||
],
|
],
|
||||||
define: {
|
define: {
|
||||||
...defines,
|
...defines,
|
||||||
IS_DISCORD_DESKTOP: true,
|
IS_DISCORD_DESKTOP: "true",
|
||||||
IS_VESKTOP: false
|
IS_VESKTOP: "false"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...nodeCommonOpts,
|
...nodeCommonOpts,
|
||||||
entryPoints: ["src/preload.ts"],
|
entryPoints: ["src/preload.ts"],
|
||||||
outfile: "dist/preload.js",
|
outfile: "dist/desktop/preload.js",
|
||||||
footer: { js: "//# sourceURL=VencordPreload\n" + sourceMapFooter("preload") },
|
footer: { js: "//# sourceURL=VencordPreload\n" + sourceMapFooter("preload") },
|
||||||
sourcemap,
|
sourcemap,
|
||||||
define: {
|
define: {
|
||||||
...defines,
|
...defines,
|
||||||
IS_DISCORD_DESKTOP: true,
|
IS_DISCORD_DESKTOP: "true",
|
||||||
IS_VESKTOP: false
|
IS_VESKTOP: "false"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Vencord Desktop main & renderer & preload
|
// Vencord Desktop main & renderer & preload
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...nodeCommonOpts,
|
...nodeCommonOpts,
|
||||||
entryPoints: ["src/main/index.ts"],
|
entryPoints: ["src/main/index.ts"],
|
||||||
outfile: "dist/vencordDesktopMain.js",
|
outfile: "dist/vesktop/main.js",
|
||||||
footer: { js: "//# sourceURL=VencordDesktopMain\n" + sourceMapFooter("vencordDesktopMain") },
|
footer: { js: "//# sourceURL=VencordMain\n" + sourceMapFooter("main") },
|
||||||
sourcemap,
|
sourcemap,
|
||||||
define: {
|
define: {
|
||||||
...defines,
|
...defines,
|
||||||
IS_DISCORD_DESKTOP: false,
|
IS_DISCORD_DESKTOP: "false",
|
||||||
IS_VESKTOP: true
|
IS_VESKTOP: "true"
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
...nodeCommonOpts.plugins,
|
...nodeCommonOpts.plugins,
|
||||||
globNativesPlugin
|
globNativesPlugin
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...commonOpts,
|
...commonOpts,
|
||||||
entryPoints: ["src/Vencord.ts"],
|
entryPoints: ["src/Vencord.ts"],
|
||||||
outfile: "dist/vencordDesktopRenderer.js",
|
outfile: "dist/vesktop/renderer.js",
|
||||||
format: "iife",
|
format: "iife",
|
||||||
target: ["esnext"],
|
target: ["esnext"],
|
||||||
footer: { js: "//# sourceURL=VencordDesktopRenderer\n" + sourceMapFooter("vencordDesktopRenderer") },
|
footer: { js: "//# sourceURL=VencordRenderer\n" + sourceMapFooter("renderer") },
|
||||||
globalName: "Vencord",
|
globalName: "Vencord",
|
||||||
sourcemap,
|
sourcemap,
|
||||||
plugins: [
|
plugins: [
|
||||||
|
@ -184,26 +180,58 @@ await Promise.all([
|
||||||
],
|
],
|
||||||
define: {
|
define: {
|
||||||
...defines,
|
...defines,
|
||||||
IS_DISCORD_DESKTOP: false,
|
IS_DISCORD_DESKTOP: "false",
|
||||||
IS_VESKTOP: true
|
IS_VESKTOP: "true"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...nodeCommonOpts,
|
...nodeCommonOpts,
|
||||||
entryPoints: ["src/preload.ts"],
|
entryPoints: ["src/preload.ts"],
|
||||||
outfile: "dist/vencordDesktopPreload.js",
|
outfile: "dist/vesktop/preload.js",
|
||||||
footer: { js: "//# sourceURL=VencordPreload\n" + sourceMapFooter("vencordDesktopPreload") },
|
footer: { js: "//# sourceURL=VencordPreload\n" + sourceMapFooter("preload") },
|
||||||
sourcemap,
|
sourcemap,
|
||||||
define: {
|
define: {
|
||||||
...defines,
|
...defines,
|
||||||
IS_DISCORD_DESKTOP: false,
|
IS_DISCORD_DESKTOP: "false",
|
||||||
IS_VESKTOP: true
|
IS_VESKTOP: "true"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
]).catch(err => {
|
]);
|
||||||
console.error("Build failed");
|
|
||||||
console.error(err.message);
|
await buildOrWatchAll();
|
||||||
// make ci fail
|
|
||||||
if (!commonOpts.watch)
|
await Promise.all([
|
||||||
process.exitCode = 1;
|
writeFile("dist/desktop/package.json", JSON.stringify({
|
||||||
});
|
name: "vencord",
|
||||||
|
main: "patcher.js"
|
||||||
|
})),
|
||||||
|
writeFile("dist/vesktop/package.json", JSON.stringify({
|
||||||
|
name: "vencord",
|
||||||
|
main: "main.js"
|
||||||
|
}))
|
||||||
|
]);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
createPackage("dist/desktop", "dist/desktop.asar"),
|
||||||
|
createPackage("dist/vesktop", "dist/vesktop.asar")
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
if (existsSync("dist/renderer.js")) {
|
||||||
|
console.warn("Legacy dist folder. Cleaning up and adding shims.");
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
readdirSync("dist")
|
||||||
|
.filter(f =>
|
||||||
|
f.endsWith(".map") ||
|
||||||
|
f.endsWith(".LEGAL.txt") ||
|
||||||
|
["patcher", "preload", "renderer"].some(name => f.startsWith(name))
|
||||||
|
)
|
||||||
|
.map(file => rm(join("dist", file)))
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
writeFile("dist/patcher.js", 'require("./desktop")'),
|
||||||
|
writeFile("dist/vencordDesktopMain.js", 'require("./vesktop")')
|
||||||
|
]);
|
||||||
|
}
|
|
@ -23,12 +23,12 @@ import { appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import Zip from "zip-local";
|
import Zip from "zip-local";
|
||||||
|
|
||||||
import { BUILD_TIMESTAMP, commonOpts, globPlugins, IS_DEV, IS_REPORTER, VERSION } from "./common.mjs";
|
import { addBuild, BUILD_TIMESTAMP, buildOrWatchAll, commonOpts, globPlugins, IS_DEV, IS_REPORTER, VERSION } from "./common.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {esbuild.BuildOptions}
|
* @type {esbuild.BuildOptions}
|
||||||
*/
|
*/
|
||||||
const commonOptions = {
|
const commonOptions: esbuild.BuildOptions = {
|
||||||
...commonOpts,
|
...commonOpts,
|
||||||
entryPoints: ["browser/Vencord.ts"],
|
entryPoints: ["browser/Vencord.ts"],
|
||||||
globalName: "Vencord",
|
globalName: "Vencord",
|
||||||
|
@ -40,16 +40,16 @@ const commonOptions = {
|
||||||
],
|
],
|
||||||
target: ["esnext"],
|
target: ["esnext"],
|
||||||
define: {
|
define: {
|
||||||
IS_WEB: true,
|
IS_WEB: "true",
|
||||||
IS_EXTENSION: false,
|
IS_EXTENSION: "false",
|
||||||
IS_STANDALONE: true,
|
IS_STANDALONE: "true",
|
||||||
IS_DEV,
|
IS_DEV: String(IS_DEV),
|
||||||
IS_REPORTER,
|
IS_REPORTER: String(IS_REPORTER),
|
||||||
IS_DISCORD_DESKTOP: false,
|
IS_DISCORD_DESKTOP: "false",
|
||||||
IS_VESKTOP: false,
|
IS_VESKTOP: "false",
|
||||||
IS_UPDATER_DISABLED: true,
|
IS_UPDATER_DISABLED: "true",
|
||||||
VERSION: JSON.stringify(VERSION),
|
VERSION: JSON.stringify(VERSION),
|
||||||
BUILD_TIMESTAMP
|
BUILD_TIMESTAMP: String(BUILD_TIMESTAMP)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,39 +67,39 @@ const RnNoiseFiles = [
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
[
|
[
|
||||||
esbuild.build({
|
addBuild({
|
||||||
entryPoints: MonacoWorkerEntryPoints.map(entry => `node_modules/monaco-editor/esm/${entry}`),
|
entryPoints: MonacoWorkerEntryPoints.map(entry => `node_modules/monaco-editor/esm/${entry}`),
|
||||||
bundle: true,
|
bundle: true,
|
||||||
minify: true,
|
minify: true,
|
||||||
format: "iife",
|
format: "iife",
|
||||||
outbase: "node_modules/monaco-editor/esm/",
|
outbase: "node_modules/monaco-editor/esm/",
|
||||||
outdir: "dist/monaco"
|
outdir: "dist/browser/monaco"
|
||||||
}),
|
}),
|
||||||
esbuild.build({
|
addBuild({
|
||||||
entryPoints: ["browser/monaco.ts"],
|
entryPoints: ["browser/monaco.ts"],
|
||||||
bundle: true,
|
bundle: true,
|
||||||
minify: true,
|
minify: true,
|
||||||
format: "iife",
|
format: "iife",
|
||||||
outfile: "dist/monaco/index.js",
|
outfile: "dist/browser/monaco/index.js",
|
||||||
loader: {
|
loader: {
|
||||||
".ttf": "file"
|
".ttf": "file"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
outfile: "dist/browser.js",
|
outfile: "dist/browser/browser.js",
|
||||||
footer: { js: "//# sourceURL=VencordWeb" }
|
footer: { js: "//# sourceURL=VencordWeb" }
|
||||||
}),
|
}),
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
outfile: "dist/extension.js",
|
outfile: "dist/browser/extension.js",
|
||||||
define: {
|
define: {
|
||||||
...commonOptions?.define,
|
...commonOptions?.define,
|
||||||
IS_EXTENSION: true,
|
IS_EXTENSION: "true",
|
||||||
},
|
},
|
||||||
footer: { js: "//# sourceURL=VencordWeb" }
|
footer: { js: "//# sourceURL=VencordWeb" }
|
||||||
}),
|
}),
|
||||||
esbuild.build({
|
addBuild({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])],
|
inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])],
|
||||||
define: {
|
define: {
|
||||||
|
@ -118,11 +118,10 @@ await Promise.all(
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
await buildOrWatchAll();
|
||||||
* @type {(dir: string) => Promise<string[]>}
|
|
||||||
*/
|
async function globDir(dir: string): Promise<string[]> {
|
||||||
async function globDir(dir) {
|
const files = [] as string[];
|
||||||
const files = [];
|
|
||||||
|
|
||||||
for (const child of await readdir(dir, { withFileTypes: true })) {
|
for (const child of await readdir(dir, { withFileTypes: true })) {
|
||||||
const p = join(dir, child.name);
|
const p = join(dir, child.name);
|
||||||
|
@ -135,27 +134,23 @@ async function globDir(dir) {
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async function loadDir(dir: string, basePath = "") {
|
||||||
* @type {(dir: string, basePath?: string) => Promise<Record<string, string>>}
|
|
||||||
*/
|
|
||||||
async function loadDir(dir, basePath = "") {
|
|
||||||
const files = await globDir(dir);
|
const files = await globDir(dir);
|
||||||
return Object.fromEntries(await Promise.all(files.map(async f => [f.slice(basePath.length), await readFile(f)])));
|
return Object.fromEntries(await Promise.all(files.map(async f =>
|
||||||
|
[f.slice(basePath.length), await readFile(f)] as const
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async function buildExtension(target: string, files: string[]): Promise<void> {
|
||||||
* @type {(target: string, files: string[]) => Promise<void>}
|
const entries: Record<string, Buffer> = {
|
||||||
*/
|
"dist/Vencord.js": await readFile("dist/browser/extension.js"),
|
||||||
async function buildExtension(target, files) {
|
"dist/Vencord.css": await readFile("dist/browser/extension.css"),
|
||||||
const entries = {
|
...await loadDir("dist/browser/monaco"),
|
||||||
"dist/Vencord.js": await readFile("dist/extension.js"),
|
|
||||||
"dist/Vencord.css": await readFile("dist/extension.css"),
|
|
||||||
...await loadDir("dist/monaco"),
|
|
||||||
...Object.fromEntries(await Promise.all(RnNoiseFiles.map(async file =>
|
...Object.fromEntries(await Promise.all(RnNoiseFiles.map(async file =>
|
||||||
[`third-party/rnnoise/${file.replace(/^dist\//, "")}`, await readFile(`node_modules/@sapphi-red/web-noise-suppressor/${file}`)]
|
[`third-party/rnnoise/${file.replace(/^dist\//, "")}`, await readFile(`node_modules/@sapphi-red/web-noise-suppressor/${file}`)] as const
|
||||||
))),
|
))),
|
||||||
...Object.fromEntries(await Promise.all(files.map(async f => {
|
...Object.fromEntries(await Promise.all(files.map(async f => {
|
||||||
let content = await readFile(join("browser", f));
|
let content: Uint8Array | Buffer = await readFile(join("browser", f));
|
||||||
if (f.startsWith("manifest")) {
|
if (f.startsWith("manifest")) {
|
||||||
const json = JSON.parse(content.toString("utf-8"));
|
const json = JSON.parse(content.toString("utf-8"));
|
||||||
json.version = VERSION;
|
json.version = VERSION;
|
||||||
|
@ -165,19 +160,19 @@ async function buildExtension(target, files) {
|
||||||
return [
|
return [
|
||||||
f.startsWith("manifest") ? "manifest.json" : f,
|
f.startsWith("manifest") ? "manifest.json" : f,
|
||||||
content
|
content
|
||||||
];
|
] as const;
|
||||||
})))
|
})))
|
||||||
};
|
};
|
||||||
|
|
||||||
await rm(target, { recursive: true, force: true });
|
await rm(target, { recursive: true, force: true });
|
||||||
await Promise.all(Object.entries(entries).map(async ([file, content]) => {
|
await Promise.all(Object.entries(entries).map(async ([file, content]) => {
|
||||||
const dest = join("dist", target, file);
|
const dest = join("dist/browser", target, file);
|
||||||
const parentDirectory = join(dest, "..");
|
const parentDirectory = join(dest, "..");
|
||||||
await mkdir(parentDirectory, { recursive: true });
|
await mkdir(parentDirectory, { recursive: true });
|
||||||
await writeFile(dest, content);
|
await writeFile(dest, content);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
console.info("Unpacked Extension written to dist/" + target);
|
console.info("Unpacked Extension written to dist/browser/" + target);
|
||||||
}
|
}
|
||||||
|
|
||||||
const appendCssRuntime = readFile("dist/Vencord.user.css", "utf-8").then(content => {
|
const appendCssRuntime = readFile("dist/Vencord.user.css", "utf-8").then(content => {
|
||||||
|
@ -200,12 +195,14 @@ if (!process.argv.includes("--skip-extension")) {
|
||||||
buildExtension("firefox-unpacked", ["background.js", "content.js", "manifestv2.json", "icon.png"]),
|
buildExtension("firefox-unpacked", ["background.js", "content.js", "manifestv2.json", "icon.png"]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Zip.sync.zip("dist/chromium-unpacked").compress().save("dist/extension-chrome.zip");
|
Zip.zip("dist/browser/chromium-unpacked", (_err, zip) => {
|
||||||
|
zip.compress().save("dist/extension-chrome.zip");
|
||||||
console.info("Packed Chromium Extension written to dist/extension-chrome.zip");
|
console.info("Packed Chromium Extension written to dist/extension-chrome.zip");
|
||||||
|
});
|
||||||
Zip.sync.zip("dist/firefox-unpacked").compress().save("dist/extension-firefox.zip");
|
Zip.zip("dist/browser/firefox-unpacked", (_err, zip) => {
|
||||||
|
zip.compress().save("dist/extension-firefox.zip");
|
||||||
console.info("Packed Firefox Extension written to dist/extension-firefox.zip");
|
console.info("Packed Firefox Extension written to dist/extension-firefox.zip");
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
await appendCssRuntime;
|
await appendCssRuntime;
|
||||||
}
|
}
|
|
@ -20,7 +20,7 @@ import "../suppressExperimentalWarnings.js";
|
||||||
import "../checkNodeVersion.js";
|
import "../checkNodeVersion.js";
|
||||||
|
|
||||||
import { exec, execSync } from "child_process";
|
import { exec, execSync } from "child_process";
|
||||||
import esbuild from "esbuild";
|
import esbuild, { build, BuildOptions, context, Plugin } from "esbuild";
|
||||||
import { constants as FsConstants, readFileSync } from "fs";
|
import { constants as FsConstants, readFileSync } from "fs";
|
||||||
import { access, readdir, readFile } from "fs/promises";
|
import { access, readdir, readFile } from "fs/promises";
|
||||||
import { minify as minifyHtml } from "html-minifier-terser";
|
import { minify as minifyHtml } from "html-minifier-terser";
|
||||||
|
@ -29,8 +29,7 @@ import { promisify } from "util";
|
||||||
|
|
||||||
import { getPluginTarget } from "../utils.mjs";
|
import { getPluginTarget } from "../utils.mjs";
|
||||||
|
|
||||||
/** @type {import("../../package.json")} */
|
const PackageJSON: typeof import("../../package.json") = JSON.parse(readFileSync("package.json", "utf-8"));
|
||||||
const PackageJSON = JSON.parse(readFileSync("package.json"));
|
|
||||||
|
|
||||||
export const VERSION = PackageJSON.version;
|
export const VERSION = PackageJSON.version;
|
||||||
// https://reproducible-builds.org/docs/source-date-epoch/
|
// https://reproducible-builds.org/docs/source-date-epoch/
|
||||||
|
@ -54,11 +53,8 @@ export const banner = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const PluginDefinitionNameMatcher = /definePlugin\(\{\s*(["'])?name\1:\s*(["'`])(.+?)\2/;
|
const PluginDefinitionNameMatcher = /definePlugin\(\{\s*(["'])?name\1:\s*(["'`])(.+?)\2/;
|
||||||
/**
|
|
||||||
* @param {string} base
|
export async function resolvePluginName(base: string, dirent: import("fs").Dirent) {
|
||||||
* @param {import("fs").Dirent} dirent
|
|
||||||
*/
|
|
||||||
export async function resolvePluginName(base, dirent) {
|
|
||||||
const fullPath = join(base, dirent.name);
|
const fullPath = join(base, dirent.name);
|
||||||
const content = dirent.isFile()
|
const content = dirent.isFile()
|
||||||
? await readFile(fullPath, "utf-8")
|
? await readFile(fullPath, "utf-8")
|
||||||
|
@ -79,28 +75,13 @@ export async function resolvePluginName(base, dirent) {
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function exists(path) {
|
export async function exists(path: string) {
|
||||||
return await access(path, FsConstants.F_OK)
|
return await access(path, FsConstants.F_OK)
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch(() => false);
|
.catch(() => false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/evanw/esbuild/issues/619#issuecomment-751995294
|
export const globPlugins: (kind: "web" | "discordDesktop" | "vencordDesktop") => Plugin = kind => ({
|
||||||
/**
|
|
||||||
* @type {import("esbuild").Plugin}
|
|
||||||
*/
|
|
||||||
export const makeAllPackagesExternalPlugin = {
|
|
||||||
name: "make-all-packages-external",
|
|
||||||
setup(build) {
|
|
||||||
const filter = /^[^./]|^\.[^./]|^\.\.[^/]/; // Must not start with "/" or "./" or "../"
|
|
||||||
build.onResolve({ filter }, args => ({ path: args.path, external: true }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {(kind: "web" | "discordDesktop" | "vencordDesktop") => import("esbuild").Plugin}
|
|
||||||
*/
|
|
||||||
export const globPlugins = kind => ({
|
|
||||||
name: "glob-plugins",
|
name: "glob-plugins",
|
||||||
setup: build => {
|
setup: build => {
|
||||||
const filter = /^~plugins$/;
|
const filter = /^~plugins$/;
|
||||||
|
@ -164,10 +145,7 @@ export const globPlugins = kind => ({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
export const gitHashPlugin: Plugin = {
|
||||||
* @type {import("esbuild").Plugin}
|
|
||||||
*/
|
|
||||||
export const gitHashPlugin = {
|
|
||||||
name: "git-hash-plugin",
|
name: "git-hash-plugin",
|
||||||
setup: build => {
|
setup: build => {
|
||||||
const filter = /^~git-hash$/;
|
const filter = /^~git-hash$/;
|
||||||
|
@ -180,10 +158,7 @@ export const gitHashPlugin = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const gitRemotePlugin: Plugin = {
|
||||||
* @type {import("esbuild").Plugin}
|
|
||||||
*/
|
|
||||||
export const gitRemotePlugin = {
|
|
||||||
name: "git-remote-plugin",
|
name: "git-remote-plugin",
|
||||||
setup: build => {
|
setup: build => {
|
||||||
const filter = /^~git-remote$/;
|
const filter = /^~git-remote$/;
|
||||||
|
@ -205,10 +180,7 @@ export const gitRemotePlugin = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const fileUrlPlugin: Plugin = {
|
||||||
* @type {import("esbuild").Plugin}
|
|
||||||
*/
|
|
||||||
export const fileUrlPlugin = {
|
|
||||||
name: "file-uri-plugin",
|
name: "file-uri-plugin",
|
||||||
setup: build => {
|
setup: build => {
|
||||||
const filter = /^file:\/\/.+$/;
|
const filter = /^file:\/\/.+$/;
|
||||||
|
@ -228,7 +200,7 @@ export const fileUrlPlugin = {
|
||||||
|
|
||||||
const encoding = base64 ? "base64" : "utf-8";
|
const encoding = base64 ? "base64" : "utf-8";
|
||||||
|
|
||||||
let content;
|
let content: string;
|
||||||
if (!minify) {
|
if (!minify) {
|
||||||
content = await readFile(path, encoding);
|
content = await readFile(path, encoding);
|
||||||
if (!noTrim) content = content.trimEnd();
|
if (!noTrim) content = content.trimEnd();
|
||||||
|
@ -268,10 +240,7 @@ export const fileUrlPlugin = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const styleModule = readFileSync("./scripts/build/module/style.js", "utf-8");
|
const styleModule = readFileSync("./scripts/build/module/style.js", "utf-8");
|
||||||
/**
|
export const stylePlugin: Plugin = {
|
||||||
* @type {import("esbuild").Plugin}
|
|
||||||
*/
|
|
||||||
export const stylePlugin = {
|
|
||||||
name: "style-plugin",
|
name: "style-plugin",
|
||||||
setup: ({ onResolve, onLoad }) => {
|
setup: ({ onResolve, onLoad }) => {
|
||||||
onResolve({ filter: /\.css\?managed$/, namespace: "file" }, ({ path, resolveDir }) => ({
|
onResolve({ filter: /\.css\?managed$/, namespace: "file" }, ({ path, resolveDir }) => ({
|
||||||
|
@ -292,22 +261,59 @@ export const stylePlugin = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
let buildsFinished = Promise.resolve();
|
||||||
* @type {import("esbuild").BuildOptions}
|
const buildsFinishedPlugin: Plugin = {
|
||||||
*/
|
name: "builds-finished-plugin",
|
||||||
|
setup({ onEnd }) {
|
||||||
|
if (!watch) return;
|
||||||
|
|
||||||
|
let resolve: () => void;
|
||||||
|
const done = new Promise<void>(r => resolve = r);
|
||||||
|
buildsFinished = buildsFinished.then(() => done);
|
||||||
|
|
||||||
|
onEnd(() => resolve());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const commonOpts = {
|
export const commonOpts = {
|
||||||
logLevel: "info",
|
logLevel: "info",
|
||||||
bundle: true,
|
bundle: true,
|
||||||
watch,
|
|
||||||
minify: !watch,
|
minify: !watch,
|
||||||
sourcemap: watch ? "inline" : "",
|
sourcemap: watch ? "inline" : "external",
|
||||||
legalComments: "linked",
|
legalComments: "linked",
|
||||||
banner,
|
banner,
|
||||||
plugins: [fileUrlPlugin, gitHashPlugin, gitRemotePlugin, stylePlugin],
|
plugins: [fileUrlPlugin, gitHashPlugin, gitRemotePlugin, stylePlugin, buildsFinishedPlugin],
|
||||||
external: ["~plugins", "~git-hash", "~git-remote", "/assets/*"],
|
external: ["~plugins", "~git-hash", "~git-remote", "/assets/*"],
|
||||||
inject: ["./scripts/build/inject/react.mjs"],
|
inject: ["./scripts/build/inject/react.mjs"],
|
||||||
jsxFactory: "VencordCreateElement",
|
jsxFactory: "VencordCreateElement",
|
||||||
jsxFragment: "VencordFragment",
|
jsxFragment: "VencordFragment",
|
||||||
// Work around https://github.com/evanw/esbuild/issues/2460
|
jsx: "transform"
|
||||||
tsconfig: "./scripts/build/tsconfig.esbuild.json"
|
} satisfies BuildOptions;
|
||||||
};
|
|
||||||
|
|
||||||
|
const builds = [] as BuildOptions[];
|
||||||
|
export function addBuild(options: BuildOptions) {
|
||||||
|
builds.push(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function buildOrWatchAll() {
|
||||||
|
if (watch) {
|
||||||
|
const contexts = await Promise.all(builds.map(context));
|
||||||
|
await Promise.all(contexts.map(ctx => ctx.watch()));
|
||||||
|
|
||||||
|
await buildsFinished;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await Promise.all(builds.map(build));
|
||||||
|
} catch (err) {
|
||||||
|
const reason = err instanceof Error
|
||||||
|
? err.message
|
||||||
|
: err;
|
||||||
|
|
||||||
|
console.error("Build failed");
|
||||||
|
console.error(reason);
|
||||||
|
// make ci fail
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
// Work around https://github.com/evanw/esbuild/issues/2460
|
|
||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"jsx": "react"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -124,6 +124,7 @@ try {
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
VENCORD_USER_DATA_DIR: BASE_DIR,
|
VENCORD_USER_DATA_DIR: BASE_DIR,
|
||||||
|
VENCORD_DIRECTORY: join(BASE_DIR, "dist/desktop"),
|
||||||
VENCORD_DEV_INSTALL: "1"
|
VENCORD_DEV_INSTALL: "1"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,15 +16,11 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
export function getPluginTarget(filePath: string) {
|
||||||
* @param {string} filePath
|
|
||||||
* @returns {string | null}
|
|
||||||
*/
|
|
||||||
export function getPluginTarget(filePath) {
|
|
||||||
const pathParts = filePath.split(/[/\\]/);
|
const pathParts = filePath.split(/[/\\]/);
|
||||||
if (/^index\.tsx?$/.test(pathParts.at(-1))) pathParts.pop();
|
if (/^index\.tsx?$/.test(pathParts.at(-1)!)) pathParts.pop();
|
||||||
|
|
||||||
const identifier = pathParts.at(-1).replace(/\.tsx?$/, "");
|
const identifier = pathParts.at(-1)!.replace(/\.tsx?$/, "");
|
||||||
const identiferBits = identifier.split(".");
|
const identiferBits = identifier.split(".");
|
||||||
return identiferBits.length === 1 ? null : identiferBits.at(-1);
|
return identiferBits.length === 1 ? null : identiferBits.at(-1);
|
||||||
}
|
}
|
|
@ -43,11 +43,9 @@ if (IS_VESKTOP || !IS_VANILLA) {
|
||||||
}
|
}
|
||||||
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 "vencordDesktopPreload.js.map":
|
|
||||||
case "patcher.js.map":
|
case "patcher.js.map":
|
||||||
case "vencordDesktopMain.js.map":
|
case "main.js.map":
|
||||||
cb(join(__dirname, url));
|
cb(join(__dirname, url));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -131,7 +131,7 @@ ipcMain.handle(IpcEvents.OPEN_MONACO_EDITOR, async () => {
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
darkTheme: true,
|
darkTheme: true,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: join(__dirname, IS_DISCORD_DESKTOP ? "preload.js" : "vencordDesktopPreload.js"),
|
preload: join(__dirname, "preload.js"),
|
||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
sandbox: false
|
sandbox: false
|
||||||
|
|
|
@ -26,14 +26,14 @@ import { IS_VANILLA } from "./utils/constants";
|
||||||
|
|
||||||
console.log("[Vencord] Starting up...");
|
console.log("[Vencord] Starting up...");
|
||||||
|
|
||||||
|
// FIXME: remove at some point
|
||||||
|
export const isLegacyNonAsarVencord = IS_STANDALONE && !__dirname.endsWith(".asar");
|
||||||
|
|
||||||
// Our injector file at app/index.js
|
// Our injector file at app/index.js
|
||||||
const injectorPath = require.main!.filename;
|
const injectorPath = require.main!.filename;
|
||||||
|
|
||||||
// special discord_arch_electron injection method
|
|
||||||
const asarName = require.main!.path.endsWith("app.asar") ? "_app.asar" : "app.asar";
|
|
||||||
|
|
||||||
// The original app.asar
|
// The original app.asar
|
||||||
const asarPath = join(dirname(injectorPath), "..", asarName);
|
const asarPath = join(dirname(injectorPath), "..", "_app.asar");
|
||||||
|
|
||||||
const discordPkg = require(join(asarPath, "package.json"));
|
const discordPkg = require(join(asarPath, "package.json"));
|
||||||
require.main!.filename = join(asarPath, discordPkg.main);
|
require.main!.filename = join(asarPath, discordPkg.main);
|
||||||
|
@ -41,7 +41,7 @@ require.main!.filename = join(asarPath, discordPkg.main);
|
||||||
// @ts-ignore Untyped method? Dies from cringe
|
// @ts-ignore Untyped method? Dies from cringe
|
||||||
app.setAppPath(asarPath);
|
app.setAppPath(asarPath);
|
||||||
|
|
||||||
if (!IS_VANILLA) {
|
if (!IS_VANILLA && !isLegacyNonAsarVencord) {
|
||||||
const settings = RendererSettings.store;
|
const settings = RendererSettings.store;
|
||||||
// Repatch after host updates on Windows
|
// Repatch after host updates on Windows
|
||||||
if (process.platform === "win32") {
|
if (process.platform === "win32") {
|
||||||
|
@ -71,7 +71,7 @@ if (!IS_VANILLA) {
|
||||||
constructor(options: BrowserWindowConstructorOptions) {
|
constructor(options: BrowserWindowConstructorOptions) {
|
||||||
if (options?.webPreferences?.preload && options.title) {
|
if (options?.webPreferences?.preload && options.title) {
|
||||||
const original = options.webPreferences.preload;
|
const original = options.webPreferences.preload;
|
||||||
options.webPreferences.preload = join(__dirname, IS_DISCORD_DESKTOP ? "preload.js" : "vencordDesktopPreload.js");
|
options.webPreferences.preload = join(__dirname, "preload.js");
|
||||||
options.webPreferences.sandbox = false;
|
options.webPreferences.sandbox = false;
|
||||||
// work around discord unloading when in background
|
// work around discord unloading when in background
|
||||||
options.webPreferences.backgroundThrottling = false;
|
options.webPreferences.backgroundThrottling = false;
|
||||||
|
@ -157,5 +157,7 @@ if (!IS_VANILLA) {
|
||||||
console.log("[Vencord] Running in vanilla mode. Not loading Vencord");
|
console.log("[Vencord] Running in vanilla mode. Not loading Vencord");
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[Vencord] Loading original Discord app.asar");
|
if (!isLegacyNonAsarVencord) {
|
||||||
require(require.main!.filename);
|
console.log("[Vencord] Loading original Discord app.asar");
|
||||||
|
require(require.main!.filename);
|
||||||
|
}
|
||||||
|
|
|
@ -16,12 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const VENCORD_FILES = [
|
export const ASAR_FILE = IS_VESKTOP
|
||||||
IS_DISCORD_DESKTOP ? "patcher.js" : "vencordDesktopMain.js",
|
? "vesktop.asar"
|
||||||
IS_DISCORD_DESKTOP ? "preload.js" : "vencordDesktopPreload.js",
|
: "desktop.asar";
|
||||||
IS_DISCORD_DESKTOP ? "renderer.js" : "vencordDesktopRenderer.js",
|
|
||||||
IS_DISCORD_DESKTOP ? "renderer.css" : "vencordDesktopRenderer.css",
|
|
||||||
];
|
|
||||||
|
|
||||||
export function serializeErrors(func: (...args: any[]) => any) {
|
export function serializeErrors(func: (...args: any[]) => any) {
|
||||||
return async function () {
|
return async function () {
|
||||||
|
|
|
@ -16,20 +16,27 @@
|
||||||
* 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 { isLegacyNonAsarVencord } from "@main/patcher";
|
||||||
import { IpcEvents } from "@shared/IpcEvents";
|
import { IpcEvents } from "@shared/IpcEvents";
|
||||||
import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
|
import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
|
||||||
import { ipcMain } from "electron";
|
import { app, dialog, ipcMain } from "electron";
|
||||||
import { writeFile } from "fs/promises";
|
import {
|
||||||
|
existsSync as originalExistsSync,
|
||||||
|
renameSync as originalRenameSync,
|
||||||
|
writeFileSync as originalWriteFileSync,
|
||||||
|
} from "original-fs";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
|
|
||||||
import gitHash from "~git-hash";
|
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 { serializeErrors, VENCORD_FILES } from "./common";
|
import { ASAR_FILE, serializeErrors } 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 PendingUpdate: string | null = null;
|
||||||
|
|
||||||
|
let hasUpdateToApplyOnQuit = false;
|
||||||
|
|
||||||
async function githubGet(endpoint: string) {
|
async function githubGet(endpoint: string) {
|
||||||
return get(API_BASE + endpoint, {
|
return get(API_BASE + endpoint, {
|
||||||
|
@ -65,22 +72,22 @@ async function fetchUpdates() {
|
||||||
if (hash === gitHash)
|
if (hash === gitHash)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
data.assets.forEach(({ name, browser_download_url }) => {
|
|
||||||
if (VENCORD_FILES.some(s => name.startsWith(s))) {
|
const asset = data.assets.find(a => a.name === ASAR_FILE);
|
||||||
PendingUpdates.push([name, browser_download_url]);
|
PendingUpdate = asset.browser_download_url;
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function applyUpdates() {
|
async function applyUpdates() {
|
||||||
await Promise.all(PendingUpdates.map(
|
if (!PendingUpdate) return true;
|
||||||
async ([name, data]) => writeFile(
|
|
||||||
join(__dirname, name),
|
const data = await get(PendingUpdate);
|
||||||
await get(data)
|
originalWriteFileSync(__dirname + ".new", data);
|
||||||
)
|
hasUpdateToApplyOnQuit = true;
|
||||||
));
|
|
||||||
PendingUpdates = [];
|
PendingUpdate = null;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,3 +95,51 @@ ipcMain.handle(IpcEvents.GET_REPO, serializeErrors(() => `https://github.com/${g
|
||||||
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));
|
||||||
ipcMain.handle(IpcEvents.BUILD, serializeErrors(applyUpdates));
|
ipcMain.handle(IpcEvents.BUILD, serializeErrors(applyUpdates));
|
||||||
|
|
||||||
|
async function migrateLegacyToAsar() {
|
||||||
|
try {
|
||||||
|
const isFlatpak = process.platform === "linux" && !!process.env.FLATPAK_ID;
|
||||||
|
if (isFlatpak) throw "Flatpak Discord can't automatically be migrated.";
|
||||||
|
|
||||||
|
const data = await get(`https://github.com/${gitRemote}/releases/latest/download/desktop.asar`);
|
||||||
|
|
||||||
|
originalWriteFileSync(join(__dirname, "../vencord.asar"), data);
|
||||||
|
originalWriteFileSync(__filename, '// Legacy shim for new asar\n\nrequire("../vencord.asar");');
|
||||||
|
|
||||||
|
app.relaunch();
|
||||||
|
app.exit();
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to migrate to asar", e);
|
||||||
|
|
||||||
|
app.whenReady().then(() => {
|
||||||
|
dialog.showErrorBox(
|
||||||
|
"Legacy Install",
|
||||||
|
"The way Vencord loaded was changed and the updater failed to migrate. Please reinstall using the Vencord Installer!"
|
||||||
|
);
|
||||||
|
app.exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyPreviousUpdate() {
|
||||||
|
originalRenameSync(__dirname + ".new", __dirname);
|
||||||
|
|
||||||
|
app.relaunch();
|
||||||
|
app.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
app.on("will-quit", () => {
|
||||||
|
if (hasUpdateToApplyOnQuit)
|
||||||
|
originalRenameSync(__dirname + ".new", __dirname);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isLegacyNonAsarVencord) {
|
||||||
|
console.warn("This is a legacy non asar install! Migrating to asar and restarting...");
|
||||||
|
migrateLegacyToAsar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalExistsSync(__dirname + ".new")) {
|
||||||
|
console.warn("Found previous not applied update, applying now and restarting...");
|
||||||
|
applyPreviousUpdate();
|
||||||
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ export default definePlugin({
|
||||||
|
|
||||||
wrapSort(comparator: Function, row: any) {
|
wrapSort(comparator: Function, row: any) {
|
||||||
return row.type === 5
|
return row.type === 5
|
||||||
? -UserAffinitiesStore.getUserAffinity(row.user.id)?.affinity ?? 0
|
? -(UserAffinitiesStore.getUserAffinity(row.user.id)?.affinity ?? 0)
|
||||||
: comparator(row);
|
: comparator(row);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ contextBridge.exposeInMainWorld("VencordNative", VencordNative);
|
||||||
// Discord
|
// Discord
|
||||||
if (location.protocol !== "data:") {
|
if (location.protocol !== "data:") {
|
||||||
// #region cssInsert
|
// #region cssInsert
|
||||||
const rendererCss = join(__dirname, IS_VESKTOP ? "vencordDesktopRenderer.css" : "renderer.css");
|
const rendererCss = join(__dirname, "renderer.css");
|
||||||
|
|
||||||
const style = document.createElement("style");
|
const style = document.createElement("style");
|
||||||
style.id = "vencord-css-core";
|
style.id = "vencord-css-core";
|
||||||
|
|
|
@ -299,7 +299,7 @@ export const lazyWebpackSearchHistory = [] as Array<["find" | "findByProps" | "f
|
||||||
* Note that the example below exists already as an api, see {@link findByPropsLazy}
|
* Note that the example below exists already as an api, see {@link findByPropsLazy}
|
||||||
* @example const mod = proxyLazy(() => findByProps("blah")); console.log(mod.blah);
|
* @example const mod = proxyLazy(() => findByProps("blah")); console.log(mod.blah);
|
||||||
*/
|
*/
|
||||||
export function proxyLazyWebpack<T = any>(factory: () => any, attempts?: number) {
|
export function proxyLazyWebpack<T = any>(factory: () => T, attempts?: number) {
|
||||||
if (IS_REPORTER) lazyWebpackSearchHistory.push(["proxyLazyWebpack", [factory]]);
|
if (IS_REPORTER) lazyWebpackSearchHistory.push(["proxyLazyWebpack", [factory]]);
|
||||||
|
|
||||||
return proxyLazy<T>(factory, attempts);
|
return proxyLazy<T>(factory, attempts);
|
||||||
|
|
Loading…
Reference in a new issue