From 5c1eae4c71075b0d537a87010f9ad22fd99953e3 Mon Sep 17 00:00:00 2001 From: Mirco Wittrien Date: Thu, 10 Sep 2020 23:22:07 +0200 Subject: [PATCH] Update 0BDFDB.plugin.js --- Library/0BDFDB.plugin.js | 7411 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 7134 insertions(+), 277 deletions(-) diff --git a/Library/0BDFDB.plugin.js b/Library/0BDFDB.plugin.js index 44b8bd5c5f..df4d8239cc 100644 --- a/Library/0BDFDB.plugin.js +++ b/Library/0BDFDB.plugin.js @@ -1,17 +1,39 @@ //META{"name":"BDFDB","authorId":"278543574059057154","invite":"Jx3TjNS","donate":"https://www.paypal.me/MircoWittrien","patreon":"https://www.patreon.com/MircoWittrien","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/0BDFDB.plugin.js"}*// -var BDFDB = (_ => { +module.exports = (_ => { + const config = { + name: "BDFDB", + author: "DevilBro", + version: "1.0.0", + description: "Gives other plugins utility functions." + }; + + const DiscordObjects = {}; + const LibraryRequires = {}; + const LibraryModules = {}; + const InternalComponents = {NativeSubComponents: {}, LibraryComponents: {}}; + const Cache = {data: {}, modules: {}}; + const myId = "278543574059057154", myGuildId = "410787888507256842"; + var settings = {}; if (window.BDFDB && window.BDFDB.PluginUtils && typeof window.BDFDB.PluginUtils.cleanUp == "function") window.BDFDB.PluginUtils.cleanUp(window.BDFDB); - const BDFDB = { - name: "BDFDB", - patchPriority: 0, + const BDFDB = Object.assign({ started: true - }; - const InternalBDFDB = Object.assign({}, BDFDB); + }, config); + const InternalBDFDB = Object.assign({}, BDFDB, { + patchPriority: 0, + defaults: { + settings: { + showToasts: {value:true, description:"Show Plugin start and stop Toasts"}, + showSupportBadges: {value:true, description:"Show little Badges for Users who support my Patreon"} + } + }, + }); + + const delayedLoads = [], delayedStarts = []; const Plugin = function(config) { return class Plugin { getName() {return config.name;} @@ -19,18 +41,23 @@ var BDFDB = (_ => { getVersion() {return config.version;} getDescription() {return config.description;} load() { - Object.assign(this, BDFDB.ObjectUtils.extract(config, "name", "author", "version", "description")); - BDFDB.PluginUtils.load(this, config); - if (typeof this.onLoad == "function") this.onLoad(); + if (window.BDFDB.loading) delayedLoads.push(this); + else { + Object.assign(this, BDFDB.ObjectUtils.extract(config, "name", "author", "version", "description", "changeLog", "patchedModules", "rawUrl")); + BDFDB.PluginUtils.load(this); + if (typeof this.onLoad == "function") this.onLoad(); + } } start() { - if (this.started) return; - - BDFDB.PluginUtils.init(this, config); - if (typeof this.onStart == "function") this.onStart(); - - this.started = true; - delete this.stopping; + if (window.BDFDB.loading) delayedStarts.push(this); + else { + if (this.started) return; + BDFDB.PluginUtils.init(this); + if (typeof this.onStart == "function") this.onStart(); + + this.started = true; + delete this.stopping; + } } stop() { if (this.stopping) return; @@ -38,71 +65,124 @@ var BDFDB = (_ => { BDFDB.TimeUtils.timeout(_ => {delete this.stopping;}); if (typeof this.onStop == "function") this.onStop(); - BDFDB.PluginUtils.clear(this, config); + BDFDB.PluginUtils.clear(this); delete this.started; } }; }; - - const updateTimeouts = [], plugins = []; + + BDFDB.LogUtils = {}; + BDFDB.LogUtils.log = function (string, name) { + console.log(`%c[${typeof name == "string" && name || "BDFDB"}]`, "color: #3a71c1; font-weight: 700;", (typeof string == "string" && string || "").trim()); + }; + BDFDB.LogUtils.warn = function (string, name) { + console.warn(`%c[${typeof name == "string" && name || "BDFDB"}]`, "color: #3a71c1; font-weight: 700;", (typeof string == "string" && string || "").trim()); + }; + BDFDB.LogUtils.error = function (string, name) { + console.error(`%c[${typeof name == "string" && name || "BDFDB"}]`, "color: #3a71c1; font-weight: 700;", "Fatal Error: " + (typeof string == "string" && string || "").trim()); + }; + + BDFDB.LogUtils.log("Loading library."); + + BDFDB.sameProto = function (a, b) { + if (a != null && typeof a == "object") return a.constructor && a.constructor.prototype && typeof a.constructor.prototype.isPrototypeOf == "function" && a.constructor.prototype.isPrototypeOf(b); + else return typeof a == typeof b; + }; + BDFDB.equals = function (mainA, mainB, sorted) { + let i = -1; + if (sorted === undefined || typeof sorted !== "boolean") sorted = false; + return equal(mainA, mainB); + function equal(a, b) { + i++; + let result = true; + if (i > 1000) result = null; + else { + if (typeof a !== typeof b) result = false; + else if (typeof a === "function") result = a.toString() == b.toString(); + else if (typeof a === "undefined") result = true; + else if (typeof a === "symbol") result = true; + else if (typeof a === "boolean") result = a == b; + else if (typeof a === "string") result = a == b; + else if (typeof a === "number") { + if (isNaN(a) || isNaN(b)) result = isNaN(a) == isNaN(b); + else result = a == b; + } + else if (!a && !b) result = true; + else if (!a || !b) result = false; + else if (typeof a === "object") { + let keysA = Object.getOwnPropertyNames(a); + let keysB = Object.getOwnPropertyNames(b); + if (keysA.length !== keysB.length) result = false; + else for (let j = 0; result === true && j < keysA.length; j++) { + if (sorted) result = equal(a[keysA[j]], b[keysB[j]]); + else result = equal(a[keysA[j]], b[keysA[j]]); + } + } + } + i--; + return result; + } + }; + + const updateTimeouts = [], componentPatchQueries = {}, startedPlugins = []; BDFDB.PluginUtils = {}; BDFDB.PluginUtils.buildPlugin = function (config) { return [Plugin(config), Object.assign({}, BDFDB)]; }; - BDFDB.PluginUtils.load = function (plugin, config) { - if (!updateTimeouts.includes(config.name)) { - updateTimeouts.push(config.name); - let url = ["ImageZoom", "ImageGallery", "ReverseImageSearch", "ShowImageDetails"].includes(config.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/ImageUtilities/ImageUtilities.plugin.js" : ["BetterFriendCount"].includes(config.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BetterFriendList/BetterFriendList.plugin.js" : (config.rawUrl ||`https://mwittrien.github.io/BetterDiscordAddons/Plugins/${config.name}/${config.name}.plugin.js`); - BDFDB.PluginUtils.checkUpdate(config.name, url); + BDFDB.PluginUtils.load = function (plugin) { + if (!updateTimeouts.includes(plugin.name)) { + updateTimeouts.push(plugin.name); + let url = ["ImageZoom", "ImageGallery", "ReverseImageSearch", "ShowImageDetails"].includes(plugin.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/ImageUtilities/ImageUtilities.plugin.js" : ["BetterFriendCount"].includes(plugin.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BetterFriendList/BetterFriendList.plugin.js" : (plugin.rawUrl ||`https://mwittrien.github.io/BetterDiscordAddons/Plugins/${plugin.name}/${plugin.name}.plugin.js`); - if (!window.PluginUpdates || typeof window.PluginUpdates !== "object") window.PluginUpdates = {plugins: {} }; - window.PluginUpdates.plugins[url] = {name: config.name, raw: url, version: config.version}; + if (!window.PluginUpdates || typeof window.PluginUpdates !== "object") window.PluginUpdates = {plugins:{}}; + window.PluginUpdates.plugins[url] = {name: plugin.name, raw: url, version: plugin.version}; + + BDFDB.PluginUtils.checkUpdate(plugin.name, url); + if (typeof window.PluginUpdates.interval === "undefined") window.PluginUpdates.interval = BDFDB.TimeUtils.interval(_ => { BDFDB.PluginUtils.checkAllUpdates(); }, 1000*60*60*2); - BDFDB.TimeUtils.timeout(_ => {BDFDB.ArrayUtils.remove(updateTimeouts, config.name, true);}, 30000); + + BDFDB.TimeUtils.timeout(_ => {BDFDB.ArrayUtils.remove(updateTimeouts, plugin.name, true);}, 30000); } }; - BDFDB.PluginUtils.init = BDFDB.loadMessage = function (plugin, config) { - BDFDB.PluginUtils.load(plugin, config); - if (!plugins.includes(plugin)) plugins.push(plugin); + BDFDB.PluginUtils.init = function (plugin) { + BDFDB.PluginUtils.load(plugin); + if (!startedPlugins.includes(plugin.name)) startedPlugins.push(plugin.name); - let startMsg = BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_started", "v" + config.version); - BDFDB.LogUtils.log(startMsg, config.name); - if (settings.showToasts && !BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts)) BDFDB.NotificationUtils.toast(`${config.name} ${startMsg}`, {nopointer: true}); + let startMsg = BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_started", "v" + plugin.version); + BDFDB.LogUtils.log(startMsg, plugin.name); + if (settings.showToasts && !BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts)) BDFDB.NotificationUtils.toast(`${plugin.name} ${startMsg}`, {nopointer: true}); - if (typeof plugin.initConstructor === "function") BDFDB.TimeUtils.suppress(plugin.initConstructor.bind(plugin), "Could not initiate constructor!", config.name)(); - if (typeof plugin.css === "string") BDFDB.DOMUtils.appendLocalStyle(config.name, plugin.css); + if (typeof plugin.initConstructor === "function") BDFDB.TimeUtils.suppress(plugin.initConstructor.bind(plugin), "Could not initiate constructor!", plugin.name)(); + if (typeof plugin.css === "string") BDFDB.DOMUtils.appendLocalStyle(plugin.name, plugin.css); InternalBDFDB.patchPlugin(plugin); - InternalBDFDB.addSpecialListeners(plugin); + addSpecialListeners(plugin); BDFDB.PluginUtils.translate(plugin); BDFDB.PluginUtils.checkChangeLog(plugin); }; - BDFDB.PluginUtils.clear = BDFDB.unloadMessage = function (plugin, config) { - InternalBDFDB.clearStartTimeout(plugin); + BDFDB.PluginUtils.clear = function (plugin) { + let stopMsg = BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_stopped", "v" + plugin.version); + BDFDB.LogUtils.log(stopMsg, plugin.name); + if (settings.showToasts && !BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts)) BDFDB.NotificationUtils.toast(`${plugin.name} ${stopMsg}`, {nopointer: true}); - let stopMsg = BDFDB.LanguageUtils.LibraryStringsFormat("toast_plugin_stopped", "v" + config.version); - BDFDB.LogUtils.log(stopMsg, config.name); - if (settings.showToasts && !BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts)) BDFDB.NotificationUtils.toast(`${config.name} ${stopMsg}`, {nopointer: true}); - - let url = ["ImageZoom", "ImageGallery", "ReverseImageSearch", "ShowImageDetails"].includes(config.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/ImageUtilities/ImageUtilities.plugin.js" : ["BetterFriendCount"].includes(config.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BetterFriendList/BetterFriendList.plugin.js" : (config.rawUrl ||`https://mwittrien.github.io/BetterDiscordAddons/Plugins/${config.name}/${config.name}.plugin.js`); - - if (typeof plugin.css === "string") BDFDB.DOMUtils.removeLocalStyle(plugin.name); + let url = ["ImageZoom", "ImageGallery", "ReverseImageSearch", "ShowImageDetails"].includes(plugin.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/ImageUtilities/ImageUtilities.plugin.js" : ["BetterFriendCount"].includes(plugin.name) ? "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BetterFriendList/BetterFriendList.plugin.js" : (plugin.rawUrl ||`https://mwittrien.github.io/BetterDiscordAddons/Plugins/${plugin.name}/${plugin.name}.plugin.js`); BDFDB.PluginUtils.cleanUp(plugin); - for (let type in BDFDB.InternalData.componentPatchQueries) BDFDB.ArrayUtils.remove(BDFDB.InternalData.componentPatchQueries[type].query, plugin, true); + for (let type in componentPatchQueries) BDFDB.ArrayUtils.remove(componentPatchQueries[type].query, plugin, true); - for (let modal of document.querySelectorAll(`.${config.name}-modal, .${config.name.toLowerCase()}-modal, .${config.name}-settingsmodal, .${plugin.name.toLowerCase()}-settingsmodal`)) { + for (let modal of document.querySelectorAll(`.${plugin.name}-modal, .${plugin.name.toLowerCase()}-modal, .${plugin.name}-settingsmodal, .${plugin.name.toLowerCase()}-settingsmodal`)) { let closeButton = modal.querySelector(BDFDB.dotCN.modalclose); if (closeButton) closeButton.click(); } - delete BDFDB.DataUtils.cached[config.name] + BDFDB.ArrayUtils.remove(startedPlugins, plugin.name, true); + delete Cache.data[plugin.name] delete window.PluginUpdates.plugins[url]; }; BDFDB.PluginUtils.translate = function (plugin) { @@ -124,20 +204,24 @@ var BDFDB = (_ => { } }; BDFDB.PluginUtils.cleanUp = function (plugin) { - return; if (!BDFDB.ObjectUtils.is(plugin)) return; - if (plugin.name == "BDFDB") { - plugin = BDFDB; + if (plugin == BDFDB) { + delete window.BDFDB.loaded; + BDFDB.TimeUtils.interval((interval, count) => { + if (count > 60 || window.BDFDB.loaded) BDFDB.TimeUtils.clear(interval); + if (window.BDFDB.loaded) for (let pluginName of startedPlugins) BDFDB.BDUtils.reloadPlugin(pluginName); + }, 1000); } + BDFDB.DOMUtils.removeLocalStyle(plugin.name); BDFDB.ListenerUtils.remove(plugin); BDFDB.StoreChangeUtils.remove(plugin); BDFDB.ObserverUtils.disconnect(plugin); - BDFDB.ModuleUtils.unpatch(plugin); + BDFDB.PatchUtils.unpatch(plugin); BDFDB.WindowUtils.closeAll(plugin); BDFDB.WindowUtils.removeListener(plugin); }; BDFDB.PluginUtils.checkUpdate = function (pluginName, url) { - if (pluginName && url) return new Promise(callback => { + if (pluginName && url && window.PluginUpdates.plugins[url]) return new Promise(callback => { LibraryRequires.request(url, (error, response, body) => { if (error) return callback(null); let newName = (body.match(/"name"\s*:\s*"([^"]+)"/) || [])[1] || pluginName; @@ -161,7 +245,7 @@ var BDFDB = (_ => { } }); }); - return new Promise(_ => {callback(null);}); + return new Promise(callback => {callback(null);}); }; BDFDB.PluginUtils.checkAllUpdates = function () { return new Promise(callback => { @@ -251,7 +335,6 @@ var BDFDB = (_ => { BDFDB.LogUtils.warn("Unable to get update for " + pluginName); } else { - BDFDB.InternalData.creationTime = 0; let wasEnabled = BDFDB.BDUtils.isPluginEnabled(pluginName); let newName = (body.match(/"name"\s*:\s*"([^"]+)"/) || [])[1] || pluginName; let newVersion = body.match(/['"][0-9]+\.[0-9]+\.[0-9]+['"]/i).toString().replace(/['"]/g, ""); @@ -281,28 +364,28 @@ var BDFDB = (_ => { }); }; BDFDB.PluginUtils.checkChangeLog = function (plugin) { - if (!BDFDB.ObjectUtils.is(plugin) || !plugin.changelog) return; - let changeLog = BDFDB.DataUtils.load(plugin, "changelog"); - if (!changeLog.currentversion || BDFDB.NumberUtils.compareVersions(plugin.version, changeLog.currentversion)) { - changeLog.currentversion = plugin.version; - BDFDB.DataUtils.save(changeLog, plugin, "changelog"); + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(plugin.changeLog)) return; + let changeLog = BDFDB.DataUtils.load(plugin, "changeLog"); + if (!changeLog.version || BDFDB.NumberUtils.compareVersions(plugin.version, changeLog.version)) { + changeLog.version = plugin.version; + BDFDB.DataUtils.save(changeLog, plugin, "changeLog"); BDFDB.PluginUtils.openChangeLog(plugin); } }; BDFDB.PluginUtils.openChangeLog = function (plugin) { - if (!BDFDB.ObjectUtils.is(plugin) || !plugin.changelog) return; + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(plugin.changeLog)) return; let changeLogHTML = "", headers = { added: "New Features", fixed: "Bug Fixes", improved: "Improvements", progress: "Progress" }; - for (let type in plugin.changelog) { + for (let type in plugin.changeLog) { type = type.toLowerCase(); let className = BDFDB.disCN["changelog" + type]; if (className) { changeLogHTML += `

${headers[type]}

` } } @@ -339,35 +422,6 @@ var BDFDB = (_ => { onClick: _ => {BDFDB.PluginUtils.openChangeLog(plugin);} }) }) - }), - plugin != BDFDB && !plugin.noLibrary && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Button, { - size: InternalComponents.LibraryComponents.Button.Sizes.MIN, - children: BDFDB.LanguageUtils.LibraryStrings.library_settings, - onClick: event => { - let wrapper = BDFDB.DOMUtils.getParent(BDFDB.dotCN._repocard, event.currentTarget); - if (wrapper) { - let settingsPanel = InternalBDFDB.createLibrarySettings(); - if (settingsPanel) { - let savedChildren = []; - while (wrapper.childElementCount) { - savedChildren.push(wrapper.firstChild); - wrapper.firstChild.remove(); - } - let closeButton = BDFDB.DOMUtils.create(`
`); - wrapper.appendChild(closeButton); - closeButton.addEventListener("click", _ => { - while (wrapper.childElementCount) wrapper.firstChild.remove(); - while (savedChildren.length) wrapper.appendChild(savedChildren.shift()); - let settings = wrapper.querySelector(BDFDB.dotCN._reposettings); - if (settings) { - while (settings.childElementCount) settings.firstChild.remove(); - settings.appendChild(plugin.getSettingsPanel()); - } - }); - wrapper.appendChild(settingsPanel); - } - } - } }) ], children: children @@ -379,32 +433,7 @@ var BDFDB = (_ => { settingsPanel.parentElement.appendChild(plugin.getSettingsPanel(...args)); settingsPanel.remove(); }; - InternalBDFDB.createLibrarySettings = function () { - if (!window.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded) return; - let settingsPanel, settingsItems = []; - - let bdToastSetting = BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts); - for (let key in settings) settingsItems.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsSaveItem, { - className: BDFDB.disCN.marginbottom8, - type: "Switch", - plugin: InternalBDFDB, - disabled: key == "showToasts" && bdToastSetting, - keys: ["settings", key], - label: InternalBDFDB.defaults.settings[key].description, - note: key == "showToasts" && bdToastSetting && "Disable BBDs general 'Show Toast' setting before disabling this", - dividerbottom: true, - value: settings[key] || key == "showToasts" && bdToastSetting - })); - - return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(BDFDB, settingsItems); - }; - InternalBDFDB.clearStartTimeout = function (plugin) { - if (!BDFDB.ObjectUtils.is(plugin)) return; - BDFDB.TimeUtils.clear(plugin.startTimeout, plugin.libLoadTimeout); - delete plugin.startTimeout; - delete plugin.libLoadTimeout; - }; - InternalBDFDB.addSpecialListeners = function (plugin) { + const addSpecialListeners = function (plugin) { plugin = plugin == BDFDB && InternalBDFDB || plugin; if (BDFDB.ObjectUtils.is(plugin)) { if (typeof plugin.onSwitch === "function") { @@ -426,175 +455,7003 @@ var BDFDB = (_ => { } }; - BDFDB.ObjectUtils = {}; - BDFDB.ObjectUtils.is = function (obj) { - return obj && Object.prototype.isPrototypeOf(obj) && !Array.prototype.isPrototypeOf(obj); - }; - BDFDB.ObjectUtils.extract = function (obj, ...keys) { - let newObj = {}; - if (BDFDB.ObjectUtils.is(obj)) for (let key of keys.flat(10).filter(n => n)) if (obj[key]) newObj[key] = obj[key]; - return newObj; - }; - BDFDB.ObjectUtils.exclude = function (obj, ...keys) { - let newObj = Object.assign({}, obj); - BDFDB.ObjectUtils.delete(newObj, ...keys) - return newObj; - }; - BDFDB.ObjectUtils.delete = function (obj, ...keys) { - if (BDFDB.ObjectUtils.is(obj)) for (let key of keys.flat(10).filter(n => n)) delete obj[key]; - }; - BDFDB.ObjectUtils.sort = function (obj, sort, except) { - if (!BDFDB.ObjectUtils.is(obj)) return {}; - let newObj = {}; - if (sort === undefined || !sort) for (let key of Object.keys(obj).sort()) newObj[key] = obj[key]; - else { - let values = []; - for (let key in obj) values.push(obj[key]); - values = BDFDB.ArrayUtils.keySort(values, sort, except); - for (let value of values) for (let key in obj) if (BDFDB.equals(value, obj[key])) { - newObj[key] = value; - break; - } - } - return newObj; - }; - BDFDB.ObjectUtils.reverse = function (obj, sort) { - if (!BDFDB.ObjectUtils.is(obj)) return {}; - let newObj = {}; - for (let key of (sort === undefined || !sort) ? Object.keys(obj).reverse() : Object.keys(obj).sort().reverse()) newObj[key] = obj[key]; - return newObj; - }; - BDFDB.ObjectUtils.filter = function (obj, filter, byKey = false) { - if (!BDFDB.ObjectUtils.is(obj)) return {}; - if (typeof filter != "function") return obj; - return Object.keys(obj).filter(key => filter(byKey ? key : obj[key])).reduce((newObj, key) => (newObj[key] = obj[key], newObj), {}); - }; - BDFDB.ObjectUtils.push = function (obj, value) { - if (BDFDB.ObjectUtils.is(obj)) obj[Object.keys(obj).length] = value; - }; - BDFDB.ObjectUtils.pop = function (obj, value) { - if (BDFDB.ObjectUtils.is(obj)) { - let keys = Object.keys(obj); - if (!keys.length) return; - let value = obj[keys[keys.length-1]]; - delete obj[keys[keys.length-1]]; - return value; - } - }; - BDFDB.ObjectUtils.map = function (obj, mapfunc) { - if (!BDFDB.ObjectUtils.is(obj)) return {}; - if (typeof mapfunc != "string" && typeof mapfunc != "function") return obj; - let newObj = {}; - for (let key in obj) if (BDFDB.ObjectUtils.is(obj[key])) newObj[key] = typeof mapfunc == "string" ? obj[key][mapfunc] : mapfunc(obj[key], key); - return newObj; - }; - BDFDB.ObjectUtils.toArray = function (obj) { - if (!BDFDB.ObjectUtils.is(obj)) return []; - return Object.entries(obj).map(n => n[1]); - }; - BDFDB.ObjectUtils.deepAssign = function (obj, ...objs) { - if (!objs.length) return obj; - let nextObj = objs.shift(); - if (BDFDB.ObjectUtils.is(obj) && BDFDB.ObjectUtils.is(nextObj)) { - for (let key in nextObj) { - if (BDFDB.ObjectUtils.is(nextObj[key])) { - if (!obj[key]) Object.assign(obj, {[key]:{}}); - BDFDB.ObjectUtils.deepAssign(obj[key], nextObj[key]); - } - else Object.assign(obj, {[key]:nextObj[key]}); - } - } - return BDFDB.ObjectUtils.deepAssign(obj, ...objs); - }; - BDFDB.ObjectUtils.isEmpty = function (obj) { - return !BDFDB.ObjectUtils.is(obj) || Object.getOwnPropertyNames(obj).length == 0; - }; - - BDFDB.ArrayUtils = {}; - BDFDB.ArrayUtils.is = function (array) { - return array && Array.isArray(array); - }; - BDFDB.ArrayUtils.sum = function (array) { - return Array.isArray(array) ? array.reduce((total, num) => total + Math.round(num), 0) : 0; - }; - BDFDB.ArrayUtils.keySort = function (array, key, except) { - if (!BDFDB.ArrayUtils.is(array)) return []; - if (key == null) return array; - if (except === undefined) except = null; - return array.sort((x, y) => { - let xValue = x[key], yValue = y[key]; - if (xValue !== except) return xValue < yValue ? -1 : xValue > yValue ? 1 : 0; - }); - }; - BDFDB.ArrayUtils.numSort = function (array) { - return array.sort((x, y) => (x < y ? -1 : x > y ? 1 : 0)); - }; - BDFDB.ArrayUtils.includes = function (array, ...values) { - if (!BDFDB.ArrayUtils.is(array)) return null; - if (!array.length) return false; - let all = values.pop(); - if (typeof all != "boolean") { - values.push(all); - all = true; - } - if (!values.length) return false; - let contained = undefined; - for (let v of values) { - if (contained === undefined) contained = all; - if (all && !array.includes(v)) contained = false; - if (!all && array.includes(v)) contained = true; - } - return contained; - }; - BDFDB.ArrayUtils.remove = function (array, value, all = false) { - if (!BDFDB.ArrayUtils.is(array)) return []; - if (!array.includes(value)) return array; - if (!all) array.splice(array.indexOf(value), 1); - else while (array.indexOf(value) > -1) array.splice(array.indexOf(value), 1); - return array; - }; - BDFDB.ArrayUtils.getAllIndexes = function (array, value) { - if (!BDFDB.ArrayUtils.is(array) && typeof array != "string") return []; - var indexes = [], index = -1; - while ((index = array.indexOf(value, index + 1)) !== -1) indexes.push(index); - return indexes; - }; - BDFDB.ArrayUtils.removeCopies = function (array) { - if (!BDFDB.ArrayUtils.is(array)) return []; - return [...new Set(array)]; - }; - - let pluginQueue = window.BDFDB && BDFDB.ArrayUtils.is(window.BDFDB.pluginQueue) ? window.BDFDB.pluginQueue : null; - - window.BDFDB = { - name: "BDFDB", - loaded: true, + window.BDFDB = Object.assign({ + started: true, + loading: true, PluginUtils: { buildPlugin: BDFDB.PluginUtils.buildPlugin, cleanUp: BDFDB.PluginUtils.cleanUp } - }; + }, config, window.BDFDB); - if (pluginQueue) for (let pluginName of pluginQueue) BdApi.Plugins.reload(pluginName); + require("request").get("https://mwittrien.github.io/BetterDiscordAddons/Library/_res/BDFDB.data.json", (error, response, body) => { + const InternalData = JSON.parse(body); - return class BDFDB { - getName () {return "BDFDB";} + BDFDB.ObserverUtils = {}; + BDFDB.ObserverUtils.connect = function (plugin, eleOrSelec, observer, config = {childList: true}) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !eleOrSelec || !observer) return; + if (BDFDB.ObjectUtils.isEmpty(plugin.observers)) plugin.observers = {}; + if (!BDFDB.ArrayUtils.is(plugin.observers[observer.name])) plugin.observers[observer.name] = []; + if (!observer.multi) for (let subinstance of plugin.observers[observer.name]) subinstance.disconnect(); + if (observer.instance) plugin.observers[observer.name].push(observer.instance); + let instance = plugin.observers[observer.name][plugin.observers[observer.name].length - 1]; + if (instance) { + let node = Node.prototype.isPrototypeOf(eleOrSelec) ? eleOrSelec : typeof eleOrSelec === "string" ? document.querySelector(eleOrSelec) : null; + if (node) instance.observe(node, config); + } + }; + BDFDB.ObserverUtils.disconnect = function (plugin, observer) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (BDFDB.ObjectUtils.is(plugin) && !BDFDB.ObjectUtils.isEmpty(plugin.observers)) { + let observername = typeof observer == "string" ? observer : (BDFDB.ObjectUtils.is(observer) ? observer.name : null); + if (!observername) { + for (let observer in plugin.observers) for (let instance of plugin.observers[observer]) instance.disconnect(); + delete plugin.observers; + } + else if (!BDFDB.ArrayUtils.is(plugin.observers[observername])) { + for (let instance of plugin.observers[observername]) instance.disconnect(); + delete plugin.observers[observername]; + } + } + }; - getAuthor () {return "DevilBro";} + BDFDB.StoreChangeUtils = {}; + BDFDB.StoreChangeUtils.add = function (plugin, store, callback) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(store) || typeof store.addChangeListener != "function" || typeof callback != "function") return; + BDFDB.ListenerUtils.remove(plugin, store, callback); + if (!BDFDB.ArrayUtils.is(plugin.changeListeners)) plugin.changeListeners = []; + plugin.changeListeners.push({store, callback}); + store.addChangeListener(callback); + }; + BDFDB.StoreChangeUtils.remove = function (plugin, store, callback) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ArrayUtils.is(plugin.changeListeners)) return; + if (!store) { + while (plugin.changeListeners.length) { + let listener = plugin.changeListeners.pop(); + listener.store.removeChangeListener(listener.callback); + } + } + else if (BDFDB.ObjectUtils.is(store) && typeof store.addChangeListener == "function") { + if (!callback) { + for (let listener of plugin.changeListeners) { + let removedListeners = []; + if (listener.store == store) { + listener.store.removeChangeListener(listener.callback); + removedListeners.push(listener); + } + if (removedListeners.length) plugin.changeListeners = plugin.changeListeners.filter(listener => !removedListeners.includes(listener)); + } + } + else if (typeof callback == "function") { + store.removeChangeListener(callback); + plugin.changeListeners = plugin.changeListeners.filter(listener => listener.store == store && listener.callback == callback); + } + } + }; - getVersion () {return "1.0.0";} + var pressedKeys = [], mousePosition; + BDFDB.ListenerUtils = {}; + BDFDB.ListenerUtils.isPressed = function (key) { + return pressedKeys.includes(key); + }; + BDFDB.ListenerUtils.getPosition = function (key) { + return mousePosition; + }; + BDFDB.ListenerUtils.add = function (plugin, ele, actions, selectorOrCallback, callbackOrNothing) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || (!Node.prototype.isPrototypeOf(ele) && ele !== window) || !actions) return; + let callbackIs4th = typeof selectorOrCallback == "function"; + let selector = callbackIs4th ? undefined : selectorOrCallback; + let callback = callbackIs4th ? selectorOrCallback : callbackOrNothing; + if (typeof callback != "function") return; + BDFDB.ListenerUtils.remove(plugin, ele, actions, selector); + for (let action of actions.split(" ")) { + action = action.split("."); + let eventName = action.shift().toLowerCase(); + if (!eventName) return; + let origEventName = eventName; + eventName = eventName == "mouseenter" || eventName == "mouseleave" ? "mouseover" : eventName; + let namespace = (action.join(".") || "") + plugin.name; + if (!BDFDB.ArrayUtils.is(plugin.eventListeners)) plugin.eventListeners = []; + let eventCallback = null; + if (selector) { + if (origEventName == "mouseenter" || origEventName == "mouseleave") { + eventCallback = e => { + for (let child of e.path) if (typeof child.matches == "function" && child.matches(selector) && !child[namespace + "BDFDB" + origEventName]) { + child[namespace + "BDFDB" + origEventName] = true; + if (origEventName == "mouseenter") callback(BDFDB.ListenerUtils.copyEvent(e, child)); + let mouseout = e2 => { + if (e2.target.contains(child) || e2.target == child || !child.contains(e2.target)) { + if (origEventName == "mouseleave") callback(BDFDB.ListenerUtils.copyEvent(e, child)); + delete child[namespace + "BDFDB" + origEventName]; + document.removeEventListener("mouseout", mouseout); + } + }; + document.addEventListener("mouseout", mouseout); + break; + } + }; + } + else { + eventCallback = e => { + for (let child of e.path) if (typeof child.matches == "function" && child.matches(selector)) { + callback(BDFDB.ListenerUtils.copyEvent(e, child)); + break; + } + }; + } + } + else eventCallback = e => {callback(BDFDB.ListenerUtils.copyEvent(e, ele));}; - getDescription () {return "Gives other plugins utility functions.";} + plugin.eventListeners.push({ele, eventName, origEventName, namespace, selector, eventCallback}); + ele.addEventListener(eventName, eventCallback, true); + } + }; + BDFDB.ListenerUtils.remove = function (plugin, ele, actions = "", selector) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ArrayUtils.is(plugin.eventListeners)) return; + if (!ele) { + while (plugin.eventListeners.length) { + let listener = plugin.eventListeners.pop(); + listener.ele.removeEventListener(listener.eventName, listener.eventCallback, true); + } + } + else if (Node.prototype.isPrototypeOf(ele) || ele === window) { + for (let action of actions.split(" ")) { + action = action.split("."); + let eventName = action.shift().toLowerCase(); + let namespace = (action.join(".") || "") + plugin.name; + for (let listener of plugin.eventListeners) { + let removedListeners = []; + if (listener.ele == ele && (!eventName || listener.origEventName == eventName) && listener.namespace == namespace && (selector === undefined || listener.selector == selector)) { + listener.ele.removeEventListener(listener.eventName, listener.eventCallback, true); + removedListeners.push(listener); + } + if (removedListeners.length) plugin.eventListeners = plugin.eventListeners.filter(listener => !removedListeners.includes(listener)); + } + } + } + }; + BDFDB.ListenerUtils.multiAdd = function (node, actions, callback) { + if (!Node.prototype.isPrototypeOf(node) || !actions || typeof callback != "function") return; + for (let action of actions.trim().split(" ").filter(n => n)) node.addEventListener(action, callback, true); + }; + BDFDB.ListenerUtils.multiRemove = function (node, actions, callback) { + if (!Node.prototype.isPrototypeOf(node) || !actions || typeof callback != "function") return; + for (let action of actions.trim().split(" ").filter(n => n)) node.removeEventListener(action, callback, true); + }; + BDFDB.ListenerUtils.addToChildren = function (node, actions, selector, callback) { + if (!Node.prototype.isPrototypeOf(node) || !actions || !selector || !selector.trim() || typeof callback != "function") return; + for (let action of actions.trim().split(" ").filter(n => n)) { + let eventCallback = callback; + if (action == "mouseenter" || action == "mouseleave") eventCallback = e => {if (e.target.matches(selector)) callback(e);}; + node.querySelectorAll(selector.trim()).forEach(child => {child.addEventListener(action, eventCallback, true);}); + } + }; + BDFDB.ListenerUtils.copyEvent = function (e, ele) { + if (!e || !e.constructor || !e.type) return e; + let eCopy = new e.constructor(e.type, e); + Object.defineProperty(eCopy, "originalEvent", {value: e}); + Object.defineProperty(eCopy, "which", {value: e.which}); + Object.defineProperty(eCopy, "keyCode", {value: e.keyCode}); + Object.defineProperty(eCopy, "path", {value: e.path}); + Object.defineProperty(eCopy, "relatedTarget", {value: e.relatedTarget}); + Object.defineProperty(eCopy, "srcElement", {value: e.srcElement}); + Object.defineProperty(eCopy, "target", {value: e.target}); + Object.defineProperty(eCopy, "toElement", {value: e.toElement}); + if (ele) Object.defineProperty(eCopy, "currentTarget", {value: ele}); + return eCopy; + }; + BDFDB.ListenerUtils.stopEvent = function (e) { + if (BDFDB.ObjectUtils.is(e)) { + if (typeof e.preventDefault == "function") e.preventDefault(); + if (typeof e.stopPropagation == "function") e.stopPropagation(); + if (typeof e.stopImmediatePropagation == "function") e.stopImmediatePropagation(); + if (BDFDB.ObjectUtils.is(e.originalEvent)) { + if (typeof e.originalEvent.preventDefault == "function") e.originalEvent.preventDefault(); + if (typeof e.originalEvent.stopPropagation == "function") e.originalEvent.stopPropagation(); + if (typeof e.originalEvent.stopImmediatePropagation == "function") e.originalEvent.stopImmediatePropagation(); + } + } + }; + + var NotificationBars = [], DesktopNotificationQueue = {queue:[], running:false}; + BDFDB.NotificationUtils = {}; + BDFDB.NotificationUtils.toast = function (text, options = {}) { + let toasts = document.querySelector(".toasts, .bd-toasts"); + if (!toasts) { + let channels = document.querySelector(BDFDB.dotCN.channels + " + div"); + let channelRects = channels ? BDFDB.DOMUtils.getRects(channels) : null; + let members = channels ? channels.querySelector(BDFDB.dotCN.memberswrap) : null; + let left = channelRects ? channelRects.left : 310; + let width = channelRects ? (members ? channelRects.width - BDFDB.DOMUtils.getRects(members).width : channelRects.width) : window.outerWidth - 0; + let form = channels ? channels.querySelector("form") : null; + let bottom = form ? BDFDB.DOMUtils.getRects(form).height : 80; + toasts = BDFDB.DOMUtils.create(`
`); + (document.querySelector(BDFDB.dotCN.app) || document.body).appendChild(toasts); + } + const {type = "", icon = true, timeout = 3000, html = false, selector = "", nopointer = false, color = ""} = options; + let toast = BDFDB.DOMUtils.create(`
${html === true ? text : BDFDB.StringUtils.htmlEscape(text)}
`); + if (type) { + BDFDB.DOMUtils.addClass(toast, "toast-" + type); + if (icon) BDFDB.DOMUtils.addClass(toast, "icon"); + } + else if (color) { + let rgbcolor = BDFDB.ColorUtils.convert(color, "RGB"); + if (rgbcolor) toast.style.setProperty("background-color", rgbcolor); + } + BDFDB.DOMUtils.addClass(toast, selector); + toasts.appendChild(toast); + toast.close = _ => { + if (document.contains(toast)) { + BDFDB.DOMUtils.addClass(toast, "closing"); + toast.style.setProperty("pointer-events", "none", "important"); + BDFDB.TimeUtils.timeout(_ => { + toast.remove(); + if (!toasts.querySelectorAll(".toast, .bd-toast").length) toasts.remove(); + }, 3000); + } + }; + if (nopointer) toast.style.setProperty("pointer-events", "none", "important"); + else toast.addEventListener("click", toast.close); + BDFDB.TimeUtils.timeout(_ => {toast.close();}, timeout > 0 ? timeout : 600000); + return toast; + }; + BDFDB.NotificationUtils.desktop = function (parsedcontent, parsedoptions = {}) { + const queue = _ => { + DesktopNotificationQueue.queue.push({parsedcontent, parsedoptions}); + runqueue(); + }; + const runqueue = _ => { + if (!DesktopNotificationQueue.running) { + let notification = DesktopNotificationQueue.queue.shift(); + if (notification) notify(notification.parsedcontent, notification.parsedoptions); + } + }; + const notify = (content, options) => { + DesktopNotificationQueue.running = true; + let muted = options.silent; + options.silent = options.silent || options.sound ? true : false; + let notification = new Notification(content, options); + let audio = new Audio(); + let timeout = BDFDB.TimeUtils.timeout(_ => {close();}, options.timeout ? options.timeout : 3000); + if (typeof options.click == "function") notification.onclick = _ => { + BDFDB.TimeUtils.clear(timeout); + close(); + options.click(); + }; + if (!muted && options.sound) { + audio.src = options.sound; + audio.play(); + } + const close = _ => { + audio.pause(); + notification.close(); + DesktopNotificationQueue.running = false; + BDFDB.TimeUtils.timeout(_ => {runqueue();}, 1000); + }; + }; + if (!("Notification" in window)) {} + else if (Notification.permission === "granted") queue(); + else if (Notification.permission !== "denied") Notification.requestPermission(function (response) {if (response === "granted") queue();}); + }; + BDFDB.NotificationUtils.notice = function (text, options = {}) { + if (!text) return; + let layers = document.querySelector(BDFDB.dotCN.layers); + if (!layers) return; + let id = BDFDB.NumberUtils.generateId(NotificationBars); + let notice = BDFDB.DOMUtils.create(`
`); + layers.parentElement.insertBefore(notice, layers); + let noticeMessage = notice.querySelector(".notice-message"); + if (options.platform) for (let platform of options.platform.split(" ")) if (DiscordClasses["noticeicon" + platform]) { + let icon = BDFDB.DOMUtils.create(``); + BDFDB.DOMUtils.addClass(icon, BDFDB.disCN.noticeplatformicon); + BDFDB.DOMUtils.removeClass(icon, BDFDB.disCN.noticeicon); + notice.insertBefore(icon, noticeMessage); + } + if (options.customicon) { + let iconinner = BDFDB.DOMUtils.create(options.customicon) + let icon = BDFDB.DOMUtils.create(``); + if (iconinner.tagName == "span" && !iconinner.firstElementChild) icon.style.setProperty("background", `url(${options.customicon}) center/cover no-repeat`); + else icon.appendChild(iconinner); + BDFDB.DOMUtils.addClass(icon, BDFDB.disCN.noticeplatformicon); + BDFDB.DOMUtils.removeClass(icon, BDFDB.disCN.noticeicon); + notice.insertBefore(icon, noticeMessage); + } + if (options.btn || options.button) notice.appendChild(BDFDB.DOMUtils.create(``)); + if (options.id) notice.id = options.id.split(" ").join(""); + if (options.selector) BDFDB.DOMUtils.addClass(notice, options.selector); + if (options.css) BDFDB.DOMUtils.appendLocalStyle("BDFDBcustomNotificationBar" + id, options.css); + if (options.style) notice.style = options.style; + if (options.html === true) noticeMessage.innerHTML = text; + else { + let link = document.createElement("a"); + let newText = []; + for (let word of text.split(" ")) { + let encodedWord = BDFDB.StringUtils.htmlEscape(word); + link.href = word; + newText.push(link.host && link.host !== window.location.host ? `` : encodedWord); + } + noticeMessage.innerHTML = newText.join(" "); + } + let type = null; + if (options.type && !document.querySelector(BDFDB.dotCNS.chatbase + BDFDB.dotCN.noticestreamer)) { + if (type = BDFDB.disCN["notice" + options.type]) BDFDB.DOMUtils.addClass(notice, type); + if (options.type == "premium") { + let noticeButton = notice.querySelector(BDFDB.dotCN.noticebutton); + if (noticeButton) BDFDB.DOMUtils.addClass(noticeButton, BDFDB.disCN.noticepremiumaction); + BDFDB.DOMUtils.addClass(noticeMessage, BDFDB.disCN.noticepremiumtext); + notice.insertBefore(BDFDB.DOMUtils.create(``), noticeMessage); + } + } + if (!type) { + let comp = BDFDB.ColorUtils.convert(options.color, "RGBCOMP"); + if (comp) { + let fontColor = comp[0] > 180 && comp[1] > 180 && comp[2] > 180 ? "#000" : "#FFF"; + let backgroundcolor = BDFDB.ColorUtils.convert(comp, "HEX"); + let filter = comp[0] > 180 && comp[1] > 180 && comp[2] > 180 ? "brightness(0%)" : "brightness(100%)"; + BDFDB.DOMUtils.appendLocalStyle("BDFDBcustomNotificationBarColorCorrection" + id, `${BDFDB.dotCN.noticewrapper}[notice-id="${id}"]{background-color:${backgroundcolor} !important;}${BDFDB.dotCN.noticewrapper}[notice-id="${id}"] .notice-message {color:${fontColor} !important;}${BDFDB.dotCN.noticewrapper}[notice-id="${id}"] ${BDFDB.dotCN.noticebutton} {color:${fontColor} !important;border-color:${BDFDB.ColorUtils.setAlpha(fontColor, 0.25, "RGBA")} !important;}${BDFDB.dotCN.noticewrapper}[notice-id="${id}"] ${BDFDB.dotCN.noticebutton}:hover {color:${backgroundcolor} !important;background-color:${fontColor} !important;}${BDFDB.dotCN.noticewrapper}[notice-id="${id}"] ${BDFDB.dotCN.noticedismiss} {filter:${filter} !important;}`); + } + else BDFDB.DOMUtils.addClass(notice, BDFDB.disCN.noticedefault); + } + notice.style.setProperty("height", "36px", "important"); + notice.style.setProperty("min-width", "70vw", "important"); + notice.style.setProperty("left", "unset", "important"); + notice.style.setProperty("right", "unset", "important"); + let sideMargin = ((BDFDB.DOMUtils.getWidth(document.body.firstElementChild) - BDFDB.DOMUtils.getWidth(notice))/2); + notice.style.setProperty("left", `${sideMargin}px`, "important"); + notice.style.setProperty("right", `${sideMargin}px`, "important"); + notice.style.setProperty("min-width", "unset", "important"); + notice.style.setProperty("width", "unset", "important"); + notice.style.setProperty("max-width", `calc(100vw - ${sideMargin*2}px)`, "important"); + notice.querySelector(BDFDB.dotCN.noticedismiss).addEventListener("click", _ => { + notice.style.setProperty("overflow", "hidden", "important"); + notice.style.setProperty("height", "0px", "important"); + if (notice.tooltip && typeof notice.tooltip.removeTooltip == "function") notice.tooltip.removeTooltip(); + BDFDB.TimeUtils.timeout(_ => { + BDFDB.ArrayUtils.remove(NotificationBars, id); + BDFDB.DOMUtils.removeLocalStyle("BDFDBcustomNotificationBar" + id); + BDFDB.DOMUtils.removeLocalStyle("BDFDBcustomNotificationBarColorCorrection" + id); + BDFDB.DOMUtils.remove(notice); + }, 500); + }); + return notice; + }; + BDFDB.NotificationUtils.alert = function (header, body) { + if (typeof header == "string" && typeof header == "string" && window.BdApi && typeof BdApi.alert == "function") BdApi.alert(header, body); + }; - // Legacy + var Tooltips = []; + BDFDB.TooltipUtils = {}; + BDFDB.TooltipUtils.create = function (anker, text, options = {}) { + let itemLayerContainer = document.querySelector(BDFDB.dotCN.appmount + " > " + BDFDB.dotCN.itemlayercontainer); + if (!itemLayerContainer || !Node.prototype.isPrototypeOf(anker) || !document.contains(anker)) return null; + text = typeof text == "function" ? text() : text; + if (typeof text != "string" && !BDFDB.ReactUtils.isValidElement(text) && !BDFDB.ObjectUtils.is(options.guild)) return null; + let id = BDFDB.NumberUtils.generateId(Tooltips); + let zIndexed = typeof options.zIndex == "number" || options.unhideable; + let itemLayer = BDFDB.DOMUtils.create(`
`); + if (zIndexed) { + let itemLayerContainerClone = itemLayerContainer.cloneNode(); + itemLayerContainerClone.style.setProperty("z-index", options.zIndex || 1002, "important"); + itemLayerContainer.parentElement.insertBefore(itemLayerContainerClone, itemLayerContainer.nextElementChild); + itemLayerContainer = itemLayerContainerClone; + } + itemLayerContainer.appendChild(itemLayer); + + let tooltip = itemLayer.firstElementChild; + let tooltipContent = itemLayer.querySelector(BDFDB.dotCN.tooltipcontent); + let tooltipPointer = itemLayer.querySelector(BDFDB.dotCN.tooltippointer); + + if (options.id) tooltip.id = options.id.split(" ").join(""); + + if (typeof options.type != "string" || !BDFDB.disCN["tooltip" + options.type.toLowerCase()]) options.type = "top"; + let type = options.type.toLowerCase(); + BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN["tooltip" + type], options.className, options.selector); + + let fontColorIsGradient = false, customBackgroundColor = false, style = ""; + if (options.style) style += options.style; + if (options.fontColor) { + fontColorIsGradient = BDFDB.ObjectUtils.is(options.fontColor); + if (!fontColorIsGradient) style = (style ? (style + " ") : "") + `color: ${BDFDB.ColorUtils.convert(options.fontColor, "RGBA")} !important;` + } + if (options.backgroundColor) { + customBackgroundColor = true; + let backgroundColorIsGradient = BDFDB.ObjectUtils.is(options.backgroundColor); + let backgroundColor = !backgroundColorIsGradient ? BDFDB.ColorUtils.convert(options.backgroundColor, "RGBA") : BDFDB.ColorUtils.createGradient(options.backgroundColor); + style = (style ? (style + " ") : "") + `background: ${backgroundColor} !important; border-color: ${backgroundColorIsGradient ? BDFDB.ColorUtils.convert(options.backgroundColor[type == "left" ? 100 : 0], "RGBA") : backgroundColor} !important;`; + } + if (style) tooltip.style = style; + if (zIndexed) { + itemLayer.style.setProperty("z-index", options.zIndex || 1002, "important"); + tooltip.style.setProperty("z-index", options.zIndex || 1002, "important"); + tooltipContent.style.setProperty("z-index", options.zIndex || 1002, "important"); + } + if (typeof options.width == "number" && options.width > 196) { + tooltip.style.setProperty("width", `${options.width}px`, "important"); + tooltip.style.setProperty("max-width", `${options.width}px`, "important"); + } + if (typeof options.maxWidth == "number" && options.maxWidth > 196) { + tooltip.style.setProperty("max-width", `${options.maxWidth}px`, "important"); + } + if (customBackgroundColor || options.unhideable) BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN.tooltipcustom); + else if (options.color && BDFDB.disCN["tooltip" + options.color.toLowerCase()]) BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN["tooltip" + options.color.toLowerCase()]); + else BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN.tooltipblack); + + if (options.list || BDFDB.ObjectUtils.is(options.guild)) BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN.tooltiplistitem); + + let mouseLeave = _ => {itemLayer.removeTooltip();}; + if (!options.perssist) anker.addEventListener("mouseleave", mouseLeave); + + let observer = new MutationObserver(changes => changes.forEach(change => { + let nodes = Array.from(change.removedNodes); + if (nodes.indexOf(itemLayer) > -1 || nodes.indexOf(anker) > -1 || nodes.some(n => n.contains(anker))) { + BDFDB.ArrayUtils.remove(Tooltips, id); + observer.disconnect(); + BDFDB.DOMUtils.removeLocalStyle("BDFDBhideOtherTooltips" + id, itemLayerContainer); + itemLayer.removeTooltip(); + anker.removeEventListener("mouseleave", mouseLeave); + if (typeof options.onHide == "function") options.onHide(itemLayer, anker); + } + })); + observer.observe(document.body, {subtree:true, childList:true}); + + (tooltip.setText = itemLayer.setText = newText => { + if (BDFDB.ObjectUtils.is(options.guild)) { + let streamOwnerIds = LibraryModules.StreamUtils.getAllApplicationStreams().filter(app => app.guildId === options.guild.id).map(app => app.ownerId) || []; + let streamOwners = streamOwnerIds.map(ownerId => LibraryModules.UserStore.getUser(ownerId)).filter(n => n); + let connectedUsers = Object.keys(LibraryModules.VoiceUtils.getVoiceStates(options.guild.id)).map(userId => !streamOwnerIds.includes(userId) && BDFDB.LibraryModules.UserStore.getUser(userId)).filter(n => n); + let tooltipText = options.guild.toString(); + if (fontColorIsGradient) tooltipText = `${BDFDB.StringUtils.htmlEscape(tooltipText)}`; + BDFDB.ReactUtils.render(BDFDB.ReactUtils.createElement(BDFDB.ReactUtils.Fragment, { + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltiprow, BDFDB.disCN.tooltiprowguildname), + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.GuildComponents.Badge, { + guild: options.guild, + size: LibraryModules.StringUtils.cssValueToNumber(DiscordClassModules.TooltipGuild.iconSize), + className: BDFDB.disCN.tooltiprowicon + }), + BDFDB.ReactUtils.createElement("span", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltipguildnametext, (connectedUsers.length || streamOwners.length) && BDFDB.disCN.tooltipguildnametextlimitedsize), + children: fontColorIsGradient || options.html ? BDFDB.ReactUtils.elementToReact(BDFDB.DOMUtils.create(tooltipText)) : tooltipText + }), + ] + }), + newText && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tooltiprow, BDFDB.disCN.tooltiprowextra), + children: newText + }), + connectedUsers.length && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.tooltiprow, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: InternalComponents.LibraryComponents.SvgIcon.Names.SPEAKER, + className: BDFDB.disCN.tooltipactivityicon + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.UserSummaryItem, { + users: connectedUsers, + max: 6 + }) + ] + }), + streamOwners.length && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.tooltiprow, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: InternalComponents.LibraryComponents.SvgIcon.Names.STREAM, + className: BDFDB.disCN.tooltipactivityicon + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.UserSummaryItem, { + users: streamOwners, + max: 6 + }) + ] + }) + ].filter(n => n) + }), tooltipContent); + } + else { + if (fontColorIsGradient) tooltipContent.innerHTML = `${BDFDB.StringUtils.htmlEscape(newText)}`; + else if (options.html === true) tooltipContent.innerHTML = newText; + else tooltipContent.innerText = newText; + } + })(text); + (tooltip.removeTooltip = itemLayer.removeTooltip = _ => { + BDFDB.DOMUtils.remove(itemLayer); + if (zIndexed) BDFDB.DOMUtils.remove(itemLayerContainer); + }); + (tooltip.update = itemLayer.update = newText => { + if (newText) tooltip.setText(newText); + let left, top, tRects = BDFDB.DOMUtils.getRects(anker), iRects = BDFDB.DOMUtils.getRects(itemLayer), aRects = BDFDB.DOMUtils.getRects(document.querySelector(BDFDB.dotCN.appmount)), positionOffsets = {height: 10, width: 10}, offset = typeof options.offset == "number" ? options.offset : 0; + switch (type) { + case "top": + top = tRects.top - iRects.height - positionOffsets.height + 2 - offset; + left = tRects.left + (tRects.width - iRects.width) / 2; + break; + case "bottom": + top = tRects.top + tRects.height + positionOffsets.height - 2 + offset; + left = tRects.left + (tRects.width - iRects.width) / 2; + break; + case "left": + top = tRects.top + (tRects.height - iRects.height) / 2; + left = tRects.left - iRects.width - positionOffsets.width + 2 - offset; + break; + case "right": + top = tRects.top + (tRects.height - iRects.height) / 2; + left = tRects.left + tRects.width + positionOffsets.width - 2 + offset; + break; + } + + itemLayer.style.setProperty("top", `${top}px`, "important"); + itemLayer.style.setProperty("left", `${left}px`, "important"); + + tooltipPointer.style.removeProperty("margin-left"); + tooltipPointer.style.removeProperty("margin-top"); + if (type == "top" || type == "bottom") { + if (left < 0) { + itemLayer.style.setProperty("left", "5px", "important"); + tooltipPointer.style.setProperty("margin-left", `${left - 10}px`, "important"); + } + else { + let rightMargin = aRects.width - (left + iRects.width); + if (rightMargin < 0) { + itemLayer.style.setProperty("left", `${aRects.width - iRects.width - 5}px`, "important"); + tooltipPointer.style.setProperty("margin-left", `${-1*rightMargin}px`, "important"); + } + } + } + else if (type == "left" || type == "right") { + if (top < 0) { + itemLayer.style.setProperty("top", "5px"); + tooltipPointer.style.setProperty("margin-top", `${top - 10}px`, "important"); + } + else { + let bottomMargin = aRects.height - (top + iRects.height); + if (bottomMargin < 0) { + itemLayer.style.setProperty("top", `${aRects.height - iRects.height - 5}px`, "important"); + tooltipPointer.style.setProperty("margin-top", `${-1*bottomMargin}px`, "important"); + } + } + } + if (options.unhideable) { + for (let node of [itemLayer, tooltip, tooltipContent]) { + node.style.setProperty("position", "absolute", "important"); + node.style.setProperty("right", "unset", "important"); + node.style.setProperty("bottom", "unset", "important"); + node.style.setProperty("display", "block", "important"); + node.style.setProperty("opacity", "1", "important"); + node.style.setProperty("visibility", "visible", "important"); + node.style.setProperty("max-width", "unset", "important"); + node.style.setProperty("min-width", "50px", "important"); + node.style.setProperty("width", "unset", "important"); + node.style.setProperty("max-height", "unset", "important"); + node.style.setProperty("min-height", "14px", "important"); + node.style.setProperty("height", "unset", "important"); + node.style.setProperty("animation", "unset", "important"); + node.style.setProperty("transform", "unset", "important"); + } + for (let node of [tooltip, tooltipContent]) { + node.style.setProperty("position", "static", "important"); + node.style.setProperty("top", "unset", "important"); + node.style.setProperty("left", "unset", "important"); + } + tooltip.style.setProperty("background", "#000", "important"); + tooltipContent.style.setProperty("color", "#dcddde", "important"); + tooltipPointer.style.setProperty(`border-top-color`, "#000", "important"); + } + })(); + + if (options.delay) { + BDFDB.DOMUtils.toggle(itemLayer); + BDFDB.TimeUtils.timeout(_ => { + BDFDB.DOMUtils.toggle(itemLayer); + if (typeof options.onShow == "function") options.onShow(itemLayer, anker); + }, options.delay); + } + else { + if (typeof options.onShow == "function") options.onShow(itemLayer, anker); + } + return itemLayer; + }; + + BDFDB.ObjectUtils = {}; + BDFDB.ObjectUtils.is = function (obj) { + return obj && Object.prototype.isPrototypeOf(obj) && !Array.prototype.isPrototypeOf(obj); + }; + BDFDB.ObjectUtils.get = function (nodeOrObj, valuePath) { + if (!nodeOrObj || !valuePath) return null; + let obj = Node.prototype.isPrototypeOf(nodeOrObj) ? BDFDB.ReactUtils.getInstance(nodeOrObj) : nodeOrObj; + if (!BDFDB.ObjectUtils.is(obj)) return null; + let found = obj, values = valuePath.split(".").filter(n => n); + for (value of values) { + if (!found) return null; + found = found[value]; + } + return found; + }; + BDFDB.ObjectUtils.extract = function (obj, ...keys) { + let newObj = {}; + if (BDFDB.ObjectUtils.is(obj)) for (let key of keys.flat(10).filter(n => n)) if (obj[key]) newObj[key] = obj[key]; + return newObj; + }; + BDFDB.ObjectUtils.exclude = function (obj, ...keys) { + let newObj = Object.assign({}, obj); + BDFDB.ObjectUtils.delete(newObj, ...keys) + return newObj; + }; + BDFDB.ObjectUtils.delete = function (obj, ...keys) { + if (BDFDB.ObjectUtils.is(obj)) for (let key of keys.flat(10).filter(n => n)) delete obj[key]; + }; + BDFDB.ObjectUtils.sort = function (obj, sort, except) { + if (!BDFDB.ObjectUtils.is(obj)) return {}; + let newObj = {}; + if (sort === undefined || !sort) for (let key of Object.keys(obj).sort()) newObj[key] = obj[key]; + else { + let values = []; + for (let key in obj) values.push(obj[key]); + values = BDFDB.ArrayUtils.keySort(values, sort, except); + for (let value of values) for (let key in obj) if (BDFDB.equals(value, obj[key])) { + newObj[key] = value; + break; + } + } + return newObj; + }; + BDFDB.ObjectUtils.reverse = function (obj, sort) { + if (!BDFDB.ObjectUtils.is(obj)) return {}; + let newObj = {}; + for (let key of (sort === undefined || !sort) ? Object.keys(obj).reverse() : Object.keys(obj).sort().reverse()) newObj[key] = obj[key]; + return newObj; + }; + BDFDB.ObjectUtils.filter = function (obj, filter, byKey = false) { + if (!BDFDB.ObjectUtils.is(obj)) return {}; + if (typeof filter != "function") return obj; + return Object.keys(obj).filter(key => filter(byKey ? key : obj[key])).reduce((newObj, key) => (newObj[key] = obj[key], newObj), {}); + }; + BDFDB.ObjectUtils.push = function (obj, value) { + if (BDFDB.ObjectUtils.is(obj)) obj[Object.keys(obj).length] = value; + }; + BDFDB.ObjectUtils.pop = function (obj, value) { + if (BDFDB.ObjectUtils.is(obj)) { + let keys = Object.keys(obj); + if (!keys.length) return; + let value = obj[keys[keys.length-1]]; + delete obj[keys[keys.length-1]]; + return value; + } + }; + BDFDB.ObjectUtils.map = function (obj, mapfunc) { + if (!BDFDB.ObjectUtils.is(obj)) return {}; + if (typeof mapfunc != "string" && typeof mapfunc != "function") return obj; + let newObj = {}; + for (let key in obj) if (BDFDB.ObjectUtils.is(obj[key])) newObj[key] = typeof mapfunc == "string" ? obj[key][mapfunc] : mapfunc(obj[key], key); + return newObj; + }; + BDFDB.ObjectUtils.toArray = function (obj) { + if (!BDFDB.ObjectUtils.is(obj)) return []; + return Object.entries(obj).map(n => n[1]); + }; + BDFDB.ObjectUtils.deepAssign = function (obj, ...objs) { + if (!objs.length) return obj; + let nextObj = objs.shift(); + if (BDFDB.ObjectUtils.is(obj) && BDFDB.ObjectUtils.is(nextObj)) { + for (let key in nextObj) { + if (BDFDB.ObjectUtils.is(nextObj[key])) { + if (!obj[key]) Object.assign(obj, {[key]:{}}); + BDFDB.ObjectUtils.deepAssign(obj[key], nextObj[key]); + } + else Object.assign(obj, {[key]:nextObj[key]}); + } + } + return BDFDB.ObjectUtils.deepAssign(obj, ...objs); + }; + BDFDB.ObjectUtils.isEmpty = function (obj) { + return !BDFDB.ObjectUtils.is(obj) || Object.getOwnPropertyNames(obj).length == 0; + }; + + BDFDB.ArrayUtils = {}; + BDFDB.ArrayUtils.is = function (array) { + return array && Array.isArray(array); + }; + BDFDB.ArrayUtils.sum = function (array) { + return Array.isArray(array) ? array.reduce((total, num) => total + Math.round(num), 0) : 0; + }; + BDFDB.ArrayUtils.keySort = function (array, key, except) { + if (!BDFDB.ArrayUtils.is(array)) return []; + if (key == null) return array; + if (except === undefined) except = null; + return array.sort((x, y) => { + let xValue = x[key], yValue = y[key]; + if (xValue !== except) return xValue < yValue ? -1 : xValue > yValue ? 1 : 0; + }); + }; + BDFDB.ArrayUtils.numSort = function (array) { + return array.sort((x, y) => (x < y ? -1 : x > y ? 1 : 0)); + }; + BDFDB.ArrayUtils.includes = function (array, ...values) { + if (!BDFDB.ArrayUtils.is(array)) return null; + if (!array.length) return false; + let all = values.pop(); + if (typeof all != "boolean") { + values.push(all); + all = true; + } + if (!values.length) return false; + let contained = undefined; + for (let v of values) { + if (contained === undefined) contained = all; + if (all && !array.includes(v)) contained = false; + if (!all && array.includes(v)) contained = true; + } + return contained; + }; + BDFDB.ArrayUtils.remove = function (array, value, all = false) { + if (!BDFDB.ArrayUtils.is(array)) return []; + if (!array.includes(value)) return array; + if (!all) array.splice(array.indexOf(value), 1); + else while (array.indexOf(value) > -1) array.splice(array.indexOf(value), 1); + return array; + }; + BDFDB.ArrayUtils.getAllIndexes = function (array, value) { + if (!BDFDB.ArrayUtils.is(array) && typeof array != "string") return []; + var indexes = [], index = -1; + while ((index = array.indexOf(value, index + 1)) !== -1) indexes.push(index); + return indexes; + }; + BDFDB.ArrayUtils.removeCopies = function (array) { + if (!BDFDB.ArrayUtils.is(array)) return []; + return [...new Set(array)]; + }; + + InternalBDFDB.findModule = function (type, cachestring, filter, getExport) { + if (!BDFDB.ObjectUtils.is(Cache.modules[type])) Cache.modules[type] = {module:{}, export:{}}; + if (getExport && Cache.modules[type].export[cachestring]) return Cache.modules[type].export[cachestring]; + else if (!getExport && Cache.modules[type].module[cachestring]) return Cache.modules[type].module[cachestring]; + else { + let m = BDFDB.ModuleUtils.find(filter, getExport); + if (m) { + if (getExport) Cache.modules[type].export[cachestring] = m; + else Cache.modules[type].module[cachestring] = m; + return m; + } + else BDFDB.LogUtils.warn(`${cachestring} [${type}] not found in WebModules`); + } + }; + InternalBDFDB.getWebModuleReq = function () { + if (!InternalBDFDB.getWebModuleReq.req) { + const id = "BDFDB-WebModules"; + const req = window.webpackJsonp.push([[], {[id]: (module, exports, req) => module.exports = req}, [[id]]]); + delete req.m[id]; + delete req.c[id]; + InternalBDFDB.getWebModuleReq.req = req; + } + return InternalBDFDB.getWebModuleReq.req; + }; + BDFDB.ModuleUtils = {}; + BDFDB.ModuleUtils.find = function (filter, getExport) { + getExport = typeof getExport != "boolean" ? true : getExport; + let req = InternalBDFDB.getWebModuleReq(); + for (let i in req.c) if (req.c.hasOwnProperty(i)) { + let m = req.c[i].exports; + if (m && (typeof m == "object" || typeof m == "function") && filter(m)) return getExport ? m : req.c[i]; + if (m && m.__esModule) { + for (let j in m) if (m[j] && (typeof m[j] == "object" || typeof m[j] == "function") && filter(m[j])) return getExport ? m[j] : req.c[i]; + if (m.default && (typeof m.default == "object" || typeof m.default == "function")) for (let j in m.default) if (m.default[j] && (typeof m.default[j] == "object" || typeof m.default[j] == "function") && filter(m.default[j])) return getExport ? m.default[j] : req.c[i]; + } + } + for (let i in req.m) if (req.m.hasOwnProperty(i)) { + let m = req.m[i]; + if (m && typeof m == "function" && filter(m)) { + if (req.c[i]) return getExport ? req.c[i].exports : req.c[i]; + else { + let resolved = {}; + req.m[i](resolved, null, req); + return getExport ? resolved.exports : resolved; + } + } + } + }; + BDFDB.ModuleUtils.findByProperties = function (...properties) { + properties = properties.flat(10); + let getExport = properties.pop(); + if (typeof getExport != "boolean") { + properties.push(getExport); + getExport = true; + } + return InternalBDFDB.findModule("prop", JSON.stringify(properties), m => properties.every(prop => m[prop] !== undefined), getExport); + }; + BDFDB.ModuleUtils.findByName = function (name, getExport) { + return InternalBDFDB.findModule("name", JSON.stringify(name), m => m.displayName === name || m.render && m.render.displayName === name, typeof getExport != "boolean" ? true : getExport); + }; + BDFDB.ModuleUtils.findByString = function (...strings) { + strings = strings.flat(10); + let getExport = strings.pop(); + if (typeof getExport != "boolean") { + strings.push(getExport); + getExport = true; + } + return InternalBDFDB.findModule("string", JSON.stringify(strings), m => strings.every(string => typeof m == "function" && (m.toString().indexOf(string) > -1 || typeof m.__originalMethod == "function" && m.__originalMethod.toString().indexOf(string) > -1 || typeof m.__originalFunction == "function" && m.__originalFunction.toString().indexOf(string) > -1) || BDFDB.ObjectUtils.is(m) && typeof m.type == "function" && m.type.toString().indexOf(string) > -1), getExport); + }; + BDFDB.ModuleUtils.findByPrototypes = function (...protoProps) { + protoProps = protoProps.flat(10); + let getExport = protoProps.pop(); + if (typeof getExport != "boolean") { + protoProps.push(getExport); + getExport = true; + } + return InternalBDFDB.findModule("proto", JSON.stringify(protoProps), m => m.prototype && protoProps.every(prop => m.prototype[prop] !== undefined), getExport); + }; + + InternalBDFDB.forceInitiateProcess = function (pluginDataObjs, instance, type) { + pluginDataObjs = [pluginDataObjs].flat(10).filter(n => n); + if (pluginDataObjs.length && instance && type) { + let forceRender = false; + for (let pluginData of pluginDataObjs) { + let plugin = pluginData.plugin == BDFDB && InternalBDFDB || pluginData.plugin, methodNames = []; + for (let patchType in plugin.patchedModules) { + if (plugin.patchedModules[patchType][type]) methodNames.push(plugin.patchedModules[patchType][type]); + } + methodNames = BDFDB.ArrayUtils.removeCopies(methodNames).flat(10).filter(n => n); + if (methodNames.includes("componentDidMount")) InternalBDFDB.initiateProcess(plugin, type, { + instance: instance, + methodname: "componentDidMount", + patchtypes: pluginData.patchTypes[type] + }); + if (methodNames.includes("render")) forceRender = true; + else if (!forceRender && methodNames.includes("componentDidUpdate")) InternalBDFDB.initiateProcess(plugin, type, { + instance: instance, + methodname: "componentDidUpdate", + patchtypes: pluginData.patchTypes[type] + }); + } + if (forceRender) BDFDB.ReactUtils.forceUpdate(instance); + } + }; + InternalBDFDB.initiateProcess = function (plugin, type, e) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (BDFDB.ObjectUtils.is(plugin) && !plugin.stopping && e.instance) { + type = LibraryModules.StringUtils.upperCaseFirstChar(type.split(" _ _ ")[1] || type).replace(/[^A-z0-9]|_/g, ""); + if (typeof plugin[`process${type}`] == "function") { + if (typeof e.methodname == "string" && (e.methodname.indexOf("componentDid") == 0 || e.methodname.indexOf("componentWill") == 0)) { + e.node = BDFDB.ReactUtils.findDOMNode(e.instance); + if (e.node) return plugin[`process${type}`](e); + else BDFDB.TimeUtils.timeout(_ => { + e.node = BDFDB.ReactUtils.findDOMNode(e.instance); + if (e.node) return plugin[`process${type}`](e); + }); + } + else if (e.returnvalue || e.patchtypes.includes("before")) return plugin[`process${type}`](e); + } + } + }; + InternalBDFDB.patchObserverData = {observer:null, data:{}}; + InternalBDFDB.patchPlugin = function (plugin) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(plugin.patchedModules)) return; + BDFDB.PatchUtils.unpatch(plugin); + let patchedModules = {}; + for (let patchType in plugin.patchedModules) for (let type in plugin.patchedModules[patchType]) { + if (!patchedModules[type]) patchedModules[type] = {}; + patchedModules[type][patchType] = plugin.patchedModules[patchType][type]; + } + for (let type in patchedModules) { + let pluginData = {plugin: plugin, patchTypes: patchedModules[type]}; + let unmappedType = type.split(" _ _ ")[1] || type; + + let config = { + classNames: [InternalData.ModuleUtilsConfig.Finder[unmappedType] && InternalData.ModuleUtilsConfig.Finder[unmappedType].class].flat(10).filter(n => DiscordClasses[n]), + stringFind: InternalData.ModuleUtilsConfig.Finder[unmappedType] && InternalData.ModuleUtilsConfig.Finder[unmappedType].strings, + propertyFind: InternalData.ModuleUtilsConfig.Finder[unmappedType] && InternalData.ModuleUtilsConfig.Finder[unmappedType].props, + memoComponent: InternalData.ModuleUtilsConfig.MemoComponent.includes(unmappedType), + forceObserve: InternalData.ModuleUtilsConfig.ForceObserve.includes(unmappedType), + nonRender: BDFDB.ObjectUtils.toArray(pluginData.patchTypes).flat(10).filter(n => n && !InternalData.ModuleUtilsConfig.InstanceFunctions.includes(n)).length > 0, + mapped: InternalData.ModuleUtilsConfig.PatchMap[type] + }; + config.ignoreCheck = !!(config.stringFind || config.propertyFind || config.nonRender); + config.nonPrototype = InternalData.ModuleUtilsConfig.NonPrototype.includes(unmappedType) || config.ignoreCheck; + + let component = InternalData.ModuleUtilsConfig.LoadedInComponents[type] && BDFDB.ObjectUtils.get(InternalComponents, InternalData.ModuleUtilsConfig.LoadedInComponents[type]); + if (component) InternalBDFDB.patchInstance(pluginData, config.nonRender ? (BDFDB.ModuleUtils.find(m => m == component, false) || {}).exports : component, type, config); + else { + let mappedType = config.mapped ? config.mapped + " _ _ " + type : type; + let name = mappedType.split(" _ _ ")[0]; + if (config.mapped) { + for (let patchType in plugin.patchedModules) if (plugin.patchedModules[patchType][type]) { + plugin.patchedModules[patchType][mappedType] = plugin.patchedModules[patchType][type]; + delete plugin.patchedModules[patchType][type]; + } + } + if (config.classNames.length) InternalBDFDB.checkForInstance(pluginData, mappedType, config); + else if (config.stringFind) { + let exports = (BDFDB.ModuleUtils.findByString(config.stringFind, false) || {}).exports; + InternalBDFDB.patchInstance(pluginData, exports && config.memoComponent ? exports.default : exports, mappedType, config); + } + else if (config.propertyFind) { + let exports = (BDFDB.ModuleUtils.findByProperties(config.propertyFind, false) || {}).exports; + InternalBDFDB.patchInstance(pluginData, exports && config.memoComponent ? exports.default : exports, mappedType, config); + } + else if (config.nonRender) { + let exports = (BDFDB.ModuleUtils.findByName(name, false) || {}).exports; + InternalBDFDB.patchInstance(pluginData, exports && config.memoComponent ? exports.default : exports, mappedType, config); + } + else InternalBDFDB.patchInstance(pluginData, BDFDB.ModuleUtils.findByName(name), mappedType, config); + } + } + }; + InternalBDFDB.patchInstance = function (pluginDataObjs, instance, type, config) { + pluginDataObjs = [pluginDataObjs].flat(10).filter(n => n); + if (pluginDataObjs.length && instance) { + let name = type.split(" _ _ ")[0]; + instance = instance._reactInternalFiber && instance._reactInternalFiber.type ? instance._reactInternalFiber.type : instance; + instance = config.ignoreCheck || BDFDB.ReactUtils.isCorrectInstance(instance, name) || InternalData.ModuleUtilsConfig.LoadedInComponents[type] ? instance : (BDFDB.ReactUtils.findConstructor(instance, name) || BDFDB.ReactUtils.findConstructor(instance, name, {up:true})); + if (instance) { + instance = instance._reactInternalFiber && instance._reactInternalFiber.type ? instance._reactInternalFiber.type : instance; + let toBePatched = config.nonPrototype ? instance : instance.prototype; + for (let pluginData of pluginDataObjs) for (let patchType in pluginData.patchTypes) { + let patchMethods = {}; + patchMethods[patchType] = e => { + return InternalBDFDB.initiateProcess(pluginData.plugin, type, { + instance: e.thisObject && window != e.thisObject ? e.thisObject : {props:e.methodArguments[0]}, + returnvalue: e.returnValue, + methodname: e.originalMethodName, + patchtypes: [patchType] + }); + }; + BDFDB.PatchUtils.patch(pluginData.plugin, toBePatched, pluginData.patchTypes[patchType], patchMethods); + } + } + } + }; + InternalBDFDB.checkEle = function (pluginDataObjs, ele, type, config) { + pluginDataObjs = [pluginDataObjs].flat(10).filter(n => n); + let unmappedType = type.split(" _ _ ")[1] || type; + let ins = BDFDB.ReactUtils.getInstance(ele); + // FIX SpecialFilter + let filter = false && InternalData.ModuleUtilsConfig.SpecialFilter[unmappedType]; + if (typeof filter == "function") { + let component = filter(ins); + if (component) { + if (config.nonRender) { + let exports = (BDFDB.ModuleUtils.find(m => m == component, false) || {}).exports; + InternalBDFDB.patchInstance(pluginDataObjs, exports && config.memoComponent ? exports.default : exports, type, config); + } + else InternalBDFDB.patchInstance(pluginDataObjs, component, type, config); + BDFDB.PatchUtils.forceAllUpdates(pluginDataObjs.map(n => n.plugin), type); + return true; + } + } + else if (InternalBDFDB.isCorrectPatchInstance(ins, type)) { + InternalBDFDB.patchInstance(pluginDataObjs, ins, type, config); + BDFDB.PatchUtils.forceAllUpdates(pluginDataObjs.map(n => n.plugin), type); + return true; + } + return false; + }; + InternalBDFDB.checkForInstance = function (pluginData, type, config) { + const app = document.querySelector(BDFDB.dotCN.app), bdSettings = document.querySelector("#bd-settingspane-container .scroller"); + let instanceFound = false; + if (!config.forceObserve) { + if (app) { + let appIns = BDFDB.ReactUtils.findConstructor(app, type, {unlimited:true}) || BDFDB.ReactUtils.findConstructor(app, type, {unlimited:true, up:true}); + if (appIns && (instanceFound = true)) InternalBDFDB.patchInstance(pluginData, appIns, type, config); + } + if (!instanceFound && bdSettings) { + let bdSettingsIns = BDFDB.ReactUtils.findConstructor(bdSettings, type, {unlimited:true}); + if (bdSettingsIns && (instanceFound = true)) InternalBDFDB.patchInstance(pluginData, bdSettingsIns, type, config); + } + } + if (!instanceFound) { + let elementFound = false, classes = config.classNames.map(n => BDFDB.disCN[n]), selector = config.classNames.map(n => BDFDB.dotCN[n]).join(", "); + for (let ele of document.querySelectorAll(selector)) { + elementFound = InternalBDFDB.checkEle(pluginData, ele, type, config); + if (elementFound) break; + } + if (!elementFound) { + if (!InternalBDFDB.patchObserverData.observer) { + let appmount = document.querySelector(BDFDB.dotCN.appmount); + if (appmount) { + InternalBDFDB.patchObserverData.observer = new MutationObserver(cs => {cs.forEach(c => {c.addedNodes.forEach(n => { + if (!n || !n.tagName) return; + for (let type in InternalBDFDB.patchObserverData.data) if (!InternalBDFDB.patchObserverData.data[type].found) { + let ele = null; + if ((ele = BDFDB.DOMUtils.containsClass(n, ...InternalBDFDB.patchObserverData.data[type].classes) ? n : n.querySelector(InternalBDFDB.patchObserverData.data[type].selector)) != null) { + InternalBDFDB.patchObserverData.data[type].found = InternalBDFDB.checkEle(InternalBDFDB.patchObserverData.data[type].plugins, ele, type, config); + if (InternalBDFDB.patchObserverData.data[type].found) { + delete InternalBDFDB.patchObserverData.data[type]; + if (BDFDB.ObjectUtils.isEmpty(InternalBDFDB.patchObserverData.data)) { + InternalBDFDB.patchObserverData.observer.disconnect(); + InternalBDFDB.patchObserverData.observer = null; + } + } + } + } + });});}); + InternalBDFDB.patchObserverData.observer.observe(appmount, {childList:true, subtree:true}); + } + } + if (!InternalBDFDB.patchObserverData.data[type]) InternalBDFDB.patchObserverData.data[type] = {selector, classes, found:false, plugins:[]}; + InternalBDFDB.patchObserverData.data[type].plugins.push(pluginData); + } + } + }; + + InternalBDFDB.isCorrectPatchInstance = function (instance, name) { + if (!instance) return false; + instance = instance._reactInternalFiber && instance._reactInternalFiber.type ? instance._reactInternalFiber.type : instance; + instance = BDFDB.ReactUtils.isCorrectInstance(instance, name) ? instance : (BDFDB.ReactUtils.findConstructor(instance, name) || BDFDB.ReactUtils.findConstructor(instance, name, {up:true})); + return !!instance; + }; + + BDFDB.PatchUtils = {}; + BDFDB.PatchUtils.isPatched = function (plugin, module, methodName) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!plugin || !BDFDB.ObjectUtils.is(module) || !module.BDFDBpatch || !methodName) return false; + const pluginId = (typeof plugin === "string" ? plugin : plugin.name).toLowerCase(); + return pluginId && module[methodName] && module[methodName].__isBDFDBpatched && module.BDFDBpatch[methodName] && BDFDB.ObjectUtils.toArray(module.BDFDBpatch[methodName]).some(patchObj => BDFDB.ObjectUtils.toArray(patchObj).some(priorityObj => Object.keys(priorityObj).includes(pluginId))); + }; + BDFDB.PatchUtils.patch = function (plugin, module, methodNames, patchMethods, config = {}) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!plugin || !BDFDB.ObjectUtils.is(module) || !methodNames || !BDFDB.ObjectUtils.is(patchMethods)) return null; + patchMethods = BDFDB.ObjectUtils.filter(patchMethods, type => InternalData.ModuleUtilsConfig.PatchTypes.includes(type), true); + if (BDFDB.ObjectUtils.isEmpty(patchMethods)) return null; + const pluginName = typeof plugin === "string" ? plugin : plugin.name; + const pluginId = pluginName.toLowerCase(); + const patchPriority = BDFDB.ObjectUtils.is(plugin) && !isNaN(plugin.patchPriority) ? (plugin.patchPriority < 0 ? 0 : (plugin.patchPriority > 10 ? 10 : Math.round(plugin.patchPriority))) : 5; + if (!BDFDB.ObjectUtils.is(module.BDFDBpatch)) module.BDFDBpatch = {}; + methodNames = [methodNames].flat(10).filter(n => n); + let cancel = _ => {BDFDB.PatchUtils.unpatch(plugin, module, methodNames);}; + for (let methodName of methodNames) if (module[methodName] == null || typeof module[methodName] == "function") { + if (!module.BDFDBpatch[methodName] || config.force && (!module[methodName] || !module[methodName].__isBDFDBpatched)) { + if (!module.BDFDBpatch[methodName]) { + module.BDFDBpatch[methodName] = {}; + for (let type of InternalData.ModuleUtilsConfig.PatchTypes) module.BDFDBpatch[methodName][type] = {}; + } + if (!module[methodName]) module[methodName] = (_ => {}); + const originalMethod = module[methodName]; + module.BDFDBpatch[methodName].originalMethod = originalMethod; + module[methodName] = function () { + let callInstead = false, stopCall = false; + const data = { + thisObject: this, + methodArguments: arguments, + originalMethod: originalMethod, + originalMethodName: methodName, + callOriginalMethod: _ => {if (!stopCall) data.returnValue = data.originalMethod.apply(data.thisObject, data.methodArguments)}, + callOriginalMethodAfterwards: _ => {callInstead = true;}, + stopOriginalMethodCall: _ => {stopCall = true;} + }; + if (module.BDFDBpatch && module.BDFDBpatch[methodName]) { + for (let priority in module.BDFDBpatch[methodName].before) for (let id in BDFDB.ObjectUtils.sort(module.BDFDBpatch[methodName].before[priority])) { + BDFDB.TimeUtils.suppress(module.BDFDBpatch[methodName].before[priority][id], `"before" callback of ${methodName} in ${module.constructor ? (module.constructor.displayName || module.constructor.name) : "module"}`, module.BDFDBpatch[methodName].before[priority][id].pluginName)(data); + } + + if (!module.BDFDBpatch || !module.BDFDBpatch[methodName]) return methodName == "render" && data.returnValue === undefined ? null : data.returnValue; + let hasInsteadPatches = BDFDB.ObjectUtils.toArray(module.BDFDBpatch[methodName].instead).some(priorityObj => !BDFDB.ObjectUtils.isEmpty(priorityObj)); + if (hasInsteadPatches) for (let priority in module.BDFDBpatch[methodName].instead) for (let id in BDFDB.ObjectUtils.sort(module.BDFDBpatch[methodName].instead[priority])) { + let tempReturn = BDFDB.TimeUtils.suppress(module.BDFDBpatch[methodName].instead[priority][id], `"instead" callback of ${methodName} in ${module.constructor ? (module.constructor.displayName || module.constructor.name) : "module"}`, module.BDFDBpatch[methodName].instead[priority][id].pluginName)(data); + if (tempReturn !== undefined) data.returnValue = tempReturn; + } + if ((!hasInsteadPatches || callInstead) && !stopCall) BDFDB.TimeUtils.suppress(data.callOriginalMethod, `originalMethod of ${methodName} in ${module.constructor ? (module.constructor.displayName || module.constructor.name) : "module"}`)(); + + if (!module.BDFDBpatch || !module.BDFDBpatch[methodName]) return methodName == "render" && data.returnValue === undefined ? null : data.returnValue; + for (let priority in module.BDFDBpatch[methodName].after) for (let id in BDFDB.ObjectUtils.sort(module.BDFDBpatch[methodName].after[priority])) { + let tempReturn = BDFDB.TimeUtils.suppress(module.BDFDBpatch[methodName].after[priority][id], `"after" callback of ${methodName} in ${module.constructor ? (module.constructor.displayName || module.constructor.name) : "module"}`, module.BDFDBpatch[methodName].after[priority][id].pluginName)(data); + if (tempReturn !== undefined) data.returnValue = tempReturn; + } + } + else BDFDB.TimeUtils.suppress(data.callOriginalMethod, `originalMethod of ${methodName} in ${module.constructor ? module.constructor.displayName || module.constructor.name : "module"}`)(); + callInstead = false, stopCall = false; + return methodName == "render" && data.returnValue === undefined ? null : data.returnValue; + }; + for (let key of Object.keys(originalMethod)) module[methodName][key] = originalMethod[key]; + if (!module[methodName].__originalFunction) { + let realOriginalMethod = originalMethod.__originalMethod || originalMethod.__originalFunction || originalMethod; + if (typeof realOriginalMethod == "function") { + module[methodName].__originalFunction = realOriginalMethod; + module[methodName].toString = _ => realOriginalMethod.toString(); + } + } + module[methodName].__isBDFDBpatched = true; + } + for (let type in patchMethods) if (typeof patchMethods[type] == "function") { + if (!BDFDB.ObjectUtils.is(module.BDFDBpatch[methodName][type][patchPriority])) module.BDFDBpatch[methodName][type][patchPriority] = {}; + module.BDFDBpatch[methodName][type][patchPriority][pluginId] = (...args) => { + if (config.once || !plugin.started) cancel(); + return patchMethods[type](...args); + }; + module.BDFDBpatch[methodName][type][patchPriority][pluginId].pluginName = pluginName; + } + } + if (BDFDB.ObjectUtils.is(plugin) && !config.once && !config.noCache) { + if (!BDFDB.ArrayUtils.is(plugin.patchCancels)) plugin.patchCancels = []; + plugin.patchCancels.push(cancel); + } + return cancel; + }; + BDFDB.PatchUtils.unpatch = function (plugin, module, methodNames) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!module && !methodNames) { + if (BDFDB.ObjectUtils.is(plugin) && BDFDB.ArrayUtils.is(plugin.patchCancels)) while (plugin.patchCancels.length) (plugin.patchCancels.pop())(); + } + else { + if (!BDFDB.ObjectUtils.is(module) || !module.BDFDBpatch) return; + const pluginId = !plugin ? null : (typeof plugin === "string" ? plugin : plugin.name).toLowerCase(); + if (methodNames) { + for (let methodName of [methodNames].flat(10).filter(n => n)) if (module[methodName] && module.BDFDBpatch[methodName]) unpatch(methodName, pluginId); + } + else for (let patchedMethod of module.BDFDBpatch) unpatch(patchedMethod, pluginId); + } + function unpatch (funcName, pluginId) { + for (let type of InternalData.ModuleUtilsConfig.PatchTypes) { + if (pluginId) for (let priority in module.BDFDBpatch[funcName][type]) { + delete module.BDFDBpatch[funcName][type][priority][pluginId]; + if (BDFDB.ObjectUtils.isEmpty(module.BDFDBpatch[funcName][type][priority])) delete module.BDFDBpatch[funcName][type][priority]; + } + else delete module.BDFDBpatch[funcName][type]; + } + if (BDFDB.ObjectUtils.isEmpty(BDFDB.ObjectUtils.filter(module.BDFDBpatch[funcName], key => InternalData.ModuleUtilsConfig.PatchTypes.includes(key) && !BDFDB.ObjectUtils.isEmpty(module.BDFDBpatch[funcName][key]), true))) { + module[funcName] = module.BDFDBpatch[funcName].originalMethod; + delete module.BDFDBpatch[funcName]; + if (BDFDB.ObjectUtils.isEmpty(module.BDFDBpatch)) delete module.BDFDBpatch; + } + } + }; + BDFDB.PatchUtils.forceAllUpdates = function (plugins, selectedTypes) { + plugins = [plugins].flat(10).map(n => n == BDFDB && InternalBDFDB || n).filter(n => BDFDB.ObjectUtils.is(n.patchedModules)); + if (plugins.length) { + const app = document.querySelector(BDFDB.dotCN.app); + const bdSettings = document.querySelector("#bd-settingspane-container > *"); + if (app) { + selectedTypes = [selectedTypes].flat(10).filter(n => n).map(type => type && InternalData.ModuleUtilsConfig.PatchMap[type] ? InternalData.ModuleUtilsConfig.PatchMap[type] + " _ _ " + type : type); + let updateData = {}; + for (let plugin of plugins) { + updateData[plugin.name] = { + filteredModules: [], + specialModules: [], + specialModuleTypes: [], + patchTypes: {} + }; + for (let patchType in plugin.patchedModules) for (let type in plugin.patchedModules[patchType]) { + let methodNames = [plugin.patchedModules[patchType][type]].flat(10).filter(n => n); + if (BDFDB.ArrayUtils.includes(methodNames, "componentDidMount", "componentDidUpdate", "render", false) && (!selectedTypes.length || selectedTypes.includes(type))) { + let unmappedType = type.split(" _ _ ")[1] || type; + // FIX SpecialFilter + let filter = false && InternalData.ModuleUtilsConfig.SpecialFilter[unmappedType]; + let selector = [InternalData.ModuleUtilsConfig.Finder[unmappedType]].flat(10).filter(n => DiscordClasses[n]).map(n => BDFDB.dotCN[n]).join(", "); + if (selector && typeof filter == "function") { + for (let ele of document.querySelectorAll(selector)) { + let constro = filter(BDFDB.ReactUtils.getInstance(ele)); + if (constro) { + updateData[plugin.name].specialModules.push([type, constro]); + updateData[plugin.name].specialModuleTypes.push(type); + break; + } + } + } + else updateData[plugin.name].filteredModules.push(type); + let name = type.split(" _ _ ")[0]; + if (!updateData[plugin.name].patchTypes[name]) updateData[plugin.name].patchTypes[name] = []; + updateData[plugin.name].patchTypes[name].push(patchType); + } + } + } + let updateDataArray = BDFDB.ObjectUtils.toArray(updateData); + if (BDFDB.ArrayUtils.sum(updateDataArray.map(n => n.filteredModules.length + n.specialModules.length))) { + try { + let filteredModules = BDFDB.ArrayUtils.removeCopies(updateDataArray.map(n => n.filteredModules).flat(10)); + let specialModules = BDFDB.ArrayUtils.removeCopies(updateDataArray.map(n => n.specialModules).flat(10)); + const appInsDown = BDFDB.ReactUtils.findOwner(app, {name:filteredModules, type:specialModules, all:true, group:true, unlimited:true}); + const appInsUp = BDFDB.ReactUtils.findOwner(app, {name:filteredModules, type:specialModules, all:true, group:true, unlimited:true, up:true}); + for (let type in appInsDown) { + let filteredPlugins = plugins.filter(n => updateData[n.name].filteredModules.includes(type) || updateData[n.name].specialModuleTypes.includes(type)).map(n => ({plugin:n, patchTypes:updateData[n.name].patchTypes})); + for (let ins of appInsDown[type]) InternalBDFDB.forceInitiateProcess(filteredPlugins, ins, type); + } + for (let type in appInsUp) { + let filteredPlugins = plugins.filter(n => updateData[n.name].filteredModules.includes(type) || updateData[n.name].specialModuleTypes.includes(type)).map(n => ({plugin:n, patchTypes:updateData[n.name].patchTypes})); + for (let ins of appInsUp[type]) InternalBDFDB.forceInitiateProcess(filteredPlugins, ins, type); + } + if (bdSettings) { + const bdSettingsIns = BDFDB.ReactUtils.findOwner(bdSettings, {name:filteredModules, type:specialModules, all:true, unlimited:true}); + if (bdSettingsIns.length) { + const bdSettingsWrap = BDFDB.ReactUtils.findOwner(BDFDB.ReactUtils.getInstance(document.querySelector("#bd-settingspane-container > *")), {props:"onChange", up:true}); + if (bdSettingsWrap && bdSettingsWrap.props && typeof bdSettingsWrap.props.onChange == "function") bdSettingsWrap.props.onChange(bdSettingsWrap.props.type); + } + } + } + catch (err) {BDFDB.LogUtils.error("Could not force update components! " + err, plugins.map(n => n.name).join(", "));} + } + } + } + }; + + BDFDB.DiscordConstants = BDFDB.ModuleUtils.findByProperties("Permissions", "ActivityTypes"); + + for (let name in InternalData.DiscordObjects) { + if (InternalData.DiscordObjects[name].props) DiscordObjects[name] = BDFDB.ModuleUtils.findByPrototypes(InternalData.DiscordObjects[name].props); + else if (InternalData.DiscordObjects[name].protos) DiscordObjects[name] = BDFDB.ModuleUtils.find(m => m.prototype && InternalData.DiscordObjects[name].protos.every(proto => m.prototype[proto] && (!InternalData.DiscordObjects[name].array || Array.isArray(m.prototype[proto])))); + } + BDFDB.DiscordObjects = Object.assign({}, DiscordObjects); + + for (let name of InternalData.LibraryRequires) { + try {LibraryRequires[name] = require(name);} catch (err) {} + } + BDFDB.LibraryRequires = Object.assign({}, LibraryRequires); + + for (let name in InternalData.LibraryModules) { + if (InternalData.LibraryModules[name].props) { + if (InternalData.LibraryModules[name].nonProps) LibraryModules[name] = BDFDB.ModuleUtils.find(m => InternalData.LibraryModules[name].props.every(prop => typeof m[prop] == "function") && InternalData.LibraryModules[name].nonProps.every(prop => typeof m[prop] != "function")); + else LibraryModules[name] = BDFDB.ModuleUtils.findByProperties(InternalData.LibraryModules[name].props); + } + } + if (LibraryModules.KeyCodeUtils) LibraryModules.KeyCodeUtils.getString = function (keyArray) { + return LibraryModules.KeyCodeUtils.toString([keyArray].flat(10).filter(n => n).map(keycode => [BDFDB.DiscordConstants.KeyboardDeviceTypes.KEYBOARD_KEY, keycode, BDFDB.DiscordConstants.KeyboardEnvs.BROWSER]), true); + }; + BDFDB.LibraryModules = Object.assign({}, LibraryModules); + + LibraryModules.React = BDFDB.ModuleUtils.findByProperties("createElement", "cloneElement"); + LibraryModules.ReactDOM = BDFDB.ModuleUtils.findByProperties("render", "findDOMNode"); + + BDFDB.ReactUtils = Object.assign({}, LibraryModules.React, LibraryModules.ReactDOM); + BDFDB.ReactUtils.childrenToArray = function (parent) { + if (parent && parent.props && parent.props.children && !BDFDB.ArrayUtils.is(parent.props.children)) { + var child = parent.props.children; + parent.props.children = []; + parent.props.children.push(child); + } + return parent.props.children; + } + BDFDB.ReactUtils.createElement = function (component, props = {}, errorWrap = false) { + if (component && component.defaultProps) for (let key in component.defaultProps) if (props[key] == null) props[key] = component.defaultProps[key]; + try { + let child = LibraryModules.React.createElement(component || "div", props) || null; + if (errorWrap) return LibraryModules.React.createElement(InternalComponents.ErrorBoundary, {}, child) || null; + else return child; + } + catch (err) {BDFDB.LogUtils.error("Could not create react element! " + err);} + return null; + }; + BDFDB.ReactUtils.objectToReact = function (obj) { + if (!obj) return null; + else if (typeof obj == "string") return obj; + else if (BDFDB.ObjectUtils.is(obj)) return BDFDB.ReactUtils.createElement(obj.type || obj.props && obj.props.href && "a" || "div", !obj.props ? {} : Object.assign({}, obj.props, { + children: obj.props.children ? BDFDB.ReactUtils.objectToReact(obj.props.children) : null + })); + else if (BDFDB.ArrayUtils.is(obj)) return obj.map(n => BDFDB.ReactUtils.objectToReact(n)); + else return null; + }; + BDFDB.ReactUtils.elementToReact = function (node, ref) { + if (BDFDB.ReactUtils.isValidElement(node)) return node; + else if (!Node.prototype.isPrototypeOf(node)) return null; + else if (node.nodeType == Node.TEXT_NODE) return node.nodeValue; + let attributes = {}, importantStyles = []; + if (typeof ref == "function") attributes.ref = ref; + for (let attr of node.attributes) attributes[attr.name] = attr.value; + if (node.attributes.style) attributes.style = BDFDB.ObjectUtils.filter(node.style, n => node.style[n] && isNaN(parseInt(n)), true); + attributes.children = []; + if (node.style && node.style.cssText) for (let propStr of node.style.cssText.split(";")) if (propStr.endsWith("!important")) { + let key = propStr.split(":")[0]; + let camelprop = key.replace(/-([a-z]?)/g, (m, g) => g.toUpperCase()); + if (attributes.style[camelprop] != null) importantStyles.push(key); + } + for (let child of node.childNodes) attributes.children.push(BDFDB.ReactUtils.elementToReact(child)); + attributes.className = BDFDB.DOMUtils.formatClassName(attributes.className, attributes.class); + delete attributes.class; + let reactEle = BDFDB.ReactUtils.createElement(node.tagName, attributes); + BDFDB.ReactUtils.forceStyle(reactEle, importantStyles); + return reactEle; + }; + BDFDB.ReactUtils.forceStyle = function (reactEle, styles) { + if (!BDFDB.ReactUtils.isValidElement(reactEle) || !BDFDB.ObjectUtils.is(reactEle.props.style) || !BDFDB.ArrayUtils.is(styles) || !styles.length) return null; + let ref = reactEle.ref; + reactEle.ref = instance => { + if (typeof ref == "function") ref(instance); + let node = BDFDB.ReactUtils.findDOMNode(instance); + if (Node.prototype.isPrototypeOf(node)) for (let key of styles) { + let propValue = reactEle.props.style[key.replace(/-([a-z]?)/g, (m, g) => g.toUpperCase())]; + if (propValue != null) node.style.setProperty(key, propValue, "important"); + } + }; + return reactEle; + }; + BDFDB.ReactUtils.findChild = function (nodeOrInstance, config) { + if (!nodeOrInstance || !BDFDB.ObjectUtils.is(config) || !config.name && !config.key && !config.props && !config.filter) return config.all ? [] : null; + let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance; + if (!BDFDB.ObjectUtils.is(instance) && !BDFDB.ArrayUtils.is(instance)) return null; + config.name = config.name && [config.name].flat().filter(n => n); + config.key = config.key && [config.key].flat().filter(n => n); + config.props = config.props && [config.props].flat().filter(n => n); + config.filter = typeof config.filter == "function" && config.filter; + let depth = -1; + let start = performance.now(); + let maxDepth = config.unlimited ? 999999999 : (config.depth === undefined ? 30 : config.depth); + let maxTime = config.unlimited ? 999999999 : (config.time === undefined ? 150 : config.time); + + let foundChildren = []; + let singleChild = getChild(instance); + if (config.all) { + for (let i in foundChildren) delete foundChildren[i].BDFDBreactSearch; + return foundChildren; + } + else return singleChild; + + function getChild (children) { + let result = null; + if (!children || depth >= maxDepth || performance.now() - start >= maxTime) return result; + if (!BDFDB.ArrayUtils.is(children)) { + if (check(children)) { + if (config.all === undefined || !config.all) result = children; + else if (config.all) { + if (!children.BDFDBreactSearch) { + children.BDFDBreactSearch = true; + foundChildren.push(children); + } + } + } + else if (children.props && children.props.children) { + depth++; + result = getChild(children.props.children); + depth--; + } + } + else { + for (let child of children) if (child) { + if (BDFDB.ArrayUtils.is(child)) result = getChild(child); + else if (check(child)) { + if (config.all === undefined || !config.all) result = child; + else if (config.all) { + if (!child.BDFDBreactSearch) { + child.BDFDBreactSearch = true; + foundChildren.push(child); + } + } + } + else if (child.props && child.props.children) { + depth++; + result = getChild(child.props.children); + depth--; + } + if (result) break; + } + } + return result; + } + function check (instance) { + if (!instance) return false; + let props = instance.stateNode ? instance.stateNode.props : instance.props; + return instance.type && config.name && config.name.some(name => BDFDB.ReactUtils.isCorrectInstance(instance, name)) || config.key && config.key.some(key => instance.key == key) || props && config.props && config.props[config.someProps ? "some" : "every"](prop => BDFDB.ArrayUtils.is(prop) ? (BDFDB.ArrayUtils.is(prop[1]) ? prop[1].some(checkValue => propCheck(props, prop[0], checkValue)) : propCheck(props, prop[0], prop[1])) : props[prop] !== undefined) || config.filter && config.filter(instance); + } + function propCheck (props, key, value) { + return key != null && props[key] != null && value != null && (key == "className" ? (" " + props[key] + " ").indexOf(" " + value + " ") > -1 : BDFDB.equals(props[key], value)); + } + }; + BDFDB.ReactUtils.setChild = function (parent, stringOrChild) { + if (!BDFDB.ReactUtils.isValidElement(parent) || (!BDFDB.ReactUtils.isValidElement(stringOrChild) && typeof stringOrChild != "string" && !BDFDB.ArrayUtils.is(stringOrChild))) return; + let set = false; + checkParent(parent); + function checkParent(child) { + if (set) return; + if (!BDFDB.ArrayUtils.is(child)) checkChild(child); + else for (let subChild of child) checkChild(subChild); + } + function checkChild(child) { + if (!BDFDB.ReactUtils.isValidElement(child)) return; + if (BDFDB.ReactUtils.isValidElement(child.props.children)) checkParent(child.props.children); + else if (BDFDB.ArrayUtils.is(child.props.children)) { + if (child.props.children.every(c => !c || typeof c == "string")) { + set = true; + child.props.children = [stringOrChild].flat(10); + } + else checkParent(child.props.children); + } + else { + set = true; + child.props.children = stringOrChild; + } + } + }; + BDFDB.ReactUtils.findConstructor = function (nodeOrInstance, types, config = {}) { + if (!BDFDB.ObjectUtils.is(config)) return null; + if (!nodeOrInstance || !types) return config.all ? (config.group ? {} : []) : null; + let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance; + if (!BDFDB.ObjectUtils.is(instance)) return config.all ? (config.group ? {} : []) : null; + types = types && [types].flat(10).filter(n => typeof n == "string"); + if (!types.length) return config.all ? (config.group ? {} : []) : null;; + let depth = -1; + let start = performance.now(); + let maxDepth = config.unlimited ? 999999999 : (config.depth === undefined ? 30 : config.depth); + let maxTime = config.unlimited ? 999999999 : (config.time === undefined ? 150 : config.time); + let whitelist = config.up ? {return:true, sibling:true, default:true, _reactInternalFiber:true} : {child:true, sibling:true, default:true, _reactInternalFiber:true}; + + let foundConstructors = config.group ? {} : []; + let singleConstructor = getConstructor(instance); + if (config.all) { + for (let i in foundConstructors) { + if (config.group) for (let j in foundConstructors[i]) delete foundConstructors[i][j].BDFDBreactSearch; + else delete foundConstructors[i].BDFDBreactSearch; + } + return foundConstructors; + } + else return singleConstructor; + + function getConstructor (instance) { + depth++; + let result = undefined; + if (instance && !Node.prototype.isPrototypeOf(instance) && !BDFDB.ReactUtils.getInstance(instance) && depth < maxDepth && performance.now() - start < maxTime) { + if (instance.type && types.some(name => BDFDB.ReactUtils.isCorrectInstance(instance, name.split(" _ _ ")[0]))) { + if (config.all === undefined || !config.all) result = instance.type; + else if (config.all) { + if (!instance.type.BDFDBreactSearch) { + instance.type.BDFDBreactSearch = true; + if (config.group) { + if (instance.type && (instance.type.render && instance.type.render.displayName || instance.type.displayName || instance.type.name)) { + let group = config.name.find(name => (instance.type.render && instance.type.render.displayName || instance.type.displayName || instance.type.name || instance.type) == name.split(" _ _ ")[0]) || "Default"; + if (!BDFDB.ArrayUtils.is(foundConstructors[group])) foundConstructors[group] = []; + foundConstructors[group].push(instance.stateNode); + } + } + else foundConstructors.push(instance.type); + } + } + } + if (result === undefined) { + let keys = Object.getOwnPropertyNames(instance); + for (let i = 0; result === undefined && i < keys.length; i++) { + let key = keys[i]; + if (key && whitelist[key] && (typeof instance[key] === "object" || typeof instance[key] === "function")) result = getConstructor(instance[key]); + } + } + } + depth--; + return result; + } + }; + BDFDB.ReactUtils.findDOMNode = function (instance) { + if (Node.prototype.isPrototypeOf(instance)) return instance; + if (!instance || !instance.updater || typeof instance.updater.isMounted !== "function" || !instance.updater.isMounted(instance)) return null; + let node = LibraryModules.ReactDOM.findDOMNode(instance) || BDFDB.ObjectUtils.get(instance, "child.stateNode"); + return Node.prototype.isPrototypeOf(node) ? node : null; + }; + BDFDB.ReactUtils.findOwner = function (nodeOrInstance, config) { + if (!BDFDB.ObjectUtils.is(config)) return null; + if (!nodeOrInstance || !config.name && !config.type && !config.key && !config.props) return config.all ? (config.group ? {} : []) : null; + let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance; + if (!BDFDB.ObjectUtils.is(instance)) return config.all ? (config.group ? {} : []) : null; + config.name = config.name && [config.name].flat().filter(n => n); + config.type = config.type && [config.type].flat().filter(n => n); + config.key = config.key && [config.key].flat().filter(n => n); + config.props = config.props && [config.props].flat().filter(n => n); + let depth = -1; + let start = performance.now(); + let maxDepth = config.unlimited ? 999999999 : (config.depth === undefined ? 30 : config.depth); + let maxTime = config.unlimited ? 999999999 : (config.time === undefined ? 150 : config.time); + let whitelist = config.up ? {return:true, sibling:true, _reactInternalFiber:true} : {child:true, sibling:true, _reactInternalFiber:true}; + + let foundInstances = config.group ? {} : []; + let singleInstance = getOwner(instance); + if (config.all) { + for (let i in foundInstances) { + if (config.group) for (let j in foundInstances[i]) delete foundInstances[i][j].BDFDBreactSearch; + else delete foundInstances[i].BDFDBreactSearch; + } + return foundInstances; + } + else return singleInstance; + + function getOwner (instance) { + depth++; + let result = undefined; + if (instance && !Node.prototype.isPrototypeOf(instance) && !BDFDB.ReactUtils.getInstance(instance) && depth < maxDepth && performance.now() - start < maxTime) { + let props = instance.stateNode ? instance.stateNode.props : instance.props; + if (instance.stateNode && !Node.prototype.isPrototypeOf(instance.stateNode) && (instance.type && config.name && config.name.some(name => BDFDB.ReactUtils.isCorrectInstance(instance, name.split(" _ _ ")[0])) || instance.type && config.type && config.type.some(type => BDFDB.ArrayUtils.is(type) ? instance.type === type[1] : instance.type === type) || instance.key && config.key && config.key.some(key => instance.key == key) || props && config.props && config.props.every(prop => BDFDB.ArrayUtils.is(prop) ? (BDFDB.ArrayUtils.is(prop[1]) ? prop[1].some(checkValue => BDFDB.equals(props[prop[0]], checkValue)) : BDFDB.equals(props[prop[0]], prop[1])) : props[prop] !== undefined))) { + if (config.all === undefined || !config.all) result = instance.stateNode; + else if (config.all) { + if (!instance.stateNode.BDFDBreactSearch) { + instance.stateNode.BDFDBreactSearch = true; + if (config.group) { + if (config.name && instance.type && (instance.type.render && instance.type.render.displayName || instance.type.displayName || instance.type.name || instance.type)) { + let group = config.name.find(name => (instance.type.render && instance.type.render.displayName || instance.type.displayName || instance.type.name || instance.type) == name.split(" _ _ ")[0]) || "Default"; + if (!BDFDB.ArrayUtils.is(foundInstances[group])) foundInstances[group] = []; + foundInstances[group].push(instance.stateNode); + } + else if (config.type && instance.type) { + let group = [config.type.find(t => BDFDB.ArrayUtils.is(t) && instance.type === t[1])].flat(10)[0] || "Default"; + if (!BDFDB.ArrayUtils.is(foundInstances[group])) foundInstances[group] = []; + foundInstances[group].push(instance.stateNode); + } + } + else foundInstances.push(instance.stateNode); + } + } + } + if (result === undefined) { + let keys = Object.getOwnPropertyNames(instance); + for (let i = 0; result === undefined && i < keys.length; i++) { + let key = keys[i]; + if (key && whitelist[key] && (typeof instance[key] === "object" || typeof instance[key] === "function")) result = getOwner(instance[key]); + } + } + } + depth--; + return result; + } + }; + BDFDB.ReactUtils.findParent = function (nodeOrInstance, config) { + if (!nodeOrInstance || !BDFDB.ObjectUtils.is(config) || !config.name && !config.key && !config.props && !config.filter) return [null, -1]; + let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance; + if (!BDFDB.ObjectUtils.is(instance) && !BDFDB.ArrayUtils.is(instance)) return [null, -1]; + config.name = config.name && [config.name].flat().filter(n => n); + config.key = config.key && [config.key].flat().filter(n => n); + config.props = config.props && [config.props].flat().filter(n => n); + config.filter = typeof config.filter == "function" && config.filter; + let parent = firstArray = instance; + while (!BDFDB.ArrayUtils.is(firstArray) && firstArray.props && firstArray.props.children) firstArray = firstArray.props.children; + if (!BDFDB.ArrayUtils.is(firstArray)) { + if (parent && parent.props) { + parent.props.children = [parent.props.children]; + firstArray = parent.props.children; + } + else firstArray = []; + } + return getParent(instance); + function getParent (children) { + let result = [firstArray, -1]; + if (!children) return result; + if (!BDFDB.ArrayUtils.is(children)) { + if (check(children)) result = found(children); + else if (children.props && children.props.children) { + parent = children; + result = getParent(children.props.children); + } + } + else { + for (let i = 0; result[1] == -1 && i < children.length; i++) if (children[i]) { + if (BDFDB.ArrayUtils.is(children[i])) { + parent = children; + result = getParent(children[i]); + } + else if (check(children[i])) { + parent = children; + result = found(children[i]); + } + else if (children[i].props && children[i].props.children) { + parent = children[i]; + result = getParent(children[i].props.children); + } + } + } + return result; + } + function found (child) { + if (BDFDB.ArrayUtils.is(parent)) return [parent, parent.indexOf(child)]; + else { + parent.props.children = []; + parent.props.children.push(child); + return [parent.props.children, 0]; + } + } + function check (instance) { + if (!instance) return false; + let props = instance.stateNode ? instance.stateNode.props : instance.props; + return instance.type && config.name && config.name.some(name => BDFDB.ReactUtils.isCorrectInstance(instance, name)) || config.key && config.key.some(key => instance.key == key) || props && config.props && config.props[config.someProps ? "some" : "every"](prop => BDFDB.ArrayUtils.is(prop) ? (BDFDB.ArrayUtils.is(prop[1]) ? prop[1].some(checkValue => propCheck(props, prop[0], checkValue)) : propCheck(props, prop[0], prop[1])) : props[prop] !== undefined) || config.filter && config.filter(instance); + } + function propCheck (props, key, value) { + return key != null && props[key] != null && value != null && (key == "className" ? (" " + props[key] + " ").indexOf(" " + value + " ") > -1 : BDFDB.equals(props[key], value)); + } + }; + BDFDB.ReactUtils.findProps = function (nodeOrInstance, config) { + if (!BDFDB.ObjectUtils.is(config)) return null; + if (!nodeOrInstance || !config.name && !config.key) return null; + let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance; + if (!BDFDB.ObjectUtils.is(instance)) return null; + config.name = config.name && [config.name].flat().filter(n => n); + config.key = config.key && [config.key].flat().filter(n => n); + let depth = -1; + let start = performance.now(); + let maxDepth = config.unlimited ? 999999999 : (config.depth === undefined ? 30 : config.depth); + let maxTime = config.unlimited ? 999999999 : (config.time === undefined ? 150 : config.time); + let whitelist = config.up ? {return:true, sibling:true, _reactInternalFiber:true} : {child:true, sibling:true, _reactInternalFiber:true}; + return findProps(instance); + + function findProps (instance) { + depth++; + let result = undefined; + if (instance && !Node.prototype.isPrototypeOf(instance) && !BDFDB.ReactUtils.getInstance(instance) && depth < maxDepth && performance.now() - start < maxTime) { + if (instance.memoizedProps && (instance.type && config.name && config.name.some(name => BDFDB.ReactUtils.isCorrectInstance(instance, name.split(" _ _ ")[0])) || config.key && config.key.some(key => instance.key == key))) result = instance.memoizedProps; + if (result === undefined) { + let keys = Object.getOwnPropertyNames(instance); + for (let i = 0; result === undefined && i < keys.length; i++) { + let key = keys[i]; + if (key && whitelist[key] && (typeof instance[key] === "object" || typeof instance[key] === "function")) result = findProps(instance[key]); + } + } + } + depth--; + return result; + } + }; + BDFDB.ReactUtils.findValue = function (nodeOrInstance, searchKey, config = {}) { + if (!BDFDB.ObjectUtils.is(config)) return null; + if (!nodeOrInstance || typeof searchKey != "string") return config.all ? [] : null; + let instance = Node.prototype.isPrototypeOf(nodeOrInstance) ? BDFDB.ReactUtils.getInstance(nodeOrInstance) : nodeOrInstance; + if (!BDFDB.ObjectUtils.is(instance)) return config.all ? [] : null; + instance = instance._reactInternalFiber || instance; + let depth = -1; + let start = performance.now(); + let maxDepth = config.unlimited ? 999999999 : (config.depth === undefined ? 30 : config.depth); + let maxTime = config.unlimited ? 999999999 : (config.time === undefined ? 150 : config.time); + let whitelist = { + props: true, + state: true, + stateNode: true, + updater: true, + prototype: true, + type: true, + children: config.up ? false : true, + memoizedProps: true, + memoizedState: true, + child: config.up ? false : true, + return: config.up ? true : false, + sibling: config.up ? false : true + }; + let blacklist = { + contextSection: true + }; + if (BDFDB.ObjectUtils.is(config.whitelist)) Object.assign(whitelist, config.whiteList); + if (BDFDB.ObjectUtils.is(config.blacklist)) Object.assign(blacklist, config.blacklist); + let foundKeys = []; + let singleKey = getKey(instance); + if (config.all) return foundKeys; + else return singleKey; + function getKey(instance) { + depth++; + let result = undefined; + if (instance && !Node.prototype.isPrototypeOf(instance) && !BDFDB.ReactUtils.getInstance(instance) && depth < maxDepth && performance.now() - start < maxTime) { + let keys = Object.getOwnPropertyNames(instance); + for (let i = 0; result === undefined && i < keys.length; i++) { + let key = keys[i]; + if (key && !blacklist[key]) { + let value = instance[key]; + if (searchKey === key && (config.value === undefined || BDFDB.equals(config.value, value))) { + if (config.all === undefined || !config.all) result = value; + else if (config.all) { + if (config.noCopies === undefined || !config.noCopies) foundKeys.push(value); + else if (config.noCopies) { + let copy = false; + for (let foundKey of foundKeys) if (BDFDB.equals(value, foundKey)) { + copy = true; + break; + } + if (!copy) foundKeys.push(value); + } + } + } + else if ((typeof value === "object" || typeof value === "function") && (whitelist[key] || key[0] == "." || !isNaN(key[0]))) result = getKey(value); + } + } + } + depth--; + return result; + } + }; + BDFDB.ReactUtils.forceUpdate = function (...instances) { + for (let ins of instances.flat(10).filter(n => n)) if (ins.updater && typeof ins.updater.isMounted == "function" && ins.updater.isMounted(ins)) ins.forceUpdate(); + }; + BDFDB.ReactUtils.getInstance = function (node) { + if (!BDFDB.ObjectUtils.is(node)) return null; + return node[Object.keys(node).find(key => key.startsWith("__reactInternalInstance"))]; + }; + BDFDB.ReactUtils.isCorrectInstance = function (instance, name) { + return instance && ((instance.type && (instance.type.render && instance.type.render.displayName === name || instance.type.displayName === name || instance.type.name === name || instance.type === name)) || instance.render && (instance.render.displayName === name || instance.render.name === name) || instance.displayName == name || instance.name === name); + }; + BDFDB.ReactUtils.render = function (component, node) { + if (!BDFDB.ReactUtils.isValidElement(component) || !Node.prototype.isPrototypeOf(node)) return; + try { + LibraryModules.ReactDOM.render(component, node); + let observer = new MutationObserver(changes => changes.forEach(change => { + let nodes = Array.from(change.removedNodes); + if (nodes.indexOf(node) > -1 || nodes.some(n => n.contains(node))) { + observer.disconnect(); + BDFDB.ReactUtils.unmountComponentAtNode(node); + } + })); + observer.observe(document.body, {subtree:true, childList:true}); + } + catch (err) {BDFDB.LogUtils.error("Could not render react element! " + err);} + }; + + let MessageRerenderTimeout; + BDFDB.MessageUtils = {}; + BDFDB.MessageUtils.rerenderAll = function (instant) { + BDFDB.TimeUtils.clear(MessageRerenderTimeout); + MessageRerenderTimeout = BDFDB.TimeUtils.timeout(_ => { + let LayerProviderIns = BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.messageswrapper), {name:"LayerProvider", unlimited:true, up:true}); + let LayerProviderPrototype = BDFDB.ObjectUtils.get(LayerProviderIns, "_reactInternalFiber.type.prototype"); + if (LayerProviderIns && LayerProviderPrototype) { + BDFDB.PatchUtils.patch(BDFDB, LayerProviderPrototype, "render", {after: e => { + e.returnValue.props.children = []; + }}, {once: true}); + BDFDB.ReactUtils.forceUpdate(LayerProviderIns); + } + }, instant ? 0 : 1000); + }; + + BDFDB.UserUtils = {}; + BDFDB.UserUtils.is = function (user) { + return user && user instanceof BDFDB.DiscordObjects.User; + }; + var myDataUser = LibraryModules.CurrentUserStore && LibraryModules.CurrentUserStore.getCurrentUser(); + BDFDB.UserUtils.me = new Proxy(myDataUser || {}, { + get: function (list, item) { + return (myDataUser = LibraryModules.CurrentUserStore.getCurrentUser()) && myDataUser[item]; + } + }); + BDFDB.UserUtils.getStatus = function (id = BDFDB.UserUtils.me.id) { + id = typeof id == "number" ? id.toFixed() : id; + let activity = BDFDB.UserUtils.getActivitiy(id); + return activity && activity.type == BDFDB.DiscordConstants.ActivityTypes.STREAMING ? "streaming" : LibraryModules.StatusMetaUtils.getStatus(id); + }; + BDFDB.UserUtils.getStatusColor = function (status) { + status = typeof status == "string" ? status.toLowerCase() : null; + switch (status) { + case "online": return BDFDB.DiscordConstants.Colors.STATUS_GREEN; + case "mobile": return BDFDB.DiscordConstants.Colors.STATUS_GREEN; + case "idle": return BDFDB.DiscordConstants.Colors.STATUS_YELLOW; + case "dnd": return BDFDB.DiscordConstants.Colors.STATUS_RED; + case "playing": return BDFDB.DiscordConstants.Colors.BRAND; + case "listening": return BDFDB.DiscordConstants.Colors.SPOTIFY; + case "streaming": return BDFDB.DiscordConstants.Colors.TWITCH; + default: return BDFDB.DiscordConstants.Colors.STATUS_GREY; + } + }; + BDFDB.UserUtils.getActivitiy = function (id = BDFDB.UserUtils.me.id) { + for (let activity of LibraryModules.StatusMetaUtils.getActivities(id)) if (activity.type != BDFDB.DiscordConstants.ActivityTypes.CUSTOM_STATUS) return activity; + return null; + }; + BDFDB.UserUtils.getAvatar = function (id = BDFDB.UserUtils.me.id) { + let user = LibraryModules.UserStore.getUser(typeof id == "number" ? id.toFixed() : id); + if (!user) return window.location.origin + "/assets/322c936a8c8be1b803cd94861bdfa868.png"; + else return ((user.avatar ? "" : window.location.origin) + LibraryModules.IconUtils.getUserAvatarURL(user)).split("?")[0]; + }; + BDFDB.UserUtils.can = function (permission, id = BDFDB.UserUtils.me.id, channelId = LibraryModules.LastChannelStore.getChannelId()) { + if (!BDFDB.DiscordConstants.Permissions[permission]) BDFDB.LogUtils.warn(permission + " not found in Permissions"); + else { + let channel = LibraryModules.ChannelStore.getChannel(channelId); + if (channel) return LibraryModules.PermissionRoleUtils.can(BDFDB.DiscordConstants.Permissions[permission], id, channel); + } + return false; + }; + BDFDB.UserUtils.openMenu = function (id, guildId, e = mousePosition) { + if (!id || !guildId) return; + let user = LibraryModules.UserStore.getUser(id); + if (user) LibraryModules.ContextMenuUtils.openContextMenu(e, function (e) { + return BDFDB.ReactUtils.createElement((BDFDB.ModuleUtils.findByName("GuildChannelUserContextMenu", false) || {exports:{}}).exports.default, Object.assign({}, e, { + user: user, + guildId: guildId + })); + }); + }; + + let GuildsRerenderTimeout; + BDFDB.GuildUtils = {}; + BDFDB.GuildUtils.is = function (guild) { + if (!BDFDB.ObjectUtils.is(guild)) return false; + let keys = Object.keys(guild); + return guild instanceof BDFDB.DiscordObjects.Guild || Object.keys(new BDFDB.DiscordObjects.Guild({})).every(key => keys.indexOf(key) > -1); + }; + BDFDB.GuildUtils.getIcon = function (id) { + let guild = LibraryModules.GuildStore.getGuild(typeof id == "number" ? id.toFixed() : id); + if (!guild || !guild.icon) return null; + return LibraryModules.IconUtils.getGuildIconURL(guild).split("?")[0]; + }; + BDFDB.GuildUtils.getBanner = function (id) { + let guild = LibraryModules.GuildStore.getGuild(typeof id == "number" ? id.toFixed() : id); + if (!guild || !guild.banner) return null; + return LibraryModules.IconUtils.getGuildBannerURL(guild).split("?")[0]; + }; + BDFDB.GuildUtils.getFolder = function (id) { + return BDFDB.LibraryModules.FolderStore.guildFolders.filter(n => n.folderId).find(n => n.guildIds.includes(id)); + }; + BDFDB.GuildUtils.getId = function (div) { + if (!Node.prototype.isPrototypeOf(div) || !BDFDB.ReactUtils.getInstance(div)) return; + let guilddiv = BDFDB.DOMUtils.getParent(BDFDB.dotCN.guildouter, div); + if (!guilddiv) return; + let iconWrap = guilddiv.querySelector(BDFDB.dotCN.guildiconwrapper); + let id = iconWrap && iconWrap.href ? iconWrap.href.split("/").slice(-2)[0] : null; + return id && !isNaN(parseInt(id)) ? id.toString() : null; + }; + BDFDB.GuildUtils.getData = function (eleOrInfoOrId) { + if (!eleOrInfoOrId) return null; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.GuildUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + id = typeof id == "number" ? id.toFixed() : id; + for (let info of BDFDB.GuildUtils.getAll()) if (info && info.id == id) return info; + return null; + }; + BDFDB.GuildUtils.getAll = function () { + let found = [], objs = []; + for (let ins of BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.guilds), {name:["Guild","GuildIcon"], all:true, unlimited:true})) { + if (ins.props && ins.props.guild) objs.push(Object.assign(new ins.props.guild.constructor(ins.props.guild), {div:ins.handleContextMenu && BDFDB.ReactUtils.findDOMNode(ins), instance:ins})); + } + for (let id of BDFDB.LibraryModules.FolderStore.getFlattenedGuildIds()) { + let foundobj = null; + for (let obj of objs) if (obj.id == id) { + foundobj = obj + break; + } + if (foundobj) found.push(foundobj); + else { + let guild = BDFDB.LibraryModules.GuildStore.getGuild(id); + if (guild) found.push(Object.assign(new guild.constructor(guild), {div:null, instance:null})) + } + } + return found; + }; + BDFDB.GuildUtils.getUnread = function (servers) { + let found = []; + for (let eleOrInfoOrId of servers === undefined || !BDFDB.ArrayUtils.is(servers) ? BDFDB.GuildUtils.getAll() : servers) { + if (!eleOrInfoOrId) return null; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.GuildUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + id = typeof id == "number" ? id.toFixed() : id; + if (id && (LibraryModules.UnreadGuildUtils.hasUnread(id) || LibraryModules.UnreadGuildUtils.getMentionCount(id) > 0)) found.push(eleOrInfoOrId); + } + return found; + }; + BDFDB.GuildUtils.getPinged = function (servers) { + let found = []; + for (let eleOrInfoOrId of servers === undefined || !BDFDB.ArrayUtils.is(servers) ? BDFDB.GuildUtils.getAll() : servers) { + if (!eleOrInfoOrId) return null; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.GuildUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + id = typeof id == "number" ? id.toFixed() : id; + if (id && LibraryModules.UnreadGuildUtils.getMentionCount(id) > 0) found.push(eleOrInfoOrId); + } + return found; + }; + BDFDB.GuildUtils.getMuted = function (servers) { + let found = []; + for (let eleOrInfoOrId of servers === undefined || !BDFDB.ArrayUtils.is(servers) ? BDFDB.GuildUtils.getAll() : servers) { + if (!eleOrInfoOrId) return null; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.GuildUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + id = typeof id == "number" ? id.toFixed() : id; + if (id && LibraryModules.MutedUtils.isGuildOrCategoryOrChannelMuted(id)) found.push(eleOrInfoOrId); + } + return found; + }; + BDFDB.GuildUtils.getSelected = function () { + let info = LibraryModules.GuildStore.getGuild(LibraryModules.LastGuildStore.getGuildId()); + if (info) return BDFDB.GuildUtils.getData(info.id) || Object.assign(new info.constructor(info), {div:null, instance:null}); + else return null; + }; + BDFDB.GuildUtils.openMenu = function (eleOrInfoOrId, e = mousePosition) { + if (!eleOrInfoOrId) return; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.GuildUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + let guild = LibraryModules.GuildStore.getGuild(id); + if (guild) LibraryModules.ContextMenuUtils.openContextMenu(e, function (e) { + return BDFDB.ReactUtils.createElement((BDFDB.ModuleUtils.findByName("GuildContextMenu", false) || {exports:{}}).exports.default, Object.assign({}, e, { + guild: guild + })); + }); + }; + BDFDB.GuildUtils.markAsRead = function (guilds) { + if (!guilds) return; + let unreadChannels = []; + for (let guild of BDFDB.ArrayUtils.is(guilds) ? guilds : (typeof guilds == "string" || typeof guilds == "number" ? Array.of(guilds) : Array.from(guilds))) { + let id = Node.prototype.isPrototypeOf(guild) ? BDFDB.GuildUtils.getId(guild) : (guild && typeof guild == "object" ? guild.id : guild); + let channels = id && LibraryModules.GuildChannelStore.getChannels(id); + if (channels) for (let type in channels) if (BDFDB.ArrayUtils.is(channels[type])) for (let channelObj of channels[type]) unreadChannels.push(channelObj.channel.id); + } + if (unreadChannels.length) BDFDB.ChannelUtils.markAsRead(unreadChannels); + }; + BDFDB.GuildUtils.rerenderAll = function (instant) { + BDFDB.TimeUtils.clear(GuildsRerenderTimeout); + GuildsRerenderTimeout = BDFDB.TimeUtils.timeout(_ => { + let GuildsIns = BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.app), {name:"Guilds", unlimited:true}); + let GuildsPrototype = BDFDB.ObjectUtils.get(GuildsIns, "_reactInternalFiber.type.prototype"); + if (GuildsIns && GuildsPrototype) { + BDFDB.PatchUtils.patch(BDFDB, GuildsPrototype, "render", {after: e => { + let [children, index] = BDFDB.ReactUtils.findParent(e.returnValue, {name: "ConnectedUnreadDMs"}); + if (index > -1) children.splice(index + 1, 0, BDFDB.ReactUtils.createElement("div", {})); + BDFDB.ReactUtils.forceUpdate(GuildsIns); + }}, {once: true}); + BDFDB.ReactUtils.forceUpdate(GuildsIns); + } + }, instant ? 0 : 1000); + }; + + BDFDB.FolderUtils = {}; + BDFDB.FolderUtils.getId = function (div) { + if (!Node.prototype.isPrototypeOf(div) || !BDFDB.ReactUtils.getInstance(div)) return; + div = BDFDB.DOMUtils.getParent(BDFDB.dotCN.guildfolderwrapper, div); + if (!div) return; + return BDFDB.ReactUtils.findValue(div, "folderId", {up:true}); + }; + BDFDB.FolderUtils.getDefaultName = function (folderId) { + let folder = BDFDB.LibraryModules.FolderStore.getGuildFolderById(folderId); + if (!folder) return ""; + let rest = 2 * BDFDB.DiscordConstants.MAX_GUILD_FOLDER_NAME_LENGTH; + let names = [], allNames = folder.guildIds.map(guildId => (BDFDB.LibraryModules.GuildStore.getGuild(guildId) || {}).name).filter(n => n); + for (let name of allNames) if (name.length < rest || names.length === 0) { + names.push(name); + rest -= name.length; + } + return names.join(", ") + (names.length < allNames.length ? ", ..." : ""); + }; + BDFDB.FolderUtils.getDiv = function (eleOrInfoOrId) { + if (!eleOrInfoOrId) return null; + let info = BDFDB.FolderUtils.getData(eleOrInfoOrId); + return info ? info.div : null; + }; + BDFDB.FolderUtils.getData = function (eleOrInfoOrId) { + if (!eleOrInfoOrId) return null; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.FolderUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + id = typeof id == "number" ? id.toFixed() : id; + for (let info of BDFDB.FolderUtils.getAll()) if (info && info.folderId == id) return info; + return null; + }; + BDFDB.FolderUtils.getAll = function () { + let found = []; + for (let ins of BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.guildswrapper), {name:"GuildFolder", all:true, unlimited:true})) { + if (ins.props && ins.props.folderId) found.push(Object.assign({}, ins.props, {div:BDFDB.ReactUtils.findDOMNode(ins), instance:ins})); + } + return found; + }; + + BDFDB.ChannelUtils = {}; + BDFDB.ChannelUtils.is = function (channel) { + if (!BDFDB.ObjectUtils.is(channel)) return false; + let keys = Object.keys(channel); + return channel instanceof BDFDB.DiscordObjects.Channel || Object.keys(new BDFDB.DiscordObjects.Channel({})).every(key => keys.indexOf(key) > -1); + }; + BDFDB.ChannelUtils.isTextChannel = function (channelOrId) { + let channel = typeof channelOrId == "string" ? LibraryModules.ChannelStore.getChannel(channelOrId) : channelOrId; + return BDFDB.ObjectUtils.is(channel) && (channel.type == BDFDB.DiscordConstants.ChannelTypes.GUILD_TEXT || channel.type == BDFDB.DiscordConstants.ChannelTypes.GUILD_STORE || channel.type == BDFDB.DiscordConstants.ChannelTypes.GUILD_ANNOUNCEMENT); + }; + BDFDB.ChannelUtils.getId = function (div) { + if (!Node.prototype.isPrototypeOf(div) || !BDFDB.ReactUtils.getInstance(div)) return; + div = BDFDB.DOMUtils.getParent(BDFDB.dotCNC.categorycontainerdefault + BDFDB.dotCNC.channelcontainerdefault + BDFDB.dotCN.dmchannel, div); + if (!div) return; + let info = BDFDB.ReactUtils.findValue(div, "channel"); + return info ? info.id.toString() : null; + }; + BDFDB.ChannelUtils.getDiv = function (eleOrInfoOrId) { + if (!eleOrInfoOrId) return null; + let info = BDFDB.ChannelUtils.getData(eleOrInfoOrId); + return info ? info.div : null; + }; + BDFDB.ChannelUtils.getData = function (eleOrInfoOrId) { + if (!eleOrInfoOrId) return null; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.ChannelUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + id = typeof id == "number" ? id.toFixed() : id; + for (let info of BDFDB.ChannelUtils.getAll()) if (info && info.id == id) return info; + return null; + }; + BDFDB.ChannelUtils.getName = function (id, addPrefix) { + let channel = BDFDB.LibraryModules.ChannelStore.getChannel(id); + if (!channel) return ""; + switch (channel.type) { + case BDFDB.DiscordConstants.ChannelTypes.DM: + let user = channel.recipients.map(BDFDB.LibraryModules.UserStore.getUser).filter(n => n)[0]; + return (addPrefix && "@" || "") + (user && user.toString() || ""); + case BDFDB.DiscordConstants.ChannelTypes.GROUP_DM: + if (channel.name) return channel.name; + let users = channel.recipients.map(BDFDB.LibraryModules.UserStore.getUser).filter(n => n); + return users.length > 0 ? users.map(user => user.toString).join(", ") : BDFDB.LanguageUtils.LanguageStrings.UNNAMED; + case BDFDB.DiscordConstants.ChannelTypes.GUILD_ANNOUNCEMENT: + case BDFDB.DiscordConstants.ChannelTypes.GUILD_TEXT: + return (addPrefix && "#" || "") + channel.name; + default: + return channel.name + } + }; + BDFDB.ChannelUtils.getAll = function () { + let found = []; + for (let ins of BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.channels), {name: ["ChannelCategoryItem", "ChannelItem", "PrivateChannel"], all:true, unlimited:true})) if (ins.props && !ins.props.ispin && ins.props.channel && ins._reactInternalFiber.return) { + let div = BDFDB.ReactUtils.findDOMNode(ins); + div = div && BDFDB.DOMUtils.containsClass(div.parentElement, BDFDB.disCN.categorycontainerdefault, BDFDB.disCN.channelcontainerdefault, false) ? div.parentElement : div; + found.push(Object.assign(new ins.props.channel.constructor(ins.props.channel), {div, instance:ins})); + } + return found; + }; + BDFDB.ChannelUtils.getSelected = function () { + let info = LibraryModules.ChannelStore.getChannel(LibraryModules.LastChannelStore.getChannelId()); + if (info) return BDFDB.ChannelUtils.getData(info.id) || Object.assign(new info.constructor(info), {div:null, instance:null}); + else return null; + }; + BDFDB.ChannelUtils.markAsRead = function (channels) { + if (!channels) return; + let unreadChannels = []; + for (let channel of channels = BDFDB.ArrayUtils.is(channels) ? channels : (typeof channels == "string" || typeof channels == "number" ? Array.of(channels) : Array.from(channels))) { + let id = Node.prototype.isPrototypeOf(channel) ? BDFDB.ChannelUtils.getId(channel) : (channel && typeof channel == "object" ? channel.id : channel); + if (id && BDFDB.ChannelUtils.isTextChannel(id)) unreadChannels.push({ + channelId: id, + messageId: LibraryModules.UnreadChannelUtils.lastMessageId(id) + }); + } + if (unreadChannels.length) LibraryModules.AckUtils.bulkAck(unreadChannels); + }; + + BDFDB.DMUtils = {}; + BDFDB.DMUtils.isDMChannel = function (channelOrId) { + let channel = typeof channelOrId == "string" ? LibraryModules.ChannelStore.getChannel(channelOrId) : channelOrId; + return BDFDB.ObjectUtils.is(channel) && (channel.type == BDFDB.DiscordConstants.ChannelTypes.DM || channel.type == BDFDB.DiscordConstants.ChannelTypes.GROUP_DM); + }; + BDFDB.DMUtils.getIcon = function (id) { + let channel = LibraryModules.ChannelStore.getChannel(id = typeof id == "number" ? id.toFixed() : id); + if (!channel) return null; + if (!channel.icon) return channel.type == 1 ? BDFDB.UserUtils.getAvatar(channel.recipients[0]) : (channel.type == 3 ? window.location.origin + LibraryModules.IconUtils.getChannelIconURL(channel).split("?")[0] : null); + return LibraryModules.IconUtils.getChannelIconURL(channel).split("?")[0]; + }; + BDFDB.DMUtils.getId = function (div) { + if (!Node.prototype.isPrototypeOf(div) || !BDFDB.ReactUtils.getInstance(div)) return; + let dmdiv = BDFDB.DOMUtils.getParent(BDFDB.dotCN.guildouter, div); + if (!dmdiv) return; + let iconWrap = dmdiv.querySelector(BDFDB.dotCN.guildiconwrapper); + let id = iconWrap && iconWrap.href ? iconWrap.href.split("/").slice(-1)[0] : null; + return id && !isNaN(parseInt(id)) ? id.toString() : null; + }; + BDFDB.DMUtils.getDiv = function (eleOrInfoOrId) { + if (!eleOrInfoOrId) return null; + if (Node.prototype.isPrototypeOf(eleOrInfoOrId)) { + var div = BDFDB.DOMUtils.getParent(BDFDB.dotCN.guildouter, eleOrInfoOrId); + return div ? div.parentElement : div; + } + else { + let id = typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId; + if (id) { + var div = BDFDB.DOMUtils.getParent(BDFDB.dotCN.guildouter, document.querySelector(`${BDFDB.dotCNS.guilds + BDFDB.dotCN.dmpill + " + * " + BDFDB.dotCN.guildiconwrapper}[href*="/channels/@me/${id}"]`)); + return div && BDFDB? div.parentElement : div; + } + } + return null; + }; + BDFDB.DMUtils.getData = function (eleOrInfoOrId) { + if (!eleOrInfoOrId) return null; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.BDFDB.DMUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + id = typeof id == "number" ? id.toFixed() : id; + for (let info of BDFDB.DMUtils.getAll()) if (info && info.id == id) return info; + return null; + }; + BDFDB.DMUtils.getAll = function () { + let found = []; + for (let ins of BDFDB.ReactUtils.findOwner(document.querySelector(BDFDB.dotCN.guilds), {name:"DirectMessage", all:true, unlimited:true})) { + if (ins.props && ins.props.channel) found.push(Object.assign(new ins.props.channel.constructor(ins.props.channel), {div:BDFDB.ReactUtils.findDOMNode(ins), instance:ins})); + } + return found; + }; + BDFDB.DMUtils.openMenu = function (eleOrInfoOrId, e = mousePosition) { + if (!eleOrInfoOrId) return; + let id = Node.prototype.isPrototypeOf(eleOrInfoOrId) ? BDFDB.ChannelUtils.getId(eleOrInfoOrId) : (typeof eleOrInfoOrId == "object" ? eleOrInfoOrId.id : eleOrInfoOrId); + let channel = LibraryModules.ChannelStore.getChannel(id); + if (channel) { + if (channel.isMultiUserDM()) LibraryModules.ContextMenuUtils.openContextMenu(e, function (e) { + return BDFDB.ReactUtils.createElement((BDFDB.ModuleUtils.findByName("GroupDMContextMenu", false) || {exports:{}}).exports.default, Object.assign({}, e, { + channel: channel, + selected: channel.id == LibraryModules.LastChannelStore.getChannelId() + })); + }); + else LibraryModules.ContextMenuUtils.openContextMenu(e, function (e) { + return BDFDB.ReactUtils.createElement((BDFDB.ModuleUtils.findByName("DMUserContextMenu", false) || {exports:{}}).exports.default, Object.assign({}, e, { + user: LibraryModules.UserStore.getUser(channel.recipients[0]), + channel: channel, + selected: channel.id == LibraryModules.LastChannelStore.getChannelId() + })); + }); + } + }; + BDFDB.DMUtils.markAsRead = function (dms) { + if (!dms) return; + let unreadChannels = []; + for (let dm of dms = BDFDB.ArrayUtils.is(dms) ? dms : (typeof dms == "string" || typeof dms == "number" ? Array.of(dms) : Array.from(dms))) { + let id = Node.prototype.isPrototypeOf(dm) ? BDFDB.BDFDB.DMUtils.getId(dm) : (dm && typeof dm == "object" ? dm.id : dm); + if (id) unreadChannels.push(id); + } + for (let i in unreadChannels) BDFDB.TimeUtils.timeout(_ => {LibraryModules.AckUtils.ack(unreadChannels[i]);}, i * 1000); + }; + + InternalBDFDB.writeConfig = function (path, config) { + try {LibraryRequires.fs.writeFileSync(path, JSON.stringify(config, null, " "));} + catch (err) {} + }; + InternalBDFDB.readConfig = function (path) { + try {return JSON.parse(LibraryRequires.fs.readFileSync(path));} + catch (err) {return {};} + }; + + BDFDB.DataUtils = {}; + BDFDB.DataUtils.save = function (data, plugin, key, id) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + let pluginName = typeof plugin === "string" ? plugin : plugin.name; + let configPath = LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), pluginName + ".config.json"); + + let config = Cache.data[pluginName] !== undefined ? Cache.data[pluginName] : (InternalBDFDB.readConfig(configPath) || {}); + + if (key === undefined) config = BDFDB.ObjectUtils.is(data) ? BDFDB.ObjectUtils.sort(data) : data; + else { + if (id === undefined) config[key] = BDFDB.ObjectUtils.is(data) ? BDFDB.ObjectUtils.sort(data) : data; + else { + if (!BDFDB.ObjectUtils.is(config[key])) config[key] = {}; + config[key][id] = BDFDB.ObjectUtils.is(data) ? BDFDB.ObjectUtils.sort(data) : data; + } + } + + let configIsObject = BDFDB.ObjectUtils.is(config); + if (key !== undefined && configIsObject && BDFDB.ObjectUtils.is(config[key]) && BDFDB.ObjectUtils.isEmpty(config[key])) delete config[key]; + if (BDFDB.ObjectUtils.isEmpty(config)) { + delete Cache.data[pluginName]; + if (LibraryRequires.fs.existsSync(configPath)) LibraryRequires.fs.unlinkSync(configPath); + } + else { + if (configIsObject) config = BDFDB.ObjectUtils.sort(config); + Cache.data[pluginName] = configIsObject ? BDFDB.ObjectUtils.deepAssign({}, config) : config; + InternalBDFDB.writeConfig(configPath, config); + } + }; + + BDFDB.DataUtils.load = function (plugin, key, id) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + let pluginName = typeof plugin === "string" ? plugin : plugin.name; + let configPath = LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), pluginName + ".config.json"); + + let config = Cache.data[pluginName] !== undefined ? Cache.data[pluginName] : (InternalBDFDB.readConfig(configPath) || {}); + let configIsObject = BDFDB.ObjectUtils.is(config); + Cache.data[pluginName] = configIsObject ? BDFDB.ObjectUtils.deepAssign({}, config) : config; + + if (key === undefined) return config; + else { + let keydata = configIsObject ? (BDFDB.ObjectUtils.is(config[key]) || config[key] == undefined ? BDFDB.ObjectUtils.deepAssign({}, config[key]) : config[key]) : null; + if (id === undefined) return keydata; + else return !BDFDB.ObjectUtils.is(keydata) || keydata[id] === undefined ? null : keydata[id]; + } + }; + BDFDB.DataUtils.remove = function (plugin, key, id) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + let pluginName = typeof plugin === "string" ? plugin : plugin.name; + let configPath = LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), pluginName + ".config.json"); + + let config = Cache.data[pluginName] !== undefined ? Cache.data[pluginName] : (InternalBDFDB.readConfig(configPath) || {}); + let configIsObject = BDFDB.ObjectUtils.is(config); + + if (key === undefined || !configIsObject) config = {}; + else { + if (id === undefined) delete config[key]; + else if (BDFDB.ObjectUtils.is(config[key])) delete config[key][id]; + } + + if (BDFDB.ObjectUtils.is(config[key]) && BDFDB.ObjectUtils.isEmpty(config[key])) delete config[key]; + if (BDFDB.ObjectUtils.isEmpty(config)) { + delete Cache.data[pluginName]; + if (LibraryRequires.fs.existsSync(configPath)) LibraryRequires.fs.unlinkSync(configPath); + } + else { + if (configIsObject) config = BDFDB.ObjectUtils.sort(config); + Cache.data[pluginName] = configIsObject ? BDFDB.ObjectUtils.deepAssign({}, config) : config; + InternalBDFDB.writeConfig(configPath, config); + } + }; + BDFDB.DataUtils.get = function (plugin, key, id) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + plugin = typeof plugin == "string" ? BDFDB.BDUtils.getPlugin(plugin) : plugin; + if (!BDFDB.ObjectUtils.is(plugin)) return id === undefined ? {} : null; + let defaults = plugin.defaults; + if (!BDFDB.ObjectUtils.is(defaults) || !defaults[key]) return id === undefined ? {} : null; + let oldC = BDFDB.DataUtils.load(plugin, key), newC = {}, update = false; + for (let k in defaults[key]) { + let isObj = BDFDB.ObjectUtils.is(defaults[key][k].value); + if (oldC[k] == null || isObj && (!BDFDB.ObjectUtils.is(oldC[k]) || Object.keys(defaults[key][k].value).some(n => defaults[key][k].value[n] != null && !BDFDB.sameProto(defaults[key][k].value[n], oldC[k][n])))) { + newC[k] = isObj ? BDFDB.ObjectUtils.deepAssign({}, defaults[key][k].value) : defaults[key][k].value; + update = true; + } + else newC[k] = oldC[k]; + } + if (update) BDFDB.DataUtils.save(newC, plugin, key); + + if (id === undefined) return newC; + else return newC[id] === undefined ? null : newC[id]; + }; + + BDFDB.ColorUtils = {}; + BDFDB.ColorUtils.convert = function (color, conv, type) { + if (BDFDB.ObjectUtils.is(color)) { + var newColor = {}; + for (let pos in color) newColor[pos] = BDFDB.ColorUtils.convert(color[pos], conv, type); + return newColor; + } + else { + conv = conv === undefined || !conv ? conv = "RGBCOMP" : conv.toUpperCase(); + type = type === undefined || !type || !["RGB", "RGBA", "RGBCOMP", "HSL", "HSLA", "HSLCOMP", "HEX", "HEXA", "INT"].includes(type.toUpperCase()) ? BDFDB.ColorUtils.getType(color) : type.toUpperCase(); + if (conv == "RGBCOMP") { + switch (type) { + case "RGBCOMP": + if (color.length == 3) return processRGB(color); + else if (color.length == 4) { + let a = processA(color.pop()); + return processRGB(color).concat(a); + } + break; + case "RGB": + return processRGB(color.replace(/\s/g, "").slice(4, -1).split(",")); + case "RGBA": + let comp = color.replace(/\s/g, "").slice(5, -1).split(","); + let a = processA(comp.pop()); + return processRGB(comp).concat(a); + case "HSLCOMP": + if (color.length == 3) return BDFDB.ColorUtils.convert(`hsl(${processHSL(color).join(",")})`, "RGBCOMP"); + else if (color.length == 4) { + let a = processA(color.pop()); + return BDFDB.ColorUtils.convert(`hsl(${processHSL(color).join(",")})`, "RGBCOMP").concat(a); + } + break; + case "HSL": + var hslcomp = processHSL(color.replace(/\s/g, "").slice(4, -1).split(",")); + var r, g, b, m, c, x, p, q; + var h = hslcomp[0] / 360, l = parseInt(hslcomp[1]) / 100, s = parseInt(hslcomp[2]) / 100; m = Math.floor(h * 6); c = h * 6 - m; x = s * (1 - l); p = s * (1 - c * l); q = s * (1 - (1 - c) * l); + switch (m % 6) { + case 0: r = s, g = q, b = x; break; + case 1: r = p, g = s, b = x; break; + case 2: r = x, g = s, b = q; break; + case 3: r = x, g = p, b = s; break; + case 4: r = q, g = x, b = s; break; + case 5: r = s, g = x, b = p; break; + } + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; + case "HSLA": + var hslcomp = color.replace(/\s/g, "").slice(5, -1).split(","); + return BDFDB.ColorUtils.convert(`hsl(${hslcomp.slice(0, 3).join(",")})`, "RGBCOMP").concat(processA(hslcomp.pop())); + case "HEX": + var hex = /^#([a-f\d]{1})([a-f\d]{1})([a-f\d]{1})$|^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color); + return [parseInt(hex[1] + hex[1] || hex[4], 16).toString(), parseInt(hex[2] + hex[2] || hex[5], 16).toString(), parseInt(hex[3] + hex[3] || hex[6], 16).toString()]; + case "HEXA": + var hex = /^#([a-f\d]{1})([a-f\d]{1})([a-f\d]{1})([a-f\d]{1})$|^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color); + return [parseInt(hex[1] + hex[1] || hex[5], 16).toString(), parseInt(hex[2] + hex[2] || hex[6], 16).toString(), parseInt(hex[3] + hex[3] || hex[7], 16).toString(), Math.floor(BDFDB.NumberUtils.mapRange([0, 255], [0, 100], parseInt(hex[4] + hex[4] || hex[8], 16).toString()))/100]; + case "INT": + color = processINT(color); + return [(color >> 16 & 255).toString(), (color >> 8 & 255).toString(), (color & 255).toString()]; + default: + return null; + } + } + else { + if (conv && type && conv.indexOf("HSL") == 0 && type.indexOf("HSL") == 0) { + if (type == "HSLCOMP") { + switch (conv) { + case "HSLCOMP": + if (color.length == 3) return processHSL(color); + else if (color.length == 4) { + var a = processA(color.pop()); + return processHSL(color).concat(a); + } + break; + case "HSL": + return `hsl(${processHSL(color.slice(0, 3)).join(",")})`; + case "HSLA": + color = color.slice(0, 4); + var a = color.length == 4 ? processA(color.pop()) : 1; + return `hsla(${processHSL(color).concat(a).join(",")})`; + } + } + else return BDFDB.ColorUtils.convert(color.replace(/\s/g, "").slice(color.toLowerCase().indexOf("hsla") == 0 ? 5 : 4, -1).split(","), conv, "HSLCOMP"); + } + else { + let rgbcomp = type == "RGBCOMP" ? color : BDFDB.ColorUtils.convert(color, "RGBCOMP", type); + if (rgbcomp) switch (conv) { + case "RGB": + return `rgb(${processRGB(rgbcomp.slice(0, 3)).join(",")})`; + case "RGBA": + rgbcomp = rgbcomp.slice(0, 4); + var a = rgbcomp.length == 4 ? processA(rgbcomp.pop()) : 1; + return `rgba(${processRGB(rgbcomp).concat(a).join(",")})`; + case "HSLCOMP": + var a = rgbcomp.length == 4 ? processA(rgbcomp.pop()) : null; + var hslcomp = processHSL(BDFDB.ColorUtils.convert(rgbcomp, "HSL").replace(/\s/g, "").split(",")); + return a != null ? hslcomp.concat(a) : hslcomp; + case "HSL": + var r = processC(rgbcomp[0]), g = processC(rgbcomp[1]), b = processC(rgbcomp[2]); + var max = Math.max(r, g, b), min = Math.min(r, g, b), dif = max - min, h, l = max === 0 ? 0 : dif / max, s = max / 255; + switch (max) { + case min: h = 0; break; + case r: h = g - b + dif * (g < b ? 6 : 0); h /= 6 * dif; break; + case g: h = b - r + dif * 2; h /= 6 * dif; break; + case b: h = r - g + dif * 4; h /= 6 * dif; break; + } + return `hsl(${processHSL([Math.round(h * 360), l * 100, s * 100]).join(",")})`; + case "HSLA": + var a = rgbcomp.length == 4 ? processA(rgbcomp.pop()) : 1; + return `hsla(${BDFDB.ColorUtils.convert(rgbcomp, "HSL").slice(4, -1).split(",").concat(a).join(",")})`; + case "HEX": + return ("#" + (0x1000000 + (rgbcomp[2] | rgbcomp[1] << 8 | rgbcomp[0] << 16)).toString(16).slice(1)).toUpperCase(); + case "HEXA": + return ("#" + (0x1000000 + (rgbcomp[2] | rgbcomp[1] << 8 | rgbcomp[0] << 16)).toString(16).slice(1) + (0x100 + Math.round(BDFDB.NumberUtils.mapRange([0, 100], [0, 255], processA(rgbcomp[3]) * 100))).toString(16).slice(1)).toUpperCase(); + case "INT": + return processINT(rgbcomp[2] | rgbcomp[1] << 8 | rgbcomp[0] << 16); + default: + return null; + } + } + } + } + return null; + function processC(c) {if (c == null) {return 255;} else {c = parseInt(c.toString().replace(/[^0-9\-]/g, ""));return isNaN(c) || c > 255 ? 255 : c < 0 ? 0 : c;}}; + function processRGB(comp) {return comp.map(c => {return processC(c);});}; + function processA(a) {if (a == null) {return 1;} else {a = a.toString();a = (a.indexOf("%") > -1 ? 0.01 : 1) * parseFloat(a.replace(/[^0-9\.\-]/g, ""));return isNaN(a) || a > 1 ? 1 : a < 0 ? 0 : a;}}; + function processSL(sl) {if (sl == null) {return "100%";} else {sl = parseFloat(sl.toString().replace(/[^0-9\.\-]/g, ""));return (isNaN(sl) || sl > 100 ? 100 : sl < 0 ? 0 : sl) + "%";}}; + function processHSL(comp) {let h = parseFloat(comp.shift().toString().replace(/[^0-9\.\-]/g, ""));h = isNaN(h) || h > 360 ? 360 : h < 0 ? 0 : h;return [h].concat(comp.map(sl => {return processSL(sl);}));}; + function processINT(c) {if (c == null) {return 16777215;} else {c = parseInt(c.toString().replace(/[^0-9]/g, ""));return isNaN(c) || c > 16777215 ? 16777215 : c < 0 ? 0 : c;}}; + }; + BDFDB.ColorUtils.setAlpha = function (color, a, conv) { + if (BDFDB.ObjectUtils.is(color)) { + var newcolor = {}; + for (let pos in color) newcolor[pos] = BDFDB.ColorUtils.setAlpha(color[pos], a, conv); + return newcolor; + } + else { + var comp = BDFDB.ColorUtils.convert(color, "RGBCOMP"); + if (comp) { + a = a.toString(); + a = (a.indexOf("%") > -1 ? 0.01 : 1) * parseFloat(a.replace(/[^0-9\.\-]/g, "")); + a = isNaN(a) || a > 1 ? 1 : a < 0 ? 0 : a; + comp[3] = a; + conv = (conv || BDFDB.ColorUtils.getType(color)).toUpperCase(); + conv = conv == "RGB" || conv == "HSL" || conv == "HEX" ? conv + "A" : conv; + return BDFDB.ColorUtils.convert(comp, conv); + } + } + return null; + }; + BDFDB.ColorUtils.getAlpha = function (color) { + var comp = BDFDB.ColorUtils.convert(color, "RGBCOMP"); + if (comp) { + if (comp.length == 3) return 1; + else if (comp.length == 4) { + let a = comp[3].toString(); + a = (a.indexOf("%") > -1 ? 0.01 : 1) * parseFloat(a.replace(/[^0-9\.\-]/g, "")); + return isNaN(a) || a > 1 ? 1 : a < 0 ? 0 : a; + } + } + return null; + }; + BDFDB.ColorUtils.change = function (color, value, conv) { + value = parseFloat(value); + if (color != null && typeof value == "number" && !isNaN(value)) { + if (BDFDB.ObjectUtils.is(color)) { + var newcolor = {}; + for (let pos in color) newcolor[pos] = BDFDB.ColorUtils.change(color[pos], value, conv); + return newcolor; + } + else { + var comp = BDFDB.ColorUtils.convert(color, "RGBCOMP"); + if (comp) { + if (parseInt(value) !== value) { + value = value.toString(); + value = (value.indexOf("%") > -1 ? 0.01 : 1) * parseFloat(value.replace(/[^0-9\.\-]/g, "")); + value = isNaN(value) ? 0 : value; + return BDFDB.ColorUtils.convert([Math.round(comp[0] * (1 + value)), Math.round(comp[1] * (1 + value)), Math.round(comp[2] * (1 + value))], conv || BDFDB.ColorUtils.getType(color)); + } + else return BDFDB.ColorUtils.convert([Math.round(comp[0] + value), Math.round(comp[1] + value), Math.round(comp[2] + value)], conv || BDFDB.ColorUtils.getType(color)); + } + } + } + return null; + }; + BDFDB.ColorUtils.invert = function (color, conv) { + if (BDFDB.ObjectUtils.is(color)) { + var newcolor = {}; + for (let pos in color) newcolor[pos] = BDFDB.ColorUtils.invert(color[pos], conv); + return newcolor; + } + else { + var comp = BDFDB.ColorUtils.convert(color, "RGBCOMP"); + if (comp) return BDFDB.ColorUtils.convert([255 - comp[0], 255 - comp[1], 255 - comp[2]], conv || BDFDB.ColorUtils.getType(color)); + } + return null; + }; + BDFDB.ColorUtils.compare = function (color1, color2) { + if (color1 && color2) { + color1 = BDFDB.ColorUtils.convert(color1, "RGBA"); + color2 = BDFDB.ColorUtils.convert(color2, "RGBA"); + if (color1 && color2) return BDFDB.equals(color1, color2); + } + return null; + }; + BDFDB.ColorUtils.isBright = function (color, compare = 160) { + color = BDFDB.ColorUtils.convert(color, "RGBCOMP"); + if (!color) return false; + return parseInt(compare) < Math.sqrt(0.299 * color[0]**2 + 0.587 * color[1]**2 + 0.144 * color[2]**2); + }; + BDFDB.ColorUtils.getType = function (color) { + if (color != null) { + if (typeof color === "object" && (color.length == 3 || color.length == 4)) { + if (isRGB(color)) return "RGBCOMP"; + else if (isHSL(color)) return "HSLCOMP"; + } + else if (typeof color === "string") { + if (/^#[a-f\d]{3}$|^#[a-f\d]{6}$/i.test(color)) return "HEX"; + else if (/^#[a-f\d]{4}$|^#[a-f\d]{8}$/i.test(color)) return "HEXA"; + else { + color = color.toUpperCase(); + var comp = color.replace(/[^0-9\.\-\,\%]/g, "").split(","); + if (color.indexOf("RGB(") == 0 && comp.length == 3 && isRGB(comp)) return "RGB"; + else if (color.indexOf("RGBA(") == 0 && comp.length == 4 && isRGB(comp)) return "RGBA"; + else if (color.indexOf("HSL(") == 0 && comp.length == 3 && isHSL(comp)) return "HSL"; + else if (color.indexOf("HSLA(") == 0 && comp.length == 4 && isHSL(comp)) return "HSLA"; + } + } + else if (typeof color === "number" && parseInt(color) == color && color > -1 && color < 16777216) return "INT"; + } + return null; + function isRGB(comp) {return comp.slice(0, 3).every(rgb => rgb.toString().indexOf("%") == -1 && parseFloat(rgb) == parseInt(rgb));}; + function isHSL(comp) {return comp.slice(1, 3).every(hsl => hsl.toString().indexOf("%") == hsl.length - 1);}; + }; + BDFDB.ColorUtils.createGradient = function (colorobj, direction = "to right") { + var sortedgradient = {}; + var gradientstring = "linear-gradient(" + direction; + for (let pos of Object.keys(colorobj).sort()) { + let color = BDFDB.ColorUtils.convert(colorobj[pos], "RGBA"); + gradientstring += color ? `, ${color} ${pos*100}%` : '' + } + return gradientstring += ")"; + }; + BDFDB.ColorUtils.getSwatchColor = function (container, number) { + if (!Node.prototype.isPrototypeOf(container)) return; + let swatches = container.querySelector(`${BDFDB.dotCN.colorpickerswatches}[number="${number}"], ${BDFDB.dotCN.colorpickerswatch}[number="${number}"]`); + if (!swatches) return null; + return BDFDB.ColorUtils.convert(BDFDB.ReactUtils.findValue(BDFDB.ReactUtils.getInstance(swatches), "selectedColor", {up:true, blacklist:{"props":true}})); + }; + + BDFDB.DOMUtils = {}; + BDFDB.DOMUtils.getSelection = function () { + let selection = document.getSelection(); + return selection && selection.anchorNode ? selection.getRangeAt(0).toString() : ""; + }; + BDFDB.DOMUtils.addClass = function (eles, ...classes) { + if (!eles || !classes) return; + for (let ele of [eles].flat(10).filter(n => n)) { + if (Node.prototype.isPrototypeOf(ele)) add(ele); + else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) add(e); + else if (typeof ele == "string") for (let e of ele.split(",")) if (e && (e = e.trim())) for (let n of document.querySelectorAll(e)) add(n); + } + function add(node) { + if (node && node.classList) for (let cla of classes) for (let cl of [cla].flat(10).filter(n => n)) if (typeof cl == "string") for (let c of cl.split(" ")) if (c) node.classList.add(c); + } + }; + BDFDB.DOMUtils.removeClass = function (eles, ...classes) { + if (!eles || !classes) return; + for (let ele of [eles].flat(10).filter(n => n)) { + if (Node.prototype.isPrototypeOf(ele)) remove(ele); + else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) remove(e); + else if (typeof ele == "string") for (let e of ele.split(",")) if (e && (e = e.trim())) for (let n of document.querySelectorAll(e)) remove(n); + } + function remove(node) { + if (node && node.classList) for (let cla of classes) for (let cl of [cla].flat(10).filter(n => n)) if (typeof cl == "string") for (let c of cl.split(" ")) if (c) node.classList.remove(c); + } + }; + BDFDB.DOMUtils.toggleClass = function (eles, ...classes) { + if (!eles || !classes) return; + var force = classes.pop(); + if (typeof force != "boolean") { + classes.push(force); + force = undefined; + } + if (!classes.length) return; + for (let ele of [eles].flat(10).filter(n => n)) { + if (!ele) {} + else if (Node.prototype.isPrototypeOf(ele)) toggle(ele); + else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) toggle(e); + else if (typeof ele == "string") for (let e of ele.split(",")) if (e && (e = e.trim())) for (let n of document.querySelectorAll(e)) toggle(n); + } + function toggle(node) { + if (node && node.classList) for (let cla of classes) for (let cl of [cla].flat(10).filter(n => n)) if (typeof cl == "string") for (let c of cl.split(" ")) if (c) node.classList.toggle(c, force); + } + }; + BDFDB.DOMUtils.containsClass = function (eles, ...classes) { + if (!eles || !classes) return; + let all = classes.pop(); + if (typeof all != "boolean") { + classes.push(all); + all = true; + } + if (!classes.length) return; + let contained = undefined; + for (let ele of BDFDB.ArrayUtils.is(eles) ? eles : Array.of(eles)) { + if (!ele) {} + else if (Node.prototype.isPrototypeOf(ele)) contains(ele); + else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) contains(e); + else if (typeof ele == "string") for (let c of ele.split(",")) if (c && (c = c.trim())) for (let n of document.querySelectorAll(c)) contains(n); + } + return contained; + function contains(node) { + if (node && node.classList) for (let cla of classes) if (typeof cla == "string") for (let c of cla.split(" ")) if (c) { + if (contained === undefined) contained = all; + if (all && !node.classList.contains(c)) contained = false; + if (!all && node.classList.contains(c)) contained = true; + } + } + }; + BDFDB.DOMUtils.replaceClass = function (eles, oldclass, newclass) { + if (!eles || typeof oldclass != "string" || typeof newclass != "string") return; + for (let ele of [eles].flat(10).filter(n => n)) { + if (Node.prototype.isPrototypeOf(ele)) replace(ele); + else if (NodeList.prototype.isPrototypeOf(ele)) for (let e of ele) replace(e); + else if (typeof ele == "string") for (let e of ele.split(",")) if (e && (e = e.trim())) for (let n of document.querySelectorAll(e)) replace(n); + } + function replace(node) { + if (node && node.tagName && node.className) node.className = node.className.replace(new RegExp(oldclass, "g"), newclass).trim(); + } + }; + BDFDB.DOMUtils.formatClassName = function (...classes) { + return BDFDB.ArrayUtils.removeCopies(classes.flat(10).filter(n => n).join(" ").split(" ")).join(" ").trim(); + }; + BDFDB.DOMUtils.removeClassFromDOM = function (...classes) { + for (let c of classes.flat(10).filter(n => n)) if (typeof c == "string") for (let a of c.split(",")) if (a && (a = a.replace(/\.|\s/g, ""))) BDFDB.DOMUtils.removeClass(document.querySelectorAll("." + a), a); + }; + BDFDB.DOMUtils.show = function (...eles) { + BDFDB.DOMUtils.toggle(...eles, true); + }; + BDFDB.DOMUtils.hide = function (...eles) { + BDFDB.DOMUtils.toggle(...eles, false); + }; + BDFDB.DOMUtils.toggle = function (...eles) { + if (!eles) return; + let force = eles.pop(); + if (typeof force != "boolean") { + eles.push(force); + force = undefined; + } + if (!eles.length) return; + for (let ele of eles.flat(10).filter(n => n)) { + if (Node.prototype.isPrototypeOf(ele)) toggle(ele); + else if (NodeList.prototype.isPrototypeOf(ele)) for (let node of ele) toggle(node); + else if (typeof ele == "string") for (let c of ele.split(",")) if (c && (c = c.trim())) for (let node of document.querySelectorAll(c)) toggle(node); + } + function toggle(node) { + if (!node || !Node.prototype.isPrototypeOf(node)) return; + let hidden = force === undefined ? !BDFDB.DOMUtils.isHidden(node) : !force; + if (hidden) { + let display = node.style.getPropertyValue("display"); + if (display && display != "none") node.BDFDBhideDisplayState = { + display: display, + important: (` ${node.style.cssText} `.split(` display: ${display}`)[1] || "").trim().indexOf("!important") == 0 + }; + node.style.setProperty("display", "none", "important"); + } + else { + if (node.BDFDBhideDisplayState) { + node.style.setProperty("display", node.BDFDBhideDisplayState.display, node.BDFDBhideDisplayState.important ? "important" : ""); + delete node.BDFDBhideDisplayState; + } + else node.style.removeProperty("display"); + } + } + }; + BDFDB.DOMUtils.isHidden = function (node) { + if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) return getComputedStyle(node, null).getPropertyValue("display") == "none"; + }; + BDFDB.DOMUtils.remove = function (...eles) { + for (let ele of eles.flat(10).filter(n => n)) { + if (Node.prototype.isPrototypeOf(ele)) ele.remove(); + else if (NodeList.prototype.isPrototypeOf(ele)) { + let nodes = Array.from(ele); + while (nodes.length) nodes.shift().remove(); + } + else if (typeof ele == "string") for (let c of ele.split(",")) if (c && (c = c.trim())) { + let nodes = Array.from(document.querySelectorAll(c)); + while (nodes.length) nodes.shift().remove(); + } + } + }; + BDFDB.DOMUtils.create = function (html) { + if (typeof html != "string" || !html.trim()) return null; + let template = document.createElement("template"); + try {template.innerHTML = html.replace(/(?[\t\r\n]+<(?!pre)/g, "><");} + catch (err) {template.innerHTML = html.replace(/>[\t\r\n]+<(?!pre)/g, "><");} + if (template.content.childNodes.length == 1) return template.content.firstElementChild; + else { + let wrapper = document.createElement("span"); + let nodes = Array.from(template.content.childNodes); + while (nodes.length) wrapper.appendChild(nodes.shift()); + return wrapper; + } + }; + BDFDB.DOMUtils.getParent = function (listOrSelector, node) { + let parent = null; + if (Node.prototype.isPrototypeOf(node) && listOrSelector) { + let list = NodeList.prototype.isPrototypeOf(listOrSelector) ? listOrSelector : typeof listOrSelector == "string" ? document.querySelectorAll(listOrSelector) : null; + if (list) for (let listNode of list) if (listNode.contains(node)) { + parent = listNode; + break; + } + } + return parent; + }; + BDFDB.DOMUtils.setText = function (node, stringOrNode) { + if (!node || !Node.prototype.isPrototypeOf(node)) return; + let textnode = node.nodeType == Node.TEXT_NODE ? node : null; + if (!textnode) for (let child of node.childNodes) if (child.nodeType == Node.TEXT_NODE || BDFDB.DOMUtils.containsClass(child, "BDFDB-textnode")) { + textnode = child; + break; + } + if (textnode) { + if (Node.prototype.isPrototypeOf(stringOrNode) && stringOrNode.nodeType != Node.TEXT_NODE) { + BDFDB.DOMUtils.addClass(stringOrNode, "BDFDB-textnode"); + node.replaceChild(stringOrNode, textnode); + } + else if (Node.prototype.isPrototypeOf(textnode) && textnode.nodeType != Node.TEXT_NODE) node.replaceChild(document.createTextNode(stringOrNode), textnode); + else textnode.textContent = stringOrNode; + } + else node.appendChild(Node.prototype.isPrototypeOf(stringOrNode) ? stringOrNode : document.createTextNode(stringOrNode)); + }; + BDFDB.DOMUtils.getText = function (node) { + if (!node || !Node.prototype.isPrototypeOf(node)) return; + for (let child of node.childNodes) if (child.nodeType == Node.TEXT_NODE) return child.textContent; + }; + BDFDB.DOMUtils.getRects = function (node) { + let rects = {}; + if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) { + let hideNode = node; + while (hideNode) { + let hidden = BDFDB.DOMUtils.isHidden(hideNode); + if (hidden) { + BDFDB.DOMUtils.toggle(hideNode, true); + hideNode.BDFDBgetRectsHidden = true; + } + hideNode = hideNode.parentElement; + } + rects = node.getBoundingClientRect(); + hideNode = node; + while (hideNode) { + if (hideNode.BDFDBgetRectsHidden) { + BDFDB.DOMUtils.toggle(hideNode, false); + delete hideNode.BDFDBgetRectsHidden; + } + hideNode = hideNode.parentElement; + } + } + return rects; + }; + BDFDB.DOMUtils.getHeight = function (node) { + if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) { + let rects = BDFDB.DOMUtils.getRects(node); + let style = getComputedStyle(node); + return rects.height + parseInt(style.marginTop) + parseInt(style.marginBottom); + } + return 0; + }; + BDFDB.DOMUtils.getInnerHeight = function (node) { + if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) { + let rects = BDFDB.DOMUtils.getRects(node); + let style = getComputedStyle(node); + return rects.height - parseInt(style.paddingTop) - parseInt(style.paddingBottom); + } + return 0; + }; + BDFDB.DOMUtils.getWidth = function (node) { + if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) { + let rects = BDFDB.DOMUtils.getRects(node); + let style = getComputedStyle(node); + return rects.width + parseInt(style.marginLeft) + parseInt(style.marginRight); + } + return 0; + }; + BDFDB.DOMUtils.getInnerWidth = function (node) { + if (Node.prototype.isPrototypeOf(node) && node.nodeType != Node.TEXT_NODE) { + let rects = BDFDB.DOMUtils.getRects(node); + let style = getComputedStyle(node); + return rects.width - parseInt(style.paddingLeft) - parseInt(style.paddingRight); + } + return 0; + }; + BDFDB.DOMUtils.appendWebScript = function (url, container) { + if (!container && !document.head.querySelector("bd-head bd-scripts")) document.head.appendChild(BDFDB.DOMUtils.create(``)); + container = container || document.head.querySelector("bd-head bd-scripts") || document.head; + container = Node.prototype.isPrototypeOf(container) ? container : document.head; + BDFDB.DOMUtils.removeWebScript(url, container); + let script = document.createElement("script"); + script.src = url; + container.appendChild(script); + }; + BDFDB.DOMUtils.removeWebScript = function (url, container) { + container = container || document.head.querySelector("bd-head bd-scripts") || document.head; + container = Node.prototype.isPrototypeOf(container) ? container : document.head; + BDFDB.DOMUtils.remove(container.querySelectorAll(`script[src="${url}"]`)); + }; + BDFDB.DOMUtils.appendWebStyle = function (url, container) { + if (!container && !document.head.querySelector("bd-head bd-styles")) document.head.appendChild(BDFDB.DOMUtils.create(``)); + container = container || document.head.querySelector("bd-head bd-styles") || document.head; + container = Node.prototype.isPrototypeOf(container) ? container : document.head; + BDFDB.DOMUtils.removeWebStyle(url, container); + container.appendChild(BDFDB.DOMUtils.create(``)); + }; + BDFDB.DOMUtils.removeWebStyle = function (url, container) { + container = container || document.head.querySelector("bd-head bd-styles") || document.head; + container = Node.prototype.isPrototypeOf(container) ? container : document.head; + BDFDB.DOMUtils.remove(container.querySelectorAll(`link[href="${url}"]`)); + }; + BDFDB.DOMUtils.appendLocalStyle = function (id, css, container) { + if (!container && !document.head.querySelector("bd-head bd-styles")) document.head.appendChild(BDFDB.DOMUtils.create(``)); + container = container || document.head.querySelector("bd-head bd-styles") || document.head; + container = Node.prototype.isPrototypeOf(container) ? container : document.head; + BDFDB.DOMUtils.removeLocalStyle(id, container); + container.appendChild(BDFDB.DOMUtils.create(``)); + }; + BDFDB.DOMUtils.removeLocalStyle = function (id, container) { + container = container || document.head.querySelector("bd-head bd-styles") || document.head; + container = Node.prototype.isPrototypeOf(container) ? container : document.head; + BDFDB.DOMUtils.remove(container.querySelectorAll(`style[id="${id}CSS"]`)); + }; + + BDFDB.ModalUtils = {}; + BDFDB.ModalUtils.open = function (plugin, config) { + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ObjectUtils.is(config)) return; + let modal, modalInstance, modalProps, cancels = [], closeModal = _ => { + if (BDFDB.ObjectUtils.is(modalProps) && typeof modalProps.onClose == "function") modalProps.onClose(); + }; + let headerChildren = [], contentChildren = [], footerChildren = []; + if (typeof config.text == "string") { + contentChildren.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextElement, { + children: config.text + })); + } + if (config.children) { + let tabBarItems = []; + for (let child of [config.children].flat(10).filter(n => n)) if (LibraryModules.React.isValidElement(child)) { + if (child.type == InternalComponents.LibraryComponents.ModalComponents.ModalTabContent) { + if (!tabBarItems.length) child.props.open = true; + else delete child.props.open; + tabBarItems.push({value:child.props.tab}); + } + contentChildren.push(child); + } + if (tabBarItems.length) headerChildren.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.tabbarcontainer, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TabBar, { + className: BDFDB.disCN.tabbar, + itemClassName: BDFDB.disCN.tabbaritem, + type: InternalComponents.LibraryComponents.TabBar.Types.TOP, + items: tabBarItems, + onItemSelect: (value, instance) => { + let tabContentInstances = BDFDB.ReactUtils.findOwner(modal, {name:"BDFDB_ModalTabContent", all:true, unlimited:true}); + for (let ins of tabContentInstances) { + if (ins.props.tab == value) ins.props.open = true; + else delete ins.props.open; + } + BDFDB.ReactUtils.forceUpdate(tabContentInstances); + } + }), + config.tabBarChildren + ].flat(10).filter(n => n) + })); + } + if (BDFDB.ArrayUtils.is(config.buttons)) for (let button of config.buttons) { + let contents = typeof button.contents == "string" && button.contents; + if (contents) { + let color = typeof button.color == "string" && InternalComponents.LibraryComponents.Button.Colors[button.color.toUpperCase()]; + let look = typeof button.look == "string" && InternalComponents.LibraryComponents.Button.Looks[button.look.toUpperCase()]; + let click = typeof button.click == "function" ? button.click : (typeof button.onClick == "function" ? button.onClick : _ => {}); + + if (button.cancel) cancels.push(click); + + footerChildren.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Button, BDFDB.ObjectUtils.exclude(Object.assign({}, button, { + look: look || (color ? InternalComponents.LibraryComponents.Button.Looks.FILLED : InternalComponents.LibraryComponents.Button.Looks.LINK), + color: color || InternalComponents.LibraryComponents.Button.Colors.PRIMARY, + onClick: _ => { + if (button.close) closeModal(); + if (!(button.close && button.cancel)) click(modal, modalInstance); + }, + children: contents + }), "click", "close", "cancel", "contents"))); + } + } + contentChildren = contentChildren.concat(config.contentChildren).filter(n => n && (typeof n == "string" || BDFDB.ReactUtils.isValidElement(n))); + headerChildren = headerChildren.concat(config.headerChildren).filter(n => n && (typeof n == "string" || BDFDB.ReactUtils.isValidElement(n))); + footerChildren = footerChildren.concat(config.footerChildren).filter(n => n && (typeof n == "string" || BDFDB.ReactUtils.isValidElement(n))); + if (contentChildren.length) { + if (typeof config.onClose != "function") config.onClose = _ => {}; + if (typeof config.onOpen != "function") config.onOpen = _ => {}; + + let name = plugin.name || (typeof plugin.getName == "function" ? plugin.getName() : null); + name = typeof name == "string" ? name : null; + let oldTransitionState = 0; + LibraryModules.ModalUtils.openModal(props => { + modalProps = props; + return BDFDB.ReactUtils.createElement(class BDFDB_Modal extends LibraryModules.React.Component { + render () { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ModalComponents.ModalRoot, { + className: BDFDB.DOMUtils.formatClassName(name && `${name}-modal`, BDFDB.disCN.modalwrapper, config.className), + size: typeof config.size == "string" && InternalComponents.LibraryComponents.ModalComponents.ModalSize[config.size.toUpperCase()] || InternalComponents.LibraryComponents.ModalComponents.ModalSize.SMALL, + transitionState: props.transitionState, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ModalComponents.ModalHeader, { + className: BDFDB.DOMUtils.formatClassName(config.headerClassName, config.shade && BDFDB.disCN.modalheadershade, headerChildren.length && BDFDB.disCN.modalheaderhassibling), + separator: config.headerSeparator || false, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormTitle, { + tag: InternalComponents.LibraryComponents.FormComponents.FormTitle.Tags.H4, + children: config.header + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextElement, { + size: InternalComponents.LibraryComponents.TextElement.Sizes.SIZE_12, + children: typeof config.subheader == "string" || BDFDB.ReactUtils.isValidElement(config.subheader) ? config.subheader : (name || "") + }) + ] + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ModalComponents.ModalCloseButton, { + onClick: closeModal + }) + ] + }), + headerChildren.length ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + grow: 0, + shrink: 0, + children: headerChildren + }) : null, + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ModalComponents.ModalContent, { + className: config.contentClassName, + scroller: config.scroller, + direction: config.direction, + content: config.content, + children: contentChildren + }), + footerChildren.length ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ModalComponents.ModalFooter, { + className: config.footerClassName, + children: footerChildren + }) : null + ] + }); + } + componentDidMount () { + modalInstance = this; + modal = BDFDB.ReactUtils.findDOMNode(this); + modal = modal && modal.parentElement ? modal.parentElement.querySelector(BDFDB.dotCN.modalwrapper) : null; + if (modal && props.transitionState == 1 && props.transitionState > oldTransitionState) config.onOpen(modal, this); + oldTransitionState = props.transitionState; + } + componentWillUnmount () { + if (modal && props.transitionState == 3) { + for (let cancel of cancels) cancel(modal); + config.onClose(modal, this); + } + } + }, props, true); + }, { + onCloseRequest: closeModal + }); + } + }; + BDFDB.ModalUtils.confirm = function (plugin, text, callback) { + if (!BDFDB.ObjectUtils.is(plugin) || typeof text != "string") return; + BDFDB.ModalUtils.open(plugin, {text, header:"Are you sure?", className:BDFDB.disCN.modalconfirmmodal, scroller:false, buttons:[ + {contents: BDFDB.LanguageUtils.LanguageStrings.OKAY, close:true, color:"RED", click:typeof callback == "function" ? callback : _ => {}}, + {contents: BDFDB.LanguageUtils.LanguageStrings.CANCEL, close:true} + ]}); + }; + + const RealMenuItems = BDFDB.ModuleUtils.findByProperties("MenuItem", "MenuGroup"); + BDFDB.ContextMenuUtils = {}; + BDFDB.ContextMenuUtils.open = function (plugin, e, children) { + LibraryModules.ContextMenuUtils.openContextMenu(e, function (e) { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Menu, { + navId: "bdfdb-context", + onClose: BDFDB.LibraryModules.ContextMenuUtils.closeContextMenu, + children: children + }, true); + }); + }; + BDFDB.ContextMenuUtils.close = function (nodeOrInstance) { + if (!BDFDB.ObjectUtils.is(nodeOrInstance)) return; + let instance = BDFDB.ReactUtils.findOwner(nodeOrInstance, {props:"closeContextMenu", up:true}); + if (BDFDB.ObjectUtils.is(instance) && instance.props && typeof instance.props.closeContextMenu == "function") instance.props.closeContextMenu(); + else BDFDB.LibraryModules.ContextMenuUtils.closeContextMenu(); + }; + BDFDB.ContextMenuUtils.createItem = function (component, props = {}) { + if (!component) return null; + else { + if (props.persisting || BDFDB.ObjectUtils.is(props.popoutProps) || (typeof props.color == "string" && !BDFDB.DiscordClasses[`menu${props.color.toLowerCase()}`])) component = InternalComponents.MenuItem; + if (BDFDB.ObjectUtils.toArray(RealMenuItems).some(c => c == component)) return BDFDB.ReactUtils.createElement(component, props); + else return BDFDB.ReactUtils.createElement(RealMenuItems.MenuItem, { + id: props.id, + disabled: props.disabled, + render: menuItemProps => { + if (!props.state) props.state = BDFDB.ObjectUtils.extract(props, "checked", "value"); + return BDFDB.ReactUtils.createElement(InternalComponents.CustomMenuItemWrapper, { + disabled: props.disabled, + childProps: Object.assign({}, props, menuItemProps, {color: props.color}), + children: component + }, true); + } + }); + } + }; + BDFDB.ContextMenuUtils.createItemId = function (...strings) { + return strings.map(s => typeof s == "number" ? s.toString() : s).filter(s => typeof s == "string").map(s => s.toLowerCase().replace(/\s/, "-")).join("-"); + }; + BDFDB.ContextMenuUtils.findItem = function (returnvalue, config) { + if (!returnvalue || !BDFDB.ObjectUtils.is(config) || !config.label && !config.id) return [null, -1]; + config.label = config.label && [config.label].flat().filter(n => n); + config.id = config.id && [config.id].flat().filter(n => n); + let contextMenu = BDFDB.ReactUtils.findChild(returnvalue, {props: "navId"}); + if (contextMenu) { + for (let i in contextMenu.props.children) { + if (contextMenu.props.children[i] && contextMenu.props.children[i].type == RealMenuItems.MenuGroup) { + if (BDFDB.ArrayUtils.is(contextMenu.props.children[i].props.children)) { + for (let j in contextMenu.props.children[i].props.children) if (check(contextMenu.props.children[i].props.children[j])) { + if (config.group) return [contextMenu.props.children, parseInt(i)]; + else return [contextMenu.props.children[i].props.children, parseInt(j)]; + } + } + else if (contextMenu.props.children[i] && contextMenu.props.children[i].props) { + if (check(contextMenu.props.children[i].props.children)) { + if (config.group) return [contextMenu.props.children, parseInt(i)]; + else { + contextMenu.props.children[i].props.children = [contextMenu.props.children[i].props.children]; + return [contextMenu.props.children[i].props.children, 0]; + } + } + else if (contextMenu.props.children[i].props.children && contextMenu.props.children[i].props.children.props && BDFDB.ArrayUtils.is(contextMenu.props.children[i].props.children.props.children)) { + for (let j in contextMenu.props.children[i].props.children.props.children) if (check(contextMenu.props.children[i].props.children.props.children[j])) { + if (config.group) return [contextMenu.props.children, parseInt(i)]; + else return [contextMenu.props.children[i].props.children.props.children, parseInt(j)]; + } + } + } + } + else if (check(contextMenu.props.children[i])) return [contextMenu.props.children, parseInt(i)]; + } + return [contextMenu.props.children, -1]; + } + return [null, -1]; + function check (child) { + if (!child) return false; + let props = child.stateNode ? child.stateNode.props : child.props; + if (!props) return false; + return config.id && config.id.some(key => props.id == key) || config.label && config.label.some(key => props.label == key); + } + }; + + BDFDB.TimeUtils = {}; + BDFDB.TimeUtils.interval = function (callback, delay, ...args) { + if (typeof callback != "function" || typeof delay != "number" || delay < 1) return; + else { + let count = 0, interval = setInterval(_ => {BDFDB.TimeUtils.suppress(callback, "Interval")(...[interval, count++, args].flat());}, delay); + return interval; + } + }; + BDFDB.TimeUtils.timeout = function (callback, delay, ...args) { + delay = parseFloat(delay); + if (typeof callback != "function") return; + else if (isNaN(delay) || typeof delay != "number" || delay < 1) { + let immediate = setImmediate(_ => {BDFDB.TimeUtils.suppress(callback, "Immediate")(...[immediate, args].flat());}); + return immediate; + } + else { + let timeout = setTimeout(_ => {BDFDB.TimeUtils.suppress(callback, "Timeout")(...[timeout, args].flat());}, delay); + return timeout; + } + }; + BDFDB.TimeUtils.clear = function (...timeObjects) { + for (let t of timeObjects.flat(10).filter(n => n)) { + if (typeof t == "number") { + clearInterval(t); + clearTimeout(t); + } + else if (typeof t == "object") clearImmediate(t); + } + }; + BDFDB.TimeUtils.suppress = function (callback, string, name) {return function (...args) { + try {return callback(...args);} + catch (err) {BDFDB.LogUtils.error((typeof string == "string" && string || "") + " " + err, name);} + }}; + + BDFDB.StringUtils = {}; + BDFDB.StringUtils.htmlEscape = function (string) { + let ele = document.createElement("div"); + ele.innerText = string; + return ele.innerHTML; + }; + BDFDB.StringUtils.regEscape = function (string) { + return typeof string == "string" && string.replace(/([\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}])/g, "\\$1"); + }; + BDFDB.StringUtils.insertNRST = function (string) { + return typeof string == "string" && string.replace(/\\r/g, "\r").replace(/\\n/g, "\n").replace(/\\t/g, "\t").replace(/\\s/g, " "); + }; + BDFDB.StringUtils.highlight = function (string, searchstring, prefix = ``, suffix = ``) { + if (typeof string != "string" || !searchstring || searchstring.length < 1) return string; + let offset = 0, original = string; + BDFDB.ArrayUtils.getAllIndexes(string.toUpperCase(), searchstring.toUpperCase()).forEach(index => { + let d1 = offset * (prefix.length + suffix.length); + index = index + d1; + let d2 = index + searchstring.length; + let d3 = [-1].concat(BDFDB.ArrayUtils.getAllIndexes(string.substring(0, index), "<")); + let d4 = [-1].concat(BDFDB.ArrayUtils.getAllIndexes(string.substring(0, index), ">")); + if (d3[d3.length - 1] > d4[d4.length - 1]) return; + string = string.substring(0, index) + prefix + string.substring(index, d2) + suffix + string.substring(d2); + offset++; + }); + return string || original; + }; + BDFDB.StringUtils.extractSelection = function (original, selection) { + if (typeof original != "string") return ""; + if (typeof selection != "string") return original; + let s = [], f = [], wrong = 0, canceled = false, done = false; + for (let i of BDFDB.ArrayUtils.getAllIndexes(original, selection[0])) if (!done) { + while (i <= original.length && !done) { + let subSelection = selection.slice(s.filter(n => n != undefined).length); + if (!subSelection && s.length - 20 <= selection.length) done = true; + else for (let j in subSelection) if (!done && !canceled) { + if (original[i] == subSelection[j]) { + s[i] = subSelection[j]; + f[i] = subSelection[j]; + wrong = 0; + if (i == original.length) done = true; + } + else { + s[i] = null; + f[i] = original[i]; + wrong++; + if (wrong > 4) { + s = [], f = [], wrong = 0, canceled = true; + break; + } + } + break; + } + canceled = false; + i++; + } + } + if (s.filter(n => n).length) { + let reverseS = [].concat(s).reverse(), i = 0, j = 0; + for (let k in s) { + if (s[k] == null) i = parseInt(k) + 1; + else break; + } + for (let k in reverseS) { + if (reverseS[k] == null) j = parseInt(k) + 1; + else break; + } + return f.slice(i, f.length - j).join(""); + } + else return original; + }; + + BDFDB.SlateUtils = {}; + BDFDB.SlateUtils.isRichValue = function (richValue) { + return BDFDB.ObjectUtils.is(richValue) && LibraryModules.SlateUtils.deserialize("").constructor.prototype.isPrototypeOf(richValue); + }; + BDFDB.SlateUtils.copyRichValue = function (string, richValue) { + let newRichValue = LibraryModules.SlateUtils.deserialize(string); + if (BDFDB.SlateUtils.isRichValue(richValue) && richValue._map && richValue._map._root && BDFDB.ArrayUtils.is(richValue._map._root.entries)) { + for (let i in richValue._map._root.entries) if (richValue._map._root.entries[i][0] == "selection") { + newRichValue._map._root.entries[i] = richValue._map._root.entries[i]; + break; + } + } + return newRichValue; + }; + BDFDB.SlateUtils.hasOpenPlainTextCodeBlock = function (editor) { + let richValue = BDFDB.ObjectUtils.get(editor, "props.richValue"); + if (!BDFDB.SlateUtils.isRichValue(richValue)) return false; + let codeMatches = BDFDB.LibraryModules.SlateSelectionUtils.serializeSelection(richValue.document, { + start: { + key: richValue.document.getFirstText().key, + offset: 0 + }, + end: richValue.selection.start + }, "raw").match(/```/g); + return codeMatches && codeMatches.length && codeMatches.length % 2 != 0; + }; + BDFDB.SlateUtils.getCurrentWord = function (editor) { + let richValue = BDFDB.ObjectUtils.get(editor, "props.richValue"); + if (!BDFDB.SlateUtils.isRichValue(richValue) || !richValue.selection.isCollapsed || BDFDB.SlateUtils.hasOpenPlainTextCodeBlock(editor) || richValue.document.text.trim().length == 0) return {word: null, isAtStart: false}; + if (editor.props.useSlate) { + if (richValue.document.text.startsWith("/giphy ") || richValue.document.text.startsWith("/tenor ")) { + let node = richValue.document.getNode(richValue.selection.start.key); + if (node) return { + word: node.text.substring(0, richValue.selection.start.offset), + isAtStart: true + } + } + let node = richValue.document.getNode(richValue.selection.start.key); + if (node == null) return { + word: null, + isAtStart: false + }; + let word = "", atStart = false; + let offset = richValue.selection.start.offset; + let block = richValue.document.getClosestBlock(node.key); + while (true) { + if (--offset < 0) { + if ((node = block.getPreviousNode(node.key) == null)) { + atStart = true; + break; + } + if (node.object!== "text") break; + offset = node.text.length - 1; + } + if (node.object !== "text") break; + let prefix = node.text[offset]; + if (/(\t|\s)/.test(prefix)) break; + word = prefix + word; + } + return { + word: !word ? null : word, + isAtStart: atStart && block.type == "line" && richValue.document.nodes.get(0) === block + }; + } + else { + let textarea = BDFDB.ReactUtils.findDOMNode(editor.ref.current); + if (!Node.prototype.isPrototypeOf(textarea) || textarea.tagName != "TEXTAREA" || !textarea.value.length || /\s/.test(textarea.value.slice(textarea.selectionStart, textarea.selectionEnd))) return { + word: null, + isAtStart: true + }; + else { + if (textarea.selectionEnd == textarea.value.length) { + let words = textarea.value.split(/\s/).reverse(); + return { + word: !words[0] ? null : words[0], + isAtStart: words.length > 1 + }; + } + else { + let chars = textarea.value.split(""), word = "", currentWord = "", isCurrentWord = false, isAtStart = true; + for (let i in chars) { + if (i == textarea.selectionStart) isCurrentWord = true; + if (/\s/.test(chars[i])) { + word = ""; + isAtStart = currentWord.length > 0 && isAtStart || false; + isCurrentWord = false; + } + else { + word += chars[i]; + if (isCurrentWord) currentWord = word; + } + } + return { + word: !currentWord ? null : currentWord, + isAtStart: isAtStart + }; + } + } + } + }; + + BDFDB.NumberUtils = {}; + BDFDB.NumberUtils.formatBytes = function (bytes, sigDigits) { + bytes = parseInt(bytes); + if (isNaN(bytes) || bytes < 0) return "0 Bytes"; + if (bytes == 1) return "1 Byte"; + let size = Math.floor(Math.log(bytes) / Math.log(1024)); + return parseFloat((bytes / Math.pow(1024, size)).toFixed(sigDigits < 1 ? 0 : sigDigits > 20 ? 20 : sigDigits || 2)) + " " + ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"][size]; + }; + BDFDB.NumberUtils.mapRange = function (from, to, value) { + if (parseFloat(value) < parseFloat(from[0])) return parseFloat(to[0]); + else if (parseFloat(value) > parseFloat(from[1])) return parseFloat(to[1]); + else return parseFloat(to[0]) + (parseFloat(value) - parseFloat(from[0])) * (parseFloat(to[1]) - parseFloat(to[0])) / (parseFloat(from[1]) - parseFloat(from[0])); + }; + BDFDB.NumberUtils.generateId = function (array) { + array = BDFDB.ArrayUtils.is(array) ? array : []; + let id = Math.floor(Math.random() * 10000000000000000); + if (array.includes(id)) return BDFDB.NumberUtils.generateId(array); + else { + array.push(id); + return id; + } + }; + BDFDB.NumberUtils.compareVersions = function (newv, oldv) { + if (!newv || !oldv) return true; + newv = newv.toString().replace(/["'`]/g, "").split(/,|\./g).map(n => parseInt(n)).filter(n => (n || n == 0) && !isNaN(n)); + oldv = oldv.toString().replace(/["'`]/g, "").split(/,|\./g).map(n => parseInt(n)).filter(n => (n || n == 0) && !isNaN(n)); + var length = Math.max(newv.length, oldv.length); + if (!length) return true; + if (newv.length > oldv.length) { + var temparray = new Array(newv.length - oldv.length); + for (let i = 0; i < temparray.length; i++) temparray[i] = 0; + oldv = temparray.concat(oldv); + } + else if (newv.length < oldv.length) { + var temparray = new Array(oldv.length - newv.length); + for (let i = 0; i < temparray.length; i++) temparray[i] = 0; + newv = temparray.concat(newv); + } + for (let i = 0; i < length; i++) for (let ioutdated = false, j = 0; j <= i; j++) { + if (j == i && newv[j] < oldv[j]) return false; + if (j < i) ioutdated = newv[j] == oldv[j]; + if ((j == 0 || ioutdated) && j == i && newv[j] > oldv[j]) return true; + } + return false; + }; + BDFDB.NumberUtils.getVersionDifference = function (newv, oldv) { + if (!newv || !oldv) return false; + newv = newv.toString().replace(/["'`]/g, "").split(/,|\./g).map(n => parseInt(n)).filter(n => (n || n == 0) && !isNaN(n)); + oldv = oldv.toString().replace(/["'`]/g, "").split(/,|\./g).map(n => parseInt(n)).filter(n => (n || n == 0) && !isNaN(n)); + var length = Math.max(newv.length, oldv.length); + if (!length) return false; + if (newv.length > oldv.length) { + var temparray = new Array(newv.length - oldv.length); + for (let i = 0; i < temparray.length; i++) temparray[i] = 0; + oldv = temparray.concat(oldv); + } + else if (newv.length < oldv.length) { + var temparray = new Array(oldv.length - newv.length); + for (let i = 0; i < temparray.length; i++) temparray[i] = 0; + newv = temparray.concat(newv); + } + var oldvvalue = 0, newvvalue = 0; + for (let i in oldv.reverse()) oldvvalue += (oldv[i] * (10 ** i)); + for (let i in newv.reverse()) newvvalue += (newv[i] * (10 ** i)); + return (newvvalue - oldvvalue) / (10 ** (length-1)); + }; + + BDFDB.DiscordUtils = {}; + BDFDB.DiscordUtils.openLink = function (url, inbuilt, minimized) { + if (!inbuilt) window.open(url, "_blank"); + else { + let browserWindow = new LibraryRequires.electron.remote.BrowserWindow({ + frame: true, + resizeable: true, + show: true, + darkTheme: BDFDB.DiscordUtils.getTheme() == BDFDB.disCN.themedark, + webPreferences: { + nodeIntegration: false, + nodeIntegrationInWorker: false + } + }); + browserWindow.setMenu(null); + browserWindow.loadURL(url); + if (minimized) browserWindow.minimize(null); + } + }; + BDFDB.DiscordUtils.getFolder = function () { + var built = BDFDB.DiscordUtils.getBuilt(); + built = "discord" + (built == "stable" ? "" : built); + return LibraryRequires.path.resolve(LibraryRequires.electron.remote.app.getPath("appData"), built, BDFDB.DiscordUtils.getVersion()); + }; + BDFDB.DiscordUtils.getBuilt = function () { + if (BDFDB.DiscordUtils.getBuilt.built) return BDFDB.DiscordUtils.getBuilt.built; + else { + var built = null; + try {built = require(LibraryRequires.electron.remote.app.getAppPath() + "/build_info.json").releaseChannel.toLowerCase();} + catch (err) { + try {built = require(LibraryRequires.electron.remote.app.getAppPath().replace("\app.asar", "") + "/build_info.json").releaseChannel.toLowerCase();} + catch (err) { + var version = BDFDB.DiscordUtils.getVersion(); + if (version) { + version = version.split("."); + if (version.length == 3 && !isNaN(version = parseInt(version[2]))) built = version > 300 ? "stable" : da > 200 ? "canary" : "ptb"; + else built = "stable"; + } + else built = "stable"; + } + } + BDFDB.DiscordUtils.getBuilt.built = built; + return built; + } + }; + BDFDB.DiscordUtils.getVersion = function () { + if (BDFDB.DiscordUtils.getBuilt.version) return BDFDB.DiscordUtils.getBuilt.version; + else { + let version = null; + try {version = LibraryRequires.electron.remote.app.getVersion();} + catch (err) {version = "";} + BDFDB.DiscordUtils.getBuilt.version = version; + return version; + } + }; + BDFDB.DiscordUtils.isDevModeEnabled = function () { + return LibraryModules.StoreChangeUtils.get("UserSettingsStore").developerMode; + }; + BDFDB.DiscordUtils.getTheme = function () { + return LibraryModules.StoreChangeUtils.get("UserSettingsStore").theme == "dark" ? BDFDB.disCN.themedark : BDFDB.disCN.themelight; + }; + BDFDB.DiscordUtils.getMode = function () { + return LibraryModules.StoreChangeUtils.get("UserSettingsStore").message_display_compact ? "compact" : "cozy"; + }; + BDFDB.DiscordUtils.getZoomFactor = function () { + let aRects = BDFDB.DOMUtils.getRects(document.querySelector(BDFDB.dotCN.appmount)); + let widthZoom = Math.round(100 * window.outerWidth / aRects.width); + let heightZoom = Math.round(100 * window.outerHeight / aRects.height); + return widthZoom < heightZoom ? widthZoom : heightZoom; + }; + BDFDB.DiscordUtils.getFontScale = function () { + return parseInt(document.firstElementChild.style.fontSize.replace("%", "")); + }; + BDFDB.DiscordUtils.shake = function () { + BDFDB.ReactUtils.getInstance(document.querySelector(BDFDB.dotCN.appold)).return.stateNode.shake(); + }; + + BDFDB.WindowUtils = {}; + BDFDB.WindowUtils.open = function (plugin, url, options = {}) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !url) return; + if (!BDFDB.ArrayUtils.is(plugin.browserWindows)) plugin.browserWindows = []; + let config = Object.assign({ + show: false, + webPreferences: { + nodeIntegration: true, + nodeIntegrationInWorker: true + } + }, options); + let browserWindow = new LibraryRequires.electron.remote.BrowserWindow(BDFDB.ObjectUtils.exclude(config, "showOnReady", "onLoad")); + + if (!config.show && config.showOnReady) browserWindow.once("ready-to-show", browserWindow.show); + if (config.devTools) browserWindow.openDevTools(); + if (typeof config.onLoad == "function") browserWindow.webContents.on("did-finish-load", (...args) => {config.onLoad(...args);}); + if (typeof config.onClose == "function") browserWindow.once("closed", (...args) => {config.onClose(...args);}); + + if (typeof browserWindow.removeMenu == "function") browserWindow.removeMenu(); + else browserWindow.setMenu(null); + browserWindow.loadURL(url); + browserWindow.executeJavaScriptSafe = js => {if (!browserWindow.isDestroyed()) browserWindow.webContents.executeJavaScript(`(_ => {${js}})();`);}; + plugin.browserWindows.push(browserWindow); + return browserWindow; + }; + BDFDB.WindowUtils.close = function (browserWindow) { + if (BDFDB.ObjectUtils.is(browserWindow) && !browserWindow.isDestroyed() && browserWindow.isClosable()) browserWindow.close(); + }; + BDFDB.WindowUtils.closeAll = function (plugin) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ArrayUtils.is(plugin.browserWindows)) return; + while (plugin.browserWindows.length) BDFDB.WindowUtils.close(plugin.browserWindows.pop()); + }; + BDFDB.WindowUtils.addListener = function (plugin, actions, callback) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !actions || typeof callback != "function") return; + BDFDB.WindowUtils.removeListener(plugin, actions); + for (let action of actions.split(" ")) { + action = action.split("."); + let eventName = action.shift(); + if (!eventName) return; + let namespace = (action.join(".") || "") + plugin.name; + if (!BDFDB.ArrayUtils.is(plugin.ipcListeners)) plugin.ipcListeners = []; + + plugin.ipcListeners.push({eventName, namespace, callback}); + LibraryRequires.electron.ipcRenderer.on(eventName, callback); + } + }; + BDFDB.WindowUtils.removeListener = function (plugin, actions = "") { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (!BDFDB.ObjectUtils.is(plugin) || !BDFDB.ArrayUtils.is(plugin.ipcListeners)) return; + if (actions) { + for (let action of actions.split(" ")) { + action = action.split("."); + let eventName = action.shift(); + let namespace = (action.join(".") || "") + plugin.name; + for (let listener of plugin.ipcListeners) { + let removedListeners = []; + if (listener.eventName == eventName && listener.namespace == namespace) { + LibraryRequires.electron.ipcRenderer.off(listener.eventName, listener.callback); + removedListeners.push(listener); + } + if (removedListeners.length) plugin.ipcListeners = plugin.ipcListeners.filter(listener => {return removedListeners.indexOf(listener) < 0;}); + } + } + } + else { + for (let listener of plugin.ipcListeners) LibraryRequires.electron.ipcRenderer.off(listener.eventName, listener.callback); + plugin.ipcListeners = []; + } + }; + + BDFDB.BDUtils = {}; + BDFDB.BDUtils.getPluginsFolder = function () { + if (LibraryRequires.process.env.injDir) return LibraryRequires.path.resolve(LibraryRequires.process.env.injDir, "plugins/"); + else switch (LibraryRequires.process.platform) { + case "win32": + return LibraryRequires.path.resolve(LibraryRequires.process.env.appdata, "BetterDiscord/plugins/"); + case "darwin": + return LibraryRequires.path.resolve(LibraryRequires.process.env.HOME, "Library/Preferences/BetterDiscord/plugins/"); + default: + if (LibraryRequires.process.env.XDG_CONFIG_HOME) return LibraryRequires.path.resolve(LibraryRequires.process.env.XDG_CONFIG_HOME, "BetterDiscord/plugins/"); + else return LibraryRequires.path.resolve(LibraryRequires.process.env.HOME, ".config/BetterDiscord/plugins/"); + } + }; + BDFDB.BDUtils.getThemesFolder = function () { + if (LibraryRequires.process.env.injDir) return LibraryRequires.path.resolve(LibraryRequires.process.env.injDir, "plugins/"); + else switch (LibraryRequires.process.platform) { + case "win32": + return LibraryRequires.path.resolve(LibraryRequires.process.env.appdata, "BetterDiscord/themes/"); + case "darwin": + return LibraryRequires.path.resolve(LibraryRequires.process.env.HOME, "Library/Preferences/BetterDiscord/themes/"); + default: + if (LibraryRequires.process.env.XDG_CONFIG_HOME) return LibraryRequires.path.resolve(LibraryRequires.process.env.XDG_CONFIG_HOME, "BetterDiscord/themes/"); + else return LibraryRequires.path.resolve(LibraryRequires.process.env.HOME, ".config/BetterDiscord/themes/"); + } + }; + BDFDB.BDUtils.isPluginEnabled = function (pluginName) { + if (!window.BdApi) return null; + else if (BdApi.Plugins && typeof BdApi.Plugins.isEnabled == "function") return BdApi.Plugins.isEnabled(pluginName); + else if (typeof BdApi.isPluginEnabled == "function") return BdApi.isPluginEnabled(pluginName); + }; + BDFDB.BDUtils.reloadPlugin = function (pluginName) { + if (!window.BdApi) return; + else if (BdApi.Plugins && typeof BdApi.Plugins.reload == "function") BdApi.Plugins.reload(pluginName); + else if (window.pluginModule) window.pluginModule.reloadPlugin(pluginName); + }; + BDFDB.BDUtils.enablePlugin = function (pluginName) { + if (!window.BdApi) return; + else if (BdApi.Plugins && typeof BdApi.Plugins.enable == "function") BdApi.Plugins.enable(pluginName); + else if (window.pluginModule) window.pluginModule.startPlugin(pluginName); + }; + BDFDB.BDUtils.disablePlugin = function (pluginName) { + if (!window.BdApi) return; + else if (BdApi.Plugins && typeof BdApi.Plugins.disable == "function") BdApi.Plugins.disable(pluginName); + else if (window.pluginModule) window.pluginModule.stopPlugin(pluginName); + }; + BDFDB.BDUtils.getPlugin = function (pluginName, hasToBeEnabled = false, overHead = false) { + if (window.BdApi && !hasToBeEnabled || BDFDB.BDUtils.isPluginEnabled(pluginName)) { + if (BdApi.Plugins.get && typeof BdApi.Plugins.get == "function") { + let plugin = BdApi.Plugins.get(pluginName); + if (overHead) return plugin ? {filename: LibraryRequires.fs.existsSync(LibraryRequires.path.join(BDFDB.BDUtils.getPluginsFolder(), `${pluginName}.plugin.js`)) ? `${pluginName}.plugin.js` : null, id: pluginName, name: pluginName, plugin: plugin} : null; + else return plugin; + } + else if (window.bdplugins) overHead ? window.bdplugins[pluginName] : (window.bdplugins[pluginName] || {}).plugin; + } + return null; + }; + BDFDB.BDUtils.isThemeEnabled = function (themeName) { + if (!window.BdApi) return null; + else if (BdApi.Themes && typeof BdApi.Themes.isEnabled == "function") return BdApi.Themes.isEnabled(themeName); + else if (typeof BdApi.isThemeEnabled == "function") return BdApi.isThemeEnabled(themeName); + }; + BDFDB.BDUtils.enableTheme = function (themeName) { + if (!window.BdApi) return; + else if (BdApi.Themes && typeof BdApi.Themes.enable == "function") BdApi.Themes.enable(themeName); + else if (window.themeModule) window.themeModule.enableTheme(themeName); + }; + BDFDB.BDUtils.disableTheme = function (themeName) { + if (!window.BdApi) return; + else if (BdApi.Themes && typeof BdApi.Themes.disable == "function") BdApi.Themes.disable(themeName); + else if (window.themeModule) window.themeModule.disableTheme(themeName); + }; + BDFDB.BDUtils.getTheme = function (themeName, hasToBeEnabled = false) { + if (window.BdApi && !hasToBeEnabled || BDFDB.BDUtils.isThemeEnabled(themeName)) { + if (BdApi.Themes && typeof BdApi.Themes.get == "function") return BdApi.Themes.get(themeName); + else if (window.bdthemes) window.bdthemes[themeName]; + } + return null; + }; + BDFDB.BDUtils.settingsIds = { + automaticLoading: "settings.addons.autoReload", + coloredText: "settings.appearance.coloredText", + normalizedClasses: "settings.general.classNormalizer", + showToasts: "settings.general.showToasts" + }; + BDFDB.BDUtils.toggleSettings = function (key, state) { + if (window.BdApi && typeof key == "string") { + let path = key.split("."); + let currentState = BDFDB.BDUtils.getSettings(key); + if (state === true) { + if (currentState === false) BdApi.enableSetting(...path); + } + else if (state === false) { + if (currentState === true) BdApi.disableSetting(...path); + } + else if (currentState === true || currentState === false) BDFDB.BDUtils.toggleSettings(key, !currentState); + } + }; + BDFDB.BDUtils.getSettings = function (key) { + if (!window.BdApi) return {}; + if (typeof key == "string") return BdApi.isSettingEnabled(...key.split(".")); + else return BdApi.settings.map(n => n.settings.map(m => m.settings.map(l => ({id: [n.id, m.id, l.id].join("."), value:l.value})))).flat(10).reduce((newObj, setting) => (newObj[setting.id] = setting.value, newObj), {}); + }; + + const DiscordClassModules = Object.assign({}, InternalData.CustomClassModules); + for (let name in InternalData.DiscordClassModules) { + if (InternalData.DiscordClassModules[name].length) DiscordClassModules[name] = BDFDB.ModuleUtils.find(m => InternalData.DiscordClassModules[name].props.every(prop => typeof m[prop] == "string") && (InternalData.DiscordClassModules[name].smaller ? Object.keys(m).length < InternalData.DiscordClassModules[name].length : Object.keys(m).length == InternalData.DiscordClassModules[name].length)); + else DiscordClassModules[name] = BDFDB.ModuleUtils.findByProperties(InternalData.DiscordClassModules[name].props); + } + BDFDB.DiscordClassModules = Object.assign({}, DiscordClassModules); + + const DiscordClasses = Object.assign({}, InternalData.DiscordClasses); + InternalBDFDB.getDiscordClass = (item, selector) => { + let className = DiscordClassModules.BDFDB.BDFDBundefined; + if (DiscordClasses[item] === undefined) { + BDFDB.LogUtils.warn(item + " not found in DiscordClasses"); + return className; + } + else if (!BDFDB.ArrayUtils.is(DiscordClasses[item]) || DiscordClasses[item].length != 2) { + BDFDB.LogUtils.warn(item + " is not an Array of Length 2 in DiscordClasses"); + return className; + } + else if (DiscordClassModules[DiscordClasses[item][0]] === undefined) { + BDFDB.LogUtils.warn(DiscordClasses[item][0] + " not found in DiscordClassModules"); + return className; + } + else if (DiscordClassModules[DiscordClasses[item][0]][DiscordClasses[item][1]] === undefined) { + BDFDB.LogUtils.warn(DiscordClasses[item][1] + " not found in " + DiscordClasses[item][0] + " in DiscordClassModules"); + return className; + } + else { + className = DiscordClassModules[DiscordClasses[item][0]][DiscordClasses[item][1]]; + if (selector) { + className = className.split(" ").filter(n => n.indexOf("da-") != 0).join(selector ? "." : " "); + className = className || DiscordClassModules.BDFDB.BDFDBundefined; + } + else { + if (BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.normalizedClasses)) className = className.split(" ").filter(n => n.indexOf("da-") != 0).map(n => n.replace(/^([A-z0-9]+?)-([A-z0-9_-]{6})$/g, "$1-$2 da-$1")).join(" "); + } + return BDFDB.ArrayUtils.removeCopies(className.split(" ")).join(" "); + } + }; + BDFDB.disCN = new Proxy(DiscordClasses, { + get: function (list, item) { + return InternalBDFDB.getDiscordClass(item, false).replace("#", ""); + } + }); + BDFDB.disCNS = new Proxy(DiscordClasses, { + get: function (list, item) { + return InternalBDFDB.getDiscordClass(item, false).replace("#", "") + " "; + } + }); + BDFDB.disCNC = new Proxy(DiscordClasses, { + get: function (list, item) { + return InternalBDFDB.getDiscordClass(item, false).replace("#", "") + ","; + } + }); + BDFDB.dotCN = new Proxy(DiscordClasses, { + get: function (list, item) { + let className = InternalBDFDB.getDiscordClass(item, true); + return (className.indexOf("#") == 0 ? "" : ".") + className; + } + }); + BDFDB.dotCNS = new Proxy(DiscordClasses, { + get: function (list, item) { + let className = InternalBDFDB.getDiscordClass(item, true); + return (className.indexOf("#") == 0 ? "" : ".") + className + " "; + } + }); + BDFDB.dotCNC = new Proxy(DiscordClasses, { + get: function (list, item) { + let className = InternalBDFDB.getDiscordClass(item, true); + return (className.indexOf("#") == 0 ? "" : ".") + className + ","; + } + }); + BDFDB.notCN = new Proxy(DiscordClasses, { + get: function (list, item) { + return `:not(.${InternalBDFDB.getDiscordClass(item, true).split(".")[0]})`; + } + }); + BDFDB.notCNS = new Proxy(DiscordClasses, { + get: function (list, item) { + return `:not(.${InternalBDFDB.getDiscordClass(item, true).split(".")[0]}) `; + } + }); + BDFDB.notCNC = new Proxy(DiscordClasses, { + get: function (list, item) { + return `:not(.${InternalBDFDB.getDiscordClass(item, true).split(".")[0]}),`; + } + }); + + const LanguageStrings = LibraryModules.LanguageStore && LibraryModules.LanguageStore._proxyContext ? Object.assign({}, LibraryModules.LanguageStore._proxyContext.defaultMessages) : {}; + const LibraryStrings = Object.assign({}, InternalData.LibraryStrings); + BDFDB.LanguageUtils = {}; + BDFDB.LanguageUtils.languages = Object.assign({}, InternalData.Languages); + BDFDB.LanguageUtils.getLanguage = function () { + let lang = LibraryModules.LanguageStore.chosenLocale || "en"; + if (lang == "en-GB" || lang == "en-US") lang = "en"; + let langIds = lang.split("-"); + let langId = langIds[0]; + let langId2 = langIds[1] || ""; + lang = langId2 && langId.toUpperCase() !== langId2.toUpperCase() ? langId + "-" + langId2 : langId; + return BDFDB.LanguageUtils.languages[lang] || BDFDB.LanguageUtils.languages[langId] || BDFDB.LanguageUtils.languages["en"]; + }; + BDFDB.LanguageUtils.LanguageStrings = new Proxy(LanguageStrings, { + get: function (list, item) { + let stringObj = LibraryModules.LanguageStore.Messages[item]; + if (!stringObj) BDFDB.LogUtils.warn(item + " not found in BDFDB.LanguageUtils.LanguageStrings"); + else { + if (stringObj && typeof stringObj == "object" && typeof stringObj.format == "function") return BDFDB.LanguageUtils.LanguageStringsFormat(item); + else return stringObj; + } + return ""; + } + }); + BDFDB.LanguageUtils.LanguageStringsCheck = new Proxy(LanguageStrings, { + get: function (list, item) { + return !!LibraryModules.LanguageStore.Messages[item]; + } + }); + let parseLanguageStringObj = obj => { + let string = ""; + if (typeof obj == "string") string += obj; + else if (BDFDB.ObjectUtils.is(obj)) { + if (obj.props) string += parseLanguageStringObj(obj.props); + else if (obj.type) { + let text = obj.content || obj.children && obj.children[0] && obj.children[0].toString() || ""; + if (text) { + if (obj.type == "text" || obj.content) string = parseLanguageStringObj(text); + else string += `<${obj.type}>${parseLanguageStringObj(text)}`; + } + } + } + else if (BDFDB.ArrayUtils.is(obj)) for (let ele of obj) string += parseLanguageStringObj(ele); + return string; + }; + BDFDB.LanguageUtils.LanguageStringsFormat = function (item, ...values) { + if (item) { + let stringObj = LibraryModules.LanguageStore.Messages[item]; + if (stringObj && typeof stringObj == "object" && typeof stringObj.format == "function") { + let i = 0, returnvalue, formatVars = {}; + while (!returnvalue && i < 10) { + i++; + try {returnvalue = stringObj.format(formatVars, false);} + catch (err) { + returnvalue = null; + let value = values.shift(); + formatVars[err.toString().split("for: ")[1]] = value != null ? (value === 0 ? "0" : value) : "undefined"; + } + } + if (returnvalue) return parseLanguageStringObj(returnvalue); + else { + BDFDB.LogUtils.warn(item + " failed to format string in BDFDB.LanguageUtils.LanguageStrings"); + return ""; + } + } + else return BDFDB.LanguageUtils.LanguageStrings[item]; + } + else BDFDB.LogUtils.warn(item + " enter a valid key to format the string in BDFDB.LanguageUtils.LanguageStrings"); + return ""; + }; + BDFDB.LanguageUtils.LibraryStrings = new Proxy(LibraryStrings.default || {}, { + get: function (list, item) { + let languageId = BDFDB.LanguageUtils.getLanguage().id; + if (LibraryStrings[languageId] && LibraryStrings[languageId][item]) return LibraryStrings[languageId][item]; + else if (LibraryStrings.default[item]) return LibraryStrings.default[item]; + else BDFDB.LogUtils.warn(item + " not found in BDFDB.LanguageUtils.LibraryStrings"); + return ""; + } + }); + BDFDB.LanguageUtils.LibraryStringsCheck = new Proxy(LanguageStrings, { + get: function (list, item) { + return !!LibraryStrings.default[item]; + } + }); + BDFDB.LanguageUtils.LibraryStringsFormat = function (item, ...values) { + if (item && values.length) { + let languageId = BDFDB.LanguageUtils.getLanguage().id, string = null; + if (LibraryStrings[languageId] && LibraryStrings[languageId][item]) string = LibraryStrings[languageId][item]; + else if (LibraryStrings.default[item]) string = LibraryStrings.default[item]; + if (string) { + for (let i = 0; i < values.length; i++) if (typeof values[i] == "string") string = string.replace(new RegExp(`{{var${i}}}`, "g"), values[i]); + return string; + } + else BDFDB.LogUtils.warn(item + " not found in BDFDB.LanguageUtils.LibraryStrings"); + } + else BDFDB.LogUtils.warn(item + " enter a valid key and at least one value to format the string in BDFDB.LanguageUtils.LibraryStrings"); + return ""; + }; + BDFDB.TimeUtils.interval(interval => { + if (LibraryModules.LanguageStore.chosenLocale) { + BDFDB.TimeUtils.clear(interval); + let language = BDFDB.LanguageUtils.getLanguage(); + if (language) BDFDB.LanguageUtils.languages.$discord = Object.assign({}, language, {name: `Discord (${language.name})`}); + } + }, 100); + + const reactInitialized = LibraryModules.React && LibraryModules.React.Component; + InternalBDFDB.setDefaultProps = function (component, defaultProps) { + if (BDFDB.ObjectUtils.is(component)) component.defaultProps = Object.assign({}, component.defaultProps, defaultProps); + }; + let openedItem; + InternalComponents.MenuItem = reactInitialized && class BDFDB_MenuItem extends LibraryModules.React.Component { + constructor(props) { + super(props); + this.state = {hovered: false}; + } + componentWillUnmount() { + if (openedItem == this.props.id) openedItem = null; + } + render() { + let color = (typeof this.props.color == "string" ? this.props.color : InternalComponents.LibraryComponents.MenuItems.Colors.DEFAULT).toLowerCase(); + let isCustomColor = false; + if (color) { + if (BDFDB.DiscordClasses[`menu${color}`]) color = color; + else if (BDFDB.ColorUtils.getType(color)) { + isCustomColor = true; + color = BDFDB.ColorUtils.convert(color, "RGBA"); + } + else color = (InternalComponents.LibraryComponents.MenuItems.Colors.DEFAULT || "").toLowerCase(); + } + let renderPopout, onClose, hasPopout = BDFDB.ObjectUtils.is(this.props.popoutProps); + if (hasPopout) { + renderPopout = instance => { + openedItem = this.props.id; + return typeof this.props.popoutProps.renderPopout == "function" && this.props.popoutProps.renderPopout(instance); + }; + onClose = instance => { + openedItem = null; + typeof this.props.popoutProps.onClose == "function" && this.props.popoutProps.onClose(instance); + }; + } + let focused = !openedItem ? this.props.isFocused : openedItem == this.props.id; + let themeDark = BDFDB.DiscordUtils.getTheme() == BDFDB.disCN.themedark; + let item = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Clickable, Object.assign({ + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.menuitem, BDFDB.disCN.menulabelcontainer, color && (isCustomColor ? BDFDB.disCN.menucolorcustom : BDFDB.disCN[`menu${color}`]), this.props.disabled && BDFDB.disCN.menudisabled, focused && BDFDB.disCN.menufocused), + style: { + color: isCustomColor ? ((focused || this.state.hovered) ? (BDFDB.ColorUtils.isBright(color) ? "#000000" : "#ffffff") : color) : (this.state.hovered ? "#ffffff" : null), + background: isCustomColor && (focused || this.state.hovered) && color + }, + onClick: this.props.disabled ? null : e => { + if (!this.props.action) return false; + !this.props.persisting && !hasPopout && this.props.onClose(); + this.props.action(e, this); + }, + onMouseEnter: this.props.disabled ? null : e => { + this.setState({hovered: true}); + }, + onMouseLeave: this.props.disabled ? null : e => { + this.setState({hovered: false}); + }, + "aria-disabled": this.props.disabled, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.menulabel, + children: [ + typeof this.props.label == "function" ? this.props.label(this) : this.props.label, + this.props.subtext && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.menusubtext, + children: typeof this.props.subtext == "function" ? this.props.subtext(this) : this.props.subtext + }) + ].filter(n => n) + }), + this.props.hint && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.menuhintcontainer, + children: typeof this.props.hint == "function" ? this.props.hint(this) : this.props.hint + }), + this.props.icon && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.menuiconcontainer, + children: BDFDB.ReactUtils.createElement(this.props.icon, { + className: BDFDB.disCN.menuicon, + }) + }), + this.props.imageUrl && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.menuimagecontainer, + children: BDFDB.ReactUtils.createElement("img", { + className: BDFDB.disCN.menuimage, + src: typeof this.props.imageUrl == "function" ? this.props.imageUrl(this) : this.props.imageUrl, + alt: "" + }) + }) + ].filter(n => n) + }, this.props.menuItemProps, {isFocused: focused})); + return hasPopout ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutContainer, Object.assign({}, this.props.popoutProps, { + children: item, + renderPopout: renderPopout, + onClose: onClose + })) : item; + } + }; + InternalComponents.CustomMenuItemWrapper = reactInitialized && class BDFDB_CustomMenuItemWrapper extends LibraryModules.React.Component { + constructor(props) { + super(props); + this.state = {hovered: false}; + } + render() { + return BDFDB.ReactUtils.createElement("div", { + onMouseEnter: e => { + this.setState({hovered: true}); + }, + onMouseLeave: e => { + this.setState({hovered: false}); + }, + children: BDFDB.ReactUtils.createElement(this.props.children, Object.assign({}, this.props.childProps, {isFocused:this.state.hovered && !this.props.disabled})) + }); + } + }; + InternalComponents.ErrorBoundary = reactInitialized && class BDFDB_ErrorBoundary extends LibraryModules.React.PureComponent { + constructor(props) { + super(props); + this.state = {hasError: false}; + } + static getDerivedStateFromError(error) { + return {hasError: true}; + } + componentDidCatch(error, info) { + BDFDB.LogUtils.error("Could not create react element! " + error); + } + render() { + if (this.state.hasError) return LibraryModules.React.createElement("span", { + style: { + background: BDFDB.DiscordConstants && BDFDB.DiscordConstants.Colors && BDFDB.DiscordConstants.Colors.PRIMARY_DARK, + borderRadius: 5, + color: BDFDB.DiscordConstants && BDFDB.DiscordConstants.Colors && BDFDB.DiscordConstants.Colors.STATUS_RED, + fontSize: 12, + fontWeight: 600, + padding: 6, + textAlign: "center", + verticalAlign: "center" + }, + children: "React Component Error" + }); + return this.props.children; + } + }; + + for (let name in InternalData.NativeSubComponents) { + if (InternalData.NativeSubComponents[name].name) { + if (InternalData.NativeSubComponents[name].protos) InternalComponents.NativeSubComponents[name] = BDFDB.ModuleUtils.find(m => m && m.displayName == InternalData.NativeSubComponents[name].name && m.prototype && InternalData.NativeSubComponents[name].protos.every(proto => m.prototype[proto])); + else InternalComponents.NativeSubComponents[name] = BDFDB.ModuleUtils.findByName(InternalData.NativeSubComponents[name].name); + } + else if (InternalData.NativeSubComponents[name].props) InternalComponents.NativeSubComponents[name] = BDFDB.ModuleUtils.findByProperties(InternalData.NativeSubComponents[name].props); + } + + for (let name in InternalData.LibraryComponents) { + let module; + if (InternalData.LibraryComponents[name].name) module = BDFDB.ModuleUtils.findByName(InternalData.LibraryComponents[name].name); + else if (InternalData.LibraryComponents[name].strings) module = BDFDB.ModuleUtils.findByString(InternalData.LibraryComponents[name].strings); + else if (InternalData.LibraryComponents[name].props) module = BDFDB.ModuleUtils.findByProperties(InternalData.LibraryComponents[name].props); + let child = name, parent = child.split(" "), components = InternalComponents.LibraryComponents; + if (parent.length > 1) { + child = parent[1], parent = parent[0]; + if (!InternalComponents.LibraryComponents[parent]) InternalComponents.LibraryComponents[parent] = {}; + components = InternalComponents.LibraryComponents[parent]; + } + if (InternalData.LibraryComponents[name].value) module = (module || {})[InternalData.LibraryComponents[name].value]; + if (InternalData.LibraryComponents[name].assign) components[child] = Object.assign({}, module); + else components[child] = module; + } + + InternalComponents.LibraryComponents.AddonCard = reactInitialized && class BDFDB_AddonCard extends LibraryModules.React.Component { + render() { + return !BDFDB.ObjectUtils.is(this.props.data) ? null : BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN._repoentry, this.props.className, BDFDB.disCN._repocard, BDFDB.disCN._reposettingsclosed, BDFDB.disCN._repocheckboxitem), + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN._repoheader, + style: {overflow: "visible"}, + children: [ + BDFDB.ReactUtils.createElement("span", { + className: BDFDB.disCN._repoheadertitle, + children: [ + BDFDB.ReactUtils.createElement("span", { + className: BDFDB.disCN._reponame, + children: this.props.data.name + }), + " v", + BDFDB.ReactUtils.createElement("span", { + className: BDFDB.disCN._repoversion, + children: this.props.data.version + }), + " by ", + BDFDB.ReactUtils.createElement("span", { + className: BDFDB.disCN._repoauthor, + children: this.props.data.author + }) + ] + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN._repocontrols, + children: this.props.controls + }) + ] + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN._repodescriptionwrap, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN._repodescription, + children: this.props.data.description + }) + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN._repofooter, + children: [ + BDFDB.ReactUtils.createElement("span", { + className: BDFDB.disCN._repolinks, + children: [].concat(this.props.links).map((link, i) => BDFDB.ObjectUtils.is(link) && [ + i > 0 && " | ", + BDFDB.ReactUtils.createElement("a", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN._repolink, typeof link.label == "string" && BDFDB.disCN._repolink + "-" + link.label.toLowerCase().replace(/\s/g, "")), + href: link.href, + children: link.label + }) + ]).flat(10).filter(n => n) + }), + this.props.buttons + ].flat(10).filter(n => n) + }), + ] + }); + } + }; + + InternalComponents.LibraryComponents.BadgeAnimationContainer = reactInitialized && class BDFDB_BadgeAnimationContainer extends LibraryModules.React.Component { + componentDidMount() {BDFDB.ReactUtils.forceUpdate(this);} + componentWillAppear(e) {if (typeof e == "function") e();} + componentWillEnter(e) {if (typeof e == "function") e();} + componentWillLeave(e) {if (typeof e == "function") this.timeoutId = setTimeout(e, 300);} + componentWillUnmount() {clearTimeout(this.timeoutId)} + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.div, { + className: this.props.className, + style: this.props.animatedStyle, + children: this.props.children + }); + } + }; + + InternalComponents.LibraryComponents.Badges = Object.assign({}, BDFDB.ModuleUtils.findByProperties("IconBadge", "NumberBadge")); + InternalComponents.LibraryComponents.Badges.IconBadge = reactInitialized && class BDFDB_IconBadge extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.badgeiconbadge, this.props.className), + style: Object.assign({ + backgroundColor: this.props.disableColor ? null : (this.props.color || BDFDB.DiscordConstants.Colors.STATUS_RED) + }, this.props.style), + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.badgeicon, + name: this.props.icon + }) + }); + } + }; + + InternalComponents.LibraryComponents.BotTag = reactInitialized && class BDFDB_BotTag extends LibraryModules.React.Component { + handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);} + handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);} + handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);} + handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);} + render() { + return BDFDB.ReactUtils.createElement("span", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, this.props.invertColor ? BDFDB.disCN.bottaginvert : BDFDB.disCN.bottagregular, this.props.useRemSizes ? BDFDB.disCN.bottagrem : BDFDB.disCN.bottagpx), + style: this.props.style, + onClick: this.handleClick.bind(this), + onContextMenu: this.handleContextMenu.bind(this), + onMouseEnter: this.handleMouseEnter.bind(this), + onMouseLeave: this.handleMouseLeave.bind(this), + children: BDFDB.ReactUtils.createElement("span", { + className: BDFDB.disCN.bottagtext, + children: this.props.tag || BDFDB.LanguageUtils.LanguageStrings.BOT_TAG_BOT + }) + }); + } + }; + + InternalComponents.LibraryComponents.Button = reactInitialized && class BDFDB_Button extends LibraryModules.React.Component { + handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);} + handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);} + handleMouseDown(e) {if (typeof this.props.onMouseDown == "function") this.props.onMouseDown(e, this);} + handleMouseUp(e) {if (typeof this.props.onMouseUp == "function") this.props.onMouseUp(e, this);} + handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);} + handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);} + render() { + let processingAndListening = (this.props.disabled || this.props.submitting) && (null != this.props.onMouseEnter || null != this.props.onMouseLeave); + let props = BDFDB.ObjectUtils.exclude(this.props, "look", "color", "hover", "size", "fullWidth", "grow", "disabled", "submitting", "type", "style", "wrapperClassName", "className", "innerClassName", "onClick", "onContextMenu", "onMouseDown", "onMouseUp", "onMouseEnter", "onMouseLeave", "children", "rel"); + let button = BDFDB.ReactUtils.createElement("button", Object.assign({}, !this.props.disabled && !this.props.submitting && props, { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.button, this.props.look != null ? this.props.look : InternalComponents.LibraryComponents.Button.Looks.FILLED, this.props.color != null ? this.props.color : InternalComponents.LibraryComponents.Button.Colors.BRAND, this.props.hover, this.props.size != null ? this.props.size : InternalComponents.LibraryComponents.Button.Sizes.MEDIUM, processingAndListening && this.props.wrapperClassName, this.props.fullWidth && BDFDB.disCN.buttonfullwidth, (this.props.grow === undefined || this.props.grow) && BDFDB.disCN.buttongrow, this.props.hover && this.props.hover !== InternalComponents.LibraryComponents.Button.Hovers.DEFAULT && BDFDB.disCN.buttonhashover, this.props.submitting && BDFDB.disCN.buttonsubmitting), + onClick: (this.props.disabled || this.props.submitting) ? e => {return e.preventDefault();} : this.handleClick.bind(this), + onContextMenu: (this.props.disabled || this.props.submitting) ? e => {return e.preventDefault();} : this.handleContextMenu.bind(this), + onMouseUp: !this.props.disabled && this.handleMouseDown.bind(this), + onMouseDown: !this.props.disabled && this.handleMouseUp.bind(this), + onMouseEnter: this.handleMouseEnter.bind(this), + onMouseLeave: this.handleMouseLeave.bind(this), + type: !this.props.type ? "button" : this.props.type, + disabled: this.props.disabled, + style: this.props.style, + rel: this.props.rel, + children: [ + this.props.submitting && !this.props.disabled ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Spinner, { + type: InternalComponents.LibraryComponents.Spinner.Type.PULSING_ELLIPSIS, + className: BDFDB.disCN.buttonspinner, + itemClassName: BDFDB.disCN.buttonspinneritem + }) : null, + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.buttoncontents, this.props.innerClassName), + children: this.props.children + }) + ] + })); + return !processingAndListening ? button : BDFDB.ReactUtils.createElement("span", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.buttondisabledwrapper, this.props.wrapperClassName, this.props.size != null ? this.props.size : InternalComponents.LibraryComponents.Button.Sizes.MEDIUM, this.props.fullWidth && BDFDB.disCN.buttonfullwidth, (this.props.grow === undefined || this.props.grow) && BDFDB.disCN.buttongrow), + children: [ + button, + BDFDB.ReactUtils.createElement("span", { + onMouseEnter: this.handleMouseEnter.bind(this), + onMouseLeave: this.handleMouseLeave.bind(this), + className: BDFDB.disCN.buttondisabledoverlay + }) + ] + }); + } + }; + + InternalComponents.LibraryComponents.Card = reactInitialized && class BDFDB_Card extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.hovercardwrapper, this.props.backdrop && BDFDB.disCN.hovercard, this.props.className), + onMouseEnter: e => {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);}, + onMouseLeave: e => {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);}, + onClick: e => {if (typeof this.props.onClick == "function") this.props.onClick(e, this);}, + onContextMenu: e => {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);}, + children: [ + !this.props.noRemove ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.CardRemoveButton, { + onClick: e => { + if (typeof this.props.onRemove == "function") this.props.onRemove(e, this); + BDFDB.ListenerUtils.stopEvent(e); + } + }) : null, + typeof this.props.children == "string" ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextElement, { + className: BDFDB.disCN.hovercardinner, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextScroller, {children: this.props.children}) + }) : this.props.children + ].flat(10).filter(n => n) + }), "backdrop", "noRemove")); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Card, {backdrop:true, noRemove:false}); + + InternalComponents.LibraryComponents.ChannelTextAreaButton = reactInitialized && class BDFDB_ChannelTextAreaButton extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Button, { + look: InternalComponents.LibraryComponents.Button.Looks.BLANK, + size: InternalComponents.LibraryComponents.Button.Sizes.NONE, + "aria-label": this.props.label, + tabIndex: this.props.tabIndex, + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.textareabuttonwrapper, this.props.isActive && BDFDB.disCN.textareabuttonactive), + innerClassName: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.textareabutton, this.props.className, this.props.pulse && BDFDB.disCN.textareaattachbuttonplus), + onClick: this.props.onClick, + onContextMenu: this.props.onContextMenu, + onMouseEnter: this.props.onMouseEnter, + onMouseLeave: this.props.onMouseLeave, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: this.props.iconName, + iconSVG: this.props.iconSVG, + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.textareaicon, this.props.iconClassName, this.props.pulse && BDFDB.disCN.textareaiconpulse), + nativeClass: this.props.nativeClass + }) + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.ChannelTextAreaButton, {tabIndex:0}); + + InternalComponents.LibraryComponents.CharCounter = reactInitialized && class BDFDB_CharCounter extends LibraryModules.React.Component { + getCounterString() { + let input = this.refElement || {}, string = ""; + if (BDFDB.DOMUtils.containsClass(this.refElement, BDFDB.disCN.textarea)) { + let instance = BDFDB.ReactUtils.findOwner(input, {name:"ChannelEditorContainer", up:true}); + if (instance) string = instance.props.textValue; + else string = input.value || input.textContent || ""; + } + else string = input.value || input.textContent || ""; + let start = input.selectionStart || 0, end = input.selectionEnd || 0, selectlength = end - start, selection = BDFDB.DOMUtils.getSelection(); + let select = !selectlength && !selection ? 0 : (selectlength || selection.length); + select = !select ? 0 : (select > string.length ? (end || start ? string.length - (string.length - end - start) : string.length) : select); + let children = [ + typeof this.props.renderPrefix == "function" && this.props.renderPrefix(string.length), + `${string.length}${!this.props.max ? "" : "/" + this.props.max}${!select ? "" : " (" + select + ")"}`, + typeof this.props.renderSuffix == "function" && this.props.renderSuffix(string.length) + ].filter(n => n); + if (typeof this.props.onChange == "function") this.props.onChange(this); + return children.length == 1 ? children[0] : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: children + }); + } + updateCounter() { + if (!this.refElement) return; + BDFDB.TimeUtils.clear(this.updateTimeout); + this.updateTimeout = BDFDB.TimeUtils.timeout(this.forceUpdateCounter.bind(this), 100); + } + forceUpdateCounter() { + if (!this.refElement) return; + this.props.children = this.getCounterString(); + BDFDB.ReactUtils.forceUpdate(this); + } + handleSelection() { + if (!this.refElement) return; + let mousemove = _ => { + BDFDB.TimeUtils.timeout(this.forceUpdateCounter.bind(this), 10); + }; + let mouseup = _ => { + document.removeEventListener("mousemove", mousemove); + document.removeEventListener("mouseup", mouseup); + if (this.refElement.selectionEnd - this.refElement.selectionStart) BDFDB.TimeUtils.timeout(_ => { + document.addEventListener("click", click); + }); + }; + let click = _ => { + BDFDB.TimeUtils.timeout(this.forceUpdateCounter.bind(this), 100); + document.removeEventListener("mousemove", mousemove); + document.removeEventListener("mouseup", mouseup); + document.removeEventListener("click", click); + }; + document.addEventListener("mousemove", mousemove); + document.addEventListener("mouseup", mouseup); + } + componentDidMount() { + if (this.props.refClass) { + let node = BDFDB.ReactUtils.findDOMNode(this); + if (node && node.parentElement) { + this.refElement = node.parentElement.querySelector(this.props.refClass); + if (this.refElement) { + if (!this._updateCounter) this._updateCounter = _ => { + if (!document.contains(node)) BDFDB.ListenerUtils.multiRemove(this.refElement, "keydown click change", this._updateCounter); + else this.updateCounter(); + }; + if (!this._handleSelection) this._handleSelection = _ => { + if (!document.contains(node)) BDFDB.ListenerUtils.multiRemove(this.refElement, "mousedown", this._handleSelection); + else this.handleSelection(); + }; + BDFDB.ListenerUtils.multiRemove(this.refElement, "mousedown", this._handleSelection); + BDFDB.ListenerUtils.multiAdd(this.refElement, "mousedown", this._handleSelection); + if (this.refElement.tagName == "INPUT" || this.refElement.tagName == "TEXTAREA") { + BDFDB.ListenerUtils.multiRemove(this.refElement, "keydown click change", this._updateCounter); + BDFDB.ListenerUtils.multiAdd(this.refElement, "keydown click change", this._updateCounter); + } + else { + if (!this._mutationObserver) this._mutationObserver = new MutationObserver(changes => { + if (!document.contains(node)) this._mutationObserver.disconnect(); + else this.updateCounter(); + }); + else this._mutationObserver.disconnect(); + this._mutationObserver.observe(this.refElement, {childList: true, subtree: true}); + } + this.updateCounter(); + } + else BDFDB.LogUtils.warn("could not find referenceElement for BDFDB_CharCounter"); + } + } + else BDFDB.LogUtils.warn("refClass can not be undefined for BDFDB_CharCounter"); + } + render() { + let string = this.getCounterString(); + BDFDB.TimeUtils.timeout(_ => {if (string != this.getCounterString()) BDFDB.ReactUtils.forceUpdate(this);}); + return BDFDB.ReactUtils.createElement("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.charcounter, this.props.className), + children: string + }), "parsing", "max", "refClass", "renderPrefix", "renderSuffix")); + } + }; + + InternalComponents.LibraryComponents.Checkbox = reactInitialized && class BDFDB_Checkbox extends LibraryModules.React.Component { + handleChange() { + this.props.value = !this.props.value; + if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.Checkbox, Object.assign({}, this.props, {onChange: this.handleChange.bind(this)})); + } + }; + + InternalComponents.LibraryComponents.Clickable = reactInitialized && class BDFDB_Clickable extends LibraryModules.React.Component { + handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);} + handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);} + handleMouseDown(e) {if (typeof this.props.onMouseDown == "function") this.props.onMouseDown(e, this);} + handleMouseUp(e) {if (typeof this.props.onMouseUp == "function") this.props.onMouseUp(e, this);} + handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);} + handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);} + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.Clickable, Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName(this.props.className, (this.props.className || "").toLowerCase().indexOf("disabled") == -1 && BDFDB.disCN.cursorpointer), + onClick: this.handleClick.bind(this), + onContextMenu: this.handleContextMenu.bind(this), + onMouseUp: this.handleMouseDown.bind(this), + onMouseDown: !this.props.disabled && this.handleMouseUp.bind(this), + onMouseEnter: this.handleMouseEnter.bind(this), + onMouseLeave: this.handleMouseLeave.bind(this) + })); + } + }; + + InternalComponents.LibraryComponents.CollapseContainer = reactInitialized && class BDFDB_CollapseContainer extends LibraryModules.React.Component { + render() { + if (!BDFDB.ObjectUtils.is(this.props.collapseStates)) this.props.collapseStates = {}; + this.props.collapsed = this.props.collapsed && (this.props.collapseStates[this.props.title] || this.props.collapseStates[this.props.title] == undefined); + this.props.collapseStates[this.props.title] = this.props.collapsed; + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.collapsed && BDFDB.disCN.collapsecontainercollapsed, this.props.mini ? BDFDB.disCN.collapsecontainermini : BDFDB.disCN.collapsecontainer, this.props.className), + id: this.props.id, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.collapsecontainerheader, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + onClick: e => { + this.props.collapsed = !this.props.collapsed; + this.props.collapseStates[this.props.title] = this.props.collapsed; + if (typeof this.props.onClick == "function") this.props.onClick(this.props.collapsed, this); + BDFDB.ReactUtils.forceUpdate(this); + }, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormTitle, { + tag: InternalComponents.LibraryComponents.FormComponents.FormTitle.Tags.H5, + className: BDFDB.disCN.collapsecontainertitle, + children: this.props.title + }) + }), + !this.props.collapsed ? BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.collapsecontainerinner, + children: this.props.children + }) : null + ] + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.CollapseContainer, {collapsed:true, mini:true}); + + InternalComponents.LibraryComponents.ColorPicker = reactInitialized && class BDFDB_ColorPicker extends LibraryModules.React.Component { + constructor(props) { + super(props); + if (!this.state) this.state = {}; + this.state.isGradient = props.gradient && props.color && BDFDB.ObjectUtils.is(props.color); + this.state.gradientBarEnabled = this.state.isGradient; + this.state.draggingAlphaCursor = false; + this.state.draggingGradientCursor = false; + this.state.selectedGradientCursor = 0; + } + handleColorChange(color) { + let changed = false; + if (color != null) { + changed = !BDFDB.equals(this.state.isGradient ? this.props.color[this.state.selectedGradientCursor] : this.props.color, color); + if (this.state.isGradient) this.props.color[this.state.selectedGradientCursor] = color; + else this.props.color = color; + } + else changed = true; + if (changed) { + if (typeof this.props.onColorChange == "function") this.props.onColorChange(this.props.color); + BDFDB.ReactUtils.forceUpdate(this); + } + } + componentDidMount() { + this.domElementRef = {current: BDFDB.DOMUtils.getParent(BDFDB.dotCN.itemlayer, BDFDB.ReactUtils.findDOMNode(this))}; + let popoutContainerInstance = BDFDB.ReactUtils.findOwner(this.domElementRef.current, {name:"BDFDB_PopoutContainer", up:true, unlimited:true}); + if (popoutContainerInstance) { + let mousedown = event => { + if (!this.domElementRef.current || !document.contains(this.domElementRef.current)) document.removeEventListener("mousedown", mousedown); + else if (!this.domElementRef.current.contains(event.target)) { + let mouseup = event => { + if (!this.domElementRef.current || !document.contains(this.domElementRef.current)) { + document.removeEventListener("mousedown", mousedown); + document.removeEventListener("mouseup", mouseup); + } + else if (!this.domElementRef.current.contains(event.target)) { + document.removeEventListener("mousedown", mousedown); + document.removeEventListener("mouseup", mouseup); + popoutContainerInstance.handleClick(event); + } + }; + document.addEventListener("mouseup", mouseup); + } + }; + document.addEventListener("mousedown", mousedown); + } + } + render() { + if (this.state.isGradient) this.props.color = Object.assign({}, this.props.color); + + let hslFormat = this.props.alpha ? "HSLA" : "HSL"; + let hexRegex = this.props.alpha ? /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i : /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i; + + let selectedColor = BDFDB.ColorUtils.convert(this.state.isGradient ? this.props.color[this.state.selectedGradientCursor] : this.props.color, hslFormat) || BDFDB.ColorUtils.convert("#000000FF", hslFormat); + let currentGradient = (this.state.isGradient ? Object.entries(this.props.color, hslFormat) : [[0, selectedColor], [1, selectedColor]]); + + let [h, s, l] = BDFDB.ColorUtils.convert(selectedColor, "HSLCOMP"); + let a = BDFDB.ColorUtils.getAlpha(selectedColor); + a = a == null ? 1 : a; + + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutFocusLock, { + className: BDFDB.disCNS.colorpickerwrapper + BDFDB.disCN.colorpicker, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickerinner, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickersaturation, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickersaturationcolor, + style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0, cursor: "crosshair", backgroundColor: BDFDB.ColorUtils.convert([h, "100%", "100%"], "RGB")}, + onClick: event => { + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickersaturationcolor, event.target)); + let newS = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 100], event.clientX) + "%"; + let newL = BDFDB.NumberUtils.mapRange([rects.top, rects.top + rects.height], [100, 0], event.clientY) + "%"; + this.handleColorChange(BDFDB.ColorUtils.convert([h, newS, newL, a], hslFormat)); + }, + onMouseDown: event => { + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickersaturationcolor, event.target)); + + let mouseup = _ => { + document.removeEventListener("mouseup", mouseup); + document.removeEventListener("mousemove", mousemove); + }; + let mousemove = event2 => { + let newS = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 100], event2.clientX) + "%"; + let newL = BDFDB.NumberUtils.mapRange([rects.top, rects.top + rects.height], [100, 0], event2.clientY) + "%"; + this.handleColorChange(BDFDB.ColorUtils.convert([h, newS, newL, a], hslFormat)); + }; + document.addEventListener("mouseup", mouseup); + document.addEventListener("mousemove", mousemove); + }, + children: [ + BDFDB.ReactUtils.createElement("style", { + children: `${BDFDB.dotCN.colorpickersaturationwhite} {background: -webkit-linear-gradient(to right, #fff, rgba(255,255,255,0));background: linear-gradient(to right, #fff, rgba(255,255,255,0));}${BDFDB.dotCN.colorpickersaturationblack} {background: -webkit-linear-gradient(to top, #000, rgba(0,0,0,0));background: linear-gradient(to top, #000, rgba(0,0,0,0));}` + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickersaturationwhite, + style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0}, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickersaturationblack, + style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0} + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickersaturationcursor, + style: {position: "absolute", cursor: "crosshair", left: s, top: `${BDFDB.NumberUtils.mapRange([0, 100], [100, 0], parseFloat(l))}%`}, + children: BDFDB.ReactUtils.createElement("div", { + style: {width: 4, height: 4, boxShadow: "rgb(255, 255, 255) 0px 0px 0px 1.5px, rgba(0, 0, 0, 0.3) 0px 0px 1px 1px inset, rgba(0, 0, 0, 0.4) 0px 0px 1px 2px", borderRadius: "50%", transform: "translate(-2px, -2px)"} + }) + }) + ] + }) + ] + }) + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickerhue, + children: BDFDB.ReactUtils.createElement("div", { + style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0}, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickerhuehorizontal, + style: {padding: "0px 2px", position: "relative", height: "100%"}, + onClick: event => { + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickerhuehorizontal, event.target)); + let newH = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 360], event.clientX); + this.handleColorChange(BDFDB.ColorUtils.convert([newH, s, l, a], hslFormat)); + }, + onMouseDown: event => { + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickerhuehorizontal, event.target)); + + let mouseup = _ => { + document.removeEventListener("mouseup", mouseup); + document.removeEventListener("mousemove", mousemove); + }; + let mousemove = event2 => { + let newH = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 360], event2.clientX); + this.handleColorChange(BDFDB.ColorUtils.convert([newH, s, l, a], hslFormat)); + }; + document.addEventListener("mouseup", mouseup); + document.addEventListener("mousemove", mousemove); + }, + children: [ + BDFDB.ReactUtils.createElement("style", { + children: `${BDFDB.dotCN.colorpickerhuehorizontal} {background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);background: -webkit-linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);}${BDFDB.dotCN.colorpickerhuevertical} {background: linear-gradient(to top, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);background: -webkit-linear-gradient(to top, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);}` + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickerhuecursor, + style: {position: "absolute", cursor: "ew-resize", left: `${BDFDB.NumberUtils.mapRange([0, 360], [0, 100], h)}%`}, + children: BDFDB.ReactUtils.createElement("div", { + style: {marginTop: 1, width: 4, borderRadius: 1, height: 8, boxShadow: "rgba(0, 0, 0, 0.6) 0px 0px 2px", background: "rgb(255, 255, 255)", transform: "translateX(-2px)"} + }) + }) + ] + }) + }) + }), + this.props.alpha && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickeralpha, + children: [ + BDFDB.ReactUtils.createElement("div", { + style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0}, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickeralphacheckered, + style: {padding: "0px 2px", position: "relative", height: "100%"} + }) + }), + BDFDB.ReactUtils.createElement("div", { + style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0}, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickeralphahorizontal, + style: {padding: "0px 2px", position: "relative", height: "100%", background: `linear-gradient(to right, ${BDFDB.ColorUtils.setAlpha([h, s, l], 0, "RGBA")}, ${BDFDB.ColorUtils.setAlpha([h, s, l], 1, "RGBA")}`}, + onClick: event => { + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickeralphahorizontal, event.target)); + let newA = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 1], event.clientX); + this.handleColorChange(BDFDB.ColorUtils.setAlpha(selectedColor, newA, hslFormat)); + }, + onMouseDown: event => { + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickeralphahorizontal, event.target)); + + let mouseup = _ => { + document.removeEventListener("mouseup", mouseup); + document.removeEventListener("mousemove", mousemove); + this.state.draggingAlphaCursor = false; + BDFDB.ReactUtils.forceUpdate(this); + }; + let mousemove = event2 => { + this.state.draggingAlphaCursor = true; + let newA = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 1], event2.clientX); + this.handleColorChange(BDFDB.ColorUtils.setAlpha(selectedColor, newA, hslFormat)); + }; + document.addEventListener("mouseup", mouseup); + document.addEventListener("mousemove", mousemove); + }, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickeralphacursor, + style: {position: "absolute", cursor: "ew-resize", left: `${a * 100}%`}, + children: [ + BDFDB.ReactUtils.createElement("div", { + style: {marginTop: 1, width: 4, borderRadius: 1, height: 8, boxShadow: "rgba(0, 0, 0, 0.6) 0px 0px 2px", background: "rgb(255, 255, 255)", transform: "translateX(-2px)"} + }), + this.state.draggingAlphaCursor && BDFDB.ReactUtils.createElement("span", { + className: BDFDB.disCN.sliderbubble, + style: {opacity: 1, visibility: "visible", left: 2}, + children: `${Math.floor(a * 100)}%` + }) + ].filter(n => n) + }) + }) + }) + ] + }), + this.state.gradientBarEnabled && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickergradient, + children: [ + BDFDB.ReactUtils.createElement("div", { + style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0}, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickergradientcheckered, + style: {padding: "0px 2px", position: "relative", height: "100%"} + }) + }), + BDFDB.ReactUtils.createElement("div", { + style: {position: "absolute", top: 0, right: 0, bottom: 0, left: 0}, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickergradienthorizontal, + style: {padding: "0px 2px", position: "relative", cursor: "copy", height: "100%", background: BDFDB.ColorUtils.createGradient(currentGradient.reduce((colorObj, posAndColor) => (colorObj[posAndColor[0]] = posAndColor[1], colorObj), {}))}, + onClick: event => { + let rects = BDFDB.DOMUtils.getRects(event.target); + let pos = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0.01, 0.99], event.clientX); + if (Object.keys(this.props.color).indexOf(pos) == -1) { + this.props.color[pos] = BDFDB.ColorUtils.convert("#000000FF", hslFormat); + this.state.selectedGradientCursor = pos; + this.handleColorChange(); + } + }, + children: currentGradient.map(posAndColor => BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickergradientcursor, (posAndColor[0] == 0 || posAndColor[0] == 1) && BDFDB.disCNS.colorpickergradientcursoredge, this.state.selectedGradientCursor == posAndColor[0] && BDFDB.disCN.colorpickergradientcursorselected), + style: {position: "absolute", cursor: "pointer", left: `${posAndColor[0] * 100}%`}, + onMouseDown: posAndColor[0] == 0 || posAndColor[0] == 1 ? _ => {} : event => { + event = event.nativeEvent || event; + let mousemove = event2 => { + if (Math.sqrt((event.pageX - event2.pageX)**2) > 10) { + document.removeEventListener("mousemove", mousemove); + document.removeEventListener("mouseup", mouseup); + + this.state.draggingGradientCursor = true; + let cursor = BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickergradientcursor, event.target); + let rects = BDFDB.DOMUtils.getRects(cursor.parentElement); + + let releasing = _ => { + document.removeEventListener("mousemove", dragging); + document.removeEventListener("mouseup", releasing); + BDFDB.TimeUtils.timeout(_ => {this.state.draggingGradientCursor = false;}); + }; + let dragging = event3 => { + let pos = BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0.01, 0.99], event3.clientX); + if (Object.keys(this.props.color).indexOf(pos) == -1) { + delete this.props.color[posAndColor[0]]; + posAndColor[0] = pos; + this.props.color[pos] = posAndColor[1]; + this.state.selectedGradientCursor = pos; + this.handleColorChange(); + } + }; + document.addEventListener("mousemove", dragging); + document.addEventListener("mouseup", releasing); + } + }; + let mouseup = _ => { + document.removeEventListener("mousemove", mousemove); + document.removeEventListener("mouseup", mouseup); + }; + document.addEventListener("mousemove", mousemove); + document.addEventListener("mouseup", mouseup); + }, + onClick: event => { + BDFDB.ListenerUtils.stopEvent(event); + if (!this.state.draggingGradientCursor) { + this.state.selectedGradientCursor = posAndColor[0]; + BDFDB.ReactUtils.forceUpdate(this); + } + }, + onContextMenu: posAndColor[0] == 0 || posAndColor[0] == 1 ? _ => {} : event => { + BDFDB.ListenerUtils.stopEvent(event); + delete this.props.color[posAndColor[0]]; + this.state.selectedGradientCursor = 0; + this.handleColorChange(); + }, + children: BDFDB.ReactUtils.createElement("div", { + style: {background: BDFDB.ColorUtils.convert(posAndColor[1], "RGBA")} + }) + })) + }) + }) + ] + }) + ].filter(n => n) + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, { + className: BDFDB.disCNS.colorpickerhexinput + BDFDB.disCN.margintop8, + maxLength: this.props.alpha ? 9 : 7, + valuePrefix: "#", + value: BDFDB.ColorUtils.convert(selectedColor, this.props.alpha ? "HEXA" : "HEX"), + autoFocus: true, + onChange: value => { + if (hexRegex.test(value)) this.handleColorChange(value); + }, + inputChildren: this.props.gradient && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: "Gradient", + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Clickable, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickergradientbutton, this.state.gradientBarEnabled && BDFDB.disCN.colorpickergradientbuttonenabled), + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + nativeClass: true, + width: 28, + height: 28, + name: InternalComponents.LibraryComponents.SvgIcon.Names.GRADIENT + }), + onClick: _ => { + this.state.gradientBarEnabled = !this.state.gradientBarEnabled; + if (this.state.gradientBarEnabled && !this.state.isGradient) this.props.color = {0: selectedColor, 1: selectedColor}; + else if (!this.state.gradientBarEnabled && this.state.isGradient) this.props.color = selectedColor; + this.state.isGradient = this.props.color && BDFDB.ObjectUtils.is(this.props.color); + this.handleColorChange(); + } + }) + }) + }), + BDFDB.ReactUtils.createElement("div", { + className: "move-corners", + children: [{top: 0, left: 0}, {top: 0, right: 0}, {bottom: 0, right: 0}, {bottom: 0, left: 0}].map(pos => BDFDB.ReactUtils.createElement("div", { + className: "move-corner", + onMouseDown: e => { + if (!this.domElementRef.current) return; + let rects = BDFDB.DOMUtils.getRects(this.domElementRef.current); + let left = rects.left, top = rects.top; + let oldX = e.pageX, oldY = e.pageY; + let mouseup = _ => { + document.removeEventListener("mouseup", mouseup); + document.removeEventListener("mousemove", mousemove); + }; + let mousemove = e2 => { + left = left - (oldX - e2.pageX), top = top - (oldY - e2.pageY); + oldX = e2.pageX, oldY = e2.pageY; + this.domElementRef.current.style.setProperty("left", `${left}px`, "important"); + this.domElementRef.current.style.setProperty("top", `${top}px`, "important"); + }; + document.addEventListener("mouseup", mouseup); + document.addEventListener("mousemove", mousemove); + }, + style: Object.assign({}, pos, {width: 10, height: 10, cursor: "move", position: "absolute"}) + })) + }) + ] + }); + } + }; + + InternalComponents.LibraryComponents.ColorSwatches = reactInitialized && class BDFDB_ColorSwatches extends LibraryModules.React.Component { + constructor(props) { + super(props); + + props.selectedColor = BDFDB.ObjectUtils.is(props.color) ? props.color : BDFDB.ColorUtils.convert(props.color, "RGBA"); + props.colors = (BDFDB.ArrayUtils.is(props.colors) ? props.colors : [null, 5433630, 3066993, 1752220, 3447003, 3429595, 8789737, 10181046, 15277667, 15286558, 15158332, 15105570, 15844367, 13094093, 7372936, 6513507, 16777215, 3910932, 2067276, 1146986, 2123412, 2111892, 7148717, 7419530, 11342935, 11345940, 10038562, 11027200, 12745742, 9936031, 6121581, 2894892]).map(c => BDFDB.ColorUtils.convert(c, "RGBA")); + props.colorRows = props.colors.length ? [props.colors.slice(0, parseInt(props.colors.length/2)), props.colors.slice(parseInt(props.colors.length/2))] : []; + props.customColor = props.selectedColor != null ? (props.colors.indexOf(props.selectedColor) > -1 ? null : props.selectedColor) : null; + props.customSelected = !!props.customColor; + props.pickerConfig = BDFDB.ObjectUtils.is(props.pickerConfig) ? props.pickerConfig : {gradient: true, alpha: true}; + this.state = props; + + var swatches = this; + this.ColorSwatch = class BDFDB_ColorSwatch extends LibraryModules.React.Component { + render() { + let useWhite = !BDFDB.ColorUtils.isBright(this.props.color); + let swatch = BDFDB.ReactUtils.createElement("button", { + type: "button", + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickerswatch, this.props.isSingle && BDFDB.disCN.colorpickerswatchsingle, this.props.isDisabled && BDFDB.disCN.colorpickerswatchdisabled, this.props.isSelected && BDFDB.disCN.colorpickerswatchselected, this.props.isCustom && BDFDB.disCN.colorpickerswatchcustom, this.props.color == null && BDFDB.disCN.colorpickerswatchnocolor), + number: this.props.number, + disabled: this.props.isDisabled, + onClick: _ => { + if (!this.props.isSelected) { + let color = this.props.isCustom && this.props.color == null ? "rgba(0, 0, 0, 1)" : this.props.color; + if (typeof swatches.props.onColorChange == "function") swatches.props.onColorChange(BDFDB.ColorUtils.convert(color, "RGBA")); + swatches.setState({ + selectedColor: color, + customColor: this.props.isCustom ? color : swatches.state.customColor, + customSelected: this.props.isCustom + }); + } + }, + style: Object.assign({}, this.props.style, { + background: BDFDB.ObjectUtils.is(this.props.color) ? BDFDB.ColorUtils.createGradient(this.props.color) : BDFDB.ColorUtils.convert(this.props.color, "RGBA") + }), + children: [ + this.props.isCustom || this.props.isSingle ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.colorpickerswatchdropper, + foreground: BDFDB.disCN.colorpickerswatchdropperfg, + name: InternalComponents.LibraryComponents.SvgIcon.Names.DROPPER, + width: this.props.isCustom ? 14 : 10, + height: this.props.isCustom ? 14 : 10, + color: useWhite ? BDFDB.DiscordConstants.Colors.WHITE : BDFDB.DiscordConstants.Colors.BLACK + }) : null, + this.props.isSelected && !this.props.isSingle ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: InternalComponents.LibraryComponents.SvgIcon.Names.CHECKMARK, + width: this.props.isCustom ? 32 : 16, + height: this.props.isCustom ? 24 : 16, + color: useWhite ? BDFDB.DiscordConstants.Colors.WHITE : BDFDB.DiscordConstants.Colors.BLACK + }) : null + ] + }); + if (this.props.isCustom || this.props.isSingle || this.props.color == null) swatch = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: this.props.isCustom || this.props.isSingle ? BDFDB.LanguageUtils.LanguageStrings.CUSTOM_COLOR : BDFDB.LanguageUtils.LanguageStrings.DEFAULT, + tooltipConfig: {type: this.props.isSingle ? "top" : "bottom"}, + children: swatch + }); + if (this.props.isCustom || this.props.isSingle) swatch = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutContainer, { + children: swatch, + wrap: false, + popoutClassName: BDFDB.disCNS.colorpickerwrapper + BDFDB.disCN.colorpicker, + animation: InternalComponents.LibraryComponents.PopoutContainer.Animation.TRANSLATE, + position: InternalComponents.LibraryComponents.PopoutContainer.Positions.BOTTOM, + align: InternalComponents.LibraryComponents.PopoutContainer.Align.CENTER, + renderPopout: _ => { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ColorPicker, Object.assign({ + color: this.props.color, + onColorChange: color => { + if (typeof swatches.props.onColorChange == "function") swatches.props.onColorChange(BDFDB.ColorUtils.convert(color, "RGBA")) + this.props.color = color; + swatches.setState({ + selectedColor: color, + customColor: color, + customSelected: true + }); + } + }, props.pickerConfig), true); + } + }); + return swatch; + } + } + } + renderRow(colors) { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.colorpickerrow, + wrap: InternalComponents.LibraryComponents.Flex.Wrap.WRAP, + children: colors.map(color => { + return BDFDB.ReactUtils.createElement(this.ColorSwatch, { + color: color, + isCustom: false, + isSelected: !this.state.customSelected && color === this.state.selectedColor, + isDisabled: this.state.disabled + }) + }) + }); + } + render() { + let customSwatch = BDFDB.ReactUtils.createElement(this.ColorSwatch, { + number: !this.state.colors.length ? (this.props.number != null ? this.props.number : 0) : null, + color: this.state.customColor, + isSingle: !this.state.colors.length, + isCustom: this.state.colors.length, + isSelected: this.state.customSelected, + isDisabled: this.state.disabled, + style: {margin: 0} + }); + return !this.state.colors.length ? BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickerswatchsinglewrapper, + children: customSwatch + }) : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickerswatches, this.state.disabled && BDFDB.disCN.colorpickerswatchesdisabled), + number: this.props.number != null ? this.props.number : 0, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + className: BDFDB.disCN.marginreset, + shrink: 0, + grow: 0, + children: customSwatch + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + direction: InternalComponents.LibraryComponents.Flex.Direction.VERTICAL, + className: BDFDB.disCN.flexmarginreset, + grow: 1, + children: [ + this.renderRow(this.state.colorRows[0]), + this.renderRow(this.state.colorRows[1]) + ] + }) + ] + }); + } + }; + + InternalComponents.LibraryComponents.EmojiPickerButton = reactInitialized && class BDFDB_EmojiPickerButton extends LibraryModules.React.Component { + handleEmojiChange(emoji) { + if (emoji != null) { + this.props.emoji = emoji.id ? { + id: emoji.id, + name: emoji.name, + animated: emoji.animated + } : { + id: null, + name: emoji.optionallyDiverseSequence, + animated: false + }; + if (typeof this.props.onSelect == "function") this.props.onSelect(this.props.emoji, this); + BDFDB.ReactUtils.forceUpdate(this); + } + } + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutContainer, { + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.EmojiButton, { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.emojiinputbutton), + renderButtonContents: this.props.emoji ? _ => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Emoji, { + className: BDFDB.disCN.emoji, + emojiId: this.props.emoji.id, + emojiName: this.props.emoji.name + }) : null + }), + wrap: false, + animation: InternalComponents.LibraryComponents.PopoutContainer.Animation.NONE, + position: InternalComponents.LibraryComponents.PopoutContainer.Positions.TOP, + align: InternalComponents.LibraryComponents.PopoutContainer.Align.LEFT, + renderPopout: instance => { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.EmojiPicker, { + closePopout: instance.close, + onSelectEmoji: this.handleEmojiChange.bind(this), + allowManagedEmojis: this.props.allowManagedEmojis + }); + } + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.EmojiPickerButton, {allowManagedEmojis:false}); + + InternalComponents.LibraryComponents.FavButton = reactInitialized && class BDFDB_FavButton extends LibraryModules.React.Component { + handleClick() { + this.props.isFavorite = !this.props.isFavorite; + if (typeof this.props.onClick == "function") this.props.onClick(this.props.isFavorite, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.favbuttoncontainer, this.props.className), + children: BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.FavButton, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {onClick: this.handleClick.bind(this)}), "className")) + }); + } + }; + + InternalComponents.LibraryComponents.FileButton = reactInitialized && class BDFDB_FileButton extends LibraryModules.React.Component { + componentDidMount() { + if (this.props.searchFolders) { + let node = BDFDB.ReactUtils.findDOMNode(this); + if (node && (node = node.querySelector("input[type='file']")) != null) { + node.setAttribute("directory", ""); + node.setAttribute("webkitdirectory", ""); + } + } + } + render() { + let filter = this.props.filter && [this.props.filter].flat(10).filter(n => typeof n == "string") || []; + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Button, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + onClick: e => {e.currentTarget.querySelector("input").click();}, + children: [ + BDFDB.LanguageUtils.LibraryStrings.file_navigator_text, + BDFDB.ReactUtils.createElement("input", { + type: "file", + accept: filter.length && (filter.join("/*,") + "/*"), + style: {display: "none"}, + onChange: e => { + let file = e.currentTarget.files[0]; + if (this.refInput && file && (!filter.length || filter.some(n => file.type.indexOf(n) == 0))) { + this.refInput.props.value = this.props.searchFolders ? file.path.split(file.name).slice(0, -1).join(file.name) : `${this.props.mode == "url" ? "url('" : ""}${(this.props.useFilePath) ? file.path : `data:${file.type};base64,${BDFDB.LibraryRequires.fs.readFileSync(file.path).toString("base64")}`}${this.props.mode ? "')" : ""}`; + BDFDB.ReactUtils.forceUpdate(this.refInput); + this.refInput.handleChange(this.refInput.props.value); + } + } + }) + ] + }), "filter", "mode", "useFilePath", "searchFolders")); + } + }; + + InternalComponents.LibraryComponents.FormComponents.FormItem = reactInitialized && class BDFDB_FormItem extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement("div", { + className: this.props.className, + style: this.props.style, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + align: InternalComponents.LibraryComponents.Flex.Align.BASELINE, + children: [ + this.props.title != null || this.props.error != null ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + wrap: true, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormTitle, { + tag: this.props.tag || InternalComponents.LibraryComponents.FormComponents.FormTitle.Tags.H5, + disabled: this.props.disabled, + required: this.props.required, + error: this.props.error, + className: this.props.titleClassName, + children: this.props.title + }) + }) : null + ].concat([this.props.titlechildren].flat(10)).filter(n => n) + }), + ].concat(this.props.children) + }); + } + }; + + InternalComponents.LibraryComponents.GuildComponents.Guild = reactInitialized && class BDFDB_Guild extends LibraryModules.React.Component { + constructor(props) { + super(props); + this.state = {hovered: false}; + } + handleMouseEnter(e) { + if (!this.props.sorting) this.setState({hovered: true}); + if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this); + } + handleMouseLeave(e) { + if (!this.props.sorting) this.setState({hovered: false}); + if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this); + } + handleMouseDown(e) { + if (!this.props.unavailable && this.props.guild && this.props.selectedChannelId) LibraryModules.DirectMessageUtils.preload(this.props.guild.id, this.props.selectedChannelId); + if (e.button == 0 && typeof this.props.onMouseDown == "function") this.props.onMouseDown(e, this); + } + handleMouseUp(e) { + if (e.button == 0 && typeof this.props.onMouseUp == "function") this.props.onMouseUp(e, this); + } + handleClick(e) { + if (typeof this.props.onClick == "function") this.props.onClick(e, this); + } + handleContextMenu(e) { + if (this.props.menu) BDFDB.GuildUtils.openMenu(this.props.guild, e); + if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this); + } + setRef(e) { + if (typeof this.props.setRef == "function") this.props.setRef(this.props.guild.id, e) + } + componentDidMount() { + let node = BDFDB.ReactUtils.findDOMNode(this); + if (node) for (let child of node.querySelectorAll("a")) child.setAttribute("draggable", false); + } + render() { + if (!this.props.guild) return null; + let currentVoiceChannel = LibraryModules.ChannelStore.getChannel(LibraryModules.CurrentVoiceUtils.getChannelId()); + let hasVideo = currentVoiceChannel && LibraryModules.VoiceUtils.hasVideo(currentVoiceChannel); + this.props.guildId = this.props.guild.id; + this.props.selectedChannelId = LibraryModules.LastChannelStore.getChannelId(this.props.guild.id); + this.props.selected = this.props.state ? LibraryModules.LastGuildStore.getGuildId() == this.props.guild.id : false; + this.props.unread = this.props.state ? LibraryModules.UnreadGuildUtils.hasUnread(this.props.guild.id) : false; + this.props.badge = this.props.state ? LibraryModules.UnreadGuildUtils.getMentionCount(this.props.guild.id) : 0; + this.props.audio = this.props.state ? currentVoiceChannel && currentVoiceChannel.guild_id == this.props.guild.id && !hasVideo : false; + this.props.video = this.props.state ? currentVoiceChannel && currentVoiceChannel.guild_id == this.props.guild.id && hasVideo : false; + this.props.screenshare = this.props.state ? !!LibraryModules.StreamUtils.getAllApplicationStreams().filter(stream => stream.guildId == this.props.guild.id)[0] : false; + this.props.isCurrentUserInThisGuildVoice = this.props.state ? LibraryModules.CurrentVoiceUtils.getGuildId() == this.props.guild.id : false; + this.props.animatable = this.props.state ? LibraryModules.IconUtils.hasAnimatedGuildIcon(this.props.guild) : false; + this.props.unavailable = this.props.state ? LibraryModules.GuildUnavailableStore.unavailableGuilds.includes(this.props.guild.id) : false; + let isDraggedGuild = this.props.draggingGuildId === this.props.guild.id; + let guild = isDraggedGuild ? BDFDB.ReactUtils.createElement("div", { + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.GuildComponents.Items.DragPlaceholder, {}) + }) : BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.guildcontainer, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.GuildComponents.BlobMask, { + selected: this.state.isDropHovering || this.props.selected || this.state.hovered, + upperBadge: this.props.unavailable ? InternalComponents.LibraryComponents.GuildComponents.Items.renderUnavailableBadge() : InternalComponents.LibraryComponents.GuildComponents.Items.renderIconBadge(this.props.audio, this.props.video, this.props.screenshare, this.props.isCurrentUserInThisGuildVoice), + lowerBadge: this.props.badge > 0 ? InternalComponents.LibraryComponents.GuildComponents.Items.renderMentionBadge(this.props.badge) : null, + lowerBadgeWidth: InternalComponents.LibraryComponents.Badges.getBadgeWidthForValue(this.props.badge), + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.NavItem, { + to: { + pathname: BDFDB.DiscordConstants.Routes.CHANNEL(this.props.guild.id, this.props.selectedChannelId), + state: { + analyticsSource: { + page: BDFDB.DiscordConstants.AnalyticsPages.GUILD_CHANNEL, + section: BDFDB.DiscordConstants.AnalyticsSections.CHANNEL_LIST, + object: BDFDB.DiscordConstants.AnalyticsObjects.CHANNEL + } + } + }, + name: this.props.guild.name, + onMouseEnter: this.handleMouseEnter.bind(this), + onMouseLeave: this.handleMouseLeave.bind(this), + onMouseDown: this.handleMouseDown.bind(this), + onMouseUp: this.handleMouseUp.bind(this), + onClick: this.handleClick.bind(this), + onContextMenu: this.handleContextMenu.bind(this), + icon: this.props.guild.getIconURL(this.state.hovered && this.props.animatable ? "gif" : "png"), + selected: this.props.selected || this.state.hovered + }) + }) + }); + + if (this.props.draggable && typeof this.props.connectDragSource == "function") guild = this.props.connectDragSource(guild); + + let children = [ + this.props.list || this.props.pill ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.GuildComponents.Pill, { + hovered: !isDraggedGuild && this.state.hovered, + selected: !isDraggedGuild && this.props.selected, + unread: !isDraggedGuild && this.props.unread, + className: BDFDB.disCN.guildpill + }) : null, + !this.props.tooltip ? guild : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + tooltipConfig: Object.assign({type: "right"}, this.props.tooltipConfig, {guild: this.props.list && this.props.guild}), + children: guild + }) + ].filter(n => n); + return this.props.list ? BDFDB.ReactUtils.createElement("div", { + ref: null != this.props.setRef ? this.props.setRef : null, + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.guildouter, BDFDB.disCN._bdguild, this.props.unread && BDFDB.disCN._bdguildunread, this.props.selected && BDFDB.disCN._bdguildselected, this.props.unread && BDFDB.disCN._bdguildunread, this.props.audio && BDFDB.disCN._bdguildaudio, this.props.video && BDFDB.disCN._bdguildvideo), + children: BDFDB.ReactUtils.createElement(BDFDB.ReactUtils.Fragment, { + children: children + }) + }) : BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.guild, this.props.className), + children: children + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.GuildComponents.Guild, {menu:true, tooltip:true, list:false, state:false, draggable:false, sorting:false}); + + InternalComponents.LibraryComponents.GuildSummaryItem = reactInitialized && class BDFDB_GuildSummaryItem extends LibraryModules.React.Component { + defaultRenderGuild(guild, isLast) { + if (!guild) return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.guildsummaryemptyguild + }); + let icon = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.GuildComponents.Icon, { + className: BDFDB.disCN.guildsummaryicon, + guild: guild, + showTooltip: this.props.showTooltip, + tooltipPosition: "top", + size: InternalComponents.LibraryComponents.GuildComponents.Icon.Sizes.SMALLER + }); + return this.props.switchOnClick ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Clickable, { + className: BDFDB.disCN.guildsummaryclickableicon, + onClick: _ => {LibraryModules.SelectChannelUtils.selectChannel(guild.id, LibraryModules.LastChannelStore.getChannelId(guild.id));}, + key: guild.id, + tabIndex: -1, + children: icon + }) : icon; + } + renderGuilds() { + let elements = []; + let renderGuild = typeof this.props.renderGuild != "function" ? this.defaultRenderGuild : this.props.renderGuild; + let loaded = 0, max = this.props.guilds.length === this.props.max ? this.props.guilds.length : this.props.max - 1; + while (loaded < max && loaded < this.props.guilds.length) { + let isLast = loaded === this.props.guilds.length - 1; + let guild = renderGuild.apply(this, [this.props.guilds[loaded], isLast]); + elements.push(BDFDB.ReactUtils.createElement("div", { + className: isLast ? BDFDB.disCN.guildsummaryiconcontainer : BDFDB.disCN.guildsummaryiconcontainermasked, + children: guild + })); + loaded++; + } + if (loaded < this.props.guilds.length) { + let rest = Math.min(this.props.guilds.length - loaded, 99); + elements.push(BDFDB.ReactUtils.createElement(LibraryModules.React.Fragment, { + key: "more-guilds", + children: this.props.renderMoreGuilds("+" + rest, rest, this.props.guilds.slice(loaded), this.props) + })); + } + return elements; + } + renderIcon() { + return this.props.renderIcon ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: InternalComponents.LibraryComponents.SvgIcon.Names.WHATISTHIS, + className: BDFDB.disCN.guildsummarysvgicon + }) : null; + } + render() { + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.guildsummarycontainer), + ref: this.props._ref, + children: [ + this.renderIcon.apply(this), + this.renderGuilds.apply(this) + ].flat(10).filter(n => n) + }); + } + } + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.GuildSummaryItem, {max:10, renderMoreGuilds: (count, amount, restGuilds, props) => { + let icon = BDFDB.ReactUtils.createElement("div", {className: BDFDB.disCN.guildsummarymoreguilds, children: count}); + return props.showTooltip ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: restGuilds.map(guild => guild.name).join(", "), + children: icon + }) : icon; + }, renderIcon:false}); + + InternalComponents.LibraryComponents.KeybindRecorder = reactInitialized && class BDFDB_KeybindRecorder extends LibraryModules.React.Component { + handleChange(arrays) { + if (typeof this.props.onChange == "function") this.props.onChange(arrays.map(platformkey => LibraryModules.KeyEvents.codes[BDFDB.LibraryModules.KeyCodeUtils.codeToKey(platformkey)] || platformkey[1]), this); + } + handleReset() { + this.props.defaultValue = []; + let recorder = BDFDB.ReactUtils.findOwner(this, {name: "KeybindRecorder"}); + if (recorder) recorder.setState({codes: []}); + if (typeof this.props.onChange == "function") this.props.onChange([], this); + if (typeof this.props.onReset == "function") this.props.onReset(this); + } + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.hotkeywrapper, + direction: InternalComponents.LibraryComponents.Flex.Direction.HORIZONTAL, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.KeybindRecorder, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + defaultValue: [this.props.defaultValue].flat(10).filter(n => n).map(keycode => [BDFDB.DiscordConstants.KeyboardDeviceTypes.KEYBOARD_KEY, keycode, BDFDB.DiscordConstants.KeyboardEnvs.BROWSER]), + onChange: this.handleChange.bind(this) + }), "reset", "onReset")), + this.props.reset || this.props.onReset ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: BDFDB.LanguageUtils.LanguageStrings.REMOVE_KEYBIND, + tooltipConfig: {type: "top"}, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Clickable, { + className: BDFDB.disCN.hotkeyresetbutton, + onClick: this.handleReset.bind(this), + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + iconSVG: ``, + }) + }) + }) : null + ].filter(n => n) + }); + } + }; + + InternalComponents.LibraryComponents.ListRow = reactInitialized && class BDFDB_ListRow extends LibraryModules.React.Component { + render () { + return BDFDB.ReactUtils.createElement("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.listrowwrapper, this.props.className, BDFDB.disCN.listrow), + children: [ + this.props.prefix, + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.listrowcontent, + style: {flex: "1 1 auto"}, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.listname, this.props.labelClassName), + style: {flex: "1 1 auto"}, + children: this.props.label + }), + typeof this.props.note == "string" ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormText, { + type: InternalComponents.LibraryComponents.FormComponents.FormText.Types.DESCRIPTION, + children: this.props.note + }) : null + ].filter(n => n) + }), + this.props.suffix + ].filter(n => n) + }), "label", "note", "suffix", "prefix", "labelClassName")); + } + }; + + InternalComponents.LibraryComponents.MemberRole = reactInitialized && class BDFDB_MemberRole extends LibraryModules.React.Component { + handleClick(e) {if (typeof this.props.onClick == "function") this.props.onClick(e, this);} + handleContextMenu(e) {if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this);} + render() { + let color = BDFDB.ColorUtils.convert(this.props.role.colorString || BDFDB.DiscordConstants.Colors.PRIMARY_DARK_300, "RGB"); + return BDFDB.ReactUtils.createElement("li", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.userpopoutrole, this.props.className), + style: {borderColor: BDFDB.ColorUtils.setAlpha(color, 0.6)}, + onClick: this.handleClick.bind(this), + onContextMenu: this.handleContextMenu.bind(this), + children: [ + !this.props.noCircle ? BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.userpopoutrolecircle, + style: {backgroundColor: color} + }) : null, + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.userpopoutrolename, + children: this.props.role.name + }) + ].filter(n => n) + }); + } + }; + + InternalComponents.LibraryComponents.MenuItems.MenuCheckboxItem = reactInitialized && class BDFDB_MenuCheckboxItem extends LibraryModules.React.Component { + handleClick() { + if (this.props.state) { + this.props.state.checked = !this.props.state.checked; + if (typeof this.props.action == "function") this.props.action(this.props.state.checked, this); + } + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.MenuCheckboxItem, Object.assign({}, this.props, { + checked: this.props.state && this.props.state.checked, + action: this.handleClick.bind(this) + })); + } + }; + + InternalComponents.LibraryComponents.MenuItems.MenuHint = reactInitialized && class BDFDB_MenuHint extends LibraryModules.React.Component { + render() { + return !this.props.hint ? null : BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.menuhint, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextScroller, { + children: this.props.hint + }) + }); + } + }; + + InternalComponents.LibraryComponents.MenuItems.MenuIcon = reactInitialized && class BDFDB_MenuIcon extends LibraryModules.React.Component { + render() { + let isString = typeof this.props.icon == "string"; + return !this.props.icon ? null : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.menuicon, + iconSVG: isString ? this.props.icon : null, + name: !isString ? this.props.icon : null + }); + } + }; + + InternalComponents.LibraryComponents.MenuItems.MenuSliderItem = reactInitialized && class BDFDB_MenuSliderItem extends LibraryModules.React.Component { + handleValueChange(value) { + if (this.props.state) { + this.props.state.value = Math.round(BDFDB.NumberUtils.mapRange([0, 100], [this.props.minValue, this.props.maxValue], value) * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits); + if (typeof this.props.onValueChange == "function") this.props.onValueChange(this.props.state.value, this); + } + BDFDB.ReactUtils.forceUpdate(this); + } + handleValueRender(value) { + let newValue = Math.round(BDFDB.NumberUtils.mapRange([0, 100], [this.props.minValue, this.props.maxValue], value) * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits); + if (typeof this.props.onValueRender == "function") { + let tempReturn = this.props.onValueRender(newValue, this); + if (tempReturn != undefined) newValue = tempReturn; + } + return newValue; + } + render() { + let value = this.props.state && this.props.state.value || 0; + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.MenuControlItem, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + label: typeof this.props.renderLabel == "function" ? this.props.renderLabel(Math.round(value * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits)) : this.props.label, + control: (menuItemProps, ref) => { + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.menuslidercontainer, + children: BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.Slider, Object.assign({}, menuItemProps, { + ref: ref, + className: BDFDB.disCN.menuslider, + mini: true, + initialValue: Math.round(BDFDB.NumberUtils.mapRange([this.props.minValue, this.props.maxValue], [0, 100], value) * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits), + onValueChange: this.handleValueChange.bind(this), + onValueRender: this.handleValueRender.bind(this) + })) + }); + } + }), "digits", "renderLabel")); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.MenuItems.MenuSliderItem, {minValue:0, maxValue:100, digits:0}); + + InternalComponents.LibraryComponents.ModalComponents.ModalContent = reactInitialized && class BDFDB_ModalContent extends LibraryModules.React.Component { + render() { + return this.props.scroller ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ScrollerThin, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modalcontent, this.props.className), + ref: this.props.scrollerRef, + children: this.props.children + }) : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.DOMUtils.formatClassName(this.props.content && BDFDB.disCN.modalcontent, BDFDB.disCN.modalnoscroller, this.props.className), + direction: this.props.direction || InternalComponents.LibraryComponents.Flex.Direction.VERTICAL, + align: InternalComponents.LibraryComponents.Flex.Align.STRETCH, + children: this.props.children + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.ModalComponents.ModalContent, {scroller:true, content:true}); + + InternalComponents.LibraryComponents.ModalComponents.ModalTabContent = reactInitialized && class BDFDB_ModalTabContent extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.forceStyle(BDFDB.ReactUtils.createElement(this.props.scroller ? InternalComponents.LibraryComponents.ScrollerThin : "div", Object.assign(BDFDB.ObjectUtils.exclude(this.props, "scroller", "open", "render"), { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modaltabcontent, this.props.open && BDFDB.disCN.modaltabcontentopen, this.props.className), + style: Object.assign({}, this.props.style, { + display: this.props.open ? null : "none" + }), + children: !this.props.open && !this.props.render ? null : this.props.children + })), ["display"]); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.ModalComponents.ModalTabContent, {tab:"unnamed", render:true}); + + InternalComponents.LibraryComponents.PaginatedList = reactInitialized && class BDFDB_PaginatedList extends LibraryModules.React.Component { + constructor(props) { + super(props); + this.state = { + offset: props.offset + }; + } + jump(offset) { + if (offset > -1 && offset < Math.ceil(this.props.items.length/this.props.amount) && this.state.offset != offset) { + this.state.offset = offset; + if (typeof this.props.onJump == "function") this.props.onJump(offset, this); + BDFDB.ReactUtils.forceUpdate(this); + } + } + renderPagination() { + let maxOffset = Math.ceil(this.props.items.length/this.props.amount) - 1; + return this.props.items.length > this.props.amount && BDFDB.ReactUtils.createElement("nav", { + className: BDFDB.disCN.paginationlistpagination, + children: [ + this.props.first && BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, { + text: BDFDB.LanguageUtils.LibraryStrings.first, + "aria-label": BDFDB.LanguageUtils.LibraryStrings.first, + tooltipConfig: {zIndex: 3001}, + onClick: _ => {if (this.state.offset > 0) this.jump(0);}, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.searchresultspaginationbutton, this.state.offset <= 0 && BDFDB.disCN.searchresultspaginationdisabled, BDFDB.disCN.focusable), + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.searchresultspaginationicon, + name: BDFDB.LibraryComponents.SvgIcon.Names.LEFT_DOUBLE_CARET + }) + }) + }), + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, { + text: BDFDB.LanguageUtils.LanguageStrings.PAGINATION_PREVIOUS, + "aria-label": BDFDB.LanguageUtils.LanguageStrings.PAGINATION_PREVIOUS, + tooltipConfig: {zIndex: 3001}, + onClick: _ => { + if (this.state.offset > 0) this.jump(this.state.offset - 1); + }, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.searchresultspaginationbutton, this.state.offset <= 0 && BDFDB.disCN.searchresultspaginationdisabled, BDFDB.disCN.focusable), + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.searchresultspaginationicon, + name: BDFDB.LibraryComponents.SvgIcon.Names.LEFT_CARET + }) + }) + }), + BDFDB.LanguageUtils.LanguageStringsFormat("PAGINATION_PAGE_OF", this.state.offset + 1, maxOffset + 1), + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, { + text: BDFDB.LanguageUtils.LanguageStrings.PAGINATION_NEXT, + "aria-label": BDFDB.LanguageUtils.LanguageStrings.PAGINATION_NEXT, + tooltipConfig: {zIndex: 3001}, + onClick: _ => {if (this.state.offset < maxOffset) this.jump(this.state.offset + 1);}, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.searchresultspaginationbutton, this.state.offset >= maxOffset && BDFDB.disCN.searchresultspaginationdisabled, BDFDB.disCN.focusable), + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.searchresultspaginationicon, + name: BDFDB.LibraryComponents.SvgIcon.Names.RIGHT_CARET + }) + }) + }), + this.props.last && BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, { + text: BDFDB.LanguageUtils.LibraryStrings.last, + "aria-label": BDFDB.LanguageUtils.LibraryStrings.last, + tooltipConfig: {zIndex: 3001}, + onClick: _ => {if (this.state.offset < maxOffset) this.jump(maxOffset);}, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.searchresultspaginationbutton, this.state.offset >= maxOffset && BDFDB.disCN.searchresultspaginationdisabled, BDFDB.disCN.focusable), + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.searchresultspaginationicon, + name: BDFDB.LibraryComponents.SvgIcon.Names.RIGHT_DOUBLE_CARET + }) + }) + }), + this.props.jump && BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, { + key: "pagination-list-jumpinput", + type: "number", + size: BDFDB.LibraryComponents.TextInput.Sizes.MINI, + value: this.state.offset + 1, + min: 1, + max: maxOffset + 1, + onKeyDown: (event, instance) => {if (event.which == 13) this.jump(isNaN(parseInt(instance.props.value)) ? -1 : instance.props.value - 1);} + }), + this.props.jump && BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, { + text: BDFDB.LanguageUtils.LanguageStrings.JUMP, + "aria-label": BDFDB.LanguageUtils.LanguageStrings.JUMP, + tooltipConfig: {zIndex: 3001}, + onClick: (event, instance) => { + let jumpInput = BDFDB.ReactUtils.findOwner(instance._reactInternalFiber.return, {key:"pagination-list-jumpinput"}); + if (jumpInput) this.jump(isNaN(parseInt(jumpInput.props.value)) ? -1 : jumpInput.props.value - 1); + }, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, { + className: BDFDB.disCN.searchresultspaginationbutton, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.searchresultspaginationicon, + style: {transform: "rotate(90deg"}, + name: BDFDB.LibraryComponents.SvgIcon.Names.RIGHT_CARET + }) + }) + }) + ].filter(n => n) + }); + } + render() { + let items = [], alphabet = {}; + if (BDFDB.ArrayUtils.is(this.props.items) && this.props.items.length) { + if (!this.props.alphabetKey) items = this.props.items; + else { + let unsortedItems = [].concat(this.props.items); + for (let key of ["0-9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]) { + let numbers = key == "0-9", alphaItems = []; + for (let item of unsortedItems) if (item && item[this.props.alphabetKey] && (numbers && !isNaN(parseInt(item[this.props.alphabetKey][0])) || item[this.props.alphabetKey].toUpperCase().indexOf(key) == 0)) alphaItems.push(item); + for (let sortedItem of alphaItems) BDFDB.ArrayUtils.remove(unsortedItems, sortedItem); + alphabet[key] = {items:BDFDB.ArrayUtils.keySort(alphaItems, this.props.alphabetKey), disabled:!alphaItems.length}; + } + alphabet["?!"] = {items:BDFDB.ArrayUtils.keySort(unsortedItems, this.props.alphabetKey), disabled:!unsortedItems.length}; + for (let key in alphabet) items.push(alphabet[key].items); + items = items.flat(10); + } + } + return typeof this.props.renderItem != "function" || !items.length ? null : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ScrollerThin, { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.paginationlist, this.props.mini, BDFDB.disCN.paginationlistmini), + fade: this.props.fade, + children: [ + this.renderPagination(), + items.length > this.props.amount && this.props.alphabetKey && BDFDB.ReactUtils.createElement("nav", { + className: BDFDB.disCN.paginationlistalphabet, + children: Object.keys(alphabet).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.paginationlistalphabetchar, alphabet[key].disabled &&BDFDB.disCN.paginationlistalphabetchardisabled), + onClick: _ => {if (!alphabet[key].disabled) this.jump(Math.floor(items.indexOf(alphabet[key].items[0])/this.props.amount));}, + children: key + })) + }), + this.props.header, + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.paginationlistcontent, + children: items.slice(this.state.offset * this.props.amount, (this.state.offset + 1) * this.props.amount).map((data, i) => {return this.props.renderItem(data, i);}).flat(10).filter(n => n) + }), + this.props.copyToBottom && this.renderPagination() + ].flat(10).filter(n => n) + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.PaginatedList, {amount:50, offset:0, jump:true, first:true, last:true, copyToBottom:false, fade:true}); + + InternalComponents.LibraryComponents.Popout = reactInitialized && class BDFDB_Popout extends LibraryModules.React.Component { + componentWillUnmount() { + delete this.props.containerInstance.popout; + if (typeof this.props.onClose == "function") this.props.onClose(this.props.containerInstance, this); + } + render() { + let pos = typeof this.props.position == "string" ? this.props.position.toLowerCase() : null; + let positionClass = pos && DiscordClasses["popout" + pos] ? BDFDB.disCN["popout" + pos] : BDFDB.disCN.popouttop; + let arrowClass = !this.props.arrow ? BDFDB.disCN.popoutnoarrow : (pos && pos.indexOf("top") > -1 && pos != "top" ? BDFDB.disCN.popoutarrowalignmenttop : BDFDB.disCN.popoutarrowalignmentmiddle); + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutFocusLock, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.popoutwrapper, BDFDB.disCN.popout, positionClass, this.props.invert && pos && pos != "bottom" && BDFDB.disCN.popoutinvert, arrowClass, !this.props.shadow && BDFDB.disCN.popoutnoshadow), + id: this.props.id, + onClick: e => {e.stopPropagation();}, + style: Object.assign({}, this.props.style, { + position: this.props.isChild ? "relative" : "absolute" + }), + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, this.props.themed && BDFDB.disCN.popoutthemedpopout), + style: BDFDB.ObjectUtils.extract(this.props, "padding", "height", "maxHeight", "minHeight", "width", "maxWidth", "minWidth"), + children: this.props.children + }) + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Popout, {themed:true}); + + InternalComponents.LibraryComponents.PopoutContainer = reactInitialized && class BDFDB_PopoutContainer extends LibraryModules.React.Component { + handleRender(e) { + let children = typeof this.props.renderPopout == "function" ? this.props.renderPopout(this) : null; + return this.context.popout = !children ? null : (!this.props.wrap ? children : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Popout, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: this.props.popoutClassName, + containerInstance: this, + isChild: true, + position: e.position, + style: this.props.popoutStyle, + onClose: typeof this.props.onClose == "function" ? this.props.onClose.bind(this) : _ => {}, + children: children + }), "popoutStyle", "popoutClassName"))); + } + componentDidMount() { + let basePopout = BDFDB.ReactUtils.findOwner(this, {name:"BasePopout"}); + if (!basePopout || !basePopout.handleClick) return; + basePopout.isBDFDBpopout = true; + this.handleClick = e => {return basePopout.handleClick(BDFDB.ObjectUtils.is(e) ? e : (new MouseEvent({})));}; + this.close = basePopout.close; + this.domElementRef = basePopout.domElementRef; + } + render() { + let child = (BDFDB.ArrayUtils.is(this.props.children) ? this.props.children[0] : this.props.children) || BDFDB.ReactUtils.createElement("div", {style: {height: "100%", width: "100%"}}); + child.props.className = BDFDB.DOMUtils.formatClassName(child.props.className, this.props.className); + let childClick = child.props.onClick, childContextMenu = child.props.onContextMenu; + child.props.onClick = (e, childThis) => { + if (!this.domElementRef.current || this.domElementRef.current.contains(e.target)) { + if ((this.props.openOnClick || this.props.openOnClick === undefined) && typeof this.handleClick == "function") this.handleClick(e); + if (typeof this.props.onClick == "function") this.props.onClick(e, this); + if (typeof childClick == "function") childClick(e, childThis); + } + else e.stopPropagation(); + }; + child.props.onContextMenu = (e, childThis) => { + if (!this.domElementRef.current || this.domElementRef.current.contains(e.target)) { + if (this.props.openOnContextMenu && typeof this.handleClick == "function") this.handleClick(e); + if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this); + if (typeof childContextMenu == "function") childContextMenu(e, childThis); + } + else e.stopPropagation(); + }; + return BDFDB.ReactUtils.createElement(LibraryModules.React.Fragment, { + children: BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.PopoutContainer, Object.assign({}, this.props, { + children: _ => {return child;}, + renderPopout: this.handleRender.bind(this) + })) + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.PopoutContainer, {wrap:true}); + + InternalComponents.LibraryComponents.QuickSelect = reactInitialized && class BDFDB_QuickSelect extends LibraryModules.React.Component { + handleChange(option) { + this.props.value = option; + if (typeof this.props.onChange == "function") this.props.onChange(option.value || option.key, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + let options = (BDFDB.ArrayUtils.is(this.props.options) ? this.props.options : [{}]).filter(n => n); + let selectedOption = BDFDB.ObjectUtils.is(this.props.value) ? this.props.value : (options[0] || {}); + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.quickselectwrapper), + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.quickselect, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.quickselectlabel, + children: this.props.label + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + className: BDFDB.disCN.quickselectclick, + onClick: event => { + LibraryModules.ContextMenuUtils.openContextMenu(event, _ => { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Menu, { + navId: "bdfdb-quickselect", + onClose: BDFDB.LibraryModules.ContextMenuUtils.closeContextMenu, + className: this.props.popoutClassName, + children: BDFDB.ContextMenuUtils.createItem(InternalComponents.LibraryComponents.MenuItems.MenuGroup, { + children: options.map((option, i) => { + let selected = option.value && option.value === selectedOption.value || option.key && option.key === selectedOption.key; + return BDFDB.ContextMenuUtils.createItem(InternalComponents.LibraryComponents.MenuItems.MenuItem, { + label: option.label, + id: BDFDB.ContextMenuUtils.createItemId("option", option.key || option.value || i), + action: selected ? null : event2 => { + this.handleChange.bind(this)(option) + } + }); + }) + }) + }); + }); + }, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.quickselectvalue, + children: typeof this.props.renderValue == "function" ? this.props.renderValue(this.props.value) : this.props.value.label + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.quickselectarrow + }) + ] + }) + ] + }) + }); + } + }; + + InternalComponents.LibraryComponents.RadioGroup = reactInitialized && class BDFDB_RadioGroup extends LibraryModules.React.Component { + handleChange(value) { + this.props.value = value.value; + if (typeof this.props.onChange == "function") this.props.onChange(value, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.RadioGroup, Object.assign({}, this.props, { + onChange: this.handleChange.bind(this) + })); + } + }; + + InternalComponents.LibraryComponents.SearchBar = reactInitialized && class BDFDB_SearchBar extends LibraryModules.React.Component { + handleChange(query) { + this.props.query = query; + if (typeof this.props.onChange == "function") this.props.onChange(query, this); + BDFDB.ReactUtils.forceUpdate(this); + } + handleClear() { + this.props.query = ""; + if (this.props.changeOnClear && typeof this.props.onChange == "function") this.props.onChange("", this); + if (typeof this.props.onClear == "function") this.props.onClear(this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + let props = Object.assign({}, this.props, { + onChange: this.handleChange.bind(this), + onClear: this.handleClear.bind(this) + }); + if (typeof props.query != "string") props.query = ""; + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.SearchBar, props); + } + }; + + InternalComponents.LibraryComponents.Select = reactInitialized && class BDFDB_Select extends LibraryModules.React.Component { + handleChange(value) { + this.props.value = value.value || value; + if (typeof this.props.onChange == "function") this.props.onChange(value, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.selectwrapper, + direction: InternalComponents.LibraryComponents.Flex.Direction.HORIZONTAL, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.Select, Object.assign({}, this.props, { + onChange: this.handleChange.bind(this) + })) + }); + } + }; + + InternalComponents.LibraryComponents.SettingsGuildList = reactInitialized && class BDFDB_SettingsGuildList extends LibraryModules.React.Component { + render() { + this.props.disabled = BDFDB.ArrayUtils.is(this.props.disabled) ? this.props.disabled : []; + return BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, { + className: this.props.className, + wrap: BDFDB.LibraryComponents.Flex.Wrap.WRAP, + children: [this.props.includeDMs && {name:"Direct Messages", acronym:"DMs", id:BDFDB.DiscordConstants.ME, getIconURL: _ => {}}].concat(BDFDB.LibraryModules.FolderStore.getFlattenedGuilds()).filter(n => n).map(guild => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, { + text: guild.name, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.guildClassName, BDFDB.disCN.settingsguild, this.props.disabled.includes(guild.id) && BDFDB.disCN.settingsguilddisabled), + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.GuildComponents.Icon, { + guild: guild, + size: this.props.size || BDFDB.LibraryComponents.GuildComponents.Icon.Sizes.MEDIUM + }), + onClick: e => { + let isDisabled = this.props.disabled.includes(guild.id); + if (isDisabled) BDFDB.ArrayUtils.remove(this.props.disabled, guild.id, true); + else this.props.disabled.push(guild.id); + if (typeof this.props.onClick == "function") this.props.onClick(this.props.disabled, this); + BDFDB.ReactUtils.forceUpdate(this); + } + }) + })) + }); + } + }; + + InternalComponents.LibraryComponents.SettingsPanel = reactInitialized && class BDFDB_SettingsPanel extends LibraryModules.React.Component { + componentWillUnmount() { + if (BDFDB.ObjectUtils.is(this.props.plugin) && typeof this.props.plugin.onSettingsClosed == "function") this.props.plugin.onSettingsClosed(); + } + render() { + let headerItems = [ + this.props.title && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormTitle, { + className: BDFDB.disCN.settingspaneltitle, + tag: InternalComponents.LibraryComponents.FormComponents.FormTitle.Tags.H2, + children: this.props.title + }), + this.props.controls && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.settingspanelheadercontrols, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + grow: 0, + children: this.props.controls + }) + ].flat(10).filter(n => n); + + let panelItems = [ + this.props.children + ].flat(10).filter(n => n); + + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + direction: InternalComponents.LibraryComponents.Flex.Direction.VERTICAL, + grow: 1, + children: [ + headerItems.length && [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.settingspanelheader, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: headerItems + }), + panelItems.length && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { + className: BDFDB.disCNS.margintop4 + BDFDB.disCN.marginbottom8 + }) + ], + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.settingspanelinner, + direction: InternalComponents.LibraryComponents.Flex.Direction.VERTICAL, + children: panelItems + }) + ].flat(10).filter(n => n) + }); + } + }; + + InternalComponents.LibraryComponents.SettingsPanelInner = reactInitialized && class BDFDB_SettingsPanelInner extends LibraryModules.React.Component { + render() { + return this.props.children ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: this.props.className, + direction: InternalComponents.LibraryComponents.Flex.Direction.VERTICAL, + children: [ + !this.props.first ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { + className: BDFDB.disCN.marginbottom8 + }) : null, + typeof this.props.title == "string" ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormTitle, { + className: BDFDB.disCN.marginbottom4, + tag: InternalComponents.LibraryComponents.FormComponents.FormTitle.Tags.H3, + children: this.props.title + }) : null, + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.settingspanellist, + direction: InternalComponents.LibraryComponents.Flex.Direction.VERTICAL, + children: this.props.children + }), + !this.props.last ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { + className: BDFDB.disCN.marginbottom20 + }) : null + ] + }) : null; + } + }; + + InternalComponents.LibraryComponents.SettingsItem = reactInitialized && class BDFDB_SettingsItem extends LibraryModules.React.Component { + handleChange(value) { + if (typeof this.props.onChange == "function") this.props.onChange(value, this); + } + render() { + if (typeof this.props.type != "string" || !["BUTTON", "SELECT", "SLIDER", "SWITCH", "TEXTINPUT"].includes(this.props.type.toUpperCase())) return null; + let childComponent = InternalComponents.LibraryComponents[this.props.type]; + if (!childComponent) return null; + if (this.props.mini && childComponent.Sizes) this.props.size = childComponent.Sizes.MINI || childComponent.Sizes.MIN; + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.DOMUtils.formatClassName(this.props.className, this.props.disabled && BDFDB.disCN.disabled), + id: this.props.id, + direction: InternalComponents.LibraryComponents.Flex.Direction.VERTICAL, + align: InternalComponents.LibraryComponents.Flex.Align.STRETCH, + grow: this.props.grow, + stretch: this.props.stretch, + children: [ + this.props.dividertop ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { + className: this.props.mini ? BDFDB.disCN.marginbottom4 : BDFDB.disCN.marginbottom8 + }) : null, + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: [ + this.props.label ? (this.props.tag ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormTitle, { + className: BDFDB.DOMUtils.formatClassName(this.props.labelClassName, BDFDB.disCN.marginreset), + tag: this.props.tag, + children: this.props.label + }) : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { + className: this.props.labelClassName, + mini: this.props.mini, + label: this.props.label + }) + })) : null, + this.props.labelchildren, + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + grow: 0, + shrink: this.props.basis ? 0 : 1, + basis: this.props.basis, + wrap: true, + children: BDFDB.ReactUtils.createElement(childComponent, BDFDB.ObjectUtils.exclude(Object.assign(BDFDB.ObjectUtils.exclude(this.props, "className", "id", "type"), this.props.childProps, { + onChange: this.handleChange.bind(this), + onValueChange: this.handleChange.bind(this) + }), "grow", "stretch", "basis", "dividerbottom", "dividertop", "label", "labelClassName", "labelchildren", "tag", "mini", "note", "childProps")) + }) + ].flat(10).filter(n => n) + }), + typeof this.props.note == "string" ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + className: BDFDB.disCN.note, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormText, { + disabled: this.props.disabled, + type: InternalComponents.LibraryComponents.FormComponents.FormText.Types.DESCRIPTION, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextScroller, {speed: 2, children: this.props.note}) + }) + }) : null, + this.props.dividerbottom ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { + className: this.props.mini ? BDFDB.disCN.margintop4 : BDFDB.disCN.margintop8 + }) : null + ] + }); + } + }; + + InternalComponents.LibraryComponents.SettingsLabel = reactInitialized && class BDFDB_SettingsLabel extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextScroller, { + className: BDFDB.DOMUtils.formatClassName(this.props.className, this.props.mini ? BDFDB.disCN.titlemini : BDFDB.disCN.titledefault, BDFDB.disCN.cursordefault), + speed: 2, + children: this.props.label + }); + } + }; + + InternalComponents.LibraryComponents.SettingsList = reactInitialized && class BDFDB_SettingsList extends LibraryModules.React.Component { + componentDidMount() { + let list = BDFDB.ReactUtils.findDOMNode(this); + if (list && !this.props.maxWidth) { + let headers = Array.from(list.querySelectorAll(BDFDB.dotCN.settingstableheader)); + headers.shift(); + if (BDFDB.DOMUtils.getRects(headers[0]).width == 0) BDFDB.TimeUtils.timeout(_ => {this.resizeList(list, headers);}); + else this.resizeList(list, headers); + } + } + resizeList(list, headers) { + let maxWidth = 0, biggestWidth = 0; + if (!maxWidth) { + for (let header of headers) { + header.style = ""; + let width = BDFDB.DOMUtils.getRects(header).width; + maxWidth = width > maxWidth ? width : maxWidth; + } + maxWidth += 4; + biggestWidth = maxWidth; + } + if (headers.length * maxWidth > 300) { + this.props.vertical = true; + maxWidth = parseInt(290 / headers.length); + } + else if (maxWidth < 36) { + maxWidth = 36; + biggestWidth = maxWidth; + } + this.props.maxWidth = maxWidth; + this.props.biggestWidth = biggestWidth; + this.props.fullWidth = BDFDB.DOMUtils.getRects(list).width; + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + this.props.settings = BDFDB.ArrayUtils.is(this.props.settings) ? this.props.settings : []; + this.props.renderLabel = typeof this.props.renderLabel == "function" ? this.props.renderLabel : data => data.label; + this.props.data = (BDFDB.ArrayUtils.is(this.props.data) ? this.props.data : [{}]).filter(n => n); + let labelWidth = this.props.maxWidth && this.props.fullWidth && (this.props.fullWidth - 20 - (this.props.maxWidth * this.props.settings.length)); + let configWidth = this.props.maxWidth && this.props.maxWidth * this.props.settings.length; + let isHeaderClickable = typeof this.props.onHeaderClick == "function" || typeof this.props.onHeaderContextMenu == "function"; + let renderItem = data => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Card, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName([this.props.cardClassName, data.className].filter(n => n).join(" ").indexOf(BDFDB.disCN.card) == -1 && BDFDB.disCN.cardprimaryoutline, BDFDB.disCN.settingstablecard, this.props.cardClassName, data.className), + cardId: data.key, + backdrop: false, + style: Object.assign({}, this.props.cardStyle, data.style), + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.settingstablecardlabel, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + grow: 0, + shrink: 0, + basis: labelWidth || "auto", + style: {maxWidth: labelWidth || null}, + children: this.props.renderLabel(data) + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.settingstablecardconfigs, + justify: InternalComponents.LibraryComponents.Flex.Justify.AROUND, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + grow: 0, + shrink: 0, + basis: configWidth || "auto", + style: {maxWidth: configWidth || null}, + children: this.props.settings.map(setting => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + className: BDFDB.disCN.checkboxcontainer, + grow: 0, + shrink: 0, + wrap: true, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Checkbox, { + disabled: data.disabled, + cardId: data.key, + settingId: setting, + shape: InternalComponents.LibraryComponents.Checkbox.Shapes.ROUND, + type: InternalComponents.LibraryComponents.Checkbox.Types.INVERTED, + value: data[setting], + onChange: this.props.onCheckboxChange + }) + })).flat(10).filter(n => n) + }) + ] + }), "title", "data", "settings", "renderLabel", "cardClassName", "cardStyle", "onCheckboxChange", "maxWidth", "fullWidth", "biggestWidth", "pagination")); + let header = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.settingstableheaders, + align: InternalComponents.LibraryComponents.Flex.Align.STRETCH, + style: this.props.vertical && this.props.biggestWidth ? { + marginTop: this.props.biggestWidth - 15 || 0 + } : {}, + children: [].concat(this.props.title || "", this.props.settings).map((setting, i) => BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(i == 0 ? BDFDB.disCN.settingstableheadername : BDFDB.disCN.settingstableheaderoption, i != 0 && this.props.vertical && BDFDB.disCN.settingstableheadervertical, BDFDB.disCN.colorbase, BDFDB.disCN.size10, isHeaderClickable && BDFDB.disCN.cursorpointer), + onClick: _ => {if (typeof this.props.onHeaderClick == "function") this.props.onHeaderClick(setting, this);}, + onContextMenu: _ => {if (typeof this.props.onHeaderContextMenu == "function") this.props.onHeaderContextMenu(setting, this);}, + style: i != 0 && this.props.maxWidth ? { + maxWidth: this.props.maxWidth, + width: this.props.maxWidth, + flex: `0 0 ${this.props.maxWidth}px` + } : {}, + children: BDFDB.ReactUtils.createElement("span", { + children: setting + }) + })) + }); + let usePagination = BDFDB.ObjectUtils.is(this.props.pagination); + return !this.props.data.length ? null : BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.settingstablelist, this.props.className), + children: [ + !usePagination && header, + !usePagination ? this.props.data.map(renderItem) : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PaginatedList, Object.assign({}, this.props.pagination, { + header: header, + items: this.props.data, + renderItem: renderItem, + onJump: (offset, instance) => { + this.props.pagination.offset = offset; + if (typeof this.props.pagination.onJump == "function") this.props.pagination.onJump(offset, this, instance); + } + })) + ].filter(n => n) + }); + } + }; + + InternalComponents.LibraryComponents.SettingsSaveItem = reactInitialized && class BDFDB_SettingsSaveItem extends LibraryModules.React.Component { + saveSettings(value) { + if (!BDFDB.ArrayUtils.is(this.props.keys) || !BDFDB.ObjectUtils.is(this.props.plugin)) return; + let keys = this.props.keys.filter(n => n); + let option = keys.shift(); + if (BDFDB.ObjectUtils.is(this.props.plugin) && option) { + let data = BDFDB.DataUtils.load(this.props.plugin, option); + let newData = ""; + for (let key of keys) newData += `{"${key}":`; + value = value != null && value.value != null ? value.value : value; + let isString = typeof value == "string"; + let marker = isString ? `"` : ``; + newData += (marker + (isString ? value.replace(/\\/g, "\\\\") : value) + marker) + "}".repeat(keys.length); + newData = JSON.parse(newData); + BDFDB.DataUtils.save(BDFDB.ObjectUtils.is(newData) ? BDFDB.ObjectUtils.deepAssign({}, data, newData) : newData, this.props.plugin, option); + this.props.plugin.SettingsUpdated = true; + } + if (typeof this.props.onChange == "function") this.props.onChange(value, this); + } + render() { + if (typeof this.props.type != "string" || !["SELECT", "SLIDER", "SWITCH", "TEXTINPUT"].includes(this.props.type.toUpperCase())) return null; + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsItem, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + onChange: this.saveSettings.bind(this) + }), "keys", "key", "plugin")); + } + }; + + InternalComponents.LibraryComponents.SidebarList = reactInitialized && class BDFDB_SidebarList extends LibraryModules.React.Component { + handleItemSelect(item) { + this.props.selectedItem = item; + if (typeof this.props.onItemSelect == "function") this.props.onItemSelect(item, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + let items = (BDFDB.ArrayUtils.is(this.props.items) ? this.props.items : [{}]).filter(n => n); + let selectedItem = this.props.selectedItem || (items[0] || {}).value; + let selectedElements = (items.find(n => n.value == selectedItem) || {}).elements; + let renderElement = typeof this.props.renderElement == "function" ? this.props.renderElement : (_ => {}); + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.sidebarlist), + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ScrollerThin, { + className: BDFDB.DOMUtils.formatClassName(this.props.sidebarClassName, BDFDB.disCN.sidebar), + fade: true, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TabBar, { + itemClassName: this.props.itemClassName, + type: InternalComponents.LibraryComponents.TabBar.Types.SIDE, + items: items, + selectedItem: selectedItem, + renderItem: this.props.renderItem, + onItemSelect: this.handleItemSelect.bind(this) + }) + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ScrollerThin, { + className: BDFDB.DOMUtils.formatClassName(this.props.contentClassName, BDFDB.disCN.sidebarcontent), + fade: true, + children: [selectedElements].flat(10).filter(n => n).map(data => renderElement(data)) + }) + ] + }); + } + }; + + InternalComponents.LibraryComponents.Slider = reactInitialized && class BDFDB_Slider extends LibraryModules.React.Component { + handleMarkerRender(marker) { + let newMarker = BDFDB.NumberUtils.mapRange([0, 100], this.props.edges, marker); + if (typeof this.props.digits == "number") newMarker = Math.round(newMarker * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits); + return newMarker; + } + handleValueChange(value) { + let newValue = BDFDB.NumberUtils.mapRange([0, 100], this.props.edges, value); + if (typeof this.props.digits == "number") newValue = Math.round(newValue * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits); + this.props.defaultValue = this.props.value = newValue; + if (typeof this.props.onValueChange == "function") this.props.onValueChange(newValue, this); + BDFDB.ReactUtils.forceUpdate(this); + } + handleValueRender(value) { + let newValue = BDFDB.NumberUtils.mapRange([0, 100], this.props.edges, value); + if (typeof this.props.digits == "number") newValue = Math.round(newValue * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits); + if (typeof this.props.onValueRender == "function") { + let tempReturn = this.props.onValueRender(newValue, this); + if (tempReturn != undefined) newValue = tempReturn; + } + return newValue; + } + render() { + let value = this.props.value || this.props.defaultValue || 0; + if (!BDFDB.ArrayUtils.is(this.props.edges) || this.props.edges.length != 2) this.props.edges = [this.props.min || this.props.minValue || 0, this.props.max || this.props.maxValue || 100]; + this.props.minValue = 0; + this.props.maxValue = 100; + let defaultValue = BDFDB.NumberUtils.mapRange(this.props.edges, [0, 100], value); + if (typeof this.props.digits == "number") defaultValue = Math.round(defaultValue * Math.pow(10, this.props.digits)) / Math.pow(10, this.props.digits); + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.Slider, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + initialValue: defaultValue, + markers: typeof this.props.markerAmount == "number" ? Array.from(Array(this.props.markerAmount).keys()).map((_, i) => i * (this.props.maxValue - this.props.minValue)/10) : undefined, + onMarkerRender: this.handleMarkerRender.bind(this), + onValueChange: this.handleValueChange.bind(this), + onValueRender: this.handleValueRender.bind(this) + }), "digits", "edges", "max", "min", "markerAmount")); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Slider, {hideBubble:false}); + + InternalComponents.LibraryComponents.SvgIcon = reactInitialized && class BDFDB_Icon extends LibraryModules.React.Component { + render() { + if (BDFDB.ObjectUtils.is(this.props.name)) { + if (this.props.className) this.props.nativeClass = true; + this.props.iconSVG = this.props.name.icon; + let props = Object.assign({ + width: 24, + height: 24, + color: "currentColor" + }, this.props.name.defaultProps, this.props, { + className: BDFDB.DOMUtils.formatClassName(typeof this.props.name.getClassName == "function" && this.props.name.getClassName(this.props), this.props.className) + }); + for (let key in props) this.props.iconSVG = this.props.iconSVG.replace(new RegExp(`%%${key}`, "g"), props[key]); + } + if (this.props.iconSVG) { + let icon = BDFDB.ReactUtils.elementToReact(BDFDB.DOMUtils.create(this.props.iconSVG)); + if (BDFDB.ReactUtils.isValidElement(icon)) { + icon.props.className = BDFDB.DOMUtils.formatClassName(!this.props.nativeClass && BDFDB.disCN.svgicon, icon.props.className, this.props.className); + icon.props.style = Object.assign({}, icon.props.style, this.props.style); + icon.props = Object.assign({}, BDFDB.ObjectUtils.extract(this.props, "onClick", "onContextMenu", "onMouseDown", "onMouseUp", "onMouseEnter", "onMouseLeave"), icon.props); + return icon; + } + } + return null; + } + }; + InternalComponents.LibraryComponents.SvgIcon.Names = { + ARROW_DOWN: { + defaultProps: { + width: 18, + height: 18 + }, + icon: `` + }, + ARROW_UP: { + defaultProps: { + width: 18, + height: 18 + }, + icon: `` + }, + CHANGELOG: { + icon: `` + }, + WHATISTHIS: { + icon: `` + }, + CHECKBOX: { + defaultProps: { + background: "", + foreground: "" + }, + icon: `` + }, + CHECKBOX_EMPTY: { + defaultProps: { + foreground: "" + }, + icon: `` + }, + CHECKMARK: { + defaultProps: { + width: 18, + height: 18 + }, + icon: `` + }, + CLOSE: { + defaultProps: { + width: 12, + height: 12 + }, + icon: `` + }, + CLOSE_CIRCLE: { + icon: `` + }, + COG: { + defaultProps: { + width: 20, + height: 20 + }, + icon: `` + }, + CROWN: { + icon: `` + }, + DROPPER: { + defaultProps: { + width: 16, + height: 16, + foreground: "" + }, + icon: `` + }, + FOLDER: { + icon: `` + }, + GITHUB: { + icon: `` + }, + GRADIENT: { + defaultProps: { + width: 36, + height: 36 + }, + icon: `` + }, + LEFT_CARET: { + icon: `` + }, + LEFT_DOUBLE_CARET: { + icon: `` + }, + LOCK_CLOSED: { + icon: `` + }, + MENU_CARET: { + getClassName: props => BDFDB.DOMUtils.formatClassName(BDFDB.disCN.menucaretarrow, props.open && BDFDB.disCN.menucaretopen), + icon: `` + }, + MORE: { + icon: `` + }, + NOVA_AT: { + icon: `` + }, + NOVA_PIN: { + icon: `` + }, + NOVA_TRASH: { + icon: `` + }, + PENCIL: { + defaultProps: { + width: 16, + height: 16 + }, + icon: `` + }, + PIN: { + defaultProps: { + width: 16, + height: 16 + }, + icon: `` + }, + RAW_TEXT: { + icon: `` + }, + RIGHT_CARET: { + icon: `` + }, + RIGHT_DOUBLE_CARET: { + icon: `` + }, + SEARCH: { + defaultProps: { + width: 18, + height: 18 + }, + icon: `` + }, + SPEAKER: { + icon: `` + }, + STREAM: { + icon: `` + } + }; + + InternalComponents.LibraryComponents.Switch = reactInitialized && class BDFDB_Switch extends LibraryModules.React.Component { + handleChange() { + this.props.value = !this.props.value; + if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.Switch, Object.assign({}, this.props, {onChange: this.handleChange.bind(this)})); + } + }; + + InternalComponents.LibraryComponents.TabBar = reactInitialized && class BDFDB_TabBar extends LibraryModules.React.Component { + handleItemSelect(item) { + this.props.selectedItem = item; + if (typeof this.props.onItemSelect == "function") this.props.onItemSelect(item, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + let items = (BDFDB.ArrayUtils.is(this.props.items) ? this.props.items : [{}]).filter(n => n); + let selectedItem = this.props.selectedItem || (items[0] || {}).value; + let renderItem = typeof this.props.renderItem == "function" ? this.props.renderItem : (data => data.label || data.value); + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.TabBar, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + selectedItem: selectedItem, + onItemSelect: this.handleItemSelect.bind(this), + children: items.map(data => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TabBar.Item, { + className: BDFDB.DOMUtils.formatClassName(this.props.itemClassName, selectedItem == data.value && this.props.itemSelectedClassName), + itemType: this.props.type, + id: data.value, + children: renderItem(data), + "aria-label": data.label || data.value + })) + }), "itemClassName", "items", "renderItem")); + } + }; + + InternalComponents.LibraryComponents.Table = reactInitialized && class BDFDB_Table extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.Table, Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.table, this.props.className), + headerCellClassName: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tableheadercell, this.props.headerCellClassName), + sortedHeaderCellClassName: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tableheadercellsorted, this.props.sortedHeaderCellClassName), + bodyCellClassName: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.tablebodycell, this.props.bodyCellClassName), + onSort: (sortKey, sortDirection) => { + this.props.sortDirection = this.props.sortKey != sortKey && sortDirection == InternalComponents.LibraryComponents.Table.SortDirection.ASCENDING && this.props.columns.filter(n => n.key == sortKey)[0].reverse ? InternalComponents.LibraryComponents.Table.SortDirection.DESCENDING : sortDirection; + this.props.sortKey = sortKey; + this.props.data = BDFDB.ArrayUtils.keySort(this.props.data, this.props.sortKey); + if (this.props.sortDirection == InternalComponents.LibraryComponents.Table.SortDirection.DESCENDING) this.props.data.reverse(); + if (typeof this.props.onSort == "function") this.props.onSort(this.props.sortKey, this.props.sortDirection); + BDFDB.ReactUtils.forceUpdate(this); + } + })); + } + }; + + InternalComponents.LibraryComponents.TextArea = reactInitialized && class BDFDB_TextArea extends LibraryModules.React.Component { + handleChange(e) { + this.props.value = e; + if (typeof this.props.onChange == "function") this.props.onChange(e, this); + BDFDB.ReactUtils.forceUpdate(this); + } + handleBlur(e) {if (typeof this.props.onBlur == "function") this.props.onBlur(e, this);} + handleFocus(e) {if (typeof this.props.onFocus == "function") this.props.onFocus(e, this);} + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.TextArea, Object.assign({}, this.props, { + onChange: this.handleChange.bind(this), + onBlur: this.handleBlur.bind(this), + onFocus: this.handleFocus.bind(this) + })); + } + }; + + InternalComponents.LibraryComponents.TextGradientElement = reactInitialized && class BDFDB_TextGradientElement extends LibraryModules.React.Component { + render() { + if (this.props.gradient && this.props.children) return BDFDB.ReactUtils.createElement("span", { + children: this.props.children, + ref: instance => { + let ele = BDFDB.ReactUtils.findDOMNode(instance); + if (ele) { + ele.style.setProperty("background-image", this.props.gradient, "important"); + ele.style.setProperty("color", "transparent", "important"); + ele.style.setProperty("-webkit-background-clip", "text", "important"); + } + } + }); + return this.props.children || null; + } + }; + + InternalComponents.LibraryComponents.TextInput = reactInitialized && class BDFDB_TextInput extends LibraryModules.React.Component { + handleChange(e) { + let value = e = BDFDB.ObjectUtils.is(e) ? e.currentTarget.value : e; + this.props.value = this.props.valuePrefix && !value.startsWith(this.props.valuePrefix) ? (this.props.valuePrefix + value) : value; + if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this); + BDFDB.ReactUtils.forceUpdate(this); + } + handleInput(e) {if (typeof this.props.onInput == "function") this.props.onInput(BDFDB.ObjectUtils.is(e) ? e.currentTarget.value : e, this);} + handleKeyDown(e) {if (typeof this.props.onKeyDown == "function") this.props.onKeyDown(e, this);} + handleBlur(e) {if (typeof this.props.onBlur == "function") this.props.onBlur(e, this);} + handleFocus(e) {if (typeof this.props.onFocus == "function") this.props.onFocus(e, this);} + handleMouseEnter(e) {if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this);} + handleMouseLeave(e) {if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this);} + handleNumberButton(ins, value) { + BDFDB.TimeUtils.clear(ins.pressedTimeout); + ins.pressedTimeout = BDFDB.TimeUtils.timeout(_ => { + delete this.props.focused; + BDFDB.ReactUtils.forceUpdate(this); + }, 1000); + this.props.focused = true; + this.handleChange.bind(this)(value); + this.handleInput.bind(this)(value); + } + componentDidMount() { + if (this.props.type == "file") { + let navigatorInstance = BDFDB.ReactUtils.findOwner(this, {name: "BDFDB_FileButton"}); + if (navigatorInstance) navigatorInstance.refInput = this; + } + let input = BDFDB.ReactUtils.findDOMNode(this); + if (!input) return; + input = input.querySelector("input") || input; + if (input && !input.patched) { + input.addEventListener("keydown", e => { + this.handleKeyDown.bind(this)(e); + e.stopImmediatePropagation(); + }); + input.patched = true; + } + } + render() { + let inputChildren = [ + BDFDB.ReactUtils.createElement("input", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName(this.props.size && InternalComponents.LibraryComponents.TextInput.Sizes[this.props.size.toUpperCase()] && BDFDB.disCN["input" + this.props.size.toLowerCase()] || BDFDB.disCN.inputdefault, this.props.inputClassName, this.props.focused && BDFDB.disCN.inputfocused, this.props.error || this.props.errorMessage ? BDFDB.disCN.inputerror : (this.props.success && BDFDB.disCN.inputsuccess), this.props.disabled && BDFDB.disCN.inputdisabled, this.props.editable && BDFDB.disCN.inputeditable), + type: this.props.type == "color" || this.props.type == "file" ? "text" : this.props.type, + onChange: this.handleChange.bind(this), + onInput: this.handleInput.bind(this), + onKeyDown: this.handleKeyDown.bind(this), + onBlur: this.handleBlur.bind(this), + onFocus: this.handleFocus.bind(this), + onMouseEnter: this.handleMouseEnter.bind(this), + onMouseLeave: this.handleMouseLeave.bind(this), + maxLength: this.props.type == "file" ? false : this.props.maxLength, + ref: this.props.inputRef + }), "errorMessage", "focused", "error", "success", "inputClassName", "inputChildren", "valuePrefix", "inputPrefix", "size", "editable", "inputRef", "style", "mode", "noAlpha", "filter", "useFilePath", "searchFolders")), + this.props.inputChildren, + this.props.type == "color" ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + wrap: true, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ColorSwatches, { + colors: [], + color: this.props.value && this.props.mode == "comp" ? BDFDB.ColorUtils.convert(this.props.value.split(","), "RGB") : this.props.value, + onColorChange: color => { + this.handleChange(!color ? "" : (this.props.mode == "comp" ? BDFDB.ColorUtils.convert(color, "RGBCOMP").slice(0, 3).join(",") : (this.props.noAlpha ? BDFDB.ColorUtils.convert(color, "RGB") : color))); + }, + pickerConfig: {gradient:false, alpha:this.props.mode != "comp" && !this.props.noAlpha} + }) + }) : null, + this.props.type == "file" ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FileButton, { + filter: this.props.filter, + mode: this.props.mode, + useFilePath: this.props.useFilePath, + searchFolders: this.props.searchFolders + }) : null + ].flat(10).filter(n => n); + + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.inputwrapper, this.props.type == "number" && (this.props.size && InternalComponents.LibraryComponents.TextInput.Sizes[this.props.size.toUpperCase()] && BDFDB.disCN["inputnumberwrapper" + this.props.size.toLowerCase()] || BDFDB.disCN.inputnumberwrapperdefault), this.props.className), + style: this.props.style, + children: [ + this.props.inputPrefix ? BDFDB.ReactUtils.createElement("span", { + className: BDFDB.disCN.inputprefix + }) : null, + this.props.type == "number" ? BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.inputnumberbuttons, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.inputnumberbuttonup, + onClick: e => { + let min = parseInt(this.props.min); + let max = parseInt(this.props.max); + let newv = parseInt(this.props.value) + 1 || min || 0; + if (isNaN(max) || !isNaN(max) && newv <= max) this.handleNumberButton.bind(this)(e._targetInst, isNaN(min) || !isNaN(min) && newv >= min ? newv : min); + } + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.inputnumberbuttondown, + onClick: e => { + let min = parseInt(this.props.min); + let max = parseInt(this.props.max); + let newv = parseInt(this.props.value) - 1 || min || 0; + if (isNaN(min) || !isNaN(min) && newv >= min) this.handleNumberButton.bind(this)(e._targetInst, isNaN(max) || !isNaN(max) && newv <= max ? newv : max); + } + }) + ] + }) : null, + inputChildren.length == 1 ? inputChildren[0] : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: inputChildren.map((child, i) => i != 0 ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, {shrink: 0, children: child}) : child) + }), + this.props.errorMessage ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextElement, { + className: BDFDB.disCN.carderror, + size: InternalComponents.LibraryComponents.TextElement.Sizes.SIZE_12, + color: InternalComponents.LibraryComponents.TextElement.Colors.STATUS_RED, + children: this.props.errorMessage + }) : null + ].filter(n => n) + }); + } + }; + + InternalComponents.LibraryComponents.TextScroller = reactInitialized && class BDFDB_TextScroller extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.textscroller, this.props.className), + style: Object.assign({}, this.props.style, { + position: "relative", + display: "block", + overflow: "hidden" + }), + ref: instance => { + let ele = BDFDB.ReactUtils.findDOMNode(instance); + if (ele && ele.parentElement) { + let maxWidth = BDFDB.DOMUtils.getInnerWidth(ele.parentElement); + if (maxWidth > 50) ele.style.setProperty("max-width", `${maxWidth}px`); + BDFDB.TimeUtils.timeout(_ => { + if (document.contains(ele.parentElement)) { + let newMaxWidth = BDFDB.DOMUtils.getInnerWidth(ele.parentElement); + if (newMaxWidth > maxWidth) ele.style.setProperty("max-width", `${newMaxWidth}px`); + } + }, 3000); + let Animation = new LibraryModules.AnimationUtils.Value(0); + Animation + .interpolate({inputRange:[0, 1], outputRange:[0, (BDFDB.DOMUtils.getRects(ele.firstElementChild).width - BDFDB.DOMUtils.getRects(ele).width) * -1]}) + .addListener(v => {ele.firstElementChild.style.setProperty("left", `${v.value}px`, "important");}); + this.scroll = p => { + let w = p + parseFloat(ele.firstElementChild.style.getPropertyValue("left")) / (BDFDB.DOMUtils.getRects(ele.firstElementChild).width - BDFDB.DOMUtils.getRects(ele).width); + w = isNaN(w) || !isFinite(w) ? p : w; + w *= BDFDB.DOMUtils.getRects(ele.firstElementChild).width / (BDFDB.DOMUtils.getRects(ele).width * 2); + LibraryModules.AnimationUtils.parallel([LibraryModules.AnimationUtils.timing(Animation, {toValue:p, duration:Math.sqrt(w**2) * 4000 / (parseInt(this.props.speed) || 1)})]).start(); + } + } + }, + onClick: e => { + if (typeof this.props.onClick == "function") this.props.onClick(e, this); + }, + onMouseEnter: e => { + if (BDFDB.DOMUtils.getRects(e.currentTarget).width < BDFDB.DOMUtils.getRects(e.currentTarget.firstElementChild).width) { + this.scrolling = true; + e.currentTarget.firstElementChild.style.setProperty("display", "block", "important"); + this.scroll(1); + } + }, + onMouseLeave: e => { + if (this.scrolling) { + delete this.scrolling; + e.currentTarget.firstElementChild.style.setProperty("display", "inline", "important"); + this.scroll(0); + } + }, + children: BDFDB.ReactUtils.createElement("div", { + style: { + left: "0", + position: "relative", + display: "inline", + whiteSpace: "nowrap" + }, + children: this.props.children + }) + }); + } + }; + InternalComponents.LibraryComponents.TooltipContainer = reactInitialized && class BDFDB_TooltipContainer extends LibraryModules.React.Component { + updateTooltip(text) { + if (this.tooltip) this.tooltip.update(text); + } + render() { + let child = (BDFDB.ArrayUtils.is(this.props.children) ? this.props.children[0] : this.props.children) || BDFDB.ReactUtils.createElement("div", {}); + child.props.className = BDFDB.DOMUtils.formatClassName(child.props.className, this.props.className); + let childMouseEnter = child.props.onMouseEnter, childMouseLeave = child.props.onMouseLeave, childClick = child.props.onClick, childContextMenu = child.props.onContextMenu; + let shown = false; + child.props.onMouseEnter = (e, childThis) => { + if (!shown) { + shown = true; + this.tooltip = BDFDB.TooltipUtils.create(e.currentTarget, typeof this.props.text == "function" ? this.props.text(this) : this.props.text, Object.assign({delay: this.props.delay}, this.props.tooltipConfig)); + if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this); + if (typeof childMouseEnter == "function") childMouseEnter(e, childThis); + } + }; + child.props.onMouseLeave = (e, childThis) => { + shown = false; + if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this); + if (typeof childMouseLeave == "function") childMouseLeave(e, childThis); + }; + child.props.onClick = (e, childThis) => { + if (typeof this.props.onClick == "function") this.props.onClick(e, this); + if (typeof childClick == "function") childClick(e, childThis); + }; + child.props.onContextMenu = (e, childThis) => { + if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this); + if (typeof childContextMenu == "function") childContextMenu(e, childThis); + }; + return BDFDB.ReactUtils.createElement(LibraryModules.React.Fragment, { + children: child + }); + } + }; + + InternalComponents.LibraryComponents.UserPopoutContainer = reactInitialized && class BDFDB_UserPopoutContainer extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutContainer, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + wrap: false, + renderPopout: instance => { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.UserPopout, { + userId: this.props.userId, + guildId: this.props.guildId, + channelId: this.props.channelId + }); + } + }), "userId", "guildId", "channelId")); + } + }; + + for (let type in InternalComponents.NativeSubComponents) if (InternalComponents.LibraryComponents[type]) for (let key in InternalComponents.NativeSubComponents[type]) if (key != "displayName" && key != "name" && (typeof InternalComponents.NativeSubComponents[type][key] != "function" || key.charAt(0) == key.charAt(0).toUpperCase())) { + if (key == "defaultProps") InternalComponents.LibraryComponents[type][key] = Object.assign({}, InternalComponents.LibraryComponents[type][key], InternalComponents.NativeSubComponents[type][key]); + else InternalComponents.LibraryComponents[type][key] = InternalComponents.NativeSubComponents[type][key]; + } + BDFDB.LibraryComponents = Object.assign({}, InternalComponents.LibraryComponents); + + const keyDownTimeouts = {}; + BDFDB.ListenerUtils.add(BDFDB, document, "keydown.BDFDBPressedKeys", e => { + if (!pressedKeys.includes(e.which)) { + BDFDB.TimeUtils.clear(keyDownTimeouts[e.which]); + pressedKeys.push(e.which); + keyDownTimeouts[e.which] = BDFDB.TimeUtils.timeout(_ => { + BDFDB.ArrayUtils.remove(pressedKeys, e.which, true); + }, 60000); + } + }); + BDFDB.ListenerUtils.add(BDFDB, document, "keyup.BDFDBPressedKeys", e => { + BDFDB.TimeUtils.clear(keyDownTimeouts[e.which]); + BDFDB.ArrayUtils.remove(pressedKeys, e.which, true); + }); + BDFDB.ListenerUtils.add(BDFDB, document, "mousedown.BDFDBMousePosition", e => { + mousePosition = e; + }); + BDFDB.ListenerUtils.add(BDFDB, window, "focus.BDFDBPressedKeysReset", e => { + pressedKeys = []; + }); + + InternalBDFDB.patchedModules = { + before: { + MessageContent: "type" + }, + after: { + DiscordTag: "default", + Mention: "default", + Message: "default", + MessageHeader: "default", + MemberListItem: ["componentDidMount", "componentDidUpdate"], + PrivateChannel: ["componentDidMount", "componentDidUpdate"], + UserPopout: ["componentDidMount", "componentDidUpdate"], + UserProfile: ["componentDidMount", "componentDidUpdate"], + V2C_ContentColumn: "render" + } + }; + + InternalBDFDB.processV2CContentColumn = function (e) { + if (window.PluginUpdates && window.PluginUpdates.plugins && typeof e.instance.props.title == "string" && e.instance.props.title.toUpperCase().indexOf("PLUGINS") == 0) { + let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {key: "folder-button"}); + if (index > -1) children.splice(index + 1, 0, BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: "Only checks for updates of plugins, which support the updatecheck. Rightclick for a list of supported plugins. (Listed ≠ Outdated)", + tooltipConfig: { + type: "bottom", + maxWidth: 420 + }, + onContextMenu: (event, instance) => { + instance.updateTooltip(BDFDB.ObjectUtils.toArray(window.PluginUpdates.plugins).map(p => p.name).filter(n => n).sort().join(", ")); + }, + children: BDFDB.ReactUtils.createElement("button", { + className: `${BDFDB.disCNS._repobutton + BDFDB.disCN._repofolderbutton} bd-updatebtn`, + onClick: _ => { + let toast = BDFDB.NotificationUtils.toast("Plugin update check in progress.", {type: "info", timeout: 0}); + BDFDB.PluginUtils.checkAllUpdates().then(outdated => { + toast.close(); + if (outdated > 0) BDFDB.NotificationUtils.toast(`Plugin update check complete. ${outdated} outdated!`, {type: "error"}); + else BDFDB.NotificationUtils.toast(`Plugin update check complete.`, {type: "success"}); + }); + }, + children: "Check for Updates" + }) + })); + } + }; + + let MessageHeaderExport = BDFDB.ModuleUtils.findByProperties("MessageTimestamp", false); + if (MessageHeaderExport) InternalBDFDB.processMessage = function (e) { + if (BDFDB.ObjectUtils.get(e, "instance.props.childrenHeader.type.type.name") && BDFDB.ObjectUtils.get(e, "instance.props.childrenHeader.props.message")) { + e.instance.props.childrenHeader.type = MessageHeaderExport.exports.default; + } + }; + + const BDFDB_Patrons = Object.assign({}, InternalData.BDFDB_Patrons); + InternalBDFDB._processAvatarRender = function (user, avatar) { + if (BDFDB.ReactUtils.isValidElement(avatar) && BDFDB.ObjectUtils.is(user)) { + avatar.props["user_by_BDFDB"] = user.id; + let role = "", className = BDFDB.DOMUtils.formatClassName((avatar.props.className || "").replace(BDFDB.disCN.avatar, "")), addBadge = settings.showSupportBadges, customBadge = false; + if (BDFDB_Patrons[user.id] && BDFDB_Patrons[user.id].active) { + role = BDFDB_Patrons[user.id].t3 ? "BDFDB Patron Level 2" : "BDFDB Patron"; + customBadge = addBadge && BDFDB_Patrons[user.id].t3 && BDFDB_Patrons[user.id].custom; + className = BDFDB.DOMUtils.formatClassName(className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbsupporter, customBadge && BDFDB.disCN.bdfdbsupportercustom); + } + if (user.id == myId) { + addBadge = true; + role = "Theme Developer"; + className = BDFDB.DOMUtils.formatClassName(className, BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbdev); + } + if (role) { + delete avatar.props["user_by_BDFDB"]; + if (avatar.type == "img") avatar = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AvatarComponents.default, Object.assign({}, avatar.props, { + size: BDFDB.LibraryComponents.AvatarComponents.Sizes.SIZE_40 + })); + delete avatar.props.className; + avatar = BDFDB.ReactUtils.createElement("div", { + className: className, + style: {borderRadius: 0, overflow: "visible"}, + "custombadge_id": customBadge ? user.id : null, + "user_by_BDFDB": user.id, + children: [avatar] + }); + if (addBadge) avatar.props.children.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: role, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.bdfdbbadge + }) + })); + return avatar; + } + } + }; + InternalBDFDB._processAvatarMount = function (user, avatar, wrapper) { + if (Node.prototype.isPrototypeOf(avatar) && BDFDB.ObjectUtils.is(user)) { + if (wrapper) wrapper.setAttribute("user_by_BDFDB", user.id); + avatar.setAttribute("user_by_BDFDB", user.id); + let role = "", addBadge = settings.showSupportBadges, customBadge = false; + if (BDFDB_Patrons[user.id] && BDFDB_Patrons[user.id].active) { + role = BDFDB_Patrons[user.id].t3 ? "BDFDB Patron Level 2" : "BDFDB Patron"; + customBadge = addBadge && BDFDB_Patrons[user.id].t3 && BDFDB_Patrons[user.id].custom; + avatar.className = BDFDB.DOMUtils.formatClassName(avatar.className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbsupporter, customBadge && BDFDB.disCN.bdfdbsupportercustom); + } + else if (user.id == myId) { + addBadge = true; + role = "Theme Developer"; + avatar.className = BDFDB.DOMUtils.formatClassName(avatar.className, BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbdev); + } + if (role && !avatar.querySelector(BDFDB.dotCN.bdfdbbadge)) { + if (addBadge) { + if (customBadge) avatar.setAttribute("custombadge_id", user.id); + let badge = document.createElement("div"); + badge.className = BDFDB.disCN.bdfdbbadge; + badge.addEventListener("mouseenter", _ => {BDFDB.TooltipUtils.create(badge, role, {position: "top"});}); + avatar.style.setProperty("position", "relative"); + avatar.style.setProperty("overflow", "visible"); + avatar.style.setProperty("border-radius", 0); + avatar.appendChild(badge); + } + } + } + }; + InternalBDFDB.processMessageHeader = function (e) { + if (e.instance.props.message && e.instance.props.message.author) { + let avatarWrapper = BDFDB.ObjectUtils.get(e, "returnvalue.props.children.0"); + if (avatarWrapper && avatarWrapper.props && typeof avatarWrapper.props.children == "function") { + let renderChildren = avatarWrapper.props.children; + avatarWrapper.props.children = (...args) => { + let renderedChildren = renderChildren(...args); + return InternalBDFDB._processAvatarRender(e.instance.props.message.author, renderedChildren) || renderedChildren; + }; + } + else if (avatarWrapper && avatarWrapper.type == "img") e.returnvalue.props.children[0] = InternalBDFDB._processAvatarRender(e.instance.props.message.author, avatarWrapper) || avatarWrapper; + } + }; + InternalBDFDB.processMemberListItem = function (e) { + InternalBDFDB._processAvatarMount(e.instance.props.user, e.node.querySelector(BDFDB.dotCN.avatarwrapper)); + }; + InternalBDFDB.processPrivateChannel = function (e) { + InternalBDFDB._processAvatarMount(e.instance.props.user, e.node.querySelector(BDFDB.dotCN.avatarwrapper)); + }; + InternalBDFDB.processUserPopout = function (e) { + InternalBDFDB._processAvatarMount(e.instance.props.user, e.node.querySelector(BDFDB.dotCN.userpopoutavatarwrapper), e.node); + }; + InternalBDFDB.processUserProfile = function (e) { + InternalBDFDB._processAvatarMount(e.instance.props.user, e.node.querySelector(BDFDB.dotCN.avatarwrapper), e.node); + }; + InternalBDFDB.processDiscordTag = function (e) { + if (e.instance && e.instance.props && e.returnvalue && e.instance.props.user) e.returnvalue.props.user = e.instance.props.user; + }; + InternalBDFDB.processMessageContent = function (e) { + if (BDFDB.ArrayUtils.is(e.instance.props.content)) for (let ele of e.instance.props.content) InternalBDFDB._processMessageContentEle(ele, e.instance.props.message); + }; + InternalBDFDB._processMessageContentEle = function (ele, message) { + if (BDFDB.ReactUtils.isValidElement(ele)) { + if (typeof ele.props.render == "function" && BDFDB.ObjectUtils.get(ele, "props.children.type.displayName") == "Mention") { + let userId = BDFDB.ObjectUtils.get(ele.props.render(), "props.userId"); + if (userId && !ele.props.children.props.userId) ele.props.children.props.userId = userId; + if (message && message.mentioned) ele.props.children.props.mentioned = true; + } + else if (BDFDB.ReactUtils.isValidElement(ele.props.children)) InternalBDFDB._processMessageContentEle(ele.props.children, message); + else if (BDFDB.ArrayUtils.is(ele.props.children)) for (let child of ele.props.children) InternalBDFDB._processMessageContentEle(child, message); + } + else if (BDFDB.ArrayUtils.is(ele)) for (let child of ele) InternalBDFDB._processMessageContentEle(child, message); + }; + InternalBDFDB.processMention = function (e) { + delete e.returnvalue.props.userId; + }; + + const ContextMenuTypes = ["UserSettingsCog", "User", "Developer", "Slate", "GuildFolder", "GroupDM", "SystemMessage", "Message", "Native", "Role", "Guild", "Channel"]; + const QueuedComponents = BDFDB.ArrayUtils.removeCopies([].concat(ContextMenuTypes.map(n => n + "ContextMenu"), ["GuildHeaderContextMenu", "MessageOptionContextMenu", "MessageOptionToolbar"])); + InternalBDFDB.addContextListeners = function (plugin) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + for (let type of QueuedComponents) if (typeof plugin[`on${type}`] === "function") { + componentPatchQueries[type].query.push(plugin); + componentPatchQueries[type].query = BDFDB.ArrayUtils.removeCopies(componentPatchQueries[type].query); + componentPatchQueries[type].query.sort((x, y) => {return x.name < y.name ? -1 : x.name > y.name ? 1 : 0;}); + for (let module of componentPatchQueries[type].modules) InternalBDFDB.patchContextMenuForPlugin(plugin, type, module); + } + }; + InternalBDFDB.patchContextMenuForPlugin = function (plugin, type, module) { + plugin = plugin == BDFDB && InternalBDFDB || plugin; + if (module && module.exports && module.exports.default) BDFDB.PatchUtils.patch(plugin, module.exports, "default", {after: e => { + if (e.returnValue && typeof plugin[`on${type}`] === "function") plugin[`on${type}`]({instance:{props:e.methodArguments[0]}, returnvalue:e.returnValue, methodname:"default", type:module.exports.default.displayName}); + }}); + }; + InternalBDFDB.executeExtraPatchedPatches = function (type, e) { + if (e.returnvalue && BDFDB.ObjectUtils.is(componentPatchQueries[type]) && BDFDB.ArrayUtils.is(componentPatchQueries[type].query)) { + for (let plugin of componentPatchQueries[type].query) if(typeof plugin[`on${type}`] === "function") plugin[`on${type}`](e); + } + }; + + InternalBDFDB.patchPlugin(BDFDB); + + for (let type of QueuedComponents) if (!componentPatchQueries[type]) componentPatchQueries[type] = {query:[], modules:[]}; + BDFDB.PatchUtils.patch(BDFDB, LibraryModules.ContextMenuUtils, "openContextMenu", {before: e => { + let menu = e.methodArguments[1](); + if (BDFDB.ObjectUtils.is(menu) && menu.type && menu.type.displayName) { + for (let type of ContextMenuTypes) if (menu.type.displayName.indexOf(type) > -1) { + let patchType = type + "ContextMenu"; + let module = BDFDB.ModuleUtils.find(m => m == menu.type, false); + if (module && module.exports && module.exports.default && componentPatchQueries[patchType]) { + componentPatchQueries[patchType].modules.push(module); + componentPatchQueries[patchType].modules = BDFDB.ArrayUtils.removeCopies(componentPatchQueries[patchType].modules); + for (let plugin of componentPatchQueries[patchType].query) InternalBDFDB.patchContextMenuForPlugin(plugin, patchType, module); + } + break; + } + } + }}); + + BDFDB.PatchUtils.patch(BDFDB, BDFDB.ObjectUtils.get(BDFDB.ModuleUtils.findByString("renderReactions", "canAddNewReactions", "showMoreUtilities", false), "exports.default"), "type", {after: e => { + if (document.querySelector(BDFDB.dotCN.emojipicker) || !BDFDB.ObjectUtils.toArray(BDFDB.myPlugins).some(p => p.onMessageOptionContextMenu || p.onMessageOptionToolbar)) return; + let toolbar = BDFDB.ReactUtils.findChild(e.returnValue, {filter: c => c && c.props && c.props.showMoreUtilities != undefined && c.props.showEmojiPicker != undefined && c.props.setPopout != undefined}); + if (toolbar) BDFDB.PatchUtils.patch(BDFDB, toolbar, "type", {after: e2 => { + let menu = BDFDB.ReactUtils.findChild(e2.returnValue, {filter: c => c && c.props && typeof c.props.onRequestClose == "function" && c.props.onRequestClose.toString().indexOf("moreUtilities") > -1}); + InternalBDFDB.executeExtraPatchedPatches("MessageOptionToolbar", {instance:{props:e2.methodArguments[0]}, returnvalue:e2.returnValue, methodname:"default"}); + if (menu && typeof menu.props.renderPopout == "function") { + let renderPopout = menu.props.renderPopout; + menu.props.renderPopout = (...args) => { + let renderedPopout = renderPopout(...args); + BDFDB.PatchUtils.patch(BDFDB, renderedPopout, "type", {after: e3 => { + InternalBDFDB.executeExtraPatchedPatches("MessageOptionContextMenu", {instance:{props:e3.methodArguments[0]}, returnvalue:e3.returnValue, methodname:"default"}); + }}, {noCache: true}); + return renderedPopout; + } + } + }}, {once: true}); + }}); + + BDFDB.PatchUtils.patch(BDFDB, BDFDB.ObjectUtils.get(BDFDB.ModuleUtils.findByString("guild-header-popout", false), "exports.default.prototype"), "render", {after: e => { + BDFDB.PatchUtils.patch(BDFDB, e.returnValue.type, "type", {after: e2 => { + InternalBDFDB.executeExtraPatchedPatches("GuildHeaderContextMenu", {instance:{props:e2.methodArguments[0]}, returnvalue:e2.returnValue, methodname:"type"}); + }}, {noCache: true}); + }}); + + InternalBDFDB.onSettingsClosed = function () { + if (InternalBDFDB.SettingsUpdated) { + delete InternalBDFDB.SettingsUpdated; + InternalBDFDB.forceUpdateAll(); + } + }; + + InternalBDFDB.forceUpdateAll = function () { + if (LibraryRequires.path) settings = BDFDB.DataUtils.get(this, "settings"); + + BDFDB.MessageUtils.rerenderAll(); + BDFDB.PatchUtils.forceAllUpdates(BDFDB); + }; + + addSpecialListeners(BDFDB); + + let BasePopout = BDFDB.ModuleUtils.findByName("BasePopout"), ReferencePositionLayer = BDFDB.ModuleUtils.findByName("ReferencePositionLayer"); + if (BasePopout && ReferencePositionLayer) BDFDB.PatchUtils.patch(BDFDB, BasePopout.prototype, "renderLayer", {after: e => { + if (e.returnValue && e.thisObject.isBDFDBpopout) { + e.returnValue = BDFDB.ReactUtils.createPortal(BDFDB.ReactUtils.createElement(ReferencePositionLayer, e.returnValue.props), document.querySelector(BDFDB.dotCN.appmount + " > " + BDFDB.dotCN.itemlayercontainer)); + } + }}); + + if (InternalComponents.LibraryComponents.GuildComponents.BlobMask) { + let newBadges = ["lowerLeftBadge", "upperLeftBadge"]; + BDFDB.PatchUtils.patch(BDFDB, InternalComponents.LibraryComponents.GuildComponents.BlobMask.prototype, "render", { + before: e => { + e.thisObject.props = Object.assign({}, InternalComponents.LibraryComponents.GuildComponents.BlobMask.defaultProps, e.thisObject.props); + for (let type of newBadges) if (!e.thisObject.state[`${type}Mask`]) e.thisObject.state[`${type}Mask`] = new InternalComponents.LibraryComponents.Animations.Controller({spring: 0}); + }, + after: e => { + let [children, index] = BDFDB.ReactUtils.findParent(e.returnValue, {name: "TransitionGroup"}); + if (index > -1) { + children[index].props.children.push(!e.thisObject.props.lowerLeftBadge ? null : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.BadgeAnimationContainer, { + className: BDFDB.disCN.guildlowerleftbadge, + key: "lower-left-badge", + animatedStyle: e.thisObject.getLowerLeftBadgeStyles(), + children: e.thisObject.props.lowerLeftBadge + })); + children[index].props.children.push(!e.thisObject.props.upperLeftBadge ? null : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.BadgeAnimationContainer, { + className: BDFDB.disCN.guildupperleftbadge, + key: "upper-left-badge", + animatedStyle: e.thisObject.getUpperLeftBadgeStyles(), + children: e.thisObject.props.upperLeftBadge + })); + } + [children, index] = BDFDB.ReactUtils.findParent(e.returnValue, {name: "mask"}); + if (index > -1) { + children[index].props.children.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.rect, { + x: -4, + y: -4, + width: e.thisObject.props.upperLeftBadgeWidth + 8, + height: 24, + rx: 12, + ry: 12, + transform: e.thisObject.getLeftBadgePositionInterpolation(e.thisObject.state.upperLeftBadgeMask, -1), + fill: "black" + })); + children[index].props.children.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.rect, { + x: -4, + y: 28, + width: e.thisObject.props.lowerLeftBadgeWidth + 8, + height: 24, + rx: 12, + ry: 12, + transform: e.thisObject.getLeftBadgePositionInterpolation(e.thisObject.state.lowerLeftBadgeMask), + fill: "black" + })); + } + } + }); + BDFDB.PatchUtils.patch(BDFDB, InternalComponents.LibraryComponents.GuildComponents.BlobMask.prototype, "componentDidMount", { + after: e => { + for (let type of newBadges) e.thisObject.state[`${type}Mask`].update({ + spring: e.thisObject.props[type] != null ? 1 : 0, + immediate: true + }).start(); + } + }); + BDFDB.PatchUtils.patch(BDFDB, InternalComponents.LibraryComponents.GuildComponents.BlobMask.prototype, "componentWillUnmount", { + after: e => { + for (let type of newBadges) if (e.thisObject.state[`${type}Mask`]) e.thisObject.state[`${type}Mask`].dispose(); + } + }); + BDFDB.PatchUtils.patch(BDFDB, InternalComponents.LibraryComponents.GuildComponents.BlobMask.prototype, "componentDidUpdate", { + after: e => { + for (let type of newBadges) if (e.thisObject.props[type] != null && e.methodArguments[0][type] == null) { + e.thisObject.state[`${type}Mask`].update({ + spring: 1, + immediate: !document.hasFocus(), + config: {friction: 30, tension: 900, mass: 1} + }).start(); + } + else if (e.thisObject.props[type] == null && e.methodArguments[0][type] != null) { + e.thisObject.state[`${type}Mask`].update({ + spring: 0, + immediate: !document.hasFocus(), + config: {duration: 150, friction: 10, tension: 100, mass: 1} + }).start(); + } + } + }); + InternalComponents.LibraryComponents.GuildComponents.BlobMask.prototype.getLeftBadgePositionInterpolation = function (e, t) { + return void 0 === t && (t = 1), e.springs.spring.to([0, 1], [20, 0]).to(function (e) { + return "translate(" + e * -1 + " " + e * t + ")"; + }); + }; + InternalComponents.LibraryComponents.GuildComponents.BlobMask.prototype.getLowerLeftBadgeStyles = function () { + var e = this.state.lowerLeftBadgeMask.springs.spring; + return { + opacity: e.to([0, .5, 1], [0, 0, 1]), + transform: e.to(function (e) { + return "translate(" + -1 * (16 - 16 * e) + "px, " + (16 - 16 * e) + "px)"; + }) + }; + }; + InternalComponents.LibraryComponents.GuildComponents.BlobMask.prototype.getUpperLeftBadgeStyles = function () { + var e = this.state.upperLeftBadgeMask.springs.spring; + return { + opacity: e.to([0, .5, 1], [0, 0, 1]), + transform: e.to(function (e) { + return "translate(" + -1 * (16 - 16 * e) + "px, " + -1 * (16 - 16 * e) + "px)"; + }) + }; + }; + let extraDefaultProps = {}; + for (let type of newBadges) extraDefaultProps[`${type}Width`] = 16; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.GuildComponents.BlobMask, extraDefaultProps); + } + + BDFDB.PatchUtils.patch(BDFDB, LibraryModules.GuildStore, "getGuild", {after: e => { + if (e.returnValue && e.methodArguments[0] == myGuildId) e.returnValue.banner = "https://mwittrien.github.io/BetterDiscordAddons/Library/_res/BDFDB.banner.png"; + }}); + + BDFDB.PatchUtils.patch(BDFDB, LibraryModules.IconUtils, "getGuildBannerURL", {instead: e => { + return e.methodArguments[0].id == myGuildId ? e.methodArguments[0].banner : e.callOriginalMethod(); + }}); + + InternalBDFDB.forceUpdateAll(); + + const pluginQueue = window.BDFDB && BDFDB.ArrayUtils.is(window.BDFDB.pluginQueue) ? window.BDFDB.pluginQueue : []; + + if (BDFDB.UserUtils.me.id == myId) { + for (let module in DiscordClassModules) if (!DiscordClassModules[module]) BDFDB.LogUtils.warn(module + " not initialized in DiscordClassModules"); + for (let obj in DiscordObjects) if (!DiscordObjects[obj]) BDFDB.LogUtils.warn(obj + " not initialized in DiscordObjects"); + for (let require in LibraryRequires) if (!LibraryRequires[require]) BDFDB.LogUtils.warn(require + " not initialized in LibraryRequires"); + for (let module in LibraryModules) if (!LibraryModules[module]) BDFDB.LogUtils.warn(module + " not initialized in LibraryModules"); + for (let component in InternalComponents.NativeSubComponents) if (!InternalComponents.NativeSubComponents[component]) BDFDB.LogUtils.warn(component + " not initialized in NativeSubComponents"); + for (let component in InternalComponents.LibraryComponents) if (!InternalComponents.LibraryComponents[component]) BDFDB.LogUtils.warn(component + " not initialized in LibraryComponents"); + + BDFDB.DevUtils = {}; + BDFDB.DevUtils.generateClassId = function () { + let id = "", chars = "0123456789ABCDEFGHIJKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_".split(""); + while (id.length < 6) id += chars[Math.floor(Math.random() * chars.length)]; + return id; + }; + BDFDB.DevUtils.findByIndex = function (index) { + return BDFDB.DevUtils.req.c[index]; + }; + BDFDB.DevUtils.findPropAny = function (...strings) { + window.t = {"$filter":(prop => [...strings].flat(10).filter(n => typeof n == "string").every(string => prop.toLowerCase().indexOf(string.toLowerCase()) > -1))}; + for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) { + let m = BDFDB.DevUtils.req.c[i].exports; + if (m && typeof m == "object") for (let j in m) if (window.t.$filter(j)) window.t[j + "_" + i] = m; + if (m && typeof m == "object" && typeof m.default == "object") for (let j in m.default) if (window.t.$filter(j)) window.t[j + "_default_" + i] = m.default; + } + console.clear(); + console.log(window.t); + }; + BDFDB.DevUtils.findPropFunc = function (...strings) { + window.t = {"$filter":(prop => [...strings].flat(10).filter(n => typeof n == "string").every(string => prop.toLowerCase().indexOf(string.toLowerCase()) > -1))}; + for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) { + let m = BDFDB.DevUtils.req.c[i].exports; + if (m && typeof m == "object") for (let j in m) if (window.t.$filter(j) && typeof m[j] != "string") window.t[j + "_" + i] = m; + if (m && typeof m == "object" && typeof m.default == "object") for (let j in m.default) if (window.t.$filter(j) && typeof m.default[j] != "string") window.t[j + "_default_" + i] = m.default; + } + console.clear(); + console.log(window.t); + }; + BDFDB.DevUtils.findPropStringLib = function (...strings) { + window.t = {"$filter":(prop => [...strings].flat(10).filter(n => typeof n == "string").every(string => prop.toLowerCase().indexOf(string.toLowerCase()) > -1))}; + for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) { + let m = BDFDB.DevUtils.req.c[i].exports; + if (m && typeof m == "object") for (let j in m) if (window.t.$filter(j) && typeof m[j] == "string" && /^[A-z0-9]+\-[A-z0-9_-]{6}$/.test(m[j])) window.t[j + "_" + i] = m; + if (m && typeof m == "object" && typeof m.default == "object") for (let j in m.default) if (window.t.$filter(j) && typeof m.default[j] == "string" && /^[A-z0-9]+\-[A-z0-9_-]{6}$/.test(m.default[j])) window.t[j + "_default_" + i] = m.default; + } + console.clear(); + console.log(window.t); + }; + BDFDB.DevUtils.findNameAny = function (...strings) { + window.t = {"$filter":(modu => [...strings].flat(10).filter(n => typeof n == "string").some(string => typeof modu.displayName == "string" && modu.displayName.toLowerCase().indexOf(string.toLowerCase()) > -1 || modu.name == "string" && modu.name.toLowerCase().indexOf(string.toLowerCase()) > -1))}; + for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) { + let m = BDFDB.DevUtils.req.c[i].exports; + if (m && (typeof m == "object" || typeof m == "function") && window.t.$filter(m)) window.t[(m.displayName || m.name) + "_" + i] = m; + if (m && (typeof m == "object" || typeof m == "function") && m.default && (typeof m.default == "object" || typeof m.default == "function") && window.t.$filter(m.default)) window.t[(m.default.displayName || m.default.name) + "_" + i] = m.default; + } + console.clear(); + console.log(window.t); + }; + BDFDB.DevUtils.findCodeAny = function (...strings) { + window.t = {"$filter":(m => [...strings].flat(10).filter(n => typeof n == "string").map(string => string.toLowerCase()).every(string => typeof m == "function" && (m.toString().toLowerCase().indexOf(string) > -1 || typeof m.__originalMethod == "function" && m.__originalMethod.toString().toLowerCase().indexOf(string) > -1 || typeof m.__originalFunction == "function" && m.__originalFunction.toString().toLowerCase().indexOf(string) > -1) || BDFDB.ObjectUtils.is(m) && typeof m.type == "function" && m.type.toString().toLowerCase().indexOf(string) > -1))}; + for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) { + let m = BDFDB.DevUtils.req.c[i].exports; + if (m && typeof m == "function" && window.t.$filter(m)) window.t["module_" + i] = {string:m.toString(), func:m}; + if (m && m.__esModule) { + for (let j in m) if (m[j] && typeof m[j] == "function" && window.t.$filter(m[j])) window.t[j + "_module_" + i] = {string:m[j].toString(), func:m[j], module:m}; + if (m.default && (typeof m.default == "object" || typeof m.default == "function")) for (let j in m.default) if (m.default[j] && typeof m.default[j] == "function" && window.t.$filter(m.default[j])) window.t[j + "_module_" + i + "_default"] = {string:m.default[j].toString(), func:m.default[j], module:m}; + } + } + for (let i in BDFDB.DevUtils.req.m) if (typeof BDFDB.DevUtils.req.m[i] == "function" && window.t.$filter(BDFDB.DevUtils.req.m[i])) window.t["funtion_" + i] = {string:BDFDB.DevUtils.req.m[i].toString(), func:BDFDB.DevUtils.req.m[i]}; + console.clear(); + console.log(window.t); + }; + BDFDB.DevUtils.getAllModules = function () { + window.t = {}; + for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) { + let m = BDFDB.DevUtils.req.c[i].exports; + if (m && typeof m == "object") window.t[i] = m; + } + console.clear(); + console.log(window.t); + }; + BDFDB.DevUtils.getAllStringLibs = function () { + window.t = []; + for (let i in BDFDB.DevUtils.req.c) if (BDFDB.DevUtils.req.c.hasOwnProperty(i)) { + let m = BDFDB.DevUtils.req.c[i].exports; + if (m && typeof m == "object" && !BDFDB.ArrayUtils.is(m) && Object.keys(m).length) { + var string = true, stringlib = false; + for (let j in m) { + if (typeof m[j] != "string") string = false; + if (typeof m[j] == "string" && /^[A-z0-9]+\-[A-z0-9_-]{6}$/.test(m[j])) stringlib = true; + } + if (string && stringlib) window.t.push(m); + } + if (m && typeof m == "object" && m.default && typeof m.default == "object" && !BDFDB.ArrayUtils.is(m.default) && Object.keys(m.default).length) { + var string = true, stringlib = false; + for (let j in m.default) { + if (typeof m.default[j] != "string") string = false; + if (typeof m.default[j] == "string" && /^[A-z0-9]+\-[A-z0-9_-]{6}$/.test(m.default[j])) stringlib = true; + } + if (string && stringlib) window.t.push(m.default); + } + } + console.clear(); + console.log(window.t); + }; + BDFDB.DevUtils.listen = function (strings) { + strings = BDFDB.ArrayUtils.is(strings) ? strings : Array.from(arguments); + BDFDB.DevUtils.listenStop(); + BDFDB.DevUtils.listen.p = BDFDB.PatchUtils.patch("WebpackSearch", BDFDB.ModuleUtils.findByProperties(strings), strings[0], {after: e => { + console.log(e); + }}); + }; + BDFDB.DevUtils.listenStop = function () { + if (typeof BDFDB.DevUtils.listen.p == "function") BDFDB.DevUtils.listen.p(); + }; + BDFDB.DevUtils.req = InternalBDFDB.getWebModuleReq(); + + window.BDFDB = BDFDB; + } + else { + window.BDFDB = Object.assign({ + PluginUtils: { + buildPlugin: BDFDB.PluginUtils.buildPlugin, + cleanUp: BDFDB.PluginUtils.cleanUp + } + }, config); + } + for (let obj in DiscordObjects) if (!DiscordObjects[obj]) { + DiscordObjects[obj] = function () {}; + BDFDB.DiscordObjects[obj] = function () {}; + } + for (let component in InternalComponents.NativeSubComponents) if (!InternalComponents.NativeSubComponents[component]) InternalComponents.NativeSubComponents[component] = "div"; + for (let component in InternalComponents.LibraryComponents) if (!InternalComponents.LibraryComponents[component]) { + InternalComponents.LibraryComponents[component] = "div"; + BDFDB.LibraryComponents[component] = "div"; + } + + require("request").get("https://mwittrien.github.io/BetterDiscordAddons/Library/_res/BDFDB.raw.css", (error, response, body) => { + BDFDB.DOMUtils.appendLocalStyle("BDFDB", body.replace(/[\n\t\r]/g, "").replace(/\[REPLACE_CLASS_([A-z0-9_]+?)\]/g, function(a, b) {return BDFDB.dotCN[b];})); + }); + + window.BDFDB.loaded = true; + delete window.BDFDB.loading; + + BDFDB.LogUtils.log("Finished loading library."); + + while (delayedLoads.length) delayedLoads.shift().load(); + while (delayedStarts.length) delayedStarts.shift().start(); + while (pluginQueue.length) BDFDB.BDUtils.reloadPlugin(pluginQueue.shift()); + }); + + return class BDFDB_Frame { + getName () {return config.name;} + getAuthor () {return config.author;} + getVersion () {return config.version;} + getDescription () {return config.description;} + load () {} + start() {} + stop() {} - start () {} - - stop () {} - - // Begin of own functions + getSettingsPanel (collapseStates = {}) { + let settingsPanel, settingsItems = []; + let bdToastSetting = BDFDB.BDUtils.getSettings(BDFDB.BDUtils.settingsIds.showToasts); + for (let key in settings) settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, { + className: BDFDB.disCN.marginbottom8, + type: "Switch", + plugin: InternalBDFDB, + disabled: key == "showToasts" && bdToastSetting, + keys: ["settings", key], + label: InternalBDFDB.defaults.settings[key].description, + note: key == "showToasts" && bdToastSetting && "Disable BBDs general 'Show Toast' setting before disabling this", + dividerbottom: true, + value: settings[key] || key == "showToasts" && bdToastSetting + })); + + return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(BDFDB, settingsItems); + } } -})(); - -module.exports = BDFDB; \ No newline at end of file +})(); \ No newline at end of file