Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
5cd430c41a
31
CHANGELOG.md
31
CHANGELOG.md
|
@ -2,6 +2,37 @@
|
|||
|
||||
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.8.3
|
||||
|
||||
### Added
|
||||
- Checking for old installs and deleting them
|
||||
|
||||
### Removed
|
||||
- All references to Emotes, this will become a separate plugin
|
||||
|
||||
### Changed
|
||||
- Moved to the more permissive Apache 2.0 license
|
||||
- Now check for discord.asar for electron17+
|
||||
- Handle setting module exports internally rather than maintaining getter references
|
||||
|
||||
### Fixed
|
||||
- Fixed `inject` for electron17+
|
||||
- Updater checking `>` which does not work for open versions
|
||||
- Fixed a startup bug with the context menu api
|
||||
|
||||
## 1.8.2
|
||||
|
||||
### Added
|
||||
|
||||
### Removed
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
- Fixed modals not working
|
||||
- Fixed downloading binary files
|
||||
- Fixed public server invites
|
||||
|
||||
## 1.8.1
|
||||
|
||||
### Added
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import {app} from "electron";
|
||||
import Module from "module";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
// Detect old install and delete it
|
||||
const appPath = app.getAppPath(); // Should point to app or app.asar
|
||||
const oldInstall = path.resolve(appPath, "..", "app");
|
||||
if (fs.existsSync(oldInstall)) {
|
||||
fs.rmdirSync(oldInstall, {recursive: true});
|
||||
app.quit();
|
||||
app.relaunch();
|
||||
}
|
||||
|
||||
import ipc from "./modules/ipc";
|
||||
import BrowserWindow from "./modules/browserwindow";
|
||||
|
@ -19,32 +27,30 @@ if (!process.argv.includes("--vanilla")) {
|
|||
|
||||
|
||||
// Remove CSP immediately on linux since they install to discord_desktop_core still
|
||||
if (process.platform == "win32" || process.platform == "darwin") app.once("ready", CSP.remove);
|
||||
else CSP.remove();
|
||||
try {
|
||||
CSP.remove();
|
||||
}
|
||||
catch (_) {
|
||||
// Remove when everyone is moved to core
|
||||
}
|
||||
}
|
||||
|
||||
// Enable DevTools on Stable.
|
||||
let fakeAppSettings;
|
||||
Object.defineProperty(global, "appSettings", {
|
||||
get() {
|
||||
return fakeAppSettings;
|
||||
},
|
||||
set(value) {
|
||||
if (!value.hasOwnProperty("settings")) value.settings = {};
|
||||
value.settings.DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING = true;
|
||||
fakeAppSettings = value;
|
||||
},
|
||||
});
|
||||
|
||||
// Use Discord's info to run the app
|
||||
if (process.platform == "win32" || process.platform == "darwin") {
|
||||
const appAsar = path.join(app.getAppPath(), "..", "app.asar");
|
||||
const discordAsar = path.join(app.getAppPath(), "..", "discord.asar");
|
||||
const basePath = fs.existsSync(discordAsar) ? discordAsar : appAsar;
|
||||
const pkg = __non_webpack_require__(path.join(basePath, "package.json"));
|
||||
app.setAppPath(basePath);
|
||||
app.name = pkg.name;
|
||||
Module._load(path.join(basePath, pkg.main), null, true);
|
||||
try {
|
||||
let fakeAppSettings;
|
||||
Object.defineProperty(global, "appSettings", {
|
||||
get() {
|
||||
return fakeAppSettings;
|
||||
},
|
||||
set(value) {
|
||||
if (!value.hasOwnProperty("settings")) value.settings = {};
|
||||
value.settings.DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING = true;
|
||||
fakeAppSettings = value;
|
||||
},
|
||||
});
|
||||
}
|
||||
catch (_) {
|
||||
// Remove when everyone is moved to core
|
||||
}
|
||||
|
||||
// Needs to run this after Discord but before ready()
|
||||
|
|
|
@ -46,16 +46,6 @@ export default class BetterDiscord {
|
|||
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
|
||||
|
|
|
@ -128,17 +128,23 @@ const registerPreload = (event, path) => {
|
|||
|
||||
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.on(IPCEvents.TOGGLE_DEVTOOLS, toggleDevTools);
|
||||
ipc.on(IPCEvents.INSPECT_ELEMENT, inspectElement);
|
||||
ipc.on(IPCEvents.MINIMUM_SIZE, setMinimumSize);
|
||||
ipc.on(IPCEvents.DEVTOOLS_WARNING, stopDevtoolsWarning);
|
||||
ipc.on(IPCEvents.REGISTER_PRELOAD, registerPreload);
|
||||
ipc.handle(IPCEvents.RUN_SCRIPT, runScript);
|
||||
ipc.handle(IPCEvents.OPEN_DIALOG, openDialog);
|
||||
ipc.handle(IPCEvents.OPEN_WINDOW, createBrowserWindow);
|
||||
try {
|
||||
ipc.on(IPCEvents.GET_PATH, getPath);
|
||||
ipc.on(IPCEvents.RELAUNCH, relaunch);
|
||||
ipc.on(IPCEvents.OPEN_DEVTOOLS, openDevTools);
|
||||
ipc.on(IPCEvents.CLOSE_DEVTOOLS, closeDevTools);
|
||||
ipc.on(IPCEvents.TOGGLE_DEVTOOLS, toggleDevTools);
|
||||
ipc.on(IPCEvents.INSPECT_ELEMENT, inspectElement);
|
||||
ipc.on(IPCEvents.MINIMUM_SIZE, setMinimumSize);
|
||||
ipc.on(IPCEvents.DEVTOOLS_WARNING, stopDevtoolsWarning);
|
||||
ipc.on(IPCEvents.REGISTER_PRELOAD, registerPreload);
|
||||
ipc.handle(IPCEvents.RUN_SCRIPT, runScript);
|
||||
ipc.handle(IPCEvents.OPEN_DIALOG, openDialog);
|
||||
ipc.handle(IPCEvents.OPEN_WINDOW, createBrowserWindow);
|
||||
}
|
||||
catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "betterdiscord",
|
||||
"version": "1.8.2",
|
||||
"version": "1.8.3",
|
||||
"description": "Enhances Discord by adding functionality and themes.",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -2,15 +2,21 @@
|
|||
export default {
|
||||
description: "Just some smaller fixes while we work on some big things in the background.",
|
||||
changes: [
|
||||
{
|
||||
title: "What's New?",
|
||||
type: "",
|
||||
items: [
|
||||
"Twitch emotes are no longer a part of BetterDiscord, we are opting to move them to a plugin. Stay tuned for when that will be completed!",
|
||||
"We changed the way patching is handled internally hoping it'll help with memory leaks.",
|
||||
"Everything should be working again for Canary and PTB with the latest updates!",
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Bug Fixes",
|
||||
type: "fixed",
|
||||
items: [
|
||||
"Fixed _even more_ issues with the built-in updater.",
|
||||
"Fixed not being able to click support server links in plugin/theme pages.",
|
||||
"Fixed some issues with not being able to join public servers.",
|
||||
"Fixed plugin settings not being able to be displayed.",
|
||||
"Fixed changelog modal not being able to be displayed."
|
||||
"Fixed the way the update compares version numbers.",
|
||||
"Fixed the startup bug."
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,6 +3,8 @@ import Patcher from "../patcher";
|
|||
import Logger from "common/logger";
|
||||
import {React} from "../modules";
|
||||
|
||||
let startupComplete = false;
|
||||
|
||||
const MenuComponents = (() => {
|
||||
const out = {};
|
||||
const componentMap = {
|
||||
|
@ -14,14 +16,25 @@ const MenuComponents = (() => {
|
|||
customitem: "Item"
|
||||
};
|
||||
|
||||
let ContextMenuIndex = null;
|
||||
const ContextMenuModule = WebpackModules.getModule((m, _, id) => Object.values(m).some(v => v?.FLEXIBLE) && (ContextMenuIndex = id), {searchExports: false});
|
||||
const rawMatches = WebpackModules.require.m[ContextMenuIndex].toString().matchAll(/if\(\w+\.type===\w+\.(\w+)\).+?type:"(.+?)"/g);
|
||||
|
||||
out.Menu = Object.values(ContextMenuModule).find(v => v.toString().includes(".isUsingKeyboardNavigation"));
|
||||
try {
|
||||
let contextMenuId = Object.keys(WebpackModules.require.m).find(e => WebpackModules.require.m[e]?.toString().includes("menuitemcheckbox"));
|
||||
const ContextMenuModule = WebpackModules.getModule((m, t, id) => id === contextMenuId);
|
||||
const rawMatches = WebpackModules.require.m[contextMenuId].toString().matchAll(/if\(\w+\.type===\w+\.(\w+)\).+?type:"(.+?)"/g);
|
||||
|
||||
for (const [, identifier, type] of rawMatches) {
|
||||
out[componentMap[type]] = ContextMenuModule[identifier];
|
||||
out.Menu = Object.values(ContextMenuModule).find(v => v.toString().includes(".isUsingKeyboardNavigation"));
|
||||
|
||||
for (const [, identifier, type] of rawMatches) {
|
||||
out[componentMap[type]] = ContextMenuModule[identifier];
|
||||
}
|
||||
|
||||
startupComplete = Object.values(componentMap).every(k => out[k]) && !!out.Menu;
|
||||
} catch (error) {
|
||||
startupComplete = false;
|
||||
Logger.stacktrace("ContextMenu~Components", "Fatal startup error:", error);
|
||||
|
||||
Object.assign(out, Object.fromEntries(
|
||||
Object.values(componentMap).map(k => [k, () => null])
|
||||
));
|
||||
}
|
||||
|
||||
return out;
|
||||
|
@ -30,15 +43,27 @@ const MenuComponents = (() => {
|
|||
const ContextMenuActions = (() => {
|
||||
const out = {};
|
||||
|
||||
const ActionsModule = WebpackModules.getModule(m => Object.values(m).some(v => typeof v === "function" && v.toString().includes("CONTEXT_MENU_CLOSE")), {searchExports: false});
|
||||
try {
|
||||
const ActionsModule = WebpackModules.getModule(m => Object.values(m).some(v => typeof v === "function" && v.toString().includes("CONTEXT_MENU_CLOSE")), {searchExports: false});
|
||||
|
||||
for (const key of Object.keys(ActionsModule)) {
|
||||
if (ActionsModule[key].toString().includes("CONTEXT_MENU_CLOSE")) {
|
||||
out.closeContextMenu = ActionsModule[key];
|
||||
}
|
||||
else if (ActionsModule[key].toString().includes("renderLazy")) {
|
||||
out.openContextMenu = ActionsModule[key];
|
||||
for (const key of Object.keys(ActionsModule)) {
|
||||
if (ActionsModule[key].toString().includes("CONTEXT_MENU_CLOSE")) {
|
||||
out.closeContextMenu = ActionsModule[key];
|
||||
}
|
||||
else if (ActionsModule[key].toString().includes("renderLazy")) {
|
||||
out.openContextMenu = ActionsModule[key];
|
||||
}
|
||||
}
|
||||
|
||||
startupComplete = typeof(out.closeContextMenu) === "function" && typeof(out.openContextMenu) === "function";
|
||||
} catch (error) {
|
||||
startupComplete = false;
|
||||
Logger.stacktrace("ContextMenu~Components", "Fatal startup error:", error);
|
||||
|
||||
Object.assign(out, {
|
||||
closeContextMenu: () => {},
|
||||
openContextMenu: () => {}
|
||||
});
|
||||
}
|
||||
|
||||
return out;
|
||||
|
@ -50,6 +75,8 @@ class MenuPatcher {
|
|||
static subPatches = new WeakMap();
|
||||
|
||||
static initialize() {
|
||||
if (!startupComplete) return Logger.warn("ContextMenu~Patcher", "Startup wasn't successfully, aborting initialization.");
|
||||
|
||||
const {module, key} = (() => {
|
||||
const foundModule = WebpackModules.getModule(m => Object.values(m).some(v => typeof v === "function" && v.toString().includes("CONTEXT_MENU_CLOSE")), {searchExports: false});
|
||||
const foundKey = Object.keys(foundModule).find(k => foundModule[k].length === 3);
|
||||
|
@ -320,6 +347,11 @@ class ContextMenu {
|
|||
Object.assign(ContextMenu.prototype, MenuComponents);
|
||||
Object.freeze(ContextMenu);
|
||||
Object.freeze(ContextMenu.prototype);
|
||||
MenuPatcher.initialize();
|
||||
|
||||
try {
|
||||
MenuPatcher.initialize();
|
||||
} catch (error) {
|
||||
Logger.error("ContextMenu~Patcher", "Fatal error:", error);
|
||||
}
|
||||
|
||||
export default ContextMenu;
|
||||
|
|
|
@ -134,6 +134,25 @@ export class CoreUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
const semverRegex = /^[0-9]+\.[0-9]+\.[0-9]+$/;
|
||||
|
||||
/**
|
||||
* This works on basic semantic versioning e.g. "1.0.0".
|
||||
*
|
||||
* @param {string} currentVersion
|
||||
* @param {string} content
|
||||
* @returns {boolean} whether there is an update
|
||||
*/
|
||||
function semverComparator(currentVersion, remoteVersion) {
|
||||
currentVersion = currentVersion.split(".").map((e) => {return parseInt(e);});
|
||||
remoteVersion = remoteVersion.split(".").map((e) => {return parseInt(e);});
|
||||
|
||||
if (remoteVersion[0] > currentVersion[0]) return true;
|
||||
else if (remoteVersion[0] == currentVersion[0] && remoteVersion[1] > currentVersion[1]) return true;
|
||||
else if (remoteVersion[0] == currentVersion[0] && remoteVersion[1] == currentVersion[1] && remoteVersion[2] > currentVersion[2]) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class AddonUpdater {
|
||||
|
||||
|
@ -176,7 +195,10 @@ class AddonUpdater {
|
|||
if (this.pending.includes(filename)) return;
|
||||
const info = this.cache[path.basename(filename)];
|
||||
if (!info) return;
|
||||
const hasUpdate = info.version > currentVersion;
|
||||
let hasUpdate = info.update > currentVersion;
|
||||
if (semverRegex.test(info.version) && semverRegex.test(currentVersion)) {
|
||||
hasUpdate = semverComparator(currentVersion, info.version);
|
||||
}
|
||||
if (!hasUpdate) return;
|
||||
this.pending.push(filename);
|
||||
}
|
||||
|
|
|
@ -15,18 +15,13 @@ const discordPath = (function() {
|
|||
const basedir = path.join(process.env.LOCALAPPDATA, release.replace(/ /g, ""));
|
||||
if (!fs.existsSync(basedir)) throw new Error(`Cannot find directory for ${release}`);
|
||||
const version = fs.readdirSync(basedir).filter(f => fs.lstatSync(path.join(basedir, f)).isDirectory() && f.split(".").length > 1).sort().reverse()[0];
|
||||
resourcePath = path.join(basedir, version, "resources");
|
||||
}
|
||||
else if (process.platform === "darwin") {
|
||||
const appPath = releaseInput === "canary" ? path.join("/Applications", "Discord Canary.app")
|
||||
: releaseInput === "ptb" ? path.join("/Applications", "Discord PTB.app")
|
||||
: useBdRelease && args[3] ? args[3] ? args[2] : args[2]
|
||||
: path.join("/Applications", "Discord.app");
|
||||
|
||||
resourcePath = path.join(appPath, "Contents", "Resources");
|
||||
// To account for discord_desktop_core-1 or any other number
|
||||
const coreWrap = fs.readdirSync(path.join(basedir, version, "modules")).filter(e => e.indexOf("discord_desktop_core") === 0).sort().reverse()[0];
|
||||
resourcePath = path.join(basedir, version, "modules", coreWrap, "discord_desktop_core");
|
||||
}
|
||||
else {
|
||||
const userData = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : path.join(process.env.HOME, ".config");
|
||||
let userData = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : path.join(process.env.HOME, ".config");
|
||||
if (process.platform === "darwin") userData = path.join(process.env.HOME, "Library", "Application Support");
|
||||
const basedir = path.join(userData, release.toLowerCase().replace(" ", ""));
|
||||
if (!fs.existsSync(basedir)) return "";
|
||||
const version = fs.readdirSync(basedir).filter(f => fs.lstatSync(path.join(basedir, f)).isDirectory() && f.split(".").length > 1).sort().reverse()[0];
|
||||
|
@ -46,50 +41,11 @@ 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 = 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");
|
||||
|
||||
if (!fs.existsSync(appPath)) fs.mkdirSync(appPath);
|
||||
if (fs.existsSync(packageJson)) fs.unlinkSync(packageJson);
|
||||
const indexJs = path.join(discordPath, "index.js");
|
||||
if (fs.existsSync(indexJs)) fs.unlinkSync(indexJs);
|
||||
|
||||
if (process.platform === "win32" || process.platform === "darwin") {
|
||||
fs.writeFileSync(packageJson, JSON.stringify({
|
||||
name: "betterdiscord",
|
||||
main: "index.js",
|
||||
}, null, 4));
|
||||
console.log(" ✅ Wrote package.json");
|
||||
|
||||
fs.writeFileSync(indexJs, `require("${bdPath.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}");`);
|
||||
}
|
||||
else {
|
||||
fs.writeFileSync(indexJs, `require("${bdPath.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}");\nmodule.exports = require("./core.asar");`);
|
||||
}
|
||||
fs.writeFileSync(indexJs, `require("${bdPath.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}");\nmodule.exports = require("./core.asar");`);
|
||||
|
||||
console.log(" ✅ Wrote index.js");
|
||||
console.log("");
|
||||
|
||||
const asarPath = path.join(discordPath, "app.asar");
|
||||
const modifiedPath = path.join(discordPath, "discord.asar");
|
||||
|
||||
if (!fs.existsSync(modifiedPath)) {
|
||||
console.log("Renaming app.asar -> discord.asar");
|
||||
console.log("");
|
||||
|
||||
if (!fs.existsSync(asarPath)) {
|
||||
console.log(" ❌ Unable to rename app.asar -> discord.asar, discord installation appears to be corrupt.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
try {
|
||||
fs.renameSync(asarPath, modifiedPath);
|
||||
console.log(" ✅ Successfully renamed app.asar -> discord.asar");
|
||||
console.log("");
|
||||
} catch (error) {
|
||||
console.log(" ❌ Failed to rename app.asar -> discord.asar:", error);
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Injection successful, please restart ${release}.`);
|
||||
|
|
Loading…
Reference in New Issue