first working version

This commit is contained in:
Zack Rauen 2019-05-28 23:48:41 -04:00
parent 950ab70df4
commit 1968955244
40 changed files with 7411 additions and 2240 deletions

View File

@ -22,7 +22,9 @@
"yoda": 2,
"linebreak-style": ["error", "windows"],
"quote-props": ["error", "consistent-as-needed", {"keywords": true}],
"object-curly-spacing": ["error", "never", { "objectsInObjects": false }]
"object-curly-spacing": ["error", "never", { "objectsInObjects": false }],
"no-var": "error",
"prefer-const": "error"
},
"globals": {
"webpackJsonp": false,
@ -30,12 +32,6 @@
"Set": false,
"WeakMap": false,
"Promise": false,
"bdplugins": false,
"bdthemes": false,
"betterDiscordIPC": false,
"bdVersion": false,
"version": false,
"_bdhash": true,
"ace": false,
"Reflect": false,
"DiscordNative": false,

5795
js/main.js

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

9
src/data/data.js Normal file
View File

@ -0,0 +1,9 @@
import SettingsInfo from "./settings";
import SettingsCookie from "./settingscookie";
import Config from "./config";
import PluginCookie from "./plugincookie";
import ThemeCookie from "./themecookie";
import Themes from "./themes";
import Plugins from "./plugins";
export {SettingsInfo, SettingsCookie, Config, PluginCookie, ThemeCookie, Themes, Plugins};

1
src/data/plugincookie.js Normal file
View File

@ -0,0 +1 @@
export default {};

1
src/data/plugins.js Normal file
View File

@ -0,0 +1 @@
export default {};

View File

@ -5,21 +5,21 @@ export default {
/* Core */
/* ====== */
"Public Servers": {id: "bda-gs-1", info: "Display public servers button", implemented: true, hidden: false, cat: "core", category: "core"},
"Minimal Mode": {id: "bda-gs-2", info: "Hide elements and reduce the size of elements.", implemented: true, hidden: false, cat: "core", category: "core"},
"Voice Mode": {id: "bda-gs-4", info: "Only show voice chat", implemented: true, hidden: false, cat: "core", category: "core"},
"Hide Channels": {id: "bda-gs-3", info: "Hide channels in minimal mode", implemented: true, hidden: false, cat: "core", category: "core"},
"Dark Mode": {id: "bda-gs-5", info: "Make certain elements dark by default(wip)", implemented: true, hidden: false, cat: "core", category: "core"},
"Voice Disconnect": {id: "bda-dc-0", info: "Disconnect from voice server when closing Discord", implemented: true, hidden: false, cat: "core", category: "core"},
"24 Hour Timestamps": {id: "bda-gs-6", info: "Replace 12hr timestamps with proper ones", implemented: true, hidden: false, cat: "core", category: "core"},
"Coloured Text": {id: "bda-gs-7", info: "Make text colour the same as role colour", implemented: true, hidden: false, cat: "core", category: "core"},
"Normalize Classes": {id: "fork-ps-4", info: "Adds stable classes to elements to help themes. (e.g. adds .da-channels to .channels-Ie2l6A)", implemented: true, hidden: false, cat: "core", category: "core"},
"Public Servers": {id: "bda-gs-1", info: "Display public servers button", implemented: true, hidden: false, cat: "core", category: "modules"},
"Minimal Mode": {id: "bda-gs-2", info: "Hide elements and reduce the size of elements.", implemented: true, hidden: false, cat: "core", category: "modules"},
"Voice Mode": {id: "bda-gs-4", info: "Only show voice chat", implemented: true, hidden: false, cat: "core", category: "modules"},
"Hide Channels": {id: "bda-gs-3", info: "Hide channels in minimal mode", implemented: true, hidden: false, cat: "core", category: "modules"},
"Dark Mode": {id: "bda-gs-5", info: "Make certain elements dark by default(wip)", implemented: true, hidden: false, cat: "core", category: "modules"},
"Voice Disconnect": {id: "bda-dc-0", info: "Disconnect from voice server when closing Discord", implemented: true, hidden: false, cat: "core", category: "modules"},
"24 Hour Timestamps": {id: "bda-gs-6", info: "Replace 12hr timestamps with proper ones", implemented: true, hidden: false, cat: "core", category: "modules"},
"Coloured Text": {id: "bda-gs-7", info: "Make text colour the same as role colour", implemented: true, hidden: false, cat: "core", category: "modules"},
"Normalize Classes": {id: "fork-ps-4", info: "Adds stable classes to elements to help themes. (e.g. adds .da-channels to .channels-Ie2l6A)", implemented: true, hidden: false, cat: "core", category: "modules"},
/* Content */
"Content Error Modal": {id: "fork-ps-1", info: "Shows a modal with plugin/theme errors", implemented: true, hidden: false, cat: "core", category: "plugins & themes"},
"Show Toasts": {id: "fork-ps-2", info: "Shows a small notification for important information", implemented: true, hidden: false, cat: "core", category: "plugins & themes"},
"Scroll To Settings": {id: "fork-ps-3", info: "Auto-scrolls to a plugin's settings when the button is clicked (only if out of view)", implemented: true, hidden: false, cat: "core", category: "plugins & themes"},
"Automatic Loading": {id: "fork-ps-5", info: "Automatically loads, reloads, and unloads plugins and themes", implemented: true, hidden: false, cat: "core", category: "plugins & themes"},
"Content Error Modal": {id: "fork-ps-1", info: "Shows a modal with plugin/theme errors", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Show Toasts": {id: "fork-ps-2", info: "Shows a small notification for important information", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Scroll To Settings": {id: "fork-ps-3", info: "Auto-scrolls to a plugin's settings when the button is clicked (only if out of view)", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Automatic Loading": {id: "fork-ps-5", info: "Automatically loads, reloads, and unloads plugins and themes", implemented: true, hidden: false, cat: "core", category: "content manager"},
/* Developer */
"Developer Mode": {id: "bda-gs-8", info: "Developer Mode", implemented: true, hidden: false, cat: "core", category: "developer settings"},

1
src/data/themecookie.js Normal file
View File

@ -0,0 +1 @@
export default {};

1
src/data/themes.js Normal file
View File

@ -0,0 +1 @@
export default {};

View File

@ -1,5 +1,9 @@
import {SettingsCookie, SettingsInfo, PluginCookie, ThemeCookie, Plugins, Themes} from "data";
import proxyLocalStorage from "./localstorage";
import Core from "./modules/core";
import BdApi from "./modules/pluginapi";
import PluginManager from "./modules/pluginmanager";
import ThemeManager from "./modules/thememanager";
// Perform some setup
proxyLocalStorage();
@ -8,6 +12,26 @@ loadingIcon.className = "bd-loaderv2";
loadingIcon.title = "BandagedBD is loading...";
document.body.appendChild(loadingIcon);
window.Core = Core;
// window.Core = Core;
window.BdApi = BdApi;
window.settings = SettingsInfo;
window.settingsCookie = SettingsCookie;
window.pluginCookie = PluginCookie;
window.themeCookie = ThemeCookie;
window.pluginModule = PluginManager;
window.themeModule = ThemeManager;
window.bdthemes = Plugins;
window.bdplugins = Themes;
export default Core;
export default class CoreWrapper {
constructor(config) {
Core.setConfig(config);
}
init() {
Core.init();
}
}
// var settingsPanel, emoteModule, quickEmoteMenu, voiceMode,, dMode, publicServersModule;
// var bdConfig = null;

View File

@ -1,7 +1,7 @@
/* Localstorage fix */
export default function() {
const fs = window.require("fs");
const fs = require("fs");
const platform = process.platform;
const dataPath = (platform === "win32" ? process.env.APPDATA : platform === "darwin" ? process.env.HOME + "/Library/Preferences" : process.env.HOME + "/.config") + "/BetterDiscord/";
const localStorageFile = "localStorage.json";
@ -25,7 +25,7 @@ export default function() {
}
const storage = data;
storage.setItem = function(i, v) {
storage.setItem = function(i, v) {
storage[i] = v;
this.save();
};

View File

@ -1,6 +1,6 @@
import Settings from "../data/settings";
import {SettingsInfo} from "data";
import BdApi from "./pluginapi";
import BDLogo from "../ui/icons/bdlogo";
// import BDLogo from "../ui/icons/bdlogo";
export default new class V2 {
@ -49,7 +49,7 @@ export default new class V2 {
}
initialize() {
BdApi.suppressErrors(this.patchSocial.bind(this), "BD Social Patch")();
// BdApi.suppressErrors(this.patchSocial.bind(this), "BD Social Patch")();
BdApi.suppressErrors(this.patchGuildPills.bind(this), "BD Guild Pills Patch")();
BdApi.suppressErrors(this.patchGuildListItems.bind(this), "BD Guild List Items Patch")();
BdApi.suppressErrors(this.patchGuildSeparator.bind(this), "BD Guild Separator Patch")();
@ -75,8 +75,8 @@ export default new class V2 {
get KeyGenerator() {return this.WebpackModules.find(m => m.toString && /"binary"/.test(m.toString()));}
parseSettings(cat) {
return Object.keys(Settings).reduce((arr, key) => {
let setting = Settings[key];
return Object.keys(SettingsInfo).reduce((arr, key) => {
let setting = SettingsInfo[key];
if (setting.cat === cat && setting.implemented && !setting.hidden) {
setting.text = key;
arr.push(setting);
@ -84,27 +84,27 @@ export default new class V2 {
}, []);
}
patchSocial() {
if (this.socialPatch) return;
const TabBar = BdApi.findModule(m => m.displayName == "TabBar");
const Anchor = BdApi.findModule(m => m.displayName == "Anchor");
if (!TabBar || !Anchor) return;
this.socialPatch = BdApi.monkeyPatch(TabBar.prototype, "render", {after: (data) => {
const children = data.returnValue.props.children;
if (!children || !children.length) return;
if (children[children.length - 2].type.displayName !== "Separator") return;
if (!children[children.length - 1].type.toString().includes("socialLinks")) return;
const original = children[children.length - 1].type;
const newOne = function() {
const returnVal = original(...arguments);
returnVal.props.children.push(BdApi.React.createElement(Anchor, {className: "bd-social-link", href: "https://github.com/rauenzi/BetterDiscordApp", rel: "author", title: "BandagedBD", target: "_blank"},
BdApi.React.createElement(BDLogo, {size: "16px", className: "bd-social-logo"})
));
return returnVal;
};
children[children.length - 1].type = newOne;
}});
}
// patchSocial() {
// if (this.socialPatch) return;
// const TabBar = BdApi.findModule(m => m.displayName == "TabBar");
// const Anchor = BdApi.findModule(m => m.displayName == "Anchor");
// if (!TabBar || !Anchor) return;
// this.socialPatch = BdApi.monkeyPatch(TabBar.prototype, "render", {after: (data) => {
// const children = data.returnValue.props.children;
// if (!children || !children.length) return;
// if (children[children.length - 2].type.displayName !== "Separator") return;
// if (!children[children.length - 1].type.toString().includes("socialLinks")) return;
// const original = children[children.length - 1].type;
// const newOne = function() {
// const returnVal = original(...arguments);
// returnVal.props.children.push(BdApi.React.createElement(Anchor, {className: "bd-social-link", href: "https://github.com/rauenzi/BetterDiscordApp", rel: "author", title: "BandagedBD", target: "_blank"},
// BdApi.React.createElement(BDLogo, {size: "16px", className: "bd-social-logo"})
// ));
// return returnVal;
// };
// children[children.length - 1].type = newOne;
// }});
// }
patchGuildListItems() {
if (this.guildListItemsPatch) return;

View File

@ -1,22 +1,22 @@
import Modules from "./webpackmodules";
import BdApi from "./pluginapi";
const normalizedPrefix = "da";
const randClass = new RegExp(`^(?!${normalizedPrefix}-)((?:[A-Za-z]|[0-9]|-)+)-(?:[A-Za-z]|[0-9]|-|_){6}$`);
export default class ClassNormalizer {
export default new class ClassNormalizer {
get id() {return "fork-ps-4";}
get name() {return "ClassNormalizer";}
stop() {
if (!this.hasPatched) return;
this.unpatchClassModules(Modules.getModules(this.moduleFilter.bind(this)));
this.unpatchClassModules(BdApi.findAllModules(this.moduleFilter.bind(this)));
this.revertElement(document.querySelector("#app-mount"));
this.hasPatched = false;
}
start() {
if (this.hasPatched) return;
this.patchClassModules(Modules.getModules(this.moduleFilter.bind(this)));
this.patchClassModules(BdApi.findAllModules(this.moduleFilter.bind(this)));
this.normalizeElement(document.querySelector("#app-mount"));
this.hasPatched = true;
}
@ -109,4 +109,4 @@ export default class ClassNormalizer {
element.classList.remove(...toRemove);
}
}
};

View File

@ -1,195 +1,194 @@
window.bdthemes = {};
window.bdplugins = {};
var ContentManager = (() => {
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"));
class MetaError extends Error {
constructor(message) {
super(message);
this.name = "MetaError";
import {Config, Plugins, Themes} from "data";
import Utilities from "./utilities";
import PluginManager from "./pluginmanager";
import ThemeManager from "./thememanager";
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"));
class MetaError extends Error {
constructor(message) {
super(message);
this.name = "MetaError";
}
}
const originalJSRequire = Module._extensions[".js"];
const originalCSSRequire = Module._extensions[".css"] ? Module._extensions[".css"] : () => {return null;};
export default new class ContentManager {
constructor() {
this.timeCache = {};
this.watchers = {};
Module._extensions[".js"] = this.getContentRequire("plugin");
Module._extensions[".css"] = this.getContentRequire("theme");
}
get pluginsFolder() {return this._pluginsFolder || (this._pluginsFolder = fs.realpathSync(path.resolve(Config.dataPath + "plugins/")));}
get themesFolder() {return this._themesFolder || (this._themesFolder = fs.realpathSync(path.resolve(Config.dataPath + "themes/")));}
watchContent(contentType) {
if (this.watchers[contentType]) return;
const isPlugin = contentType === "plugin";
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
const fileEnding = isPlugin ? ".plugin.js" : ".theme.css";
this.watchers[contentType] = fs.watch(baseFolder, {persistent: false}, async (eventType, filename) => {
if (!eventType || !filename || !filename.endsWith(fileEnding)) return;
await new Promise(r => setTimeout(r, 50));
try {fs.statSync(path.resolve(baseFolder, filename));}
catch (err) {
if (err.code !== "ENOENT") return;
delete this.timeCache[filename];
if (isPlugin) return PluginManager.unloadPlugin(filename);
return ThemeManager.unloadTheme(filename);
}
if (!fs.statSync(path.resolve(baseFolder, filename)).isFile()) return;
const stats = fs.statSync(path.resolve(baseFolder, filename));
if (!stats || !stats.mtime || !stats.mtime.getTime()) return;
if (typeof(stats.mtime.getTime()) !== "number") return;
if (this.timeCache[filename] == stats.mtime.getTime()) return;
this.timeCache[filename] = stats.mtime.getTime();
if (eventType == "rename") {
if (isPlugin) PluginManager.loadPlugin(filename);
else ThemeManager.loadTheme(filename);
}
if (eventType == "change") {
if (isPlugin) PluginManager.reloadPlugin(filename);
else ThemeManager.reloadTheme(filename);
}
});
}
unwatchContent(contentType) {
if (!this.watchers[contentType]) return;
this.watchers[contentType].close();
delete this.watchers[contentType];
}
extractMeta(content) {
const meta = content.split("\n")[0];
const rawMeta = meta.substring(meta.lastIndexOf("//META") + 6, meta.lastIndexOf("*//"));
if (meta.indexOf("META") < 0) throw new MetaError("META was not found.");
if (!Utilities.testJSON(rawMeta)) throw new MetaError("META could not be parsed.");
const parsed = JSON.parse(rawMeta);
if (!parsed.name) throw new MetaError("META missing name data.");
return parsed;
}
getContentRequire(type) {
const isPlugin = type === "plugin";
const self = this;
const originalRequire = isPlugin ? originalJSRequire : originalCSSRequire;
return function(module, filename) {
const baseFolder = isPlugin ? self.pluginsFolder : self.themesFolder;
const possiblePath = path.resolve(baseFolder, path.basename(filename));
if (!fs.existsSync(possiblePath) || filename !== fs.realpathSync(possiblePath)) return Reflect.apply(originalRequire, this, arguments);
let content = fs.readFileSync(filename, "utf8");
content = Utilities.stripBOM(content);
const meta = self.extractMeta(content);
meta.filename = path.basename(filename);
if (!isPlugin) {
meta.css = content.split("\n").slice(1).join("\n");
content = `module.exports = ${JSON.stringify(meta)};`;
}
if (isPlugin) {
content += `\nmodule.exports = ${JSON.stringify(meta)};\nmodule.exports.type = ${meta.name};`;
}
module._compile(content, filename);
};
}
makePlaceholderPlugin(data) {
return {plugin: {
start: () => {},
getName: () => {return data.name || data.filename;},
getAuthor: () => {return "???";},
getDescription: () => {return data.message ? data.message : "This plugin was unable to be loaded. Check the author's page for updates.";},
getVersion: () => {return "???";}
},
name: data.name || data.filename,
filename: data.filename,
source: data.source ? data.source : "",
website: data.website ? data.website : ""
};
}
loadContent(filename, type) {
if (typeof(filename) === "undefined" || typeof(type) === "undefined") return;
const isPlugin = type === "plugin";
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
try {__non_webpack_require__(path.resolve(baseFolder, filename));}
catch (error) {return {name: filename, file: filename, message: "Could not be compiled.", error: {message: error.message, stack: error.stack}};}
const content = __non_webpack_require__(path.resolve(baseFolder, filename));
if (isPlugin) {
if (!content.type) return;
try {
content.plugin = new content.type();
delete Plugins[content.plugin.getName()];
Plugins[content.plugin.getName()] = content;
}
catch (error) {return {name: filename, file: filename, message: "Could not be constructed.", error: {message: error.message, stack: error.stack}};}
}
else {
delete Themes[content.name];
Themes[content.name] = content;
}
}
const originalJSRequire = Module._extensions[".js"];
const originalCSSRequire = Module._extensions[".css"] ? Module._extensions[".css"] : () => {return null;};
unloadContent(filename, type) {
if (typeof(filename) === "undefined" || typeof(type) === "undefined") return;
const isPlugin = type === "plugin";
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
try {
delete __non_webpack_require__.cache[__non_webpack_require__.resolve(path.resolve(baseFolder, filename))];
}
catch (err) {return {name: filename, file: filename, message: "Could not be unloaded.", error: {message: err.message, stack: err.stack}};}
}
isLoaded(filename, type) {
const isPlugin = type === "plugin";
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
try {__non_webpack_require__.cache[__non_webpack_require__.resolve(path.resolve(baseFolder, filename))];}
catch (err) {return false;}
return true;
}
return new class ContentManager {
reloadContent(filename, type) {
const cantUnload = this.unloadContent(filename, type);
if (cantUnload) return cantUnload;
return this.loadContent(filename, type);
}
constructor() {
this.timeCache = {};
this.watchers = {};
Module._extensions[".js"] = this.getContentRequire("plugin");
Module._extensions[".css"] = this.getContentRequire("theme");
loadNewContent(type) {
const isPlugin = type === "plugin";
const fileEnding = isPlugin ? ".plugin.js" : ".theme.css";
const basedir = isPlugin ? this.pluginsFolder : this.themesFolder;
const files = fs.readdirSync(basedir);
const contentList = Object.values(isPlugin ? Plugins : Themes);
const removed = contentList.filter(t => !files.includes(t.filename)).map(c => isPlugin ? c.plugin.getName() : c.name);
const added = files.filter(f => !contentList.find(t => t.filename == f) && f.endsWith(fileEnding) && fs.statSync(path.resolve(basedir, f)).isFile());
return {added, removed};
}
loadAllContent(type) {
const isPlugin = type === "plugin";
const fileEnding = isPlugin ? ".plugin.js" : ".theme.css";
const basedir = isPlugin ? this.pluginsFolder : this.themesFolder;
const errors = [];
const files = fs.readdirSync(basedir);
for (const filename of files) {
if (!fs.statSync(path.resolve(basedir, filename)).isFile() || !filename.endsWith(fileEnding)) continue;
const error = this.loadContent(filename, type);
if (error) errors.push(error);
}
get pluginsFolder() {return this._pluginsFolder || (this._pluginsFolder = fs.realpathSync(path.resolve(bdConfig.dataPath + "plugins/")));}
get themesFolder() {return this._themesFolder || (this._themesFolder = fs.realpathSync(path.resolve(bdConfig.dataPath + "themes/")));}
return errors;
}
watchContent(contentType) {
if (this.watchers[contentType]) return;
const isPlugin = contentType === "plugin";
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
const fileEnding = isPlugin ? ".plugin.js" : ".theme.css";
this.watchers[contentType] = fs.watch(baseFolder, {persistent: false}, async (eventType, filename) => {
if (!eventType || !filename || !filename.endsWith(fileEnding)) return;
await new Promise(r => setTimeout(r, 50));
try {fs.statSync(path.resolve(baseFolder, filename));}
catch (err) {
if (err.code !== "ENOENT") return;
delete this.timeCache[filename];
if (isPlugin) return pluginModule.unloadPlugin(filename);
return themeModule.unloadTheme(filename);
}
if (!fs.statSync(path.resolve(baseFolder, filename)).isFile()) return;
const stats = fs.statSync(path.resolve(baseFolder, filename));
if (!stats || !stats.mtime || !stats.mtime.getTime()) return;
if (typeof(stats.mtime.getTime()) !== "number") return;
if (this.timeCache[filename] == stats.mtime.getTime()) return;
this.timeCache[filename] = stats.mtime.getTime();
if (eventType == "rename") {
if (isPlugin) pluginModule.loadPlugin(filename);
else themeModule.loadTheme(filename);
}
if (eventType == "change") {
if (isPlugin) pluginModule.reloadPlugin(filename);
else themeModule.reloadTheme(filename);
}
});
}
unwatchContent(contentType) {
if (!this.watchers[contentType]) return;
this.watchers[contentType].close();
delete this.watchers[contentType];
}
extractMeta(content) {
const meta = content.split("\n")[0];
const rawMeta = meta.substring(meta.lastIndexOf("//META") + 6, meta.lastIndexOf("*//"));
if (meta.indexOf("META") < 0) throw new MetaError("META was not found.");
if (!Utils.testJSON(rawMeta)) throw new MetaError("META could not be parsed.");
const parsed = JSON.parse(rawMeta);
if (!parsed.name) throw new MetaError("META missing name data.");
return parsed;
}
getContentRequire(type) {
const isPlugin = type === "plugin";
const self = this;
const originalRequire = isPlugin ? originalJSRequire : originalCSSRequire;
return function(module, filename) {
const baseFolder = isPlugin ? self.pluginsFolder : self.themesFolder;
const possiblePath = path.resolve(baseFolder, path.basename(filename));
if (!fs.existsSync(possiblePath) || filename !== fs.realpathSync(possiblePath)) return Reflect.apply(originalRequire, this, arguments);
let content = fs.readFileSync(filename, "utf8");
content = Utils.stripBOM(content);
const meta = self.extractMeta(content);
meta.filename = path.basename(filename);
if (!isPlugin) {
meta.css = content.split("\n").slice(1).join("\n");
content = `module.exports = ${JSON.stringify(meta)};`;
}
if (isPlugin) {
content += `\nmodule.exports = ${JSON.stringify(meta)};\nmodule.exports.type = ${meta.name};`;
}
module._compile(content, filename);
};
}
makePlaceholderPlugin(data) {
return {plugin: {
start: () => {},
getName: () => {return data.name || data.filename;},
getAuthor: () => {return "???";},
getDescription: () => {return data.message ? data.message : "This plugin was unable to be loaded. Check the author's page for updates.";},
getVersion: () => {return "???";}
},
name: data.name || data.filename,
filename: data.filename,
source: data.source ? data.source : "",
website: data.website ? data.website : ""
};
}
loadContent(filename, type) {
if (typeof(filename) === "undefined" || typeof(type) === "undefined") return;
const isPlugin = type === "plugin";
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
try {__non_webpack_require__(path.resolve(baseFolder, filename));}
catch (error) {return {name: filename, file: filename, message: "Could not be compiled.", error: {message: error.message, stack: error.stack}};}
const content = __non_webpack_require__(path.resolve(baseFolder, filename));
if (isPlugin) {
if (!content.type) return;
try {
content.plugin = new content.type();
delete bdplugins[content.plugin.getName()];
bdplugins[content.plugin.getName()] = content;
}
catch (error) {return {name: filename, file: filename, message: "Could not be constructed.", error: {message: error.message, stack: error.stack}};}
}
else {
delete bdthemes[content.name];
bdthemes[content.name] = content;
}
}
unloadContent(filename, type) {
if (typeof(filename) === "undefined" || typeof(type) === "undefined") return;
const isPlugin = type === "plugin";
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
try {
delete __non_webpack_require__.cache[__non_webpack_require__.resolve(path.resolve(baseFolder, filename))];
}
catch (err) {return {name: filename, file: filename, message: "Could not be unloaded.", error: {message: err.message, stack: err.stack}};}
}
isLoaded(filename, type) {
const isPlugin = type === "plugin";
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
try {__non_webpack_require__.cache[__non_webpack_require__.resolve(path.resolve(baseFolder, filename))];}
catch (err) {return false;}
return true;
}
reloadContent(filename, type) {
const cantUnload = this.unloadContent(filename, type);
if (cantUnload) return cantUnload;
return this.loadContent(filename, type);
}
loadNewContent(type) {
const isPlugin = type === "plugin";
const fileEnding = isPlugin ? ".plugin.js" : ".theme.css";
const basedir = isPlugin ? this.pluginsFolder : this.themesFolder;
const files = fs.readdirSync(basedir);
const contentList = Object.values(isPlugin ? bdplugins : bdthemes);
const removed = contentList.filter(t => !files.includes(t.filename)).map(c => isPlugin ? c.plugin.getName() : c.name);
const added = files.filter(f => !contentList.find(t => t.filename == f) && f.endsWith(fileEnding) && fs.statSync(path.resolve(basedir, f)).isFile());
return {added, removed};
}
loadAllContent(type) {
const isPlugin = type === "plugin";
const fileEnding = isPlugin ? ".plugin.js" : ".theme.css";
const basedir = isPlugin ? this.pluginsFolder : this.themesFolder;
const errors = [];
const files = fs.readdirSync(basedir);
for (const filename of files) {
if (!fs.statSync(path.resolve(basedir, filename)).isFile() || !filename.endsWith(fileEnding)) continue;
const error = this.loadContent(filename, type);
if (error) errors.push(error);
}
return errors;
}
loadPlugins() {return this.loadAllContent("plugin");}
loadThemes() {return this.loadAllContent("theme");}
};
})();
loadPlugins() {return this.loadAllContent("plugin");}
loadThemes() {return this.loadAllContent("theme");}
};

View File

@ -1,73 +1,67 @@
import Utilties from "./utilities";
import Config from "../data/config";
import Settings from "../data/settingscookie";
import BDV2 from "./bdv2";
import Utilties from "./utilities";
import {Config, SettingsCookie} from "data";
import EmoteModule from "./emotes";
import QuickEmoteMenu from "./emotemenu";
import VoiceMode from "./voicemode";
import DevMode from "./devmode";
import PluginModule from "./pluginmanager";
import ThemeModule from "./thememanager";
// import VoiceMode from "./voicemode";
// import DevMode from "./devmode";
import PluginManager from "./pluginmanager";
import ThemeManager from "./thememanager";
import DataStore from "./datastore";
import {PublicServers, SettingsPanel} from "ui";
import PublicServers from "./publicservers";
import SettingsPanel from "./settingspanel";
function Core(config) {
Object.assign(Config, config);
function Core() {
}
Core.prototype.setConfig = function(config) {
Object.assign(Config, config);
};
Core.prototype.init = async function() {
if (Config.version < Config.minSupportedVersion) {
this.alert("Not Supported", "BetterDiscord v" + Config.version + " (your version)" + " is not supported by the latest js (" + Config.bbdVersion + ").<br><br> Please download the latest version from <a href='https://github.com/rauenzi/BetterDiscordApp/releases/latest' target='_blank'>GitHub</a>");
return;
}
if (Config.updater.LatestVersion > Config.version) {
const latestLocalVersion = Config.updater ? Config.updater.LatestVersion : Config.latestVersion;
if (latestLocalVersion > Config.version) {
this.alert("Update Available", `
An update for BandagedBD is available (${Config.updater.LatestVersion})! Please Reinstall!<br /><br />
An update for BandagedBD is available (${latestLocalVersion})! Please Reinstall!<br /><br />
<a href='https://github.com/rauenzi/BetterDiscordApp/releases/latest' target='_blank'>Download Installer</a>
`);
}
Utilties.log("Startup", "Initializing Settings");
this.initSettings();
this.emoteModule = new EmoteModule();
this.quickEmoteMenu = new QuickEmoteMenu();
Utilties.log("Startup", "Initializing EmoteModule");
window.emotePromise = this.emoteModule.init().then(() => {
this.emoteModule.initialized = true;
window.emotePromise = EmoteModule.init().then(() => {
EmoteModule.initialized = true;
Utilties.log("Startup", "Initializing QuickEmoteMenu");
this.quickEmoteMenu.init();
QuickEmoteMenu.init();
});
this.publicServersModule = new PublicServers();
this.voiceMode = new VoiceMode();
this.dMode = new DevMode();
this.injectExternals();
await this.checkForGuilds();
BDV2.initialize();
Utilties.log("Startup", "Updating Settings");
this.settingsPanel = new SettingsPanel();
this.settingsPanel.initializeSettings();
SettingsPanel.initializeSettings();
Utilties.log("Startup", "Loading Plugins");
this.pluginModule = new PluginModule();
const pluginErrors = this.pluginModule.loadPlugins();
const pluginErrors = PluginManager.loadPlugins();
Utilties.log("Startup", "Loading Themes");
this.themeModule = new ThemeModule();
const themeErrors = this.themeModule.loadThemes();
const themeErrors = ThemeManager.loadThemes();
$("#customcss").detach().appendTo(document.head);
window.addEventListener("beforeunload", function() {
if (Settings["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click();
if (SettingsCookie["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click();
});
this.publicServersModule.initialize();
this.emoteModule.autoCapitalize();
PublicServers.initialize();
EmoteModule.autoCapitalize();
Utilties.log("Startup", "Removing Loading Icon");
document.getElementsByClassName("bd-loaderv2")[0].remove();
@ -75,7 +69,7 @@ Core.prototype.init = async function() {
this.initObserver();
// Show loading errors
if (Settings["fork-ps-1"]) {
if (SettingsCookie["fork-ps-1"]) {
Utilties.log("Startup", "Collecting Startup Errors");
this.showContentErrors({plugins: pluginErrors, themes: themeErrors});
}
@ -112,18 +106,18 @@ Core.prototype.initSettings = function () {
const savedSettings = this.loadSettings();
$("<style id=\"customcss\">").text(atob(DataStore.getBDData("bdcustomcss"))).appendTo(document.head);
for (const setting in savedSettings) {
if (savedSettings[setting] !== undefined) Settings[setting] = savedSettings[setting];
if (savedSettings[setting] !== undefined) SettingsCookie[setting] = savedSettings[setting];
}
this.saveSettings();
};
Core.prototype.saveSettings = function () {
DataStore.setSettingGroup("settings", Settings);
DataStore.setSettingGroup("settings", SettingsCookie);
};
Core.prototype.loadSettings = function () {
Settings = DataStore.getSettingGroup("settings");
return DataStore.getSettingGroup("settings");
};
Core.prototype.initObserver = function () {
@ -131,7 +125,7 @@ Core.prototype.initObserver = function () {
for (let i = 0, mlen = mutations.length; i < mlen; i++) {
let mutation = mutations[i];
if (typeof pluginModule !== "undefined") this.pluginModule.rawObserver(mutation);
if (typeof PluginManager !== "undefined") PluginManager.rawObserver(mutation);
// if there was nothing added, skip
if (!mutation.addedNodes.length || !(mutation.addedNodes[0] instanceof Element)) continue;
@ -144,12 +138,12 @@ Core.prototype.initObserver = function () {
if (node.getElementsByClassName("socialLinks-3jqNFy").length) {
node.setAttribute("layer-id", "user-settings");
node.setAttribute("id", "user-settings");
if (!document.getElementById("bd-settings-sidebar")) this.settingsPanel.renderSidebar();
if (!document.getElementById("bd-settings-sidebar")) SettingsPanel.renderSidebar();
}
}
// Emoji Picker
if (node.classList.contains("popout-3sVMXz") && !node.classList.contains("popoutLeft-30WmrD") && node.getElementsByClassName("emojiPicker-3m1S-j").length) this.quickEmoteMenu.obsCallback(node);
if (node.classList.contains("popout-3sVMXz") && !node.classList.contains("popoutLeft-30WmrD") && node.getElementsByClassName("emojiPicker-3m1S-j").length) QuickEmoteMenu.obsCallback(node);
}
});
@ -165,7 +159,7 @@ Core.prototype.inject24Hour = function() {
const twelveHour = new RegExp(`([0-9]{1,2}):([0-9]{1,2})\\s(AM|PM)`);
const convert = (data) => {
if (!Settings["bda-gs-6"]) return;
if (!SettingsCookie["bda-gs-6"]) return;
const matched = data.returnValue.match(twelveHour);
if (!matched || matched.length !== 4) return;
if (matched[3] === "AM") return data.returnValue = data.returnValue.replace(matched[0], `${matched[1] === "12" ? "00" : matched[1].padStart(2, "0")}:${matched[2]}`);
@ -182,7 +176,7 @@ Core.prototype.injectColoredText = function() {
if (this.cancelColoredText) return;
this.cancelColoredText = Utilties.monkeyPatch(BDV2.MessageContentComponent.prototype, "render", {after: (data) => {
if (!Settings["bda-gs-7"]) return;
if (!SettingsCookie["bda-gs-7"]) return;
Utilties.monkeyPatch(data.returnValue.props, "children", {silent: true, after: ({returnValue}) => {
const markup = returnValue.props.children[1];
const roleColor = data.thisObject.props.message.colorString;
@ -341,4 +335,4 @@ Core.prototype.showToast = function(content, options = {}) {
};
export default Core;
export default new Core();

View File

@ -1,10 +1,10 @@
import Config from "../data/config";
import {Config} from "data";
import BdApi from "./pluginapi";
const fs = require("fs");
const path = require("path");
const releaseChannel = DiscordNative.globals.releaseChannel;
export default class DataStore {
export default new class DataStore {
constructor() {
this.data = {settings: {stable: {}, canary: {}, ptb: {}}};
this.pluginData = {};
@ -68,4 +68,4 @@ export default class DataStore {
delete this.pluginData[pluginName][key];
fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4));
}
}
};

View File

@ -81,4 +81,4 @@ devMode.prototype.getSelector = function(element) {
$(document).off("contextmenu.bdDevModeCtx");
};
export default devMode;
export default new devMode();

View File

@ -1,4 +1,4 @@
import Settings from "../data/settingscookie";
import {SettingsCookie} from "data";
import DataStore from "./datastore";
import Utilities from "./utilities";
@ -130,14 +130,14 @@ QuickEmoteMenu.prototype.switchQem = function(id) {
QuickEmoteMenu.prototype.obsCallback = function (elem) {
if (!this.initialized) return;
var e = $(elem);
if (!Settings["bda-es-9"]) {
if (!SettingsCookie["bda-es-9"]) {
e.addClass("bda-qme-hidden");
}
else {
e.removeClass("bda-qme-hidden");
}
if (!Settings["bda-es-0"]) return;
if (!SettingsCookie["bda-es-0"]) return;
e.prepend(this.qmeHeader);
e.append(this.teContainer);
@ -182,4 +182,4 @@ QuickEmoteMenu.prototype.updateFavorites = function () {
DataStore.setBDData("bdfavemotes", btoa(JSON.stringify(this.favoriteEmotes)));
};
export default QuickEmoteMenu;
export default new QuickEmoteMenu();

View File

@ -1,5 +1,4 @@
import Config from "../data/config";
import Settings from "../data/settingscookie";
import {Config, SettingsCookie} from "data";
import Utilities from "./utilities";
import BDV2 from "./bdv2";
import BDEmote from "../ui/emote";
@ -33,7 +32,7 @@ function EmoteModule() {
get: function() {
const cats = [];
for (const current in window.bdEmoteSettingIDs) {
if (Settings[window.bdEmoteSettingIDs[current]]) cats.push(current);
if (SettingsCookie[window.bdEmoteSettingIDs[current]]) cats.push(current);
}
return cats;
}
@ -117,7 +116,7 @@ EmoteModule.prototype.init = async function () {
let emoteOverride = emoteModifier.slice(0);
if (emoteName.length < 4 || bemotes.includes(emoteName)) continue;
if (!this.modifiers.includes(emoteModifier) || !Settings["bda-es-8"]) emoteModifier = "";
if (!this.modifiers.includes(emoteModifier) || !SettingsCookie["bda-es-8"]) emoteModifier = "";
if (!this.overrides.includes(emoteOverride)) emoteOverride = "";
else emoteModifier = emoteOverride;
@ -134,7 +133,7 @@ EmoteModule.prototype.init = async function () {
if (window.bdEmotes.FrankerFaceZ[emoteName]) current = "FrankerFaceZ";
}
if (!window.bdEmotes[current][emoteName] || !Settings[window.bdEmoteSettingIDs[current]]) continue;
if (!window.bdEmotes[current][emoteName] || !SettingsCookie[window.bdEmoteSettingIDs[current]]) continue;
const results = nodes[n].match(new RegExp(`([\\s]|^)${Utilities.escape(emoteModifier ? emoteName + ":" + emoteModifier : emoteName)}([\\s]|$)`));
if (!results) continue;
const pre = nodes[n].substring(0, results.index + results[1].length);
@ -196,10 +195,11 @@ EmoteModule.prototype.goBack = async function(emoteInfo) {
};
EmoteModule.prototype.isCacheValid = function() {
const cacheLength = DataStore.getBDData("emoteCacheDays") || DataStore.setBDData("emoteCacheDays", 7) || 7;
const cacheDate = new Date(DataStore.getBDData("emoteCacheDate") || null);
const currentDate = new Date();
const daysBetween = Math.round(Math.abs((currentDate.getTime() - cacheDate.getTime()) / (24 * 60 * 60 * 1000)));
if (daysBetween > Config.cache.days) {
if (daysBetween > cacheLength) {
DataStore.setBDData("emoteCacheDate", currentDate.toJSON());
return false;
}
@ -213,7 +213,7 @@ EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
const exists = _fs.existsSync(file);
if (exists && this.isCacheValid()) {
if (Settings["fork-ps-2"]) BdApi.showToast("Loading emotes from cache.", {type: "info"});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast("Loading emotes from cache.", {type: "info"});
Utilities.log("Emotes", "Loading emotes from local cache.");
const data = await new Promise(resolve => {
@ -232,7 +232,7 @@ EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
}
if (isValid) {
if (Settings["fork-ps-2"]) BdApi.showToast("Emotes successfully loaded.", {type: "success"});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast("Emotes successfully loaded.", {type: "success"});
return;
}
@ -240,8 +240,8 @@ EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
_fs.unlinkSync(file);
}
if (!Settings["fork-es-3"]) return;
if (Settings["fork-ps-2"]) BdApi.showToast("Downloading emotes in the background do not reload.", {type: "info"});
if (!SettingsCookie["fork-es-3"]) return;
if (SettingsCookie["fork-ps-2"]) BdApi.showToast("Downloading emotes in the background do not reload.", {type: "info"});
for (let e in emoteInfo) {
await new Promise(r => setTimeout(r, 1000));
@ -249,7 +249,7 @@ EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
window.bdEmotes[emoteInfo[e].variable] = data;
}
if (Settings["fork-ps-2"]) BdApi.showToast("All emotes successfully downloaded.", {type: "success"});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast("All emotes successfully downloaded.", {type: "success"});
try { _fs.writeFileSync(file, JSON.stringify(window.bdEmotes), "utf8"); }
catch (err) { Utilities.err("Emotes", "Could not save emote data.", err); }
@ -317,7 +317,7 @@ EmoteModule.prototype.getBlacklist = function () {
var bemotes = [];
EmoteModule.prototype.autoCapitalize = function () {
if (!Settings["bda-es-4"] || this.autoCapitalizeActive) return;
if (!SettingsCookie["bda-es-4"] || this.autoCapitalizeActive) return;
$("body").on("keyup.bdac change.bdac paste.bdac", $(".channelTextArea-1LDbYG textarea:first"), () => {
var text = $(".channelTextArea-1LDbYG textarea:first").val();
if (text == undefined) return;
@ -348,4 +348,4 @@ EmoteModule.prototype.disableAutoCapitalize = function() {
$("body").off(".bdac");
};
export default EmoteModule;
export default new EmoteModule();

View File

@ -1,9 +1,19 @@
import BDV2 from "./bdv2";
import Utilities from "./utilities";
import BdApi from "./pluginapi";
import Core from "./core";
import ClassNormalizer from "./classnormalizer";
import ContentManager from "./contentmanager";
import Emitter from "./emitter";
import DataStore from "./datastore";
import DevMode from "./devmode";
import Emitter from "./emitter";
import EmoteMenu from "./emotemenu";
import EmoteModule from "./emotes";
import PluginManager from "./pluginmanager";
import PublicServer from "./publicservers";
import ThemeManager from "./thememanager";
import VoiceMode from "./voicemode";
import Utilities from "./utilities";
export {BDV2, Utilities, BdApi, ClassNormalizer, ContentManager, Emitter, DataStore};
export {BDV2, BdApi, Core, ClassNormalizer, ContentManager, DataStore, DevMode,
Emitter, EmoteMenu, EmoteModule, PluginManager, PublicServer, ThemeManager,
VoiceMode, Utilities};

View File

@ -1,7 +1,8 @@
import Config from "../data/config";
import {Config, Plugins, SettingsCookie, PluginCookie, ThemeCookie} from "data";
import Utilities from "./utilities";
import BDV2 from "./bdv2";
import DataStore from "./datastore";
import Core from "./core";
const BdApi = {
get React() { return BDV2.react; },
@ -66,22 +67,16 @@ BdApi.unlinkJS = function (id) {
//Get another plugin
//name = name of plugin
BdApi.getPlugin = function (name) {
if (bdplugins.hasOwnProperty(name)) {
return bdplugins[name].plugin;
if (Plugins.hasOwnProperty(name)) {
return Plugins[name].plugin;
}
return null;
};
var betterDiscordIPC = require("electron").ipcRenderer;
//Get ipc for reason
BdApi.getIpc = function () {
Utilities.warn("Deprecation Notice", "BetterDiscord's IPC has been deprecated and may be removed in future versions.");
return betterDiscordIPC;
};
//Get BetterDiscord Core
BdApi.getCore = function () {
return window.mainCore;
return Core;
};
/**
@ -92,7 +87,7 @@ BdApi.getCore = function () {
BdApi.alert = function (title, content) {
const ModalStack = BdApi.findModuleByProps("push", "update", "pop", "popWithKey");
const AlertModal = BdApi.findModuleByPrototypes("handleCancel", "handleSubmit", "handleMinorConfirm");
if (!ModalStack || !AlertModal) return window.mainCore.alert(title, content);
if (!ModalStack || !AlertModal) return Core.alert(title, content);
ModalStack.push(function(props) {
return BdApi.React.createElement(AlertModal, Object.assign({
@ -117,7 +112,7 @@ BdApi.showConfirmationModal = function (title, content, options = {}) {
const ModalStack = BdApi.findModuleByProps("push", "update", "pop", "popWithKey");
const TextElement = BdApi.findModuleByProps("Sizes", "Weights");
const ConfirmationModal = BdApi.findModule(m => m.defaultProps && m.key && m.key() == "confirm-modal");
if (!ModalStack || !ConfirmationModal || !TextElement) return window.mainCore.alert(title, content);
if (!ModalStack || !ConfirmationModal || !TextElement) return Core.alert(title, content);
const {onConfirm, onCancel, confirmText, cancelText, danger = false} = options;
if (typeof(content) == "string") content = TextElement({color: TextElement.Colors.PRIMARY, children: [content]});
@ -140,7 +135,7 @@ BdApi.showConfirmationModal = function (title, content, options = {}) {
//Show toast alert
BdApi.showToast = function(content, options = {}) {
window.mainCore.showToast(content, options);
Core.showToast(content, options);
};
// Finds module
@ -212,17 +207,17 @@ BdApi.testJSON = function(data) {
return Utilities.testJSON(data);
};
// BdApi.isPluginEnabled = function(name) {
// return !!pluginCookie[name];
// };
BdApi.isPluginEnabled = function(name) {
return !!PluginCookie[name];
};
// BdApi.isThemeEnabled = function(name) {
// return !!themeCookie[name];
// };
BdApi.isThemeEnabled = function(name) {
return !!ThemeCookie[name];
};
// BdApi.isSettingEnabled = function(id) {
// return !!settingsCookie[id];
// };
BdApi.isSettingEnabled = function(id) {
return !!SettingsCookie[id];
};
// Gets data
BdApi.getBDData = function(key) {

View File

@ -1,4 +1,10 @@
var pluginCookie = {};
import {SettingsCookie, PluginCookie, Plugins} from "data";
import ContentManager from "./contentmanager";
import Utilities from "./utilities";
import Core from "./core";
import BdApi from "./pluginapi";
import Emitter from "./emitter";
import DataStore from "./datastore";
function PluginModule() {
@ -7,135 +13,135 @@ function PluginModule() {
PluginModule.prototype.loadPlugins = function () {
this.loadPluginData();
const errors = ContentManager.loadPlugins();
var plugins = Object.keys(bdplugins);
var plugins = Object.keys(Plugins);
for (var i = 0; i < plugins.length; i++) {
var plugin, name;
try {
plugin = bdplugins[plugins[i]].plugin;
plugin = Plugins[plugins[i]].plugin;
name = plugin.getName();
if (plugin.load && typeof(plugin.load) == "function") plugin.load();
}
catch (err) {
pluginCookie[name] = false;
Utils.err("Plugins", name + " could not be loaded.", err);
errors.push({name: name, file: bdplugins[plugins[i]].filename, message: "load() could not be fired.", error: {message: err.message, stack: err.stack}});
PluginCookie[name] = false;
Utilities.err("Plugins", name + " could not be loaded.", err);
errors.push({name: name, file: Plugins[plugins[i]].filename, message: "load() could not be fired.", error: {message: err.message, stack: err.stack}});
continue;
}
if (!pluginCookie[name]) pluginCookie[name] = false;
if (!PluginCookie[name]) PluginCookie[name] = false;
if (pluginCookie[name]) {
if (PluginCookie[name]) {
try {
plugin.start();
if (settingsCookie["fork-ps-2"]) mainCore.showToast(`${plugin.getName()} v${plugin.getVersion()} has started.`);
if (SettingsCookie["fork-ps-2"]) Core.showToast(`${plugin.getName()} v${plugin.getVersion()} has started.`);
}
catch (err) {
pluginCookie[name] = false;
Utils.err("Plugins", name + " could not be started.", err);
errors.push({name: name, file: bdplugins[plugins[i]].filename, message: "start() could not be fired.", error: {message: err.message, stack: err.stack}});
PluginCookie[name] = false;
Utilities.err("Plugins", name + " could not be started.", err);
errors.push({name: name, file: Plugins[plugins[i]].filename, message: "start() could not be fired.", error: {message: err.message, stack: err.stack}});
}
}
}
this.savePluginData();
require("electron").remote.getCurrentWebContents().on("did-navigate-in-page", this.channelSwitch.bind(this));
// if (settingsCookie["fork-ps-5"]) ContentManager.watchContent("plugin");
// if (SettingsCookie["fork-ps-5"]) ContentManager.watchContent("plugin");
return errors;
};
PluginModule.prototype.startPlugin = function(plugin, reload = false) {
try {
bdplugins[plugin].plugin.start();
if (settingsCookie["fork-ps-2"] && !reload) mainCore.showToast(`${bdplugins[plugin].plugin.getName()} v${bdplugins[plugin].plugin.getVersion()} has started.`);
Plugins[plugin].plugin.start();
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} has started.`);
}
catch (err) {
if (settingsCookie["fork-ps-2"] && !reload) mainCore.showToast(`${bdplugins[plugin].plugin.getName()} v${bdplugins[plugin].plugin.getVersion()} could not be started.`, {type: "error"});
pluginCookie[plugin] = false;
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} could not be started.`, {type: "error"});
PluginCookie[plugin] = false;
this.savePluginData();
Utils.err("Plugins", name + " could not be started.", err);
Utilities.err("Plugins", name + " could not be started.", err);
}
};
PluginModule.prototype.stopPlugin = function(plugin, reload = false) {
try {
bdplugins[plugin].plugin.stop();
if (settingsCookie["fork-ps-2"] && !reload) mainCore.showToast(`${bdplugins[plugin].plugin.getName()} v${bdplugins[plugin].plugin.getVersion()} has stopped.`);
Plugins[plugin].plugin.stop();
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} has stopped.`);
}
catch (err) {
if (settingsCookie["fork-ps-2"] && !reload) mainCore.showToast(`${bdplugins[plugin].plugin.getName()} v${bdplugins[plugin].plugin.getVersion()} could not be stopped.`, {type: "error"});
Utils.err("Plugins", bdplugins[plugin].plugin.getName() + " could not be stopped.", err);
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} could not be stopped.`, {type: "error"});
Utilities.err("Plugins", Plugins[plugin].plugin.getName() + " could not be stopped.", err);
}
};
PluginModule.prototype.enablePlugin = function (plugin, reload = false) {
if (pluginCookie[plugin]) return;
pluginCookie[plugin] = true;
if (PluginCookie[plugin]) return;
PluginCookie[plugin] = true;
this.savePluginData();
this.startPlugin(plugin, reload);
};
PluginModule.prototype.disablePlugin = function (plugin, reload = false) {
if (!pluginCookie[plugin]) return;
pluginCookie[plugin] = false;
if (!PluginCookie[plugin]) return;
PluginCookie[plugin] = false;
this.savePluginData();
this.stopPlugin(plugin, reload);
};
PluginModule.prototype.togglePlugin = function (plugin) {
if (pluginCookie[plugin]) this.disablePlugin(plugin);
if (PluginCookie[plugin]) this.disablePlugin(plugin);
else this.enablePlugin(plugin);
};
PluginModule.prototype.loadPlugin = function(filename) {
const error = ContentManager.loadContent(filename, "plugin");
if (error) {
if (settingsCookie["fork-ps-1"]) mainCore.showContentErrors({plugins: [error]});
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${filename} could not be loaded.`, {type: "error"});
return Utils.err("ContentManager", `${filename} could not be loaded.`, error);
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({plugins: [error]});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${filename} could not be loaded.`, {type: "error"});
return Utilities.err("ContentManager", `${filename} could not be loaded.`, error);
}
const plugin = Object.values(bdplugins).find(p => p.filename == filename).plugin;
const plugin = Object.values(Plugins).find(p => p.filename == filename).plugin;
try { if (plugin.load && typeof(plugin.load) == "function") plugin.load();}
catch (err) {if (settingsCookie["fork-ps-1"]) mainCore.showContentErrors({plugins: [err]});}
Utils.log("ContentManager", `${plugin.getName()} v${plugin.getVersion()} was loaded.`);
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin.getName()} v${plugin.getVersion()} was loaded.`, {type: "success"});
BDEvents.dispatch("plugin-loaded", plugin.getName());
catch (err) {if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({plugins: [err]});}
Utilities.log("ContentManager", `${plugin.getName()} v${plugin.getVersion()} was loaded.`);
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin.getName()} v${plugin.getVersion()} was loaded.`, {type: "success"});
Emitter.dispatch("plugin-loaded", plugin.getName());
};
PluginModule.prototype.unloadPlugin = function(filenameOrName) {
const bdplugin = Object.values(bdplugins).find(p => p.filename == filenameOrName) || bdplugins[filenameOrName];
const bdplugin = Object.values(Plugins).find(p => p.filename == filenameOrName) || Plugins[filenameOrName];
if (!bdplugin) return;
const plugin = bdplugin.plugin.getName();
if (pluginCookie[plugin]) this.disablePlugin(plugin, true);
const error = ContentManager.unloadContent(bdplugins[plugin].filename, "plugin");
delete bdplugins[plugin];
if (PluginCookie[plugin]) this.disablePlugin(plugin, true);
const error = ContentManager.unloadContent(Plugins[plugin].filename, "plugin");
delete Plugins[plugin];
if (error) {
if (settingsCookie["fork-ps-1"]) mainCore.showContentErrors({plugins: [error]});
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
return Utils.err("ContentManager", `${plugin} could not be unloaded. It may have not been loaded yet.`, error);
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({plugins: [error]});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
return Utilities.err("ContentManager", `${plugin} could not be unloaded. It may have not been loaded yet.`, error);
}
Utils.log("ContentManager", `${plugin} was unloaded.`);
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} was unloaded.`, {type: "success"});
BDEvents.dispatch("plugin-unloaded", plugin);
Utilities.log("ContentManager", `${plugin} was unloaded.`);
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} was unloaded.`, {type: "success"});
Emitter.dispatch("plugin-unloaded", plugin);
};
PluginModule.prototype.reloadPlugin = function(filenameOrName) {
const bdplugin = Object.values(bdplugins).find(p => p.filename == filenameOrName) || bdplugins[filenameOrName];
const bdplugin = Object.values(Plugins).find(p => p.filename == filenameOrName) || Plugins[filenameOrName];
if (!bdplugin) return this.loadPlugin(filenameOrName);
const plugin = bdplugin.plugin.getName();
const enabled = pluginCookie[plugin];
const enabled = PluginCookie[plugin];
if (enabled) this.stopPlugin(plugin, true);
const error = ContentManager.reloadContent(bdplugins[plugin].filename, "plugin");
const error = ContentManager.reloadContent(Plugins[plugin].filename, "plugin");
if (error) {
if (settingsCookie["fork-ps-1"]) mainCore.showContentErrors({plugins: [error]});
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} could not be reloaded.`, {type: "error"});
return Utils.err("ContentManager", `${plugin} could not be reloaded.`, error);
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({plugins: [error]});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} could not be reloaded.`, {type: "error"});
return Utilities.err("ContentManager", `${plugin} could not be reloaded.`, error);
}
if (bdplugins[plugin].plugin.load && typeof(bdplugins[plugin].plugin.load) == "function") bdplugins[plugin].plugin.load();
if (Plugins[plugin].plugin.load && typeof(Plugins[plugin].plugin.load) == "function") Plugins[plugin].plugin.load();
if (enabled) this.startPlugin(plugin, true);
Utils.log("ContentManager", `${plugin} v${bdplugins[plugin].plugin.getVersion()} was reloaded.`);
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} v${bdplugins[plugin].plugin.getVersion()} was reloaded.`, {type: "success"});
BDEvents.dispatch("plugin-reloaded", plugin);
Utilities.log("ContentManager", `${plugin} v${Plugins[plugin].plugin.getVersion()} was reloaded.`);
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} v${Plugins[plugin].plugin.getVersion()} was reloaded.`, {type: "success"});
Emitter.dispatch("plugin-reloaded", plugin);
};
PluginModule.prototype.updatePluginList = function() {
@ -145,50 +151,49 @@ PluginModule.prototype.updatePluginList = function() {
};
PluginModule.prototype.loadPluginData = function () {
let saved = DataStore.getSettingGroup("plugins");
if (saved) {
pluginCookie = saved;
}
const saved = DataStore.getSettingGroup("plugins");
if (!saved) return;
Object.assign(PluginCookie, saved);
};
PluginModule.prototype.savePluginData = function () {
DataStore.setSettingGroup("plugins", pluginCookie);
DataStore.setSettingGroup("plugins", PluginCookie);
};
PluginModule.prototype.newMessage = function () {
var plugins = Object.keys(bdplugins);
var plugins = Object.keys(Plugins);
for (var i = 0; i < plugins.length; i++) {
var plugin = bdplugins[plugins[i]].plugin;
if (!pluginCookie[plugin.getName()]) continue;
var plugin = Plugins[plugins[i]].plugin;
if (!PluginCookie[plugin.getName()]) continue;
if (typeof plugin.onMessage === "function") {
try { plugin.onMessage(); }
catch (err) { Utils.err("Plugins", "Unable to fire onMessage for " + plugin.getName() + ".", err); }
catch (err) { Utilities.err("Plugins", "Unable to fire onMessage for " + plugin.getName() + ".", err); }
}
}
};
PluginModule.prototype.channelSwitch = function () {
var plugins = Object.keys(bdplugins);
var plugins = Object.keys(Plugins);
for (var i = 0; i < plugins.length; i++) {
var plugin = bdplugins[plugins[i]].plugin;
if (!pluginCookie[plugin.getName()]) continue;
var plugin = Plugins[plugins[i]].plugin;
if (!PluginCookie[plugin.getName()]) continue;
if (typeof plugin.onSwitch === "function") {
try { plugin.onSwitch(); }
catch (err) { Utils.err("Plugins", "Unable to fire onSwitch for " + plugin.getName() + ".", err); }
catch (err) { Utilities.err("Plugins", "Unable to fire onSwitch for " + plugin.getName() + ".", err); }
}
}
};
PluginModule.prototype.rawObserver = function(e) {
var plugins = Object.keys(bdplugins);
var plugins = Object.keys(Plugins);
for (var i = 0; i < plugins.length; i++) {
var plugin = bdplugins[plugins[i]].plugin;
if (!pluginCookie[plugin.getName()]) continue;
var plugin = Plugins[plugins[i]].plugin;
if (!PluginCookie[plugin.getName()]) continue;
if (typeof plugin.observer === "function") {
try { plugin.observer(e); }
catch (err) { Utils.err("Plugins", "Unable to fire observer for " + plugin.getName() + ".", err); }
catch (err) { Utilities.err("Plugins", "Unable to fire observer for " + plugin.getName() + ".", err); }
}
}
};
export default PluginModule;
export default new PluginModule();

View File

@ -0,0 +1,62 @@
import {SettingsCookie} from "data";
import {BDV2} from "modules";
import {PublicServers} from "ui";
export default new class {
initialize() {
const wrapper = BDV2.guildClasses.wrapper.split(" ")[0];
const guilds = $(`.${wrapper} .scroller-2FKFPG >:first-child`);
guilds.after(this.button);
}
get component() {
return BDV2.react.createElement(PublicServers.Layer, {
rootId: "pubslayerroot",
id: "pubslayer",
children: BDV2.react.createElement(PublicServers.Menu, {rootId: "pubslayerroot"})
});
}
get root() {
let _root = document.getElementById("pubslayerroot");
if (!_root) {
if (!this.injectRoot()) return null;
return this.root;
}
return _root;
}
injectRoot() {
if (!$(".layers, .layers-3iHuyZ").length) return false;
$(".layers, .layers-3iHuyZ").append($("<div/>", {
id: "pubslayerroot"
}));
return true;
}
render() {
// BdApi.alert("Broken", "Sorry but the Public Servers modules is currently broken, I recommend disabling this feature for now.");
let root = this.root;
if (!root) {
console.log("FAILED TO LOCATE ROOT: .layers");
return;
}
BDV2.reactDom.render(this.component, root);
}
get button() {
let btn = $("<div/>", {
"class": BDV2.guildClasses.listItem,
"id": "bd-pub-li",
"style": SettingsCookie["bda-gs-1"] ? "" : "display: none;"
}).append($("<div/>", {
"class": "wrapper-25eVIn " + BDV2.guildClasses.circleButtonMask,
"text": "public",
"id": "bd-pub-button",
"click": () => { this.render(); }
}));
return btn;
}
};

View File

@ -0,0 +1,125 @@
import {SettingsCookie} from "data";
import ClassNormalizer from "./classnormalizer";
import ContentManager from "./contentmanager";
import BdApi from "./pluginapi";
import Core from "./core";
import VoiceMode from "./voicemode";
import EmoteModule from "./emotes";
import DevMode from "./devmode";
import {SettingsPanel as SettingsRenderer} from "ui";
export default new class SettingsPanel {
constructor() {
this.renderer = new SettingsRenderer({onChange: this.updateSettings.bind(this)});
}
renderSidebar() {
this.renderer.renderSidebar();
}
updateSettings(id, enabled) {
SettingsCookie[id] = enabled;
if (id == "bda-es-0") {
if (enabled) $("#twitchcord-button-container").show();
else $("#twitchcord-button-container").hide();
}
if (id == "bda-gs-2") {
if (enabled) $("body").addClass("bd-minimal");
else $("body").removeClass("bd-minimal");
}
if (id == "bda-gs-3") {
if (enabled) $("body").addClass("bd-minimal-chan");
else $("body").removeClass("bd-minimal-chan");
}
if (id == "bda-gs-1") {
if (enabled) $("#bd-pub-li").show();
else $("#bd-pub-li").hide();
}
if (id == "bda-gs-4") {
if (enabled) VoiceMode.enable();
else VoiceMode.disable();
}
if (id == "bda-gs-5") {
if (enabled) $("#app-mount").addClass("bda-dark");
else $("#app-mount").removeClass("bda-dark");
}
if (enabled && id == "bda-gs-6") Core.inject24Hour();
if (id == "bda-gs-7") {
if (enabled) Core.injectColoredText();
else Core.removeColoredText();
}
if (id == "bda-es-4") {
if (enabled) EmoteModule.autoCapitalize();
else EmoteModule.disableAutoCapitalize();
}
if (id == "fork-ps-4") {
if (enabled) ClassNormalizer.start();
else ClassNormalizer.stop();
}
if (id == "fork-ps-5") {
if (enabled) {
ContentManager.watchContent("plugin");
ContentManager.watchContent("theme");
}
else {
ContentManager.unwatchContent("plugin");
ContentManager.unwatchContent("theme");
}
}
if (id == "fork-wp-1") {
BdApi.setWindowPreference("transparent", enabled);
if (enabled) BdApi.setWindowPreference("backgroundColor", null);
else BdApi.setWindowPreference("backgroundColor", "#2f3136");
}
/*if (_c["fork-wp-2"]) {
const current = BdApi.getWindowPreference("frame");
if (current != _c["fork-wp-2"]) BdApi.setWindowPreference("frame", _c["fork-wp-2"]);
}*/
if (id == "bda-gs-8") {
if (enabled) DevMode.enable(SettingsCookie["fork-dm-1"]);
else DevMode.disable();
}
Core.saveSettings();
}
initializeSettings() {
if (SettingsCookie["bda-es-0"]) $("#twitchcord-button-container").show();
// if (SettingsCookie["bda-gs-b"]) $("body").addClass("bd-blue");
if (SettingsCookie["bda-gs-2"]) $("body").addClass("bd-minimal");
if (SettingsCookie["bda-gs-3"]) $("body").addClass("bd-minimal-chan");
if (SettingsCookie["bda-gs-1"]) $("#bd-pub-li").show();
if (SettingsCookie["bda-gs-4"]) VoiceMode.enable();
if (SettingsCookie["bda-gs-5"]) $("#app-mount").addClass("bda-dark");
if (SettingsCookie["bda-gs-6"]) Core.inject24Hour();
if (SettingsCookie["bda-gs-7"]) Core.injectColoredText();
if (SettingsCookie["bda-es-4"]) EmoteModule.autoCapitalize();
if (SettingsCookie["fork-ps-4"]) ClassNormalizer.start();
if (SettingsCookie["fork-ps-5"]) {
ContentManager.watchContent("plugin");
ContentManager.watchContent("theme");
}
if (SettingsCookie["bda-gs-8"]) DevMode.enable(SettingsCookie["fork-dm-1"]);
Core.saveSettings();
}
};

View File

@ -1,4 +1,10 @@
var themeCookie = {};
import {SettingsCookie, ThemeCookie, Themes} from "data";
import ContentManager from "./contentmanager";
import Utilities from "./utilities";
import Core from "./core";
import BdApi from "./pluginapi";
import Emitter from "./emitter";
import DataStore from "./datastore";
function ThemeModule() {
@ -7,84 +13,84 @@ function ThemeModule() {
ThemeModule.prototype.loadThemes = function () {
this.loadThemeData();
const errors = ContentManager.loadThemes();
var themes = Object.keys(bdthemes);
var themes = Object.keys(Themes);
for (var i = 0; i < themes.length; i++) {
var name = bdthemes[themes[i]].name;
if (!themeCookie[name]) themeCookie[name] = false;
if (themeCookie[name]) $("head").append($("<style>", {id: Utils.escapeID(name), text: unescape(bdthemes[name].css)}));
var name = Themes[themes[i]].name;
if (!ThemeCookie[name]) ThemeCookie[name] = false;
if (ThemeCookie[name]) $("head").append($("<style>", {id: Utilities.escapeID(name), text: unescape(Themes[name].css)}));
}
for (let theme in themeCookie) {
if (!bdthemes[theme]) delete themeCookie[theme];
for (let theme in ThemeCookie) {
if (!Themes[theme]) delete ThemeCookie[theme];
}
this.saveThemeData();
return errors;
// if (settingsCookie["fork-ps-5"]) ContentManager.watchContent("theme");
// if (SettingsCookie["fork-ps-5"]) ContentManager.watchContent("theme");
};
ThemeModule.prototype.enableTheme = function(theme, reload = false) {
themeCookie[theme] = true;
ThemeCookie[theme] = true;
this.saveThemeData();
$("head").append($("<style>", {id: Utils.escapeID(theme), text: unescape(bdthemes[theme].css)}));
if (settingsCookie["fork-ps-2"] && !reload) mainCore.showToast(`${bdthemes[theme].name} v${bdthemes[theme].version} has been applied.`);
$("head").append($("<style>", {id: Utilities.escapeID(theme), text: unescape(Themes[theme].css)}));
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Themes[theme].name} v${Themes[theme].version} has been applied.`);
};
ThemeModule.prototype.disableTheme = function(theme, reload = false) {
themeCookie[theme] = false;
ThemeCookie[theme] = false;
this.saveThemeData();
$(`#${Utils.escapeID(bdthemes[theme].name)}`).remove();
if (settingsCookie["fork-ps-2"] && !reload) mainCore.showToast(`${bdthemes[theme].name} v${bdthemes[theme].version} has been disabled.`);
$(`#${Utilities.escapeID(Themes[theme].name)}`).remove();
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Themes[theme].name} v${Themes[theme].version} has been disabled.`);
};
ThemeModule.prototype.toggleTheme = function(theme) {
if (themeCookie[theme]) this.disableTheme(theme);
if (ThemeCookie[theme]) this.disableTheme(theme);
else this.enableTheme(theme);
};
ThemeModule.prototype.loadTheme = function(filename) {
const error = ContentManager.loadContent(filename, "theme");
if (error) {
if (settingsCookie["fork-ps-1"]) mainCore.showContentErrors({themes: [error]});
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${filename} could not be loaded. It may not have been loaded.`, {type: "error"});
return Utils.err("ContentManager", `${filename} could not be loaded.`, error);
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({themes: [error]});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${filename} could not be loaded. It may not have been loaded.`, {type: "error"});
return Utilities.err("ContentManager", `${filename} could not be loaded.`, error);
}
const theme = Object.values(bdthemes).find(p => p.filename == filename);
Utils.log("ContentManager", `${theme.name} v${theme.version} was loaded.`);
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${theme.name} v${theme.version} was loaded.`, {type: "success"});
BDEvents.dispatch("theme-loaded", theme.name);
const theme = Object.values(Themes).find(p => p.filename == filename);
Utilities.log("ContentManager", `${theme.name} v${theme.version} was loaded.`);
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme.name} v${theme.version} was loaded.`, {type: "success"});
Emitter.dispatch("theme-loaded", theme.name);
};
ThemeModule.prototype.unloadTheme = function(filenameOrName) {
const bdtheme = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
const bdtheme = Object.values(Themes).find(p => p.filename == filenameOrName) || Themes[filenameOrName];
if (!bdtheme) return;
const theme = bdtheme.name;
if (themeCookie[theme]) this.disableTheme(theme, true);
const error = ContentManager.unloadContent(bdthemes[theme].filename, "theme");
delete bdthemes[theme];
if (ThemeCookie[theme]) this.disableTheme(theme, true);
const error = ContentManager.unloadContent(Themes[theme].filename, "theme");
delete Themes[theme];
if (error) {
if (settingsCookie["fork-ps-1"]) mainCore.showContentErrors({themes: [error]});
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
return Utils.err("ContentManager", `${theme} could not be unloaded. It may have not been loaded yet.`, error);
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({themes: [error]});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
return Utilities.err("ContentManager", `${theme} could not be unloaded. It may have not been loaded yet.`, error);
}
Utils.log("ContentManager", `${theme} was unloaded.`);
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} was unloaded.`, {type: "success"});
BDEvents.dispatch("theme-unloaded", theme);
Utilities.log("ContentManager", `${theme} was unloaded.`);
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} was unloaded.`, {type: "success"});
Emitter.dispatch("theme-unloaded", theme);
};
ThemeModule.prototype.reloadTheme = function(filenameOrName) {
const bdtheme = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
const bdtheme = Object.values(Themes).find(p => p.filename == filenameOrName) || Themes[filenameOrName];
if (!bdtheme) return this.loadTheme(filenameOrName);
const theme = bdtheme.name;
const error = ContentManager.reloadContent(bdthemes[theme].filename, "theme");
if (themeCookie[theme]) this.disableTheme(theme, true), this.enableTheme(theme, true);
const error = ContentManager.reloadContent(Themes[theme].filename, "theme");
if (ThemeCookie[theme]) this.disableTheme(theme, true), this.enableTheme(theme, true);
if (error) {
if (settingsCookie["fork-ps-1"]) mainCore.showContentErrors({themes: [error]});
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} could not be reloaded.`, {type: "error"});
return Utils.err("ContentManager", `${theme} could not be reloaded.`, error);
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({themes: [error]});
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} could not be reloaded.`, {type: "error"});
return Utilities.err("ContentManager", `${theme} could not be reloaded.`, error);
}
Utils.log("ContentManager", `${theme} v${bdthemes[theme].version} was reloaded.`);
if (settingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} v${bdthemes[theme].version} was reloaded.`, {type: "success"});
BDEvents.dispatch("theme-reloaded", theme);
Utilities.log("ContentManager", `${theme} v${Themes[theme].version} was reloaded.`);
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} v${Themes[theme].version} was reloaded.`, {type: "success"});
Emitter.dispatch("theme-reloaded", theme);
};
ThemeModule.prototype.updateThemeList = function() {
@ -94,14 +100,13 @@ ThemeModule.prototype.updateThemeList = function() {
};
ThemeModule.prototype.loadThemeData = function() {
let saved = DataStore.getSettingGroup("themes");
if (saved) {
themeCookie = saved;
}
const saved = DataStore.getSettingGroup("themes");
if (!saved) return;
Object.assign(ThemeCookie, saved);
};
ThemeModule.prototype.saveThemeData = function () {
DataStore.setSettingGroup("themes", themeCookie);
DataStore.setSettingGroup("themes", ThemeCookie);
};
export default ThemeModule;
export default new ThemeModule();

View File

@ -1,4 +1,4 @@
var Utils = class {
export default class Utilities {
/** Document/window width */
static get screenWidth() { return Math.max(document.documentElement.clientWidth, window.innerWidth || 0); }
/** Document/window height */
@ -108,13 +108,13 @@ var Utils = class {
callOriginalMethod: () => data.returnValue = data.originalMethod.apply(data.thisObject, data.methodArguments)
};
if (instead) {
const tempRet = Utils.suppressErrors(instead, "`instead` callback of " + what[methodName].displayName)(data);
const tempRet = Utilities.suppressErrors(instead, "`instead` callback of " + what[methodName].displayName)(data);
if (tempRet !== undefined) data.returnValue = tempRet;
}
else {
if (before) Utils.suppressErrors(before, "`before` callback of " + what[methodName].displayName)(data);
if (before) Utilities.suppressErrors(before, "`before` callback of " + what[methodName].displayName)(data);
data.callOriginalMethod();
if (after) Utils.suppressErrors(after, "`after` callback of " + what[methodName].displayName)(data);
if (after) Utilities.suppressErrors(after, "`after` callback of " + what[methodName].displayName)(data);
}
if (once) cancel();
return data.returnValue;
@ -172,4 +172,4 @@ var Utils = class {
return proxy;
}
};
}

View File

@ -1,4 +1,4 @@
export default class {
export default new class {
enable() {
$(".scroller.guild-channels ul").first().css("display", "none");
$(".scroller.guild-channels header").first().css("display", "none");
@ -16,4 +16,4 @@ export default class {
$(".flex-vertical.channels-wrap").first().css("flex-grow", "");
$(".guild-header .btn.btn-hamburger").first().css("visibility", "");
}
}
};

View File

@ -1,411 +0,0 @@
/**
* Allows for grabbing and searching through Discord's webpacked modules.
* @module WebpackModules
* @version 0.0.2
*/
import Utilities from "./utilities";
const KnownModules = Utilities.memoizeObject({
get React() {return WebpackModules.getByProps("createElement", "cloneElement");},
get ReactDOM() {return WebpackModules.getByProps("render", "findDOMNode");},
get Events() {return WebpackModules.getByPrototypes("setMaxListeners", "emit");},
/* Guild Info, Stores, and Utilities */
get GuildStore() {return WebpackModules.getByProps("getGuild");},
get SortedGuildStore() {return WebpackModules.getByProps("getSortedGuilds");},
get SelectedGuildStore() {return WebpackModules.getByProps("getLastSelectedGuildId");},
get GuildSync() {return WebpackModules.getByProps("getSyncedGuilds");},
get GuildInfo() {return WebpackModules.getByProps("getAcronym");},
get GuildChannelsStore() {return WebpackModules.getByProps("getChannels", "getDefaultChannel");},
get GuildMemberStore() {return WebpackModules.getByProps("getMember");},
get MemberCountStore() {return WebpackModules.getByProps("getMemberCounts");},
get GuildEmojiStore() {return WebpackModules.getByProps("getEmojis");},
get GuildActions() {return WebpackModules.getByProps("markGuildAsRead");},
get GuildPermissions() {return WebpackModules.getByProps("getGuildPermissions");},
/* Channel Store & Actions */
get ChannelStore() {return WebpackModules.getByProps("getChannels", "getDMFromUserId");},
get SelectedChannelStore() {return WebpackModules.getByProps("getLastSelectedChannelId");},
get ChannelActions() {return WebpackModules.getByProps("selectChannel");},
get PrivateChannelActions() {return WebpackModules.getByProps("openPrivateChannel");},
get ChannelSelector() {return WebpackModules.getByProps("selectGuild", "selectChannel");},
/* Current User Info, State and Settings */
get UserInfoStore() {return WebpackModules.getByProps("getToken");},
get UserSettingsStore() {return WebpackModules.getByProps("guildPositions");},
get AccountManager() {return WebpackModules.getByProps("register", "login");},
get UserSettingsUpdater() {return WebpackModules.getByProps("updateRemoteSettings");},
get OnlineWatcher() {return WebpackModules.getByProps("isOnline");},
get CurrentUserIdle() {return WebpackModules.getByProps("getIdleTime");},
get RelationshipStore() {return WebpackModules.getByProps("isBlocked", "getFriendIDs");},
get RelationshipManager() {return WebpackModules.getByProps("addRelationship");},
get MentionStore() {return WebpackModules.getByProps("getMentions");},
/* User Stores and Utils */
get UserStore() {return WebpackModules.getByProps("getCurrentUser");},
get UserStatusStore() {return WebpackModules.getByProps("getStatus", "getState");},
get UserTypingStore() {return WebpackModules.getByProps("isTyping");},
get UserActivityStore() {return WebpackModules.getByProps("getActivity");},
get UserNameResolver() {return WebpackModules.getByProps("getName");},
get UserNoteStore() {return WebpackModules.getByProps("getNote");},
get UserNoteActions() {return WebpackModules.getByProps("updateNote");},
/* Emoji Store and Utils */
get EmojiInfo() {return WebpackModules.getByProps("isEmojiDisabled");},
get EmojiUtils() {return WebpackModules.getByProps("getGuildEmoji");},
get EmojiStore() {return WebpackModules.getByProps("getByCategory", "EMOJI_NAME_RE");},
/* Invite Store and Utils */
get InviteStore() {return WebpackModules.getByProps("getInvites");},
get InviteResolver() {return WebpackModules.getByProps("findInvite");},
get InviteActions() {return WebpackModules.getByProps("acceptInvite");},
/* Discord Objects & Utils */
get DiscordConstants() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes");},
get DiscordPermissions() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes").Permissions;},
get Permissions() {return WebpackModules.getByProps("getHighestRole");},
get ColorConverter() {return WebpackModules.getByProps("hex2int");},
get ColorShader() {return WebpackModules.getByProps("darken");},
get TinyColor() {return WebpackModules.getByPrototypes("toRgb");},
get ClassResolver() {return WebpackModules.getByProps("getClass");},
get ButtonData() {return WebpackModules.getByProps("ButtonSizes");},
get IconNames() {return WebpackModules.getByProps("IconNames");},
get NavigationUtils() {return WebpackModules.getByProps("transitionTo", "replaceWith", "getHistory");},
/* Discord Messages */
get MessageStore() {return WebpackModules.getByProps("getMessages");},
get MessageActions() {return WebpackModules.getByProps("jumpToMessage", "_sendMessage");},
get MessageQueue() {return WebpackModules.getByProps("enqueue");},
get MessageParser() {return WebpackModules.getByProps("createMessage", "parse", "unparse");},
/* In-Game Overlay */
get OverlayUserPopoutSettings() {return WebpackModules.getByProps("openUserPopout");},
get OverlayUserPopoutInfo() {return WebpackModules.getByProps("getOpenedUserPopout");},
/* Experiments */
get ExperimentStore() {return WebpackModules.getByProps("getExperimentOverrides");},
get ExperimentsManager() {return WebpackModules.getByProps("isDeveloper");},
get CurrentExperiment() {return WebpackModules.getByProps("getExperimentId");},
/* Images, Avatars and Utils */
get ImageResolver() {return WebpackModules.getByProps("getUserAvatarURL", "getGuildIconURL");},
get ImageUtils() {return WebpackModules.getByProps("getSizedImageSrc");},
get AvatarDefaults() {return WebpackModules.getByProps("getUserAvatarURL", "DEFAULT_AVATARS");},
/* Drag & Drop */
get DNDActions() {return WebpackModules.getByProps("beginDrag");},
get DNDSources() {return WebpackModules.getByProps("addTarget");},
get DNDObjects() {return WebpackModules.getByProps("DragSource");},
/* Electron & Other Internals with Utils*/
get ElectronModule() {return WebpackModules.getByProps("setBadge");},
get Dispatcher() {return WebpackModules.getByProps("dirtyDispatch");},
get PathUtils() {return WebpackModules.getByProps("hasBasename");},
get NotificationModule() {return WebpackModules.getByProps("showNotification");},
get RouterModule() {return WebpackModules.getByProps("Router");},
get APIModule() {return WebpackModules.getByProps("getAPIBaseURL");},
get AnalyticEvents() {return WebpackModules.getByProps("AnalyticEventConfigs");},
get KeyGenerator() {return WebpackModules.getByRegex(/"binary"/);},
get Buffers() {return WebpackModules.getByProps("Buffer", "kMaxLength");},
get DeviceStore() {return WebpackModules.getByProps("getDevices");},
get SoftwareInfo() {return WebpackModules.getByProps("os");},
get CurrentContext() {return WebpackModules.getByProps("setTagsContext");},
/* Media Stuff (Audio/Video) */
get MediaDeviceInfo() {return WebpackModules.getByProps("Codecs", "SUPPORTED_BROWSERS");},
get MediaInfo() {return WebpackModules.getByProps("getOutputVolume");},
get MediaEngineInfo() {return WebpackModules.getByProps("MediaEngineFeatures");},
get VoiceInfo() {return WebpackModules.getByProps("EchoCancellation");},
get VideoStream() {return WebpackModules.getByProps("getVideoStream");},
get SoundModule() {return WebpackModules.getByProps("playSound");},
/* Window, DOM, HTML */
get WindowInfo() {return WebpackModules.getByProps("isFocused", "windowSize");},
get TagInfo() {return WebpackModules.getByProps("VALID_TAG_NAMES");},
get DOMInfo() {return WebpackModules.getByProps("canUseDOM");},
/* Locale/Location and Time */
get LocaleManager() {return WebpackModules.getByProps("setLocale");},
get Moment() {return WebpackModules.getByProps("parseZone");},
get LocationManager() {return WebpackModules.getByProps("createLocation");},
get Timestamps() {return WebpackModules.getByProps("fromTimestamp");},
/* Strings and Utils */
get Strings() {return WebpackModules.getByProps("Messages").Messages;},
get StringFormats() {return WebpackModules.getByProps("a", "z");},
get StringUtils() {return WebpackModules.getByProps("toASCII");},
/* URLs and Utils */
get URLParser() {return WebpackModules.getByProps("Url", "parse");},
get ExtraURLs() {return WebpackModules.getByProps("getArticleURL");},
/* Text Processing */
get hljs() {return WebpackModules.getByProps("highlight", "highlightBlock");},
get SimpleMarkdown() {return WebpackModules.getByProps("parseBlock", "parseInline", "defaultOutput");},
/* DOM/React Components */
/* ==================== */
get LayerManager() {return WebpackModules.getByProps("popLayer", "pushLayer");},
get Tooltips() {return WebpackModules.find(m => m.hide && m.show && !m.search && !m.submit && !m.search && !m.activateRagingDemon && !m.dismiss);},
get UserSettingsWindow() {return WebpackModules.getByProps("open", "updateAccount");},
get ChannelSettingsWindow() {return WebpackModules.getByProps("open", "updateChannel");},
get GuildSettingsWindow() {return WebpackModules.getByProps("open", "updateGuild");},
/* Modals */
get ModalStack() {return WebpackModules.getByProps("push", "update", "pop", "popWithKey");},
get UserProfileModals() {return WebpackModules.getByProps("fetchMutualFriends", "setSection");},
get AlertModal() {return WebpackModules.getByPrototypes("handleCancel", "handleSubmit", "handleMinorConfirm");},
get ConfirmationModal() {return WebpackModules.getModule(m => m.defaultProps && m.key && m.key() == "confirm-modal");},
get UserProfileModal() {
return WebpackModules.find(m => {
try {return m.modalConfig && m.prototype.render().type.displayName == "FluxContainer(Component)";}
catch (err) {return false;}
});
},
get ChangeNicknameModal() {return WebpackModules.getByProps("open", "changeNickname");},
get CreateChannelModal() {return WebpackModules.getByProps("open", "createChannel");},
get PruneMembersModal() {return WebpackModules.getByProps("open", "prune");},
get NotificationSettingsModal() {return WebpackModules.getByProps("open", "updateNotificationSettings");},
get PrivacySettingsModal() {return WebpackModules.getByRegex(/PRIVACY_SETTINGS_MODAL_OPEN/, m => m.open);},
get CreateInviteModal() {return WebpackModules.getByProps("open", "createInvite");},
get Changelog() {return WebpackModules.getModule((m => m.defaultProps && m.defaultProps.selectable == false));},
get Avatar() {
return WebpackModules.find(m => {
if (m.displayName != "FluxContainer(t)") return false;
try {
const temp = new m();
return temp && temp.state && temp.state.hasOwnProperty("isFocused");
}
catch (err) {return false;}
});
},
/* Popouts */
get PopoutStack() {return WebpackModules.getByProps("open", "close", "closeAll");},
get PopoutOpener() {return WebpackModules.getByProps("openPopout");},
get EmojiPicker() {return WebpackModules.getByDisplayName("FluxContainer(EmojiPicker)");},
get UserPopout() {
return WebpackModules.find(m => {
try {return m.displayName == "FluxContainer(Component)" && !(new m());}
catch (e) {return e.toString().includes("user");}
});
},
/* Context Menus */
get ContextMenuActions() {return WebpackModules.getByProps("openContextMenu");},
get ContextMenuItemsGroup() {return WebpackModules.getByRegex(/itemGroup/);},
get ContextMenuItem() {return WebpackModules.getByRegex(/\.label\b.*\.hint\b.*\.action\b/);},
/* Misc */
get ExternalLink() {return WebpackModules.getByRegex(/trusted/);},
get TextElement() {return WebpackModules.getByProps("Sizes", "Weights");},
get FlexChild() {return WebpackModules.getByProps("Child");},
get Titles() {return WebpackModules.getByProps("Tags", "default");},
/* Settings */
get SettingsWrapper() {return WebpackModules.getModule(m => m.prototype && m.prototype.render && m.prototype.render.toString().includes("required:"));},
get SettingsNote() {return WebpackModules.getModule(m => m.Types && m.defaultProps);},
get SettingsDivider() {return WebpackModules.getModule(m => !m.defaultProps && m.prototype && m.prototype.render && m.prototype.render.toString().includes("default.divider"));},
get ColorPicker() {return WebpackModules.getByPrototypes("renderCustomColorPopout");},
get Dropdown() {return WebpackModules.getModule(m => m.prototype && !m.prototype.handleClick && m.prototype.render && m.prototype.render.toString().includes("default.select"));},
get Keybind() {return WebpackModules.getByPrototypes("handleComboChange");},
get RadioGroup() {return WebpackModules.getModule(m => m.defaultProps && m.defaultProps.options && m.defaultProps.size);},
get Slider() {return WebpackModules.getByPrototypes("renderMark");},
get SwitchRow() {return WebpackModules.getModule(m => m.defaultProps && m.defaultProps.hideBorder == false);},
get Textbox() {return WebpackModules.getModule(m => m.defaultProps && m.defaultProps.type == "text");},
});
export {KnownModules};
/**
* Checks if a given module matches a set of parameters.
* @callback module:WebpackModules.Filters~filter
* @param {*} module - module to check
* @returns {boolean} - True if the module matches the filter, false otherwise
*/
/**
* Filters for use with {@link module:WebpackModules} but may prove useful elsewhere.
*/
export class Filters {
/**
* Generates a {@link module:WebpackModules.Filters~filter} that filters by a set of properties.
* @param {Array<string>} props - Array of property names
* @param {module:WebpackModules.Filters~filter} filter - Additional filter
* @returns {module:WebpackModules.Filters~filter} - A filter that checks for a set of properties
*/
static byProperties(props, filter = m => m) {
return module => {
const component = filter(module);
if (!component) return false;
return props.every(property => component[property] !== undefined);
};
}
/**
* Generates a {@link module:WebpackModules.Filters~filter} that filters by a set of properties on the object's prototype.
* @param {Array<string>} fields - Array of property names
* @param {module:WebpackModules.Filters~filter} filter - Additional filter
* @returns {module:WebpackModules.Filters~filter} - A filter that checks for a set of properties on the object's prototype
*/
static byPrototypeFields(fields, filter = m => m) {
return module => {
const component = filter(module);
if (!component) return false;
if (!component.prototype) return false;
return fields.every(field => component.prototype[field] !== undefined);
};
}
/**
* Generates a {@link module:WebpackModules.Filters~filter} that filters by a regex.
* @param {RegExp} search - A RegExp to check on the module
* @param {module:WebpackModules.Filters~filter} filter - Additional filter
* @returns {module:WebpackModules.Filters~filter} - A filter that checks for a set of properties
*/
static byCode(search, filter = m => m) {
return module => {
const method = filter(module);
if (!method) return false;
return method.toString([]).search(search) !== -1;
};
}
/**
* Generates a {@link module:WebpackModules.Filters~filter} that filters by a set of properties.
* @param {string} name - Name the module should have
* @param {module:WebpackModules.Filters~filter} filter - Additional filter
* @returns {module:WebpackModules.Filters~filter} - A filter that checks for a set of properties
*/
static byDisplayName(name) {
return module => {
return module && module.displayName === name;
};
}
/**
* Generates a combined {@link module:WebpackModules.Filters~filter} from a list of filters.
* @param {...module:WebpackModules.Filters~filter} filters - A list of filters
* @returns {module:WebpackModules.Filters~filter} - Combinatory filter of all arguments
*/
static combine(...filters) {
return module => {
return filters.every(filter => filter(module));
};
}
}
export default class WebpackModules {
static find(filter, first = true) {return this.getModule(filter, first);}
static findByUniqueProperties(props, first = true) {return first ? this.getByProps(...props) : this.getAllByProps(...props);}
static findByDisplayName(name) {return this.getByDisplayName(name);}
/**
* Finds a module using a filter function.
* @param {Function} filter A function to use to filter modules
* @param {Boolean} first Whether to return only the first matching module
* @return {Any}
*/
static getModule(filter, first = true) {
const modules = this.getAllModules();
const rm = [];
for (let index in modules) {
if (!modules.hasOwnProperty(index)) continue;
const module = modules[index];
const {exports} = module;
let foundModule = null;
if (!exports) continue;
if (exports.__esModule && exports.default && filter(exports.default)) foundModule = exports.default;
if (filter(exports)) foundModule = exports;
if (!foundModule) continue;
if (first) return foundModule;
rm.push(foundModule);
}
return first || rm.length == 0 ? undefined : rm;
}
/**
* Finds a module by its display name.
* @param {String} name The display name of the module
* @return {Any}
*/
static getByDisplayName(name) {
return this.getModule(Filters.byDisplayName(name), true);
}
/**
* Finds a module using its code.
* @param {RegEx} regex A regular expression to use to filter modules
* @param {Boolean} first Whether to return the only the first matching module
* @return {Any}
*/
static getByRegex(regex, first = true) {
return this.getModule(Filters.byCode(regex), first);
}
/**
* Finds a single module using properties on its prototype.
* @param {...string} prototypes Properties to use to filter modules
* @return {Any}
*/
static getByPrototypes(...prototypes) {
return this.getModule(Filters.byPrototypeFields(prototypes), true);
}
/**
* Finds all modules with a set of properties of its prototype.
* @param {...string} prototypes Properties to use to filter modules
* @return {Any}
*/
static getAllByPrototypes(...prototypes) {
return this.getModule(Filters.byPrototypeFields(prototypes), false);
}
/**
* Finds a single module using its own properties.
* @param {...string} props Properties to use to filter modules
* @return {Any}
*/
static getByProps(...props) {
return this.getModule(Filters.byProperties(props), true);
}
/**
* Finds all modules with a set of properties.
* @param {...string} props Properties to use to filter modules
* @return {Any}
*/
static getAllByProps(...props) {
return this.getModule(Filters.byProperties(props), false);
}
/**
* Discord's __webpack_require__ function.
*/
static get require() {
if (this._require) return this._require;
const id = "zl-webpackmodules";
const __webpack_require__ = typeof(window.webpackJsonp) == "function" ? window.webpackJsonp([], {
[id]: (module, exports, __webpack_require__) => exports.default = __webpack_require__
}, [id]).default : window.webpackJsonp.push([[], {
[id]: (module, exports, __webpack_require__) => module.exports = __webpack_require__
}, [[id]]]);
delete __webpack_require__.m[id];
delete __webpack_require__.c[id];
return this._require = __webpack_require__;
}
/**
* Returns all loaded modules.
* @return {Array}
*/
static getAllModules() {
return this.require.c;
}
}

View File

@ -1,5 +1,5 @@
import Settings from "../../data/settingscookie";
import {BDV2, DataStore} from "modules";
import {SettingsCookie} from "data";
import {BDV2, DataStore, Core} from "modules";
import Checkbox from "../settings/checkbox";
@ -24,7 +24,7 @@ export default class V2C_CssEditorDetached extends BDV2.reactComponent {
this.editor.setShowPrintMargin(false);
this.editor.setFontSize(14);
this.editor.on("change", () => {
if (!Settings["bda-css-0"]) return;
if (!SettingsCookie["bda-css-0"]) return;
this.saveCss();
this.updateCss();
});
@ -97,7 +97,7 @@ export default class V2C_CssEditorDetached extends BDV2.reactComponent {
BDV2.react.createElement(
"ul",
{className: "checkbox-group"},
BDV2.react.createElement(Checkbox, {id: "live-update", text: "Live Update", onChange: self.onChange, checked: Settings["bda-css-0"]})
BDV2.react.createElement(Checkbox, {id: "live-update", text: "Live Update", onChange: self.onChange, checked: SettingsCookie["bda-css-0"]})
),
BDV2.react.createElement(
"div",
@ -137,8 +137,8 @@ export default class V2C_CssEditorDetached extends BDV2.reactComponent {
onChange(id, checked) {
switch (id) {
case "live-update":
Settings["bda-css-0"] = checked;
window.mainCore.saveSettings();
SettingsCookie["bda-css-0"] = checked;
Core.saveSettings();
break;
}
}

View File

@ -1,5 +1,5 @@
import Settings from "../../data/settingscookie";
import {BDV2, DataStore} from "modules";
import {SettingsCookie} from "data";
import {BDV2, DataStore, Core} from "modules";
import EditorDetached from "./detached";
import Checkbox from "../settings/checkbox";
@ -34,7 +34,7 @@ export default class V2C_CssEditor extends BDV2.reactComponent {
this.editor.setShowPrintMargin(false);
this.editor.setFontSize(14);
this.editor.on("change", () => {
if (!Settings["bda-css-0"]) return;
if (!SettingsCookie["bda-css-0"]) return;
this.saveCss();
this.updateCss();
});
@ -117,7 +117,7 @@ export default class V2C_CssEditor extends BDV2.reactComponent {
BDV2.react.createElement(
"ul",
{className: "checkbox-group"},
BDV2.react.createElement(Checkbox, {id: "live-update", text: "Live Update", onChange: this.onChange, checked: Settings["bda-css-0"]})
BDV2.react.createElement(Checkbox, {id: "live-update", text: "Live Update", onChange: this.onChange, checked: SettingsCookie["bda-css-0"]})
),
BDV2.react.createElement(
"div",
@ -179,8 +179,8 @@ export default class V2C_CssEditor extends BDV2.reactComponent {
onChange(id, checked) {
switch (id) {
case "live-update":
Settings["bda-css-0"] = checked;
window.mainCore.saveSettings();
SettingsCookie["bda-css-0"] = checked;
Core.saveSettings();
break;
}
}

View File

@ -1,11 +1,11 @@
import Settings from "../data/settingscookie";
import {BDV2} from "modules";
import {SettingsCookie} from "data";
import {BDV2, EmoteMenu} from "modules";
export default class BDEmote extends BDV2.reactComponent {
constructor(props) {
super(props);
const isFav = window.mainCore.quickEmoteMenu && window.mainCore.quickEmoteMenu.favoriteEmotes && window.mainCore.quickEmoteMenu.favoriteEmotes[this.label] ? true : false;
const isFav = EmoteMenu && EmoteMenu.favoriteEmotes && EmoteMenu.favoriteEmotes[this.label] ? true : false;
this.state = {
shouldAnimate: !this.animateOnHover,
isFavorite: isFav
@ -17,7 +17,7 @@ export default class BDEmote extends BDV2.reactComponent {
}
get animateOnHover() {
return Settings["fork-es-2"];
return SettingsCookie["fork-es-2"];
}
get label() {
@ -30,8 +30,8 @@ export default class BDEmote extends BDV2.reactComponent {
onMouseEnter() {
if (!this.state.shouldAnimate && this.animateOnHover) this.setState({shouldAnimate: true});
if (!this.state.isFavorite && window.mainCore.quickEmoteMenu.favoriteEmotes[this.label]) this.setState({isFavorite: true});
else if (this.state.isFavorite && !window.mainCore.quickEmoteMenu.favoriteEmotes[this.label]) this.setState({isFavorite: false});
if (!this.state.isFavorite && EmoteMenu.favoriteEmotes[this.label]) this.setState({isFavorite: true});
else if (this.state.isFavorite && !EmoteMenu.favoriteEmotes[this.label]) this.setState({isFavorite: false});
}
onMouseLeave() {
@ -70,11 +70,11 @@ export default class BDEmote extends BDV2.reactComponent {
e.preventDefault();
e.stopPropagation();
if (this.state.isFavorite) {
delete window.mainCore.quickEmoteMenu.favoriteEmotes[this.label];
window.mainCore.quickEmoteMenu.updateFavorites();
delete EmoteMenu.favoriteEmotes[this.label];
EmoteMenu.updateFavorites();
}
else {
window.mainCore.quickEmoteMenu.favorite(this.label, this.props.url);
EmoteMenu.favorite(this.label, this.props.url);
}
this.setState({isFavorite: !this.state.isFavorite});
}

View File

@ -1,61 +1,5 @@
import Settings from "../../data/settingscookie";
import {BDV2} from "modules";
import Layer from "../layer";
import Menu from "./menu";
import Card from "./card";
import Layer from "../layer";
export default class V2_PublicServers {
constructor() {}
get component() {
return BDV2.react.createElement(Layer, {rootId: "pubslayerroot", id: "pubslayer", children: BDV2.react.createElement(Menu, {rootId: "pubslayerroot"})});
}
get root() {
let _root = document.getElementById("pubslayerroot");
if (!_root) {
if (!this.injectRoot()) return null;
return this.root;
}
return _root;
}
injectRoot() {
if (!$(".layers, .layers-3iHuyZ").length) return false;
$(".layers, .layers-3iHuyZ").append($("<div/>", {
id: "pubslayerroot"
}));
return true;
}
render() {
// BdApi.alert("Broken", "Sorry but the Public Servers modules is currently broken, I recommend disabling this feature for now.");
let root = this.root;
if (!root) {
console.log("FAILED TO LOCATE ROOT: .layers");
return;
}
BDV2.reactDom.render(this.component, root);
}
get button() {
let btn = $("<div/>", {
"class": BDV2.guildClasses.listItem,
"id": "bd-pub-li",
"style": Settings["bda-gs-1"] ? "" : "display: none;"
}).append($("<div/>", {
"class": "wrapper-25eVIn " + BDV2.guildClasses.circleButtonMask,
"text": "public",
"id": "bd-pub-button",
"click": () => { this.render(); }
}));
return btn;
}
initialize() {
const wrapper = BDV2.guildClasses.wrapper.split(" ")[0];
const guilds = $(`.${wrapper} .scroller-2FKFPG >:first-child`);
guilds.after(this.button);
}
}
export {Menu, Card, Layer};

View File

@ -1,4 +1,4 @@
import Settings from "../../data/settingscookie";
import {SettingsCookie} from "data";
import {BDV2} from "modules";
import SettingsTitle from "./title";
import Switch from "./switch";
@ -17,7 +17,7 @@ export default class V2C_SettingsPanel extends BDV2.reactComponent {
BDV2.react.createElement(SettingsTitle, {text: this.props.title}),
this.props.button && BDV2.react.createElement("button", {key: "title-button", className: "bd-pfbtn", onClick: this.props.button.onClick}, this.props.button.title),
settings.map(setting => {
return BDV2.react.createElement(Switch, {id: setting.id, key: setting.id, data: setting, checked: Settings[setting.id], onChange: (id, checked) => {
return BDV2.react.createElement(Switch, {id: setting.id, key: setting.id, data: setting, checked: SettingsCookie[setting.id], onChange: (id, checked) => {
this.props.onChange(id, checked);
}});
})

View File

@ -1,5 +1,5 @@
import Settings from "../../data/settingscookie";
import {BDV2, Utilities} from "modules";
import {SettingsCookie, PluginCookie, Plugins} from "data";
import {BDV2, Utilities, PluginManager} from "modules";
import CloseButton from "../icons/close";
import ReloadIcon from "../icons/reload";
@ -20,7 +20,7 @@ export default class V2C_PluginCard extends BDV2.reactComponent {
setInitialState() {
this.state = {
checked: pluginCookie[this.props.plugin.getName()],
checked: PluginCookie[this.props.plugin.getName()],
settings: false,
reloads: 0
};
@ -45,7 +45,7 @@ export default class V2C_PluginCard extends BDV2.reactComponent {
this.refs.settingspanel.appendChild(this.settingsPanel);
}
if (!Settings["fork-ps-3"]) return;
if (!SettingsCookie["fork-ps-3"]) return;
var isHidden = (container, element) => {
let cTop = container.scrollTop;
@ -68,8 +68,8 @@ export default class V2C_PluginCard extends BDV2.reactComponent {
reload() {
const plugin = this.props.plugin.getName();
window.mainCore.pluginModule.reloadPlugin(plugin);
this.props.plugin = bdplugins[plugin].plugin;
PluginManager.reloadPlugin(plugin);
this.props.plugin = Plugins[plugin].plugin;
this.onReload(this.props.plugin.getName());
}
@ -84,8 +84,8 @@ export default class V2C_PluginCard extends BDV2.reactComponent {
let author = this.getString(plugin.getAuthor());
let description = this.getString(plugin.getDescription());
let version = this.getString(plugin.getVersion());
let website = bdplugins[name].website;
let source = bdplugins[name].source;
let website = Plugins[name].website;
let source = Plugins[name].source;
if (this.state.settings) {
try { self.settingsPanel = plugin.getSettingsPanel(); }
@ -113,7 +113,7 @@ export default class V2C_PluginCard extends BDV2.reactComponent {
BDV2.react.createElement("span", {className: "bda-author"}, author)
),
BDV2.react.createElement("div", {className: "bda-controls"},
!Settings["fork-ps-5"] && BDV2.react.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}),
!SettingsCookie["fork-ps-5"] && BDV2.react.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}),
BDV2.react.createElement("label", {className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}},
BDV2.react.createElement("input", {checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox"}),
BDV2.react.createElement("div", {className: this.state.checked ? "ui-switch checked" : "ui-switch"})
@ -136,7 +136,7 @@ export default class V2C_PluginCard extends BDV2.reactComponent {
onChange() {
this.setState({checked: !this.state.checked});
window.mainCore.pluginModule.togglePlugin(this.props.plugin.getName());
PluginManager.togglePlugin(this.props.plugin.getName());
}
showSettings() {

View File

@ -1,6 +1,5 @@
import SettingsInfo from "../../data/settings";
import Settings from "../../data/settingscookie";
import {BDV2, Utilities, BdApi, ClassNormalizer, ContentManager, Emitter} from "modules";
import {SettingsInfo, SettingsCookie, Plugins, Themes} from "data";
import {BDV2, Utilities, ContentManager, Emitter, EmoteModule, EmoteMenu, PluginManager, ThemeManager} from "modules";
import Sidebar from "./sidebar";
import Scroller from "../scroller";
import List from "../list";
@ -16,12 +15,10 @@ import CssEditor from "../customcss/editor";
export default class V2_SettingsPanel {
constructor() {
let self = this;
self.sideBarOnClick = self.sideBarOnClick.bind(self);
self.onChange = self.onChange.bind(self);
self.updateSettings = this.updateSettings.bind(self);
self.sidebar = new Sidebar(self.sideBarOnClick);
constructor(props) {
this.sideBarOnClick = this.sideBarOnClick.bind(this);
this.onChange = props.onChange;
this.sidebar = new Sidebar(this.sideBarOnClick);
}
get root() {
@ -91,121 +88,6 @@ export default class V2_SettingsPanel {
}
}
onClick() {}
onChange(id, checked) {
this.updateSettings(id, checked);
}
updateSettings(id, enabled) {
Settings[id] = enabled;
if (id == "bda-es-0") {
if (enabled) $("#twitchcord-button-container").show();
else $("#twitchcord-button-container").hide();
}
// if (id == "bda-gs-b") {
// if (enabled) $("body").addClass("bd-blue");
// else $("body").removeClass("bd-blue");
// }
if (id == "bda-gs-2") {
if (enabled) $("body").addClass("bd-minimal");
else $("body").removeClass("bd-minimal");
}
if (id == "bda-gs-3") {
if (enabled) $("body").addClass("bd-minimal-chan");
else $("body").removeClass("bd-minimal-chan");
}
if (id == "bda-gs-1") {
if (enabled) $("#bd-pub-li").show();
else $("#bd-pub-li").hide();
}
if (id == "bda-gs-4") {
if (enabled) window.mainCore.voiceMode.enable();
else window.mainCore.voiceMode.disable();
}
if (id == "bda-gs-5") {
if (enabled) $("#app-mount").addClass("bda-dark");
else $("#app-mount").removeClass("bda-dark");
}
if (enabled && id == "bda-gs-6") window.mainCore.inject24Hour();
if (id == "bda-gs-7") {
if (enabled) window.mainCore.injectColoredText();
else window.mainCore.removeColoredText();
}
if (id == "bda-es-4") {
if (enabled) window.mainCore.emoteModule.autoCapitalize();
else window.mainCore.emoteModule.disableAutoCapitalize();
}
if (id == "fork-ps-4") {
if (enabled) ClassNormalizer.start();
else ClassNormalizer.stop();
}
if (id == "fork-ps-5") {
if (enabled) {
ContentManager.watchContent("plugin");
ContentManager.watchContent("theme");
}
else {
ContentManager.unwatchContent("plugin");
ContentManager.unwatchContent("theme");
}
}
if (id == "fork-wp-1") {
BdApi.setWindowPreference("transparent", enabled);
if (enabled) BdApi.setWindowPreference("backgroundColor", null);
else BdApi.setWindowPreference("backgroundColor", "#2f3136");
}
/*if (_c["fork-wp-2"]) {
const current = BdApi.getWindowPreference("frame");
if (current != _c["fork-wp-2"]) BdApi.setWindowPreference("frame", _c["fork-wp-2"]);
}*/
if (id == "bda-gs-8") {
if (enabled) window.mainCore.dMode.enable(Settings["fork-dm-1"]);
else window.mainCore.dMode.disable();
}
window.mainCore.saveSettings();
}
initializeSettings() {
if (Settings["bda-es-0"]) $("#twitchcord-button-container").show();
// if (Settings["bda-gs-b"]) $("body").addClass("bd-blue");
if (Settings["bda-gs-2"]) $("body").addClass("bd-minimal");
if (Settings["bda-gs-3"]) $("body").addClass("bd-minimal-chan");
if (Settings["bda-gs-1"]) $("#bd-pub-li").show();
if (Settings["bda-gs-4"]) window.mainCore.voiceMode.enable();
if (Settings["bda-gs-5"]) $("#app-mount").addClass("bda-dark");
if (Settings["bda-gs-6"]) window.mainCore.inject24Hour();
if (Settings["bda-gs-7"]) window.mainCore.injectColoredText();
if (Settings["bda-es-4"]) window.mainCore.emoteModule.autoCapitalize();
if (Settings["fork-ps-4"]) ClassNormalizer.start();
if (Settings["fork-ps-5"]) {
ContentManager.watchContent("plugin");
ContentManager.watchContent("theme");
}
if (Settings["bda-gs-8"]) window.mainCore.dMode.enable(Settings["fork-dm-1"]);
window.mainCore.saveSettings();
}
renderSidebar() {
let self = this;
$("[class*='side-'] > [class*='item-']").off("click.v2settingspanel").on("click.v2settingspanel", () => {
@ -228,7 +110,7 @@ export default class V2_SettingsPanel {
contentColumn: true, fade: true, dark: true, children: [
BDV2.react.createElement(SettingsPanel, {key: "espanel", title: "Emote Settings", onChange: this.onChange, settings: this.emoteSettings, button: {
title: "Clear Emote Cache",
onClick: () => { window.mainCore.emoteModule.clearEmoteData(); window.mainCore.emoteModule.init(); window.mainCore.quickEmoteMenu.init(); }
onClick: () => { EmoteModule.clearEmoteData(); EmoteModule.init(); EmoteMenu.init(); }
}}),
BDV2.react.createElement(Tools, {key: "tools"})
]});
@ -270,12 +152,12 @@ export default class V2_SettingsPanel {
}
get pluginsComponent() {
let plugins = Object.keys(bdplugins).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reduce((arr, key) => {
arr.push(BDV2.react.createElement(PluginCard, {key: key, plugin: bdplugins[key].plugin}));return arr;
let plugins = Object.keys(Plugins).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reduce((arr, key) => {
arr.push(BDV2.react.createElement(PluginCard, {key: key, plugin: Plugins[key].plugin}));return arr;
}, []);
let list = BDV2.react.createElement(List, {key: "plugin-list", className: "bda-slist", children: plugins});
let refreshIcon = !Settings["fork-ps-5"] && BDV2.react.createElement(ReloadIcon, {className: "bd-reload-header", size: "18px", onClick: async () => {
window.mainCore.pluginModule.updatePluginList();
let refreshIcon = !SettingsCookie["fork-ps-5"] && BDV2.react.createElement(ReloadIcon, {className: "bd-reload-header", size: "18px", onClick: async () => {
PluginManager.updatePluginList();
this.sideBarOnClick("plugins");
}});
let pfBtn = BDV2.react.createElement("button", {key: "folder-button", className: "bd-pfbtn", onClick: () => { require("electron").shell.openItem(ContentManager.pluginsFolder); }}, "Open Plugin Folder");
@ -284,12 +166,12 @@ export default class V2_SettingsPanel {
}
get themesComponent() {
let themes = Object.keys(bdthemes).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reduce((arr, key) => {
arr.push(BDV2.react.createElement(ThemeCard, {key: key, theme: bdthemes[key]}));return arr;
let themes = Object.keys(Themes).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reduce((arr, key) => {
arr.push(BDV2.react.createElement(ThemeCard, {key: key, theme: Themes[key]}));return arr;
}, []);
let list = BDV2.react.createElement(List, {key: "theme-list", className: "bda-slist", children: themes});
let refreshIcon = !Settings["fork-ps-5"] && BDV2.react.createElement(ReloadIcon, {className: "bd-reload-header", size: "18px", onClick: async () => {
window.mainCore.themeModule.updateThemeList();
let refreshIcon = !SettingsCookie["fork-ps-5"] && BDV2.react.createElement(ReloadIcon, {className: "bd-reload-header", size: "18px", onClick: async () => {
ThemeManager.updateThemeList();
this.sideBarOnClick("themes");
}});
let tfBtn = BDV2.react.createElement("button", {key: "folder-button", className: "bd-pfbtn", onClick: () => { require("electron").shell.openItem(ContentManager.themesFolder); }}, "Open Theme Folder");

View File

@ -1,4 +1,4 @@
import Settings from "../../data/settingscookie";
import {SettingsCookie} from "data";
import {BDV2} from "modules";
import SettingsTitle from "./title";
import Switch from "./switch";
@ -15,7 +15,7 @@ export default class V2C_SettingsGroup extends BDV2.reactComponent {
return [BDV2.react.createElement(SettingsTitle, {text: title}),
buttonComponent,
settings.map(setting => {
return BDV2.react.createElement(Switch, {id: setting.id, key: setting.id, data: setting, checked: Settings[setting.id], onChange: (id, checked) => {
return BDV2.react.createElement(Switch, {id: setting.id, key: setting.id, data: setting, checked: SettingsCookie[setting.id], onChange: (id, checked) => {
this.props.onChange(id, checked);
}});
})];

View File

@ -1,4 +1,4 @@
import Config from "../../data/config";
import {Config} from "data";
import {BDV2, Utilities} from "modules";
import SideBar from "./sidebarmenu";

View File

@ -1,5 +1,5 @@
import Settings from "../../data/settingscookie";
import {BDV2} from "modules";
import {SettingsCookie, ThemeCookie, Themes} from "data";
import {BDV2, Core, ThemeManager} from "modules";
import ReloadIcon from "../icons/reload";
export default class V2C_ThemeCard extends BDV2.reactComponent {
@ -13,7 +13,7 @@ export default class V2C_ThemeCard extends BDV2.reactComponent {
setInitialState() {
this.state = {
checked: themeCookie[this.props.theme.name],
checked: ThemeCookie[this.props.theme.name],
reloads: 0
};
}
@ -33,11 +33,11 @@ export default class V2C_ThemeCard extends BDV2.reactComponent {
reload() {
const theme = this.props.theme.name;
const error = window.mainCore.themeModule.reloadTheme(theme);
if (error) window.mainCore.showToast(`Could not reload ${bdthemes[theme].name}. Check console for details.`, {type: "error"});
else window.mainCore.showToast(`${bdthemes[theme].name} v${bdthemes[theme].version} has been reloaded.`, {type: "success"});
const error = ThemeManager.reloadTheme(theme);
if (error) Core.showToast(`Could not reload ${Themes[theme].name}. Check console for details.`, {type: "error"});
else Core.showToast(`${Themes[theme].name} v${Themes[theme].version} has been reloaded.`, {type: "success"});
// this.setState(this.state);
this.props.theme = bdthemes[theme];
this.props.theme = Themes[theme];
this.onReload(this.props.theme.name);
}
@ -47,8 +47,8 @@ export default class V2C_ThemeCard extends BDV2.reactComponent {
let description = theme.description;
let version = theme.version;
let author = theme.author;
let website = bdthemes[name].website;
let source = bdthemes[name].source;
let website = Themes[name].website;
let source = Themes[name].source;
return BDV2.react.createElement("li", {"data-name": name, "data-version": version, "className": "settings-closed ui-switch-item"},
BDV2.react.createElement("div", {className: "bda-header"},
@ -60,7 +60,7 @@ export default class V2C_ThemeCard extends BDV2.reactComponent {
BDV2.react.createElement("span", {className: "bda-author"}, author)
),
BDV2.react.createElement("div", {className: "bda-controls"},
!Settings["fork-ps-5"] && BDV2.react.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}),
!SettingsCookie["fork-ps-5"] && BDV2.react.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}),
BDV2.react.createElement("label", {className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}},
BDV2.react.createElement("input", {checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox"}),
BDV2.react.createElement("div", {className: this.state.checked ? "ui-switch checked" : "ui-switch"})
@ -82,6 +82,6 @@ export default class V2C_ThemeCard extends BDV2.reactComponent {
onChange() {
this.setState({checked: !this.state.checked});
window.mainCore.themeModule.toggleTheme(this.props.theme.name);
ThemeManager.toggleTheme(this.props.theme.name);
}
}

View File

@ -1,4 +1,4 @@
import SettingsPanel from "./settings/settings";
import PublicServers from "./publicservers/publicservers";
import * as PublicServers from "./publicservers/publicservers";
export {SettingsPanel, PublicServers};

View File

@ -8,7 +8,7 @@ module.exports = env => {
devtool: "none",
entry: "./src/index.js",
output: {
filename: "release.js",
filename: "main.js",
path: path.resolve(__dirname, "js"),
library: "Core",
libraryTarget: "var",
@ -18,13 +18,14 @@ module.exports = env => {
electron: `require("electron")`,
fs: `require("fs")`,
path: `require("path")`,
request: `require("request")`
request: `require("request")`,
events: `require("events")`
},
resolve: {
extensions: [".js"],
modules: [
path.resolve("src", "data"),
path.resolve("src", "modules"),
path.resolve("src", "structs"),
path.resolve("src", "ui")
]
}