diff --git a/browser/Vencord.ts b/browser/Vencord.ts
new file mode 100644
index 000000000..2d4315df0
--- /dev/null
+++ b/browser/Vencord.ts
@@ -0,0 +1,3 @@
+import "./VencordNativeStub";
+
+export * from "../src/Vencord";
diff --git a/browser/VencordNativeStub.ts b/browser/VencordNativeStub.ts
new file mode 100644
index 000000000..bdcae4e18
--- /dev/null
+++ b/browser/VencordNativeStub.ts
@@ -0,0 +1,39 @@
+import IpcEvents from "../src/utils/IpcEvents";
+
+// Discord deletes this so need to store in variable
+var localStorage = window.localStorage;
+
+const handlers = {
+ [IpcEvents.GET_REPO]: () => "", // TODO
+ [IpcEvents.GET_SETTINGS_DIR]: () => "LocalStorage",
+
+ [IpcEvents.GET_QUICK_CSS]: () => localStorage.getItem("VencordQuickCss"),
+ [IpcEvents.GET_SETTINGS]: () => localStorage.getItem("VencordSettings") || "{}",
+ [IpcEvents.SET_SETTINGS]: (s: string) => localStorage.setItem("VencordSettings", s),
+
+ [IpcEvents.GET_UPDATES]: () => ({ ok: true, value: [] }),
+
+ [IpcEvents.OPEN_EXTERNAL]: (url: string) => open(url, "_blank"),
+ [IpcEvents.OPEN_QUICKCSS]: () => { } // TODO
+};
+
+function onEvent(event: string, ...args: any[]) {
+ const handler = handlers[event];
+ if (!handler) throw new Error(`Event ${event} not implemented.`);
+ return handler(...args);
+}
+
+window.VencordNative = {
+ getVersions: () => ({}),
+ ipc: {
+ send: (event: string, ...args: any[]) => void onEvent(event, ...args),
+ sendSync: onEvent,
+ on(event: string, listener: () => {}) {
+ // TODO quickCss
+ },
+ off(event: string, listener: () => {}) {
+ // not used for now
+ },
+ invoke: (event: string, ...args: any[]) => Promise.resolve(onEvent(event, ...args))
+ },
+};
diff --git a/browser/background.js b/browser/background.js
new file mode 100644
index 000000000..872134b7f
--- /dev/null
+++ b/browser/background.js
@@ -0,0 +1 @@
+// could use this in the future
diff --git a/browser/content.js b/browser/content.js
new file mode 100644
index 000000000..5922e8fad
--- /dev/null
+++ b/browser/content.js
@@ -0,0 +1,10 @@
+// This is just the bootstrap script
+
+if (typeof browser === "undefined") {
+ var browser = chrome;
+}
+
+var script = document.createElement("script");
+script.src = browser.runtime.getURL("dist/Vencord.js");
+// documentElement because we load before body/head are ready
+document.documentElement.appendChild(script);
diff --git a/browser/manifest.json b/browser/manifest.json
new file mode 100644
index 000000000..c01bc4496
--- /dev/null
+++ b/browser/manifest.json
@@ -0,0 +1,30 @@
+{
+ "manifest_version": 2,
+ "name": "Vencord Web",
+ "description": "Yeee",
+ "version": "1.0.0",
+ "author": "Vendicated",
+ "homepage_url": "https://github.com/Vendicated/Vencord",
+ "background": {
+ "scripts": [
+ "background.js"
+ ]
+ },
+ "content_scripts": [
+ {
+ "run_at": "document_start",
+ "matches": [
+ "*://*.discord.com/*"
+ ],
+ "js": [
+ "content.js"
+ ]
+ }
+ ],
+ "permissions": [
+ "*://*.discord.com/*"
+ ],
+ "web_accessible_resources": [
+ "dist/Vencord.js"
+ ]
+}
diff --git a/build.mjs b/build.mjs
index d6de0d2df..5b0b1c09e 100755
--- a/build.mjs
+++ b/build.mjs
@@ -2,7 +2,6 @@
import { execSync } from "child_process";
import esbuild from "esbuild";
import { readdirSync } from "fs";
-import { performance } from "perf_hooks";
/**
* @type {esbuild.WatchMode|false}
@@ -115,7 +114,7 @@ await Promise.all([
sourcemap: false,
watch,
minify: true,
- })
+ }),
]).catch(err => {
console.error("Build failed");
console.error(err.message);
diff --git a/buildWeb.mjs b/buildWeb.mjs
new file mode 100644
index 000000000..9031d1493
--- /dev/null
+++ b/buildWeb.mjs
@@ -0,0 +1,86 @@
+// TODO: Modularise these plugins since both build scripts use them
+
+import { execSync } from "child_process";
+import { createWriteStream, readdirSync } from "fs";
+import yazl from "yazl";
+import esbuild from "esbuild";
+
+/**
+ * @type {esbuild.Plugin}
+ */
+const globPlugins = {
+ name: "glob-plugins",
+ setup: build => {
+ build.onResolve({ filter: /^plugins$/ }, args => {
+ return {
+ namespace: "import-plugins",
+ path: args.path
+ };
+ });
+
+ build.onLoad({ filter: /^plugins$/, namespace: "import-plugins" }, () => {
+ const files = readdirSync("./src/plugins");
+ let code = "";
+ let obj = "";
+ for (let i = 0; i < files.length; i++) {
+ if (files[i] === "index.ts") {
+ continue;
+ }
+ const mod = `__pluginMod${i}`;
+ code += `import ${mod} from "./${files[i].replace(/.tsx?$/, "")}";\n`;
+ obj += `[${mod}.name]: ${mod},`;
+ }
+ code += `export default {${obj}}`;
+ return {
+ contents: code,
+ resolveDir: "./src/plugins"
+ };
+ });
+ }
+};
+
+const gitHash = execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
+/**
+ * @type {esbuild.Plugin}
+ */
+const gitHashPlugin = {
+ name: "git-hash-plugin",
+ setup: build => {
+ const filter = /^git-hash$/;
+ build.onResolve({ filter }, args => ({
+ namespace: "git-hash", path: args.path
+ }));
+ build.onLoad({ filter, namespace: "git-hash" }, () => ({
+ contents: `export default "${gitHash}"`
+ }));
+ }
+};
+
+await esbuild.build({
+ logLevel: "info",
+ entryPoints: ["browser/Vencord.ts"],
+ outfile: "dist/browser.js",
+ format: "iife",
+ bundle: true,
+ globalName: "Vencord",
+ target: ["esnext"],
+ footer: { js: "//# sourceURL=VencordWeb" },
+ external: ["plugins", "git-hash"],
+ plugins: [
+ globPlugins,
+ gitHashPlugin
+ ],
+ sourcemap: false,
+ minify: true,
+});
+
+const zip = new yazl.ZipFile();
+zip.outputStream.pipe(createWriteStream("dist/extension.zip")).on("close", () => {
+ console.info("Extension written to dist/extension.zip");
+});
+
+zip.addFile("dist/browser.js", "dist/Vencord.js");
+["background.js", "content.js", "manifest.json"].forEach(f => {
+ zip.addFile(`browser/${f}`, `${f}`);
+});
+zip.end();
diff --git a/package.json b/package.json
index bde4752d6..39ac69961 100644
--- a/package.json
+++ b/package.json
@@ -2,14 +2,17 @@
"devDependencies": {
"@types/node": "^18.7.13",
"@types/react": "^18.0.17",
+ "@types/yazl": "^2.4.2",
"electron": "^20.1.0",
- "esbuild": "^0.15.5"
+ "esbuild": "^0.15.5",
+ "yazl": "^2.5.1"
},
"dependencies": {
"discord-types": "^1.3.26",
"electron-devtools-installer": "^3.2.0"
},
"scripts": {
+ "buildWeb": "node buildWeb.mjs",
"build": "node build.mjs",
"watch": "node build.mjs --watch"
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 304261da2..25adfb49e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,28 +1,26 @@
-lockfileVersion: 5.3
+lockfileVersion: 5.4
specifiers:
- '@types/flux': ^3.1.11
'@types/node': ^18.7.13
'@types/react': ^18.0.17
+ '@types/yazl': ^2.4.2
discord-types: ^1.3.26
electron: ^20.1.0
electron-devtools-installer: ^3.2.0
esbuild: ^0.15.5
- jsposed: ^1.0.2
- prettier: ^2.7.1
+ yazl: ^2.5.1
dependencies:
discord-types: 1.3.26
electron-devtools-installer: 3.2.0
- jsposed: 1.0.2
- prettier: 2.7.1
devDependencies:
- '@types/flux': 3.1.11
'@types/node': 18.7.13
'@types/react': 18.0.17
+ '@types/yazl': 2.4.2
electron: 20.1.0
esbuild: 0.15.5
+ yazl: 2.5.1
packages:
@@ -65,17 +63,6 @@ packages:
defer-to-connect: 1.1.3
dev: true
- /@types/fbemitter/2.0.32:
- resolution: {integrity: sha512-Hwq28bBlbmfCgLnNJvjl5ssTrbZCTSblI4vqPpqZrbbEL8vn5l2UivxhlMYfUY7a4SR8UB6RKoLjOZfljqAa6g==}
- dev: true
-
- /@types/flux/3.1.11:
- resolution: {integrity: sha512-Aq4UB1ZqAKcPbhB0GpgMw2sntvOh71he9tjz53TLKrI7rw3Y3LxCW5pTYY9IV455hQapm4pmxFjpqlWOs308Yg==}
- dependencies:
- '@types/fbemitter': 2.0.32
- '@types/react': 18.0.17
- dev: true
-
/@types/keyv/3.1.4:
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
dependencies:
@@ -126,6 +113,12 @@ packages:
dev: true
optional: true
+ /@types/yazl/2.4.2:
+ resolution: {integrity: sha512-T+9JH8O2guEjXNxqmybzQ92mJUh2oCwDDMSSimZSe1P+pceZiFROZLYmcbqkzV5EUwz6VwcKXCO2S2yUpra6XQ==}
+ dependencies:
+ '@types/node': 18.7.13
+ dev: true
+
/balanced-match/1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: false
@@ -684,10 +677,6 @@ packages:
graceful-fs: 4.2.10
dev: true
- /jsposed/1.0.2:
- resolution: {integrity: sha512-t1vQsxnH65kOBRc4swue6EFm/WmPZwLLJ/84IV3aP93f2F724tHK5HIWwrRUKYYqJb9BJEewBsVh/jHQssJfbw==}
- dev: false
-
/jszip/3.10.1:
resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
dependencies:
@@ -822,12 +811,6 @@ packages:
engines: {node: '>=4'}
dev: true
- /prettier/2.7.1:
- resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==}
- engines: {node: '>=10.13.0'}
- hasBin: true
- dev: false
-
/process-nextick-args/2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
dev: false
@@ -1001,3 +984,9 @@ packages:
buffer-crc32: 0.2.13
fd-slicer: 1.1.0
dev: true
+
+ /yazl/2.5.1:
+ resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==}
+ dependencies:
+ buffer-crc32: 0.2.13
+ dev: true
diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx
index d4a3dcaec..4dbb1b21a 100644
--- a/src/components/Settings.tsx
+++ b/src/components/Settings.tsx
@@ -9,6 +9,7 @@ import { startPlugin } from "../plugins";
import { stopPlugin } from '../plugins/index';
import { Flex } from './Flex';
import { ChangeList } from '../utils/ChangeList';
+import { IS_WEB } from '../utils/isWeb';
function showErrorToast(message: string) {
Toasts.show({
@@ -72,7 +73,7 @@ export default ErrorBoundary.wrap(function Settings() {
SettingsDir: {settingsDir}
-
+ {!IS_WEB &&
-
+ }
Settings
Use QuickCss
- settings.notifyAboutUpdates = v}
note="Shows a Toast on StartUp"
>
Get notified about new Updates
-
- }
+ {!IS_WEB && settings.unsafeRequire = v}
note="Enables VencordNative.require. Useful for testing, very bad for security. Leave this off unless you need it."
>
Enable Unsafe Require
-
+ }
diff --git a/src/plugins/settings.ts b/src/plugins/settings.ts
index 2ed85e63e..6927f642f 100644
--- a/src/plugins/settings.ts
+++ b/src/plugins/settings.ts
@@ -1,6 +1,7 @@
import definePlugin from "../utils/types";
import gitHash from "git-hash";
import { Devs } from '../utils/constants';
+import { IS_WEB } from "../utils/isWeb";
export default definePlugin({
name: "Settings",
@@ -15,9 +16,12 @@ export default definePlugin({
replace: m => {
const idx = m.indexOf("Host") - 1;
const template = m.slice(0, idx);
- return `${m}, ${template}"Vencord ", "${gitHash}"), " "), ` +
- `${template} "Electron ",VencordNative.getVersions().electron)," "), ` +
- `${template} "Chrome ",VencordNative.getVersions().chrome)," ")`;
+ let r = `${m}, ${template}"Vencord ", "${gitHash}${IS_WEB ? " (Web)" : ""}"), " ")`;
+ if (!IS_WEB) {
+ r += `,${template} "Electron ",VencordNative.getVersions().electron)," "),`;
+ r += `${template} "Chrome ",VencordNative.getVersions().chrome)," ")`;
+ }
+ return r;
}
}
]
@@ -28,7 +32,7 @@ export default definePlugin({
replace: (m, mod) =>
`{section:${mod}.ID.HEADER,label:"Vencord"},` +
`{section:"VencordSetting",label:"Vencord",element:Vencord.Components.Settings},` +
- `{section:"VencordUpdater",label:"Updater",element:Vencord.Components.Updater},` +
+ `{section:"VencordUpdater",label:"Updater",element:Vencord.Components.Updater,predicate:()=>!IS_WEB},` +
`{section:${mod}.ID.DIVIDER},${m}`
}
diff --git a/src/utils/isWeb.ts b/src/utils/isWeb.ts
new file mode 100644
index 000000000..408216483
--- /dev/null
+++ b/src/utils/isWeb.ts
@@ -0,0 +1 @@
+export const IS_WEB = window.IS_WEB = typeof window.DiscordNative === "undefined";
diff --git a/src/utils/types.ts b/src/utils/types.ts
index a6b79c5e3..1c6361360 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -33,6 +33,10 @@ interface PluginDef {
patches?: Omit[];
dependencies?: string[],
required?: boolean;
+ /**
+ * Set this if your plugin only works on Browser or Desktop, not both
+ */
+ target?: "WEB" | "DESKTOP" | "BOTH";
}
export type IpcRes = { ok: true; value: V; } | { ok: false, error: any; };
diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts
index 469b9302c..ffd81d5a8 100644
--- a/src/webpack/patchWebpack.ts
+++ b/src/webpack/patchWebpack.ts
@@ -6,6 +6,7 @@ let webpackChunk: any[];
const logger = new Logger("WebpackInterceptor", "#8caaee");
+console.log("prepatch is", window[WEBPACK_CHUNK]);
Object.defineProperty(window, WEBPACK_CHUNK, {
get: () => webpackChunk,
set: (v) => {