Restructure BD into a small mono-repo
This is a repo-wide refactor that introduces the injector to the main branch. The new architecture is as such: common/ injector/ renderer/
This commit is contained in:
parent
59f2025309
commit
74b2dace04
61
.eslintrc
61
.eslintrc
|
@ -1,15 +1,5 @@
|
|||
{
|
||||
"extends": ["eslint:recommended", "plugin:react/recommended"],
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "16.12.0"
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"parserOptions": {
|
||||
|
@ -91,64 +81,17 @@
|
|||
"template-curly-spacing": "error",
|
||||
"wrap-iife": ["error", "inside"],
|
||||
"yield-star-spacing": "error",
|
||||
"yoda": "error",
|
||||
|
||||
|
||||
"react/display-name": "off",
|
||||
"react/prop-types": "off",
|
||||
"react/jsx-key": "off",
|
||||
"react/jsx-no-target-blank": "error",
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error"
|
||||
"yoda": "error"
|
||||
},
|
||||
"globals": {
|
||||
"webpackJsonp": "readonly",
|
||||
"Proxy": "readonly",
|
||||
"Set": "readonly",
|
||||
"WeakMap": "readonly",
|
||||
"Map": "readonly",
|
||||
"Promise": "readonly",
|
||||
"ace": "readonly",
|
||||
"Reflect": "readonly",
|
||||
"DiscordNative": "readonly",
|
||||
"__non_webpack_require__": "readonly",
|
||||
"Symbol": "readonly",
|
||||
|
||||
"alert": "off",
|
||||
"blur": "off",
|
||||
"caches": "off",
|
||||
"close": "off",
|
||||
"closed": "off",
|
||||
"confirm": "off",
|
||||
"crypto": "off",
|
||||
"defaultstatus": "off",
|
||||
"event": "off",
|
||||
"external": "off",
|
||||
"find": "off",
|
||||
"focus": "off",
|
||||
"frames": "off",
|
||||
"history": "off",
|
||||
"length": "off",
|
||||
"location": "off",
|
||||
"locationbar": "off",
|
||||
"menubar": "off",
|
||||
"name": "off",
|
||||
"navigator": "off",
|
||||
"open": "off",
|
||||
"opener": "off",
|
||||
"origin": "off",
|
||||
"parent": "off",
|
||||
"personalbar": "off",
|
||||
"print": "off",
|
||||
"prompt": "off",
|
||||
"screen": "off",
|
||||
"scroll": "off",
|
||||
"scrollbars": "off",
|
||||
"self": "off",
|
||||
"status": "off",
|
||||
"statusbar": "off",
|
||||
"stop": "off",
|
||||
"toolbar": "off",
|
||||
"top": "off"
|
||||
"Symbol": "readonly"
|
||||
}
|
||||
}
|
|
@ -33,15 +33,15 @@ This project and everyone participating in it is governed by the [Code of Conduc
|
|||
|
||||
### BetterDiscord Architecture
|
||||
|
||||
BetterDiscord is currently broken up into two main pieces--the local injector, and the remote application.
|
||||
BetterDiscord is currently broken up into two main pieces--the local injector, and the renderer application.
|
||||
|
||||
#### Injector
|
||||
|
||||
The injector is the piece that runs on the user's computer, and the piece added by the [installer](https://github.com/rauenzi/BBDInstaller). The main job of this package is to inject into Discord and load the remote package. The injector and its code lives on the [injector branch](https://github.com/rauenzi/BetterDiscordApp/tree/injector).
|
||||
The injector is the piece that runs on the user's computer, and the piece added by the [installer](https://github.com/rauenzi/BBDInstaller). The main job of this package is to inject into Discord and load the renderer package. The injector and its code lives in the `injector` folder.
|
||||
|
||||
#### Remote Application
|
||||
#### Renderer Application
|
||||
|
||||
This is the main payload of BetterDiscord. This is what gets linked remotely by the [injector](#injector). This portion is where most of the user interaction and development will be. This module is responsible for loading plugins and themes, as well as handling settings, emotes and more.
|
||||
This is the main payload of BetterDiscord. This is what gets linked executed in the renderer context by the [injector](#injector). This portion is where most of the user interaction and development will be. This module is responsible for loading plugins and themes, as well as handling settings, emotes and more.
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/* eslint-disable no-multi-spaces */
|
||||
|
||||
export const MINIMIZE = "bd-window-minimize";
|
||||
export const MAXIMIZE = "bd-window-maximize";
|
||||
export const RELAUNCH = "bd-relaunch-app";
|
||||
export const GET_PATH = "bd-get-path";
|
||||
export const RUN_SCRIPT = "bd-run-script";
|
||||
export const NAVIGATE = "bd-did-navigate-in-page";
|
||||
export const OPEN_DEVTOOLS = "bd-open-devtools";
|
||||
export const CLOSE_DEVTOOLS = "bd-close-devtools";
|
||||
export const OPEN_WINDOW = "bd-open-window";
|
|
@ -0,0 +1 @@
|
|||
node_modules
|
|
@ -0,0 +1,3 @@
|
|||
# BetterDiscord Injector
|
||||
|
||||
You're probably looking for the main app, [click here](https://github.com/rauenzi/BetterDiscordApp) to go there.
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"common": ["../common"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "betterdiscord-injector",
|
||||
"version": "0.6.2",
|
||||
"description": "BetterDiscord injector module",
|
||||
"main": "src/index.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "cp ./src/preload.js ../dist/preload.js && webpack --progress --color",
|
||||
"watch": "cp ./src/preload.js ../dist/preload.js && webpack --progress --color --watch",
|
||||
"build-prod": "cp ./src/preload.js ../dist/preload.js && webpack --stats minimal --mode production",
|
||||
"lint": "eslint --ext .js src/"
|
||||
},
|
||||
"devDependencies": {
|
||||
"circular-dependency-plugin": "^5.2.2",
|
||||
"eslint": "^7.21.0",
|
||||
"webpack": "^5.24.2",
|
||||
"webpack-cli": "^4.5.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
const path = require("path");
|
||||
const electron = require("electron");
|
||||
const Module = require("module");
|
||||
|
||||
import ipc from "./modules/ipc";
|
||||
import BrowserWindow from "./modules/browserwindow";
|
||||
import CSP from "./modules/csp";
|
||||
|
||||
|
||||
process.env.NODE_OPTIONS = "--no-force-async-hooks-checks";
|
||||
electron.app.commandLine.appendSwitch("no-force-async-hooks-checks");
|
||||
process.electronBinding("command_line").appendSwitch("no-force-async-hooks-checks");
|
||||
|
||||
|
||||
// Patch and replace the built-in BrowserWindow
|
||||
BrowserWindow.patchBrowserWindow();
|
||||
|
||||
// Register all IPC events
|
||||
ipc.registerEvents();
|
||||
|
||||
|
||||
// Remove CSP immediately on linux since they install to discord_desktop_core still
|
||||
if (process.platform == "win32" || process.platform == "darwin") electron.app.once("ready", CSP.remove);
|
||||
else CSP.remove();
|
||||
|
||||
// Use Discord's info to run the app
|
||||
if (process.platform == "win32" || process.platform == "darwin") {
|
||||
const basePath = path.join(electron.app.getAppPath(), "..", "app.asar");
|
||||
const pkg = __non_webpack_require__(path.join(basePath, "package.json"));
|
||||
electron.app.setAppPath(basePath);
|
||||
electron.app.name = pkg.name;
|
||||
Module._load(path.join(basePath, pkg.main), null, true);
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const electron = require("electron");
|
||||
|
||||
import ReactDevTools from "./reactdevtools";
|
||||
import * as IPCEvents from "common/constants/ipcevents";
|
||||
|
||||
// Build info file only exists for non-linux (for current injection)
|
||||
const appPath = electron.app.getAppPath();
|
||||
const buildInfoFile = path.resolve(appPath, "..", "build_info.json");
|
||||
|
||||
// Locate data path to find transparency settings
|
||||
let dataPath = "";
|
||||
if (process.platform === "win32") dataPath = process.env.APPDATA;
|
||||
else if (process.platform === "darwin") dataPath = path.join(process.env.HOME, "Library", "Preferences");
|
||||
else dataPath = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : path.join(process.env.HOME, ".config");
|
||||
dataPath = path.join(dataPath, "BetterDiscord") + "/";
|
||||
|
||||
|
||||
electron.app.once("ready", async () => {
|
||||
if (!BetterDiscord.getSetting("developer", "reactDevTools")) return;
|
||||
await ReactDevTools.install();
|
||||
});
|
||||
|
||||
export default class BetterDiscord {
|
||||
static getWindowPrefs() {
|
||||
if (!fs.existsSync(buildInfoFile)) return {};
|
||||
const buildInfo = __non_webpack_require__(buildInfoFile);
|
||||
const prefsFile = path.resolve(dataPath, "data", buildInfo.releaseChannel, "windowprefs.json");
|
||||
if (!fs.existsSync(prefsFile)) return {};
|
||||
return __non_webpack_require__(prefsFile);
|
||||
}
|
||||
|
||||
static getSetting(category, key) {
|
||||
if (this._settings) return this._settings[category]?.[key];
|
||||
|
||||
try {
|
||||
const buildInfo = __non_webpack_require__(buildInfoFile);
|
||||
const settingsFile = path.resolve(dataPath, "data", buildInfo.releaseChannel, "settings.json");
|
||||
this._settings = __non_webpack_require__(settingsFile) ?? {};
|
||||
return this._settings[category]?.[key];
|
||||
}
|
||||
catch (_) {
|
||||
this._settings = {};
|
||||
return this._settings[category]?.[key];
|
||||
}
|
||||
}
|
||||
|
||||
static ensureDirectories() {
|
||||
if (!fs.existsSync(dataPath)) fs.mkdirSync(dataPath);
|
||||
if (!fs.existsSync(path.join(dataPath, "plugins"))) fs.mkdirSync(path.join(dataPath, "plugins"));
|
||||
if (!fs.existsSync(path.join(dataPath, "themes"))) fs.mkdirSync(path.join(dataPath, "themes"));
|
||||
}
|
||||
|
||||
static async ensureWebpackModules(browserWindow) {
|
||||
await browserWindow.webContents.executeJavaScript(`new Promise(resolve => {
|
||||
const check = function() {
|
||||
if (window.webpackJsonp && window.webpackJsonp.flat().flat().length >= 7000) return resolve();
|
||||
setTimeout(check, 100);
|
||||
};
|
||||
check();
|
||||
});`);
|
||||
}
|
||||
|
||||
static async injectRenderer(browserWindow) {
|
||||
const location = path.join(__dirname, "renderer.js");
|
||||
if (!fs.existsSync(location)) return; // TODO: cut a fatal log
|
||||
const content = fs.readFileSync(location).toString();
|
||||
const success = await browserWindow.webContents.executeJavaScript(`
|
||||
(() => {
|
||||
try {
|
||||
${content}
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
`);
|
||||
|
||||
if (!success) return; // TODO: cut a fatal log
|
||||
}
|
||||
|
||||
static setup(browserWindow) {
|
||||
// Setup some useful vars to avoid blocking IPC calls
|
||||
process.env.DISCORD_PRELOAD = browserWindow.__originalPreload;
|
||||
process.env.DISCORD_APP_PATH = appPath;
|
||||
process.env.DISCORD_USER_DATA = electron.app.getPath("userData");
|
||||
process.env.BETTERDISCORD_DATA_PATH = dataPath;
|
||||
|
||||
// When DOM is available, pass the renderer over the wall
|
||||
browserWindow.webContents.on("dom-ready", () => {
|
||||
this.injectRenderer(browserWindow);
|
||||
});
|
||||
|
||||
// This is used to alert renderer code to onSwitch events
|
||||
browserWindow.webContents.on("did-navigate-in-page", () => {
|
||||
browserWindow.webContents.send(IPCEvents.NAVIGATE);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
const electron = require("electron");
|
||||
const path = require("path");
|
||||
|
||||
import BetterDiscord from "./betterdiscord";
|
||||
|
||||
class BrowserWindow extends electron.BrowserWindow {
|
||||
constructor(options) {
|
||||
if (!options || !options.webPreferences || !options.webPreferences.preload || !options.title) return super(options); // eslint-disable-line constructor-super
|
||||
const originalPreload = options.webPreferences.preload;
|
||||
options.webPreferences.preload = path.join(__dirname, "preload.js");
|
||||
|
||||
// Don't allow just "truthy" values
|
||||
const shouldBeTransparent = BetterDiscord.getSetting("window", "transparency");
|
||||
if (typeof(shouldBeTransparent) === "boolean" && shouldBeTransparent) {
|
||||
options.transparent = true;
|
||||
options.backgroundColor = "#00000000";
|
||||
}
|
||||
|
||||
// Only affect frame if it is *explicitly* set
|
||||
// const shouldHaveFrame = BetterDiscord.getSetting("window", "frame");
|
||||
// if (typeof(shouldHaveFrame) === "boolean") options.frame = shouldHaveFrame;
|
||||
|
||||
super(options);
|
||||
this.__originalPreload = originalPreload;
|
||||
BetterDiscord.setup(this);
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(BrowserWindow, electron.BrowserWindow);
|
||||
|
||||
export default class {
|
||||
static patchBrowserWindow() {
|
||||
// Reassign electron using proxy to avoid the onReady issue, thanks Powercord!
|
||||
const newElectron = new Proxy(electron, {
|
||||
get: function(target, prop) {
|
||||
if (prop === "BrowserWindow") return BrowserWindow;
|
||||
return target[prop];
|
||||
}
|
||||
});
|
||||
const electronPath = __non_webpack_require__.resolve("electron");
|
||||
delete __non_webpack_require__.cache[electronPath].exports; // If it didn't work, try to delete existing
|
||||
__non_webpack_require__.cache[electronPath].exports = newElectron; // Try to assign again after deleting
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
const electron = require("electron");
|
||||
|
||||
export default class {
|
||||
static remove() {
|
||||
electron.session.defaultSession.webRequest.onHeadersReceived(function(details, callback) {
|
||||
if (!details.responseHeaders["content-security-policy-report-only"] && !details.responseHeaders["content-security-policy"]) return callback({cancel: false});
|
||||
delete details.responseHeaders["content-security-policy-report-only"];
|
||||
delete details.responseHeaders["content-security-policy"];
|
||||
callback({cancel: false, responseHeaders: details.responseHeaders});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
import {ipcMain as ipc, BrowserWindow, app, dialog} from "electron";
|
||||
|
||||
import * as IPCEvents from "common/constants/ipcevents";
|
||||
|
||||
const getPath = (event, pathReq) => {
|
||||
let returnPath;
|
||||
switch (pathReq) {
|
||||
case "appPath":
|
||||
returnPath = app.getAppPath();
|
||||
break;
|
||||
case "appData":
|
||||
case "userData":
|
||||
case "home":
|
||||
case "cache":
|
||||
case "temp":
|
||||
case "exe":
|
||||
case "module":
|
||||
case "desktop":
|
||||
case "documents":
|
||||
case "downloads":
|
||||
case "music":
|
||||
case "pictures":
|
||||
case "videos":
|
||||
case "recent":
|
||||
case "logs":
|
||||
returnPath = app.getPath(pathReq);
|
||||
break;
|
||||
default:
|
||||
returnPath = "";
|
||||
}
|
||||
|
||||
event.returnValue = returnPath;
|
||||
};
|
||||
|
||||
const relaunch = () => {
|
||||
app.quit();
|
||||
app.relaunch();
|
||||
};
|
||||
|
||||
const runScript = async (event, script) => {
|
||||
try {
|
||||
// TODO: compile with vm to prevent escape with clever strings
|
||||
await event.sender.executeJavaScript(`(() => {try {${script}} catch {}})();`);
|
||||
}
|
||||
catch (e) {
|
||||
// TODO: cut a log
|
||||
}
|
||||
};
|
||||
|
||||
const openDevTools = event => event.sender.openDevTools();
|
||||
const closeDevTools = event => event.sender.closeDevTools();
|
||||
|
||||
const createBrowserWindow = async (event, url, {windowOptions, closeOnUrl} = {}) => {
|
||||
return await new Promise(resolve => {
|
||||
const windowInstance = new BrowserWindow(windowOptions);
|
||||
windowInstance.webContents.on("did-navigate", (_, navUrl) => {
|
||||
if (navUrl != closeOnUrl) return;
|
||||
windowInstance.close();
|
||||
resolve();
|
||||
});
|
||||
windowInstance.loadURL(url);
|
||||
});
|
||||
};
|
||||
|
||||
export default class IPCMain {
|
||||
static registerEvents() {
|
||||
ipc.on(IPCEvents.GET_PATH, getPath);
|
||||
ipc.on(IPCEvents.RELAUNCH, relaunch);
|
||||
ipc.on(IPCEvents.OPEN_DEVTOOLS, openDevTools);
|
||||
ipc.on(IPCEvents.CLOSE_DEVTOOLS, closeDevTools);
|
||||
ipc.handle(IPCEvents.RUN_SCRIPT, runScript);
|
||||
ipc.handle(IPCEvents.OPEN_WINDOW, createBrowserWindow);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import {session} from "electron";
|
||||
|
||||
export const REACT_DEVTOOLS_ID = "fmkadmapgofadopljbjfkapdkoienihi";
|
||||
|
||||
const findExtension = function() {
|
||||
let extensionPath = "";
|
||||
if (process.platform === "win32") extensionPath = path.resolve(process.env.LOCALAPPDATA, "Google/Chrome/User Data");
|
||||
else if (process.platform === "linux") extensionPath = path.resolve(process.env.HOME, ".config/google-chrome");
|
||||
else if (process.platform === "darwin") extensionPath = path.resolve(process.env.HOME, "Library/Application Support/Google/Chrome");
|
||||
else extensionPath = path.resolve(process.env.HOME, ".config/chromium");
|
||||
extensionPath += `/Default/Extensions/${REACT_DEVTOOLS_ID}`;
|
||||
if (fs.existsSync(extensionPath)) {
|
||||
const versions = fs.readdirSync(extensionPath);
|
||||
extensionPath = path.resolve(extensionPath, versions[versions.length - 1]);
|
||||
}
|
||||
|
||||
const isExtensionInstalled = fs.existsSync(extensionPath);
|
||||
if (isExtensionInstalled) return extensionPath;
|
||||
return "";
|
||||
};
|
||||
|
||||
export default class ReactDevTools {
|
||||
static async install() {
|
||||
const extPath = findExtension();
|
||||
if (!extPath) return; // TODO: cut a log
|
||||
|
||||
try {
|
||||
const ext = await session.defaultSession.loadExtension(extPath);
|
||||
if (!ext) return; // TODO: cut a log
|
||||
}
|
||||
catch (err) {
|
||||
// TODO: cut a log
|
||||
}
|
||||
}
|
||||
|
||||
static async remove() {
|
||||
const extPath = findExtension();
|
||||
if (!extPath) return; // TODO: cut a log
|
||||
|
||||
try {
|
||||
await session.defaultSession.removeExtension(extPath);
|
||||
}
|
||||
catch (err) {
|
||||
// TODO: cut a log
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
const Module = require("module");
|
||||
const path = require("path");
|
||||
const electron = require("electron");
|
||||
|
||||
/* global window:false */
|
||||
|
||||
// const context = electron.webFrame.top.context;
|
||||
Object.defineProperty(window, "webpackJsonp", {
|
||||
get: () => electron.webFrame.top.context.webpackJsonp
|
||||
});
|
||||
|
||||
electron.webFrame.top.context.global = electron.webFrame.top.context;
|
||||
electron.webFrame.top.context.require = require;
|
||||
electron.webFrame.top.context.process = process;
|
||||
|
||||
// Load Discord's original preload
|
||||
const preload = process.env.DISCORD_PRELOAD;
|
||||
if (preload) {
|
||||
|
||||
// Restore original preload for future windows
|
||||
process.electronBinding("command_line").appendSwitch("preload", preload);
|
||||
|
||||
// Run original preload
|
||||
try {require(preload);}
|
||||
catch (e) {
|
||||
// TODO bail out
|
||||
}
|
||||
}
|
||||
|
||||
Module.globalPaths.push(path.resolve(process.env.DISCORD_APP_PATH, "..", "app.asar", "node_modules"));
|
|
@ -0,0 +1,47 @@
|
|||
const path = require("path");
|
||||
const CircularDependencyPlugin = require("circular-dependency-plugin");
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
|
||||
module.exports = (env, argv) => ({
|
||||
mode: "development",
|
||||
target: "node",
|
||||
devtool: argv.mode === "production" ? undefined : "eval-source-map",
|
||||
entry: "./src/index.js",
|
||||
output: {
|
||||
filename: "injector.js",
|
||||
path: path.resolve(__dirname, "..", "dist")
|
||||
},
|
||||
externals: {
|
||||
electron: `require("electron")`,
|
||||
fs: `require("fs")`,
|
||||
path: `require("path")`,
|
||||
request: `require("request")`,
|
||||
events: `require("events")`,
|
||||
rimraf: `require("rimraf")`,
|
||||
yauzl: `require("yauzl")`,
|
||||
mkdirp: `require("mkdirp")`,
|
||||
module: `require("module")`
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".js"],
|
||||
alias: {
|
||||
common: path.resolve(__dirname, "..", "common")
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new CircularDependencyPlugin({
|
||||
exclude: /node_modules/,
|
||||
cwd: process.cwd(),
|
||||
})
|
||||
],
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
compress: {drop_debugger: false},
|
||||
keep_classnames: true
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
});
|
File diff suppressed because it is too large
Load Diff
52
package.json
52
package.json
|
@ -1,51 +1,23 @@
|
|||
{
|
||||
"name": "betterdiscord",
|
||||
"version": "1.0.0",
|
||||
"description": "Enhances Discord adding functionality and themes.",
|
||||
"description": "Enhances Discord by adding functionality and themes.",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"build": "webpack --progress --colors",
|
||||
"watch": "webpack --progress --colors --watch",
|
||||
"build-prod": "webpack --display errors-only --mode production -o dist/remote.js --devtool none",
|
||||
"lint-js": "eslint --ext .jsx,.js src/",
|
||||
"build-css": "postcss src/styles/index.css -o dist/style.css",
|
||||
"watch-css": "postcss src/styles/index.css -o dist/style.css -w",
|
||||
"build-prod-css": "postcss src/styles/index.css -o dist/style.css --no-map --env production",
|
||||
"lint-css": "stylelint src/styles/*.css && stylelint src/styles/**/*.css",
|
||||
"lint": "npm run lint-js && npm run lint-css",
|
||||
"test": "mocha --require @babel/register --recursive \"./tests/*.js\"",
|
||||
"lint-prod": "npm run lint-js -- --quiet && npm run lint-css -- --quiet",
|
||||
"test-prod": "npm run test -- --reporter min"
|
||||
"install": "cd injector && npm install && cd ../renderer && npm install",
|
||||
"build": "npm run build-injector && npm run build-renderer",
|
||||
"build-prod": "npm run build-prod --prefix injector && npm run build-prod --prefix renderer",
|
||||
"build-injector": "npm run build --prefix injector",
|
||||
"build-renderer": "npm run build --prefix renderer",
|
||||
"inject": "node scripts/inject.js",
|
||||
"lint": "eslint --ext .js common/ && npm run lint --prefix injector && npm run lint --prefix renderer",
|
||||
"test": "mocha --require @babel/register --recursive \"./tests/renderer/*.js\"",
|
||||
"dist": "npm run build-prod && node scripts/pack.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/rauenzi/BetterDiscordApp.git"
|
||||
},
|
||||
"author": "rauenzi",
|
||||
"bugs": {
|
||||
"url": "https://github.com/rauenzi/BetterDiscordApp/issues"
|
||||
},
|
||||
"homepage": "https://github.com/rauenzi/BetterDiscordApp",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.3",
|
||||
"@babel/preset-env": "^7.12.1",
|
||||
"@babel/preset-react": "^7.12.1",
|
||||
"@babel/register": "^7.12.1",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-plugin-module-resolver": "^4.0.0",
|
||||
"circular-dependency-plugin": "^5.2.0",
|
||||
"css-loader": "^5.1.0",
|
||||
"asar": "^3.0.3",
|
||||
"eslint": "^7.12.0",
|
||||
"eslint-plugin-react": "^7.21.5",
|
||||
"mocha": "^8.2.0",
|
||||
"postcss": "^8.1.4",
|
||||
"postcss-cli": "^8.1.0",
|
||||
"postcss-csso": "^4.0.0",
|
||||
"postcss-easy-import": "^3.0.0",
|
||||
"postcss-loader": "^5.0.0",
|
||||
"stylelint": "^13.7.2",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
"mocha": "^8.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"@babel/env",
|
||||
{
|
||||
"targets": {
|
||||
"node": "12.8.1"
|
||||
"node": "12.14.1"
|
||||
}
|
||||
}
|
||||
]],
|
||||
|
@ -13,7 +13,8 @@
|
|||
"alias": {
|
||||
"builtins": "./src/builtins/builtins.js",
|
||||
"data": "./src/data/data.js",
|
||||
"modules": "./src/modules/modules.js"
|
||||
"modules": "./src/modules/modules.js",
|
||||
"common": "../common"
|
||||
}
|
||||
}
|
||||
]]
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"extends": ["plugin:react/recommended"],
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "16.12.0"
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"rules": {
|
||||
"react/display-name": "off",
|
||||
"react/prop-types": "off",
|
||||
"react/jsx-key": "off",
|
||||
"react/jsx-no-target-blank": "error",
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error"
|
||||
},
|
||||
"globals": {
|
||||
"webpackJsonp": "readonly",
|
||||
|
||||
"alert": "off",
|
||||
"blur": "off",
|
||||
"caches": "off",
|
||||
"close": "off",
|
||||
"closed": "off",
|
||||
"confirm": "off",
|
||||
"crypto": "off",
|
||||
"defaultstatus": "off",
|
||||
"event": "off",
|
||||
"external": "off",
|
||||
"find": "off",
|
||||
"focus": "off",
|
||||
"frames": "off",
|
||||
"history": "off",
|
||||
"length": "off",
|
||||
"location": "off",
|
||||
"locationbar": "off",
|
||||
"menubar": "off",
|
||||
"name": "off",
|
||||
"navigator": "off",
|
||||
"open": "off",
|
||||
"opener": "off",
|
||||
"origin": "off",
|
||||
"parent": "off",
|
||||
"personalbar": "off",
|
||||
"print": "off",
|
||||
"prompt": "off",
|
||||
"screen": "off",
|
||||
"scroll": "off",
|
||||
"scrollbars": "off",
|
||||
"self": "off",
|
||||
"status": "off",
|
||||
"statusbar": "off",
|
||||
"stop": "off",
|
||||
"toolbar": "off",
|
||||
"top": "off"
|
||||
}
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"target": "es2020",
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"modules": ["./src/modules/modules.js"],
|
||||
"builtins": ["./src/builtins/builtins.js"],
|
||||
"data": ["./src/data/data.js"]
|
||||
"data": ["./src/data/data.js"],
|
||||
"common": ["../common"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
"exclude": ["node_modules"]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "betterdiscord-renderer",
|
||||
"version": "1.0.0",
|
||||
"description": "Renderer portion of the BetterDiscord application.",
|
||||
"private": true,
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"build": "webpack --progress --colors",
|
||||
"watch": "webpack --progress --colors --watch",
|
||||
"build-prod": "webpack --display errors-only --mode production --devtool none",
|
||||
"lint-js": "eslint --ext .jsx,.js src/",
|
||||
"build-css": "postcss src/styles/index.css -o dist/style.css",
|
||||
"watch-css": "postcss src/styles/index.css -o dist/style.css -w",
|
||||
"lint-css": "stylelint src/styles/*.css && stylelint src/styles/**/*.css",
|
||||
"lint": "npm run lint-js && npm run lint-css",
|
||||
"lint-prod": "npm run lint-js -- --quiet && npm run lint-css -- --quiet",
|
||||
"test-prod": "npm run test -- --reporter min"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.3",
|
||||
"@babel/preset-env": "^7.12.1",
|
||||
"@babel/preset-react": "^7.12.1",
|
||||
"@babel/register": "^7.12.1",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-plugin-module-resolver": "^4.0.0",
|
||||
"circular-dependency-plugin": "^5.2.0",
|
||||
"css-loader": "^5.1.0",
|
||||
"eslint": "^7.12.0",
|
||||
"eslint-plugin-react": "^7.21.5",
|
||||
"postcss": "^8.1.4",
|
||||
"postcss-cli": "^8.1.0",
|
||||
"postcss-csso": "^4.0.0",
|
||||
"postcss-easy-import": "^3.0.0",
|
||||
"postcss-loader": "^4.2.0",
|
||||
"stylelint": "^13.7.2",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
}
|
||||
}
|
|
@ -48,14 +48,15 @@ export default new class CustomCSS extends Builtin {
|
|||
|
||||
const commonjsLoader = window.require;
|
||||
delete window.module; // Make monaco think this isn't a local node script or else it freaks out
|
||||
DOMManager.linkStyle("monaco-style", "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.min.css", {documentHead: true});
|
||||
DOMManager.injectScript("monaco-script", "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/loader.min.js").then(() => {
|
||||
const amdLoader = window.require; // Grab Monaco's amd loader
|
||||
window.require = commonjsLoader; // Revert to commonjs
|
||||
amdLoader.config({paths: {vs: "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs"}});
|
||||
amdLoader(["vs/editor/editor.main"], () => {}); // exposes the monaco global
|
||||
});
|
||||
|
||||
DOMManager.linkStyle("monaco-style", "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.min.css", {documentHead: true});
|
||||
await DOMManager.injectScript("monaco-script", "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/loader.min.js");
|
||||
|
||||
const amdLoader = window.require; // Grab Monaco's amd loader
|
||||
window.require = commonjsLoader; // Revert to commonjs
|
||||
this.log(amdLoader, window.require);
|
||||
amdLoader.config({paths: {vs: "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs"}});
|
||||
amdLoader(["vs/editor/editor.main"], () => {}); // exposes the monaco global
|
||||
|
||||
Settings.registerPanel(this.id, Strings.Panels.customcss, {
|
||||
order: 2,
|
|
@ -0,0 +1,29 @@
|
|||
import Builtin from "../../structs/builtin";
|
||||
import Modals from "../../ui/modals";
|
||||
import {Strings, IPC} from "modules";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
export default new class ReactDevTools extends Builtin {
|
||||
get name() {return "ReactDevTools";}
|
||||
get category() {return "developer";}
|
||||
get id() {return "reactDevTools";}
|
||||
|
||||
async enabled() {
|
||||
this.showModal();
|
||||
}
|
||||
|
||||
async disabled() {
|
||||
this.showModal();
|
||||
}
|
||||
|
||||
showModal() {
|
||||
if (!this.initialized) return;
|
||||
Modals.showConfirmationModal(Strings.Modals.additionalInfo, Strings.Modals.restartPrompt, {
|
||||
confirmText: Strings.Modals.restartNow,
|
||||
cancelText: Strings.Modals.restartLater,
|
||||
onConfirm: () => IPC.relaunch()
|
||||
});
|
||||
}
|
||||
};
|
|
@ -10,10 +10,10 @@ export default new class PublicServers extends Builtin {
|
|||
get id() {return "publicServers";}
|
||||
|
||||
enabled() {
|
||||
const GuildList = WebpackModules.find(m => m.default && m.default.displayName == "NavigableGuilds");
|
||||
const GuildList = WebpackModules.find(m => m.type && m.type.displayName == "NavigableGuilds");
|
||||
const GuildListOld = WebpackModules.findByDisplayName("Guilds");
|
||||
if (!GuildList && !GuildListOld) this.warn("Can't find GuildList component");
|
||||
this.guildPatch = this.after(GuildList ? GuildList : GuildListOld.prototype, GuildList ? "default" : "render", this._appendButton);
|
||||
this.guildPatch = this.after(GuildList ? GuildList : GuildListOld.prototype, GuildList ? "type" : "render", this._appendButton);
|
||||
this._appendButton();
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import Builtin from "../structs/builtin";
|
||||
import Modals from "../ui/modals";
|
||||
import {DataStore, Strings, IPC} from "modules";
|
||||
|
||||
export default new class WindowPrefs extends Builtin {
|
||||
get name() {return "WindowPrefs";}
|
||||
get category() {return "window";}
|
||||
get id() {return "transparency";}
|
||||
|
||||
enabled() {
|
||||
this.showModal(Strings.WindowPrefs.enabledInfo);
|
||||
}
|
||||
|
||||
disabled() {
|
||||
this.showModal(Strings.WindowPrefs.disabledInfo);
|
||||
}
|
||||
|
||||
showModal(info) {
|
||||
if (!this.initialized) return;
|
||||
Modals.showConfirmationModal(Strings.Modals.additionalInfo, info, {
|
||||
confirmText: Strings.Modals.restartNow,
|
||||
cancelText: Strings.Modals.restartLater,
|
||||
onConfirm: () => IPC.relaunch()
|
||||
});
|
||||
}
|
||||
};
|
|
@ -279,11 +279,12 @@ export default {
|
|||
restartRequired: "Restart Required",
|
||||
restartNow: "Restart Now",
|
||||
restartLater: "Restart Later",
|
||||
additionalInfo: "Additional Info"
|
||||
additionalInfo: "Additional Info",
|
||||
restartPrompt: "In order to take effect, Discord needs to be restarted. Do you want to restart now?"
|
||||
},
|
||||
ReactDevTools: {
|
||||
notFound: "Extension Not Found",
|
||||
notFoundDetails: "Unable to find the React Developer Tools extension on your PC. Please install the extension on your local Chrome installation."
|
||||
notFoundDetails: "Unable to find the React Developer Tools extension on your PC. Please install the extension on your local Chrome installation."
|
||||
},
|
||||
Sorting: {
|
||||
sortBy: "Sort By",
|
|
@ -1,5 +1,5 @@
|
|||
import Utilities from "./utilities";
|
||||
import Logger from "./logger";
|
||||
import Logger from "common/logger";
|
||||
import Settings from "./settingsmanager";
|
||||
import Events from "./emitter";
|
||||
import DataStore from "./datastore";
|
||||
|
@ -16,7 +16,6 @@ const React = DiscordModules.React;
|
|||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const Module = require("module").Module;
|
||||
// Module.globalPaths.push(path.resolve(require("electron").remote.app.getAppPath(), "node_modules"));
|
||||
|
||||
const splitRegex = /[^\S\r\n]*?\r?(?:\r\n|\n)[^\S\r\n]*?\*[^\S\r\n]?/;
|
||||
const escapedAtRegex = /^\\@/;
|
|
@ -0,0 +1,116 @@
|
|||
import LocaleManager from "./localemanager";
|
||||
|
||||
import Logger from "common/logger";
|
||||
import {Config, Changelog} from "data";
|
||||
import DOMManager from "./dommanager";
|
||||
import PluginManager from "./pluginmanager";
|
||||
import ThemeManager from "./thememanager";
|
||||
import Settings from "./settingsmanager";
|
||||
import * as Builtins from "builtins";
|
||||
import Modals from "../ui/modals";
|
||||
import ReactComponents from "./reactcomponents";
|
||||
import DataStore from "./datastore";
|
||||
import DiscordModules from "./discordmodules";
|
||||
import ComponentPatcher from "./componentpatcher";
|
||||
import Strings from "./strings";
|
||||
import LoadingIcon from "../loadingicon";
|
||||
import Styles from "../styles/index.css";
|
||||
|
||||
const GuildClasses = DiscordModules.GuildClasses;
|
||||
|
||||
export default new class Core {
|
||||
async startup() {
|
||||
if (this.hasStarted) return;
|
||||
this.hasStarted = true;
|
||||
|
||||
// (() => {
|
||||
// const fs = require("fs");
|
||||
// fs.appendFileSync("Z:\\debug.log", "\n\n\n");
|
||||
// window.ocl = console.log;
|
||||
// console.log = (...args) => {
|
||||
// fs.appendFileSync("Z:\\debug.log", JSON.stringify(args) + "\n");
|
||||
// window.ocl(...args);
|
||||
// };
|
||||
// })();
|
||||
|
||||
Config.appPath = process.env.DISCORD_APP_PATH;
|
||||
Config.userData = process.env.DISCORD_USER_DATA;
|
||||
Config.dataPath = process.env.BETTERDISCORD_DATA_PATH;
|
||||
|
||||
// Load css early
|
||||
Logger.log("Startup", "Injecting BD Styles");
|
||||
DOMManager.injectStyle("bd-stylesheet", Styles.toString());
|
||||
|
||||
Logger.log("Startup", "Initializing DataStore");
|
||||
DataStore.initialize();
|
||||
|
||||
Logger.log("Startup", "Initializing LocaleManager");
|
||||
await LocaleManager.initialize();
|
||||
|
||||
Logger.log("Startup", "Performing incompatibility checks");
|
||||
if (Config.version < Config.minSupportedVersion) return Modals.alert(Strings.Startup.notSupported, Strings.Startup.versionMismatch.format({injector: Config.version, remote: Config.bdVersion}));
|
||||
if (window.ED) return Modals.alert(Strings.Startup.notSupported, Strings.Startup.incompatibleApp.format({app: "EnhancedDiscord"}));
|
||||
if (window.WebSocket && window.WebSocket.name && window.WebSocket.name.includes("Patched")) return Modals.alert(Strings.Startup.notSupported, Strings.Startup.incompatibleApp.format({app: "Powercord"}));
|
||||
|
||||
|
||||
Logger.log("Startup", "Initializing Settings");
|
||||
Settings.initialize();
|
||||
|
||||
Logger.log("Startup", "Initializing DOMManager");
|
||||
DOMManager.initialize();
|
||||
|
||||
Logger.log("Startup", "Waiting for guilds...");
|
||||
await this.waitForGuilds();
|
||||
|
||||
Logger.log("Startup", "Initializing ReactComponents");
|
||||
ReactComponents.initialize();
|
||||
|
||||
Logger.log("Startup", "Initializing ComponentPatcher");
|
||||
ComponentPatcher.initialize();
|
||||
|
||||
Logger.log("Startup", "Initializing Builtins");
|
||||
for (const module in Builtins) {
|
||||
if (module === "CustomCSS") await Builtins[module].initialize();
|
||||
else Builtins[module].initialize();
|
||||
}
|
||||
|
||||
Logger.log("Startup", "Loading Plugins");
|
||||
// const pluginErrors = [];
|
||||
const pluginErrors = PluginManager.initialize();
|
||||
|
||||
Logger.log("Startup", "Loading Themes");
|
||||
// const themeErrors = [];
|
||||
const themeErrors = ThemeManager.initialize();
|
||||
|
||||
Logger.log("Startup", "Removing Loading Icon");
|
||||
LoadingIcon.hide();
|
||||
|
||||
// Show loading errors
|
||||
Logger.log("Startup", "Collecting Startup Errors");
|
||||
Modals.showAddonErrors({plugins: pluginErrors, themes: themeErrors});
|
||||
|
||||
const previousVersion = DataStore.getBDData("version");
|
||||
if (Config.bdVersion > previousVersion) {
|
||||
Modals.showChangelogModal(Changelog);
|
||||
DataStore.setBDData("version", Config.bdVersion);
|
||||
}
|
||||
}
|
||||
|
||||
waitForGuilds() {
|
||||
let timesChecked = 0;
|
||||
return new Promise(resolve => {
|
||||
const checkForGuilds = function () {
|
||||
timesChecked++;
|
||||
if (document.readyState != "complete") setTimeout(checkForGuilds, 100);
|
||||
const wrapper = GuildClasses.wrapper.split(" ")[0];
|
||||
const guild = GuildClasses.listItem.split(" ")[0];
|
||||
const blob = GuildClasses.blobContainer.split(" ")[0];
|
||||
if (document.querySelectorAll(`.${wrapper} .${guild} .${blob}`).length > 0) return resolve(Config.deferLoaded = true);
|
||||
else if (timesChecked >= 50) return resolve(Config.deferLoaded = true);
|
||||
setTimeout(checkForGuilds, 100);
|
||||
};
|
||||
|
||||
checkForGuilds();
|
||||
});
|
||||
}
|
||||
};
|
|
@ -1,11 +1,14 @@
|
|||
import {Config} from "data";
|
||||
import Utilities from "./utilities";
|
||||
import Logger from "./logger";
|
||||
import Logger from "common/logger";
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const releaseChannel = window?.DiscordNative?.app?.getReleaseChannel?.() ?? "stable";
|
||||
const discordVersion = window?.DiscordNative?.remoteApp?.getVersion?.() ?? "0.0.309";
|
||||
|
||||
// const releaseChannel = "stable";
|
||||
// const discordVersion = "0.0.309";
|
||||
|
||||
// Schema
|
||||
// =======================
|
||||
// %appdata%\BetterDiscord
|
||||
|
@ -25,11 +28,14 @@ export default new class DataStore {
|
|||
initialize() {
|
||||
const newStorageExists = fs.existsSync(this.baseFolder);
|
||||
if (!newStorageExists) fs.mkdirSync(this.baseFolder);
|
||||
|
||||
if (!fs.existsSync(this.dataFolder)) fs.mkdirSync(this.dataFolder);
|
||||
if (!fs.existsSync(this.localeFolder)) fs.mkdirSync(this.localeFolder);
|
||||
if (!fs.existsSync(this.emoteFolder)) fs.mkdirSync(this.emoteFolder);
|
||||
|
||||
if (!fs.existsSync(this.cacheFile)) fs.writeFileSync(this.cacheFile, JSON.stringify({}));
|
||||
if (!fs.existsSync(this.customCSS)) fs.writeFileSync(this.customCSS, "");
|
||||
|
||||
const dataFiles = fs.readdirSync(this.dataFolder).filter(f => !fs.statSync(path.resolve(this.dataFolder, f)).isDirectory() && f.endsWith(".json"));
|
||||
for (const file of dataFiles) {
|
||||
this.data[file.split(".")[0]] = __non_webpack_require__(path.resolve(this.dataFolder, file));
|
|
@ -6,18 +6,18 @@ export default class DOMManager {
|
|||
static get bdStyles() {return this.getElement("bd-styles");}
|
||||
static get bdThemes() {return this.getElement("bd-themes");}
|
||||
static get bdCustomCSS() {return this.getElement("#customcss");}
|
||||
// static get bdTooltips() { return this.getElement("bd-tooltips") || this.createElement("bd-tooltips").appendTo(this.bdBody); }
|
||||
// static get bdModals() { return this.getElement("bd-modals") || this.createElement("bd-modals").appendTo(this.bdBody); }
|
||||
// static get bdToasts() { return this.getElement("bd-toasts") || this.createElement("bd-toasts").appendTo(this.bdBody); }
|
||||
static get bdTooltips() {return this.getElement("bd-tooltips") || this.createElement("bd-tooltips").appendTo(this.bdBody);}
|
||||
static get bdModals() {return this.getElement("bd-modals") || this.createElement("bd-modals").appendTo(this.bdBody);}
|
||||
static get bdToasts() {return this.getElement("bd-toasts") || this.createElement("bd-toasts").appendTo(this.bdBody);}
|
||||
|
||||
// static initialize() {
|
||||
// this.createElement("bd-head", {target: document.head});
|
||||
// this.createElement("bd-body", {target: document.body});
|
||||
// this.createElement("bd-scripts", {target: this.bdHead});
|
||||
// this.createElement("bd-styles", {target: this.bdHead});
|
||||
// this.createElement("bd-themes", {target: this.bdHead});
|
||||
// this.createElement("style", {id: "customcss", target: this.bdHead});
|
||||
// }
|
||||
static initialize() {
|
||||
// this.createElement("bd-head", {target: document.head});
|
||||
// this.createElement("bd-body", {target: document.body});
|
||||
// this.createElement("bd-scripts", {target: this.bdHead});
|
||||
// this.createElement("bd-styles", {target: this.bdHead});
|
||||
// this.createElement("bd-themes", {target: this.bdHead});
|
||||
// this.createElement("style", {id: "customcss", target: this.bdHead});
|
||||
}
|
||||
|
||||
static escapeID(id) {
|
||||
return id.replace(/^[^a-z]+|[^\w-]+/gi, "-");
|
|
@ -1,9 +1,11 @@
|
|||
const EventEmitter = require("events");
|
||||
|
||||
export default new class BDEvents extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.setMaxListeners(20);
|
||||
}
|
||||
|
||||
dispatch(eventName, ...args) {
|
||||
this.emit(eventName, ...args);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import {ipcRenderer as ipc} from "electron";
|
||||
|
||||
import Events from "./emitter";
|
||||
|
||||
import * as IPCEvents from "common/constants/ipcevents";
|
||||
|
||||
export default new class IPCRenderer {
|
||||
|
||||
constructor() {
|
||||
ipc.on(IPCEvents.NAVIGATE, () => Events.dispatch("navigate"));
|
||||
ipc.on(IPCEvents.MAXIMIZE, () => Events.dispatch("maximize"));
|
||||
ipc.on(IPCEvents.MINIMIZE, () => Events.dispatch("minimize"));
|
||||
}
|
||||
|
||||
openDevTools() {
|
||||
return ipc.send(IPCEvents.OPEN_DEVTOOLS);
|
||||
}
|
||||
|
||||
closeDevTools() {
|
||||
return ipc.send(IPCEvents.CLOSE_DEVTOOLS);
|
||||
}
|
||||
|
||||
relaunch() {
|
||||
return ipc.send(IPCEvents.RELAUNCH);
|
||||
}
|
||||
|
||||
runScript(script) {
|
||||
return ipc.invoke(IPCEvents.RUN_SCRIPT, script);
|
||||
}
|
||||
|
||||
openWindow(url, options) {
|
||||
return ipc.invoke(IPCEvents.OPEN_WINDOW, url, options);
|
||||
}
|
||||
};
|
|
@ -11,8 +11,9 @@ export {default as Events} from "./emitter";
|
|||
export {default as Settings} from "./settingsmanager";
|
||||
export {default as DOMManager} from "./dommanager";
|
||||
export {default as DOM} from "./domtools";
|
||||
export {default as Logger} from "./logger";
|
||||
export {default as Patcher} from "./patcher";
|
||||
export {default as ReactComponents} from "./reactcomponents";
|
||||
export {default as LocaleManager} from "./localemanager";
|
||||
export {default as Strings} from "./strings";
|
||||
export {default as Strings} from "./strings";
|
||||
export {default as IPC} from "./ipc";
|
||||
export {default as Logger} from "common/logger";
|
|
@ -8,7 +8,7 @@
|
|||
* @version 0.0.2
|
||||
*/
|
||||
|
||||
import Logger from "./logger";
|
||||
import Logger from "common/logger";
|
||||
import DiscordModules from "./discordmodules";
|
||||
import WebpackModules from "./webpackmodules";
|
||||
|
|
@ -9,7 +9,7 @@ import Modals from "../ui/modals";
|
|||
import PluginManager from "./pluginmanager";
|
||||
import ThemeManager from "./thememanager";
|
||||
import Settings from "./settingsmanager";
|
||||
import Logger from "./logger";
|
||||
import Logger from "common/logger";
|
||||
import Patcher from "./patcher";
|
||||
import Emotes from "../builtins/emotes/emotes";
|
||||
|
||||
|
@ -35,17 +35,20 @@ const BdApi = {
|
|||
};
|
||||
|
||||
BdApi.getAllWindowPreferences = function() {
|
||||
return DataStore.getData("windowprefs") || {};
|
||||
// return DataStore.getData("windowprefs") || {};
|
||||
// TODO: mark deprecated
|
||||
};
|
||||
|
||||
BdApi.getWindowPreference = function(key) {
|
||||
return this.getAllWindowPreferences()[key];
|
||||
// return this.getAllWindowPreferences()[key];
|
||||
// TODO: mark deprecated
|
||||
};
|
||||
|
||||
BdApi.setWindowPreference = function(key, value) {
|
||||
const prefs = this.getAllWindowPreferences();
|
||||
prefs[key] = value;
|
||||
return DataStore.setData("windowprefs", prefs);
|
||||
// const prefs = this.getAllWindowPreferences();
|
||||
// prefs[key] = value;
|
||||
// return DataStore.setData("windowprefs", prefs);
|
||||
// TODO: mark deprecated
|
||||
};
|
||||
|
||||
// Inject CSS to document head
|
|
@ -1,9 +1,11 @@
|
|||
import {Config} from "data";
|
||||
import Logger from "./logger";
|
||||
import Logger from "common/logger";
|
||||
import AddonManager from "./addonmanager";
|
||||
import AddonError from "../structs/addonerror";
|
||||
import Settings from "./settingsmanager";
|
||||
import Strings from "./strings";
|
||||
import IPC from "./ipc";
|
||||
import Events from "./emitter";
|
||||
|
||||
import Toasts from "../ui/toasts";
|
||||
import Modals from "../ui/modals";
|
||||
|
@ -11,7 +13,6 @@ import SettingsRenderer from "../ui/settings";
|
|||
|
||||
const path = require("path");
|
||||
const electron = require("electron");
|
||||
const ipc = electron.ipcRenderer;
|
||||
const vm = require("vm");
|
||||
// const electronRemote = require("electron").remote;
|
||||
|
||||
|
@ -105,10 +106,10 @@ export default new class PluginManager extends AddonManager {
|
|||
window.module = module;
|
||||
window.__filename = path.basename(module.filename);
|
||||
window.__dirname = this.addonFolder;
|
||||
const wrapped = `(${vm.compileFunction(fileContent, ["exports", "require", "module", "__filename", "__dirname"])})`;
|
||||
const wrapped = `(${vm.compileFunction(fileContent, ["exports", "require", "module", "__filename", "__dirname"]).toString()})`;
|
||||
// console.log(module);
|
||||
module.exports = new Promise(resolve => {
|
||||
ipc.invoke("EXEC_JS", `${wrapped}(window.module.exports, window.require, window.module, window.__filename, window.__dirname)`).then(() => {
|
||||
IPC.runScript(`${wrapped}(window.module.exports, window.require, window.module, window.__filename, window.__dirname)`).then(() => {
|
||||
// console.log(window.module);
|
||||
meta.exports = module.exports;
|
||||
module.exports = meta;
|
||||
|
@ -170,7 +171,8 @@ export default new class PluginManager extends AddonManager {
|
|||
|
||||
setupFunctions() {
|
||||
// electronRemote.getCurrentWebContents().on("did-navigate-in-page", this.onSwitch.bind(this));
|
||||
ipc.on("DID_NAVIGATE_IN_PAGE", this.onSwitch);
|
||||
Events.on("navigate", this.onSwitch);
|
||||
// ipc.on(IPCEvents.NAVIGATE, this.onSwitch);
|
||||
this.observer.observe(document, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
|
@ -178,7 +180,6 @@ export default new class PluginManager extends AddonManager {
|
|||
}
|
||||
|
||||
onSwitch() {
|
||||
this.emit("page-switch");
|
||||
for (let i = 0; i < this.addonList.length; i++) {
|
||||
const plugin = this.addonList[i].instance;
|
||||
if (!this.state[this.addonList[i].id]) continue;
|
|
@ -1,5 +1,5 @@
|
|||
import {SettingsConfig} from "data";
|
||||
import Logger from "./logger";
|
||||
import Logger from "common/logger";
|
||||
import DataStore from "./datastore";
|
||||
import Events from "./emitter";
|
||||
import DiscordModules from "./discordmodules";
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import PluginUtilities from "./pluginutilities";
|
||||
import DOMTools from "./domtools";
|
||||
import Logger from "./logger";
|
||||
import Logger from "common/logger";
|
||||
import DiscordClasses from "./discordclasses";
|
||||
import {EmulatedTooltip, Toasts} from "ui";
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import {Config} from "data";
|
||||
import Logger from "./logger";
|
||||
import Logger from "common/logger";
|
||||
import DOM from "./domtools";
|
||||
|
||||
export default class Utilities {
|
|
@ -1,4 +1,4 @@
|
|||
import Logger from "../modules/logger";
|
||||
import Logger from "common/logger";
|
||||
import Events from "../modules/emitter";
|
||||
import Settings from "../modules/settingsmanager";
|
||||
import Patcher from "../modules/patcher";
|
|
@ -1,4 +1,5 @@
|
|||
import {Logger, WebpackModules} from "modules";
|
||||
import Logger from "common/logger";
|
||||
import {WebpackModules, IPC} from "modules";
|
||||
|
||||
const SortedGuildStore = WebpackModules.getByProps("getSortedGuilds");
|
||||
const AvatarDefaults = WebpackModules.getByProps("getUserAvatarURL", "DEFAULT_AVATARS");
|
||||
|
@ -12,7 +13,7 @@ const betterDiscordServer = {
|
|||
categories: ["community", "programming", "support"],
|
||||
description: "Official BetterDiscord server for plugins, themes, support, etc",
|
||||
identifier: "86004744966914048",
|
||||
iconUrl: "https://cdn.discordapp.com/icons/86004744966914048/292e7f6bfff2b71dfd13e508a859aedd.webp",
|
||||
iconUrl: "https://cdn.discordapp.com/icons/86004744966914048/babd1af3fa6011a50e418a80f4970ceb.webp",
|
||||
nativejoin: true,
|
||||
invite_code: "BJD2yvJ",
|
||||
pinned: true,
|
||||
|
@ -29,13 +30,12 @@ export default new class PublicServersConnection {
|
|||
this.cache.set("popular", []);
|
||||
this.cache.set("keywords", []);
|
||||
this.cache.set("accessToken", "");
|
||||
|
||||
window.debugPS = this;
|
||||
}
|
||||
|
||||
get endPoint() {return "https://search.discordservers.com";}
|
||||
get joinEndPoint() {return "https://j.discordservers.com";}
|
||||
get connectEndPoint() {return "https://auth.discordservers.com/info";}
|
||||
get authorizeEndPoint() {return `https://auth.discordservers.com/connect?scopes=guilds.join&previousUrl=${this.connectEndPoint}`;}
|
||||
|
||||
getDefaultAvatar() {
|
||||
return AvatarDefaults.DEFAULT_AVATARS[Math.floor(Math.random() * 5)];
|
||||
|
@ -139,7 +139,7 @@ export default new class PublicServersConnection {
|
|||
}
|
||||
}
|
||||
|
||||
connect() {
|
||||
async connect() {
|
||||
// return new Promise(resolve => {
|
||||
// const joinWindow = new BrowserWindow(this.windowOptions);
|
||||
// const url = `https://auth.discordservers.com/connect?scopes=guilds.join&previousUrl=${this.connectEndPoint}`;
|
||||
|
@ -150,12 +150,16 @@ export default new class PublicServersConnection {
|
|||
// });
|
||||
// joinWindow.loadURL(url);
|
||||
// });
|
||||
await IPC.openWindow(this.authorizeEndPoint, {
|
||||
windowOptions: this.windowOptions,
|
||||
closeOnUrl: this.connectEndPoint
|
||||
});
|
||||
}
|
||||
|
||||
get windowOptions() {
|
||||
return {
|
||||
width: 490,
|
||||
height: 500,
|
||||
width: 520,
|
||||
height: 580,
|
||||
backgroundColor: "#282b30",
|
||||
show: true,
|
||||
resizable: true,
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue