diff --git a/js/main.js b/js/main.js
index 5e0720e..16e3a00 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1,5092 +1 @@
-/* BetterDiscordApp Core JavaScript
- * Version: 1.78
- * Author: Jiiks | http://jiiks.net
- * Date: 27/08/2015 - 16:36
- * Last Update: 01/05/2016
- * https://github.com/Jiiks/BetterDiscordApp
- */
-
-/* Localstorage fix */
-(function() {
-
- let __fs = window.require("fs");
- let __process = window.require("process");
- let __platform = __process.platform;
- let __dataPath = (__platform === "win32" ? __process.env.APPDATA : __platform === "darwin" ? __process.env.HOME + "/Library/Preferences" : process.env.HOME + "/.config") + "/BetterDiscord/";
- let localStorageFile = "localStorage.json";
-
- let __data = {};
- if (__fs.existsSync(`${__dataPath}${localStorageFile}`)) {
- try {
- __data = JSON.parse(__fs.readFileSync(`${__dataPath}${localStorageFile}`));
- }
- catch (err) {
- console.log(err);
- }
- }
- else if (__fs.existsSync(localStorageFile)) {
- try {
- __data = JSON.parse(__fs.readFileSync(localStorageFile));
- }
- catch (err) {
- console.log(err);
- }
- }
-
- var __ls = __data;
- __ls.setItem = function(i, v) {
- __ls[i] = v;
- this.save();
- };
- __ls.getItem = function(i) {
- return __ls[i] || null;
- };
- __ls.save = function() {
- __fs.writeFileSync(`${__dataPath}${localStorageFile}`, JSON.stringify(this), null, 4);
- };
-
- var __proxy = new Proxy(__ls, {
- set: function(target, name, val) {
- __ls[name] = val;
- __ls.save();
- },
- get: function(target, name) {
- return __ls[name] || null;
- }
- });
-
- window.localStorage = __proxy;
-
-})();
-
-(() => {
- let v2Loader = document.createElement("div");
- v2Loader.className = "bd-loaderv2";
- v2Loader.title = "BandagedBD is loading...";
- document.body.appendChild(v2Loader);
-})();
-
-/* global DiscordNative:false */
-
-var DataStore = (() => {
- const fs = require("fs");
- const path = require("path");
- const releaseChannel = DiscordNative.globals.releaseChannel;
-
- return new class DataStore {
- constructor() {
- this.data = {settings: {stable: {}, canary: {}, ptb: {}}};
- this.pluginData = {};
- }
-
- initialize() {
- try {
- if (!fs.existsSync(this.BDFile)) fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4));
- const data = require(this.BDFile);
- if (data.hasOwnProperty("settings")) this.data = data;
- if (!fs.existsSync(this.settingsFile)) return;
- let settings = require(this.settingsFile);
- fs.unlinkSync(this.settingsFile);
- if (settings.hasOwnProperty("settings")) settings = Object.assign({stable: {}, canary: {}, ptb: {}}, {[releaseChannel]: settings});
- else settings = Object.assign({stable: {}, canary: {}, ptb: {}}, settings);
- this.setBDData("settings", settings);
- }
- catch (err) {
- BdApi.alert("Corrupt Storage", "The bd storage has somehow become corrupt. You may either try to salvage the file or delete it then reload.");
- }
- }
-
- get BDFile() {return this._BDFile || (this._BDFile = path.resolve(bdConfig.dataPath, "bdstorage.json"));}
- get settingsFile() {return this._settingsFile || (this._settingsFile = path.resolve(bdConfig.dataPath, "bdsettings.json"));}
- getPluginFile(pluginName) {return path.resolve(ContentManager.pluginsFolder, pluginName + ".config.json");}
-
- getSettingGroup(key) {
- return this.data.settings[releaseChannel][key] || null;
- }
-
- setSettingGroup(key, data) {
- this.data.settings[releaseChannel][key] = data;
- fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4));
- }
-
- getBDData(key) {
- return this.data[key] || "";
- }
-
- setBDData(key, value) {
- this.data[key] = value;
- fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4));
- }
-
- getPluginData(pluginName, key) {
- if (this.pluginData[pluginName] !== undefined) return this.pluginData[pluginName][key] || undefined;
- if (!fs.existsSync(this.getPluginFile(pluginName))) return undefined;
- this.pluginData[pluginName] = JSON.parse(fs.readFileSync(this.getPluginFile(pluginName)));
- return this.pluginData[pluginName][key] || undefined;
- }
-
- setPluginData(pluginName, key, value) {
- if (value === undefined) return;
- if (this.pluginData[pluginName] === undefined) this.pluginData[pluginName] = {};
- this.pluginData[pluginName][key] = value;
- fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4));
- }
-
- deletePluginData(pluginName, key) {
- if (this.pluginData[pluginName] === undefined) this.pluginData[pluginName] = {};
- delete this.pluginData[pluginName][key];
- fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4));
- }
- };
-})();
-
-var BDEvents = (() => {
- const EventEmitter = require("events");
- return new class BDEvents extends EventEmitter {
- dispatch(eventName, ...args) {this.emit(eventName, ...args);}
- off(eventName, eventAction) {this.removeListener(eventName, eventAction);}
- };
-})();
-
-
-
-window.bdStorage = class bdPluginStorage {
- static get(key) {
- Utils.warn("Deprecation Notice", "Please use BdApi.getBDData(). bdStorage may be removed in future versions.");
- return DataStore.getBDData(key);
- }
-
- static set(key, data) {
- Utils.warn("Deprecation Notice", "Please use BdApi.setBDData(). bdStorage may be removed in future versions.");
- DataStore.setBDData(key, data);
- }
-};
-
-window.bdPluginStorage = class bdPluginStorage {
- static get(pluginName, key) {
- Utils.warn("Deprecation Notice", `${pluginName}, please use BdApi.loadData() or BdApi.getData(). bdPluginStorage may be removed in future versions.`);
- return DataStore.getPluginData(pluginName, key) || null;
- }
-
- static set(pluginName, key, data) {
- Utils.warn("Deprecation Notice", `${pluginName}, please use BdApi.saveData() or BdApi.setData(). bdPluginStorage may be removed in future versions.`);
- if (typeof(data) === "undefined") return Utils.warn("Deprecation Notice", "Trying to set undefined value in plugin " + pluginName);
- DataStore.setPluginData(pluginName, key, data);
- }
-
- static delete(pluginName, key) {
- Utils.warn("Deprecation Notice", `${pluginName}, please use BdApi.deleteData(). bdPluginStorage may be removed in future versions.`);
- DataStore.deletePluginData(pluginName, key);
- }
-};
-
-var settingsPanel, emoteModule, quickEmoteMenu, voiceMode, pluginModule, themeModule, dMode, publicServersModule;
-var minSupportedVersion = "0.3.0";
-var bbdVersion = "0.2.17";
-
-
-var mainCore;
-
-var settings = {
- "Custom css live update": {id: "bda-css-0", info: "", implemented: true, hidden: true, cat: "core"},
- "Custom css auto udpate": {id: "bda-css-1", info: "", implemented: true, hidden: true, cat: "core"},
- "BetterDiscord Blue": {id: "bda-gs-b", info: "Replace Discord blue with BD Blue", implemented: false, hidden: false, cat: "core"},
-
- /* 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: "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"},
- "Copy Selector": {id: "fork-dm-1", info: "Adds a \"Copy Selector\" option to context menus when developer mode is active", implemented: true, hidden: false, cat: "core", category: "developer settings"},
-
- /* Window Prefs */
- "Enable Transparency": {id: "fork-wp-1", info: "Enables the main window to be see-through (requires restart)", implemented: true, hidden: false, cat: "core", category: "window preferences"},
- "Window Frame": {id: "fork-wp-2", info: "Adds the native os window frame to the main window", implemented: false, hidden: true, cat: "core", category: "window preferences"},
-
-
- /* Emotes */
- /* ====== */
- "Download Emotes": {id: "fork-es-3", info: "Download emotes when the cache is expired", implemented: true, hidden: false, cat: "emote"},
- "Twitch Emotes": {id: "bda-es-7", info: "Show Twitch emotes", implemented: true, hidden: false, cat: "emote"},
- "FrankerFaceZ Emotes": {id: "bda-es-1", info: "Show FrankerFaceZ Emotes", implemented: true, hidden: false, cat: "emote"},
- "BetterTTV Emotes": {id: "bda-es-2", info: "Show BetterTTV Emotes", implemented: true, hidden: false, cat: "emote"},
- "Emote Menu": {id: "bda-es-0", info: "Show Twitch/Favourite emotes in emote menu", implemented: true, hidden: false, cat: "emote"},
- "Emoji Menu": {id: "bda-es-9", info: "Show Discord emoji menu", implemented: true, hidden: false, cat: "emote"},
- "Emote Auto Capitalization": {id: "bda-es-4", info: "Autocapitalize emote commands", implemented: true, hidden: false, cat: "emote"},
- "Show Names": {id: "bda-es-6", info: "Show emote names on hover", implemented: true, hidden: false, cat: "emote"},
- "Show emote modifiers": {id: "bda-es-8", info: "Enable emote mods (flip, spin, pulse, spin2, spin3, 1spin, 2spin, 3spin, tr, bl, br, shake, shake2, shake3, flap)", implemented: true, hidden: false, cat: "emote"},
- "Animate On Hover": {id: "fork-es-2", info: "Only animate the emote modifiers on hover", implemented: true, hidden: false, cat: "emote"}
-};
-
-var defaultCookie = {
- "bda-gs-1": true,
- "bda-gs-2": false,
- "bda-gs-3": false,
- "bda-gs-4": false,
- "bda-gs-5": true,
- "bda-gs-6": false,
- "bda-gs-7": false,
- "bda-gs-8": false,
- "bda-es-0": true,
- "bda-es-1": true,
- "bda-es-2": true,
- "bda-es-4": false,
- "bda-es-6": true,
- "bda-es-7": true,
- "bda-gs-b": false,
- "bda-es-8": true,
- "bda-dc-0": false,
- "bda-css-0": false,
- "bda-css-1": false,
- "bda-es-9": true,
- "fork-dm-1": false,
- "fork-ps-1": true,
- "fork-ps-2": true,
- "fork-ps-3": true,
- "fork-ps-4": true,
- "fork-ps-5": true,
- "fork-es-2": false,
- "fork-es-3": true,
- "fork-wp-1": false,
- "fork-wp-2": false
-};
-
-
-var settingsCookie = {};
-
-var bdpluginErrors = [], bdthemeErrors = []; // define for backwards compatibility
-
-var bdConfig = null;
-
-function Core(config) {
- window.bdConfig = config;
-}
-
-Core.prototype.init = async function() {
- if (bdConfig.version < minSupportedVersion) {
- this.alert("Not Supported", "BetterDiscord v" + bdConfig.version + " (your version)" + " is not supported by the latest js (" + bbdVersion + ").
Please download the latest version from GitHub");
- return;
- }
-
- const latestLocalVersion = bdConfig.updater ? bdConfig.updater.LatestVersion : bdConfig.latestVersion;
- if (latestLocalVersion > bdConfig.version) {
- this.alert("Update Available", `
- An update for BandagedBD is available (${latestLocalVersion})! Please Reinstall!
- Download Installer
- `);
- }
-
- Utils.log("Startup", "Initializing Settings");
- this.initSettings();
- emoteModule = new EmoteModule();
- quickEmoteMenu = new QuickEmoteMenu();
- Utils.log("Startup", "Initializing EmoteModule");
- window.emotePromise = emoteModule.init().then(() => {
- emoteModule.initialized = true;
- Utils.log("Startup", "Initializing QuickEmoteMenu");
- quickEmoteMenu.init();
- });
- publicServersModule = new V2_PublicServers();
-
- voiceMode = new VoiceMode();
- dMode = new devMode();
-
- this.injectExternals();
-
- await this.checkForGuilds();
- BDV2.initialize();
- Utils.log("Startup", "Updating Settings");
- settingsPanel = new V2_SettingsPanel();
- settingsPanel.initializeSettings();
-
- Utils.log("Startup", "Loading Plugins");
- pluginModule = new PluginModule();
- pluginModule.loadPlugins();
-
- Utils.log("Startup", "Loading Themes");
- themeModule = new ThemeModule();
- themeModule.loadThemes();
-
- $("#customcss").detach().appendTo(document.head);
-
- window.addEventListener("beforeunload", function() {
- if (settingsCookie["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click();
- });
-
- emoteModule.autoCapitalize();
-
- Utils.log("Startup", "Removing Loading Icon");
- document.getElementsByClassName("bd-loaderv2")[0].remove();
- Utils.log("Startup", "Initializing Main Observer");
- this.initObserver();
-
- // Show loading errors
- if (settingsCookie["fork-ps-1"]) {
- Utils.log("Startup", "Collecting Startup Errors");
- this.showContentErrors({plugins: bdpluginErrors, themes: bdthemeErrors});
- }
-
- // if (!DataStore.getBDData(bbdVersion)) {
- // BdApi.alert("BBD Updated!", ["Lots of things were fixed in this update like Public Servers, Minimal Mode, Dark Mode and 24 Hour Timestamps.", BdApi.React.createElement("br"), BdApi.React.createElement("br"), "Feel free to test them all out!"]);
- // DataStore.setBDData(bbdVersion, true);
- // }
-};
-
-Core.prototype.checkForGuilds = function() {
- return new Promise(resolve => {
- const checkForGuilds = function() {
- const wrapper = BDV2.guildClasses.wrapper.split(" ")[0];
- const guild = BDV2.guildClasses.listItem.split(" ")[0];
- const blob = BDV2.guildClasses.blobContainer.split(" ")[0];
- if (document.querySelectorAll(`.${wrapper} .${guild} .${blob}`).length > 0) return resolve(bdConfig.deferLoaded = true);
- setTimeout(checkForGuilds, 100);
- };
- $(document).ready(function () {
- setTimeout(checkForGuilds, 100);
- });
- });
-};
-
-Core.prototype.injectExternals = async function() {
- await Utils.injectJs("https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js");
- if (require.original) window.require = require.original;
-};
-
-Core.prototype.initSettings = function () {
- DataStore.initialize();
- if (!DataStore.getSettingGroup("settings")) {
- settingsCookie = defaultCookie;
- this.saveSettings();
- }
- else {
- this.loadSettings();
- $("");
- }
- $("#customcss").text(this.editor.session.getValue()).detach().appendTo(document.head);
- }
-
- saveCss() {
- DataStore.setBDData("bdcustomcss", btoa(this.editor.session.getValue()));
- }
-}
-
-class V2C_CssEditor extends BDV2.reactComponent {
-
- constructor(props) {
- super(props);
- let self = this;
- self.props.lines = 0;
- self.setInitialState();
- self.attach = self.attach.bind(self);
- self.detachedEditor = BDV2.react.createElement(V2C_CssEditorDetached, {attach: self.attach});
- self.onClick = self.onClick.bind(self);
- self.updateCss = self.updateCss.bind(self);
- self.saveCss = self.saveCss.bind(self);
- self.detach = self.detach.bind(self);
- }
-
- setInitialState() {
- this.state = {
- detached: this.props.detached || BDV2.editorDetached
- };
- }
-
- componentDidMount() {
- // this.updateLineCount();
- this.editor = ace.edit("bd-customcss-editor");
- this.editor.setTheme("ace/theme/monokai");
- this.editor.session.setMode("ace/mode/css");
- this.editor.setShowPrintMargin(false);
- this.editor.setFontSize(14);
- this.editor.on("change", () => {
- if (!settingsCookie["bda-css-0"]) return;
- this.saveCss();
- this.updateCss();
- });
- }
-
- componentWillUnmount() {
- this.editor.destroy();
- }
-
- componentDidUpdate(prevProps, prevState) {
- let self = this;
- if (prevState.detached && !self.state.detached) {
- BDV2.reactDom.unmountComponentAtNode(self.detachedRoot);
- }
- }
-
- codeMirror() {
- }
-
- get options() {
- return {
- lineNumbers: true,
- mode: "css",
- indentUnit: 4,
- theme: "material",
- scrollbarStyle: "simple"
- };
- }
-
- get css() {
- let _ccss = DataStore.getBDData("bdcustomcss");
- let ccss = "";
- if (_ccss && _ccss !== "") {
- ccss = atob(_ccss);
- }
- return ccss;
- }
-
- updateLineCount() {
- let lineCount = this.refs.editor.value.split("\n").length;
- if (lineCount == this.props.lines) return;
- this.refs.lines.textContent = Array.from(new Array(lineCount), (_, i) => i + 1).join(".\n") + ".";
- this.props.lines = lineCount;
- }
-
- render() {
- let self = this;
-
- let {detached} = self.state;
- return BDV2.react.createElement(
- "div",
- {className: "contentColumn-2hrIYH contentColumnDefault-1VQkGM content-column default", style: {padding: "60px 40px 0px"}},
- detached && BDV2.react.createElement(
- "div",
- {id: "editor-detached"},
- BDV2.react.createElement(V2Components.SettingsTitle, {text: "Custom CSS Editor"}),
- BDV2.react.createElement(
- "h3",
- null,
- "Editor Detached"
- ),
- BDV2.react.createElement(
- "button",
- {className: "btn btn-primary", onClick: () => {
- self.attach();
- }},
- "Attach"
- )
- ),
- !detached && BDV2.react.createElement(
- "div",
- null,
- BDV2.react.createElement(V2Components.SettingsTitle, {text: "Custom CSS Editor"}),
- BDV2.react.createElement("div", {className: "editor-wrapper"},
- BDV2.react.createElement("div", {id: "bd-customcss-editor", className: "editor", ref: "editor"}, self.css)
- ),
- BDV2.react.createElement(
- "div",
- {id: "bd-customcss-attach-controls"},
- BDV2.react.createElement(
- "ul",
- {className: "checkbox-group"},
- BDV2.react.createElement(V2Components.Checkbox, {id: "live-update", text: "Live Update", onChange: this.onChange, checked: settingsCookie["bda-css-0"]})
- ),
- BDV2.react.createElement(
- "div",
- {id: "bd-customcss-detach-controls-button"},
- BDV2.react.createElement(
- "button",
- {style: {borderRadius: "3px 0 0 3px", borderRight: "1px solid #3f4146"}, className: "btn btn-primary", onClick: () => {
- self.onClick("update");
- }},
- "Update"
- ),
- BDV2.react.createElement(
- "button",
- {style: {borderRadius: "0", borderLeft: "1px solid #2d2d2d", borderRight: "1px solid #2d2d2d"}, className: "btn btn-primary", onClick: () => {
- self.onClick("save");
- }},
- "Save"
- ),
- BDV2.react.createElement(
- "button",
- {style: {borderRadius: "0 3px 3px 0", borderLeft: "1px solid #3f4146"}, className: "btn btn-primary", onClick: () => {
- self.onClick("detach");
- }},
- "Detach"
- ),
- BDV2.react.createElement(
- "span",
- {style: {fontSize: "10px", marginLeft: "5px"}},
- "Unsaved changes are lost on detach"
- ),
- BDV2.react.createElement("div", {className: "help-text"},
- "Press ",
- BDV2.react.createElement("code", {className: "inline"}, "ctrl"),
- "+",
- BDV2.react.createElement("span", {className: "inline"}, ","),
- " with the editor focused to access the editor's settings."
- )
- )
- )
- )
- );
- }
-
- onClick(arg) {
- let self = this;
- switch (arg) {
- case "update":
- self.updateCss();
- break;
- case "save":
- self.saveCss();
- break;
- case "detach":
- self.detach();
- break;
- }
- }
-
- onChange(id, checked) {
- switch (id) {
- case "live-update":
- settingsCookie["bda-css-0"] = checked;
- mainCore.saveSettings();
- break;
- }
- }
-
- updateCss() {
- if ($("#customcss").length == 0) {
- $("head").append("");
- }
- $("#customcss").text(this.editor.session.getValue()).detach().appendTo(document.head);
- }
-
- saveCss() {
- DataStore.setBDData("bdcustomcss", btoa(this.editor.session.getValue()));
- }
-
- detach() {
- let self = this;
- self.setState({
- detached: true
- });
- let droot = self.detachedRoot;
- if (!droot) {
- console.log("FAILED TO INJECT ROOT: .app");
- return;
- }
- BDV2.reactDom.render(self.detachedEditor, droot);
- }
-
- get detachedRoot() {
- let _root = $("#bd-customcss-detach-container");
- if (!_root.length) {
- if (!this.injectDetachedRoot()) return null;
- return this.detachedRoot;
- }
- return _root[0];
- }
-
- injectDetachedRoot() {
- if (!$(".app, .app-2rEoOp").length) return false;
- $("
", {
- id: "bd-customcss-detach-container"
- }).insertAfter($(".app, .app-2rEoOp"));
- return true;
- }
-
- attach() {
- let self = this;
- self.setState({
- detached: false
- });
- }
-}
-
-class V2C_List extends BDV2.reactComponent {
- constructor(props) {
- super(props);
- }
-
- render() {
- return BDV2.react.createElement(
- "ul",
- {className: this.props.className},
- this.props.children
- );
- }
-}
-
-class V2C_ContentColumn extends BDV2.reactComponent {
- constructor(props) {
- super(props);
- }
-
- render() {
- return BDV2.react.createElement(
- "div",
- {className: "contentColumn-2hrIYH contentColumnDefault-1VQkGM content-column default"},
- BDV2.react.createElement(
- "h2",
- {className: "ui-form-title h2 margin-reset margin-bottom-20"},
- this.props.title
- ),
- this.props.children
- );
- }
-}
-
-class V2C_PluginCard extends BDV2.reactComponent {
-
- constructor(props) {
- super(props);
- let self = this;
- self.onChange = self.onChange.bind(self);
- self.showSettings = self.showSettings.bind(self);
- self.setInitialState();
- self.hasSettings = typeof self.props.plugin.getSettingsPanel === "function";
- self.settingsPanel = "";
-
- this.reload = this.reload.bind(this);
- this.onReload = this.onReload.bind(this);
- }
-
- setInitialState() {
- this.state = {
- checked: pluginCookie[this.props.plugin.getName()],
- settings: false,
- reloads: 0
- };
- }
-
- // componentDidMount() {
- // BDEvents.on("plugin-reloaded", this.onReload);
- // }
-
- // componentWillUnmount() {
- // BDEvents.off("plugin-reloaded", this.onReload);
- // }
-
- onReload(pluginName) {
- if (pluginName !== this.props.plugin.getName()) return;
- this.setState({reloads: this.state.reloads + 1});
- }
-
- componentDidUpdate() {
- if (this.state.settings) {
- if (typeof this.settingsPanel === "object") {
- this.refs.settingspanel.appendChild(this.settingsPanel);
- }
-
- if (!settingsCookie["fork-ps-3"]) return;
- var isHidden = (container, element) => {
-
- let cTop = container.scrollTop;
- let cBottom = cTop + container.clientHeight;
-
- let eTop = element.offsetTop;
- let eBottom = eTop + element.clientHeight;
-
- return (eTop < cTop || eBottom > cBottom);
- };
-
- let self = $(BDV2.reactDom.findDOMNode(this));
- let container = self.parents(".scroller");
- if (!isHidden(container[0], self[0])) return;
- container.animate({
- scrollTop: self.offset().top - container.offset().top + container.scrollTop() - 30
- }, 300);
- }
- }
-
- reload() {
- const plugin = this.props.plugin.getName();
- pluginModule.reloadPlugin(plugin);
- this.props.plugin = bdplugins[plugin].plugin;
- this.onReload(this.props.plugin.getName());
- }
-
- getString(value) {
- return typeof value == "string" ? value : value.toString();
- }
-
- render() {
- let self = this;
- let {plugin} = this.props;
- let name = this.getString(plugin.getName());
- 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;
-
- if (this.state.settings) {
- try { self.settingsPanel = plugin.getSettingsPanel(); }
- catch (err) { Utils.err("Plugins", "Unable to get settings panel for " + plugin.getName() + ".", err); }
-
- return BDV2.react.createElement("li", {className: "settings-open ui-switch-item"},
- BDV2.react.createElement("div", {style: {"float": "right", "cursor": "pointer"}, onClick: () => {
- this.refs.settingspanel.innerHTML = "";
- self.setState({settings: false});
- }},
- BDV2.react.createElement(V2Components.XSvg, null)
- ),
- typeof self.settingsPanel === "object" && BDV2.react.createElement("div", {id: `plugin-settings-${name}`, className: "plugin-settings", ref: "settingspanel"}),
- typeof self.settingsPanel !== "object" && BDV2.react.createElement("div", {id: `plugin-settings-${name}`, className: "plugin-settings", ref: "settingspanel", dangerouslySetInnerHTML: {__html: self.settingsPanel}})
- );
- }
-
- return BDV2.react.createElement("li", {"data-name": name, "data-version": version, "className": "settings-closed ui-switch-item"},
- BDV2.react.createElement("div", {className: "bda-header"},
- BDV2.react.createElement("span", {className: "bda-header-title"},
- BDV2.react.createElement("span", {className: "bda-name"}, name),
- " v",
- BDV2.react.createElement("span", {className: "bda-version"}, version),
- " by ",
- BDV2.react.createElement("span", {className: "bda-author"}, author)
- ),
- BDV2.react.createElement("div", {className: "bda-controls"},
- !settingsCookie["fork-ps-5"] && BDV2.react.createElement(V2Components.TooltipWrap(V2Components.ReloadIcon, {color: "black", side: "top", text: "Reload"}), {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"})
- )
- )
- ),
- BDV2.react.createElement("div", {className: "bda-description-wrap scroller-wrap fade"},
- BDV2.react.createElement("div", {className: "bda-description scroller"}, description)
- ),
- (website || source || this.hasSettings) && BDV2.react.createElement("div", {className: "bda-footer"},
- BDV2.react.createElement("span", {className: "bda-links"},
- website && BDV2.react.createElement("a", {className: "bda-link bda-link-website", href: website, target: "_blank"}, "Website"),
- website && source && " | ",
- source && BDV2.react.createElement("a", {className: "bda-link bda-link-source", href: source, target: "_blank"}, "Source")
- ),
- this.hasSettings && BDV2.react.createElement("button", {onClick: this.showSettings, className: "bda-settings-button", disabled: !this.state.checked}, "Settings")
- )
- );
- }
-
- onChange() {
- this.setState({checked: !this.state.checked});
- pluginModule.togglePlugin(this.props.plugin.getName());
- }
-
- showSettings() {
- if (!this.hasSettings) return;
- this.setState({settings: true});
- }
-}
-
-class V2C_ThemeCard extends BDV2.reactComponent {
-
- constructor(props) {
- super(props);
- this.setInitialState();
- this.onChange = this.onChange.bind(this);
- this.reload = this.reload.bind(this);
- }
-
- setInitialState() {
- this.state = {
- checked: themeCookie[this.props.theme.name],
- reloads: 0
- };
- }
-
- // componentDidMount() {
- // BDEvents.on("theme-reloaded", this.onReload);
- // }
-
- // componentWillUnmount() {
- // BDEvents.off("theme-reloaded", this.onReload);
- // }
-
- onReload(themeName) {
- if (themeName !== this.props.theme.name) return;
- this.setState({reloads: this.state.reloads + 1});
- }
-
- reload() {
- const theme = this.props.theme.name;
- const error = themeModule.reloadTheme(theme);
- if (error) mainCore.showToast(`Could not reload ${bdthemes[theme].name}. Check console for details.`, {type: "error"});
- else mainCore.showToast(`${bdthemes[theme].name} v${bdthemes[theme].version} has been reloaded.`, {type: "success"});
- // this.setState(this.state);
- this.props.theme = bdthemes[theme];
- this.onReload(this.props.theme.name);
- }
-
- render() {
- let {theme} = this.props;
- let name = theme.name;
- let description = theme.description;
- let version = theme.version;
- let author = theme.author;
- let website = bdthemes[name].website;
- let source = bdthemes[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"},
- BDV2.react.createElement("span", {className: "bda-header-title"},
- BDV2.react.createElement("span", {className: "bda-name"}, name),
- " v",
- BDV2.react.createElement("span", {className: "bda-version"}, version),
- " by ",
- BDV2.react.createElement("span", {className: "bda-author"}, author)
- ),
- BDV2.react.createElement("div", {className: "bda-controls"},
- !settingsCookie["fork-ps-5"] && BDV2.react.createElement(V2Components.TooltipWrap(V2Components.ReloadIcon, {color: "black", side: "top", text: "Reload"}), {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"})
- )
- )
- ),
- BDV2.react.createElement("div", {className: "bda-description-wrap scroller-wrap fade"},
- BDV2.react.createElement("div", {className: "bda-description scroller"}, description)
- ),
- (website || source) && BDV2.react.createElement("div", {className: "bda-footer"},
- BDV2.react.createElement("span", {className: "bda-links"},
- website && BDV2.react.createElement("a", {className: "bda-link", href: website, target: "_blank"}, "Website"),
- website && source && " | ",
- source && BDV2.react.createElement("a", {className: "bda-link", href: source, target: "_blank"}, "Source")
- )
- )
- );
- }
-
- onChange() {
- this.setState({checked: !this.state.checked});
- themeModule.toggleTheme(this.props.theme.name);
- }
-}
-
-class V2Cs_TabBar {
- static get Item() {
- return V2C_TabBarItem;
- }
- static get Header() {
- return V2C_TabBarHeader;
- }
- static get Separator() {
- return V2C_TabBarSeparator;
- }
-}
-
-
-class V2Components {
- static get SettingsGroup() {
- return V2C_SettingsGroup;
- }
- static get SectionedSettingsPanel() {
- return V2C_SectionedSettingsPanel;
- }
- static get SettingsPanel() {
- return V2C_SettingsPanel;
- }
- static get Switch() {
- return V2C_Switch;
- }
- static get Scroller() {
- return V2C_Scroller;
- }
- static get TabBar() {
- return V2Cs_TabBar;
- }
- static get SideBar() {
- return V2C_SideBar;
- }
- static get Tools() {
- return V2C_Tools;
- }
- static get SettingsTitle() {
- return V2C_SettingsTitle;
- }
- static get CssEditor() {
- return V2C_CssEditor;
- }
- static get Checkbox() {
- return V2C_Checkbox;
- }
- static get List() {
- return V2C_List;
- }
- static get PluginCard() {
- return V2C_PluginCard;
- }
- static get ThemeCard() {
- return V2C_ThemeCard;
- }
- static get ContentColumn() {
- return V2C_ContentColumn;
- }
- static get ReloadIcon() {
- return V2C_ReloadIcon;
- }
- static get XSvg() {
- return V2C_XSvg;
- }
- static get Layer() {
- return V2C_Layer;
- }
- static get SidebarView() {
- return V2C_SidebarView;
- }
- static get ServerCard() {
- return V2C_ServerCard;
- }
-
- static TooltipWrap(Component, options) {
-
- const {style = "black", side = "top", text = ""} = options;
- const id = BDV2.KeyGenerator();
-
- return class extends BDV2.reactComponent {
- constructor(props) {
- super(props);
- this.onMouseEnter = this.onMouseEnter.bind(this);
- this.onMouseLeave = this.onMouseLeave.bind(this);
- }
-
- componentDidMount() {
- this.node = BDV2.reactDom.findDOMNode(this);
- this.node.addEventListener("mouseenter", this.onMouseEnter);
- this.node.addEventListener("mouseleave", this.onMouseLeave);
- }
-
- componentWillUnmount() {
- this.node.removeEventListener("mouseenter", this.onMouseEnter);
- this.node.removeEventListener("mouseleave", this.onMouseLeave);
- }
-
- onMouseEnter() {
- if (!BDV2.Tooltips) return;
- const {left, top, width, height} = this.node.getBoundingClientRect();
- BDV2.Tooltips.show(id, {
- position: side,
- text: text,
- color: style,
- targetWidth: width,
- targetHeight: height,
- windowWidth: Utils.screenWidth,
- windowHeight: Utils.screenHeight,
- x: left,
- y: top
- });
-
- const observer = new MutationObserver((mutations) => {
- mutations.forEach((mutation) => {
- const nodes = Array.from(mutation.removedNodes);
- const directMatch = nodes.indexOf(this.node) > -1;
- const parentMatch = nodes.some(parent => parent.contains(this.node));
- if (directMatch || parentMatch) {
- this.onMouseLeave();
- observer.disconnect();
- }
- });
- });
-
- observer.observe(document.body, {subtree: true, childList: true});
- }
-
- onMouseLeave() {
- if (!BDV2.Tooltips) return;
- BDV2.Tooltips.hide(id);
- }
-
- render() {
- return BDV2.react.createElement(Component, this.props);
- }
- };
- }
-}
-
-class V2_SettingsPanel_Sidebar {
-
- constructor(onClick) {
- this.onClick = onClick;
- }
-
- get items() {
- return [{text: "Settings", id: "core"}, {text: "Emotes", id: "emotes"}, {text: "Plugins", id: "plugins"}, {text: "Themes", id: "themes"}, {text: "Custom CSS", id: "customcss"}];
- }
-
- get component() {
- return BDV2.react.createElement(
- "span",
- null,
- BDV2.react.createElement(V2Components.SideBar, {onClick: this.onClick, headerText: "Bandaged BD", items: this.items}),
- BDV2.react.createElement(
- "div",
- {style: {fontSize: "12px", fontWeight: "600", color: "#72767d", padding: "2px 10px"}},
- `BD v${bdConfig.version} by `,
- BDV2.react.createElement(
- "a",
- {href: "https://github.com/Jiiks/", target: "_blank"},
- "Jiiks"
- )
- ),
- BDV2.react.createElement(
- "div",
- {style: {fontSize: "12px", fontWeight: "600", color: "#72767d", padding: "2px 10px"}},
- `BBD v${bbdVersion} by `,
- BDV2.react.createElement(
- "a",
- {href: "https://github.com/rauenzi/", target: "_blank"},
- "Zerebos"
- )
- )
- );
- }
-
- get root() {
- let _root = $("#bd-settings-sidebar");
- if (!_root.length) {
- if (!this.injectRoot()) return null;
- return this.root;
- }
- return _root[0];
- }
-
- injectRoot() {
- let changeLog = $("[class*='side-'] > [class*='item-']:not([class*=Danger])").last();
- if (!changeLog.length) return false;
- $("", {id: "bd-settings-sidebar"}).insertBefore(changeLog.prev());
- return true;
- }
-
- render() {
- let root = this.root;
- if (!root) {
- console.log("FAILED TO LOCATE ROOT: [class*='side-'] > [class*='item-']:not([class*=Danger])");
- return;
- }
- BDV2.reactDom.render(this.component, root);
- Utils.onRemoved(root, () => {
- BDV2.reactDom.unmountComponentAtNode(root);
- });
- }
-}
-
-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 V2_SettingsPanel_Sidebar(self.sideBarOnClick);
- }
-
- get root() {
- let _root = $("#bd-settingspane-container");
- if (!_root.length) {
- if (!this.injectRoot()) return null;
- return this.root;
- }
- return _root[0];
- }
-
- injectRoot() {
- if (!$(".layer-3QrUeG .standardSidebarView-3F1I7i, .layer-3QrUeG .ui-standard-sidebar-view").length) return false;
- const root = $("", {
- "class": "contentRegion-3nDuYy content-region",
- "id": "bd-settingspane-container"
- });
- $(".layer-3QrUeG .standardSidebarView-3F1I7i, .layer-3QrUeG .ui-standard-sidebar-view").append(root);
-
- Utils.onRemoved(root[0], () => {
- BDV2.reactDom.unmountComponentAtNode(root[0]);
- });
- return true;
- }
-
- get coreSettings() {
- const settings = this.getSettings("core");
- const categories = [...new Set(settings.map(s => s.category))];
- const sections = categories.map(c => {return {title: c, settings: settings.filter(s => s.category == c)};});
- return sections;
- }
-
- get emoteSettings() {
- return this.getSettings("emote");
- }
- getSettings(category) {
- return Object.keys(settings).reduce((arr, key) => {
- let setting = settings[key];
- if (setting.cat === category && setting.implemented && !setting.hidden) {
- setting.text = key;
- arr.push(setting);
- }
- return arr;
- }, []);
- }
-
- sideBarOnClick(id) {
- let self = this;
- $(".contentRegion-3nDuYy, .content-region").first().hide();
- $(self.root).show();
- switch (id) {
- case "core":
- self.renderCoreSettings();
- break;
- case "emotes":
- self.renderEmoteSettings();
- break;
- case "customcss":
- self.renderCustomCssEditor();
- break;
- case "plugins":
- self.renderPluginPane();
- break;
- case "themes":
- self.renderThemePane();
- break;
- }
- }
-
- onClick() {}
-
- onChange(id, checked) {
- this.updateSettings(id, checked);
- }
-
- 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-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) publicServersModule.addButton();
- else publicServersModule.removeButton();
- }
-
- 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") mainCore.inject24Hour();
-
- if (id == "bda-gs-7") {
- if (enabled) mainCore.injectColoredText();
- else mainCore.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) dMode.enable(settingsCookie["fork-dm-1"]);
- else dMode.disable();
- }
-
- if (id == "fork-dm-1") {
- if (settingsCookie["bda-gs-8"]) dMode.enable(enabled);
- }
-
- mainCore.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"]) publicServersModule.addButton();
- if (settingsCookie["bda-gs-4"]) voiceMode.enable();
- if (settingsCookie["bda-gs-5"]) $("#app-mount").addClass("bda-dark");
- if (settingsCookie["bda-gs-6"]) mainCore.inject24Hour();
- if (settingsCookie["bda-gs-7"]) mainCore.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"]) dMode.enable(settingsCookie["fork-dm-1"]);
-
- mainCore.saveSettings();
- }
-
- renderSidebar() {
- let self = this;
- $("[class*='side-'] > [class*='item-']").off("click.v2settingspanel").on("click.v2settingspanel", () => {
- BDV2.reactDom.unmountComponentAtNode(self.root);
- $(self.root).hide();
- $(".contentRegion-3nDuYy, .content-region").first().show();
- });
- self.sidebar.render();
- }
-
- get coreComponent() {
- return BDV2.react.createElement(V2Components.Scroller, {contentColumn: true, fade: true, dark: true, children: [
- BDV2.react.createElement(V2Components.SectionedSettingsPanel, {key: "cspanel", onChange: this.onChange, sections: this.coreSettings}),
- BDV2.react.createElement(V2Components.Tools, {key: "tools"})
- ]});
- }
-
- get emoteComponent() {
- return BDV2.react.createElement(V2Components.Scroller, {
- contentColumn: true, fade: true, dark: true, children: [
- BDV2.react.createElement(V2Components.SettingsPanel, {key: "espanel", title: "Emote Settings", onChange: this.onChange, settings: this.emoteSettings, button: {
- title: "Clear Emote Cache",
- onClick: () => { emoteModule.clearEmoteData(); emoteModule.init(); quickEmoteMenu.init(); }
- }}),
- BDV2.react.createElement(V2Components.Tools, {key: "tools"})
- ]});
- }
-
- get customCssComponent() {
- return BDV2.react.createElement(V2Components.Scroller, {contentColumn: true, fade: true, dark: true, children: [BDV2.react.createElement(V2Components.CssEditor, {key: "csseditor"}), BDV2.react.createElement(V2Components.Tools, {key: "tools"})]});
- }
-
- contentComponent(type) {
- const componentElement = type == "plugins" ? this.pluginsComponent : this.themesComponent;
- const prefix = type.replace("s", "");
- const settingsList = this;
- class ContentList extends BDV2.react.Component {
- constructor(props) {
- super(props);
- this.onChange = this.onChange.bind(this);
- }
-
- componentDidMount() {
- BDEvents.on(`${prefix}-reloaded`, this.onChange);
- BDEvents.on(`${prefix}-loaded`, this.onChange);
- BDEvents.on(`${prefix}-unloaded`, this.onChange);
- }
-
- componentWillUnmount() {
- BDEvents.off(`${prefix}-reloaded`, this.onChange);
- BDEvents.off(`${prefix}-loaded`, this.onChange);
- BDEvents.off(`${prefix}-unloaded`, this.onChange);
- }
-
- onChange() {
- settingsList.sideBarOnClick(type);
- }
-
- render() {return componentElement;}
- }
- return BDV2.react.createElement(ContentList);
- }
-
- get pluginsComponent() {
- let plugins = Object.keys(bdplugins).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reduce((arr, key) => {
- arr.push(BDV2.react.createElement(V2Components.PluginCard, {key: key, plugin: bdplugins[key].plugin}));return arr;
- }, []);
- let list = BDV2.react.createElement(V2Components.List, {key: "plugin-list", className: "bda-slist", children: plugins});
- let refreshIcon = !settingsCookie["fork-ps-5"] && BDV2.react.createElement(V2Components.TooltipWrap(V2Components.ReloadIcon, {color: "black", side: "top", text: "Reload Plugin List"}), {className: "bd-reload-header", size: "18px", onClick: async () => {
- pluginModule.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");
- let contentColumn = BDV2.react.createElement(V2Components.ContentColumn, {key: "pcolumn", title: "Plugins", children: [refreshIcon, pfBtn, list]});
- return BDV2.react.createElement(V2Components.Scroller, {contentColumn: true, fade: true, dark: true, children: [contentColumn, BDV2.react.createElement(V2Components.Tools, {key: "tools"})]});
- }
-
- get themesComponent() {
- let themes = Object.keys(bdthemes).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reduce((arr, key) => {
- arr.push(BDV2.react.createElement(V2Components.ThemeCard, {key: key, theme: bdthemes[key]}));return arr;
- }, []);
- let list = BDV2.react.createElement(V2Components.List, {key: "theme-list", className: "bda-slist", children: themes});
- let refreshIcon = !settingsCookie["fork-ps-5"] && BDV2.react.createElement(V2Components.TooltipWrap(V2Components.ReloadIcon, {color: "black", side: "top", text: "Reload Theme List"}), {className: "bd-reload-header", size: "18px", onClick: async () => {
- themeModule.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");
- let contentColumn = BDV2.react.createElement(V2Components.ContentColumn, {key: "tcolumn", title: "Themes", children: [refreshIcon, tfBtn, list]});
- return BDV2.react.createElement(V2Components.Scroller, {contentColumn: true, fade: true, dark: true, children: [contentColumn, BDV2.react.createElement(V2Components.Tools, {key: "tools"})]});
- }
-
- renderCoreSettings() {
- let root = this.root;
- if (!root) {
- console.log("FAILED TO LOCATE ROOT: .layer-3QrUeG .standardSidebarView-3F1I7i");
- return;
- }
- BDV2.reactDom.render(this.coreComponent, root);
- }
-
- renderEmoteSettings() {
- let root = this.root;
- if (!root) {
- console.log("FAILED TO LOCATE ROOT: .layer-3QrUeG .standardSidebarView-3F1I7i");
- return;
- }
- BDV2.reactDom.render(this.emoteComponent, root);
- }
-
- renderCustomCssEditor() {
- let root = this.root;
- if (!root) {
- console.log("FAILED TO LOCATE ROOT: .layer-3QrUeG .standardSidebarView-3F1I7i");
- return;
- }
- BDV2.reactDom.render(this.customCssComponent, root);
- }
-
- renderPluginPane() {
- let root = this.root;
- if (!root) {
- console.log("FAILED TO LOCATE ROOT: .layer-3QrUeG .standardSidebarView-3F1I7i");
- return;
- }
- BDV2.reactDom.render(this.contentComponent("plugins"), root);
- }
-
- renderThemePane() {
- let root = this.root;
- if (!root) {
- console.log("FAILED TO LOCATE ROOT: .layer-3QrUeG .standardSidebarView-3F1I7i");
- return;
- }
- BDV2.reactDom.render(this.contentComponent("themes"), root);
- }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-class V2C_Layer extends BDV2.reactComponent {
-
- constructor(props) {
- super(props);
- }
-
- componentDidMount() {
- $(window).on(`keyup.${this.props.id}`, e => {
- if (e.which === 27) {
- BDV2.reactDom.unmountComponentAtNode(this.refs.root.parentNode);
- }
- });
-
- $(`#${this.props.id}`).animate({opacity: 1}, {
- step: function(now) {
- $(this).css("transform", `scale(${1.1 - 0.1 * now}) translateZ(0px)`);
- },
- duration: 200,
- done: () => {$(`#${this.props.id}`).css("opacity", "").css("transform", "");}
- });
- }
-
- componentWillUnmount() {
- $(window).off(`keyup.${this.props.id}`);
- $(`#${this.props.id}`).animate({opacity: 0}, {
- step: function(now) {
- $(this).css("transform", `scale(${1.1 - 0.1 * now}) translateZ(0px)`);
- },
- duration: 200,
- done: () => {$(`#${this.props.rootId}`).remove();}
- });
-
- $("[class*=\"layer-\"]").removeClass("publicServersOpen").animate({opacity: 1}, {
- step: function(now) {
- $(this).css("transform", `scale(${0.07 * now + 0.93}) translateZ(0px)`);
- },
- duration: 200,
- done: () => {$("[class*=\"layer-\"]").css("opacity", "").css("transform", "");}
- });
-
- }
-
- componentWillMount() {
- $("[class*=\"layer-\"]").addClass("publicServersOpen").animate({opacity: 0}, {
- step: function(now) {
- $(this).css("transform", `scale(${0.07 * now + 0.93}) translateZ(0px)`);
- },
- duration: 200
- });
- }
-
- render() {
- return BDV2.react.createElement(
- "div",
- {className: "layer bd-layer layer-3QrUeG", id: this.props.id, ref: "root", style: {opacity: 0, transform: "scale(1.1) translateZ(0px)"}},
- this.props.children
- );
- }
-}
-
-class V2C_SidebarView extends BDV2.reactComponent {
-
- constructor(props) {
- super(props);
- }
-
- render() {
- let {sidebar, content, tools} = this.props.children;
- return BDV2.react.createElement(
- "div",
- {className: "standardSidebarView-3F1I7i ui-standard-sidebar-view"},
- BDV2.react.createElement(
- "div",
- {className: "sidebarRegion-VFTUkN sidebar-region"},
- BDV2.react.createElement(V2Components.Scroller, {key: "sidebarScroller", ref: "sidebarScroller", sidebar: true, fade: sidebar.fade || true, dark: sidebar.dark || true, children: sidebar.component})
- ),
- BDV2.react.createElement("div", {className: "contentRegion-3nDuYy content-region"},
- BDV2.react.createElement("div", {className: "contentTransitionWrap-3hqOEW content-transition-wrap"},
- BDV2.react.createElement("div", {className: "scrollerWrap-2lJEkd firefoxFixScrollFlex-cnI2ix contentRegionScrollerWrap-3YZXdm content-region-scroller-wrap scrollerThemed-2oenus themeGhost-28MSn0 scrollerTrack-1ZIpsv"},
- BDV2.react.createElement("div", {className: "scroller-2FKFPG firefoxFixScrollFlex-cnI2ix contentRegionScroller-26nc1e content-region-scroller scroller", ref: "contentScroller"},
- BDV2.react.createElement("div", {className: "contentColumn-2hrIYH contentColumnDefault-1VQkGM content-column default"}, content.component),
- tools.component
- )
- )
- )
- )
- );
- }
-}
-
-
-class V2_PublicServers {
-
- constructor() {
- this._appendButton = this._appendButton.bind(this);
- }
-
- get component() {
- return BDV2.react.createElement(V2Components.Layer, {rootId: "pubslayerroot", id: "pubslayer", children: BDV2.react.createElement(V2C_PublicServers, {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($("", {
- 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 = $("", {
- "class": BDV2.guildClasses.listItem,
- "id": "bd-pub-li",
- "style": settingsCookie["bda-gs-1"] ? "" : "display: none;"
- }).append($("", {
- "class": "wrapper-25eVIn " + BDV2.guildClasses.circleButtonMask,
- "text": "public",
- "id": "bd-pub-button",
- "click": () => { this.render(); }
- }));
-
- return btn;
- }
-
- _appendButton() {
- if ($("#bd-pub-li").length) return;
- const wrapper = BDV2.guildClasses.wrapper.split(" ")[0];
- const guilds = $(`.${wrapper} .scroller-2FKFPG >:first-child`);
- guilds.after(this.button);
- }
-
- addButton() {
- if (this.guildPatch) return;
- const GuildList = BdApi.findModuleByDisplayName("Guilds");
- this.guildPatch = BdApi.monkeyPatch(GuildList.prototype, "render", {after: this._appendButton});
- this._appendButton();
- }
-
- removeButton() {
- this.guildPatch();
- delete this.guildPatch;
- $("#bd-pub-li").remove();
- }
-}
-
-
-class V2C_ServerCard extends BDV2.reactComponent {
- constructor(props) {
- super(props);
- if (!this.props.server.iconUrl) this.props.server.iconUrl = this.props.fallback;
- this.state = {
- imageError: false,
- joined: this.props.guildList.includes(this.props.server.identifier)
- };
- }
-
- render() {
- let {server} = this.props;
- return BDV2.react.createElement(
- "div", // cardPrimary-1Hv-to
- {className: `card-3Qj_Yx cardPrimary-1Hv-to marginBottom8-AtZOdT bd-server-card${server.pinned ? " bd-server-card-pinned" : ""}`},
- // BDV2.react.createElement(
- // "div",
- // { className: "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY flex-1O1GKY directionRow-3v3tfG justifyStart-2yIZo0 alignStretch-1hwxMa noWrap-3jynv6" },
- BDV2.react.createElement("img", {ref: "img", className: "bd-server-image", src: server.iconUrl, onError: this.handleError.bind(this)}),
- BDV2.react.createElement(
- "div",
- {className: "flexChild-faoVW3 bd-server-content"},
- BDV2.react.createElement(
- "div",
- {className: "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY directionRow-3v3tfG noWrap-3jynv6 bd-server-header"},
- BDV2.react.createElement(
- "h5",
- {className: "h5-18_1nd defaultColor-1_ajX0 margin-reset bd-server-name"},
- server.name
- ),
- BDV2.react.createElement(
- "h5",
- {className: "h5-18_1nd defaultColor-1_ajX0 margin-reset bd-server-member-count"},
- server.members,
- " Members"
- )
- ),
- BDV2.react.createElement(
- "div",
- {className: "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY directionRow-3v3tfG noWrap-3jynv6"},
- BDV2.react.createElement(
- "div",
- {className: "scrollerWrap-2lJEkd scrollerThemed-2oenus themeGhostHairline-DBD-2d scrollerFade-1Ijw5y bd-server-description-container"},
- BDV2.react.createElement(
- "div",
- {className: "scroller-2FKFPG scroller bd-server-description"},
- server.description
- )
- )
- ),
- BDV2.react.createElement(
- "div",
- {className: "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY directionRow-3v3tfG noWrap-3jynv6 bd-server-footer"},
- BDV2.react.createElement(
- "div",
- {className: "flexChild-faoVW3 bd-server-tags", style: {flex: "1 1 auto"}},
- server.categories.join(", ")
- ),
- this.state.joined && BDV2.react.createElement(
- "button",
- {type: "button", className: "button-38aScr lookFilled-1Gx00P colorBrand-3pXr91 sizeMin-1mJd1x grow-q77ONN colorGreen-29iAKY", style: {minHeight: "12px", marginTop: "4px", backgroundColor: "#3ac15c"}},
- BDV2.react.createElement(
- "div",
- {className: "ui-button-contents"},
- "Joined"
- )
- ),
- server.error && BDV2.react.createElement(
- "button",
- {type: "button", className: "button-38aScr lookFilled-1Gx00P colorBrand-3pXr91 sizeMin-1mJd1x grow-q77ONN disabled-9aF2ug", style: {minHeight: "12px", marginTop: "4px", backgroundColor: "#c13a3a"}},
- BDV2.react.createElement(
- "div",
- {className: "ui-button-contents"},
- "Error"
- )
- ),
- !server.error && !this.state.joined && BDV2.react.createElement(
- "button",
- {type: "button", className: "button-38aScr lookFilled-1Gx00P colorBrand-3pXr91 sizeMin-1mJd1x grow-q77ONN", style: {minHeight: "12px", marginTop: "4px"}, onClick: () => {this.join();}},
- BDV2.react.createElement(
- "div",
- {className: "ui-button-contents"},
- "Join"
- )
- )
- )
- )
- // )
- );
- }
-
- handleError() {
- this.props.server.iconUrl = this.props.fallback;
- this.setState({imageError: true});
- }
-
- join() {
- this.props.join(this);
- //this.setState({joined: true});
- }
-}
-
-class V2C_PublicServers extends BDV2.reactComponent {
-
- constructor(props) {
- super(props);
- this.setInitialState();
- this.close = this.close.bind(this);
- this.changeCategory = this.changeCategory.bind(this);
- this.search = this.search.bind(this);
- this.searchKeyDown = this.searchKeyDown.bind(this);
- this.checkConnection = this.checkConnection.bind(this);
- this.join = this.join.bind(this);
- this.connect = this.connect.bind(this);
-
- this.GuildStore = BDV2.WebpackModules.findByUniqueProperties(["getGuilds"]);
- this.AvatarDefaults = BDV2.WebpackModules.findByUniqueProperties(["getUserAvatarURL", "DEFAULT_AVATARS"]);
- this.InviteActions = BDV2.WebpackModules.findByUniqueProperties(["acceptInvite"]);
- this.SortedGuildStore = BDV2.WebpackModules.findByUniqueProperties(["getSortedGuilds"]);
- }
-
- componentDidMount() {
- this.checkConnection();
- }
-
- setInitialState() {
- this.state = {
- selectedCategory: -1,
- title: "Loading...",
- loading: true,
- servers: [],
- next: null,
- connection: {
- state: 0,
- user: null
- }
- };
- }
-
- close() {
- BDV2.reactDom.unmountComponentAtNode(document.getElementById(this.props.rootId));
- }
-
- search(query, clear) {
- let self = this;
-
- $.ajax({
- method: "GET",
- url: `${self.endPoint}${query}${query ? "&schema=new" : "?schema=new"}`,
- success: data => {
- let servers = data.results.reduce((arr, server) => {
- server.joined = false;
- arr.push(server);
- // arr.push();
- return arr;
- }, []);
-
- if (!clear) {
- servers = self.state.servers.concat(servers);
- }
- else {
- //servers.unshift(self.bdServer);
- }
-
- let end = data.size + data.from;
- data.next = `?from=${end}`;
- if (self.state.term) data.next += `&term=${self.state.term}`;
- if (self.state.selectedCategory) data.next += `&category=${self.categoryButtons[self.state.selectedCategory]}`;
- if (end >= data.total) {
- end = data.total;
- data.next = null;
- }
-
- let title = `Showing 1-${end} of ${data.total} results in ${self.categoryButtons[self.state.selectedCategory]}`;
- if (self.state.term) title += ` for ${self.state.term}`;
-
- self.setState({
- loading: false,
- title: title,
- servers: servers,
- next: data.next
- });
-
- if (clear) {
- //console.log(self);
- self.refs.sbv.refs.contentScroller.scrollTop = 0;
- }
- },
- error: () => {
- self.setState({
- loading: false,
- title: "Failed to load servers. Check console for details"
- });
- }
- });
- }
-
- join(serverCard) {
- if (serverCard.props.pinned) return this.InviteActions.acceptInvite(serverCard.props.invite_code);
- $.ajax({
- method: "GET",
- url: `${this.joinEndPoint}/${serverCard.props.server.identifier}`,
- headers: {
- "Accept": "application/json;",
- "Content-Type": "application/json;" ,
- "x-discord-token": this.state.connection.user.accessToken
- },
- crossDomain: true,
- xhrFields: {
- withCredentials: true
- },
- success: () => {
- serverCard.setState({joined: true});
- }
- });
- }
-
- connect() {
- let self = this;
- let options = self.windowOptions;
- options.x = Math.round(window.screenX + window.innerWidth / 2 - options.width / 2);
- options.y = Math.round(window.screenY + window.innerHeight / 2 - options.height / 2);
-
- self.joinWindow = new (window.require("electron").remote.BrowserWindow)(options);
- const url = "https://auth.discordservers.com/connect?scopes=guilds.join&previousUrl=https://auth.discordservers.com/info";
- self.joinWindow.webContents.on("did-navigate", (event, url) => {
- if (url != "https://auth.discordservers.com/info") return;
- self.joinWindow.close();
- self.checkConnection();
- });
- self.joinWindow.loadURL(url);
- }
-
- get windowOptions() {
- return {
- width: 500,
- height: 550,
- backgroundColor: "#282b30",
- show: true,
- resizable: false,
- maximizable: false,
- minimizable: false,
- alwaysOnTop: true,
- frame: false,
- center: false,
- webPreferences: {
- nodeIntegration: false
- }
- };
- }
-
- get bdServer() {
- let server = {
- name: "BetterDiscord",
- online: "7500+",
- members: "20000+",
- categories: ["community", "programming", "support"],
- description: "Official BetterDiscord server for support etc",
- identifier: "86004744966914048",
- iconUrl: "https://cdn.discordapp.com/icons/86004744966914048/292e7f6bfff2b71dfd13e508a859aedd.webp",
- nativejoin: true,
- invite_code: "0Tmfo5ZbORCRqbAd",
- pinned: true
- };
- let guildList = this.SortedGuildStore.guildPositions;
- let defaultList = this.AvatarDefaults.DEFAULT_AVATARS;
- return BDV2.react.createElement(V2Components.ServerCard, {server: server, pinned: true, join: this.join, guildList: guildList, fallback: defaultList[Math.floor(Math.random() * 5)]});
- }
-
- get endPoint() {
- return "https://search.discordservers.com";
- }
-
- get joinEndPoint() {
- return "https://j.discordservers.com";
- }
-
- get connectEndPoint() {
- return "https://join.discordservers.com/connect";
- }
-
- checkConnection() {
- let self = this;
- try {
- $.ajax({
- method: "GET",
- url: `https://auth.discordservers.com/info`,
- headers: {
- "Accept": "application/json;",
- "Content-Type": "application/json;"
- },
- crossDomain: true,
- xhrFields: {
- withCredentials: true
- },
- success: data => {
- // Utils.log("PublicServer", "Got data: " + JSON.stringify(data));
- self.setState({
- selectedCategory: 0,
- connection: {
- state: 2,
- user: data
- }
- });
- self.search("", true);
-
- },
- error: () => {
- self.setState({
- title: "Not connected to discordservers.com!",
- loading: true,
- selectedCategory: -1,
- connection: {
- state: 1,
- user: null
- }
- });
- }
- });
- }
- catch (error) {
- self.setState({
- title: "Not connected to discordservers.com!",
- loading: true,
- selectedCategory: -1,
- connection: {
- state: 1,
- user: null
- }
- });
- }
- }
-
- render() {
- return BDV2.react.createElement(V2Components.SidebarView, {ref: "sbv", children: this.component});
- }
-
- get component() {
- return {
- sidebar: {
- component: this.sidebar
- },
- content: {
- component: this.content
- },
- tools: {
- component: BDV2.react.createElement(V2Components.Tools, {key: "pt", ref: "tools", onClick: this.close})
- }
- };
- }
-
- get sidebar() {
- return BDV2.react.createElement(
- "div",
- {className: "sidebar", key: "ps"},
- BDV2.react.createElement(
- "div",
- {className: "ui-tab-bar SIDE"},
- BDV2.react.createElement(
- "div",
- {className: "ui-tab-bar-header", style: {fontSize: "16px"}},
- "Public Servers"
- ),
- BDV2.react.createElement(V2Components.TabBar.Separator, null),
- this.searchInput,
- BDV2.react.createElement(V2Components.TabBar.Separator, null),
- BDV2.react.createElement(V2Components.TabBar.Header, {text: "Categories"}),
- this.categoryButtons.map((value, index) => {
- return BDV2.react.createElement(V2Components.TabBar.Item, {id: index, onClick: this.changeCategory, key: index, text: value, selected: this.state.selectedCategory === index});
- }),
- BDV2.react.createElement(V2Components.TabBar.Separator, null),
- this.footer,
- this.connection
- )
- );
- }
-
- get searchInput() {
- return BDV2.react.createElement(
- "div",
- {className: "ui-form-item"},
- BDV2.react.createElement(
- "div",
- {className: "ui-text-input flex-vertical", style: {width: "172px", marginLeft: "10px"}},
- BDV2.react.createElement("input", {ref: "searchinput", onKeyDown: this.searchKeyDown, onChange: () => {}, type: "text", className: "input default", placeholder: "Search...", maxLength: "50"})
- )
- );
- }
-
- searchKeyDown(e) {
- let self = this;
- if (self.state.loading || e.which !== 13) return;
- self.setState({
- loading: true,
- title: "Loading...",
- term: e.target.value
- });
- let query = `?term=${e.target.value}`;
- if (self.state.selectedCategory !== 0) {
- query += `&category=${self.categoryButtons[self.state.selectedCategory]}`;
- }
- self.search(query, true);
- }
-
- get categoryButtons() {
- return ["All", "FPS Games", "MMO Games", "Strategy Games", "MOBA Games", "RPG Games", "Tabletop Games", "Sandbox Games", "Simulation Games", "Music", "Community", "Language", "Programming", "Other"];
- }
-
- changeCategory(id) {
- let self = this;
- if (self.state.loading) return;
- self.refs.searchinput.value = "";
- self.setState({
- loading: true,
- selectedCategory: id,
- title: "Loading...",
- term: null
- });
- if (id === 0) {
- self.search("", true);
- return;
- }
- self.search(`?category=${self.categoryButtons[id]}`, true);
- }
-
- get content() {
- let self = this;
- let guildList = this.SortedGuildStore.guildPositions;
- let defaultList = this.AvatarDefaults.DEFAULT_AVATARS;
- if (self.state.connection.state === 1) return self.notConnected;
- return [BDV2.react.createElement(
- "div",
- {ref: "content", key: "pc", className: "contentColumn-2hrIYH contentColumnDefault-1VQkGM content-column default"},
- BDV2.react.createElement(V2Components.SettingsTitle, {text: self.state.title}),
- self.bdServer,
- self.state.servers.map((server) => {
- return BDV2.react.createElement(V2Components.ServerCard, {key: server.identifier, server: server, join: self.join, guildList: guildList, fallback: defaultList[Math.floor(Math.random() * 5)]});
- }),
- self.state.next && BDV2.react.createElement(
- "button",
- {type: "button", onClick: () => {
- if (self.state.loading) return;self.setState({loading: true}); self.search(self.state.next, false);
- }, className: "ui-button filled brand small grow", style: {width: "100%", marginTop: "10px", marginBottom: "10px"}},
- BDV2.react.createElement(
- "div",
- {className: "ui-button-contents"},
- self.state.loading ? "Loading" : "Load More"
- )
- ),
- self.state.servers.length > 0 && BDV2.react.createElement(V2Components.SettingsTitle, {text: self.state.title})
- )];
- }
-
- get notConnected() {
- let self = this;
- //return BDV2.react.createElement(V2Components.SettingsTitle, { text: self.state.title });
- return [BDV2.react.createElement(
- "div",
- {key: "ncc", ref: "content", className: "contentColumn-2hrIYH contentColumnDefault-1VQkGM content-column default"},
- BDV2.react.createElement(
- "h2",
- {className: "ui-form-title h2 margin-reset margin-bottom-20"},
- "Not connected to discordservers.com!",
- BDV2.react.createElement(
- "button",
- {
- onClick: self.connect,
- type: "button",
- className: "ui-button filled brand small grow",
- style: {
- display: "inline-block",
- minHeight: "18px",
- marginLeft: "10px",
- lineHeight: "14px"
- }
- },
- BDV2.react.createElement(
- "div",
- {className: "ui-button-contents"},
- "Connect"
- )
- )
- ), self.bdServer
- )];
- }
-
- get footer() {
- return BDV2.react.createElement(
- "div",
- {className: "ui-tab-bar-header"},
- BDV2.react.createElement(
- "a",
- {href: "https://discordservers.com", target: "_blank"},
- "Discordservers.com"
- )
- );
- }
-
- get connection() {
- let self = this;
- let {connection} = self.state;
- if (connection.state !== 2) return BDV2.react.createElement("span", null);
-
- return BDV2.react.createElement(
- "span",
- null,
- BDV2.react.createElement(V2Components.TabBar.Separator, null),
- BDV2.react.createElement(
- "span",
- {style: {color: "#b9bbbe", fontSize: "10px", marginLeft: "10px"}},
- "Connected as: ",
- `${connection.user.username}#${connection.user.discriminator}`
- ),
- BDV2.react.createElement(
- "div",
- {style: {padding: "5px 10px 0 10px"}},
- BDV2.react.createElement(
- "button",
- {style: {width: "100%", minHeight: "20px"}, type: "button", className: "ui-button filled brand small grow"},
- BDV2.react.createElement(
- "div",
- {className: "ui-button-contents", onClick: self.connect},
- "Reconnect"
- )
- )
- )
- );
-}
-}
+DONT USE THIS BECAUSE ITS AGAINST TOS