Add a few small features
- Fixes colored text - Fixes detach window not showing saved css (closes #635) - Adds option to prevent Discord from hijacking the media keys (closes #410) - Adds command line flag to launch a vanilla version of Discord `--vanilla` (closes #337) - Adds option for app-wide ctrl+shift+c shortcut for inspect element (closes #349) - Adds emote blocklist to BdApi via `BdApi.Emotes.blocklist` (closes #408)
This commit is contained in:
parent
59d9ec3dea
commit
a223806060
|
@ -8,4 +8,5 @@ export const RUN_SCRIPT = "bd-run-script";
|
||||||
export const NAVIGATE = "bd-did-navigate-in-page";
|
export const NAVIGATE = "bd-did-navigate-in-page";
|
||||||
export const OPEN_DEVTOOLS = "bd-open-devtools";
|
export const OPEN_DEVTOOLS = "bd-open-devtools";
|
||||||
export const CLOSE_DEVTOOLS = "bd-close-devtools";
|
export const CLOSE_DEVTOOLS = "bd-close-devtools";
|
||||||
export const OPEN_WINDOW = "bd-open-window";
|
export const OPEN_WINDOW = "bd-open-window";
|
||||||
|
export const INSPECT_ELEMENT = "bd-inspect-element";
|
|
@ -1,34 +1,35 @@
|
||||||
const path = require("path");
|
import path from "path";
|
||||||
const electron = require("electron");
|
import {app} from "electron";
|
||||||
const Module = require("module");
|
import Module from "module";
|
||||||
|
|
||||||
import ipc from "./modules/ipc";
|
import ipc from "./modules/ipc";
|
||||||
import BrowserWindow from "./modules/browserwindow";
|
import BrowserWindow from "./modules/browserwindow";
|
||||||
import CSP from "./modules/csp";
|
import CSP from "./modules/csp";
|
||||||
|
|
||||||
|
if (!process.argv.includes("--vanilla")) {
|
||||||
process.env.NODE_OPTIONS = "--no-force-async-hooks-checks";
|
process.env.NODE_OPTIONS = "--no-force-async-hooks-checks";
|
||||||
electron.app.commandLine.appendSwitch("no-force-async-hooks-checks");
|
app.commandLine.appendSwitch("no-force-async-hooks-checks");
|
||||||
process.electronBinding("command_line").appendSwitch("no-force-async-hooks-checks");
|
process.electronBinding("command_line").appendSwitch("no-force-async-hooks-checks");
|
||||||
|
|
||||||
|
|
||||||
// Patch and replace the built-in BrowserWindow
|
// Patch and replace the built-in BrowserWindow
|
||||||
BrowserWindow.patchBrowserWindow();
|
BrowserWindow.patchBrowserWindow();
|
||||||
|
|
||||||
// Register all IPC events
|
// Register all IPC events
|
||||||
ipc.registerEvents();
|
ipc.registerEvents();
|
||||||
|
|
||||||
|
|
||||||
// Remove CSP immediately on linux since they install to discord_desktop_core still
|
// 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);
|
if (process.platform == "win32" || process.platform == "darwin") app.once("ready", CSP.remove);
|
||||||
else CSP.remove();
|
else CSP.remove();
|
||||||
|
}
|
||||||
|
|
||||||
// Use Discord's info to run the app
|
// Use Discord's info to run the app
|
||||||
if (process.platform == "win32" || process.platform == "darwin") {
|
if (process.platform == "win32" || process.platform == "darwin") {
|
||||||
const basePath = path.join(electron.app.getAppPath(), "..", "app.asar");
|
const basePath = path.join(app.getAppPath(), "..", "app.asar");
|
||||||
const pkg = __non_webpack_require__(path.join(basePath, "package.json"));
|
const pkg = __non_webpack_require__(path.join(basePath, "package.json"));
|
||||||
electron.app.setAppPath(basePath);
|
app.setAppPath(basePath);
|
||||||
electron.app.name = pkg.name;
|
app.name = pkg.name;
|
||||||
Module._load(path.join(basePath, pkg.main), null, true);
|
Module._load(path.join(basePath, pkg.main), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const fs = require("fs");
|
import fs from "fs";
|
||||||
const path = require("path");
|
import path from "path";
|
||||||
const electron = require("electron");
|
import electron from "electron";
|
||||||
|
|
||||||
import ReactDevTools from "./reactdevtools";
|
import ReactDevTools from "./reactdevtools";
|
||||||
import * as IPCEvents from "common/constants/ipcevents";
|
import * as IPCEvents from "common/constants/ipcevents";
|
||||||
|
@ -21,8 +21,12 @@ electron.app.once("ready", async () => {
|
||||||
await ReactDevTools.install();
|
await ReactDevTools.install();
|
||||||
});
|
});
|
||||||
|
|
||||||
let hasCrashed = false;
|
|
||||||
|
|
||||||
|
if (BetterDiscord.getSetting("general", "mediaKeys")) {
|
||||||
|
electron.app.commandLine.appendSwitch("disable-features", "HardwareMediaKeyHandling,MediaSessionService");
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasCrashed = false;
|
||||||
export default class BetterDiscord {
|
export default class BetterDiscord {
|
||||||
static getWindowPrefs() {
|
static getWindowPrefs() {
|
||||||
if (!fs.existsSync(buildInfoFile)) return {};
|
if (!fs.existsSync(buildInfoFile)) return {};
|
||||||
|
@ -37,7 +41,7 @@ export default class BetterDiscord {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const buildInfo = __non_webpack_require__(buildInfoFile);
|
const buildInfo = __non_webpack_require__(buildInfoFile);
|
||||||
const settingsFile = path.resolve(dataPath, "data", buildInfo.releaseChannel, "settings.json");
|
const settingsFile = path.resolve(dataPath, "data", buildInfo.releaseChannel, "settings.json");
|
||||||
this._settings = __non_webpack_require__(settingsFile) ?? {};
|
this._settings = __non_webpack_require__(settingsFile) ?? {};
|
||||||
return this._settings[category]?.[key];
|
return this._settings[category]?.[key];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const electron = require("electron");
|
import electron from "electron";
|
||||||
const path = require("path");
|
import path from "path";
|
||||||
|
|
||||||
import BetterDiscord from "./betterdiscord";
|
import BetterDiscord from "./betterdiscord";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const electron = require("electron");
|
import electron from "electron";
|
||||||
|
|
||||||
export default class {
|
export default class {
|
||||||
static remove() {
|
static remove() {
|
||||||
|
|
|
@ -8,20 +8,20 @@ const getPath = (event, pathReq) => {
|
||||||
case "appPath":
|
case "appPath":
|
||||||
returnPath = app.getAppPath();
|
returnPath = app.getAppPath();
|
||||||
break;
|
break;
|
||||||
case "appData":
|
case "appData":
|
||||||
case "userData":
|
case "userData":
|
||||||
case "home":
|
case "home":
|
||||||
case "cache":
|
case "cache":
|
||||||
case "temp":
|
case "temp":
|
||||||
case "exe":
|
case "exe":
|
||||||
case "module":
|
case "module":
|
||||||
case "desktop":
|
case "desktop":
|
||||||
case "documents":
|
case "documents":
|
||||||
case "downloads":
|
case "downloads":
|
||||||
case "music":
|
case "music":
|
||||||
case "pictures":
|
case "pictures":
|
||||||
case "videos":
|
case "videos":
|
||||||
case "recent":
|
case "recent":
|
||||||
case "logs":
|
case "logs":
|
||||||
returnPath = app.getPath(pathReq);
|
returnPath = app.getPath(pathReq);
|
||||||
break;
|
break;
|
||||||
|
@ -62,12 +62,21 @@ const createBrowserWindow = async (event, url, {windowOptions, closeOnUrl} = {})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const inspectElement = async event => {
|
||||||
|
if (!event.sender.isDevToolsOpened()) {
|
||||||
|
event.sender.openDevTools();
|
||||||
|
while (!event.sender.isDevToolsOpened()) await new Promise(r => setTimeout(r, 100));
|
||||||
|
}
|
||||||
|
event.sender.devToolsWebContents.executeJavaScript("DevToolsAPI.enterInspectElementMode();");
|
||||||
|
};
|
||||||
|
|
||||||
export default class IPCMain {
|
export default class IPCMain {
|
||||||
static registerEvents() {
|
static registerEvents() {
|
||||||
ipc.on(IPCEvents.GET_PATH, getPath);
|
ipc.on(IPCEvents.GET_PATH, getPath);
|
||||||
ipc.on(IPCEvents.RELAUNCH, relaunch);
|
ipc.on(IPCEvents.RELAUNCH, relaunch);
|
||||||
ipc.on(IPCEvents.OPEN_DEVTOOLS, openDevTools);
|
ipc.on(IPCEvents.OPEN_DEVTOOLS, openDevTools);
|
||||||
ipc.on(IPCEvents.CLOSE_DEVTOOLS, closeDevTools);
|
ipc.on(IPCEvents.CLOSE_DEVTOOLS, closeDevTools);
|
||||||
|
ipc.on(IPCEvents.INSPECT_ELEMENT, inspectElement);
|
||||||
ipc.handle(IPCEvents.RUN_SCRIPT, runScript);
|
ipc.handle(IPCEvents.RUN_SCRIPT, runScript);
|
||||||
ipc.handle(IPCEvents.OPEN_WINDOW, createBrowserWindow);
|
ipc.handle(IPCEvents.OPEN_WINDOW, createBrowserWindow);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6174,9 +6174,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"y18n": {
|
"y18n": {
|
||||||
"version": "5.0.4",
|
"version": "5.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
|
||||||
"integrity": "sha512-deLOfD+RvFgrpAmSZgfGdWYE+OKyHcVHaRQ7NphG/63scpRvTHHeQMAxGGvaLVGJ+HYVcCXlzcTK0ZehFf+eHQ==",
|
"integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"yargs": {
|
"yargs": {
|
||||||
|
@ -8812,8 +8812,7 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"readdirp": {
|
"readdirp": {
|
||||||
"version": "3.4.0",
|
"version": "3.4.0",
|
||||||
|
|
|
@ -18,24 +18,10 @@ export default new class ColoredText extends Builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
injectColoredText() {
|
injectColoredText() {
|
||||||
const MessageContent = WebpackModules.getModule(m => m.default && m.default.displayName && m.default.displayName == "Message");
|
const MessageContent = WebpackModules.getModule(m => m.type && m.type.displayName === "MessageContent");
|
||||||
this.before(MessageContent, "default", (thisObject, [props]) => {
|
this.after(MessageContent, "type", (thisObject, [props], returnValue) => {
|
||||||
if (!props || !props.childrenMessageContent) return;
|
const roleColor = this.getRoleColor(props.message.channel_id, props.message.author.id) || "";
|
||||||
const messageContent = props.childrenMessageContent;
|
returnValue.props.style = {color: roleColor};
|
||||||
if (!messageContent.type || !messageContent.type.type || messageContent.type.type.displayName != "MessageContent") return;
|
|
||||||
|
|
||||||
const originalType = messageContent.type.type;
|
|
||||||
if (originalType.__originalMethod) return; // Don't patch again
|
|
||||||
const self = this;
|
|
||||||
messageContent.type.type = function (childProps) {
|
|
||||||
const returnValue = originalType(childProps);
|
|
||||||
const roleColor = self.getRoleColor(childProps.message.channel_id, childProps.message.author.id) || "";
|
|
||||||
returnValue.props.style = {color: roleColor};
|
|
||||||
return returnValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
messageContent.type.type.__originalMethod = originalType;
|
|
||||||
Object.assign(messageContent.type.type, originalType);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ export {default as WindowPrefs} from "./windowprefs";
|
||||||
export {default as ClassNormalizer} from "./general/classnormalizer";
|
export {default as ClassNormalizer} from "./general/classnormalizer";
|
||||||
export {default as PublicServers} from "./general/publicservers";
|
export {default as PublicServers} from "./general/publicservers";
|
||||||
export {default as VoiceDisconnect} from "./general/voicedisconnect";
|
export {default as VoiceDisconnect} from "./general/voicedisconnect";
|
||||||
|
export {default as MediaKeys} from "./general/mediakeys";
|
||||||
|
|
||||||
export {default as TwentyFourHour} from "./appearance/24hour";
|
export {default as TwentyFourHour} from "./appearance/24hour";
|
||||||
export {default as ColoredText} from "./appearance/coloredtext";
|
export {default as ColoredText} from "./appearance/coloredtext";
|
||||||
|
@ -18,4 +19,5 @@ export {default as EmoteMenu} from "./emotes/emotemenu";
|
||||||
// export {default as EmoteAutocaps} from "./emotes/emoteautocaps";
|
// export {default as EmoteAutocaps} from "./emotes/emoteautocaps";
|
||||||
|
|
||||||
export {default as Debugger} from "./developer/debugger";
|
export {default as Debugger} from "./developer/debugger";
|
||||||
export {default as ReactDevTools} from "./developer/reactdevtools";
|
export {default as ReactDevTools} from "./developer/reactdevtools";
|
||||||
|
export {default as InspectElement} from "./developer/inspectelement";
|
|
@ -71,7 +71,7 @@ export default new class CustomCSS extends Builtin {
|
||||||
onClick: (thisObject) => {
|
onClick: (thisObject) => {
|
||||||
if (this.isDetached) return;
|
if (this.isDetached) return;
|
||||||
if (this.nativeOpen) return this.openNative();
|
if (this.nativeOpen) return this.openNative();
|
||||||
else if (this.startDetached) return this.openDetached();
|
else if (this.startDetached) return this.openDetached(this.savedCss);
|
||||||
const settingsView = Utilities.findInRenderTree(thisObject._reactInternalFiber, m => m && m.onSetSection, {walkable: ["child", "memoizedProps", "props", "children"]});
|
const settingsView = Utilities.findInRenderTree(thisObject._reactInternalFiber, m => m && m.onSetSection, {walkable: ["child", "memoizedProps", "props", "children"]});
|
||||||
if (settingsView && settingsView.onSetSection) settingsView.onSetSection(this.id);
|
if (settingsView && settingsView.onSetSection) settingsView.onSetSection(this.id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import Builtin from "../../structs/builtin";
|
||||||
|
import IPC from "../../modules/ipc";
|
||||||
|
|
||||||
|
export default new class InspectElement extends Builtin {
|
||||||
|
get name() {return "InspectElementHotkey";}
|
||||||
|
get category() {return "developer";}
|
||||||
|
get id() {return "inspectElement";}
|
||||||
|
|
||||||
|
enabled() {
|
||||||
|
document.addEventListener("keydown", this.inspectElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
disabled() {
|
||||||
|
document.removeEventListener("keydown", this.inspectElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
inspectElement(e) {
|
||||||
|
if (e.ctrlKey && e.shiftKey && e.which === 67) { // Ctrl + Shift + C
|
||||||
|
IPC.inspectElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -37,7 +37,7 @@ export default new class EmoteModule extends Builtin {
|
||||||
|
|
||||||
get(id) {return super.get("emotes", "general", id);}
|
get(id) {return super.get("emotes", "general", id);}
|
||||||
|
|
||||||
get MessageComponent() {return WebpackModules.find(m => m.default && m.default.displayName && m.default.displayName == "Message");}
|
get MessageComponent() {return WebpackModules.find(m => m.default && m.default.toString().search("childrenRepliedMessage") > -1);}
|
||||||
|
|
||||||
get Emotes() {return Emotes;}
|
get Emotes() {return Emotes;}
|
||||||
get TwitchGlobal() {return Emotes.TwitchGlobal;}
|
get TwitchGlobal() {return Emotes.TwitchGlobal;}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import Builtin from "../../structs/builtin";
|
||||||
|
import Modals from "../../ui/modals";
|
||||||
|
import {Strings, IPC} from "modules";
|
||||||
|
|
||||||
|
export default new class MediaKeys extends Builtin {
|
||||||
|
get name() {return "DisableMediaKeys";}
|
||||||
|
get category() {return "general";}
|
||||||
|
get id() {return "mediaKeys";}
|
||||||
|
|
||||||
|
enabled() {
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
disabled() {
|
||||||
|
this.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
showModal() {
|
||||||
|
if (!this.initialized) return;
|
||||||
|
Modals.showConfirmationModal(Strings.Modals.additionalInfo, Strings.Modals.restartPrompt, {
|
||||||
|
confirmText: Strings.Modals.restartNow,
|
||||||
|
cancelText: Strings.Modals.restartLater,
|
||||||
|
danger: true,
|
||||||
|
onConfirm: () => IPC.relaunch()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
import Builtin from "../structs/builtin";
|
import Builtin from "../structs/builtin";
|
||||||
import Modals from "../ui/modals";
|
import Modals from "../ui/modals";
|
||||||
import {DataStore, Strings, IPC} from "modules";
|
import {Strings, IPC} from "modules";
|
||||||
|
|
||||||
export default new class WindowPrefs extends Builtin {
|
export default new class WindowPrefs extends Builtin {
|
||||||
get name() {return "WindowPrefs";}
|
get name() {return "WindowPrefs";}
|
||||||
|
|
|
@ -8,7 +8,8 @@ export default [
|
||||||
{type: "switch", id: "publicServers", value: true},
|
{type: "switch", id: "publicServers", value: true},
|
||||||
{type: "switch", id: "voiceDisconnect", value: false},
|
{type: "switch", id: "voiceDisconnect", value: false},
|
||||||
{type: "switch", id: "classNormalizer", value: false},
|
{type: "switch", id: "classNormalizer", value: false},
|
||||||
{type: "switch", id: "showToasts", value: true}
|
{type: "switch", id: "showToasts", value: true},
|
||||||
|
{type: "switch", id: "mediaKeys", value: false}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -52,7 +53,8 @@ export default [
|
||||||
shown: false,
|
shown: false,
|
||||||
settings: [
|
settings: [
|
||||||
{type: "switch", id: "debuggerHotkey", value: false},
|
{type: "switch", id: "debuggerHotkey", value: false},
|
||||||
{type: "switch", id: "reactDevTools", value: false}
|
{type: "switch", id: "reactDevTools", value: false},
|
||||||
|
{type: "switch", id: "inspectElement", value: false}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -109,6 +109,10 @@ export default {
|
||||||
reactDevTools: {
|
reactDevTools: {
|
||||||
name: "React Developer Tools",
|
name: "React Developer Tools",
|
||||||
note: "Injects your local installation of React Developer Tools into Discord"
|
note: "Injects your local installation of React Developer Tools into Discord"
|
||||||
|
},
|
||||||
|
inspectElement: {
|
||||||
|
name: "Inspect Element Hotkey",
|
||||||
|
note: "Enables the inspect element hotkey (ctrl + shift + c) that is common in most browsers"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
window: {
|
window: {
|
||||||
|
@ -150,6 +154,10 @@ export default {
|
||||||
animateOnHover: {
|
animateOnHover: {
|
||||||
name: "Animate On Hover",
|
name: "Animate On Hover",
|
||||||
note: "Only animate the emote modifiers on hover"
|
note: "Only animate the emote modifiers on hover"
|
||||||
|
},
|
||||||
|
mediaKeys: {
|
||||||
|
name: "Disable Media Keys",
|
||||||
|
note: "Prevents Discord from hijacking your media keys after playing a video."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
categories: {
|
categories: {
|
||||||
|
@ -269,7 +277,7 @@ export default {
|
||||||
},
|
},
|
||||||
ReactDevTools: {
|
ReactDevTools: {
|
||||||
notFound: "Extension Not Found",
|
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: {
|
Sorting: {
|
||||||
sortBy: "Sort By",
|
sortBy: "Sort By",
|
||||||
|
|
|
@ -31,4 +31,8 @@ export default new class IPCRenderer {
|
||||||
openWindow(url, options) {
|
openWindow(url, options) {
|
||||||
return ipc.invoke(IPCEvents.OPEN_WINDOW, url, options);
|
return ipc.invoke(IPCEvents.OPEN_WINDOW, url, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inspectElement() {
|
||||||
|
ipc.send(IPCEvents.INSPECT_ELEMENT);
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -21,6 +21,7 @@ const BdApi = {
|
||||||
get emotes() {
|
get emotes() {
|
||||||
return new Proxy(Emotes.Emotes, {
|
return new Proxy(Emotes.Emotes, {
|
||||||
get(category) {
|
get(category) {
|
||||||
|
if (category === "blocklist") return Emotes.blocklist;
|
||||||
const group = Emotes.Emotes[category];
|
const group = Emotes.Emotes[category];
|
||||||
if (!group) return undefined;
|
if (!group) return undefined;
|
||||||
return new Proxy(group, {
|
return new Proxy(group, {
|
||||||
|
|
Loading…
Reference in New Issue