feat: Experimental browser support
This commit is contained in:
parent
a9eae106c7
commit
cc25753314
14 changed files with 212 additions and 41 deletions
3
browser/Vencord.ts
Normal file
3
browser/Vencord.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import "./VencordNativeStub";
|
||||
|
||||
export * from "../src/Vencord";
|
39
browser/VencordNativeStub.ts
Normal file
39
browser/VencordNativeStub.ts
Normal file
|
@ -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))
|
||||
},
|
||||
};
|
1
browser/background.js
Normal file
1
browser/background.js
Normal file
|
@ -0,0 +1 @@
|
|||
// could use this in the future
|
10
browser/content.js
Normal file
10
browser/content.js
Normal file
|
@ -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);
|
30
browser/manifest.json
Normal file
30
browser/manifest.json
Normal file
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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);
|
||||
|
|
86
buildWeb.mjs
Normal file
86
buildWeb.mjs
Normal file
|
@ -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();
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: <code style={{ userSelect: 'text', cursor: 'text' }}>{settingsDir}</code>
|
||||
</Forms.FormText>
|
||||
|
||||
<Flex className={classes(Margins.marginBottom20)}>
|
||||
{!IS_WEB && <Flex className={classes(Margins.marginBottom20)}>
|
||||
<Button
|
||||
onClick={() => window.DiscordNative.app.relaunch()}
|
||||
size={Button.Sizes.SMALL}
|
||||
|
@ -94,7 +95,7 @@ export default ErrorBoundary.wrap(function Settings() {
|
|||
>
|
||||
Open QuickCSS File
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>}
|
||||
<Forms.FormDivider />
|
||||
<Forms.FormTitle tag="h5">Settings</Forms.FormTitle>
|
||||
<Switch
|
||||
|
@ -104,20 +105,20 @@ export default ErrorBoundary.wrap(function Settings() {
|
|||
>
|
||||
Use QuickCss
|
||||
</Switch>
|
||||
<Switch
|
||||
{!IS_WEB && <Switch
|
||||
value={settings.notifyAboutUpdates}
|
||||
onChange={(v: boolean) => settings.notifyAboutUpdates = v}
|
||||
note="Shows a Toast on StartUp"
|
||||
>
|
||||
Get notified about new Updates
|
||||
</Switch>
|
||||
<Switch
|
||||
</Switch>}
|
||||
{!IS_WEB && <Switch
|
||||
value={settings.unsafeRequire}
|
||||
onChange={(v: boolean) => settings.unsafeRequire = v}
|
||||
note="Enables VencordNative.require. Useful for testing, very bad for security. Leave this off unless you need it."
|
||||
>
|
||||
Enable Unsafe Require
|
||||
</Switch>
|
||||
</Switch>}
|
||||
|
||||
<Forms.FormDivider />
|
||||
|
||||
|
|
|
@ -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}`
|
||||
|
||||
}
|
||||
|
|
1
src/utils/isWeb.ts
Normal file
1
src/utils/isWeb.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export const IS_WEB = window.IS_WEB = typeof window.DiscordNative === "undefined";
|
|
@ -33,6 +33,10 @@ interface PluginDef {
|
|||
patches?: Omit<Patch, "plugin">[];
|
||||
dependencies?: string[],
|
||||
required?: boolean;
|
||||
/**
|
||||
* Set this if your plugin only works on Browser or Desktop, not both
|
||||
*/
|
||||
target?: "WEB" | "DESKTOP" | "BOTH";
|
||||
}
|
||||
|
||||
export type IpcRes<V = any> = { ok: true; value: V; } | { ok: false, error: any; };
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Reference in a new issue