BetterDiscordApp-rauenzi/js/main.js

4176 lines
142 KiB
JavaScript
Raw Normal View History

2015-08-27 15:46:53 +02:00
/* BetterDiscordApp Core JavaScript
2017-04-30 03:11:22 +02:00
* Version: 1.78
2015-08-27 15:46:53 +02:00
* Author: Jiiks | http://jiiks.net
* Date: 27/08/2015 - 16:36
* Last Update: 01/05/2016
2015-08-27 15:46:53 +02:00
* https://github.com/Jiiks/BetterDiscordApp
*/
2017-01-09 06:41:36 +01:00
2018-01-09 04:24:00 +01:00
/* global Proxy, bdplugins, bdthemes, betterDiscordIPC, bdVersion, version, BDV2, webpackJsonp */
2017-11-03 04:05:33 +01:00
/* eslint-disable no-console */
/*Localstorage fix*/
(function() {
let __fs = window.require("fs");
2017-01-22 19:00:24 +01:00
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/';
2018-01-09 04:24:00 +01:00
let localStorageFile = "localStorage.json";
2017-01-22 19:00:24 +01:00
let __data = {};
2018-01-09 04:24:00 +01:00
if(__fs.existsSync(`${__dataPath}${localStorageFile}`)) {
2017-01-22 19:00:24 +01:00
try {
2018-01-09 04:24:00 +01:00
__data = JSON.parse(__fs.readFileSync(`${__dataPath}${localStorageFile}`));
2017-01-22 19:00:24 +01:00
}catch(err) {
console.log(err);
}
2018-01-09 04:24:00 +01:00
} else if(__fs.existsSync(localStorageFile)) {
try {
2018-01-09 04:24:00 +01:00
__data = JSON.parse(__fs.readFileSync(localStorageFile));
2017-01-11 10:23:15 +01:00
}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() {
2018-01-09 04:24:00 +01:00
__fs.writeFileSync(`${__dataPath}${localStorageFile}`, JSON.stringify(this), null, 4);
};
var __proxy = new Proxy(__ls, {
2017-11-03 04:05:33 +01:00
set: function(target, name, val) {
__ls[name] = val;
__ls.save();
},
2017-11-03 04:05:33 +01:00
get: function(target, name) {
return __ls[name] || null;
}
});
window.localStorage = __proxy;
})();
2017-04-30 03:11:22 +02:00
(() => {
let v2Loader = document.createElement('div');
v2Loader.className = "bd-loaderv2";
v2Loader.title = "BetterDiscord is loading...";
document.body.appendChild(v2Loader);
})();
2018-03-15 15:30:14 +01:00
2017-01-09 06:41:36 +01:00
window.bdStorage = {};
window.bdStorage.get = function(i) {
return betterDiscordIPC.sendSync('synchronous-message', { 'arg': 'storage', 'cmd': 'get', 'var': i });
};
window.bdStorage.set = function(i, v) {
betterDiscordIPC.sendSync('synchronous-message', { 'arg': 'storage', 'cmd': 'set', 'var': i, 'data': v });
};
window.bdPluginStorage = {};
window.bdPluginStorage.get = function(pn, i) {
return betterDiscordIPC.sendSync('synchronous-message', { 'arg': 'pluginstorage', 'cmd': 'get', 'pn': pn, 'var': i });
};
window.bdPluginStorage.set = function(pn, i, v) {
betterDiscordIPC.sendSync('synchronous-message', { 'arg': 'pluginstorage', 'cmd': 'set', 'pn': pn, 'var': i, 'data': v });
};
betterDiscordIPC.on('asynchronous-reply', (event, arg) => {
console.log(event);
console.log(arg);
});
2018-04-15 20:13:25 +02:00
var bdSettings = {};
var bdSettingsStorage = {};
bdSettingsStorage.initialize = function() {
let fs = require("fs");
let data = {};
2018-06-16 15:38:56 +02:00
if (fs.existsSync(bdConfig.dataPath + "/bdsettings.json")) {
try {
data = JSON.parse(fs.readFileSync(bdConfig.dataPath + "/bdsettings.json"));
}
catch (err) {
data = {};
}
}
2018-04-15 20:13:25 +02:00
if (data) bdSettings = data;
else bdSettings = {};
}
bdSettingsStorage.get = function(key) {
if (bdSettings[key]) return bdSettings[key];
else return null;
}
2018-06-16 15:38:56 +02:00
bdSettingsStorage.set = function(key, data) {
2018-04-15 20:13:25 +02:00
let fs = require("fs");
bdSettings[key] = data;
try {
2018-06-16 15:38:56 +02:00
fs.writeFileSync(bdConfig.dataPath + "/bdsettings.json", JSON.stringify(bdSettings, null, 4));
2018-04-15 20:13:25 +02:00
return true;
}
catch(err) {
utils.err(err);
return false;
}
}
2018-01-09 04:24:00 +01:00
var settingsPanel, emoteModule, utils, quickEmoteMenu, voiceMode, pluginModule, themeModule, dMode, publicServersModule;
2017-06-17 19:08:43 +02:00
var jsVersion = 1.792;
2017-01-09 09:38:52 +01:00
var supportedVersion = "0.2.81";
2018-04-06 16:49:26 +02:00
var bbdVersion = "0.0.7";
2015-08-29 11:36:47 +02:00
var mainObserver;
2015-08-27 15:46:53 +02:00
var twitchEmoteUrlStart = "https://static-cdn.jtvnw.net/emoticons/v1/";
var twitchEmoteUrlEnd = "/1.0";
var ffzEmoteUrlStart = "https://cdn.frankerfacez.com/emoticon/";
var ffzEmoteUrlEnd = "/1";
2015-12-10 04:01:24 +01:00
var bttvEmoteUrlStart = "https://cdn.betterttv.net/emote/";
var bttvEmoteUrlEnd = "/1x";
2015-08-27 15:46:53 +02:00
var mainCore;
2015-08-27 15:46:53 +02:00
2015-08-29 11:36:47 +02:00
var settings = {
"Save logs locally": { "id": "bda-gs-0", "info": "Saves chat logs locally", "implemented": false, "hidden": false, "cat": "core"},
2018-02-28 08:25:06 +01:00
"Public Servers": { "id": "bda-gs-1", "info": "Display public servers button", "implemented": true, "hidden": false, "cat": "core"},
2017-10-30 22:24:54 +01:00
"Minimal Mode": { "id": "bda-gs-2", "info": "Hide elements and reduce the size of elements.", "implemented": true, "hidden": false, "cat": "core"},
"Voice Mode": { "id": "bda-gs-4", "info": "Only show voice chat", "implemented": true, "hidden": false, "cat": "core"},
2017-10-30 22:24:54 +01:00
"Hide Channels": { "id": "bda-gs-3", "info": "Hide channels in minimal mode", "implemented": true, "hidden": false, "cat": "core"},
"Dark Mode": { "id": "bda-gs-5", "info": "Make certain elements dark by default(wip)", "implemented": true, "hidden": false, "cat": "core"},
"Override Default Emotes": { "id": "bda-es-5", "info": "Override default emotes", "implemented": false, "hidden": false, "cat": "core"},
"Voice Disconnect": { "id": "bda-dc-0", "info": "Disconnect from voice server when closing Discord", "implemented": true, "hidden": false, "cat": "core"},
"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"},
"24 Hour Timestamps": { "id": "bda-gs-6", "info": "Replace 12hr timestamps with proper ones", "implemented": true, "hidden": false, "cat": "core"},
"Coloured Text": { "id": "bda-gs-7", "info": "Make text colour the same as role colour", "implemented": true, "hidden": false, "cat": "core"},
2017-04-30 03:11:22 +02:00
"BetterDiscord Blue": { "id": "bda-gs-b", "info": "Replace Discord blue with BD Blue", "implemented": true, "hidden": false, "cat": "core"},
"Developer Mode": { "id": "bda-gs-8", "info": "Developer Mode", "implemented": true, "hidden": false, "cat": "core"},
2017-12-24 07:51:24 +01:00
2018-05-22 06:29:04 +02:00
"Startup Error Modal": { "id": "fork-ps-1", "info": "Show a modal with plugin/theme errors on startup", "implemented": true, "hidden": false, "cat": "fork"},
2017-12-24 07:51:24 +01:00
"Show Toasts": { "id": "fork-ps-2", "info": "Shows a small notification for starting and stopping plugins & themes", "implemented": true, "hidden": false, "cat": "fork"},
"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": "fork"},
2017-12-24 07:51:24 +01:00
"Emote Modifier Tooltip": { "id": "fork-es-1", "info": "Shows the emote modifier in the tooltip.", "implemented": true, "hidden": false, "cat": "fork"},
"Animate On Hover": { "id": "fork-es-2", "info": "Only animate the emote modifiers on hover", "implemented": true, "hidden": false, "cat": "fork"},
"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": "fork"},
2018-05-22 06:29:04 +02:00
"Download Emotes": { "id": "fork-es-3", "info": "Download emotes when the cache is expired", "implemented": true, "hidden": false, "cat": "fork"},
"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 Autocomplete": { "id": "bda-es-3", "info": "Autocomplete emote commands", "implemented": false, "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"},
2016-01-08 16:33:43 +01:00
};
2015-08-29 11:36:47 +02:00
var defaultCookie = {
2016-01-08 16:33:43 +01:00
"version": jsVersion,
"bda-gs-0": false,
2018-03-29 09:56:07 +02:00
"bda-gs-1": true,
2015-12-23 22:48:59 +01:00
"bda-gs-2": false,
"bda-gs-3": false,
"bda-gs-4": false,
2016-04-09 14:51:59 +02:00
"bda-gs-5": true,
"bda-gs-6": false,
"bda-gs-7": false,
"bda-gs-8": false,
"bda-es-0": true,
2015-12-23 09:56:16 +01:00
"bda-es-1": true,
2015-12-23 22:48:59 +01:00
"bda-es-2": true,
"bda-es-3": false,
"bda-es-4": false,
"bda-es-5": true,
"bda-es-6": true,
"bda-es-7": true,
2018-05-05 16:54:21 +02:00
"bda-gs-b": false,
2016-04-02 09:56:19 +02:00
"bda-es-8": true,
"bda-jd": true,
"bda-dc-0": false,
"bda-css-0": false,
2016-04-09 08:04:34 +02:00
"bda-css-1": false,
2017-12-24 07:51:24 +01:00
"bda-es-9": true,
"fork-dm-1": false,
"fork-ps-1": true,
"fork-ps-2": true,
"fork-ps-3": true,
"fork-es-1": true,
2018-05-22 06:29:04 +02:00
"fork-es-2": false,
"fork-es-3": true
};
2015-08-29 11:36:47 +02:00
var settingsCookie = {};
2015-08-27 15:46:53 +02:00
2017-11-03 21:01:49 +01:00
var bdpluginErrors, bdthemeErrors; // define for backwards compatibility
2018-01-09 04:24:00 +01:00
var bdConfig = null;
function Core(config) {
if (!config) {
config = {
branch: "master",
repo: "rauenzi",
updater: {
CDN: "cdn.rawgit.com"
}
}
}
else config.newLoader = true;
window.bdConfig = config;
}
2015-08-27 15:46:53 +02:00
2018-05-22 06:29:04 +02:00
var emoteModulePromise;
2018-03-15 15:30:14 +01:00
Core.prototype.init = async function() {
var self = this;
2018-04-16 00:58:48 +02:00
bdConfig.deferLoaded = false;
var lVersion = (typeof(version) === "undefined") ? bdVersion : version;
if (lVersion < supportedVersion) {
this.alert("Not Supported", "BetterDiscord v" + lVersion + "(your version)" + " is not supported by the latest js(" + jsVersion + ").<br><br> Please download the latest version from <a href='https://betterdiscord.net' target='_blank'>BetterDiscord.net</a>");
return;
}
2015-08-29 11:36:47 +02:00
2015-08-27 15:46:53 +02:00
utils = new Utils();
2018-05-03 04:17:06 +02:00
await utils.getHash();
2018-05-22 06:29:04 +02:00
utils.log("Initializing Settings");
this.initSettings();
2018-04-16 00:58:48 +02:00
emoteModule = new EmoteModule();
utils.log("Initializing EmoteModule");
2018-05-22 06:29:04 +02:00
emoteModule.init().then(() => {emoteModule.initialized = true;});
2018-01-09 04:24:00 +01:00
publicServersModule = new V2_PublicServers();
2015-08-27 15:46:53 +02:00
quickEmoteMenu = new QuickEmoteMenu();
voiceMode = new VoiceMode();
dMode = new devMode();
2015-08-27 15:46:53 +02:00
//Incase were too fast
function gwDefer() {
2018-03-15 15:30:14 +01:00
//console.log(new Date().getTime() + " Defer");
2017-10-29 08:00:33 +01:00
if (document.querySelectorAll('.guilds .guild').length > 0) {
2018-03-15 15:30:14 +01:00
//console.log(new Date().getTime() + " Defer Loaded");
2018-04-16 00:58:48 +02:00
bdConfig.deferLoaded = true;
2017-11-01 06:43:07 +01:00
self.injectExternals();
2018-01-09 22:32:02 +01:00
2018-01-20 02:17:52 +01:00
utils.log("Updating Settings");
settingsPanel = new V2_SettingsPanel();
settingsPanel.updateSettings();
// Add check for backwards compatibility
2017-11-03 21:02:50 +01:00
if (!bdpluginErrors) bdpluginErrors = [];
if (!bdthemeErrors) bdthemeErrors = [];
utils.log("Loading Plugins");
2015-12-12 07:07:56 +01:00
pluginModule = new PluginModule();
pluginModule.loadPlugins();
2018-02-28 08:25:06 +01:00
utils.log("Loading Themes");
2018-02-28 08:25:06 +01:00
themeModule = new ThemeModule();
themeModule.loadThemes();
2015-12-12 07:07:56 +01:00
2018-02-28 08:25:06 +01:00
$("#customcss").detach().appendTo(document.head);
utils.log("Initializing QuickEmoteMenu");
2018-01-09 22:32:02 +01:00
quickEmoteMenu.init();
window.addEventListener("beforeunload", function(){
if(settingsCookie["bda-dc-0"]){
2017-10-29 21:33:48 +01:00
document.querySelector('.btn.btn-disconnect').click();
}
});
2018-01-09 04:24:00 +01:00
publicServersModule.initialize();
emoteModule.autoCapitalize();
/*Display new features in BetterDiscord*/
2016-01-08 16:33:43 +01:00
if (settingsCookie["version"] < jsVersion) {
2017-10-30 01:00:34 +01:00
//var cl = self.constructChangelog();
settingsCookie["version"] = jsVersion;
self.saveSettings();
}
2015-12-27 16:39:10 +01:00
utils.log("Removing Loading Icon");
2017-04-30 03:11:22 +02:00
document.getElementsByClassName("bd-loaderv2")[0].remove();
2018-02-28 08:25:06 +01:00
utils.log("Initializing Main Observer");
self.initObserver();
// Show loading errors
2017-12-24 07:51:24 +01:00
if (settingsCookie["fork-ps-1"]) {
utils.log("Collecting Startup Errors");
2017-11-03 18:54:47 +01:00
self.showStartupErrors();
}
2015-08-31 15:20:33 +02:00
} else {
setTimeout(gwDefer, 100);
2015-08-31 15:20:33 +02:00
}
}
2015-08-31 15:59:34 +02:00
2016-01-08 16:33:43 +01:00
$(document).ready(function () {
setTimeout(gwDefer, 1000);
});
};
2015-08-27 15:46:53 +02:00
2017-11-01 06:28:53 +01:00
Core.prototype.injectExternals = function() {
utils.injectJs("https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js")
2017-11-01 06:28:53 +01:00
};
2016-01-08 16:33:43 +01:00
Core.prototype.initSettings = function () {
2018-04-15 20:13:25 +02:00
// $.removeCookie('the_cookie', { path: '/' });
bdSettingsStorage.initialize();
if ($.cookie("better-discord")) {
settingsCookie = JSON.parse($.cookie("better-discord"));
this.saveSettings();
$.removeCookie("better-discord", { path: '/' });
return;
}
if (!bdSettingsStorage.get("settings")) {
2015-08-29 11:36:47 +02:00
settingsCookie = defaultCookie;
this.saveSettings();
2018-04-15 20:13:25 +02:00
}
else {
2015-08-29 11:36:47 +02:00
this.loadSettings();
2017-11-09 14:23:20 +01:00
$('<style id="customcss">').html(atob(window.bdStorage.get("bdcustomcss"))).appendTo(document.head);
2016-01-08 16:33:43 +01:00
for (var setting in defaultCookie) {
if (settingsCookie[setting] == undefined) {
settingsCookie[setting] = defaultCookie[setting];
2015-08-29 11:36:47 +02:00
this.saveSettings();
}
2015-08-27 15:46:53 +02:00
}
}
};
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
Core.prototype.saveSettings = function () {
2018-04-15 20:13:25 +02:00
bdSettingsStorage.set("settings", settingsCookie);
};
2015-08-29 11:36:47 +02:00
2016-01-08 16:33:43 +01:00
Core.prototype.loadSettings = function () {
2018-04-15 20:13:25 +02:00
settingsCookie = bdSettingsStorage.get("settings");
};
2016-04-09 08:04:34 +02:00
2016-01-08 16:33:43 +01:00
Core.prototype.initObserver = function () {
mainObserver = new MutationObserver((mutations) => {
for (let i = 0; i < mutations.length; i++) {
let mutation = mutations[i];
if (typeof pluginModule !== "undefined") pluginModule.rawObserver(mutation);
2017-10-30 22:04:48 +01:00
// onSwitch()
// leaving Activity Feed/Friends menu
2017-10-30 21:53:27 +01:00
if (mutation.removedNodes.length && mutation.removedNodes[0] instanceof Element) {
let node = mutation.removedNodes[0];
2018-05-05 15:45:34 +02:00
if (node.classList.contains("activityFeed-28jde9") || node.id === "friends") {
pluginModule.channelSwitch();
}
2017-10-30 21:53:27 +01:00
}
2017-10-30 22:04:48 +01:00
// if there was nothing added, skip
2018-04-06 16:49:26 +02:00
if (!mutation.addedNodes.length || !(mutation.addedNodes[0] instanceof Element)) continue;
2017-10-30 21:53:27 +01:00
let node = mutation.addedNodes[0];
2018-05-05 15:45:34 +02:00
if (node.classList.contains("layer-3QrUeG")) {
if (node.getElementsByClassName("guild-settings-base-section").length) node.setAttribute('layer-id', 'server-settings');
2018-05-05 15:45:34 +02:00
if (node.getElementsByClassName("socialLinks-3jqNFy").length) {
2017-11-01 06:28:53 +01:00
node.setAttribute('layer-id', 'user-settings');
if (!document.getElementById("bd-settings-sidebar")) settingsPanel.renderSidebar();
2017-11-01 06:28:53 +01:00
}
}
2018-05-05 22:33:36 +02:00
// Emoji Picker
2018-05-05 15:45:34 +02:00
if (node.classList.contains('popout-3sVMXz') && !node.classList.contains('popoutLeft-30WmrD')) {
if (node.getElementsByClassName('emojiPicker-3m1S-j').length) quickEmoteMenu.obsCallback(node);
2017-10-30 22:04:48 +01:00
}
2017-10-30 22:04:48 +01:00
// onSwitch()
// Not a channel, but still a switch (Activity Feed/Friends menu/NSFW check)
2018-05-05 15:45:34 +02:00
if (node.classList.contains("activityFeed-28jde9") || node.id === "friends") {
2017-10-30 21:53:27 +01:00
pluginModule.channelSwitch();
}
2017-10-30 22:04:48 +01:00
// onSwitch()
2017-10-30 21:53:27 +01:00
// New Channel
if (node.classList.contains("messages-wrapper") || node.getElementsByClassName("messages-wrapper").length) {
this.inject24Hour(node);
this.injectColoredText(node);
2017-10-30 21:53:27 +01:00
pluginModule.channelSwitch();
}
2017-10-30 22:04:48 +01:00
// onMessage
2017-10-30 21:53:27 +01:00
// New Message Group
if (node.classList.contains("message-group")) {
this.inject24Hour(node);
this.injectColoredText(node);
// if (!node.getElementsByClassName("message-sending").length && node.parentElement && node.parentElement.children && node == node.parentElement.children[node.parentElement.children.length - 1]) {
// pluginModule.newMessage();
// }
2015-08-29 11:36:47 +02:00
}
if (node.classList.contains("message-text")) {
this.injectColoredText(node.parentElement.parentElement.parentElement.parentElement);
}
2017-10-30 22:04:48 +01:00
// onMessage
2017-10-30 21:53:27 +01:00
// Single Message
if (node.classList.contains("message")) {
this.injectColoredText(node.parentElement.parentElement);
//if (!node.classList.contains("message-sending")) pluginModule.newMessage();
2017-10-30 21:53:27 +01:00
}
2018-04-06 16:49:26 +02:00
}
2015-08-29 11:36:47 +02:00
});
2016-01-08 16:33:43 +01:00
mainObserver.observe(document, {
childList: true,
subtree: true
});
};
2015-08-29 11:36:47 +02:00
2017-10-30 21:53:27 +01:00
Core.prototype.inject24Hour = function(node) {
if (!settingsCookie["bda-gs-6"]) return;
node.querySelectorAll('.timestamp').forEach(elem => {
if (elem.getAttribute("data-24")) return;
let text = elem.innerText || elem.textContent;
let matches = /([^0-9]*)([0-9]?[0-9]:[0-9][0-9])([^0-9]*)/.exec(text);
if(matches == null) return;
if(matches.length < 4) return;
2017-11-04 06:59:30 +01:00
let time = matches[2].split(':');
let hours = parseInt(time[0]);
let minutes = time[1];
let timeOfDay = matches[3].toLowerCase();
if (timeOfDay.includes("am") && hours == 12) hours -= 12;
else if (timeOfDay.includes("pm") && hours < 12) hours += 12;
2017-11-04 06:59:30 +01:00
hours = ("0" + hours).slice(-2);
elem.innerText = matches[1] + hours + ":" + minutes + matches[3];
2017-11-04 06:59:30 +01:00
elem.setAttribute("data-24", matches[2]);
});
};
2017-11-04 06:59:30 +01:00
Core.prototype.remove24Hour = function(node) {
2017-10-30 21:53:27 +01:00
node.querySelectorAll('.timestamp').forEach(elem => {
2017-11-04 06:59:30 +01:00
if (!elem.getAttribute("data-24")) return;
let time = elem.getAttribute("data-24");
elem.removeAttribute("data-24");
2017-10-30 21:53:27 +01:00
let text = elem.innerText || elem.textContent;
2017-11-04 06:59:30 +01:00
let matches = /([^0-9]*)([0-9]?[0-9]:[0-9][0-9])([^0-9]*)/.exec(text);
2017-10-30 21:53:27 +01:00
if(matches == null) return;
2017-11-04 06:59:30 +01:00
if(matches.length < 4) return;
elem.innerText = matches[1] + time + matches[3];
2017-10-30 21:53:27 +01:00
});
};
Core.prototype.injectColoredText = function(node) {
if (!settingsCookie["bda-gs-7"]) return;
node.querySelectorAll('.user-name').forEach(elem => {
let color = elem.style.color;
if (color === "rgb(255, 255, 255)") return;
elem.closest(".message-group").querySelectorAll('.markup').forEach(elem => {
2018-01-09 22:32:02 +01:00
if (elem.getAttribute("data-colour")) return;
elem.setAttribute("data-colour", true);
2017-10-30 21:53:27 +01:00
elem.style.setProperty("color", color);
});
});
};
2017-11-04 06:59:30 +01:00
Core.prototype.removeColoredText = function(node) {
node.querySelectorAll('.user-name').forEach(elem => {
elem.closest(".message-group").querySelectorAll('.markup').forEach(elem => {
2018-01-09 22:32:02 +01:00
if (!elem.getAttribute("data-colour")) return;
elem.removeAttribute("data-colour");
2017-11-04 06:59:30 +01:00
elem.style.setProperty("color", "");
});
});
};
2017-11-03 18:34:26 +01:00
Core.prototype.alert = function(title, content) {
let modal = $(`<div class="bd-modal-wrapper theme-dark">
2018-05-05 16:54:21 +02:00
<div class="bd-backdrop backdrop-1ocfXc"></div>
<div class="bd-modal modal-1UGdnR">
<div class="bd-modal-inner inner-1JeGVc">
<div class="header header-1R_AjF">
2017-11-03 18:34:26 +01:00
<div class="title">${title}</div>
</div>
<div class="bd-modal-body">
<div class="scroller-wrap fade">
<div class="scroller">
${content}
</div>
</div>
</div>
2018-05-05 16:54:21 +02:00
<div class="footer footer-2yfCgX">
2017-11-03 18:34:26 +01:00
<button type="button">Okay</button>
</div>
</div>
</div>
</div>`);
modal.find('.footer button').on('click', () => {
modal.addClass('closing');
setTimeout(() => { modal.remove(); }, 300);
});
modal.find('.bd-backdrop').on('click', () => {
modal.addClass('closing');
setTimeout(() => { modal.remove(); }, 300);
});
modal.appendTo("#app-mount");
};
Core.prototype.showStartupErrors = function() {
2017-11-03 20:52:35 +01:00
if (!bdpluginErrors || !bdthemeErrors) return;
if (!bdpluginErrors.length && !bdthemeErrors.length) return;
2017-11-03 18:34:26 +01:00
let modal = $(`<div class="bd-modal-wrapper theme-dark">
2018-05-05 16:54:21 +02:00
<div class="bd-backdrop backdrop-1ocfXc"></div>
<div class="bd-modal bd-startup-modal modal-1UGdnR">
<div class="bd-modal-inner inner-1JeGVc">
<div class="header header-1R_AjF"><div class="title">Startup Errors</div></div>
2017-11-03 18:34:26 +01:00
<div class="bd-modal-body">
<div class="tab-bar-container">
<div class="tab-bar TOP">
<div class="tab-bar-item">Plugins</div>
<div class="tab-bar-item">Themes</div>
</div>
</div>
<div class="table-header">
<div class="table-column column-name">Name</div>
<div class="table-column column-reason">Reason</div>
<div class="table-column column-error">Error</div>
</div>
<div class="scroller-wrap fade">
<div class="scroller">
</div>
</div>
</div>
2018-05-05 16:54:21 +02:00
<div class="footer footer-2yfCgX">
2017-11-03 18:34:26 +01:00
<button type="button">Okay</button>
</div>
</div>
</div>
</div>`);
function generateTab(errors) {
let container = $(`<div class="errors">`);
for (let err of errors) {
let error = $(`<div class="error">
<div class="table-column column-name">${err.name ? err.name : err.file}</div>
<div class="table-column column-reason">${err.reason}</div>
<div class="table-column column-error"><a class="error-link" href="">${err.error ? err.error.message : ""}</a></div>
</div>`);
container.append(error);
if (err.error) {
error.find('a').on('click', (e) => {
e.preventDefault();
utils.err(`Error details for ${err.name ? err.name : err.file}.`, err.error);
});
}
}
return container;
}
let tabs = [generateTab(bdpluginErrors), generateTab(bdthemeErrors)];
modal.find('.tab-bar-item').on('click', (e) => {
e.preventDefault();
modal.find('.tab-bar-item').removeClass('selected');
$(e.target).addClass('selected');
modal.find('.scroller').empty().append(tabs[$(e.target).index()]);
});
modal.find('.footer button').on('click', () => {
modal.addClass('closing');
setTimeout(() => { modal.remove(); }, 300);
});
modal.find('.bd-backdrop').on('click', () => {
modal.addClass('closing');
setTimeout(() => { modal.remove(); }, 300);
});
modal.appendTo("#app-mount");
modal.find('.tab-bar-item')[0].click();
};
2017-11-03 20:52:35 +01:00
/**
* This shows a toast similar to android towards the bottom of the screen.
*
* @param {string} content The string to show in the toast.
* @param {object} options Options object. Optional parameter.
* @param {string} options.type Changes the type of the toast stylistically and semantically. Choices: "", "info", "success", "danger"/"error", "warning"/"warn". Default: ""
* @param {boolean} options.icon Determines whether the icon should show corresponding to the type. A toast without type will always have no icon. Default: true
* @param {number} options.timeout Adjusts the time (in ms) the toast should be shown for before disappearing automatically. Default: 3000
*/
Core.prototype.showToast = function(content, options = {}) {
2018-04-16 00:58:48 +02:00
if (!bdConfig.deferLoaded) return;
2017-11-03 20:52:35 +01:00
if (!document.querySelector('.bd-toasts')) {
let toastWrapper = document.createElement("div");
toastWrapper.classList.add("bd-toasts");
2018-05-05 15:45:34 +02:00
let boundingElement = document.querySelector('.chat form, #friends, .noChannel-Z1DQK7, .activityFeed-28jde9');
2017-11-03 20:52:35 +01:00
toastWrapper.style.setProperty("left", boundingElement ? boundingElement.getBoundingClientRect().left + "px" : "0px");
toastWrapper.style.setProperty("width", boundingElement ? boundingElement.offsetWidth + "px" : "100%");
toastWrapper.style.setProperty("bottom", (document.querySelector('.chat form') ? document.querySelector('.chat form').offsetHeight : 80) + "px");
document.querySelector('.app').appendChild(toastWrapper);
}
const {type = "", icon = true, timeout = 3000} = options;
let toastElem = document.createElement("div");
toastElem.classList.add("bd-toast");
if (type) toastElem.classList.add("toast-" + type);
if (type && icon) toastElem.classList.add("icon");
toastElem.innerText = content;
document.querySelector('.bd-toasts').appendChild(toastElem);
setTimeout(() => {
toastElem.classList.add('closing');
setTimeout(() => {
toastElem.remove();
if (!document.querySelectorAll('.bd-toasts .bd-toast').length) document.querySelector('.bd-toasts').remove();
}, 300);
}, timeout);
};
2017-10-30 23:14:26 +01:00
2015-08-27 15:46:53 +02:00
/* BetterDiscordApp EmoteModule JavaScript
* Version: 1.5
2015-08-27 15:46:53 +02:00
* Author: Jiiks | http://jiiks.net
* Date: 26/08/2015 - 15:29
2015-10-14 08:50:34 +02:00
* Last Update: 14/10/2015 - 09:48
2015-08-27 15:46:53 +02:00
* https://github.com/Jiiks/BetterDiscordApp
* Note: Due to conflicts autocapitalize only supports global emotes
*/
/*
* =Changelog=
* -v1.5
* --Twitchemotes.com api
*/
2015-08-27 15:46:53 +02:00
var emotesFfz = {};
var emotesBTTV = {};
2017-11-03 04:05:33 +01:00
var emotesBTTV2 = {};
2018-01-09 04:24:00 +01:00
var emotesTwitch = {};
var subEmotesTwitch = {};
2015-08-27 15:46:53 +02:00
2018-01-09 04:24:00 +01:00
window.bdEmotes = {
TwitchGlobal: {},
TwitchSubscriber: {},
BTTV: {},
2018-01-24 00:08:20 +01:00
FrankerFaceZ: {},
2018-01-09 04:24:00 +01:00
BTTV2: {}
}
window.bdEmoteSettingIDs = {
TwitchGlobal: "bda-es-7",
TwitchSubscriber: "bda-es-7",
BTTV: "bda-es-2",
2018-01-24 00:08:20 +01:00
FrankerFaceZ: "bda-es-1",
BTTV2: "bda-es-2"
2018-01-09 04:24:00 +01:00
}
2016-01-08 16:33:43 +01:00
function EmoteModule() {}
2015-08-29 11:36:47 +02:00
2018-02-28 08:25:06 +01:00
EmoteModule.prototype.init = async function () {
2018-01-09 04:24:00 +01:00
this.modifiers = ["flip", "spin", "pulse", "spin2", "spin3", "1spin", "2spin", "3spin", "tr", "bl", "br", "shake", "shake2", "shake3", "flap"];
2018-01-20 02:17:52 +01:00
this.overrides = ['twitch', 'bttv', 'ffz'];
2018-03-16 22:01:31 +01:00
this.categories = ["TwitchGlobal", "TwitchSubscriber", "BTTV", "BTTV2", "FrankerFaceZ"];
2018-01-09 04:24:00 +01:00
let emoteInfo = {
'TwitchGlobal': {
url: 'https://twitchemotes.com/api_cache/v3/global.json',
backup: "https://" + bdConfig.updater.CDN + '/' + bdConfig.repo + '/BetterDiscordApp/' + bdConfig.hash + '/data/emotedata_twitch_global.json',
variable: 'TwitchGlobal',
2018-02-13 08:49:11 +01:00
oldVariable: 'emotesTwitch',
getEmoteURL: (e) => `https://static-cdn.jtvnw.net/emoticons/v1/${e.id}/1.0`,
getOldData: (url, name) => { return {id: url.match(/\/([0-9]+)\//)[1], code: name, emoticon_set: 0, description: null} }
2018-01-09 04:24:00 +01:00
},
'TwitchSubscriber': {
url: 'https://twitchemotes.com/api_cache/v3/subscriber.json',
backup: "https://" + bdConfig.updater.CDN + '/' + bdConfig.repo + '/BetterDiscordApp/' + bdConfig.hash + '/data/emotedata_twitch_subscriber.json',
variable: 'TwitchSubscriber',
2018-02-13 08:49:11 +01:00
oldVariable: 'subEmotesTwitch',
2018-01-09 04:24:00 +01:00
parser: (data) => {
let emotes = {};
for (let c in data) {
let channel = data[c];
for (let e = 0, elen = channel.emotes.length; e < elen; e++) {
let emote = channel.emotes[e];
2018-04-16 06:57:38 +02:00
emotes[emote.code] = emote.id;
2018-01-09 04:24:00 +01:00
}
}
return emotes;
},
2018-04-16 06:57:38 +02:00
backupParser: (data) => {
return data;
},
2018-02-13 08:49:11 +01:00
getEmoteURL: (e) => `https://static-cdn.jtvnw.net/emoticons/v1/${e}/1.0`,
getOldData: (url) => url.match(/\/([0-9]+)\//)[1]
2018-01-09 04:24:00 +01:00
},
'FrankerFaceZ': {
url: "https://" + bdConfig.updater.CDN + '/' + bdConfig.repo + '/BetterDiscordApp/' + bdConfig.hash + '/data/emotedata_ffz.json',
variable: 'FrankerFaceZ',
2018-02-13 08:49:11 +01:00
oldVariable: "emotesFfz",
getEmoteURL: (e) => `https://cdn.frankerfacez.com/emoticon/${e}/1`,
getOldData: (url) => url.match(/\/([0-9]+)\//)[1]
2018-01-09 04:24:00 +01:00
},
'BTTV': {
url: 'https://api.betterttv.net/emotes',
variable: 'BTTV',
2018-02-13 08:49:11 +01:00
oldVariable: "emotesBTTV",
2018-01-09 04:24:00 +01:00
parser: (data) => {
let emotes = {};
for (let e = 0, len = data.emotes.length; e < len; e++) {
let emote = data.emotes[e];
emotes[emote.regex] = emote.url;
}
return emotes;
},
2018-02-13 08:49:11 +01:00
getEmoteURL: (e) => `${e}`,
getOldData: (url) => url
2018-01-09 04:24:00 +01:00
},
'BTTV2': {
url: "https://" + bdConfig.updater.CDN + '/' + bdConfig.repo + '/BetterDiscordApp/' + bdConfig.hash + '/data/emotedata_bttv.json',
variable: 'BTTV2',
2018-02-13 08:49:11 +01:00
oldVariable: "emotesBTTV2",
getEmoteURL: (e) => `https://cdn.betterttv.net/emote/${e}/1x`,
getOldData: (url) => url.match(/emote\/(.+)\//)[1]
2018-01-09 04:24:00 +01:00
}
};
if (!bdConfig.newLoader) {
window.bdEmotes = {
TwitchGlobal: emotesTwitch,
TwitchSubscriber: subEmotesTwitch,
BTTV: emotesBTTV,
2018-01-24 00:08:20 +01:00
FrankerFaceZ: emotesFfz,
BTTV2: emotesBTTV2
2018-01-09 04:24:00 +01:00
}
for (let type in window.bdEmotes) {
for (let emote in window.bdEmotes[type]) {
window.bdEmotes[type][emote] = emoteInfo[type].getEmoteURL(window.bdEmotes[type][emote]);
}
}
return;
}
2018-03-12 19:36:13 +01:00
2018-03-15 15:30:14 +01:00
new Promise((resolve) => {
let observer = new MutationObserver((changes) => {
for (let change of changes) {
if (!change.addedNodes.length || !(change.addedNodes[0] instanceof Element) || !change.addedNodes[0].classList) continue;
let elem = change.addedNodes[0];
if (!elem.querySelector(".message")) continue;
observer.disconnect();
2018-03-15 15:30:14 +01:00
resolve(BDV2.getInternalInstance(elem.querySelector(".message")).return.type);
}
});
observer.observe(document.querySelector('.app') || document.querySelector('#app-mount'), {childList: true, subtree: true})
}).then(MessageComponent => {
2018-03-16 19:18:50 +01:00
if (this.cancel1) this.cancel1();
if (this.cancel2) this.cancel2();
2018-03-12 19:36:13 +01:00
this.cancel1 = Utils.monkeyPatch(MessageComponent.prototype, "componentDidMount", {after: (data) => {
if (!settingsCookie["bda-es-7"] && !settingsCookie["bda-es-2"] && !settingsCookie["bda-es-1"]) return;
2018-03-12 19:36:13 +01:00
let message = BDV2.reactDom.findDOMNode(data.thisObject);
message = message.querySelector('.markup');
2018-03-15 15:30:14 +01:00
if (!message) return;
this.injectEmote(message);
2018-03-12 19:36:13 +01:00
}});
2018-03-15 15:30:14 +01:00
2018-03-12 19:36:13 +01:00
this.cancel2 = Utils.monkeyPatch(MessageComponent.prototype, "componentDidUpdate", {after: (data) => {
if (!settingsCookie["bda-es-7"] && !settingsCookie["bda-es-2"] && !settingsCookie["bda-es-1"]) return;
2018-03-12 19:36:13 +01:00
let message = BDV2.reactDom.findDOMNode(data.thisObject);
message = message.querySelector('.markup');
if (!message) return;
$(message).children('.emotewrapper').remove();
2018-03-15 15:30:14 +01:00
this.injectEmote(message);
2018-03-12 19:36:13 +01:00
}});
});
2018-03-15 15:30:14 +01:00
this.loadEmoteData(emoteInfo);
this.getBlacklist();
2018-01-09 04:24:00 +01:00
};
EmoteModule.prototype.clearEmoteData = async function() {
let _fs = require("fs");
let emoteFile = "emote_data.json";
let file = bdConfig.dataPath + emoteFile;
let exists = _fs.existsSync(file);
if (exists) _fs.unlinkSync(file);
window.bdEmotes = {
TwitchGlobal: {},
TwitchSubscriber: {},
BTTV: {},
2018-01-24 00:08:20 +01:00
FrankerFaceZ: {},
2018-01-09 04:24:00 +01:00
BTTV2: {}
}
};
2018-02-13 08:49:11 +01:00
EmoteModule.prototype.goBack = async function(emoteInfo) {
for (let e in emoteInfo) {
for (let emote in bdEmotes[emoteInfo[e].variable]) {
window[emoteInfo[e].oldVariable][emote] = emoteInfo[e].getOldData(bdEmotes[emoteInfo[e].variable][emote], emote)
}
}
}
2018-01-09 04:24:00 +01:00
EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
let _fs = require("fs");
let emoteFile = "emote_data.json";
let file = bdConfig.dataPath + emoteFile;
let exists = _fs.existsSync(file);
if (exists && !bdConfig.cache.expired) {
2018-02-13 17:06:19 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast("Loading emotes from cache.", {type: "info"});
2018-01-09 04:24:00 +01:00
utils.log("[Emotes] Loading emotes from local cache.")
2018-04-16 00:58:48 +02:00
let data = await new Promise((resolve, reject) => {
_fs.readFile(file, "utf8", (err, data) => {
utils.log("[Emotes] Emotes loaded from cache.");
if (err) data = {};
resolve(data)
});
});
let isValid = this.testJSON(data);
2018-01-09 04:24:00 +01:00
if (isValid) bdEmotes = JSON.parse(data);
for (let e in emoteInfo) {
isValid = Object.keys(bdEmotes[emoteInfo[e].variable]).length > 0;
2018-01-09 04:24:00 +01:00
}
if (isValid) {
2018-02-13 08:49:11 +01:00
await this.goBack(emoteInfo)
2018-02-13 17:06:19 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast("Emotes successfully loaded.", {type: "success"})
return;
2018-01-09 04:24:00 +01:00
}
utils.log("[Emotes] Cache was corrupt, downloading...")
_fs.unlinkSync(file);
2018-01-09 04:24:00 +01:00
}
2018-05-22 06:29:04 +02:00
if (!settingsCookie["fork-es-3"]) return quickEmoteMenu.init();
2018-02-13 17:06:19 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast("Downloading emotes in the background do not reload.", {type: "info"});
2018-01-09 04:24:00 +01:00
for (let e in emoteInfo) {
let data = await this.downloadEmotes(emoteInfo[e]);
bdEmotes[emoteInfo[e].variable] = data;
}
2018-02-13 08:49:11 +01:00
await this.goBack(emoteInfo)
2018-02-13 17:06:19 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast("All emotes successfully downloaded.", {type: "success"});
2018-01-09 04:24:00 +01:00
try { _fs.writeFileSync(file, JSON.stringify(bdEmotes), "utf8"); }
catch(err) { utils.err("[Emotes] Could not save emote data.", err); }
2018-01-09 22:32:02 +01:00
quickEmoteMenu.init();
2018-01-09 04:24:00 +01:00
}
EmoteModule.prototype.downloadEmotes = function(emoteMeta) {
let request = require("request");
let options = {
url: emoteMeta.url,
timeout: emoteMeta.timeout ? emoteMeta.timeout : 5000
};
utils.log("[Emotes] Downloading: " + emoteMeta.variable);
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (error) {
utils.err("[Emotes] Could not download " + emoteMeta.variable, error)
if (emoteMeta.backup) {
emoteMeta.url = emoteMeta.backup;
emoteMeta.backup = null;
2018-04-16 06:57:38 +02:00
if (emoteMeta.backupParser) emoteMeta.parser = emoteMeta.backupParser;
2018-04-16 00:58:48 +02:00
return resolve(this.downloadEmotes(emoteMeta));
2018-01-09 04:24:00 +01:00
}
2018-04-16 00:58:48 +02:00
return reject({});
2018-01-09 04:24:00 +01:00
}
else {
2018-04-16 00:58:48 +02:00
let parsedData = {};
try {
parsedData = JSON.parse(body);
}
catch(err) {
utils.err("[Emotes] Could not download " + emoteMeta.variable, error)
if (emoteMeta.backup) {
emoteMeta.url = emoteMeta.backup;
emoteMeta.backup = null;
2018-04-16 06:57:38 +02:00
if (emoteMeta.backupParser) emoteMeta.parser = emoteMeta.backupParser;
2018-04-16 00:58:48 +02:00
return resolve(this.downloadEmotes(emoteMeta));
}
return reject({});
}
2018-01-09 04:24:00 +01:00
if (typeof(emoteMeta.parser) === "function") parsedData = emoteMeta.parser(parsedData);
for (let emote in parsedData) {
parsedData[emote] = emoteMeta.getEmoteURL(parsedData[emote]);
}
resolve(parsedData);
2018-01-24 00:08:20 +01:00
utils.log("[Emotes] Downloaded: " + emoteMeta.variable);
2018-01-09 04:24:00 +01:00
}
});
});
}
EmoteModule.prototype.testJSON = function(data) {
try {
let json = JSON.parse(data);
return true;
}
catch(err) {
return false;
}
return false;
}
2015-11-01 12:57:10 +01:00
2016-01-08 16:33:43 +01:00
EmoteModule.prototype.getBlacklist = function () {
2018-03-15 15:30:14 +01:00
$.getJSON("https://cdn.rawgit.com/rauenzi/betterDiscordApp/" + _hash + "/data/emotefilter.json", function (data) {
2016-01-08 16:33:43 +01:00
bemotes = data.blacklist;
});
2015-11-01 12:44:25 +01:00
};
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
EmoteModule.prototype.obsCallback = function (mutation) {
2018-03-12 19:36:13 +01:00
return;
2015-08-29 11:36:47 +02:00
var self = this;
2016-01-08 16:33:43 +01:00
for (var i = 0; i < mutation.addedNodes.length; ++i) {
2015-08-29 11:36:47 +02:00
var next = mutation.addedNodes.item(i);
2016-01-08 16:33:43 +01:00
if (next) {
2015-08-29 11:36:47 +02:00
var nodes = self.getNodes(next);
2016-01-08 16:33:43 +01:00
for (var node in nodes) {
if (nodes.hasOwnProperty(node)) {
var elem = nodes[node].parentElement;
if (elem && elem.classList.contains('edited')) {
2018-03-12 19:36:13 +01:00
$(elem.parentElement).children('.emotewrapper').remove();
setTimeout(() => {
2018-03-15 15:30:14 +01:00
//$(elem.parentElement).children()
2018-03-12 19:36:13 +01:00
self.injectEmote(elem, true);
}, 200);
} else {
self.injectEmote(nodes[node]);
}
}
2015-08-29 11:36:47 +02:00
}
}
}
};
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
EmoteModule.prototype.getNodes = function (node) {
2015-08-27 15:46:53 +02:00
var next;
var nodes = [];
2015-10-31 22:49:42 +01:00
var treeWalker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT, null, false);
2015-08-27 15:46:53 +02:00
2017-11-03 04:05:33 +01:00
// eslint-disable-next-line no-cond-assign
2016-01-08 16:33:43 +01:00
while (next = treeWalker.nextNode()) {
2015-08-27 15:46:53 +02:00
nodes.push(next);
}
return nodes;
};
2015-08-27 15:46:53 +02:00
2015-11-01 12:44:25 +01:00
var bemotes = [];
2015-08-27 15:46:53 +02:00
2018-01-20 02:17:52 +01:00
EmoteModule.prototype.injectEmote = async function(node, edited) {
2018-01-09 04:24:00 +01:00
let messageScroller = document.querySelector('.messages.scroller');
2018-04-07 05:39:51 +02:00
let message = node
if (message.getElementsByClassName("message-content").length) message = message.getElementsByClassName("message-content")[0];
2018-01-20 02:17:52 +01:00
let editNode = null;
2018-02-28 08:25:06 +01:00
let textNodes = utils.getTextNodes(message);
2018-04-07 05:39:51 +02:00
let words = textNodes.map(n => n.data).join(" ").split(/([^\s]+)([\s]|$)/g).filter(function(e) { return e; });
2015-08-27 15:46:53 +02:00
2018-01-20 02:17:52 +01:00
let inject = function(message, messageScroller, category, emoteName, emoteModifier) {
2018-03-16 19:18:50 +01:00
let inCategory = Object.hasOwnProperty.call(bdEmotes[category], emoteName);
2018-01-20 02:17:52 +01:00
if (!inCategory || !settingsCookie[bdEmoteSettingIDs[category]]) return false;
let url = bdEmotes[category][emoteName];
let element = this.createEmoteElement(emoteName, url, emoteModifier);
let oldHeight = message.offsetHeight;
2018-04-07 05:39:51 +02:00
utils.insertElement(message, new RegExp(`([\\s]|^)${utils.escape(emoteModifier ? emoteName + ":" + emoteModifier : emoteName)}([\\s]|$)`), $(element)[0]);
2018-01-20 02:17:52 +01:00
messageScroller.scrollTop = messageScroller.scrollTop + (message.offsetHeight - oldHeight);
return true;
}
inject = inject.bind(this, message, messageScroller);
2018-01-09 04:24:00 +01:00
for (let w = 0, len = words.length; w < len; w++) {
let emote = words[w];
let emoteSplit = emote.split(':');
let emoteName = emoteSplit[0];
let emoteModifier = emoteSplit[1] ? emoteSplit[1] : "";
2018-01-20 02:17:52 +01:00
let emoteOverride = emoteModifier.slice(0);
2016-01-08 16:33:43 +01:00
2018-01-09 04:55:12 +01:00
if (bemotes.includes(emoteName) || emoteName.length < 4) continue;
2018-01-09 04:24:00 +01:00
if (!this.modifiers.includes(emoteModifier) || !settingsCookie["bda-es-8"]) emoteModifier = "";
2018-01-20 02:17:52 +01:00
if (!this.overrides.includes(emoteOverride)) emoteOverride = "";
if (emoteOverride === "twitch") {
let tglobal = false;
let tsubscriber = false;
tglobal = inject("TwitchGlobal", emoteName, emoteOverride);
if (!tglobal) tsubscriber = inject("TwitchSubscriber", emoteName, emoteOverride);
if (tglobal || tsubscriber) continue;
}
else if (emoteOverride === "bttv") {
let bttv = false;
let bttv2 = false;
bttv = inject("BTTV", emoteName, emoteOverride);
if (!bttv) bttv2 = inject("BTTV2", emoteName, emoteOverride);
if (bttv || bttv2) continue;
}
else if (emoteOverride === "ffz") {
let ffz = inject("FrankerFaceZ", emoteName, emoteOverride);
if (ffz) continue;
}
2018-01-09 04:24:00 +01:00
for (let c = 0, clen = this.categories.length; c < clen; c++) {
2018-01-20 02:17:52 +01:00
inject(this.categories[c], emoteName, emoteModifier);
2018-01-09 04:24:00 +01:00
}
2018-01-09 04:24:00 +01:00
if (emote == "[!s]") message.classList.add("spoiler");
}
};
2016-01-08 16:33:43 +01:00
EmoteModule.prototype.createEmoteElement = function(word, url, mod) {
var len = Math.round(word.length / 4);
var name = word.substr(0, len) + "\uFDD9" + word.substr(len, len) + "\uFDD9" + word.substr(len * 2, len) + "\uFDD9" + word.substr(len * 3);
2018-01-09 04:24:00 +01:00
var stopAnim = settingsCookie['fork-es-2'] ? " stop-animation" : "";
var modClass = mod ? "emote" + mod : "";
var html = '<span class="emotewrapper"><img draggable="false" style="max-height:32px;" data-modifier="' + mod + '" class="emote ' + modClass + stopAnim + '" alt="' + name + '" src="' + url + '"/><input onclick=\'quickEmoteMenu.favorite("' + name + '", "' + url + '");\' class="fav" title="Favorite!" type="button"></span>';
return html.replace(new RegExp("\uFDD9", "g"), "");
};
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
EmoteModule.prototype.autoCapitalize = function () {
2015-08-27 15:46:53 +02:00
var self = this;
2015-08-31 15:36:28 +02:00
2018-05-05 15:45:34 +02:00
$('body').delegate($(".channelTextArea-1LDbYG textarea:first"), 'keyup change paste', function () {
2016-01-08 16:33:43 +01:00
if (!settingsCookie["bda-es-4"]) return;
2015-08-27 15:46:53 +02:00
2018-05-05 15:45:34 +02:00
var text = $(".channelTextArea-1LDbYG textarea:first").val();
2016-01-08 16:33:43 +01:00
if (text == undefined) return;
2015-08-29 11:36:47 +02:00
2015-08-27 15:46:53 +02:00
var lastWord = text.split(" ").pop();
2016-01-08 16:33:43 +01:00
if (lastWord.length > 3) {
if (lastWord == "danSgame") return;
2015-08-27 15:46:53 +02:00
var ret = self.capitalize(lastWord.toLowerCase());
2016-01-08 16:33:43 +01:00
if (ret !== null && ret !== undefined) {
2017-10-29 21:33:48 +01:00
utils.insertText(utils.getTextArea()[0], text.replace(lastWord, ret));
2015-08-27 15:46:53 +02:00
}
}
});
};
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
EmoteModule.prototype.capitalize = function (value) {
2018-01-09 04:24:00 +01:00
var res = bdEmotes.TwitchGlobal;
2016-01-08 16:33:43 +01:00
for (var p in res) {
if (res.hasOwnProperty(p) && value == (p + '').toLowerCase()) {
return p;
}
2015-08-27 15:46:53 +02:00
}
};
2016-12-05 21:05:48 +01:00
2017-04-30 03:11:22 +02:00
/* BetterDiscordApp QuickEmoteMenu JavaScript
* Version: 1.3
* Author: Jiiks | http://jiiks.net
* Date: 26/08/2015 - 11:49
* Last Update: 29/08/2015 - 11:46
* https://github.com/Jiiks/BetterDiscordApp
*/
2015-12-31 18:27:43 +01:00
2017-04-30 03:11:22 +02:00
function QuickEmoteMenu() {
2015-12-31 18:27:43 +01:00
}
2017-04-30 03:11:22 +02:00
QuickEmoteMenu.prototype.init = function() {
2015-12-31 18:27:43 +01:00
2017-04-30 03:11:22 +02:00
$(document).on("mousedown", function(e) {
if(e.target.id != "rmenu") $("#rmenu").remove();
});
this.favoriteEmotes = {};
2017-11-03 04:05:33 +01:00
var fe = window.bdStorage.get("bdfavemotes");
2017-04-30 03:11:22 +02:00
if (fe !== "" && fe !== null) {
this.favoriteEmotes = JSON.parse(atob(fe));
2016-01-08 16:33:43 +01:00
}
2015-12-31 18:27:43 +01:00
2017-11-01 06:03:48 +01:00
var qmeHeader = "";
2017-04-30 03:11:22 +02:00
qmeHeader += "<div id=\"bda-qem\">";
2017-11-03 04:05:33 +01:00
qmeHeader += " <button class=\"active\" id=\"bda-qem-twitch\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Twitch</button>";
qmeHeader += " <button id=\"bda-qem-favourite\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Favourite</button>";
qmeHeader += " <button id=\"bda-qem-emojis\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Emojis</buttond>";
2017-11-01 06:03:48 +01:00
qmeHeader += "</div>";
2017-04-30 03:11:22 +02:00
this.qmeHeader = qmeHeader;
2015-12-31 18:27:43 +01:00
2017-11-01 06:03:48 +01:00
var teContainer = "";
2017-04-30 03:11:22 +02:00
teContainer += "<div id=\"bda-qem-twitch-container\">";
teContainer += " <div class=\"scroller-wrap fade\">";
teContainer += " <div class=\"scroller\">";
teContainer += " <div class=\"emote-menu-inner\">";
2018-01-09 04:24:00 +01:00
for (let emote in bdEmotes.TwitchGlobal) {
if (bdEmotes.TwitchGlobal.hasOwnProperty(emote)) {
var url = bdEmotes.TwitchGlobal[emote];
2017-04-30 03:11:22 +02:00
teContainer += "<div class=\"emote-container\">";
2018-01-09 04:24:00 +01:00
teContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\">";
2017-04-30 03:11:22 +02:00
teContainer += " </img>";
teContainer += "</div>";
}
2015-12-31 18:27:43 +01:00
}
2017-11-03 04:05:33 +01:00
teContainer += " </div>";
teContainer += " </div>";
teContainer += " </div>";
teContainer += "</div>";
2017-04-30 03:11:22 +02:00
this.teContainer = teContainer;
2015-12-31 18:27:43 +01:00
2017-11-01 06:03:48 +01:00
var faContainer = "";
2017-04-30 03:11:22 +02:00
faContainer += "<div id=\"bda-qem-favourite-container\">";
faContainer += " <div class=\"scroller-wrap fade\">";
faContainer += " <div class=\"scroller\">";
faContainer += " <div class=\"emote-menu-inner\">";
2017-11-03 04:05:33 +01:00
for (let emote in this.favoriteEmotes) {
2017-04-30 03:11:22 +02:00
var url = this.favoriteEmotes[emote];
faContainer += "<div class=\"emote-container\">";
2017-11-01 06:03:48 +01:00
faContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\" oncontextmenu='quickEmoteMenu.favContext(event, this);'>";
2017-04-30 03:11:22 +02:00
faContainer += " </img>";
faContainer += "</div>";
2015-12-31 18:27:43 +01:00
}
2017-11-01 06:03:48 +01:00
faContainer += " </div>";
faContainer += " </div>";
faContainer += " </div>";
faContainer += "</div>";
2017-04-30 03:11:22 +02:00
this.faContainer = faContainer;
2015-12-31 18:27:43 +01:00
};
2017-04-30 03:11:22 +02:00
QuickEmoteMenu.prototype.favContext = function(e, em) {
e.stopPropagation();
2017-11-03 20:52:35 +01:00
var menu = $('<div>', { id: "rmenu", "data-emoteid": $(em).prop("title"), text: "Remove", class: "context-menu theme-dark" });
2017-04-30 03:11:22 +02:00
menu.css({
top: e.pageY - $("#bda-qem-favourite-container").offset().top,
left: e.pageX - $("#bda-qem-favourite-container").offset().left
});
$(em).parent().append(menu);
menu.on("click", function(e) {
e.preventDefault();
e.stopPropagation();
$(this).remove();
2015-12-31 18:27:43 +01:00
2017-04-30 03:11:22 +02:00
delete quickEmoteMenu.favoriteEmotes[$(this).data("emoteid")];
quickEmoteMenu.updateFavorites();
return false;
});
return false;
2015-12-31 18:27:43 +01:00
};
2017-04-30 03:11:22 +02:00
QuickEmoteMenu.prototype.switchHandler = function(e) {
this.switchQem($(e).attr("id"));
};
2015-12-12 09:50:25 +01:00
2017-04-30 03:11:22 +02:00
QuickEmoteMenu.prototype.switchQem = function(id) {
var twitch = $("#bda-qem-twitch");
var fav = $("#bda-qem-favourite");
var emojis = $("#bda-qem-emojis");
twitch.removeClass("active");
fav.removeClass("active");
emojis.removeClass("active");
2015-12-12 09:50:25 +01:00
2018-05-05 15:45:34 +02:00
$(".emojiPicker-3m1S-j").hide();
2017-04-30 03:11:22 +02:00
$("#bda-qem-favourite-container").hide();
$("#bda-qem-twitch-container").hide();
2015-12-12 09:50:25 +01:00
2017-04-30 03:11:22 +02:00
switch(id) {
case "bda-qem-twitch":
twitch.addClass("active");
$("#bda-qem-twitch-container").show();
break;
case "bda-qem-favourite":
fav.addClass("active");
$("#bda-qem-favourite-container").show();
break;
case "bda-qem-emojis":
emojis.addClass("active");
2018-05-05 15:45:34 +02:00
$(".emojiPicker-3m1S-j").show();
$(".emojiPicker-3m1S-j .search-bar-inner input, .emojiPicker-3m1S-j .search-bar-inner input").focus();
2017-04-30 03:11:22 +02:00
break;
}
this.lastTab = id;
2015-12-12 09:50:25 +01:00
2017-04-30 03:11:22 +02:00
var emoteIcon = $(".emote-icon");
emoteIcon.off();
emoteIcon.on("click", function () {
var emote = $(this).attr("title");
2017-10-29 21:33:48 +01:00
var ta = utils.getTextArea();
utils.insertText(ta[0], ta.val().slice(-1) == " " ? ta.val() + emote : ta.val() + " " + emote);
2017-04-30 03:11:22 +02:00
});
2015-12-12 09:50:25 +01:00
};
2017-10-29 21:33:48 +01:00
QuickEmoteMenu.prototype.obsCallback = function (elem) {
var e = $(elem);
2017-04-30 03:11:22 +02:00
if(!settingsCookie["bda-es-9"]) {
e.addClass("bda-qme-hidden");
} else {
e.removeClass("bda-qme-hidden");
2015-12-12 09:50:25 +01:00
}
2017-04-30 03:11:22 +02:00
if(!settingsCookie["bda-es-0"]) return;
2015-12-12 09:50:25 +01:00
2017-04-30 03:11:22 +02:00
e.prepend(this.qmeHeader);
e.append(this.teContainer);
e.append(this.faContainer);
if(this.lastTab == undefined) {
this.lastTab = "bda-qem-favourite";
}
this.switchQem(this.lastTab);
2015-12-12 13:53:07 +01:00
};
2017-04-30 03:11:22 +02:00
QuickEmoteMenu.prototype.favorite = function (name, url) {
2016-01-08 16:33:43 +01:00
2017-04-30 03:11:22 +02:00
if (!this.favoriteEmotes.hasOwnProperty(name)) {
this.favoriteEmotes[name] = url;
}
2017-04-30 03:11:22 +02:00
this.updateFavorites();
2015-12-12 13:53:07 +01:00
};
2017-04-30 03:11:22 +02:00
QuickEmoteMenu.prototype.updateFavorites = function () {
2016-01-08 16:33:43 +01:00
2017-11-01 06:03:48 +01:00
var faContainer = "";
2017-04-30 03:11:22 +02:00
faContainer += "<div id=\"bda-qem-favourite-container\">";
faContainer += " <div class=\"scroller-wrap fade\">";
faContainer += " <div class=\"scroller\">";
faContainer += " <div class=\"emote-menu-inner\">";
for (var emote in this.favoriteEmotes) {
var url = this.favoriteEmotes[emote];
faContainer += "<div class=\"emote-container\">";
2017-11-03 20:52:35 +01:00
faContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\" oncontextmenu=\"quickEmoteMenu.favContext(event, this);\">";
2017-04-30 03:11:22 +02:00
faContainer += " </img>";
faContainer += "</div>";
}
2017-11-01 06:03:48 +01:00
faContainer += " </div>";
faContainer += " </div>";
faContainer += " </div>";
faContainer += "</div>";
2017-04-30 03:11:22 +02:00
this.faContainer = faContainer;
$("#bda-qem-favourite-container").replaceWith(faContainer);
window.bdStorage.set("bdfavemotes", btoa(JSON.stringify(this.favoriteEmotes)));
};
2017-04-30 03:11:22 +02:00
2017-05-04 17:47:16 +02:00
2017-04-30 03:11:22 +02:00
/* BetterDiscordApp Utilities JavaScript
* Version: 1.0
* Author: Jiiks | http://jiiks.net
* Date: 26/08/2015 - 15:54
* https://github.com/Jiiks/BetterDiscordApp
*/
var _hash;
function Utils() {
}
Utils.prototype.getTextArea = function () {
2018-05-03 04:17:06 +02:00
return $(".channelTextArea-1LDbYG textarea");
2017-10-29 21:33:48 +01:00
};
Utils.prototype.insertText = function (textarea, text) {
2017-10-29 21:55:59 +01:00
textarea.focus();
2017-10-29 21:33:48 +01:00
textarea.selectionStart = 0;
textarea.selectionEnd = textarea.value.length;
document.execCommand("insertText", false, text);
2017-04-30 03:11:22 +02:00
};
Utils.prototype.jqDefer = function (fnc) {
if (window.jQuery) {
fnc();
} else {
setTimeout(function () {
this.jqDefer(fnc);
}, 100);
}
};
Utils.prototype.getHash = function () {
2018-05-03 04:17:06 +02:00
return new Promise((resolve) => {
2018-06-03 22:33:38 +02:00
$.getJSON("https://api.github.com/repos/rauenzi/BetterDiscordApp/commits/master").done(function (data) {
2018-05-03 04:17:06 +02:00
_hash = data.sha;
bdConfig.hash = _hash;
resolve(_hash);
2018-06-03 22:33:38 +02:00
}).fail(() => {
_hash = _bdhash || "2cdaf11a12a8ad91cb8617be20dfb0375b61783b";
resolve(_hash)
});
2017-04-30 03:11:22 +02:00
});
};
Utils.prototype.loadHtml = function (html, callback) {
var container = $("<div/>", {
class: "bd-container"
}).appendTo("body");
//TODO Inject these in next core update
2017-11-04 16:04:50 +01:00
html = '//cdn.rawgit.com/Jiiks/BetterDiscordApp/' + _hash + '/html/' + html + '.html';
2017-04-30 03:11:22 +02:00
container.load(html, callback());
};
Utils.prototype.injectJs = function (uri) {
$("<script/>", {
type: "text/javascript",
src: uri
}).appendTo($("body"));
};
Utils.prototype.injectCss = function (uri) {
$("<link/>", {
type: "text/css",
rel: "stylesheet",
href: uri
}).appendTo($("head"));
};
2017-10-29 23:23:39 +01:00
Utils.prototype.escapeID = function(id) {
return id.replace(/^[^a-z]+|[^\w-]+/gi, "");
};
2017-04-30 03:11:22 +02:00
Utils.prototype.log = function (message) {
2017-10-31 07:35:38 +01:00
console.log('%c[BetterDiscord] %c' + message + '', 'color: #3a71c1; font-weight: 700;', '');
2017-04-30 03:11:22 +02:00
};
2017-10-31 07:35:38 +01:00
Utils.prototype.err = function (message, error) {
console.log('%c[BetterDiscord] %c' + message + '', 'color: red; font-weight: 700;', '');
if (error) {
console.groupCollapsed('%cError: ' + error.message, 'color: red;');
2017-10-31 10:12:58 +01:00
console.error(error.stack);
2017-10-31 07:35:38 +01:00
console.groupEnd();
}
2017-04-30 03:11:22 +02:00
};
2018-02-28 08:25:06 +01:00
Utils.prototype.escape = function(s) {
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
};
Utils.prototype.insertElement = function(node, regex, element) {
var child = node.firstChild;
while (child) {
if (child.nodeType != Node.TEXT_NODE) {child = child.nextSibling; continue};
var bk = 0;
child.data.replace(regex, function(all) {
2018-03-16 22:01:31 +01:00
var args = [].slice.call(arguments);
var offset = args[args.length - 2];
var newTextNode = args[1] ? child.splitText(offset + args[1].length + bk) : child.splitText(offset + bk);
2018-02-28 08:25:06 +01:00
bk -= child.data.length + all.length;
2018-03-16 22:01:31 +01:00
newTextNode.data = newTextNode.data.substr(all.trim().length);
child.parentNode.insertBefore(element, newTextNode);
2018-02-28 08:25:06 +01:00
child = newTextNode;
});
regex.lastIndex = 0;
child = child.nextSibling;
}
return node;
};
Utils.prototype.getTextNodes = function(node) {
2018-03-15 15:30:14 +01:00
var textNodes = [];
if (!node) return textNodes;
2018-02-28 08:25:06 +01:00
for (var i = 0; i < node.childNodes.length; i++) {
var curNode = node.childNodes[i];
if (curNode.nodeType === Node.TEXT_NODE) {
textNodes.push(curNode)
}
}
return textNodes;
}
2018-03-12 19:36:13 +01:00
Utils.suppressErrors = (method, desiption) => (...params) => {
try { return method(...params); }
catch (e) { console.error('Error occurred in ' + desiption, e); }
};
Utils.monkeyPatch = (what, methodName, options) => {
const {before, after, instead, once = false, silent = false} = options;
const displayName = options.displayName || what.displayName || what.name || what.constructor.displayName || what.constructor.name;
if (!silent) console.log('patch', methodName, 'of', displayName); // eslint-disable-line no-console
const origMethod = what[methodName];
const cancel = () => {
if (!silent) console.log('unpatch', methodName, 'of', displayName); // eslint-disable-line no-console
what[methodName] = origMethod;
};
what[methodName] = function() {
const data = {
thisObject: this,
methodArguments: arguments,
cancelPatch: cancel,
originalMethod: origMethod,
callOriginalMethod: () => data.returnValue = data.originalMethod.apply(data.thisObject, data.methodArguments)
};
if (instead) {
const tempRet = Utils.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);
data.callOriginalMethod();
if (after) Utils.suppressErrors(after, '`after` callback of ' + what[methodName].displayName)(data);
}
if (once) cancel();
return data.returnValue;
};
what[methodName].__monkeyPatched = true;
what[methodName].displayName = 'patched ' + (what[methodName].displayName || methodName);
return cancel;
};
2017-04-30 03:11:22 +02:00
/* BetterDiscordApp VoiceMode JavaScript
* Version: 1.0
* Author: Jiiks | http://jiiks.net
* Date: 25/10/2015 - 19:10
* https://github.com/Jiiks/BetterDiscordApp
*/
function VoiceMode() {
}
VoiceMode.prototype.obsCallback = function () {
var self = this;
if (settingsCookie["bda-gs-4"]) {
self.disable();
setTimeout(function () {
self.enable();
}, 300);
}
};
VoiceMode.prototype.enable = function () {
$(".scroller.guild-channels ul").first().css("display", "none");
$(".scroller.guild-channels header").first().css("display", "none");
$(".app.flex-vertical").first().css("overflow", "hidden");
$(".chat.flex-vertical.flex-spacer").first().css("visibility", "hidden").css("min-width", "0px");
$(".flex-vertical.channels-wrap").first().css("flex-grow", "100000");
$(".guild-header .btn.btn-hamburger").first().css("visibility", "hidden");
};
VoiceMode.prototype.disable = function () {
$(".scroller.guild-channels ul").first().css("display", "");
$(".scroller.guild-channels header").first().css("display", "");
$(".app.flex-vertical").first().css("overflow", "");
$(".chat.flex-vertical.flex-spacer").first().css("visibility", "").css("min-width", "");
$(".flex-vertical.channels-wrap").first().css("flex-grow", "");
$(".guild-header .btn.btn-hamburger").first().css("visibility", "");
};
/* BetterDiscordApp PluginModule JavaScript
* Version: 1.0
* Author: Jiiks | http://jiiks.net
* Date: 16/12/2015
* https://github.com/Jiiks/BetterDiscordApp
*/
var pluginCookie = {};
function PluginModule() {
}
PluginModule.prototype.loadPlugins = function () {
this.loadPluginData();
2017-10-31 07:39:42 +01:00
var plugins = Object.keys(bdplugins);
2017-10-31 07:35:38 +01:00
for (var i = 0; i < plugins.length; i++) {
2017-10-31 07:58:39 +01:00
var plugin, name;
2017-10-31 07:35:38 +01:00
2017-10-31 07:58:39 +01:00
try {
plugin = bdplugins[plugins[i]].plugin;
2017-10-29 22:58:35 +01:00
name = plugin.getName();
plugin.load();
}
2017-10-31 09:26:30 +01:00
catch (err) {
pluginCookie[name] = false;
2017-10-31 22:28:49 +01:00
utils.err("Plugin " + name + " could not be loaded.", err);
2017-11-03 06:34:04 +01:00
bdpluginErrors.push({name: name, file: bdplugins[plugins[i]].filename, reason: "load() could not be fired.", error: {message: err.message, stack: err.stack}});
2017-10-31 22:28:49 +01:00
continue;
2017-10-31 09:26:30 +01:00
}
2017-04-30 03:11:22 +02:00
2017-10-31 07:58:39 +01:00
if (!pluginCookie[name]) pluginCookie[name] = false;
2017-04-30 03:11:22 +02:00
2017-10-31 07:58:39 +01:00
if (pluginCookie[name]) {
2017-11-03 21:08:53 +01:00
try {
plugin.start();
2017-12-24 07:51:24 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast(`${plugin.getName()} v${plugin.getVersion()} has started.`);
2017-11-03 21:08:53 +01:00
}
2017-10-31 09:26:30 +01:00
catch (err) {
pluginCookie[name] = false;
utils.err("Plugin " + name + " could not be started.", err);
2017-11-03 06:34:04 +01:00
bdpluginErrors.push({name: name, file: bdplugins[plugins[i]].filename, reason: "start() could not be fired.", error: {message: err.message, stack: err.stack}});
2017-10-31 09:26:30 +01:00
}
2017-04-30 03:11:22 +02:00
}
2017-10-31 07:35:38 +01:00
}
2018-04-15 20:13:25 +02:00
for (let plugin in pluginCookie) {
if (!bdplugins[plugin]) delete pluginCookie[plugin];
}
2017-10-31 09:26:30 +01:00
this.savePluginData();
};
PluginModule.prototype.startPlugin = function (plugin) {
2017-11-03 20:52:35 +01:00
try {
bdplugins[plugin].plugin.start();
2017-12-24 07:51:24 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast(`${bdplugins[plugin].plugin.getName()} v${bdplugins[plugin].plugin.getVersion()} has started.`);
2017-11-03 20:52:35 +01:00
}
2017-10-31 09:26:30 +01:00
catch (err) {
pluginCookie[plugin] = false;
this.savePluginData();
utils.err("Plugin " + name + " could not be started.", err);
}
};
PluginModule.prototype.stopPlugin = function (plugin) {
2017-11-03 20:52:35 +01:00
try {
bdplugins[plugin].plugin.stop();
2017-12-24 07:51:24 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast(`${bdplugins[plugin].plugin.getName()} v${bdplugins[plugin].plugin.getVersion()} has stopped.`);
2017-11-03 20:52:35 +01:00
}
catch (err) {
utils.err("Plugin " + name + " could not be stopped.", err);
}
2017-10-31 09:26:30 +01:00
};
PluginModule.prototype.enablePlugin = function (plugin) {
pluginCookie[plugin] = true;
this.savePluginData();
this.startPlugin(plugin);
};
PluginModule.prototype.disablePlugin = function (plugin) {
pluginCookie[plugin] = false;
this.savePluginData();
this.stopPlugin(plugin);
};
PluginModule.prototype.togglePlugin = function (plugin) {
2017-11-01 18:46:13 +01:00
if (pluginCookie[plugin]) this.disablePlugin(plugin);
else this.enablePlugin(plugin);
2017-04-30 03:11:22 +02:00
};
PluginModule.prototype.loadPluginData = function () {
2018-04-15 20:13:25 +02:00
if ($.cookie("bd-plugins")) {
2017-04-30 03:11:22 +02:00
pluginCookie = JSON.parse($.cookie("bd-plugins"));
2018-04-15 20:13:25 +02:00
this.savePluginData();
$.removeCookie("bd-plugins", { path: '/' });
return;
}
let saved = bdSettingsStorage.get("plugins");
if (saved) {
pluginCookie = saved;
2017-04-30 03:11:22 +02:00
}
};
PluginModule.prototype.savePluginData = function () {
2018-04-15 20:13:25 +02:00
bdSettingsStorage.set("plugins", pluginCookie);
2017-04-30 03:11:22 +02:00
};
PluginModule.prototype.newMessage = function () {
var plugins = Object.keys(bdplugins);
for (var i = 0; i < plugins.length; i++) {
var plugin = bdplugins[plugins[i]].plugin;
2017-10-31 22:28:49 +01:00
if (!pluginCookie[plugin.getName()]) continue;
if (typeof plugin.onMessage === "function") {
try { plugin.onMessage(); }
catch (err) { utils.err("Unable to fire onMessage for " + plugin.getName() + ".", err); }
2017-04-30 03:11:22 +02:00
}
}
2017-04-30 03:11:22 +02:00
};
PluginModule.prototype.channelSwitch = function () {
var plugins = Object.keys(bdplugins);
for (var i = 0; i < plugins.length; i++) {
var plugin = bdplugins[plugins[i]].plugin;
2017-10-31 22:28:49 +01:00
if (!pluginCookie[plugin.getName()]) continue;
if (typeof plugin.onSwitch === "function") {
try { plugin.onSwitch(); }
catch (err) { utils.err("Unable to fire onSwitch for " + plugin.getName() + ".", err); }
2017-04-30 03:11:22 +02:00
}
}
2017-04-30 03:11:22 +02:00
};
PluginModule.prototype.rawObserver = function(e) {
var plugins = Object.keys(bdplugins);
for (var i = 0; i < plugins.length; i++) {
var plugin = bdplugins[plugins[i]].plugin;
2017-10-31 22:28:49 +01:00
if (!pluginCookie[plugin.getName()]) continue;
if (typeof plugin.observer === "function") {
try { plugin.observer(e); }
catch (err) { utils.err("Unable to fire observer for " + plugin.getName() + ".", err); }
2017-04-30 03:11:22 +02:00
}
}
2017-04-30 03:11:22 +02:00
};
2017-10-30 04:45:07 +01:00
2017-04-30 03:11:22 +02:00
/* BetterDiscordApp ThemeModule JavaScript
* Version: 1.0
* Author: Jiiks | http://jiiks.net
* Date: 16/12/2015
* https://github.com/Jiiks/BetterDiscordApp
*/
var themeCookie = {};
function ThemeModule() {
}
ThemeModule.prototype.loadThemes = function () {
this.loadThemeData();
2017-10-31 07:58:39 +01:00
var themes = Object.keys(bdthemes);
for (var i = 0; i < themes.length; i++) {
var name = bdthemes[themes[i]].name;
if (!themeCookie[name]) themeCookie[name] = false;
2017-11-01 18:34:00 +01:00
if (themeCookie[name]) $("head").append($('<style>', {id: utils.escapeID(name), html: unescape(bdthemes[name].css)}));
}
2018-04-15 20:13:25 +02:00
for (let theme in themeCookie) {
if (!bdthemes[theme]) delete themeCookie[theme];
}
this.saveThemeData();
2017-04-30 03:11:22 +02:00
};
2017-11-01 18:34:00 +01:00
ThemeModule.prototype.enableTheme = function (theme) {
themeCookie[theme] = true;
this.saveThemeData();
$("head").append(`<style id="${utils.escapeID(bdthemes[theme].name)}">${unescape(bdthemes[theme].css)}</style>`);
2017-12-24 07:51:24 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast(`${bdthemes[theme].name} v${bdthemes[theme].version} has been applied.`);
2017-11-01 18:34:00 +01:00
};
ThemeModule.prototype.disableTheme = function (theme) {
themeCookie[theme] = false;
this.saveThemeData();
$(`#${utils.escapeID(bdthemes[theme].name)}`).remove();
2017-12-24 07:51:24 +01:00
if (settingsCookie["fork-ps-2"]) mainCore.showToast(`${bdthemes[theme].name} v${bdthemes[theme].version} has been removed.`);
2017-11-01 18:34:00 +01:00
};
2017-11-01 18:37:44 +01:00
ThemeModule.prototype.toggleTheme = function (theme) {
2017-11-01 18:46:13 +01:00
if (themeCookie[theme]) this.disableTheme(theme);
else this.enableTheme(theme);
2017-11-01 18:34:00 +01:00
};
2017-04-30 03:11:22 +02:00
ThemeModule.prototype.loadThemeData = function () {
2018-04-15 20:13:25 +02:00
if ($.cookie("bd-themes")) {
2017-04-30 03:11:22 +02:00
themeCookie = JSON.parse($.cookie("bd-themes"));
2018-04-15 20:13:25 +02:00
this.saveThemeData();
$.removeCookie("bd-themes", { path: '/' });
return;
}
let saved = bdSettingsStorage.get("themes");
if (saved) {
themeCookie = saved;
2017-04-30 03:11:22 +02:00
}
};
ThemeModule.prototype.saveThemeData = function () {
2018-04-15 20:13:25 +02:00
bdSettingsStorage.set("themes", themeCookie);
2017-04-30 03:11:22 +02:00
};
2018-04-15 20:13:25 +02:00
2017-04-30 03:11:22 +02:00
/* BetterDiscordApp API for Plugins
* Version: 1.0
* Author: Jiiks | http://jiiks.net
* Date: 11/12/2015
* Last Update: 11/12/2015
* https://github.com/Jiiks/BetterDiscordApp
*
* Plugin Template: https://gist.github.com/Jiiks/71edd5af0beafcd08956
*/
function BdApi() {}
//Inject CSS to document head
//id = id of element
//css = custom css
BdApi.injectCSS = function (id, css) {
2017-10-29 23:23:39 +01:00
$("head").append($('<style>', {id: utils.escapeID(id), html: css}));
2017-04-30 03:11:22 +02:00
};
//Clear css/remove any element
//id = id of element
BdApi.clearCSS = function (id) {
2017-10-29 23:23:39 +01:00
$("#" + utils.escapeID(id)).remove();
2017-04-30 03:11:22 +02:00
};
2017-11-03 18:34:26 +01:00
//Inject CSS to document head
//id = id of element
//css = custom css
BdApi.linkJS = function (id, url) {
$("head").append($('<script>', {id: utils.escapeID(id), src: url, type: "text/javascript"}));
};
//Clear css/remove any element
//id = id of element
BdApi.unlinkJS = function (id) {
$("#" + utils.escapeID(id)).remove();
};
2017-04-30 03:11:22 +02:00
//Get another plugin
//name = name of plugin
BdApi.getPlugin = function (name) {
if (bdplugins.hasOwnProperty(name)) {
return bdplugins[name]["plugin"];
}
return null;
};
//Get ipc for reason
BdApi.getIpc = function () {
return betterDiscordIPC;
};
//Get BetterDiscord Core
BdApi.getCore = function () {
return mainCore;
};
2017-11-03 18:34:26 +01:00
//Show modal alert
BdApi.alert = function (title, content) {
mainCore.alert(title, content);
};
2017-11-03 20:52:35 +01:00
//Show toast alert
2017-11-03 18:54:47 +01:00
BdApi.showToast = function(content, options = {}) {
2017-11-03 20:52:35 +01:00
mainCore.showToast(content, options);
2017-11-03 18:54:47 +01:00
};
2017-04-30 03:11:22 +02:00
/* BetterDiscordApp DevMode JavaScript
* Version: 1.0
* Author: Jiiks | http://jiiks.net
* Date: 22/05/2016
* Last Update: 22/05/2016
* https://github.com/Jiiks/BetterDiscordApp
*/
function devMode() {}
devMode.prototype.enable = function(selectorMode) {
var self = this;
2017-10-30 08:39:41 +01:00
this.disable();
$(window).on("keydown.bdDevmode", function(e) {
if(e.which === 119) {//F8
2017-11-03 18:34:26 +01:00
console.log('%c[%cDevMode%c] %cBreak/Resume', 'color: red;', 'color: #303030; font-weight:700;', 'color:red;', '');
2017-11-03 04:05:33 +01:00
debugger; // eslint-disable-line no-debugger
}
});
2017-10-30 04:45:07 +01:00
2018-01-09 04:24:00 +01:00
if (!selectorMode) return;
2017-10-30 05:56:20 +01:00
$(document).on("contextmenu.bdDevmode", function(e) {
var parents = [];
$(e.toElement).parents().addBack().not('html').each(function() {
var entry = "";
2017-10-30 05:56:20 +01:00
if (this.classList && this.classList.length) {
entry += "." + Array.prototype.join.call(this.classList, '.');
parents.push(entry);
}
});
self.lastSelector = parents.join(" ").trim();
2017-04-30 03:11:22 +02:00
function attach() {
2018-05-05 15:45:34 +02:00
var cm = $(".contextMenu-HLZMGh");
2017-04-30 03:11:22 +02:00
if(cm.length <= 0) {
2018-05-05 15:45:34 +02:00
cm = $('<div class="contextMenu-HLZMGh bd-context-menu"></div>');
2017-10-30 05:56:20 +01:00
cm.addClass($('.app').hasClass("theme-dark") ? "theme-dark" : "theme-light");
cm.appendTo('.app');
cm.css("top", e.clientY);
cm.css("left", e.clientX);
2017-10-30 06:20:19 +01:00
$(document).on('click.bdDevModeCtx', () => {
cm.remove();
$(document).off('.bdDevModeCtx');
});
$(document).on('contextmenu.bdDevModeCtx', () => {
cm.remove();
$(document).off('.bdDevModeCtx');
});
$(document).on("keyup.bdDevModeCtx", (e) => {
if (e.keyCode === 27) {
cm.remove();
$(document).off('.bdDevModeCtx');
}
});
2017-04-30 03:11:22 +02:00
}
var cmo = $("<div/>", {
2018-05-05 15:45:34 +02:00
class: "itemGroup-1tL0uz"
2017-04-30 03:11:22 +02:00
});
var cmi = $("<div/>", {
2018-05-05 15:45:34 +02:00
class: "item-1Yvehc",
2017-04-30 03:11:22 +02:00
click: function() {
var t = $("<textarea/>", { text: self.lastSelector }).appendTo("body");
t.select();
document.execCommand("copy");
t.remove();
2017-10-30 05:56:20 +01:00
//if (cm.hasClass("bd-context-menu")) cm.remove();
cm.hide();
2017-04-30 03:11:22 +02:00
}
}).append($("<span/>", { text: "Copy Selector" }));
cmo.append(cmi);
cm.append(cmo);
2018-03-15 15:30:14 +01:00
if (cm.hasClass("undefined")) cm.css("top", "-=" + cmo.outerHeight());
2017-04-30 03:11:22 +02:00
}
2017-10-30 08:39:41 +01:00
setImmediate(attach);
2017-04-30 03:11:22 +02:00
e.stopPropagation();
});
};
devMode.prototype.disable = function() {
$(window).off("keydown.bdDevmode");
2017-10-30 05:56:20 +01:00
$(document).off("contextmenu.bdDevmode");
2017-10-30 08:35:08 +01:00
$(document).off("contextmenu.bdDevModeCtx");
2017-04-30 03:11:22 +02:00
};
2017-11-03 18:34:26 +01:00
2017-04-30 03:11:22 +02:00
/*V2 Premature*/
window.bdtemp = {
'editorDetached': false
};
class V2 {
constructor() {
2017-12-22 02:02:35 +01:00
this.WebpackModules = (() => {
2018-05-19 05:33:57 +02:00
//__webpack_require__ = window.webpackJsonp.push([[id], {[id]: (module, exports, req) => module.exports = req}, [[id]]]);
const req = typeof(webpackJsonp) == "function" ? webpackJsonp([], {'__extra_id__': (module, exports, req) => exports.default = req}, ['__extra_id__']).default :
webpackJsonp.push([[], {'__extra_id__': (module, exports, req) => module.exports = req}, [['__extra_id__']]]);
2017-12-22 02:02:35 +01:00
delete req.m['__extra_id__'];
delete req.c['__extra_id__'];
const find = (filter, options = {}) => {
const {cacheOnly = true} = options;
for (let i in req.c) {
if (req.c.hasOwnProperty(i)) {
let m = req.c[i].exports;
if (m && m.__esModule && m.default && filter(m.default)) return m.default;
if (m && filter(m)) return m;
}
}
if (cacheOnly) {
console.warn('Cannot find loaded module in cache');
return null;
}
console.warn('Cannot find loaded module in cache. Loading all modules may have unexpected side effects');
for (let i = 0; i < req.m.length; ++i) {
try {
let m = req(i);
if (m && m.__esModule && m.default && filter(m.default)) return m.default;
if (m && filter(m)) return m;
}
catch (e) {
console.error(e);
}
}
console.warn('Cannot find module');
return null;
};
const findByUniqueProperties = (propNames, options) => find(module => propNames.every(prop => module[prop] !== undefined), options);
const findByDisplayName = (displayName, options) => find(module => module.displayName === displayName, options);
return {find, findByUniqueProperties, findByDisplayName};
})();
2017-04-30 03:11:22 +02:00
this.internal = {
2017-12-22 02:02:35 +01:00
'react': this.WebpackModules.findByUniqueProperties(['Component', 'PureComponent', 'Children', 'createElement', 'cloneElement']),
'react-dom': this.WebpackModules.findByUniqueProperties(['findDOMNode'])
2017-04-30 03:11:22 +02:00
};
2018-03-12 19:36:13 +01:00
this.getInternalInstance = e => e[Object.keys(e).find(k => k.startsWith("__reactInternalInstance"))];
2017-04-30 03:11:22 +02:00
}
get reactComponent() {
return this.internal['react'].Component;
}
get react() {
return this.internal['react'];
}
get reactDom() {
return this.internal['react-dom'];
}
parseSettings(cat) {
return Object.keys(settings).reduce((arr, key) => {
let setting = settings[key];
if(setting.cat === cat && setting.implemented && !setting.hidden) {
setting.text = key;
2017-11-03 04:05:33 +01:00
arr.push(setting);
2017-04-30 03:11:22 +02:00
} return arr;
}, []);
}
}
2017-11-01 18:12:29 +01:00
2017-04-30 03:11:22 +02:00
window.BDV2 = new V2();
class V2C_SettingsPanel extends BDV2.reactComponent {
constructor(props) {
super(props);
}
render() {
let { settings } = this.props;
return BDV2.react.createElement(
"div",
{ className: "content-column default" },
2017-12-24 07:51:24 +01:00
BDV2.react.createElement(V2Components.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),
2017-04-30 03:11:22 +02:00
settings.map(setting => {
return BDV2.react.createElement(V2Components.Switch, { id: setting.id, key: setting.id, data: setting, checked: settingsCookie[setting.id], onChange: (id, checked) => {
this.props.onChange(id, checked);
} });
})
);
}
}
class V2C_Switch extends BDV2.reactComponent {
constructor(props) {
super(props);
this.setInitialState();
this.onChange = this.onChange.bind(this);
}
setInitialState() {
this.state = {
'checked': this.props.checked
};
}
render() {
let { text, info } = this.props.data;
let { checked } = this.state;
return BDV2.react.createElement(
"div",
{ className: "ui-flex flex-vertical flex-justify-start flex-align-stretch flex-nowrap ui-switch-item" },
BDV2.react.createElement(
"div",
{ className: "ui-flex flex-horizontal flex-justify-start flex-align-stretch flex-nowrap" },
BDV2.react.createElement(
"h3",
{ className: "ui-form-title h3 margin-reset margin-reset ui-flex-child" },
text
),
BDV2.react.createElement(
"label",
{ className: "ui-switch-wrapper ui-flex-child", style: { flex: '0 0 auto' } },
BDV2.react.createElement("input", { className: "ui-switch-checkbox", type: "checkbox", checked: checked, onChange: e => this.onChange(e) }),
2017-06-17 19:08:43 +02:00
BDV2.react.createElement("div", { className: `ui-switch ${checked ? 'checked' : ''}` })
2017-04-30 03:11:22 +02:00
)
),
BDV2.react.createElement(
"div",
{ className: "ui-form-text style-description margin-top-4", style: { flex: '1 1 auto' } },
info
)
);
}
2017-11-03 04:05:33 +01:00
onChange() {
2017-04-30 03:11:22 +02:00
this.props.onChange(this.props.id, !this.state.checked);
this.setState({
'checked': !this.state.checked
});
}
}
class V2C_Scroller extends BDV2.reactComponent {
constructor(props) {
super(props);
}
render() {
2018-05-05 15:45:34 +02:00
//scrollerWrap-2lJEkd scrollerThemed-2oenus themeGhostHairline-DBD-2d scrollerFade-1Ijw5y
let wrapperClass = `scrollerWrap-2lJEkd scrollerThemed-2oenus themeGhostHairline-DBD-2d${this.props.fade ? ' scrollerFade-1Ijw5y' : ''}`;
let scrollerClass = "scroller-2FKFPG scroller"; /* fuck */
if (this.props.sidebar) scrollerClass = "scroller-2FKFPG sidebar-region-scroller scroller scroller-2FKFPG";
2018-03-30 05:08:50 +02:00
if (this.props.contentColumn) {
2018-05-05 15:45:34 +02:00
scrollerClass = "scroller-2FKFPG content-region-scroller scroller scroller-2FKFPG"; /* fuck */
wrapperClass = "scrollerWrap-2lJEkd content-region-scroller-wrap scrollerThemed-2oenus themeGhost-10fio9 scrollerTrack-3hhmU0 scrollerWrap-2lJEkd content-region-scroller-wrap scrollerThemed-2oenus themeGhost-28MSn0 scrollerTrack-1ZIpsv";
2018-03-30 05:08:50 +02:00
}
2017-04-30 03:11:22 +02:00
let { children } = this.props;
return BDV2.react.createElement(
"div",
{ key: "scrollerwrap", className: wrapperClass },
BDV2.react.createElement(
"div",
2018-03-30 05:08:50 +02:00
{ key: "scroller", ref: "scroller", className: scrollerClass },
2017-04-30 03:11:22 +02:00
children
)
);
}
}
class V2C_TabBarItem extends BDV2.reactComponent {
constructor(props) {
super(props);
this.setInitialState();
this.onClick = this.onClick.bind(this);
}
setInitialState() {
this.state = {
'selected': this.props.selected || false
};
}
render() {
return BDV2.react.createElement(
"div",
{ className: `ui-tab-bar-item${this.props.selected ? ' selected' : ''}`, onClick: this.onClick },
this.props.text
);
}
onClick() {
if (this.props.onClick) {
this.props.onClick(this.props.id);
}
}
}
class V2C_TabBarSeparator extends BDV2.reactComponent {
constructor(props) {
super(props);
}
render() {
return BDV2.react.createElement("div", { className: "ui-tab-bar-separator margin-top-8 margin-bottom-8" });
}
}
class V2C_TabBarHeader extends BDV2.reactComponent {
constructor(props) {
super(props);
}
render() {
return BDV2.react.createElement(
"div",
{ className: "ui-tab-bar-header" },
this.props.text
);
}
}
class V2C_SideBar extends BDV2.reactComponent {
constructor(props) {
super(props);
let self = this;
2017-06-17 19:08:43 +02:00
const si = $("[class*=side] > [class*=selected]");
if(si.length) {
self.scn = si.attr("class");
}
const ns = $("[class*=side] > [class*=notSelected]");
if(ns.length) {
self.nscn = ns.attr("class");
}
2018-02-05 23:48:19 +01:00
$("[class*='side-'] > [class*='item-']").on("click", () => {
2017-04-30 03:11:22 +02:00
self.setState({
'selected': null
});
});
self.setInitialState();
self.onClick = self.onClick.bind(self);
}
setInitialState() {
let self = this;
self.state = {
'selected': null,
'items': self.props.items
};
let initialSelection = self.props.items.find(item => {
return item.selected;
});
if (initialSelection) {
self.state.selected = initialSelection.id;
}
}
render() {
let self = this;
let { headerText } = self.props;
let { items, selected } = self.state;
return BDV2.react.createElement(
"div",
null,
BDV2.react.createElement(V2Components.TabBar.Separator, null),
BDV2.react.createElement(V2Components.TabBar.Header, { text: headerText }),
items.map(item => {
let { id, text } = item;
return BDV2.react.createElement(V2Components.TabBar.Item, { key: id, selected: selected === id, text: text, id: id, onClick: self.onClick });
})
);
}
onClick(id) {
let self = this;
2017-06-17 19:08:43 +02:00
const si = $("[class*=side] > [class*=selected]");
if(si.length) {
si.off("click.bdsb").on("click.bsb", e => {
$(e.target).attr("class", self.scn);
});
si.attr("class", self.nscn);
}
2017-11-03 04:05:33 +01:00
self.setState({'selected': null});
self.setState({'selected': id});
2017-04-30 03:11:22 +02:00
if (self.props.onClick) self.props.onClick(id);
}
}
class V2C_XSvg extends BDV2.reactComponent {
constructor(props) {
super(props);
}
render() {
return BDV2.react.createElement(
"svg",
{ xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 12 12", style: { width: "18px", height: "18px" } },
BDV2.react.createElement(
"g",
2017-10-29 22:20:45 +01:00
{ className: "background", fill: "none", "fillRule": "evenodd" },
2017-04-30 03:11:22 +02:00
BDV2.react.createElement("path", { d: "M0 0h12v12H0" }),
BDV2.react.createElement("path", { className: "fill", fill: "#dcddde", d: "M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6" })
)
);
}
}
class V2C_Tools extends BDV2.reactComponent {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
render() {
return BDV2.react.createElement(
"div",
{ className: "tools" },
BDV2.react.createElement(
"div",
{ className: "btn-close", onClick: this.onClick },
BDV2.react.createElement(V2Components.XSvg, null)
),
BDV2.react.createElement(
"div",
{ className: "esc-text" },
"ESC"
)
);
}
onClick() {
if (this.props.onClick) {
this.props.onClick();
}
$(".btn-close").first().click();
}
}
class V2C_SettingsTitle extends BDV2.reactComponent {
constructor(props) {
super(props);
}
render() {
return BDV2.react.createElement(
"h2",
{ className: "ui-form-title h2 margin-reset margin-bottom-20" },
this.props.text
);
}
}
class V2C_Checkbox extends BDV2.reactComponent {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.setInitialState();
}
setInitialState() {
this.state = {
'checked': this.props.checked || false
};
}
render() {
return BDV2.react.createElement(
"li",
null,
BDV2.react.createElement(
"div",
{ className: "checkbox", onClick: this.onClick },
BDV2.react.createElement(
"div",
{ className: "checkbox-inner" },
BDV2.react.createElement("input", { checked: this.state.checked, onChange: () => {}, type: "checkbox" }),
BDV2.react.createElement("span", null)
),
BDV2.react.createElement(
"span",
null,
this.props.text
)
)
);
}
onClick() {
this.props.onChange(this.props.id, !this.state.checked);
this.setState({
'checked': !this.state.checked
});
}
}
class V2C_CssEditorDetached extends BDV2.reactComponent {
constructor(props) {
super(props);
let self = this;
self.onClick = self.onClick.bind(self);
self.updateCss = self.updateCss.bind(self);
self.saveCss = self.saveCss.bind(self);
self.onChange = self.onChange.bind(self);
}
componentDidMount() {
$("#app-mount").addClass('bd-detached-editor');
window.bdtemp.editorDetached = true;
// this.updateLineCount();
this.editor = ace.edit("bd-customcss-editor-detached");
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();
});
2017-04-30 03:11:22 +02:00
}
componentWillUnmount() {
$("#app-mount").removeClass('bd-detached-editor');
window.bdtemp.editorDetached = false;
this.editor.destroy();
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
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;
}
2017-04-30 03:11:22 +02:00
get options() {
return {
lineNumbers: true,
mode: 'css',
indentUnit: 4,
theme: 'material',
scrollbarStyle: 'simple'
};
}
get css() {
let _ccss = window.bdStorage.get("bdcustomcss");
let ccss = "";
if (_ccss && _ccss !== "") {
ccss = atob(_ccss);
}
return ccss;
}
get root() {
let _root = $("#bd-customcss-detach-container");
if (!_root.length) {
if (!this.injectRoot()) return null;
return this.detachedRoot;
}
return _root[0];
}
injectRoot() {
if (!$(".app").length) return false;
$("<div/>", {
id: 'bd-customcss-detach-container'
}).insertAfter($(".app"));
return true;
}
render() {
let self = this;
return BDV2.react.createElement(
"div",
{ className: "bd-detached-css-editor", id: "bd-customcss-detach-editor" },
BDV2.react.createElement(
"div",
{ id: "bd-customcss-innerpane" },
2018-01-09 04:24:00 +01:00
BDV2.react.createElement("div", {className: "editor-wrapper"},
BDV2.react.createElement("div", {id: "bd-customcss-editor-detached", className: "editor", ref: "editor"}, self.css)
2018-01-09 04:24:00 +01:00
),
2017-04-30 03:11:22 +02:00
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: self.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("attach");
} },
"Attach"
),
BDV2.react.createElement(
"span",
{ style: { fontSize: "10px", marginLeft: "5px" } },
"Unsaved changes are lost on attach"
)
)
)
)
);
}
onChange(id, checked) {
switch (id) {
case 'live-update':
settingsCookie["bda-css-0"] = checked;
mainCore.saveSettings();
break;
}
}
onClick(id) {
let self = this;
switch (id) {
case 'attach':
if ($("#editor-detached").length) self.props.attach();
2017-04-30 03:11:22 +02:00
BDV2.reactDom.unmountComponentAtNode(self.root);
self.root.remove();
2017-04-30 03:11:22 +02:00
break;
case 'update':
self.updateCss();
break;
case 'save':
self.saveCss();
break;
}
}
updateCss() {
if ($("#customcss").length == 0) {
$("head").append('<style id="customcss"></style>');
}
$("#customcss").html(this.editor.session.getValue()).detach().appendTo(document.head);
2017-04-30 03:11:22 +02:00
}
saveCss() {
window.bdStorage.set("bdcustomcss", btoa(this.editor.session.getValue()));
2017-04-30 03:11:22 +02:00
}
}
class V2C_CssEditor extends BDV2.reactComponent {
constructor(props) {
super(props);
let self = this;
2018-01-09 04:24:00 +01:00
self.props.lines = 0;
2017-04-30 03:11:22 +02:00
self.setInitialState();
self.attach = self.attach.bind(self);
self.detachedEditor = BDV2.react.createElement(V2C_CssEditorDetached, { attach: self.attach });
2017-04-30 03:11:22 +02:00
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 || window.bdtemp.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();
2017-04-30 03:11:22 +02:00
}
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 = window.bdStorage.get("bdcustomcss");
let ccss = "";
if (_ccss && _ccss !== "") {
ccss = atob(_ccss);
}
return ccss;
}
2018-01-09 04:24:00 +01:00
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;
}
2017-04-30 03:11:22 +02:00
render() {
let self = this;
let { detached } = self.state;
return BDV2.react.createElement(
"div",
{ className: "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" }),
2018-01-09 04:24:00 +01:00
BDV2.react.createElement("div", {className: "editor-wrapper"},
BDV2.react.createElement("div", {id: "bd-customcss-editor", className: "editor", ref: "editor"}, self.css)
2018-01-09 04:24:00 +01:00
),
2017-04-30 03:11:22 +02:00
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"
)
)
)
)
);
}
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('<style id="customcss"></style>');
}
$("#customcss").html(this.editor.session.getValue()).detach().appendTo(document.head);
2017-04-30 03:11:22 +02:00
}
saveCss() {
window.bdStorage.set("bdcustomcss", btoa(this.editor.session.getValue()));
2017-04-30 03:11:22 +02:00
}
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").length) return false;
$("<div/>", {
id: 'bd-customcss-detach-container'
}).insertAfter($(".app"));
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: "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";
2018-01-09 04:24:00 +01:00
self.settingsPanel = "";
2017-04-30 03:11:22 +02:00
}
setInitialState() {
this.state = {
'checked': pluginCookie[this.props.plugin.getName()],
'settings': false
};
}
componentDidUpdate() {
if (this.state.settings) {
2017-04-30 13:02:42 +02:00
if (typeof this.settingsPanel === "object") {
this.refs.settingspanel.appendChild(this.settingsPanel);
}
2017-12-24 07:51:24 +01:00
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);
2018-01-09 04:24:00 +01:00
};
2017-12-24 07:51:24 +01:00
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);
2017-04-30 03:11:22 +02:00
}
}
render() {
2017-04-30 13:02:42 +02:00
let self = this;
2017-04-30 03:11:22 +02:00
let { plugin } = this.props;
let name = plugin.getName();
let author = plugin.getAuthor();
let description = plugin.getDescription();
let version = plugin.getVersion();
2017-11-01 19:52:57 +01:00
let website = bdplugins[name].website;
let source = bdplugins[name].source;
//let { settingsPanel } = this;
2017-04-30 03:11:22 +02:00
if (this.state.settings) {
2017-12-22 23:06:56 +01:00
try { self.settingsPanel = plugin.getSettingsPanel(); }
catch (err) { utils.err("Unable to get settings panel for " + plugin.getName() + ".", err); }
2017-11-01 18:28:04 +01:00
return BDV2.react.createElement("li", {className: "settings-open ui-switch-item"},
BDV2.react.createElement("div", {style: { float: "right", cursor: "pointer" }, onClick: () => {
2017-11-01 18:12:29 +01:00
this.refs.settingspanel.innerHTML = "";
2017-11-01 18:28:04 +01:00
self.setState({'settings': false });
}},
2017-04-30 03:11:22 +02:00
BDV2.react.createElement(V2Components.XSvg, null)
),
2017-12-22 23:06:56 +01:00
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 } })
2017-04-30 03:11:22 +02:00
);
}
2017-11-01 18:12:29 +01:00
return BDV2.react.createElement("li", {"data-name": name, "data-version": version, className: "settings-closed ui-switch-item"},
BDV2.react.createElement("div", {className: "bda-header"},
2017-11-01 17:09:58 +01:00
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("label", {className: "ui-switch-wrapper ui-flex-child", style: { flex: '0 0 auto' }},
2017-11-01 16:21:55 +01:00
BDV2.react.createElement("input", { checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox" }),
2017-11-01 18:12:29 +01:00
BDV2.react.createElement("div", { className: this.state.checked ? "ui-switch checked" : "ui-switch" })
2017-04-30 03:11:22 +02:00
)
),
2017-11-01 18:12:29 +01:00
BDV2.react.createElement("div", {className: "bda-description-wrap scroller-wrap fade"},
BDV2.react.createElement("div", {className: "bda-description scroller"}, description)
2017-11-01 16:21:55 +01:00
),
2017-12-24 07:51:24 +01:00
(website || source || this.hasSettings) && BDV2.react.createElement("div", {className: "bda-footer"},
2017-11-01 18:12:29 +01:00
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")
),
this.hasSettings && BDV2.react.createElement("button", {onClick: this.showSettings, className: "bda-settings-button", disabled: !this.state.checked}, "Settings")
2017-04-30 03:11:22 +02:00
)
);
}
onChange() {
2017-11-01 18:34:00 +01:00
this.setState({'checked': !this.state.checked});
pluginModule.togglePlugin(this.props.plugin.getName());
2017-04-30 03:11:22 +02:00
}
showSettings() {
if (!this.hasSettings) return;
2017-11-01 18:28:04 +01:00
this.setState({'settings': true});
2017-04-30 03:11:22 +02:00
}
}
class V2C_ThemeCard extends BDV2.reactComponent {
constructor(props) {
super(props);
this.setInitialState();
this.onChange = this.onChange.bind(this);
}
setInitialState() {
this.state = {
'checked': themeCookie[this.props.theme.name]
};
}
render() {
let { theme } = this.props;
2017-10-31 10:12:58 +01:00
let name = theme.name;
2017-04-30 03:11:22 +02:00
let description = theme.description;
let version = theme.version;
let author = theme.author;
2017-11-01 18:12:29 +01:00
let website = bdthemes[name].website;
let source = bdthemes[name].source;
2017-11-01 17:09:58 +01:00
2017-11-01 18:28:04 +01:00
return BDV2.react.createElement("li", {"data-name": name, "data-version": version, className: "settings-closed ui-switch-item"},
BDV2.react.createElement("div", {className: "bda-header"},
2017-11-01 17:09:58 +01:00
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)
),
2017-11-01 17:56:51 +01:00
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" }),
2017-11-01 18:12:29 +01:00
BDV2.react.createElement("div", { className: this.state.checked ? "ui-switch checked" : "ui-switch" })
2017-11-01 17:56:51 +01:00
)
2017-04-30 03:11:22 +02:00
),
2017-11-01 18:28:04 +01:00
BDV2.react.createElement("div", {className: "bda-description-wrap scroller-wrap fade"},
BDV2.react.createElement("div", {className: "bda-description scroller"}, description)
2017-11-01 17:09:58 +01:00
),
2017-12-24 07:51:24 +01:00
(website || source) && BDV2.react.createElement("div", {className: "bda-footer"},
2017-11-01 18:12:29 +01:00
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")
)
2017-04-30 03:11:22 +02:00
)
);
}
onChange() {
2017-11-01 18:34:00 +01:00
this.setState({'checked': !this.state.checked});
themeModule.toggleTheme(this.props.theme.name);
2017-04-30 03:11:22 +02:00
}
}
class V2Cs_TabBar {
static get Item() {
return V2C_TabBarItem;
}
static get Header() {
return V2C_TabBarHeader;
}
static get Separator() {
return V2C_TabBarSeparator;
}
}
2018-01-09 04:24:00 +01:00
class V2Components {
static get SettingsPanel() {
return V2C_SettingsPanel;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
static get Switch() {
return V2C_Switch;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
static get Scroller() {
return V2C_Scroller;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
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 XSvg() {
return V2C_XSvg;
}
static get Layer() {
return V2C_Layer;
}
static get SidebarView() {
return V2C_SidebarView;
}
static get ServerCard() {
return V2C_ServerCard;
2017-04-30 03:11:22 +02:00
}
}
2018-01-09 04:24:00 +01:00
class V2_SettingsPanel_Sidebar {
2017-04-30 03:11:22 +02:00
2018-01-09 04:24:00 +01:00
constructor(onClick) {
this.onClick = onClick;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
get items() {
return [{ 'text': 'Core', 'id': 'core' }, { 'text': 'Zere\'s Fork', 'id': 'fork' }, { 'text': 'Emotes', 'id': 'emotes' }, { 'text': 'Custom CSS', 'id': 'customcss' }, { 'text': 'Plugins', 'id': 'plugins' }, { 'text': 'Themes', 'id': 'themes' }];
}
get component() {
2017-04-30 03:11:22 +02:00
return BDV2.react.createElement(
2018-01-09 04:24:00 +01:00
"span",
null,
BDV2.react.createElement(V2Components.SideBar, { onClick: this.onClick, headerText: "Bandaged BD", items: this.items }),
2017-04-30 03:11:22 +02:00
BDV2.react.createElement(
"div",
2018-01-09 04:24:00 +01:00
{ style: { fontSize: "12px", fontWeight: "600", color: "#72767d", padding: "2px 10px" } },
`BD v${bdVersion}, JS v${jsVersion} by `,
BDV2.react.createElement(
"a",
{ href: "https://github.com/Jiiks/", target: "_blank" },
"Jiiks"
)
2017-04-30 03:11:22 +02:00
),
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
2017-04-30 03:11:22 +02:00
"div",
2018-01-09 04:24:00 +01:00
{ 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"
)
2017-04-30 03:11:22 +02:00
)
);
}
2018-01-09 04:24:00 +01:00
get root() {
let _root = $("#bd-settings-sidebar");
if (!_root.length) {
if (!this.injectRoot()) return null;
return this.root;
}
return _root[0];
}
injectRoot() {
2018-02-05 23:48:19 +01:00
let changeLog = $("[class*='side-'] > [class*='item-']:not([class*=Danger])").last();
2018-01-09 04:24:00 +01:00
if (!changeLog.length) return false;
$("<span/>", { 'id': 'bd-settings-sidebar' }).insertBefore(changeLog.prev());
return true;
2017-04-30 03:11:22 +02:00
}
render() {
2018-01-09 04:24:00 +01:00
let root = this.root;
if (!root) {
2018-02-05 23:48:19 +01:00
console.log("FAILED TO LOCATE ROOT: [class*='side-'] > [class*='item-']:not([class*=Danger])");
2018-01-09 04:24:00 +01:00
return;
}
BDV2.reactDom.render(this.component, root);
}
}
2017-04-30 03:11:22 +02:00
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() {
2018-05-05 15:45:34 +02:00
if (!$(".layer-3QrUeG .ui-standard-sidebar-view, .layer-3QrUeG .ui-standard-sidebar-view").length) return false;
$(".layer-3QrUeG .ui-standard-sidebar-view, .layer-3QrUeG .ui-standard-sidebar-view").append($("<div/>", {
2017-04-30 03:11:22 +02:00
class: 'content-region',
id: 'bd-settingspane-container'
}));
return true;
}
get coreSettings() {
return this.getSettings("core");
2017-12-24 07:51:24 +01:00
}
get forkSettings() {
return this.getSettings("fork");
2017-04-30 03:11:22 +02:00
}
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;
$(".content-region").first().hide();
$(self.root).show();
switch (id) {
case 'core':
self.renderCoreSettings();
break;
2017-12-24 07:51:24 +01:00
case 'fork':
self.renderForkSettings();
break;
2017-04-30 03:11:22 +02:00
case 'emotes':
self.renderEmoteSettings();
break;
case 'customcss':
self.renderCustomCssEditor();
break;
case 'plugins':
self.renderPluginPane();
break;
case 'themes':
self.renderThemePane();
break;
}
}
2017-11-03 04:05:33 +01:00
onClick() {}
2017-04-30 03:11:22 +02:00
onChange(id, checked) {
settingsCookie[id] = checked;
this.updateSettings();
}
updateSettings() {
2017-10-30 22:33:38 +01:00
let _c = settingsCookie;
if (_c["bda-es-0"]) {
$("#twitchcord-button-container").show();
} else {
$("#twitchcord-button-container").hide();
}
if (_c["bda-gs-b"]) {
$("body").addClass("bd-blue");
} else {
$("body").removeClass("bd-blue");
}
if (_c["bda-gs-2"]) {
$("body").addClass("bd-minimal");
} else {
$("body").removeClass("bd-minimal");
}
if (_c["bda-gs-3"]) {
$("body").addClass("bd-minimal-chan");
} else {
$("body").removeClass("bd-minimal-chan");
}
if (_c["bda-gs-1"]) {
$("#bd-pub-li").show();
} else {
$("#bd-pub-li").hide();
}
if (_c["bda-gs-4"]) {
voiceMode.enable();
} else {
voiceMode.disable();
}
if (_c["bda-gs-5"]) {
$("#app-mount").addClass("bda-dark");
} else {
$("#app-mount").removeClass("bda-dark");
}
2017-11-04 06:59:30 +01:00
if (document.querySelector('.messages')) {
let elem = document.querySelector('.messages');
if (_c["bda-gs-6"]) {
mainCore.inject24Hour(elem);
} else {
mainCore.remove24Hour(elem);
}
if (_c["bda-gs-7"] && document.querySelector('.messages')) {
mainCore.injectColoredText(elem);
} else {
mainCore.removeColoredText(elem);
}
}
2017-12-24 07:51:24 +01:00
if (_c["fork-es-2"]) {
$('.emote').each(() => {
2018-01-09 04:24:00 +01:00
$(this).addClass("stop-animation");
2017-12-24 07:51:24 +01:00
});
}
else {
$('.emote').each(() => {
2018-01-09 04:24:00 +01:00
$(this).removeClass("stop-animation");
2017-12-24 07:51:24 +01:00
});
}
$(document).off('mouseover', '.emote');
//Pretty emote titles
var emoteNamePopup = $("<div class='tipsy tipsy-se' style='display: block; top: 82px; left: 1630.5px; visibility: visible; opacity: 0.8;'><div class='tipsy-inner'></div></div>");
$(document).on("mouseover", ".emote", function () {
var emote = $(this);
if (_c["fork-es-2"] && _c["bda-es-8"]) emote.removeClass("stop-animation");
if (!_c["bda-es-6"]) return;
var x = emote.offset();
var title = emote.attr("alt");
2018-01-09 04:24:00 +01:00
var modifier = emote.attr("data-modifier");
2017-12-24 07:51:24 +01:00
if (modifier && _c["fork-es-1"]) title = title + ":" + modifier;
emoteNamePopup.find(".tipsy-inner").text(title);
$(".app").append($(emoteNamePopup));
var nodecenter = x.left + (emote.outerWidth() / 2);
emoteNamePopup.css("left", nodecenter - (emoteNamePopup.outerWidth() / 2));
emoteNamePopup.css('top', x.top - emoteNamePopup.outerHeight());
});
$(document).on("mouseleave", ".emote", function () {
if (_c["bda-es-6"]) $(".tipsy").remove();
if (_c["fork-es-2"] && _c["bda-es-8"]) $(this).addClass("stop-animation");
});
2017-10-30 22:33:38 +01:00
if (_c["bda-gs-8"]) {
2017-12-24 07:51:24 +01:00
dMode.enable(_c["fork-dm-1"]);
2017-10-30 22:33:38 +01:00
} else {
dMode.disable();
}
mainCore.saveSettings();
2017-04-30 03:11:22 +02:00
}
renderSidebar() {
let self = this;
2018-02-05 23:48:19 +01:00
$("[class*='side-'] > [class*='item-']").off('click.v2settingspanel').on('click.v2settingspanel', () => {
2017-04-30 03:11:22 +02:00
BDV2.reactDom.unmountComponentAtNode(self.root);
$(self.root).hide();
$(".content-region").first().show();
});
self.sidebar.render();
}
get coreComponent() {
2018-03-30 05:08:50 +02:00
return BDV2.react.createElement(V2Components.Scroller, { contentColumn: true, fade: true, dark: true, children: [BDV2.react.createElement(V2Components.SettingsPanel, { key: "cspanel", title: "Core Settings", onChange: this.onChange, settings: this.coreSettings }), BDV2.react.createElement(V2Components.Tools, { key: "tools" })] });
2017-04-30 03:11:22 +02:00
}
2017-12-24 07:51:24 +01:00
get forkComponent() {
return BDV2.react.createElement(V2Components.Scroller, {
2018-03-30 05:08:50 +02:00
contentColumn: true,
2017-12-24 07:51:24 +01:00
fade: true,
dark: true,
children: [
BDV2.react.createElement(V2Components.SettingsPanel, { key: "fspanel", title: "Zere's Fork Settings", onChange: this.onChange, settings: this.forkSettings, button: {
2018-01-09 04:24:00 +01:00
title: "Clear Emote Cache",
2018-01-09 22:32:02 +01:00
onClick: () => { emoteModule.clearEmoteData(); emoteModule.init(); quickEmoteMenu.init(); }
2017-12-24 07:51:24 +01:00
}}),
BDV2.react.createElement(V2Components.Tools, { key: "tools" })
]
}
);
}
2017-04-30 03:11:22 +02:00
get emoteComponent() {
2018-03-30 05:08:50 +02:00
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 }), BDV2.react.createElement(V2Components.Tools, { key: "tools" })] });
2017-04-30 03:11:22 +02:00
}
get customCssComponent() {
2018-03-30 05:08:50 +02:00
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" })] });
2017-04-30 03:11:22 +02:00
}
get pluginsComponent() {
let plugins = Object.keys(bdplugins).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 });
2017-10-29 22:20:45 +01:00
let pfBtn = BDV2.react.createElement("button", {key: "folder-button", className: 'bd-pfbtn', onClick: () => { betterDiscordIPC.send('asynchronous-message', { 'arg': 'opendir', 'path': 'plugindir' }); }}, "Open Plugin Folder");
2017-05-12 21:45:19 +02:00
let contentColumn = BDV2.react.createElement(V2Components.ContentColumn, { key: "pcolumn", title: "Plugins", children: [pfBtn, list] });
2018-03-30 05:08:50 +02:00
return BDV2.react.createElement(V2Components.Scroller, { contentColumn: true, fade: true, dark: true, children: [contentColumn, BDV2.react.createElement(V2Components.Tools, { key: "tools" })] });
2017-04-30 03:11:22 +02:00
}
get themesComponent() {
let themes = Object.keys(bdthemes).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 });
2017-10-29 22:20:45 +01:00
let tfBtn = BDV2.react.createElement("button", {key: "folder-button", className: 'bd-pfbtn', onClick: () => { betterDiscordIPC.send('asynchronous-message', { 'arg': 'opendir', 'path': 'themedir' }); }}, "Open Theme Folder");
2017-05-12 21:45:19 +02:00
let contentColumn = BDV2.react.createElement(V2Components.ContentColumn, { key: "tcolumn", title: "Themes", children: [tfBtn, list] });
2018-03-30 05:08:50 +02:00
return BDV2.react.createElement(V2Components.Scroller, { contentColumn: true, fade: true, dark: true, children: [contentColumn, BDV2.react.createElement(V2Components.Tools, { key: "tools" })] });
2017-04-30 03:11:22 +02:00
}
renderCoreSettings() {
let root = this.root;
if (!root) {
console.log("FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view");
return;
}
BDV2.reactDom.render(this.coreComponent, root);
}
2017-12-24 07:51:24 +01:00
renderForkSettings() {
let root = this.root;
if (!root) {
console.log("FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view");
return;
}
BDV2.reactDom.render(this.forkComponent, root);
}
2017-04-30 03:11:22 +02:00
renderEmoteSettings() {
let root = this.root;
if (!root) {
console.log("FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view");
return;
}
BDV2.reactDom.render(this.emoteComponent, root);
}
renderCustomCssEditor() {
let root = this.root;
if (!root) {
console.log("FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view");
return;
}
BDV2.reactDom.render(this.customCssComponent, root);
}
renderPluginPane() {
let root = this.root;
if (!root) {
console.log("FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view");
return;
}
BDV2.reactDom.render(this.pluginsComponent, root);
}
renderThemePane() {
let root = this.root;
if (!root) {
console.log("FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view");
return;
}
BDV2.reactDom.render(this.themesComponent, root);
}
}
2018-01-09 04:24:00 +01:00
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);
}
});
2018-03-29 09:56:07 +02:00
$(`#${this.props.id}`).animate({opacity: 1}, {
step: function(now, fx) {
$(this).css("transform", `scale(${1.1 - 0.1*now}) translateZ(0px)`);
},
duration: 200,
done: () => {$(`#${this.props.id}`).css("opacity", "").css("transform", "");}
});
2018-01-09 04:24:00 +01:00
}
componentWillUnmount() {
$(window).off(`keyup.${this.props.id}`);
2018-03-29 09:56:07 +02:00
$(`#${this.props.id}`).animate({opacity: 0}, {
step: function(now, fx) {
$(this).css("transform", `scale(${1.1 - 0.1*now}) translateZ(0px)`);
},
duration: 200,
done: () => {$(`#${this.props.rootId}`).remove();}
});
$('[class*="layer-"]').animate({opacity: 1}, {
step: function(now, fx) {
$(this).css("transform", `scale(${0.07*now + 0.93}) translateZ(0px)`);
},
duration: 200,
done: () => {$('[class*="layer-"]').css("opacity", "").css("transform", "");}
});
}
componentWillMount() {
$('[class*="layer-"]').animate({opacity: 0}, {
step: function(now, fx) {
$(this).css("transform", `scale(${0.07*now + 0.93}) translateZ(0px)`);
},
duration: 200
});
2018-01-09 04:24:00 +01:00
}
render() {
return BDV2.react.createElement(
"div",
2018-05-05 15:45:34 +02:00
{ className: "layer bd-layer layer-3QrUeG", id: this.props.id, ref: "root", style: {opacity: 0, transform: "scale(1.1) translateZ(0px)"} },
2018-01-09 04:24:00 +01:00
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: "ui-standard-sidebar-view" },
BDV2.react.createElement(
"div",
{ className: "sidebar-region" },
2018-03-29 09:56:07 +02:00
BDV2.react.createElement(V2Components.Scroller, { key: "sidebarScroller", ref: "sidebarScroller", sidebar: true, fade: sidebar.fade || true, dark: sidebar.dark || true, children: sidebar.component })
2018-01-09 04:24:00 +01:00
),
BDV2.react.createElement("div", {className: "content-region"},
BDV2.react.createElement("div", {className: "content-transition-wrap"},
2018-05-05 15:45:34 +02:00
BDV2.react.createElement("div", {className: "scrollerWrap-2lJEkd content-region-scroller-wrap scrollerThemed-2oenus themeGhost-28MSn0 scrollerTrack-1ZIpsv"},
BDV2.react.createElement("div", {className: "scroller-2FKFPG content-region-scroller scroller", ref: "contentScroller"},
2018-01-09 04:24:00 +01:00
BDV2.react.createElement("div", {className: "content-column default"}, content.component),
tools.component
)
)
)
)
);
}
}
class V2_PublicServers {
constructor() {}
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() {
2018-05-05 15:45:34 +02:00
if (!$(".layers, .layers-3iHuyZ").length) return false;
$(".layers, .layers-3iHuyZ").append($("<div/>", {
2018-01-09 04:24:00 +01:00
id: 'pubslayerroot'
}));
return true;
}
render() {
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: 'guild',
id: 'bd-pub-li',
css: {
'height': '20px',
'display': settingsCookie['bda-gs-1'] ? "" : "none"
}
}).append($("<div/>", {
class: 'guild-inner',
css: {
'height': '20px',
'border-radius': '4px'
}
}).append($("<a/>", {
}).append($("<div/>", {
text: 'public',
id: 'bd-pub-button',
css: {
'line-height': '20px',
'font-size': '12px'
},
click: () => { this.render(); }
}))));
return btn;
}
initialize() {
let guilds = $(".guilds>:first-child");
guilds.after(this.button);
}
}
class V2C_ServerCard extends BDV2.reactComponent {
constructor(props) {
super(props);
2018-03-29 09:56:07 +02:00
if (!this.props.server.iconUrl) this.props.server.iconUrl = this.props.fallback;
2018-01-09 04:24:00 +01:00
this.state = {
imageError: false,
joined: this.props.guildList.includes(this.props.server.identifier)
};
}
render() {
let { server } = this.props;
return BDV2.react.createElement(
2018-05-05 15:45:34 +02:00
"div", // cardPrimary-1Hv-to
{ className: `card-3Qj_Yx cardPrimary-1Hv-to marginBottom8-AtZOdT bd-server-card${server.pinned ? ' bd-server-card-pinned' : ''}` },
2018-03-29 09:56:07 +02:00
// BDV2.react.createElement(
// "div",
2018-05-05 15:45:34 +02:00
// { className: "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY flex-1O1GKY directionRow-3v3tfG justifyStart-2yIZo0 alignStretch-1hwxMa noWrap-3jynv6" },
2018-03-29 09:56:07 +02:00
BDV2.react.createElement("img", { ref: "img", className: "bd-server-image", src: server.iconUrl, onError: this.handleError.bind(this) }),
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
"div",
2018-05-05 15:45:34 +02:00
{ className: "flexChild-faoVW3 bd-server-content" },
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
"div",
2018-05-05 15:45:34 +02:00
{ className: "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY directionRow-3v3tfG noWrap-3jynv6 bd-server-header" },
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
2018-03-29 09:56:07 +02:00
"h5",
2018-05-05 15:45:34 +02:00
{ className: "h5-18_1nd defaultColor-1_ajX0 margin-reset bd-server-name" },
2018-03-29 09:56:07 +02:00
server.name
2018-01-09 04:24:00 +01:00
),
BDV2.react.createElement(
2018-03-29 09:56:07 +02:00
"h5",
2018-05-05 15:45:34 +02:00
{ className: "h5-18_1nd defaultColor-1_ajX0 margin-reset bd-server-member-count" },
2018-03-29 09:56:07 +02:00
server.members,
" Members"
2018-01-09 04:24:00 +01:00
)
),
BDV2.react.createElement(
"div",
2018-05-05 15:45:34 +02:00
{ className: "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY directionRow-3v3tfG noWrap-3jynv6" },
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
"div",
2018-05-05 15:45:34 +02:00
{ className: "scrollerWrap-2lJEkd scrollerThemed-2oenus themeGhostHairline-DBD-2d scrollerFade-1Ijw5y bd-server-description-container"},
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
"div",
2018-05-05 15:45:34 +02:00
{ className: "scroller-2FKFPG scroller bd-server-description" },
2018-01-09 04:24:00 +01:00
server.description
)
)
),
BDV2.react.createElement(
"div",
2018-05-05 15:45:34 +02:00
{ className: "flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY directionRow-3v3tfG noWrap-3jynv6 bd-server-footer" },
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
"div",
2018-05-05 15:45:34 +02:00
{ className: "flexChild-faoVW3 bd-server-tags", style: { flex: "1 1 auto" } },
2018-01-09 04:24:00 +01:00
server.categories.join(', ')
),
this.state.joined && BDV2.react.createElement(
"button",
2018-05-05 15:45:34 +02:00
{ type: "button", className: "button-38aScr lookFilled-1Gx00P colorBrand-3pXr91 sizeMin-1mJd1x grow-q77ONN colorGreen-29iAKY", style: { minHeight: "12px", marginTop: "4px", backgroundColor: "#3ac15c" } },
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
"div",
{ className: "ui-button-contents" },
"Joined"
)
),
server.error && BDV2.react.createElement(
"button",
2018-05-05 15:45:34 +02:00
{ type: "button", className: "button-38aScr lookFilled-1Gx00P colorBrand-3pXr91 sizeMin-1mJd1x grow-q77ONN disabled-9aF2ug", style: { minHeight: "12px", marginTop: "4px", backgroundColor: "#c13a3a" } },
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
"div",
{ className: "ui-button-contents" },
"Error"
)
),
2018-03-29 09:56:07 +02:00
!server.error && !this.state.joined && BDV2.react.createElement(
2018-01-09 04:24:00 +01:00
"button",
2018-05-05 15:45:34 +02:00
{ type: "button", className: "button-38aScr lookFilled-1Gx00P colorBrand-3pXr91 sizeMin-1mJd1x grow-q77ONN", style: { minHeight: "12px", marginTop: "4px" }, onClick: () => {this.join();} },
2018-01-09 04:24:00 +01:00
BDV2.react.createElement(
"div",
{ className: "ui-button-contents" },
"Join"
)
)
)
)
2018-03-29 09:56:07 +02:00
// )
2018-01-09 04:24:00 +01:00
);
}
handleError() {
2018-03-29 09:56:07 +02:00
this.props.server.iconUrl = this.props.fallback;
2018-01-09 04:24:00 +01:00
this.setState({imageError: true});
}
join() {
2018-03-29 09:56:07 +02:00
this.props.join(this);
//this.setState({joined: true});
2018-01-09 04:24:00 +01:00
}
}
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);
2018-03-29 09:56:07 +02:00
this.connect = this.connect.bind(this);
2018-01-09 04:24:00 +01:00
this.GuildStore = BDV2.WebpackModules.findByUniqueProperties(["getGuilds"]);
this.AvatarDefaults = BDV2.WebpackModules.findByUniqueProperties(["getUserAvatarURL", "DEFAULT_AVATARS"]);
this.InviteActions = BDV2.WebpackModules.findByUniqueProperties(['acceptInvite']);
2018-03-29 09:56:07 +02:00
this.SortedGuildStore = BDV2.WebpackModules.findByUniqueProperties(['getSortedGuilds']);
2018-01-09 04:24:00 +01:00
}
componentDidMount() {
this.checkConnection();
2018-05-05 16:54:21 +02:00
mainCore.alert("Not Working", "Hi there,<br><br> While the public servers module was fixed on our end, DiscordServers.com is having issue with their sessions API that we need for this to work. So unfortunately until they fix that, the public servers module won't work :(")
2018-01-09 04:24:00 +01:00
}
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',
2018-03-29 09:56:07 +02:00
url: `${self.endPoint}${query}${query ? "&schema=new" : "?schema=new"}`,
2018-01-09 04:24:00 +01:00
success: data => {
let servers = data.results.reduce((arr, server) => {
server.joined = false;
arr.push(server);
// arr.push(<V2Components.ServerCard server={server} join={self.join}/>);
return arr;
}, []);
if (!clear) {
servers = self.state.servers.concat(servers);
} else {
//servers.unshift(self.bdServer);
}
2018-03-29 09:56:07 +02:00
let hasNext = true;
2018-01-09 04:24:00 +01:00
let end = data.size + data.from;
2018-03-29 09:56:07 +02:00
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]}`;
2018-01-09 04:24:00 +01:00
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) {
2018-02-28 08:25:06 +01:00
//console.log(self);
self.refs.sbv.refs.contentScroller.scrollTop = 0;
2018-01-09 04:24:00 +01:00
}
},
error: (jqXHR) => {
self.setState({
'loading': false,
'title': 'Failed to load servers. Check console for details'
});
}
});
}
2018-03-29 09:56:07 +02:00
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-id": this.state.connection.user.id,
"x-discord-token": this.state.connection.user.accessToken
},
crossDomain: true,
xhrFields: {
withCredentials: true
},
success: data => {
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);
let sub = window.location.hostname.split('.')[0];
let url = self.connectEndPoint + (sub === 'canary' || sub === 'ptb' ? `/${sub}` : '');
self.joinWindow.webContents.on('did-navigate', (event, url) => {
if (url != "https://discordservers.com/") 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
};
}
2018-01-09 04:24:00 +01:00
get bdServer() {
let server = {
"name": "BetterDiscord",
"online": "7500+",
"members": "20000+",
"categories": ["community", "programming", "support"],
"description": "Official BetterDiscord server for support etc",
"identifier": "86004744966914048",
2018-03-29 09:56:07 +02:00
"iconUrl": "https://cdn.discordapp.com/icons/86004744966914048/c8d49dc02248e1f55caeb897c3e1a26e.png",
2018-01-09 04:24:00 +01:00
"nativejoin": true,
"invite_code": "0Tmfo5ZbORCRqbAd",
"pinned": true
};
2018-03-29 09:56:07 +02:00
let guildList = this.SortedGuildStore.guildPositions;
2018-01-09 04:24:00 +01:00
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://join.discordservers.com';
}
get connectEndPoint() {
return 'https://join.discordservers.com/connect';
}
checkConnection() {
let self = this;
try {
$.ajax({
method: 'GET',
2018-03-29 09:56:07 +02:00
url: `${self.joinEndPoint}/session`,
headers: {
Accept: "application/json;",
"Content-Type": "application/json;"
},
crossDomain: true,
xhrFields: {
withCredentials: true
},
2018-01-09 04:24:00 +01:00
success: data => {
self.setState({
'selectedCategory': 0,
'connection': {
'state': 2,
'user': data
}
});
self.search("", true);
2018-03-29 09:56:07 +02:00
2018-01-09 04:24:00 +01:00
},
error: jqXHR => {
if (jqXHR.status === 403 || jqXHR.status === 404) {
//Not connected
self.setState({
'title': 'Not connected to discordservers.com!',
'loading': true,
'selectedCategory': -1,
'connection': {
'state': 1,
'user': null
}
});
return;
}
}
});
}
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),
2018-03-29 09:56:07 +02:00
this.footer,
this.connection
2018-01-09 04:24:00 +01:00
)
);
}
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", "Sports Games", "Puzzle Games", "Retro Games", "Party Games", "Tabletop Games", "Sandbox Games", "Simulation Games", "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;
2018-03-29 09:56:07 +02:00
let guildList = this.SortedGuildStore.guildPositions;
2018-01-09 04:24:00 +01:00
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: "content-column default" },
BDV2.react.createElement(V2Components.SettingsTitle, { text: self.state.title }),
self.bdServer,
self.state.servers.map((server, index) => {
2018-03-29 09:56:07 +02:00
return BDV2.react.createElement(V2Components.ServerCard, { key: server.identifier, server: server, join: self.join, guildList: guildList, fallback: defaultList[Math.floor(Math.random() * 5)] });
2018-01-09 04:24:00 +01:00
}),
self.state.next && BDV2.react.createElement(
"button",
{ type: "button", onClick: () => {
2018-03-29 09:56:07 +02:00
if (self.state.loading) return;self.setState({ 'loading': true }); self.search(self.state.next, false);
2018-01-09 04:24:00 +01:00
}, 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 })
)];
}
2018-03-29 09:56:07 +02:00
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: "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
)];
}
2018-01-09 04:24:00 +01:00
get footer() {
return BDV2.react.createElement(
"div",
{ className: "ui-tab-bar-header" },
BDV2.react.createElement(
"a",
{ href: "https://discordservers.com", target: "_blank" },
"Discordservers.com"
)
);
}
2018-03-29 09:56:07 +02:00
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"
)
)
)
);
}
2018-05-05 15:45:34 +02:00
}