Merge branch 'BetterDiscord:main' into main

This commit is contained in:
TheGreenPig 2022-06-26 19:00:06 +02:00 committed by GitHub
commit e81c515d9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 15432 additions and 5531 deletions

View File

@ -17,12 +17,10 @@
"curly": ["error", "multi-line", "consistent"],
"dot-location": ["error", "property"],
"dot-notation": "error",
// "eqeqeq": ["error", "smart"],
"func-call-spacing": "error",
"handle-callback-err": "error",
"key-spacing": "error",
"keyword-spacing": "error",
"linebreak-style": ["error", "windows"],
"new-cap": ["error", {"newIsCap": true}],
"no-array-constructor": "error",
"no-caller": "error",
@ -54,7 +52,6 @@
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-throw-literal": "error",
// "no-trailing-spaces": "error",
"no-undef": "error",
"no-undef-init": "error",
"no-unmodified-loop-condition": "error",

View File

@ -2,6 +2,28 @@
This changelog starts with the restructured 1.0.0 release that happened after context isolation changes. The changelogs here should more-or-less mirror the ones that get shown in the client but probably with less formatting and pizzazz.
## 1.5.3
### Added
### Removed
### Changed
### Fixed
- Fixed Canary crashing immediately
## 1.5.2
### Added
### Removed
### Changed
### Fixed
- Fixed being unable to inject into settings, thanks @Strencher
## 1.5.1
### Added

View File

@ -1,4 +1,4 @@
Copyright © 2019-2020, Zack Rauen
Copyright © 2019-2022, BetterDiscord Team
All rights reserved. Code may not be modified and redistributed, or otherwise
used for derivative works and redistributed without explicit permission.

View File

@ -1,46 +1,84 @@
# BetterDiscord [![Language Grade][lgtm-badge]][lgtm-link] ![GitHub Releases][downloads-badge]
# BetterDiscord [![Language Grade][lgtm-badge]][lgtm-link] [![GitHub Releases][downloads-badge]][downloads-link] [![Discord][discord-badge]][discord-link]
[patreon-badge]: https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3DZerebos%26type%3Dpatrons&style=flat-square
[patreon-link]: https://patreon.com/Zerebos
[paypal-badge]: https://img.shields.io/badge/Paypal-Donate!-%2300457C.svg?logo=paypal&style=flat-square
[paypal-link]: https://paypal.me/ZackRauen
[lgtm-badge]: https://img.shields.io/lgtm/grade/javascript/g/BetterDiscord/BetterDiscord.svg?style=flat-square
[lgtm-badge]: https://img.shields.io/lgtm/grade/javascript/g/BetterDiscord/BetterDiscord.svg?labelColor=0c0d10&style=for-the-badge
[lgtm-link]: https://lgtm.com/projects/g/BetterDiscord/BetterDiscord/context:javascript
[downloads-badge]: https://img.shields.io/github/downloads/BetterDiscord/BetterDiscord/latest/total?style=flat-square
[downloads-badge]: https://img.shields.io/github/downloads/BetterDiscord/Installer/total?labelColor=0c0d10&color=3a71c1&style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjI1IDM4LjVIMzUuNzVDMzYuNzE2NSAzOC41IDM3LjUgMzkuMjgzNSAzNy41IDQwLjI1QzM3LjUgNDEuMTY4MiAzNi43OTI5IDQxLjkyMTIgMzUuODkzNSA0MS45OTQyTDM1Ljc1IDQySDEyLjI1QzExLjI4MzUgNDIgMTAuNSA0MS4yMTY1IDEwLjUgNDAuMjVDMTAuNSAzOS4zMzE4IDExLjIwNzEgMzguNTc4OCAxMi4xMDY1IDM4LjUwNThMMTIuMjUgMzguNUgzNS43NUgxMi4yNVpNMjMuNjA2NSA2LjI1NThMMjMuNzUgNi4yNUMyNC42NjgyIDYuMjUgMjUuNDIxMiA2Ljk1NzExIDI1LjQ5NDIgNy44NTY0N0wyNS41IDhWMjkuMzMzTDMwLjI5MzEgMjQuNTQwN0MzMC45NzY1IDIzLjg1NzMgMzIuMDg0NiAyMy44NTczIDMyLjc2OCAyNC41NDA3QzMzLjQ1MTQgMjUuMjI0MiAzMy40NTE0IDI2LjMzMjIgMzIuNzY4IDI3LjAxNTZMMjQuOTg5OCAzNC43OTM4QzI0LjMwNjQgMzUuNDc3MiAyMy4xOTg0IDM1LjQ3NzIgMjIuNTE1IDM0Ljc5MzhMMTQuNzM2OCAyNy4wMTU2QzE0LjA1MzQgMjYuMzMyMiAxNC4wNTM0IDI1LjIyNDIgMTQuNzM2OCAyNC41NDA3QzE1LjQyMDIgMjMuODU3MyAxNi41MjgyIDIzLjg1NzMgMTcuMjExNyAyNC41NDA3TDIyIDI5LjMyOVY4QzIyIDcuMDgxODMgMjIuNzA3MSA2LjMyODgxIDIzLjYwNjUgNi4yNTU4TDIzLjc1IDYuMjVMMjMuNjA2NSA2LjI1NThaIiBmaWxsPSIjM2E3MWMxIi8+Cjwvc3ZnPgo=
[downloads-link]: #auto-installers
[discord-badge]: https://img.shields.io/badge/support%20server-join-green?labelColor=0c0d10&color=7289da&style=for-the-badge&logo=discord&logoColor=7289da
[discord-link]: https://discord.gg/bnSUxedypU
[patreon-badge]: https://img.shields.io/badge/Patreon-Donate-%2300457C.svg?logo=Patreon&logoColor=ff424d&labelColor=0c0d10&color=ff424d&style=for-the-badge
[patreon-link]: https://patreon.com/Zerebos
[paypal-badge]: https://img.shields.io/badge/Paypal-Donate-%2300457C.svg?logo=Paypal&labelColor=0c0d10&color=002f86&style=for-the-badge
[paypal-link]: https://paypal.me/ZackRauen
BetterDiscord is a client modification for Discord. This allows you to add plugins and themes to your personal copy of Discord. BetterDiscord also adds a number of other features out of the box.
---
# Installation
## Auto Installers
### Windows
Grab the `exe` file from [here](https://github.com/BetterDiscord/Installer/releases/latest/download/BetterDiscord-Windows.exe).
[![Windows Installer][windows-badge]][windows-link] [![Mac Installer][mac-badge]][mac-link] [![Linux Installer][linux-badge]][linux-link]
### macOS/OS X
Grab the `zip` file from [here](https://github.com/BetterDiscord/Installer/releases/latest/download/BetterDiscord-Mac.zip).
[windows-link]: https://github.com/BetterDiscord/Installer/releases/latest/download/BetterDiscord-Windows.exe
[windows-badge]: https://img.shields.io/badge/Windows%20(7+)-Download-3a71c1?logo=Windows&logoColor=3a71c1&labelColor=0c0d10&color=3a71c1&style=for-the-badge
### Linux
Grab the `AppImage` file from [here](https://github.com/BetterDiscord/Installer/releases/latest/download/BetterDiscord-Linux.AppImage).
[mac-link]: https://github.com/BetterDiscord/Installer/releases/latest/download/BetterDiscord-Mac.zip
[mac-badge]: https://img.shields.io/badge/macOS%20(10.10+)-Download-3a71c1?logo=Apple&logoColor=3a71c1&labelColor=0c0d10&color=3a71c1&style=for-the-badge
[linux-link]: https://github.com/BetterDiscord/Installer/releases/latest/download/BetterDiscord-Linux.AppImage
[linux-badge]: https://img.shields.io/badge/Linux-Download-3a71c1?logo=Linux&logoColor=3a71c1&labelColor=0c0d10&color=3a71c1&style=for-the-badge
## Manual Installation
For normal users, installing via the installers makes the most sense. However when wanting to either develop BetterDiscord, or when the installers do not work, this option can be used.
**Prerequisites**: [Git](https://git-scm.com), [Node.js](https://nodejs.org/en/) 12.x+ and the package manager [npm](https://www.npmjs.com/).
### Prerequisites
- [Git](https://git-scm.com)
- [Node.js](https://nodejs.org/en/) with `npm`.
- Command line of your choice.
1. Clone this repository `git clone https://github.com/BetterDiscord/BetterDiscord.git`
2. Install dependencies with `npm install`
3. Build both the Injector and Renderer bundles with `npm run build` this will create a `injector.js`, `preload.js`, and `renderer.js` in the `dist` folder.
4. Run the inject script to inject the local files into your Discord client (`npm run inject`). Alternately install it to non-stable using `npm run inject canary`.
### 1: Clone the repository
```ps
git clone https://github.com/BetterDiscord/BetterDiscord.git
```
### 2: Install dependencies
```ps
npm install
```
### 3: Run Build Script
This will create a `injector.js`, `preload.js`, and `renderer.js` in the `dist` folder.
```ps
npm run build
```
### 4: Inject into your Discord client
#### Install to Stable
```ps
npm run inject
```
#### Install to PTB
```ps
npm run inject ptb
```
#### Install to Canary
```ps
npm run inject canary
```
## Additional Scripts
### Compiling & Distribution
This will create a `betterdiscord.asar` file in the `dist` folder.
```ps
npm run dist
```
---
# FAQ
@ -53,9 +91,7 @@ BD has some other built-in features such as Emotes from Twitch, FFZ, and BBTV, a
The easiest way to find plugins and themes is to browse them on [our website: https://betterdiscord.app/](https://betterdiscord.app/). Additionally, in our [support servers](#support-servers) we have channels with lists of <u>official</u> plugins and themes.
### Support Servers?
There are two: [The main server](https://discord.gg/bnSUxedypU), and [the backup](https://discord.gg/XqSpb9e3dq).
There are two: [The main server][discord-link], and [the backup](https://discord.gg/XqSpb9e3dq).
# Supporters
These people have all subscribed to the `True Supporter` tier on Patreon to support me.
@ -93,11 +129,9 @@ These people have all subscribed to the `True Supporter` tier on Patreon to supp
</tr>
</table>
# Bandagers
These people have all subscribed to the `Bandager` tier on Patreon to support me.
<table>
<tr>
<td align="center">
@ -177,4 +211,13 @@ These people have either donated or subscribed to the most basic patron tier to
<strong>Pixel</strong>
</td>
</tr>
</table>
</table>
# Contributors
For information on contributing to this project, please see [CONTRIBUTING.md](/CONTRIBUTING.md).
[![Contributors][contributors-image]][contributors-link]
[contributors-image]: https://contrib.rocks/image?repo=betterdiscord/betterdiscord
[contributors-link]: https://github.com/betterdiscord/betterdiscord/graphs/contributors

View File

@ -94,10 +94,19 @@ export default class BetterDiscord {
// If a previous crash was detected, show a message explaining why BD isn't there
electron.dialog.showMessageBox({
title: "BetterDiscord Crashed",
title: "Discord Crashed",
type: "warning",
message: "BetterDiscord seems to have crashed your Discord client.",
detail: "BetterDiscord has automatically disabled itself temporarily. Try removing all your plugins then restarting Discord."
message: "Something crashed your Discord Client",
detail: "BetterDiscord has automatically disabled itself just in case. To enable it again, restart Discord or click the button below.\n\nThis may have been caused by a plugin. Try moving all of your plugins outside the plugin folder and see if Discord still crashed.",
buttons: ["Try Again", "Open Plugins Folder", "Cancel"],
}).then((result)=>{
if (result.response === 0) {
electron.app.relaunch();
electron.app.exit();
}
if (result.response === 1) {
electron.shell.openPath(path.join(dataPath, "plugins"));
}
});
hasCrashed = false;
});

View File

@ -30,15 +30,8 @@ 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
__non_webpack_require__.cache[electronPath].exports = {...electron, BrowserWindow}; // Try to assign again after deleting
}
}

2715
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "betterdiscord",
"version": "1.5.2",
"version": "1.5.3",
"description": "Enhances Discord by adding functionality and themes.",
"main": "src/index.js",
"scripts": {
@ -19,6 +19,6 @@
"asar": "^3.0.3",
"eslint": "^7.12.0",
"eslint-plugin-react": "^7.21.5",
"mocha": "^8.2.0"
"mocha": "^10.0.0"
}
}

17919
renderer/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@
"postcss": "^8.4.5",
"postcss-cli": "^9.1.0",
"postcss-csso": "^6.0.0",
"postcss-easy-import": "^3.0.0",
"postcss-easy-import": "^4.0.0",
"postcss-loader": "^6.2.1",
"stylelint": "^14.3.0",
"stylelint-config-standard": "^24.0.0",

View File

@ -14,7 +14,7 @@ export default new class DeveloperMode extends Builtin {
}
debugListener(e) {
if (e.which === 119 || e.which == 118) { // F8
if (e.key === "F7" || e.key == "F8") {
debugger; // eslint-disable-line no-debugger
e.preventDefault();
e.stopImmediatePropagation();

View File

@ -13,7 +13,7 @@ export default new class DevToolsListener extends Builtin {
}
toggleDevTools(e) {
if (e.ctrlKey && e.shiftKey && e.which === 73) { // Ctrl + Shift + I
if (e.ctrlKey && e.shiftKey && e.key === "I") {
e.stopPropagation();
e.preventDefault();
if (this.get(this.collection, this.category, this.id)) IPC.toggleDevTools();

View File

@ -15,7 +15,7 @@ export default new class InspectElement extends Builtin {
}
inspectElement(e) {
if (e.ctrlKey && e.shiftKey && e.which === 67) { // Ctrl + Shift + C
if (e.ctrlKey && e.shiftKey && e.key === "C") { // Ctrl + Shift + C
IPC.inspectElement();
}
}

View File

@ -5,7 +5,7 @@ export default {
title: "Fixes",
type: "fixed",
items: [
"BD loads again, thanks to Strencher for this late night fix while I was away"
"Injection on Canary is fixed!"
]
}
]

View File

@ -12,7 +12,7 @@ export default function() {
}
if (request === namespace || request.startsWith(prefix)) {
const requested = request.substr(prefix.length);
const requested = request.slice(prefix.length);
if (requested == "bdapi") return BdApi;
}

View File

@ -164,8 +164,8 @@ export default class AddonManager {
if (line.charAt(0) === "@" && line.charAt(1) !== " ") {
out[field] = accum;
const l = line.indexOf(" ");
field = line.substr(1, l - 1);
accum = line.substr(l + 1);
field = line.substring(1, l);
accum = line.substring(l + 1);
}
else {
accum += " " + line.replace("\\n", "\n").replace(escapedAtRegex, "@");

View File

@ -7,16 +7,6 @@ const combineClasses = function (...props) {
};
const DiscordClassModules = Utilities.memoizeObject({
get Divider() {
const toolbar = WebpackModules.getByProps("divider", "toolbar");
const discovery = WebpackModules.getByProps("divider", "emptyGuilds");
return {
verticalDivider: toolbar.divider,
dividerLarge: discovery.divider,
divider: "bd-divider"
};
},
get Text() {
return combineClasses(
["size20", "size12"],
@ -30,7 +20,7 @@ const DiscordClassModules = Utilities.memoizeObject({
);
},
get EmptyImage() {return WebpackModules.getByProps("emptyImage", "emptyHeader");},
get Modal() {return WebpackModules.getByProps("content", "root", "header");},
get Modal() {return WebpackModules.getByProps("content", "root", "header", "close");},
get Scrollers() {return WebpackModules.getByProps("thin", "scrollerBase", "content");},
get Margins() {return WebpackModules.getByProps("marginXSmall", "marginBottom8");},
get Integrations() {return WebpackModules.getByProps("secondaryHeader", "detailsWrapper");},

View File

@ -91,10 +91,11 @@ export default class DOMManager {
static injectScript(id, url) {
id = this.escapeID(id);
return new Promise(resolve => {
return new Promise((resolve, reject) => {
const script = this.getElement(`#${id}`, this.bdScripts) || this.createElement("script", {id});
script.src = url;
script.onload = resolve;
script.onerror = reject;
this.bdScripts.append(script);
});
}

View File

@ -1,3 +1,4 @@
import Logger from "../../../common/logger";
import DOMManager from "./dommanager";
export default new class Editor {
@ -22,12 +23,23 @@ export default new class Editor {
delete window.module; // Make monaco think this isn't a local node script or else it freaks out
DOMManager.linkStyle("monaco-style", `${baseUrl}/vs/editor/editor.main.min.css`, {documentHead: true});
await DOMManager.injectScript("monaco-script", `${baseUrl}/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: `${baseUrl}/vs`}});
amdLoader(["vs/editor/editor.main"], () => {}); // exposes the monaco global
try {
await DOMManager.injectScript("monaco-script", `${baseUrl}/vs/loader.min.js`);
const amdLoader = window.require; // Grab Monaco's amd loader
window.require = commonjsLoader; // Revert to commonjs
// Configure Monaco's AMD loader
amdLoader.config({paths: {vs: `${baseUrl}/vs`}});
amdLoader(["vs/editor/editor.main"], () => {}); // exposes the monaco global
}
catch (e) {
Logger.error("Editor", "Failed to load monaco editor", e);
}
finally {
// Revert the global require to CommonJS
window.require = commonjsLoader;
}
}
};

View File

@ -9,10 +9,20 @@ import Events from "./emitter";
import Toasts from "../ui/toasts";
import Modals from "../ui/modals";
import SettingsRenderer from "../ui/settings";
import Utilities from "./utilities";
const path = require("path");
const vm = require("vm");
const fileModification = name => `
if (module.exports.default) {
module.exports = module.exports.default;
}
if (typeof(module.exports) !== "function") {
module.exports = eval("${name};")
}`;
export default new class PluginManager extends AddonManager {
get name() {return "PluginManager";}
get moduleExtension() {return ".js";}
@ -78,8 +88,16 @@ export default new class PluginManager extends AddonManager {
if (!addon.exports || !addon.name) return new AddonError(addon.name || addon.filename, addon.filename, "Plugin had no exports or @name property", {message: "Plugin had no exports or no @name property. @name property is required for all addons.", stack: ""}, this.prefix);
try {
const isValid = typeof(addon.exports) === "function";
if (!isValid) return new AddonError(addon.name || addon.filename, addon.filename, "Plugin not a valid format.", {message: "Plugins should be either a function or a class", stack: ""}, this.prefix);
const isClass = Utilities.isClass(addon.exports);
const PluginClass = addon.exports;
const thePlugin = new PluginClass();
const meta = Object.assign({}, addon);
delete meta.exports;
const thePlugin = isClass ? new PluginClass(meta) : addon.exports(meta);
if (!thePlugin.start || !thePlugin.stop) return new AddonError(addon.name || addon.filename, addon.filename, "Missing start or stop function.", {message: "Plugins must have both a start and stop function.", stack: ""}, this.prefix);
addon.instance = thePlugin;
addon.name = thePlugin.getName ? thePlugin.getName() : addon.name;
addon.author = thePlugin.getAuthor ? thePlugin.getAuthor() : addon.author || "No author";
@ -93,11 +111,13 @@ export default new class PluginManager extends AddonManager {
return new AddonError(addon.name, addon.filename, "load() could not be fired.", {message: error.message, stack: error.stack}, this.prefix);
}
}
catch (error) {return new AddonError(addon.name, addon.filename, "Could not be constructed.", {message: error.message, stack: error.stack}, this.prefix);}
catch (error) {
return new AddonError(addon.name, addon.filename, "Could not be constructed.", {message: error.message, stack: error.stack}, this.prefix);
}
}
getFileModification(module, fileContent, meta) {
fileContent += `\nif (module.exports.default) {module.exports = module.exports.default;}\nif (!module.exports.prototype || !module.exports.prototype.start) {module.exports = ${meta.exports || meta.name};}`;
fileContent += fileModification(meta.exports || meta.name);
window.global = window;
window.module = module;

View File

@ -113,6 +113,10 @@ export default class Utilities {
return true;
}
static isClass(obj) {
return typeof(obj) === "function" && /^\s*class\s+/.test(obj.toString());
}
/**
* Generates an automatically memoizing version of an object.
* @author Zerebos

View File

@ -97,4 +97,12 @@
.monaco-editor .view-overlays .current-line {
width: 1e+06px !important;
}
}
.bd-fallback-editor {
height: 100%;
width: 100%;
resize: none;
overflow: auto;
white-space: nowrap;
}

View File

@ -47,5 +47,6 @@
.bd-divider {
width: 100%;
height: 1px;
border-top: thin solid hsl(0deg 0% 100% / 6%);
border-top: thin solid var(--background-modifier-accent);
margin-bottom: 1em;
}

View File

@ -1,6 +1,7 @@
import {React, Strings, WebpackModules, DiscordClasses} from "modules";
import Extension from "./icons/extension";
import ThemeIcon from "./icons/theme";
import Divider from "./divider";
const Parser = Object(WebpackModules.getByProps("defaultRules", "parse")).defaultRules;
@ -18,10 +19,10 @@ class AddonError extends React.Component {
this.setState({expanded: !this.state.expanded});
}
renderErrorBody(err) {
const stack = err.error && err.stack;
const stack = err?.error?.stack ?? err.stack;
if (!this.state.expanded || !stack) return null;
return <div className="bd-addon-error-body">
<div className={`${DiscordClasses.Card.topDivider} ${DiscordClasses.Divider.divider}`} />
<Divider />
<div className="bd-addon-error-stack">
{Parser ? Parser.codeBlock.react({content: stack, lang: "js"}, null, {}) : stack}
</div>

View File

@ -32,25 +32,45 @@ export default class CodeEditor extends React.Component {
}
componentDidMount() {
this.editor = window.monaco.editor.create(document.getElementById(this.props.id), {
value: this.props.value,
language: this.props.language,
theme: DiscordModules.UserSettingsStore.theme == "light" ? "vs" : "vs-dark",
fontSize: Settings.get("settings", "editor", "fontSize"),
lineNumbers: Settings.get("settings", "editor", "lineNumbers"),
minimap: {enabled: Settings.get("settings", "editor", "minimap")},
hover: {enabled: Settings.get("settings", "editor", "hover")},
quickSuggestions: {
other: Settings.get("settings", "editor", "quickSuggestions"),
comments: Settings.get("settings", "editor", "quickSuggestions"),
strings: Settings.get("settings", "editor", "quickSuggestions")
},
renderWhitespace: Settings.get("settings", "editor", "renderWhitespace")
});
if (window.monaco?.editor) {
this.editor = window.monaco.editor.create(document.getElementById(this.props.id), {
value: this.props.value,
language: this.props.language,
theme: DiscordModules.UserSettingsStore.theme == "light" ? "vs" : "vs-dark",
fontSize: Settings.get("settings", "editor", "fontSize"),
lineNumbers: Settings.get("settings", "editor", "lineNumbers"),
minimap: {enabled: Settings.get("settings", "editor", "minimap")},
hover: {enabled: Settings.get("settings", "editor", "hover")},
quickSuggestions: {
other: Settings.get("settings", "editor", "quickSuggestions"),
comments: Settings.get("settings", "editor", "quickSuggestions"),
strings: Settings.get("settings", "editor", "quickSuggestions")
},
renderWhitespace: Settings.get("settings", "editor", "renderWhitespace")
});
this.bindings.push(this.editor.onDidChangeModelContent(this.onChange));
}
else {
const textarea = document.createElement("textarea");
textarea.className = "bd-fallback-editor";
textarea.value = this.props.value;
textarea.onchange = (e) => this.onChange(e.target.value);
textarea.oninput = (e) => this.onChange(e.target.value);
this.editor = {
dispose: () => textarea.remove(),
getValue: () => textarea.value,
setValue: (value) => textarea.value = value,
layout: () => {},
};
document.getElementById(this.props.id).appendChild(textarea);
}
window.addEventListener("resize", this.resize);
if (DiscordModules.UserSettingsStore) DiscordModules.UserSettingsStore.addChangeListener(this.onThemeChange);
this.bindings.push(this.editor.onDidChangeModelContent(this.onChange));
window.addEventListener("resize", this.resize);
}
componentWillUnmount() {
@ -64,7 +84,7 @@ export default class CodeEditor extends React.Component {
const newTheme = DiscordModules.UserSettingsStore.theme === "light" ? "vs" : "vs-dark";
if (newTheme === this.props.theme) return;
this.props.theme = newTheme;
window.monaco.editor.setTheme(this.props.theme);
if (window.monaco?.editor) window.monaco.editor.setTheme(this.props.theme);
}
get value() {return this.editor.getValue();}

View File

@ -0,0 +1,3 @@
import {React} from "modules";
export default ({className}) => <div className={`bd-divider ${className || ""}`}></div>;

View File

@ -75,7 +75,7 @@ export default class PublicServers extends React.Component {
}
searchKeyDown(e) {
if (this.state.loading || e.which !== 13) return;
if (this.state.loading || e.key !== "Enter") return;
const term = e.target.value;
if (this.state.tab == "Featured" || this.state.tab == "Popular") this.setState({tab: "All"}, () => this.search(term));
else this.search(term);

View File

@ -1,7 +0,0 @@
import {React} from "modules";
export default class Divider extends React.Component {
render() {
return <div className="bd-divider divider-3573oO marginTop8-1DLZ1n marginBottom40-2vIwTv" />;
}
}

View File

@ -1,7 +1,7 @@
import Logger from "common/logger";
import {React} from "modules";
import Title from "./title";
import Divider from "./divider";
import Divider from "../divider";
import Switch from "./components/switch";
import Dropdown from "./components/dropdown";
import Number from "./components/number";

View File

@ -46,7 +46,7 @@ console.log(`Injecting into ${release}`);
if (!fs.existsSync(discordPath)) throw new Error(`Cannot find directory for ${release}`);
console.log(` ✅ Found ${release} in ${discordPath}`);
const appPath = path.join(discordPath, "app");
const appPath = process.platform === "win32" || process.platform === "darwin" ? path.join(discordPath, "app") : discordPath;
const packageJson = path.join(appPath, "package.json");
const indexJs = path.join(appPath, "index.js");