diff --git a/Library/0BDFDB.plugin.js b/Library/0BDFDB.plugin.js index 7d22bc65b3..13ec8ae615 100644 --- a/Library/0BDFDB.plugin.js +++ b/Library/0BDFDB.plugin.js @@ -2,7 +2,7 @@ * @name BDFDB * @author DevilBro * @authorId 278543574059057154 - * @version 2.1.7 + * @version 2.1.8 * @description Required Library for DevilBro's Plugins * @invite Jx3TjNS * @donate https://www.paypal.me/MircoWittrien @@ -19,22 +19,10 @@ module.exports = (_ => { "info": { "name": "BDFDB", "author": "DevilBro", - "version": "2.1.7", + "version": "2.1.8", "description": "Required Library for DevilBro's Plugins" }, - "rawUrl": `https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js`, - "changeLog": { - "progress": { - "Updates": "Yes there have been a lot of Updates in the Last Days, that's because I haven't had time to fix old stuff in the last weeks and Discord changed a lot in the last days. This is the last Update for now, since some of y'all are annoyed by update notifications" - }, - "fixed": { - "Context Menu Slider": "Fixed an issue where the volume slider in the User Menu couldn't be dragged properlly", - "Context Menus Entry Spam": "Fixed an issue where in some plugin combinations, context menu entries would get mulitplicated", - "Lazy Components": "Properly patches lazy components now, fixing issues with multiple plugins", - "Context Menus": "Fully work again, no further crashes", - "Better Friend List": "Fixed Crash" - } - } + "rawUrl": `https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js` }; const DiscordObjects = {}; @@ -585,7 +573,7 @@ module.exports = (_ => { BDFDB.PluginUtils.checkAllUpdates(); }, 1000*60*60*4); - BDFDB.TimeUtils.timeout(_ => {BDFDB.ArrayUtils.remove(PluginStores.updateData.timeouts, plugin.name, true);}, 30000); + BDFDB.TimeUtils.timeout(_ => BDFDB.ArrayUtils.remove(PluginStores.updateData.timeouts, plugin.name, true), 30000); } }; BDFDB.PluginUtils.init = function (plugin) { @@ -698,7 +686,7 @@ module.exports = (_ => { } }); }); - return new Promise(callback => {callback(null);}); + return new Promise(callback => callback(null)); }; BDFDB.PluginUtils.checkAllUpdates = function () { return new Promise(callback => { @@ -763,7 +751,7 @@ module.exports = (_ => { contents: BDFDB.LanguageUtils.LanguageStrings.FORM_LABEL_ALL, onClick: _ => {for (let notice of updateNotice.querySelectorAll(BDFDB.dotCN.noticeupdateentry)) notice.click();} }], - onClose: _ => {vanishObserver.disconnect();} + onClose: _ => vanishObserver.disconnect() }); updateNotice.style.setProperty("position", "relative", "important"); updateNotice.style.setProperty("visibility", "visible", "important"); @@ -1205,15 +1193,29 @@ module.exports = (_ => { }; InternalBDFDB.lazyLoadModuleImports = function (moduleString) { - if (typeof moduleString !== "string") moduleString = InternalBDFDB.getModuleString(moduleString); - if (!moduleString || typeof moduleString !== "string") return BDFDB.LogUtils.error("Trying to lazy load Imports but Module is not a String"); - const [, promiseMatch, menuRequest] = moduleString.match(/return (Promise\.all\(.+?\))\.then\((.+?)\)\);/) ?? []; - if (!promiseMatch) return BDFDB.LogUtils.error("Trying to lazy load Imports but Module does not contain lazy Imports"); - const imports = promiseMatch.match(/\d+/g)?.map(e => Number(e)); - const menuIndex = menuRequest.match(/\d+/)?.[0]; - if (!imports || !menuIndex) return BDFDB.LogUtils.error("Trying to lazy load Imports but could not find Indexes"); - const req = InternalBDFDB.getWebModuleReq(); - return Promise.all(imports.map(index => req.e(index))).then(() => req(menuIndex)); + return new Promise(callback => { + if (typeof moduleString !== "string") moduleString = InternalBDFDB.getModuleString(moduleString); + if (!moduleString || typeof moduleString !== "string") { + BDFDB.LogUtils.error("Trying to lazy load Imports but Module is not a String"); + return callback(null); + } + let run = true, imports = [], menuIndexes = []; + while (run) { + const [matchString, promiseMatch, menuRequest] = moduleString.match(/return (Promise\.all\(.+?\))\.then\((.+?)\)\)/) ?? []; + if (!promiseMatch) run = false; + else { + imports = imports.concat(promiseMatch.match(/\d+/g)?.map(e => Number(e))); + menuIndexes.push(menuRequest.match(/\d+/)?.[0]); + moduleString = moduleString.replace(matchString, ""); + } + } + if (!imports.length || !menuIndexes.length) { + BDFDB.LogUtils.error("Trying to lazy load Imports but could not find Indexes"); + return callback(null); + } + const req = InternalBDFDB.getWebModuleReq(); + Promise.all(BDFDB.ArrayUtils.removeCopies(imports).map(i => req.e(i))).then(_ => Promise.all(BDFDB.ArrayUtils.removeCopies(menuIndexes).map(i => req(i)))).then(callback); + }); }; BDFDB.ModuleUtils = {}; @@ -2242,14 +2244,21 @@ module.exports = (_ => { let exports = module && !config.exported && module.exports || module; exports = config.path && BDFDB.ObjectUtils.get(exports, config.path) || exports; exports && InternalBDFDB.patchComponent(pluginData, InternalBDFDB.isMemoOrForwardRef(exports) ? exports.default : exports, config); + return exports ? true : false; }; + let found = true; if (config.lazyLoaded) InternalBDFDB.addChunkObserver(pluginData, config); else if (config.classNames.length) InternalBDFDB.searchComponent(pluginData, config); - else if (config.subComponent && config.subComponent.strings || config.stringFind) patchSpecial("findByString", config.subComponent && config.subComponent.strings || config.stringFind); - else if (config.subComponent && config.subComponent.props || config.propertyFind) patchSpecial("findByProperties", config.subComponent && config.subComponent.props || config.propertyFind); - else if (config.subComponent && config.subComponent.protos || config.prototypeFind) patchSpecial("findByPrototypes", config.subComponent && config.subComponent.protos || config.prototypeFind); - else if (config.nonRender) patchSpecial("findByName", config.name); - else InternalBDFDB.patchComponent(pluginData, BDFDB.ModuleUtils.findByName(config.name), config); + else if (config.subComponent && config.subComponent.strings || config.stringFind) found = patchSpecial("findByString", config.subComponent && config.subComponent.strings || config.stringFind); + else if (config.subComponent && config.subComponent.props || config.propertyFind) found = patchSpecial("findByProperties", config.subComponent && config.subComponent.props || config.propertyFind); + else if (config.subComponent && config.subComponent.protos || config.prototypeFind) found = patchSpecial("findByPrototypes", config.subComponent && config.subComponent.protos || config.prototypeFind); + else if (config.nonRender) found = patchSpecial("findByName", config.name); + else { + let module = BDFDB.ModuleUtils.findByName(config.name); + if (module) InternalBDFDB.patchComponent(pluginData, module, config); + else found = false; + } + if (!found) InternalBDFDB.addChunkObserver(pluginData, config); } } }; @@ -4098,7 +4107,7 @@ module.exports = (_ => { 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"}); + let contextMenu = BDFDB.ReactUtils.findChild(returnvalue, {props: "navId"}) || (BDFDB.ArrayUtils.is(returnvalue) ? {props: {children: returnvalue}} : null); if (contextMenu) { for (let i in contextMenu.props.children) { if (contextMenu.props.children[i] && contextMenu.props.children[i].type == RealMenuItems.MenuGroup) { @@ -4859,3943 +4868,3986 @@ module.exports = (_ => { } }; - 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]) && m); - 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.AutoFocusCatcher = reactInitialized && class BDFDB_AutoFocusCatcher extends LibraryModules.React.Component { - render() { - const style = {padding: 0, margin: 0, border: "none", width: 0, maxWidth: 0, height: 0, maxHeight: 0, visibility: "hidden"}; - return BDFDB.ReactUtils.forceStyle(BDFDB.ReactUtils.createElement("input", {style}), Object.keys(style)); - } - }; - - 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() {BDFDB.TimeUtils.clear(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.getBadgePaddingForValue = function (count) { - switch (count) { - case 1: - case 4: - case 6: - return 1; - default: - return 0; - } - }; - InternalComponents.LibraryComponents.Badges.IconBadge = reactInitialized && class BDFDB_IconBadge extends LibraryModules.React.Component { - render() { - return BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.badgeiconbadge, this.props.shape && InternalComponents.LibraryComponents.Badges.BadgeShapes[this.props.shape] || InternalComponents.LibraryComponents.Badges.BadgeShapes.ROUND), - 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.Badges.NumberBadge = reactInitialized && class BDFDB_IconBadge 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("div", { - className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.badgenumberbadge, this.props.shape && InternalComponents.LibraryComponents.Badges.BadgeShapes[this.props.shape] || InternalComponents.LibraryComponents.Badges.BadgeShapes.ROUND), - style: Object.assign({ - backgroundColor: !this.props.disableColor && (this.props.color || BDFDB.DiscordConstants.Colors.STATUS_RED), - width: InternalComponents.LibraryComponents.Badges.getBadgeWidthForValue(this.props.count), - paddingRight: InternalComponents.LibraryComponents.Badges.getBadgePaddingForValue(this.props.count) - }, this.props.style), - onClick: this.handleClick.bind(this), - onContextMenu: this.handleContextMenu.bind(this), - onMouseEnter: this.handleMouseEnter.bind(this), - onMouseLeave: this.handleMouseLeave.bind(this), - children: InternalComponents.LibraryComponents.Badges.getBadgeCountString(this.props.count) - }); - } - }; - - 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("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.hovercardwrapper, this.props.horizontal && BDFDB.disCN.hovercardhorizontal, 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.Clickable, { - "aria-label": BDFDB.LanguageUtils.LanguageStrings.REMOVE, - className: BDFDB.disCNS.hovercardremovebutton + BDFDB.disCNS.hovercardremovebuttondefault, - 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", "horizontal", "noRemove")); - } - }; - InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Card, {backdrop: true, noRemove: false}); - - InternalComponents.LibraryComponents.ChannelTextAreaButton = reactInitialized && class BDFDB_ChannelTextAreaButton extends LibraryModules.React.Component { - render() { - const inner = BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.textareabuttonwrapper, - 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 - }) - }); - const button = 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(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: this.props.tooltip && this.props.tooltip.text ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, Object.assign({}, this.props.tooltip, {children: inner})) : inner - }); - return (this.props.className || "").indexOf(BDFDB.disCN.textareapickerbutton) > -1 ? BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.textareapickerbuttoncontainer, - children: button - }) : button; - } - }; - 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 || ""; + const loadComponents = _ => { + 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]) && m); + else InternalComponents.NativeSubComponents[name] = BDFDB.ModuleUtils.findByName(InternalData.NativeSubComponents[name].name); } - else string = input.value || input.textContent || ""; - if (this.props.max && this.props.showPercentage && (string.length/this.props.max) * 100 < this.props.showPercentage) return ""; - 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 - }); + else if (InternalData.NativeSubComponents[name].props) InternalComponents.NativeSubComponents[name] = BDFDB.ModuleUtils.findByProperties(InternalData.NativeSubComponents[name].props); } - updateCounter() { - if (!this.refElement) return; - BDFDB.TimeUtils.clear(this.updateTimeout); - this.updateTimeout = BDFDB.TimeUtils.timeout(this.forceUpdateCounter.bind(this), 100); + + 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; } - 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); + + InternalComponents.LibraryComponents.AutoFocusCatcher = reactInitialized && class BDFDB_AutoFocusCatcher extends LibraryModules.React.Component { + render() { + const style = {padding: 0, margin: 0, border: "none", width: 0, maxWidth: 0, height: 0, maxHeight: 0, visibility: "hidden"}; + return BDFDB.ReactUtils.forceStyle(BDFDB.ReactUtils.createElement("input", {style}), Object.keys(style)); + } + }; + + 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() {BDFDB.TimeUtils.clear(this.timeoutId)} + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.div, { + className: this.props.className, + style: this.props.animatedStyle, + children: this.props.children }); - }; - 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(_ => 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", "showPercentage")); - } - }; - - InternalComponents.LibraryComponents.Checkbox = reactInitialized && class BDFDB_Checkbox 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);} - getInputMode() { - return this.props.disabled ? "disabled" : this.props.readOnly ? "readonly" : "default"; - } - getStyle() { - let style = this.props.style || {}; - if (!this.props.value) return style; - style = Object.assign({}, style); - this.props.color = typeof this.props.getColor == "function" ? this.props.getColor(this.props.value) : this.props.color; - if (InternalComponents.LibraryComponents.Checkbox.Types) switch (this.props.type) { - case InternalComponents.LibraryComponents.Checkbox.Types.DEFAULT: - style.borderColor = this.props.color; - break; - case InternalComponents.LibraryComponents.Checkbox.Types.GHOST: - let color = BDFDB.ColorUtils.setAlpha(this.props.color, 0.15, "RGB"); - style.backgroundColor = color; - style.borderColor = color; - break; - case InternalComponents.LibraryComponents.Checkbox.Types.INVERTED: - style.backgroundColor = this.props.color; - style.borderColor = this.props.color; + }; + + InternalComponents.LibraryComponents.Badges = Object.assign({}, BDFDB.ModuleUtils.findByProperties("IconBadge", "NumberBadge")); + InternalComponents.LibraryComponents.Badges.getBadgePaddingForValue = function (count) { + switch (count) { + case 1: + case 4: + case 6: + return 1; + default: + return 0; } - return style; - } - getColor() { - return this.props.value ? (InternalComponents.LibraryComponents.Checkbox.Types && this.props.type === InternalComponents.LibraryComponents.Checkbox.Types.INVERTED ? BDFDB.DiscordConstants.Colors.WHITE : this.props.color) : "transparent"; - } - handleChange(e) { - this.props.value = typeof this.props.getValue == "function" ? this.props.getValue(this.props.value, e, this) : !this.props.value; - if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this); - BDFDB.ReactUtils.forceUpdate(this); - } - render() { - let label = this.props.children ? BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.checkboxlabel, this.props.disabled ? BDFDB.disCN.checkboxlabeldisabled : BDFDB.disCN.checkboxlabelclickable, this.props.reverse ? BDFDB.disCN.checkboxlabelreversed : BDFDB.disCN.checkboxlabelforward), - style: { - lineHeight: this.props.size + "px" - }, - children: this.props.children - }) : null; - return BDFDB.ReactUtils.createElement("label", { - className: BDFDB.DOMUtils.formatClassName(this.props.disabled ? BDFDB.disCN.checkboxwrapperdisabled : BDFDB.disCN.checkboxwrapper, this.props.align, this.props.className), - children: [ - this.props.reverse && label, - !this.props.displayOnly && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FocusRingScope, { - children: BDFDB.ReactUtils.createElement("input", { - className: BDFDB.disCN["checkboxinput" + this.getInputMode()], - type: "checkbox", - onClick: this.props.disabled || this.props.readOnly ? (_ => {}) : this.handleChange.bind(this), - onContextMenu: this.props.disabled || this.props.readOnly ? (_ => {}) : this.handleChange.bind(this), - checked: this.props.value, - style: { - width: this.props.size, - height: this.props.size + }; + InternalComponents.LibraryComponents.Badges.IconBadge = reactInitialized && class BDFDB_IconBadge extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.badgeiconbadge, this.props.shape && InternalComponents.LibraryComponents.Badges.BadgeShapes[this.props.shape] || InternalComponents.LibraryComponents.Badges.BadgeShapes.ROUND), + 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.Badges.NumberBadge = reactInitialized && class BDFDB_IconBadge 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("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.badgenumberbadge, this.props.shape && InternalComponents.LibraryComponents.Badges.BadgeShapes[this.props.shape] || InternalComponents.LibraryComponents.Badges.BadgeShapes.ROUND), + style: Object.assign({ + backgroundColor: !this.props.disableColor && (this.props.color || BDFDB.DiscordConstants.Colors.STATUS_RED), + width: InternalComponents.LibraryComponents.Badges.getBadgeWidthForValue(this.props.count), + paddingRight: InternalComponents.LibraryComponents.Badges.getBadgePaddingForValue(this.props.count) + }, this.props.style), + onClick: this.handleClick.bind(this), + onContextMenu: this.handleContextMenu.bind(this), + onMouseEnter: this.handleMouseEnter.bind(this), + onMouseLeave: this.handleMouseLeave.bind(this), + children: InternalComponents.LibraryComponents.Badges.getBadgeCountString(this.props.count) + }); + } + }; + + 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("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.hovercardwrapper, this.props.horizontal && BDFDB.disCN.hovercardhorizontal, 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.Clickable, { + "aria-label": BDFDB.LanguageUtils.LanguageStrings.REMOVE, + className: BDFDB.disCNS.hovercardremovebutton + BDFDB.disCNS.hovercardremovebuttondefault, + onClick: e => { + if (typeof this.props.onRemove == "function") this.props.onRemove(e, this); + BDFDB.ListenerUtils.stopEvent(e); } - }) - }), - BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.checkbox, BDFDB.disCN["checkbox" + this.props.shape], this.props.value && BDFDB.disCN.checkboxchecked), - style: Object.assign({ - width: this.props.size, - height: this.props.size, - borderColor: this.props.checkboxColor - }, this.getStyle()), - children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Checkmark, { - width: 18, - height: 18, - color: this.getColor(), - "aria-hidden": true - }) - }), - !this.props.reverse && label - ].filter(n => n) - }); - } - }; - InternalComponents.LibraryComponents.Checkbox.Types = { - DEFAULT: "DEFAULT", - GHOST: "GHOST", - INVERTED: "INVERTED" - }; - InternalComponents.LibraryComponents.Checkbox.Shapes = { - BOX: "box", - ROUND: "round" - }; - InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Checkbox, {type: InternalComponents.LibraryComponents.Checkbox.Types.INVERTED, shape: InternalComponents.LibraryComponents.Checkbox.Shapes.ROUND}); - - 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; + }) : 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", "horizontal", "noRemove")); } - else changed = true; - if (changed) { - if (typeof this.props.onColorChange == "function") this.props.onColorChange(BDFDB.ColorUtils.convert(this.props.color, "RGBCOMP")); + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Card, {backdrop: true, noRemove: false}); + + InternalComponents.LibraryComponents.ChannelTextAreaButton = reactInitialized && class BDFDB_ChannelTextAreaButton extends LibraryModules.React.Component { + render() { + const inner = BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.textareabuttonwrapper, + 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 + }) + }); + const button = 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(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: this.props.tooltip && this.props.tooltip.text ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, Object.assign({}, this.props.tooltip, {children: inner})) : inner + }); + return (this.props.className || "").indexOf(BDFDB.disCN.textareapickerbutton) > -1 ? BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.textareapickerbuttoncontainer, + children: button + }) : button; + } + }; + 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 || ""; + if (this.props.max && this.props.showPercentage && (string.length/this.props.max) * 100 < this.props.showPercentage) return ""; + 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); } - } - 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; - - let hexColor = BDFDB.ColorUtils.convert(selectedColor, this.props.alpha ? "HEXA" : "HEX"); - let hexLength = hexColor.length; - - 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)); - this.handleColorChange(BDFDB.ColorUtils.convert([h, BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 100], event.clientX) + "%", BDFDB.NumberUtils.mapRange([rects.top, rects.top + rects.height], [100, 0], event.clientY) + "%", 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 => { - this.handleColorChange(BDFDB.ColorUtils.convert([h, BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 100], event2.clientX) + "%", BDFDB.NumberUtils.mapRange([rects.top, rects.top + rects.height], [100, 0], event2.clientY) + "%", 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}, + 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(_ => 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", "showPercentage")); + } + }; + + InternalComponents.LibraryComponents.Checkbox = reactInitialized && class BDFDB_Checkbox 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);} + getInputMode() { + return this.props.disabled ? "disabled" : this.props.readOnly ? "readonly" : "default"; + } + getStyle() { + let style = this.props.style || {}; + if (!this.props.value) return style; + style = Object.assign({}, style); + this.props.color = typeof this.props.getColor == "function" ? this.props.getColor(this.props.value) : this.props.color; + if (InternalComponents.LibraryComponents.Checkbox.Types) switch (this.props.type) { + case InternalComponents.LibraryComponents.Checkbox.Types.DEFAULT: + style.borderColor = this.props.color; + break; + case InternalComponents.LibraryComponents.Checkbox.Types.GHOST: + let color = BDFDB.ColorUtils.setAlpha(this.props.color, 0.15, "RGB"); + style.backgroundColor = color; + style.borderColor = color; + break; + case InternalComponents.LibraryComponents.Checkbox.Types.INVERTED: + style.backgroundColor = this.props.color; + style.borderColor = this.props.color; + } + return style; + } + getColor() { + return this.props.value ? (InternalComponents.LibraryComponents.Checkbox.Types && this.props.type === InternalComponents.LibraryComponents.Checkbox.Types.INVERTED ? BDFDB.DiscordConstants.Colors.WHITE : this.props.color) : "transparent"; + } + handleChange(e) { + this.props.value = typeof this.props.getValue == "function" ? this.props.getValue(this.props.value, e, this) : !this.props.value; + if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this); + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + let label = this.props.children ? BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.checkboxlabel, this.props.disabled ? BDFDB.disCN.checkboxlabeldisabled : BDFDB.disCN.checkboxlabelclickable, this.props.reverse ? BDFDB.disCN.checkboxlabelreversed : BDFDB.disCN.checkboxlabelforward), + style: { + lineHeight: this.props.size + "px" + }, + children: this.props.children + }) : null; + return BDFDB.ReactUtils.createElement("label", { + className: BDFDB.DOMUtils.formatClassName(this.props.disabled ? BDFDB.disCN.checkboxwrapperdisabled : BDFDB.disCN.checkboxwrapper, this.props.align, this.props.className), + children: [ + this.props.reverse && label, + !this.props.displayOnly && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FocusRingScope, { + children: BDFDB.ReactUtils.createElement("input", { + className: BDFDB.disCN["checkboxinput" + this.getInputMode()], + type: "checkbox", + onClick: this.props.disabled || this.props.readOnly ? (_ => {}) : this.handleChange.bind(this), + onContextMenu: this.props.disabled || this.props.readOnly ? (_ => {}) : this.handleChange.bind(this), + checked: this.props.value, + style: { + width: this.props.size, + height: this.props.size + } + }) + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.checkbox, BDFDB.disCN["checkbox" + this.props.shape], this.props.value && BDFDB.disCN.checkboxchecked), + style: Object.assign({ + width: this.props.size, + height: this.props.size, + borderColor: this.props.checkboxColor + }, this.getStyle()), + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Checkmark, { + width: 18, + height: 18, + color: this.getColor(), + "aria-hidden": true + }) + }), + !this.props.reverse && label + ].filter(n => n) + }); + } + }; + InternalComponents.LibraryComponents.Checkbox.Types = { + DEFAULT: "DEFAULT", + GHOST: "GHOST", + INVERTED: "INVERTED" + }; + InternalComponents.LibraryComponents.Checkbox.Shapes = { + BOX: "box", + ROUND: "round" + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Checkbox, {type: InternalComponents.LibraryComponents.Checkbox.Types.INVERTED, shape: InternalComponents.LibraryComponents.Checkbox.Shapes.ROUND}); + + 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(BDFDB.ColorUtils.convert(this.props.color, "RGBCOMP")); + BDFDB.ReactUtils.forceUpdate(this); + } + } + 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; + + let hexColor = BDFDB.ColorUtils.convert(selectedColor, this.props.alpha ? "HEXA" : "HEX"); + let hexLength = hexColor.length; + + 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.colorpickerhuehorizontal, - style: {padding: "0px 2px", position: "relative", height: "100%"}, + 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.colorpickerhuehorizontal, event.target)); - this.handleColorChange(BDFDB.ColorUtils.convert([BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 360], event.clientX), s, l, a], hslFormat)); + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickersaturationcolor, event.target)); + this.handleColorChange(BDFDB.ColorUtils.convert([h, BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 100], event.clientX) + "%", BDFDB.NumberUtils.mapRange([rects.top, rects.top + rects.height], [100, 0], event.clientY) + "%", a], hslFormat)); }, onMouseDown: event => { - let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickerhuehorizontal, event.target)); + 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 => { - this.handleColorChange(BDFDB.ColorUtils.convert([BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 360], event2.clientX), s, l, a], hslFormat)); + this.handleColorChange(BDFDB.ColorUtils.convert([h, BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 100], event2.clientX) + "%", BDFDB.NumberUtils.mapRange([rects.top, rects.top + rects.height], [100, 0], event2.clientY) + "%", 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%);}` + 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.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)"} - }) + 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)"} + }) + }) + ] }) ] }) - }) - }), - this.props.alpha && BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.colorpickeralpha, - children: [ - BDFDB.ReactUtils.createElement("div", { + }), + 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.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")}`}, + className: BDFDB.disCN.colorpickerhuehorizontal, + style: {padding: "0px 2px", position: "relative", height: "100%"}, onClick: event => { - let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickeralphahorizontal, event.target)); - this.handleColorChange(BDFDB.ColorUtils.setAlpha([h, s, l], BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 1], event.clientX), hslFormat)); + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickerhuehorizontal, event.target)); + this.handleColorChange(BDFDB.ColorUtils.convert([BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 360], event.clientX), s, l, a], hslFormat)); }, onMouseDown: event => { - let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickeralphahorizontal, event.target)); + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickerhuehorizontal, 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; - this.handleColorChange(BDFDB.ColorUtils.setAlpha([h, s, l], BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 1], event2.clientX), hslFormat)); + this.handleColorChange(BDFDB.ColorUtils.convert([BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 360], event2.clientX), s, l, a], 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", { + 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.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.disCN.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); - }, + }), + 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 => { - BDFDB.ListenerUtils.stopEvent(event); - if (!this.state.draggingGradientCursor) { - this.state.selectedGradientCursor = posAndColor[0]; - BDFDB.ReactUtils.forceUpdate(this); - } + let rects = BDFDB.DOMUtils.getRects(BDFDB.DOMUtils.getParent(BDFDB.dotCN.colorpickeralphahorizontal, event.target)); + this.handleColorChange(BDFDB.ColorUtils.setAlpha([h, s, l], BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 1], event.clientX), hslFormat)); }, - onContextMenu: posAndColor[0] == 0 || posAndColor[0] == 1 ? _ => {} : event => { - BDFDB.ListenerUtils.stopEvent(event); - delete this.props.color[posAndColor[0]]; - this.state.selectedGradientCursor = 0; - this.handleColorChange(); + 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; + this.handleColorChange(BDFDB.ColorUtils.setAlpha([h, s, l], BDFDB.NumberUtils.mapRange([rects.left, rects.left + rects.width], [0, 1], event2.clientX), hslFormat)); + }; + document.addEventListener("mouseup", mouseUp); + document.addEventListener("mousemove", mouseMove); }, children: BDFDB.ReactUtils.createElement("div", { - style: {background: BDFDB.ColorUtils.convert(posAndColor[1], "RGBA")} + 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) }) - })) + }) }) - }) - ] - }) - ].filter(n => n) - }), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, { - className: BDFDB.disCNS.colorpickerhexinput + BDFDB.disCN.margintop8, - maxLength: this.props.alpha ? 9 : 7, - valuePrefix: "#", - value: hexColor, - autoFocus: true, - onChange: value => { - const oldLength = hexLength; - hexLength = (value || "").length; - if (this.props.alpha && (oldLength > 8 || oldLength < 6) && hexLength == 7) value += "FF"; - if (hexRegex.test(value)) this.handleColorChange(value); - }, - inputChildren: this.props.gradient && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { - text: BDFDB.LanguageUtils.LibraryStrings.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); + 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.disCN.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: hexColor, + autoFocus: true, + onChange: value => { + const oldLength = hexLength; + hexLength = (value || "").length; + if (this.props.alpha && (oldLength > 8 || oldLength < 6) && hexLength == 7) value += "FF"; + if (hexRegex.test(value)) this.handleColorChange(value); }, - style: Object.assign({}, pos, {width: 10, height: 10, cursor: "move", position: "absolute"}) - })) - }) - ] - }); - } - }; - - InternalComponents.LibraryComponents.ColorSwatches = reactInitialized && class BDFDB_ColorSwatches extends LibraryModules.React.Component { - ColorSwatch(props) { - const swatches = props.swatches; - let useWhite = !BDFDB.ColorUtils.isBright(props.color); - let swatch = BDFDB.ReactUtils.createElement("button", { - type: "button", - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickerswatch, props.isSingle && BDFDB.disCN.colorpickerswatchsingle, props.isDisabled && BDFDB.disCN.colorpickerswatchdisabled, props.isSelected && BDFDB.disCN.colorpickerswatchselected, props.isCustom && BDFDB.disCN.colorpickerswatchcustom, props.color == null && BDFDB.disCN.colorpickerswatchnocolor), - number: props.number, - disabled: props.isDisabled, - onClick: _ => { - if (!props.isSelected) { - let color = props.isCustom && props.color == null ? (swatches.props.color || swatches.props.defaultCustomColor || "rgba(0, 0, 0, 1)") : props.color; - if (typeof swatches.props.onColorChange == "function") swatches.props.onColorChange(BDFDB.ColorUtils.convert(color, "RGBCOMP")); - swatches.props.color = color; - swatches.props.customColor = props.isCustom ? color : swatches.props.customColor; - swatches.props.customSelected = props.isCustom; - BDFDB.ReactUtils.forceUpdate(swatches); - } - }, - style: Object.assign({}, props.style, { - background: BDFDB.ObjectUtils.is(props.color) ? BDFDB.ColorUtils.createGradient(props.color) : BDFDB.ColorUtils.convert(props.color, "RGBA") - }), - children: [ - props.isCustom || props.isSingle ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { - className: BDFDB.disCN.colorpickerswatchdropper, - foreground: BDFDB.disCN.colorpickerswatchdropperfg, - name: InternalComponents.LibraryComponents.SvgIcon.Names.DROPPER, - width: props.isCustom ? 14 : 10, - height: props.isCustom ? 14 : 10, - color: useWhite ? BDFDB.DiscordConstants.Colors.WHITE : BDFDB.DiscordConstants.Colors.BLACK - }) : null, - props.isSelected && !props.isSingle ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { - name: InternalComponents.LibraryComponents.SvgIcon.Names.CHECKMARK, - width: props.isCustom ? 32 : 16, - height: props.isCustom ? 24 : 16, - color: useWhite ? BDFDB.DiscordConstants.Colors.WHITE : BDFDB.DiscordConstants.Colors.BLACK - }) : null - ] - }); - if (props.isCustom || props.isSingle || props.color == null) swatch = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { - text: props.isCustom || props.isSingle ? BDFDB.LanguageUtils.LanguageStrings.CUSTOM_COLOR : BDFDB.LanguageUtils.LanguageStrings.DEFAULT, - tooltipConfig: {type: props.isSingle ? "top" : "bottom"}, - children: swatch - }); - if (props.isCustom || 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, - open: swatches.props.pickerOpen, - onClick: _ => swatches.props.pickerOpen = true, - onOpen: _ => { - swatches.props.pickerOpen = true; - if (typeof swatches.props.onPickerOpen == "function") swatches.props.onPickerOpen(this); - }, - onClose: _ => { - delete swatches.props.pickerOpen; - if (typeof swatches.props.onPickerClose == "function") swatches.props.onPickerClose(this); - }, - renderPopout: _ => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ColorPicker, Object.assign({}, swatches.props.pickerConfig, { - color: swatches.props.color, - onColorChange: color => { - if (typeof swatches.props.onColorChange == "function") swatches.props.onColorChange(color); - props.color = color; - swatches.props.color = color; - swatches.props.customColor = color; - swatches.props.customSelected = true; - BDFDB.ReactUtils.forceUpdate(swatches); - } - }), true) - }); - if (props.isCustom) swatch = BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.colorpickerswatchcustomcontainer, - children: swatch - }); - return swatch; - } - render() { - this.props.color = BDFDB.ObjectUtils.is(this.props.color) ? this.props.color : BDFDB.ColorUtils.convert(this.props.color, "RGBA"); - this.props.colors = (BDFDB.ArrayUtils.is(this.props.colors) ? this.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")); - this.props.colorRows = this.props.colors.length ? [this.props.colors.slice(0, parseInt(this.props.colors.length/2)), this.props.colors.slice(parseInt(this.props.colors.length/2))] : []; - this.props.customColor = !this.props.color || !this.props.customSelected && this.props.colors.indexOf(this.props.color) > -1 ? null : this.props.color; - this.props.defaultCustomColor = BDFDB.ObjectUtils.is(this.props.defaultCustomColor) ? this.props.defaultCustomColor : BDFDB.ColorUtils.convert(this.props.defaultCustomColor, "RGBA"); - this.props.customSelected = !!this.props.customColor; - this.props.pickerConfig = BDFDB.ObjectUtils.is(this.props.pickerConfig) ? this.props.pickerConfig : {gradient: true, alpha: true}; - - const isSingle = !this.props.colors.length; - return BDFDB.ReactUtils.createElement("div", { - className: isSingle ? BDFDB.disCN.colorpickerswatchsinglewrapper : BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickerswatches, BDFDB.disCN.colorpickerswatchescontainer, this.props.disabled && BDFDB.disCN.colorpickerswatchesdisabled), - children: [ - BDFDB.ReactUtils.createElement(this.ColorSwatch, { - swatches: this, - color: this.props.customColor, - isSingle: isSingle, - isCustom: !isSingle, - isSelected: this.props.customSelected, - isDisabled: this.props.disabled, - pickerOpen: this.props.pickerOpen, - style: {margin: 0} - }), - !isSingle && BDFDB.ReactUtils.createElement("div", { - children: this.props.colorRows.map(row => BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.colorpickerrow, - children: row.map(color => BDFDB.ReactUtils.createElement(this.ColorSwatch, { - swatches: this, - color: color, - isCustom: false, - isSelected: !this.props.customSelected && color == this.props.color, - isDisabled: this.props.disabled - })) - })) - }) - ] - }); - } - }; - - InternalComponents.LibraryComponents.DateInput = class BDFDB_DateInput extends LibraryModules.React.Component { - renderFormatButton(props) { - const button = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Clickable, { - className: BDFDB.disCN.dateinputbutton, - children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { - name: props.svgName, - width: 20, - height: 20 - }) - }); - return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutContainer, { - width: props.popoutWidth || 350, - padding: 10, - animation: InternalComponents.LibraryComponents.PopoutContainer.Animation.SCALE, - position: InternalComponents.LibraryComponents.PopoutContainer.Positions.TOP, - align: InternalComponents.LibraryComponents.PopoutContainer.Align.RIGHT, - onClose: instance => BDFDB.DOMUtils.removeClass(instance.domElementRef.current, BDFDB.disCN.dateinputbuttonselected), - renderPopout: instance => { - BDFDB.DOMUtils.addClass(instance.domElementRef.current, BDFDB.disCN.dateinputbuttonselected); - return props.children || BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { - align: InternalComponents.LibraryComponents.Flex.Align.CENTER, - children: [ - props.name && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { - label: props.name - }), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, { - className: BDFDB.disCN.dateinputfield, - placeholder: props.placeholder, - value: props.getValue(), - onChange: typeof props.onChange == "function" ? props.onChange : null - }), - props.tooltipText && this.renderInfoButton(props.tooltipText) - ].filter(n => n) - }) - }, - children: props.name ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { - text: props.name, - children: button - }) : button - }); - } - renderInfoButton(text, style) { - return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { - text: [text].flat(10).filter(n => n).map(n => BDFDB.ReactUtils.createElement("div", {children: n})), - tooltipConfig: { - type: "bottom", - zIndex: 1009, - maxWidth: 560 - }, - children: BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.dateinputbutton, - style: Object.assign({}, style), - children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { - name: InternalComponents.LibraryComponents.SvgIcon.Names.QUESTIONMARK, - width: 24, - height: 24 - }) - }) - }); - } - handleChange() { - if (typeof this.props.onChange == "function") this.props.onChange(BDFDB.ObjectUtils.extract(this.props, "formatString", "dateString", "timeString", "timeOffset", "language")); - } - render() { - let input = this, formatter, preview; - const defaultOffset = ((new Date()).getTimezoneOffset() * (-1/60)); - return BDFDB.ReactUtils.createElement("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.dateinputwrapper, this.props.className), - children: [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { - label: this.props.label - }), - BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.dateinputinner, - children: [ - BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.dateinputcontrols, - children: [ - BDFDB.ReactUtils.createElement(class DateInputPreview extends LibraryModules.React.Component { - componentDidMount() {formatter = this;} - render() { - return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, { - className: BDFDB.disCN.dateinputfield, - placeholder: InternalComponents.LibraryComponents.DateInput.getDefaultString(input.props.language), - value: input.props.formatString, - onChange: value => { - input.props.formatString = value; - input.handleChange.apply(input, []); - BDFDB.ReactUtils.forceUpdate(formatter, preview); - } - }); - } + inputChildren: this.props.gradient && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: BDFDB.LanguageUtils.LibraryStrings.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 }), - this.renderInfoButton([ - "$date will be replaced with the Date", - "$time will be replaced with the Time", - "$time12 will be replaced with the Time (12h Form)", - "$month will be replaced with the Month Name", - "$monthS will be replaced with the Month Name (Short Form)", - "$day will be replaced with the Weekday Name", - "$dayS will be replaced with the Weekday Name (Short Form)", - "$agoAmount will be replaced with ('Today', 'Yesterday', 'x days/weeks/months ago')", - "$agoDays will be replaced with ('Today', 'Yesterday', 'x days ago')", - "$agoDate will be replaced with ('Today', 'Yesterday', $date)" - ], {marginRight: 6}), - this.renderFormatButton({ - name: BDFDB.LanguageUtils.LanguageStrings.DATE, - svgName: InternalComponents.LibraryComponents.SvgIcon.Names.CALENDAR, - placeholder: this.props.dateString, - getValue: _ => this.props.dateString, - tooltipText: [ - "$d will be replaced with the Day", - "$dd will be replaced with the Day (Forced Zeros)", - "$m will be replaced with the Month", - "$mm will be replaced with the Month (Forced Zeros)", - "$yy will be replaced with the Year (2-Digit)", - "$yyyy will be replaced with the Year (4-Digit)", + 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 { + ColorSwatch(props) { + const swatches = props.swatches; + let useWhite = !BDFDB.ColorUtils.isBright(props.color); + let swatch = BDFDB.ReactUtils.createElement("button", { + type: "button", + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickerswatch, props.isSingle && BDFDB.disCN.colorpickerswatchsingle, props.isDisabled && BDFDB.disCN.colorpickerswatchdisabled, props.isSelected && BDFDB.disCN.colorpickerswatchselected, props.isCustom && BDFDB.disCN.colorpickerswatchcustom, props.color == null && BDFDB.disCN.colorpickerswatchnocolor), + number: props.number, + disabled: props.isDisabled, + onClick: _ => { + if (!props.isSelected) { + let color = props.isCustom && props.color == null ? (swatches.props.color || swatches.props.defaultCustomColor || "rgba(0, 0, 0, 1)") : props.color; + if (typeof swatches.props.onColorChange == "function") swatches.props.onColorChange(BDFDB.ColorUtils.convert(color, "RGBCOMP")); + swatches.props.color = color; + swatches.props.customColor = props.isCustom ? color : swatches.props.customColor; + swatches.props.customSelected = props.isCustom; + BDFDB.ReactUtils.forceUpdate(swatches); + } + }, + style: Object.assign({}, props.style, { + background: BDFDB.ObjectUtils.is(props.color) ? BDFDB.ColorUtils.createGradient(props.color) : BDFDB.ColorUtils.convert(props.color, "RGBA") + }), + children: [ + props.isCustom || props.isSingle ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.colorpickerswatchdropper, + foreground: BDFDB.disCN.colorpickerswatchdropperfg, + name: InternalComponents.LibraryComponents.SvgIcon.Names.DROPPER, + width: props.isCustom ? 14 : 10, + height: props.isCustom ? 14 : 10, + color: useWhite ? BDFDB.DiscordConstants.Colors.WHITE : BDFDB.DiscordConstants.Colors.BLACK + }) : null, + props.isSelected && !props.isSingle ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: InternalComponents.LibraryComponents.SvgIcon.Names.CHECKMARK, + width: props.isCustom ? 32 : 16, + height: props.isCustom ? 24 : 16, + color: useWhite ? BDFDB.DiscordConstants.Colors.WHITE : BDFDB.DiscordConstants.Colors.BLACK + }) : null + ] + }); + if (props.isCustom || props.isSingle || props.color == null) swatch = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: props.isCustom || props.isSingle ? BDFDB.LanguageUtils.LanguageStrings.CUSTOM_COLOR : BDFDB.LanguageUtils.LanguageStrings.DEFAULT, + tooltipConfig: {type: props.isSingle ? "top" : "bottom"}, + children: swatch + }); + if (props.isCustom || 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, + open: swatches.props.pickerOpen, + onClick: _ => swatches.props.pickerOpen = true, + onOpen: _ => { + swatches.props.pickerOpen = true; + if (typeof swatches.props.onPickerOpen == "function") swatches.props.onPickerOpen(this); + }, + onClose: _ => { + delete swatches.props.pickerOpen; + if (typeof swatches.props.onPickerClose == "function") swatches.props.onPickerClose(this); + }, + renderPopout: _ => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.ColorPicker, Object.assign({}, swatches.props.pickerConfig, { + color: swatches.props.color, + onColorChange: color => { + if (typeof swatches.props.onColorChange == "function") swatches.props.onColorChange(color); + props.color = color; + swatches.props.color = color; + swatches.props.customColor = color; + swatches.props.customSelected = true; + BDFDB.ReactUtils.forceUpdate(swatches); + } + }), true) + }); + if (props.isCustom) swatch = BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickerswatchcustomcontainer, + children: swatch + }); + return swatch; + } + render() { + this.props.color = BDFDB.ObjectUtils.is(this.props.color) ? this.props.color : BDFDB.ColorUtils.convert(this.props.color, "RGBA"); + this.props.colors = (BDFDB.ArrayUtils.is(this.props.colors) ? this.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")); + this.props.colorRows = this.props.colors.length ? [this.props.colors.slice(0, parseInt(this.props.colors.length/2)), this.props.colors.slice(parseInt(this.props.colors.length/2))] : []; + this.props.customColor = !this.props.color || !this.props.customSelected && this.props.colors.indexOf(this.props.color) > -1 ? null : this.props.color; + this.props.defaultCustomColor = BDFDB.ObjectUtils.is(this.props.defaultCustomColor) ? this.props.defaultCustomColor : BDFDB.ColorUtils.convert(this.props.defaultCustomColor, "RGBA"); + this.props.customSelected = !!this.props.customColor; + this.props.pickerConfig = BDFDB.ObjectUtils.is(this.props.pickerConfig) ? this.props.pickerConfig : {gradient: true, alpha: true}; + + const isSingle = !this.props.colors.length; + return BDFDB.ReactUtils.createElement("div", { + className: isSingle ? BDFDB.disCN.colorpickerswatchsinglewrapper : BDFDB.DOMUtils.formatClassName(BDFDB.disCN.colorpickerswatches, BDFDB.disCN.colorpickerswatchescontainer, this.props.disabled && BDFDB.disCN.colorpickerswatchesdisabled), + children: [ + BDFDB.ReactUtils.createElement(this.ColorSwatch, { + swatches: this, + color: this.props.customColor, + isSingle: isSingle, + isCustom: !isSingle, + isSelected: this.props.customSelected, + isDisabled: this.props.disabled, + pickerOpen: this.props.pickerOpen, + style: {margin: 0} + }), + !isSingle && BDFDB.ReactUtils.createElement("div", { + children: this.props.colorRows.map(row => BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.colorpickerrow, + children: row.map(color => BDFDB.ReactUtils.createElement(this.ColorSwatch, { + swatches: this, + color: color, + isCustom: false, + isSelected: !this.props.customSelected && color == this.props.color, + isDisabled: this.props.disabled + })) + })) + }) + ] + }); + } + }; + + InternalComponents.LibraryComponents.DateInput = class BDFDB_DateInput extends LibraryModules.React.Component { + renderFormatButton(props) { + const button = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Clickable, { + className: BDFDB.disCN.dateinputbutton, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: props.svgName, + width: 20, + height: 20 + }) + }); + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutContainer, { + width: props.popoutWidth || 350, + padding: 10, + animation: InternalComponents.LibraryComponents.PopoutContainer.Animation.SCALE, + position: InternalComponents.LibraryComponents.PopoutContainer.Positions.TOP, + align: InternalComponents.LibraryComponents.PopoutContainer.Align.RIGHT, + onClose: instance => BDFDB.DOMUtils.removeClass(instance.domElementRef.current, BDFDB.disCN.dateinputbuttonselected), + renderPopout: instance => { + BDFDB.DOMUtils.addClass(instance.domElementRef.current, BDFDB.disCN.dateinputbuttonselected); + return props.children || BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: [ + props.name && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { + label: props.name + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, { + className: BDFDB.disCN.dateinputfield, + placeholder: props.placeholder, + value: props.getValue(), + onChange: typeof props.onChange == "function" ? props.onChange : null + }), + props.tooltipText && this.renderInfoButton(props.tooltipText) + ].filter(n => n) + }) + }, + children: props.name ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: props.name, + children: button + }) : button + }); + } + renderInfoButton(text, style) { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: [text].flat(10).filter(n => n).map(n => BDFDB.ReactUtils.createElement("div", {children: n})), + tooltipConfig: { + type: "bottom", + zIndex: 1009, + maxWidth: 560 + }, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.dateinputbutton, + style: Object.assign({}, style), + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: InternalComponents.LibraryComponents.SvgIcon.Names.QUESTIONMARK, + width: 24, + height: 24 + }) + }) + }); + } + handleChange() { + if (typeof this.props.onChange == "function") this.props.onChange(BDFDB.ObjectUtils.extract(this.props, "formatString", "dateString", "timeString", "timeOffset", "language")); + } + render() { + let input = this, formatter, preview; + const defaultOffset = ((new Date()).getTimezoneOffset() * (-1/60)); + return BDFDB.ReactUtils.createElement("div", BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.dateinputwrapper, this.props.className), + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { + label: this.props.label + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.dateinputinner, + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.dateinputcontrols, + children: [ + BDFDB.ReactUtils.createElement(class DateInputPreview extends LibraryModules.React.Component { + componentDidMount() {formatter = this;} + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, { + className: BDFDB.disCN.dateinputfield, + placeholder: InternalComponents.LibraryComponents.DateInput.getDefaultString(input.props.language), + value: input.props.formatString, + onChange: value => { + input.props.formatString = value; + input.handleChange.apply(input, []); + BDFDB.ReactUtils.forceUpdate(formatter, preview); + } + }); + } + }), + this.renderInfoButton([ + "$date will be replaced with the Date", + "$time will be replaced with the Time", + "$time12 will be replaced with the Time (12h Form)", "$month will be replaced with the Month Name", "$monthS will be replaced with the Month Name (Short Form)", - ], - onChange: value => { - this.props.dateString = value; - this.handleChange.apply(this, []); - BDFDB.ReactUtils.forceUpdate(formatter, preview); - } - }), - this.renderFormatButton({ - name: BDFDB.LanguageUtils.LibraryStrings.time, - svgName: InternalComponents.LibraryComponents.SvgIcon.Names.CLOCK, - placeholder: this.props.timeString, - getValue: _ => this.props.timeString, - tooltipText: [ - "$h will be replaced with the Hours", - "$hh will be replaced with the Hours (Forced Zeros)", - "$m will be replaced with the Minutes", - "$mm will be replaced with the Minutes (Forced Zeros)", - "$s will be replaced with the Seconds", - "$ss will be replaced with the Seconds (Forced Zeros)", - "$u will be replaced with the Milliseconds", - "$uu will be replaced with the Milliseconds (Forced Zeros)" - ], - onChange: value => { - this.props.timeString = value; - this.handleChange.apply(this, []); - BDFDB.ReactUtils.forceUpdate(formatter, preview); - } - }), - this.renderFormatButton({ - name: BDFDB.LanguageUtils.LibraryStrings.location, - svgName: InternalComponents.LibraryComponents.SvgIcon.Names.GLOBE, - popoutWidth: 550, - children: [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AutoFocusCatcher, {}), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { - className: BDFDB.disCN.marginbottom4, - align: InternalComponents.LibraryComponents.Flex.Align.CENTER, - children: [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { - label: BDFDB.LanguageUtils.LanguageStrings.LANGUAGE - }), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Select, { - className: BDFDB.disCN.dateinputfield, - value: this.props.language != null ? this.props.language : "$discord", - options: Object.keys(BDFDB.LanguageUtils.languages).map(id => ({ - value: id, - label: BDFDB.LanguageUtils.getName(BDFDB.LanguageUtils.languages[id]) - })), - searchable: true, - optionRenderer: lang => lang.label, - onChange: value => { - this.props.language = value == "$discord" ? undefined : value; - this.handleChange.apply(this, []); - BDFDB.ReactUtils.forceUpdate(formatter, preview); - } - }) - ] - }), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { - align: InternalComponents.LibraryComponents.Flex.Align.CENTER, - children: [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { - label: BDFDB.LanguageUtils.LibraryStrings.timezone - }), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Select, { - className: BDFDB.disCN.dateinputfield, - value: this.props.timeOffset != null ? this.props.timeOffset : defaultOffset, - options: [-12.0, -11.0, -10.0, -9.5, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.5, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 5.75, 6.0, 6.5, 7.0, 8.0, 8.75, 9.0, 9.5, 10.0, 10.5, 11.0, 12.0, 12.75, 13.0, 14.0].map(offset => ({label: offset< 0 ? offset : `+${offset}`, value: offset})), - searchable: true, - onChange: value => { - this.props.timeOffset = value == defaultOffset ? undefined : value; - this.handleChange.apply(this, []); - BDFDB.ReactUtils.forceUpdate(formatter, preview); - } - }) - ] - }) - ] - }) - ] - }), - BDFDB.ReactUtils.createElement(class DateInputPreview extends LibraryModules.React.Component { - componentDidMount() {preview = this;} - render() { - return !input.props.noPreview && BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.dateinputpreview, - children: [ - input.props.prefix && BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.dateinputpreviewprefix, - children: typeof input.props.prefix == "function" ? input.props.prefix(input) : input.props.prefix, - }), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextScroller, { - children: InternalComponents.LibraryComponents.DateInput.format(input.props, new Date((new Date()) - (1000*60*60*24*2))) - }), - input.props.suffix && BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.dateinputpreviewsuffix, - children: typeof input.props.suffix == "function" ? input.props.suffix(input) : input.props.suffix, - }) - ].filter(n => n) - }); - } - }) - ] - }) - ] - }), "onChange", "label", "formatString", "dateString", "timeString", "timeOffset", "language", "noPreview", "prefix", "suffix")); - } - }; - InternalComponents.LibraryComponents.DateInput.getDefaultString = function (language) { - language = language || BDFDB.LanguageUtils.getLanguage().id; - const date = new Date(); - return date.toLocaleString(language).replace(date.toLocaleDateString(language), "$date").replace(date.toLocaleTimeString(language, {hourCycle: "h12"}), "$time12").replace(date.toLocaleTimeString(language, {hourCycle: "h11"}), "$time12").replace(date.toLocaleTimeString(language, {hourCycle: "h24"}), "$time").replace(date.toLocaleTimeString(language, {hourCycle: "h23"}), "$time"); - }; - InternalComponents.LibraryComponents.DateInput.parseDate = function (date, offset) { - let timeObj = date; - if (typeof timeObj == "string") { - const language = BDFDB.LanguageUtils.getLanguage().id; - for (let i = 0; i < 12; i++) { - const tempDate = new Date(); - tempDate.setMonth(i); - timeObj = timeObj.replace(tempDate.toLocaleDateString(language, {month:"long"}), tempDate.toLocaleDateString("en", {month:"short"})); + "$day will be replaced with the Weekday Name", + "$dayS will be replaced with the Weekday Name (Short Form)", + "$agoAmount will be replaced with ('Today', 'Yesterday', 'x days/weeks/months ago')", + "$agoDays will be replaced with ('Today', 'Yesterday', 'x days ago')", + "$agoDate will be replaced with ('Today', 'Yesterday', $date)" + ], {marginRight: 6}), + this.renderFormatButton({ + name: BDFDB.LanguageUtils.LanguageStrings.DATE, + svgName: InternalComponents.LibraryComponents.SvgIcon.Names.CALENDAR, + placeholder: this.props.dateString, + getValue: _ => this.props.dateString, + tooltipText: [ + "$d will be replaced with the Day", + "$dd will be replaced with the Day (Forced Zeros)", + "$m will be replaced with the Month", + "$mm will be replaced with the Month (Forced Zeros)", + "$yy will be replaced with the Year (2-Digit)", + "$yyyy will be replaced with the Year (4-Digit)", + "$month will be replaced with the Month Name", + "$monthS will be replaced with the Month Name (Short Form)", + ], + onChange: value => { + this.props.dateString = value; + this.handleChange.apply(this, []); + BDFDB.ReactUtils.forceUpdate(formatter, preview); + } + }), + this.renderFormatButton({ + name: BDFDB.LanguageUtils.LibraryStrings.time, + svgName: InternalComponents.LibraryComponents.SvgIcon.Names.CLOCK, + placeholder: this.props.timeString, + getValue: _ => this.props.timeString, + tooltipText: [ + "$h will be replaced with the Hours", + "$hh will be replaced with the Hours (Forced Zeros)", + "$m will be replaced with the Minutes", + "$mm will be replaced with the Minutes (Forced Zeros)", + "$s will be replaced with the Seconds", + "$ss will be replaced with the Seconds (Forced Zeros)", + "$u will be replaced with the Milliseconds", + "$uu will be replaced with the Milliseconds (Forced Zeros)" + ], + onChange: value => { + this.props.timeString = value; + this.handleChange.apply(this, []); + BDFDB.ReactUtils.forceUpdate(formatter, preview); + } + }), + this.renderFormatButton({ + name: BDFDB.LanguageUtils.LibraryStrings.location, + svgName: InternalComponents.LibraryComponents.SvgIcon.Names.GLOBE, + popoutWidth: 550, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AutoFocusCatcher, {}), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.disCN.marginbottom4, + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { + label: BDFDB.LanguageUtils.LanguageStrings.LANGUAGE + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Select, { + className: BDFDB.disCN.dateinputfield, + value: this.props.language != null ? this.props.language : "$discord", + options: Object.keys(BDFDB.LanguageUtils.languages).map(id => ({ + value: id, + label: BDFDB.LanguageUtils.getName(BDFDB.LanguageUtils.languages[id]) + })), + searchable: true, + optionRenderer: lang => lang.label, + onChange: value => { + this.props.language = value == "$discord" ? undefined : value; + this.handleChange.apply(this, []); + BDFDB.ReactUtils.forceUpdate(formatter, preview); + } + }) + ] + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + align: InternalComponents.LibraryComponents.Flex.Align.CENTER, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SettingsLabel, { + label: BDFDB.LanguageUtils.LibraryStrings.timezone + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Select, { + className: BDFDB.disCN.dateinputfield, + value: this.props.timeOffset != null ? this.props.timeOffset : defaultOffset, + options: [-12.0, -11.0, -10.0, -9.5, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.5, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 5.75, 6.0, 6.5, 7.0, 8.0, 8.75, 9.0, 9.5, 10.0, 10.5, 11.0, 12.0, 12.75, 13.0, 14.0].map(offset => ({label: offset< 0 ? offset : `+${offset}`, value: offset})), + searchable: true, + onChange: value => { + this.props.timeOffset = value == defaultOffset ? undefined : value; + this.handleChange.apply(this, []); + BDFDB.ReactUtils.forceUpdate(formatter, preview); + } + }) + ] + }) + ] + }) + ] + }), + BDFDB.ReactUtils.createElement(class DateInputPreview extends LibraryModules.React.Component { + componentDidMount() {preview = this;} + render() { + return !input.props.noPreview && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.dateinputpreview, + children: [ + input.props.prefix && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.dateinputpreviewprefix, + children: typeof input.props.prefix == "function" ? input.props.prefix(input) : input.props.prefix, + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextScroller, { + children: InternalComponents.LibraryComponents.DateInput.format(input.props, new Date((new Date()) - (1000*60*60*24*2))) + }), + input.props.suffix && BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.dateinputpreviewsuffix, + children: typeof input.props.suffix == "function" ? input.props.suffix(input) : input.props.suffix, + }) + ].filter(n => n) + }); + } + }) + ] + }) + ] + }), "onChange", "label", "formatString", "dateString", "timeString", "timeOffset", "language", "noPreview", "prefix", "suffix")); } - timeObj = new Date(timeObj); - } - else if (typeof timeObj == "number") timeObj = new Date(timeObj); - - if (timeObj.toString() == "Invalid Date") timeObj = new Date(parseInt(date)); - if (timeObj.toString() == "Invalid Date" || typeof timeObj.toLocaleDateString != "function") timeObj = new Date(); - offset = offset != null && parseFloat(offset); - if ((offset || offset === 0) && !isNaN(offset)) timeObj = new Date(timeObj.getTime() + ((offset - timeObj.getTimezoneOffset() * (-1/60)) * 60*60*1000)); - return timeObj; - }; - InternalComponents.LibraryComponents.DateInput.format = function (data, time) { - if (typeof data == "string") data = {formatString: data}; - if (data && typeof data.formatString != "string") data.formatString = ""; - if (!data || typeof data.formatString != "string" || !time) return ""; - - const language = data.language || BDFDB.LanguageUtils.getLanguage().id; - const timeObj = InternalComponents.LibraryComponents.DateInput.parseDate(time, data.timeOffset); - const now = new Date(); - const daysAgo = Math.round((Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()) - Date.UTC(timeObj.getFullYear(), timeObj.getMonth(), timeObj.getDate()))/(1000*60*60*24)); - const date = data.dateString && typeof data.dateString == "string" ? InternalComponents.LibraryComponents.DateInput.formatDate({dateString: data.dateString, language: language}, timeObj) : timeObj.toLocaleDateString(language); - - return (data.formatString || InternalComponents.LibraryComponents.DateInput.getDefaultString(language)) - .replace(/\$date/g, date) - .replace(/\$time12/g, data.timeString && typeof data.timeString == "string" ? InternalComponents.LibraryComponents.DateInput.formatTime({timeString: data.timeString, language: language}, timeObj, true) : timeObj.toLocaleTimeString(language, {hourCycle: "h12"})) - .replace(/\$time/g, data.timeString && typeof data.timeString == "string" ? InternalComponents.LibraryComponents.DateInput.formatTime({timeString: data.timeString, language: language}, timeObj) : timeObj.toLocaleTimeString(language, {hourCycle: "h23"})) - .replace(/\$monthS/g, timeObj.toLocaleDateString(language, {month: "short"})) - .replace(/\$month/g, timeObj.toLocaleDateString(language, {month: "long"})) - .replace(/\$dayS/g, timeObj.toLocaleDateString(language, {weekday: "short"})) - .replace(/\$day/g, timeObj.toLocaleDateString(language, {weekday: "long"})) - .replace(/\$agoAmount/g, daysAgo < 0 ? "" : daysAgo > 1 ? BDFDB.DiscordObjects.Timestamp(timeObj.getTime()).fromNow() : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`]) - .replace(/\$agoDays/g, daysAgo < 0 ? "" : daysAgo > 1 ? BDFDB.LanguageUtils.LanguageStringsFormat(`GAME_LIBRARY_LAST_PLAYED_DAYS`, daysAgo) : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`]) - .replace(/\$agoDate/g, daysAgo < 0 ? "" : daysAgo > 1 ? date : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`]) - .replace(/\(\)|\[\]/g, "").replace(/,\s*$|^\s*,/g, "").replace(/ +/g, " ").trim(); - }; - InternalComponents.LibraryComponents.DateInput.formatDate = function (data, time) { - if (typeof data == "string") data = {dateString: data}; - if (data && typeof data.dateString != "string") return ""; - if (!data || typeof data.dateString != "string" || !data.dateString || !time) return ""; - - const language = data.language || BDFDB.LanguageUtils.getLanguage().id; - const timeObj = InternalComponents.LibraryComponents.DateInput.parseDate(time, data.timeOffset); - - return data.dateString - .replace(/\$monthS/g, timeObj.toLocaleDateString(language, {month: "short"})) - .replace(/\$month/g, timeObj.toLocaleDateString(language, {month: "long"})) - .replace(/\$dd/g, timeObj.toLocaleDateString(language, {day: "2-digit"})) - .replace(/\$d/g, timeObj.toLocaleDateString(language, {day: "numeric"})) - .replace(/\$mm/g, timeObj.toLocaleDateString(language, {month: "2-digit"})) - .replace(/\$m/g, timeObj.toLocaleDateString(language, {month: "numeric"})) - .replace(/\$yyyy/g, timeObj.toLocaleDateString(language, {year: "numeric"})) - .replace(/\$yy/g, timeObj.toLocaleDateString(language, {year: "2-digit"})) - .trim(); - }; - InternalComponents.LibraryComponents.DateInput.formatTime = function (data, time, hour12) { - if (typeof data == "string") data = {timeString: data}; - if (data && typeof data.timeString != "string") return ""; - if (!data || typeof data.timeString != "string" || !data.timeString || !time) return ""; - - const language = data.language || BDFDB.LanguageUtils.getLanguage().id; - const timeObj = InternalComponents.LibraryComponents.DateInput.parseDate(time, data.timeOffset); - - let hours = timeObj.getHours(); - if (hour12) { - hours = hours == 0 ? 12 : hours; - if (hours > 12) hours -= 12; - } - const minutes = timeObj.getMinutes(); - const seconds = timeObj.getSeconds(); - const milli = timeObj.getMilliseconds(); - - let string = data.timeString - .replace(/\$hh/g, hours < 10 ? `0${hours}` : hours) - .replace(/\$h/g, hours) - .replace(/\$mm/g, minutes < 10 ? `0${minutes}` : minutes) - .replace(/\$m/g, minutes) - .replace(/\$ss/g, seconds < 10 ? `0${seconds}` : seconds) - .replace(/\$s/g, seconds) - .replace(/\$uu/g, milli < 10 ? `00${seconds}` : milli < 100 ? `0${milli}` : milli) - .replace(/\$u/g, milli) - .trim(); + }; + InternalComponents.LibraryComponents.DateInput.getDefaultString = function (language) { + language = language || BDFDB.LanguageUtils.getLanguage().id; + const date = new Date(); + return date.toLocaleString(language).replace(date.toLocaleDateString(language), "$date").replace(date.toLocaleTimeString(language, {hourCycle: "h12"}), "$time12").replace(date.toLocaleTimeString(language, {hourCycle: "h11"}), "$time12").replace(date.toLocaleTimeString(language, {hourCycle: "h24"}), "$time").replace(date.toLocaleTimeString(language, {hourCycle: "h23"}), "$time"); + }; + InternalComponents.LibraryComponents.DateInput.parseDate = function (date, offset) { + let timeObj = date; + if (typeof timeObj == "string") { + const language = BDFDB.LanguageUtils.getLanguage().id; + for (let i = 0; i < 12; i++) { + const tempDate = new Date(); + tempDate.setMonth(i); + timeObj = timeObj.replace(tempDate.toLocaleDateString(language, {month:"long"}), tempDate.toLocaleDateString("en", {month:"short"})); + } + timeObj = new Date(timeObj); + } + else if (typeof timeObj == "number") timeObj = new Date(timeObj); + + if (timeObj.toString() == "Invalid Date") timeObj = new Date(parseInt(date)); + if (timeObj.toString() == "Invalid Date" || typeof timeObj.toLocaleDateString != "function") timeObj = new Date(); + offset = offset != null && parseFloat(offset); + if ((offset || offset === 0) && !isNaN(offset)) timeObj = new Date(timeObj.getTime() + ((offset - timeObj.getTimezoneOffset() * (-1/60)) * 60*60*1000)); + return timeObj; + }; + InternalComponents.LibraryComponents.DateInput.format = function (data, time) { + if (typeof data == "string") data = {formatString: data}; + if (data && typeof data.formatString != "string") data.formatString = ""; + if (!data || typeof data.formatString != "string" || !time) return ""; + + const language = data.language || BDFDB.LanguageUtils.getLanguage().id; + const timeObj = InternalComponents.LibraryComponents.DateInput.parseDate(time, data.timeOffset); + const now = new Date(); + const daysAgo = Math.round((Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()) - Date.UTC(timeObj.getFullYear(), timeObj.getMonth(), timeObj.getDate()))/(1000*60*60*24)); + const date = data.dateString && typeof data.dateString == "string" ? InternalComponents.LibraryComponents.DateInput.formatDate({dateString: data.dateString, language: language}, timeObj) : timeObj.toLocaleDateString(language); + + return (data.formatString || InternalComponents.LibraryComponents.DateInput.getDefaultString(language)) + .replace(/\$date/g, date) + .replace(/\$time12/g, data.timeString && typeof data.timeString == "string" ? InternalComponents.LibraryComponents.DateInput.formatTime({timeString: data.timeString, language: language}, timeObj, true) : timeObj.toLocaleTimeString(language, {hourCycle: "h12"})) + .replace(/\$time/g, data.timeString && typeof data.timeString == "string" ? InternalComponents.LibraryComponents.DateInput.formatTime({timeString: data.timeString, language: language}, timeObj) : timeObj.toLocaleTimeString(language, {hourCycle: "h23"})) + .replace(/\$monthS/g, timeObj.toLocaleDateString(language, {month: "short"})) + .replace(/\$month/g, timeObj.toLocaleDateString(language, {month: "long"})) + .replace(/\$dayS/g, timeObj.toLocaleDateString(language, {weekday: "short"})) + .replace(/\$day/g, timeObj.toLocaleDateString(language, {weekday: "long"})) + .replace(/\$agoAmount/g, daysAgo < 0 ? "" : daysAgo > 1 ? BDFDB.DiscordObjects.Timestamp(timeObj.getTime()).fromNow() : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`]) + .replace(/\$agoDays/g, daysAgo < 0 ? "" : daysAgo > 1 ? BDFDB.LanguageUtils.LanguageStringsFormat(`GAME_LIBRARY_LAST_PLAYED_DAYS`, daysAgo) : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`]) + .replace(/\$agoDate/g, daysAgo < 0 ? "" : daysAgo > 1 ? date : BDFDB.LanguageUtils.LanguageStrings[`SEARCH_SHORTCUT_${daysAgo == 1 ? "YESTERDAY" : "TODAY"}`]) + .replace(/\(\)|\[\]/g, "").replace(/,\s*$|^\s*,/g, "").replace(/ +/g, " ").trim(); + }; + InternalComponents.LibraryComponents.DateInput.formatDate = function (data, time) { + if (typeof data == "string") data = {dateString: data}; + if (data && typeof data.dateString != "string") return ""; + if (!data || typeof data.dateString != "string" || !data.dateString || !time) return ""; + + const language = data.language || BDFDB.LanguageUtils.getLanguage().id; + const timeObj = InternalComponents.LibraryComponents.DateInput.parseDate(time, data.timeOffset); + + return data.dateString + .replace(/\$monthS/g, timeObj.toLocaleDateString(language, {month: "short"})) + .replace(/\$month/g, timeObj.toLocaleDateString(language, {month: "long"})) + .replace(/\$dd/g, timeObj.toLocaleDateString(language, {day: "2-digit"})) + .replace(/\$d/g, timeObj.toLocaleDateString(language, {day: "numeric"})) + .replace(/\$mm/g, timeObj.toLocaleDateString(language, {month: "2-digit"})) + .replace(/\$m/g, timeObj.toLocaleDateString(language, {month: "numeric"})) + .replace(/\$yyyy/g, timeObj.toLocaleDateString(language, {year: "numeric"})) + .replace(/\$yy/g, timeObj.toLocaleDateString(language, {year: "2-digit"})) + .trim(); + }; + InternalComponents.LibraryComponents.DateInput.formatTime = function (data, time, hour12) { + if (typeof data == "string") data = {timeString: data}; + if (data && typeof data.timeString != "string") return ""; + if (!data || typeof data.timeString != "string" || !data.timeString || !time) return ""; + + const language = data.language || BDFDB.LanguageUtils.getLanguage().id; + const timeObj = InternalComponents.LibraryComponents.DateInput.parseDate(time, data.timeOffset); + + let hours = timeObj.getHours(); + if (hour12) { + hours = hours == 0 ? 12 : hours; + if (hours > 12) hours -= 12; + } + const minutes = timeObj.getMinutes(); + const seconds = timeObj.getSeconds(); + const milli = timeObj.getMilliseconds(); + + let string = data.timeString + .replace(/\$hh/g, hours < 10 ? `0${hours}` : hours) + .replace(/\$h/g, hours) + .replace(/\$mm/g, minutes < 10 ? `0${minutes}` : minutes) + .replace(/\$m/g, minutes) + .replace(/\$ss/g, seconds < 10 ? `0${seconds}` : seconds) + .replace(/\$s/g, seconds) + .replace(/\$uu/g, milli < 10 ? `00${seconds}` : milli < 100 ? `0${milli}` : milli) + .replace(/\$u/g, milli) + .trim(); - let digits = "\\d"; - if (BDFDB.LanguageUtils.languages[language] && BDFDB.LanguageUtils.languages[language].numberMap) { - digits = Object.entries(BDFDB.LanguageUtils.languages[language].numberMap).map(n => n[1]).join(""); - for (let number in BDFDB.LanguageUtils.languages[language].numberMap) string = string.replace(new RegExp(number, "g"), BDFDB.LanguageUtils.languages[language].numberMap[number]); - } - return hour12 ? timeObj.toLocaleTimeString(language, {hourCycle: "h12"}).replace(new RegExp(`[${digits}]{1,2}[^${digits}][${digits}]{1,2}[^${digits}][${digits}]{1,2}`, "g"), string) : string; - }; - - 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); - if (typeof this.close == "function" && !BDFDB.ListenerUtils.isPressed(16)) this.close(); + let digits = "\\d"; + if (BDFDB.LanguageUtils.languages[language] && BDFDB.LanguageUtils.languages[language].numberMap) { + digits = Object.entries(BDFDB.LanguageUtils.languages[language].numberMap).map(n => n[1]).join(""); + for (let number in BDFDB.LanguageUtils.languages[language].numberMap) string = string.replace(new RegExp(number, "g"), BDFDB.LanguageUtils.languages[language].numberMap[number]); + } + return hour12 ? timeObj.toLocaleTimeString(language, {hourCycle: "h12"}).replace(new RegExp(`[${digits}]{1,2}[^${digits}][${digits}]{1,2}[^${digits}][${digits}]{1,2}`, "g"), string) : string; + }; + + 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); + if (typeof this.close == "function" && !BDFDB.ListenerUtils.isPressed(16)) this.close(); + BDFDB.ReactUtils.forceUpdate(this); + } + } + render() { + let button = this; + 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 => { + this.close = instance.close; + return [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.EmojiPicker, { + closePopout: this.close, + onSelectEmoji: this.handleEmojiChange.bind(this), + allowManagedEmojis: this.props.allowManagedEmojis, + allowManagedEmojisUsage: this.props.allowManagedEmojisUsage + }), + BDFDB.ReactUtils.createElement(class extends LibraryModules.React.Component { + componentDidMount() {InternalComponents.LibraryComponents.EmojiPickerButton.current = button;} + componentWillUnmount() {delete InternalComponents.LibraryComponents.EmojiPickerButton.current;} + render() {return null;} + }) + ]; + } + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.EmojiPickerButton, {allowManagedEmojis: false, allowManagedEmojisUsage: 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() { - let button = this; - 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 => { - this.close = instance.close; - return [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.EmojiPicker, { - closePopout: this.close, - onSelectEmoji: this.handleEmojiChange.bind(this), - allowManagedEmojis: this.props.allowManagedEmojis, - allowManagedEmojisUsage: this.props.allowManagedEmojisUsage - }), - BDFDB.ReactUtils.createElement(class extends LibraryModules.React.Component { - componentDidMount() {InternalComponents.LibraryComponents.EmojiPickerButton.current = button;} - componentWillUnmount() {delete InternalComponents.LibraryComponents.EmojiPickerButton.current;} - render() {return null;} - }) - ]; - } - }); - } - }; - InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.EmojiPickerButton, {allowManagedEmojis: false, allowManagedEmojisUsage: 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(InternalComponents.LibraryComponents.Clickable, { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.favbuttoncontainer, BDFDB.disCN.favbutton, this.props.isFavorite && BDFDB.disCN.favbuttonselected, this.props.className), - onClick: this.handleClick.bind(this), - children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { - name: InternalComponents.LibraryComponents.SvgIcon.Names[this.props.isFavorite ? "FAVORITE_FILLED" : "FAVORITE"], - width: this.props.width || 24, - height: this.props.height || 24, - className: BDFDB.disCN.favbuttonicon - }) - }); - } - }; - - 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() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Clickable, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.favbuttoncontainer, BDFDB.disCN.favbutton, this.props.isFavorite && BDFDB.disCN.favbuttonselected, this.props.className), + onClick: this.handleClick.bind(this), + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + name: InternalComponents.LibraryComponents.SvgIcon.Names[this.props.isFavorite ? "FAVORITE_FILLED" : "FAVORITE"], + width: this.props.width || 24, + height: this.props.height || 24, + className: BDFDB.disCN.favbuttonicon + }) + }); + } + }; + + 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,${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 = Object.assign({}, InternalComponents.LibraryComponents.GuildComponents); - - 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 && node.nodeType != Node.TEXT_NODE) for (let child of node.querySelectorAll("a")) child.setAttribute("draggable", false); - } - render() { - if (!this.props.guild) return null; - - this.props.guildId = this.props.guild.id; - this.props.selectedChannelId = LibraryModules.LastChannelStore.getChannelId(this.props.guild.id); - - let currentVoiceChannel = LibraryModules.ChannelStore.getChannel(LibraryModules.CurrentVoiceUtils.getChannelId()); - let hasVideo = currentVoiceChannel && LibraryModules.VoiceUtils.hasVideo(currentVoiceChannel); - - 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.mediaState = Object.assign({}, this.props.mediaState, { - audio: this.props.state ? currentVoiceChannel && currentVoiceChannel.guild_id == this.props.guild.id && !hasVideo : false, - video: this.props.state ? currentVoiceChannel && currentVoiceChannel.guild_id == this.props.guild.id && hasVideo : false, - screenshare: this.props.state ? !!LibraryModules.StreamUtils.getAllApplicationStreams().filter(stream => stream.guildId == this.props.guild.id)[0] : false, - liveStage: this.props.state ? Object.keys(LibraryModules.StageChannelStore.getStageInstancesByGuild(this.props.guild.id)).length > 0 : false, - hasLiveVoiceChannel: this.props.state && false ? !LibraryModules.MutedUtils.isMuted(this.props.guild.id) && BDFDB.ObjectUtils.toArray(LibraryModules.VoiceUtils.getVoiceStates(this.props.guild.id)).length > 0 : false, - participating: this.props.state ? LibraryModules.CurrentVoiceUtils.getGuildId() == this.props.guild.id : false, - participatingInStage: this.props.state ? currentVoiceChannel && currentVoiceChannel.guild_id == this.props.guild.id && currentVoiceChannel.isGuildStageVoice() : false - }); - - this.props.animatable = this.props.state ? this.props.guild.icon && LibraryModules.IconUtils.isAnimatedIconHash(this.props.guild.icon) : 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.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 ? LibraryModules.GuildBadgeUtils.renderUnavailableBadge() : LibraryModules.GuildBadgeUtils.renderMediaBadge(this.props.mediaState), - lowerBadge: this.props.badge > 0 ? LibraryModules.GuildBadgeUtils.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 + 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,${LibraryRequires.fs.readFileSync(file.path).toString("base64")}`}${this.props.mode ? "')" : ""}`; + BDFDB.ReactUtils.forceUpdate(this.refInput); + this.refInput.handleChange(this.refInput.props.value); } } - }, - 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.props.iconSize || 96, this.state.hovered && this.props.animatable), - selected: this.props.selected || this.state.hovered - }) - }) - }); + }) + ] + }), "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 = Object.assign({}, InternalComponents.LibraryComponents.GuildComponents); + + 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 && node.nodeType != Node.TEXT_NODE) for (let child of node.querySelectorAll("a")) child.setAttribute("draggable", false); + } + render() { + if (!this.props.guild) return null; + + this.props.guildId = this.props.guild.id; + this.props.selectedChannelId = LibraryModules.LastChannelStore.getChannelId(this.props.guild.id); + + let currentVoiceChannel = LibraryModules.ChannelStore.getChannel(LibraryModules.CurrentVoiceUtils.getChannelId()); + let hasVideo = currentVoiceChannel && LibraryModules.VoiceUtils.hasVideo(currentVoiceChannel); + + 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.mediaState = Object.assign({}, this.props.mediaState, { + audio: this.props.state ? currentVoiceChannel && currentVoiceChannel.guild_id == this.props.guild.id && !hasVideo : false, + video: this.props.state ? currentVoiceChannel && currentVoiceChannel.guild_id == this.props.guild.id && hasVideo : false, + screenshare: this.props.state ? !!LibraryModules.StreamUtils.getAllApplicationStreams().filter(stream => stream.guildId == this.props.guild.id)[0] : false, + liveStage: this.props.state ? Object.keys(LibraryModules.StageChannelStore.getStageInstancesByGuild(this.props.guild.id)).length > 0 : false, + hasLiveVoiceChannel: this.props.state && false ? !LibraryModules.MutedUtils.isMuted(this.props.guild.id) && BDFDB.ObjectUtils.toArray(LibraryModules.VoiceUtils.getVoiceStates(this.props.guild.id)).length > 0 : false, + participating: this.props.state ? LibraryModules.CurrentVoiceUtils.getGuildId() == this.props.guild.id : false, + participatingInStage: this.props.state ? currentVoiceChannel && currentVoiceChannel.guild_id == this.props.guild.id && currentVoiceChannel.isGuildStageVoice() : false + }); + + this.props.animatable = this.props.state ? this.props.guild.icon && LibraryModules.IconUtils.isAnimatedIconHash(this.props.guild.icon) : false; + this.props.unavailable = this.props.state ? LibraryModules.GuildUnavailableStore.unavailableGuilds.includes(this.props.guild.id) : false; - 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, { + let isDraggedGuild = this.props.draggingGuildId === this.props.guild.id; + let guild = isDraggedGuild ? BDFDB.ReactUtils.createElement("div", { + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.GuildComponents.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 ? LibraryModules.GuildBadgeUtils.renderUnavailableBadge() : LibraryModules.GuildBadgeUtils.renderMediaBadge(this.props.mediaState), + lowerBadge: this.props.badge > 0 ? LibraryModules.GuildBadgeUtils.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.props.iconSize || 96, this.state.hovered && this.props.animatable), + selected: this.props.selected || this.state.hovered + }) + }) + }); + + 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 - }) - }) : 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.HistoryUtils.transitionTo(BDFDB.DiscordConstants.Routes.CHANNEL(guild.id, LibraryModules.LastChannelStore.getChannelId(guild.id))), - key: guild.id, - tabIndex: -1, + }); + } + }; + 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.HistoryUtils.transitionTo(BDFDB.DiscordConstants.Routes.CHANNEL(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; - } - 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++; + }, renderIcon: false}); + + InternalComponents.LibraryComponents.KeybindRecorder = reactInitialized && class BDFDB_KeybindRecorder extends LibraryModules.React.Component { + handleChange(arrays) { + this.props.value = arrays.map(platformKey => LibraryModules.KeyEvents.codes[LibraryModules.KeyCodeUtils.codeToKey(platformKey)] || platformKey[1]); + if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this); } - 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) - })); + handleReset() { + this.props.value = []; + if (this.recorder) this.recorder.setState({codes: []}); + if (typeof this.props.onChange == "function") this.props.onChange([], this); + if (typeof this.props.onReset == "function") this.props.onReset(this); } - 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) { - this.props.value = arrays.map(platformKey => LibraryModules.KeyEvents.codes[LibraryModules.KeyCodeUtils.codeToKey(platformKey)] || platformKey[1]); - if (typeof this.props.onChange == "function") this.props.onChange(this.props.value, this); - } - handleReset() { - this.props.value = []; - if (this.recorder) this.recorder.setState({codes: []}); - if (typeof this.props.onChange == "function") this.props.onChange([], this); - if (typeof this.props.onReset == "function") this.props.onReset(this); - } - componentDidMount() { - if (!this.recorder) this.recorder = BDFDB.ReactUtils.findOwner(this, {name: "KeybindRecorder"}); - } - 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 || this.props.value].flat(10).filter(n => n).map(keyCode => [BDFDB.DiscordConstants.KeyboardDeviceTypes.KEYBOARD_KEY, LibraryModules.KeyCodeUtils.keyToCode((Object.entries(LibraryModules.KeyEvents.codes).find(n => n[1] == keyCode && LibraryModules.KeyCodeUtils.keyToCode(n[0], null)) || [])[0], null) || keyCode]), - 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: ``, + componentDidMount() { + if (!this.recorder) this.recorder = BDFDB.ReactUtils.findOwner(this, {name: "KeybindRecorder"}); + } + 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.ModuleUtils.findByName("KeybindRecorder"), BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + defaultValue: [this.props.defaultValue || this.props.value].flat(10).filter(n => n).map(keyCode => [BDFDB.DiscordConstants.KeyboardDeviceTypes.KEYBOARD_KEY, LibraryModules.KeyCodeUtils.keyToCode((Object.entries(LibraryModules.KeyEvents.codes).find(n => n[1] == keyCode && LibraryModules.KeyCodeUtils.keyToCode(n[0], null)) || [])[0], null) || keyCode]), + 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, "RGB") || BDFDB.DiscordConstants.Colors.PRIMARY_DARK_300; + 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 }) - }) : 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"}, + ].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, + nativeClass: true, + 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.Scrollers.Thin, { + 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 !this.props.open ? null : BDFDB.ReactUtils.createElement(this.props.scroller ? InternalComponents.LibraryComponents.Scrollers.Thin : "div", Object.assign(BDFDB.ObjectUtils.exclude(this.props, "scroller", "open"), { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modaltabcontent, this.props.open && BDFDB.disCN.modaltabcontentopen, this.props.className), + children: this.props.children + })); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.ModalComponents.ModalTabContent, {tab: "unnamed"}); + + InternalComponents.LibraryComponents.ModalComponents.ModalFooter = reactInitialized && class BDFDB_ModalFooter extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modalfooter, this.props.className), + direction: this.props.direction || InternalComponents.LibraryComponents.Flex.Direction.HORIZONTAL_REVERSE, + align: InternalComponents.LibraryComponents.Flex.Align.STRETCH, + grow: 0, + shrink: 0, + children: this.props.children + }); + } + }; + + InternalComponents.LibraryComponents.MultiInput = reactInitialized && class BDFDB_MultiInput extends LibraryModules.React.Component { + constructor(props) { + super(props); + this.state = {focused: false}; + } + render() { + if (this.props.children && this.props.children.props) this.props.children.props.className = BDFDB.DOMUtils.formatClassName(this.props.children.props.className, BDFDB.disCN.inputmultifield); + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.inputwrapper, BDFDB.disCN.inputmultiwrapper), + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.input, BDFDB.disCN.inputmulti, this.state.focused && BDFDB.disCN.inputfocused), children: [ BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.listname, this.props.labelClassName), - style: {flex: "1 1 auto"}, - children: this.props.label + className: BDFDB.DOMUtils.formatClassName(this.props.innerClassName, BDFDB.disCN.inputwrapper, BDFDB.disCN.inputmultifirst), + children: this.props.children }), - 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, "RGB") || BDFDB.DiscordConstants.Colors.PRIMARY_DARK_300; - 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 + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.disCN.inputmultilast, + inputClassName: BDFDB.disCN.inputmultifield, + onFocus: e => this.setState({focused: true}), + onBlur: e => this.setState({focused: false}) + }), "children", "innerClassName")) + ] }) - ].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, - nativeClass: true, - 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); + }; + + InternalComponents.LibraryComponents.ListInput = reactInitialized && class BDFDB_ListInput extends LibraryModules.React.Component { + handleChange() { + if (typeof this.props.onChange) this.props.onChange(this.props.items, 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.Scrollers.Thin, { - 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 !this.props.open ? null : BDFDB.ReactUtils.createElement(this.props.scroller ? InternalComponents.LibraryComponents.Scrollers.Thin : "div", Object.assign(BDFDB.ObjectUtils.exclude(this.props, "scroller", "open"), { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modaltabcontent, this.props.open && BDFDB.disCN.modaltabcontentopen, this.props.className), - children: this.props.children - })); - } - }; - InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.ModalComponents.ModalTabContent, {tab: "unnamed"}); - - InternalComponents.LibraryComponents.ModalComponents.ModalFooter = reactInitialized && class BDFDB_ModalFooter extends LibraryModules.React.Component { - render() { - return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.modalfooter, this.props.className), - direction: this.props.direction || InternalComponents.LibraryComponents.Flex.Direction.HORIZONTAL_REVERSE, - align: InternalComponents.LibraryComponents.Flex.Align.STRETCH, - grow: 0, - shrink: 0, - children: this.props.children - }); - } - }; - - InternalComponents.LibraryComponents.MultiInput = reactInitialized && class BDFDB_MultiInput extends LibraryModules.React.Component { - constructor(props) { - super(props); - this.state = {focused: false}; - } - render() { - if (this.props.children && this.props.children.props) this.props.children.props.className = BDFDB.DOMUtils.formatClassName(this.props.children.props.className, BDFDB.disCN.inputmultifield); - return BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.inputwrapper, BDFDB.disCN.inputmultiwrapper), - children: BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.input, BDFDB.disCN.inputmulti, this.state.focused && BDFDB.disCN.inputfocused), - children: [ - BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(this.props.innerClassName, BDFDB.disCN.inputwrapper, BDFDB.disCN.inputmultifirst), - children: this.props.children - }), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { - className: BDFDB.disCN.inputmultilast, - inputClassName: BDFDB.disCN.inputmultifield, - onFocus: e => this.setState({focused: true}), - onBlur: e => this.setState({focused: false}) - }), "children", "innerClassName")) - ] - }) - }); - } - }; - - InternalComponents.LibraryComponents.ListInput = reactInitialized && class BDFDB_ListInput extends LibraryModules.React.Component { - handleChange() { - if (typeof this.props.onChange) this.props.onChange(this.props.items, this); - } - render() { - if (!BDFDB.ArrayUtils.is(this.props.items)) this.props.items = []; - return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.MultiInput, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { - className: BDFDB.disCN.inputlist, - innerClassName: BDFDB.disCN.inputlistitems, - onKeyDown: e => { - if (e.which == 13 && e.target.value && e.target.value.trim()) { - let value = e.target.value.trim(); - this.props.value = ""; - if (!this.props.items.includes(value)) { - this.props.items.push(value); - BDFDB.ReactUtils.forceUpdate(this); - this.handleChange.apply(this, []); - } - } - }, - children: this.props.items.map(item => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Badges.TextBadge, { - className: BDFDB.disCN.inputlistitem, - color: "var(--bdfdb-blurple)", - style: {borderRadius: "3px"}, - text: [ - item, - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { - className: BDFDB.disCN.inputlistdelete, - name: InternalComponents.LibraryComponents.SvgIcon.Names.CLOSE, - onClick: _ => { - BDFDB.ArrayUtils.remove(this.props.items, item); + render() { + if (!BDFDB.ArrayUtils.is(this.props.items)) this.props.items = []; + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.MultiInput, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.disCN.inputlist, + innerClassName: BDFDB.disCN.inputlistitems, + onKeyDown: e => { + if (e.which == 13 && e.target.value && e.target.value.trim()) { + let value = e.target.value.trim(); + this.props.value = ""; + if (!this.props.items.includes(value)) { + this.props.items.push(value); BDFDB.ReactUtils.forceUpdate(this); this.handleChange.apply(this, []); } - }) - ] - })) - }), "items")); - } - }; - - InternalComponents.LibraryComponents.PaginatedList = reactInitialized && class BDFDB_PaginatedList extends LibraryModules.React.Component { - constructor(props) { - super(props); - this.state = { - offset: props.offset - }; - } - handleJump(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(bottom) { - 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.DOMUtils.formatClassName(BDFDB.disCN.pagination, bottom ? BDFDB.disCN.paginationbottom : BDFDB.disCN.paginationtop, this.props.mini && BDFDB.disCN.paginationmini), - children: [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Paginator, { - totalCount: this.props.items.length, - currentPage: this.state.offset + 1, - pageSize: this.props.amount, - maxVisiblePages: this.props.maxVisiblePages, - onPageChange: page => {this.handleJump(isNaN(parseInt(page)) ? -1 : page - 1);} - }), - this.props.jump && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, { - type: "number", - size: InternalComponents.LibraryComponents.TextInput.Sizes.MINI, - value: this.state.offset + 1, - min: 1, - max: maxOffset + 1, - onKeyDown: (event, instance) => {if (event.which == 13) this.handleJump(isNaN(parseInt(instance.props.value)) ? -1 : instance.props.value - 1);} - }), - ].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.Scrollers.Thin, { - 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(InternalComponents.LibraryComponents.Clickable, { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.paginationlistalphabetchar, alphabet[key].disabled &&BDFDB.disCN.paginationlistalphabetchardisabled), - onClick: _ => {if (!alphabet[key].disabled) this.handleJump(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(true) - ].flat(10).filter(n => n) - }); - } - }; - InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.PaginatedList, {amount: 50, offset: 0, mini: true, jump: true, maxVisiblePages: 7, copyToBottom: false, fade: true}); - - InternalComponents.LibraryComponents.Popout = reactInitialized && class BDFDB_Popout extends LibraryModules.React.Component { - componentDidMount() { - this.props.containerInstance.popout = this; - if (typeof this.props.onOpen == "function") this.props.onOpen(this.props.containerInstance, this); - } - componentWillUnmount() { - delete this.props.containerInstance.popout; - if (typeof this.props.onClose == "function") this.props.onClose(this.props.containerInstance, this); - } - render() { - if (!this.props.wrap) return this.props.children; - let pos = typeof this.props.position == "string" ? this.props.position.toLowerCase() : null; - return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutFocusLock, { - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.popoutwrapper, this.props.className, this.props.themed && BDFDB.disCN.popoutthemedpopout, this.props.arrow && BDFDB.disCN.popoutarrow, this.props.arrow && (pos == "top" ? BDFDB.disCN.popoutarrowtop : BDFDB.disCN.popoutarrowbottom)), - id: this.props.id, - onClick: e => e.stopPropagation(), - style: BDFDB.ObjectUtils.extract(this.props, "padding", "height", "maxHeight", "minHeight", "width", "maxWidth", "minWidth"), - children: this.props.children - }); - } - }; - InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Popout, {themed: true, wrap: true}); - - InternalComponents.LibraryComponents.PopoutContainer = reactInitialized && class BDFDB_PopoutContainer extends LibraryModules.React.Component { - componentDidMount() { - this.toggle = this.toggle.bind(this); - this.onDocumentClicked = this.onDocumentClicked.bind(this); - this.domElementRef = BDFDB.ReactUtils.createRef(); - this.domElementRef.current = BDFDB.ReactUtils.findDOMNode(this); - } - onDocumentClicked() { - const node = BDFDB.ReactUtils.findDOMNode(this.popout); - if (!node || !document.contains(node) || node != event.target && document.contains(event.target) && !node.contains(event.target)) this.toggle(); - } - toggle() { - this.props.open = !this.props.open; - BDFDB.ReactUtils.forceUpdate(this); - } - render() { - const 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); - const childProps = Object.assign({}, child.props); - child.props.onClick = (e, childThis) => { - if ((this.props.openOnClick || this.props.openOnClick === undefined)) this.toggle(); - if (typeof this.props.onClick == "function") this.props.onClick(e, this); - if (typeof childProps.onClick == "function") childProps.onClick(e, childThis); - }; - child.props.onContextMenu = (e, childThis) => { - if (this.props.openOnContextMenu) this.toggle(); - if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this); - if (typeof childProps.onContextMenu == "function") childProps.onContextMenu(e, childThis); - }; - return BDFDB.ReactUtils.createElement(LibraryModules.React.Fragment, { - onClick: this.toggle, - children: [ - child, - this.props.open && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AppReferencePositionLayer, { - onMount: _ => BDFDB.TimeUtils.timeout(_ => document.addEventListener("click", this.onDocumentClicked)), - onUnmount: _ => document.removeEventListener("click", this.onDocumentClicked), - position: this.props.position, - align: this.props.align, - reference: this.domElementRef, - children: _ => { - const popout = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Popout, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { - className: this.props.popoutClassName, - containerInstance: this, - position: this.props.position, - style: this.props.popoutStyle, - onOpen: typeof this.props.onOpen == "function" ? this.props.onOpen.bind(this) : _ => {}, - onClose: typeof this.props.onClose == "function" ? this.props.onClose.bind(this) : _ => {}, - children: typeof this.props.renderPopout == "function" ? this.props.renderPopout(this) : null - }), "popoutStyle", "popoutClassName", "shouldShow", "changing", "renderPopout", "openOnClick", "onClick", "openOnContextMenu", "onContextMenu")); - const animation = Object.entries(InternalComponents.LibraryComponents.PopoutContainer.Animation).find(n => n[1] == this.props.animation); - return !animation || this.props.animation == InternalComponents.LibraryComponents.PopoutContainer.Animation.NONE ? popout : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutCSSAnimator, { - position: this.props.position, - type: InternalComponents.LibraryComponents.PopoutCSSAnimator.Types[animation[0]], - children: popout - }); - } - }) - ] - }); - } - }; - 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, _ => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Menu, { - navId: "bdfdb-quickselect", - onClose: 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("div", { - className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.selectwrapper), - children: BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.SearchableSelect, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { - className: this.props.inputClassName, - autoFocus: this.props.autoFocus ? this.props.autoFocus : false, - maxVisibleItems: this.props.maxVisibleItems || 7, - renderOptionLabel: this.props.optionRenderer, - onChange: this.handleChange.bind(this) - }), "inputClassName", "optionRenderer")) - }); - } - }; - - 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(InternalComponents.LibraryComponents.Flex, { - className: this.props.className, - wrap: InternalComponents.LibraryComponents.Flex.Wrap.WRAP, - children: [this.props.includeDMs && {name: BDFDB.LanguageUtils.LanguageStrings.DIRECT_MESSAGES, acronym: "DMs", id: BDFDB.DiscordConstants.ME, getIconURL: _ => {}}].concat(LibraryModules.FolderStore.getFlattenedGuilds()).filter(n => n).map(guild => BDFDB.ReactUtils.createElement(InternalComponents.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(InternalComponents.LibraryComponents.GuildComponents.Icon, { - guild: guild, - size: this.props.size || InternalComponents.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 { - componentDidMount() { - this.props._instance = this; - let node = BDFDB.ReactUtils.findDOMNode(this); - if (node) this.props._node = node; - } - componentWillUnmount() { - if (BDFDB.ObjectUtils.is(this.props.addon) && typeof this.props.addon.onSettingsClosed == "function") this.props.addon.onSettingsClosed(); - } - render() { - let panelItems = [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AutoFocusCatcher, {}), - typeof this.props.children == "function" ? (_ => { - return this.props.children(this.props.collapseStates); - })() : this.props.children - ].flat(10).filter(n => n); - - return BDFDB.ReactUtils.createElement("div", { - key: this.props.addon && this.props.addon.name && `${this.props.addon.name}-settingsPanel`, - id: this.props.addon && this.props.addon.name && `${this.props.addon.name}-settings`, - className: BDFDB.disCN.settingspanel, - children: panelItems - }); - } - }; - - InternalComponents.LibraryComponents.SettingsPanelList = InternalComponents.LibraryComponents.SettingsPanelInner = reactInitialized && class BDFDB_SettingsPanelInner extends LibraryModules.React.Component { - render() { - return this.props.children ? BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingspanellistwrapper, this.props.mini && BDFDB.disCN.settingspanellistwrappermini), - children: [ - this.props.dividerTop ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { - className: this.props.mini ? BDFDB.disCN.marginbottom4 : 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("div", { - className: BDFDB.disCN.settingspanellist, - children: this.props.children - }), - this.props.dividerBottom ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { - className: this.props.mini ? BDFDB.disCN.margintop4 : BDFDB.disCN.margintop8 - }) : 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; - let label = 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.SettingsLabel, { - className: BDFDB.DOMUtils.formatClassName(this.props.labelClassName), - mini: this.props.mini, - label: this.props.label - })) : null; - let margin = this.props.margin != null ? this.props.margin : (this.props.mini ? 0 : 8); - return BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingsrow, BDFDB.disCN.settingsrowcontainer, this.props.disabled && BDFDB.disCN.settingsrowdisabled, margin != null && (DiscordClasses[`marginbottom${margin}`] && BDFDB.disCN[`marginbottom${margin}`] || margin == 0 && BDFDB.disCN.marginreset)), - id: this.props.id, - 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("div", { - className: BDFDB.disCN.settingsrowlabel, - children: [ - label && !this.props.basis ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { - grow: 1, - shrink: 1, - wrap: true, - children: label - }) : label, - this.props.labelChildren, - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { - className: BDFDB.disCNS.settingsrowcontrol + BDFDB.disCN.flexchild, - 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) - }), "basis", "margin", "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.settingsrownote, - 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, BDFDB.disCN.settingsrowtitle, this.props.mini ? BDFDB.disCN.settingsrowtitlemini : BDFDB.disCN.settingsrowtitledefault, BDFDB.disCN.cursordefault), - speed: 2, - children: this.props.label - }); - } - }; - - InternalComponents.LibraryComponents.SettingsList = reactInitialized && class BDFDB_SettingsList extends LibraryModules.React.Component { - componentDidMount() { - this.checkList(); - } - componentDidUpdate() { - this.checkList(); - } - checkList() { - let list = BDFDB.ReactUtils.findDOMNode(this); - if (list && !this.props.configWidth) { - let headers = Array.from(list.querySelectorAll(BDFDB.dotCN.settingstableheader)); - headers.shift(); - if (BDFDB.DOMUtils.getRects(headers[0]).width == 0) BDFDB.TimeUtils.timeout(_ => {this.resizeList(headers);}); - else this.resizeList(headers); - } - } - resizeList(headers) { - let configWidth = 0, biggestWidth = 0; - if (!configWidth) { - for (let header of headers) { - header.style = ""; - let width = BDFDB.DOMUtils.getRects(header).width; - configWidth = width > configWidth ? width : configWidth; - } - configWidth += 4; - biggestWidth = configWidth; - } - if (headers.length * configWidth > 300) { - this.props.vertical = true; - configWidth = parseInt(290 / headers.length); - } - else if (configWidth < 36) { - configWidth = 36; - biggestWidth = configWidth; - } - this.props.configWidth = configWidth; - this.props.biggestWidth = biggestWidth; - BDFDB.ReactUtils.forceUpdate(this); - } - renderHeaderOption(props) { - return BDFDB.ReactUtils.createElement("div", { - className: BDFDB.DOMUtils.formatClassName(props.className, BDFDB.disCN.colorbase, BDFDB.disCN.size10, props.clickable && BDFDB.disCN.cursorpointer), - onClick: _ => {if (typeof this.props.onHeaderClick == "function") this.props.onHeaderClick(props.label, this);}, - onContextMenu: _ => {if (typeof this.props.onHeaderContextMenu == "function") this.props.onHeaderContextMenu(props.label, this);}, - children: BDFDB.ReactUtils.createElement("span", { - children: props.label - }) - }); - } - renderItem(props) { - return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Card, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { - className: BDFDB.DOMUtils.formatClassName([this.props.cardClassName, props.className].filter(n => n).join(" ").indexOf(BDFDB.disCN.card) == -1 && BDFDB.disCN.cardprimaryoutline, BDFDB.disCN.settingstablecard, this.props.cardClassName, props.className), - cardId: props.key, - backdrop: false, - horizontal: true, - style: Object.assign({}, this.props.cardStyle, props.style), - children: [ - BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.settingstablecardlabel, - children: this.props.renderLabel(props) - }), - BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.settingstablecardconfigs, - style: { - width: props.wrapperWidth || null, - minWidth: props.wrapperWidth || null, - maxWidth: props.wrapperWidth || null - }, - children: this.props.settings.map(setting => BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.checkboxcontainer, - children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Checkbox, { - disabled: props.disabled, - cardId: props.key, - settingId: setting, - shape: InternalComponents.LibraryComponents.Checkbox.Shapes && InternalComponents.LibraryComponents.Checkbox.Shapes.ROUND, - type: InternalComponents.LibraryComponents.Checkbox.Types && InternalComponents.LibraryComponents.Checkbox.Types.INVERTED, - color: this.props.checkboxColor, - getColor: this.props.getCheckboxColor, - value: props[setting], - getValue: this.props.getCheckboxValue, - onChange: this.props.onCheckboxChange - }) - })).flat(10).filter(n => n) - }) - ] - }), "title", "data", "settings", "renderLabel", "cardClassName", "cardStyle", "checkboxColor", "getCheckboxColor", "getCheckboxValue", "onCheckboxChange", "configWidth", "biggestWidth", "pagination")); - } - 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 wrapperWidth = this.props.configWidth && this.props.configWidth * this.props.settings.length; - let isHeaderClickable = typeof this.props.onHeaderClick == "function" || typeof this.props.onHeaderContextMenu == "function"; - let usePagination = BDFDB.ObjectUtils.is(this.props.pagination); - - let header = BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.settingstableheaders, - style: this.props.vertical && this.props.biggestWidth ? { - marginTop: this.props.biggestWidth - 15 || 0 - } : {}, - children: [ - this.renderHeaderOption({ - className: BDFDB.disCN.settingstableheadername, - clickable: this.props.title && isHeaderClickable, - label: this.props.title || "" - }), - BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.settingstableheaderoptions, - style: { - width: wrapperWidth || null, - minWidth: wrapperWidth || null, - maxWidth: wrapperWidth || null - }, - children: this.props.settings.map(setting => this.renderHeaderOption({ - className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.settingstableheaderoption, this.props.vertical && BDFDB.disCN.settingstableheadervertical), - clickable: isHeaderClickable, - label: setting - })) - }) - ] - }); - 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(data => this.renderItem(Object.assign({}, data, {wrapperWidth}))) : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PaginatedList, Object.assign({}, this.props.pagination, { - header: header, - items: this.props.data, - renderItem: data => this.renderItem(Object.assign({}, data, {wrapperWidth})), - 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 newC = ""; - for (let key of keys) newC += `{"${key}":`; - value = value != null && value.value != null ? value.value : value; - let isString = typeof value == "string"; - let marker = isString ? `"` : ``; - newC += (marker + (isString ? value.replace(/\\/g, "\\\\") : value) + marker) + "}".repeat(keys.length); - newC = JSON.parse(newC); - newC = BDFDB.ObjectUtils.is(newC) ? BDFDB.ObjectUtils.deepAssign({}, data, newC) : newC; - BDFDB.DataUtils.save(newC, this.props.plugin, option); - if (!this.props.plugin.settings) this.props.plugin.settings = {}; - this.props.plugin.settings[option] = newC; - 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.Scrollers.Thin, { - 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.Scrollers.Thin, { - 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, digits: 3}); - - InternalComponents.LibraryComponents.SvgIcon = reactInitialized && class BDFDB_Icon extends LibraryModules.React.Component { - render() { - if (BDFDB.ObjectUtils.is(this.props.name)) { - let calcClassName = []; - if (BDFDB.ObjectUtils.is(this.props.name.getClassName)) for (let path in this.props.name.getClassName) { - if (!path || BDFDB.ObjectUtils.get(this, path)) calcClassName.push(BDFDB.disCN[this.props.name.getClassName[path]]); - } - if (calcClassName.length || 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(calcClassName, 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 = InternalData.SvgIcons || {}; - - const SwitchIconPaths = { - a: { - TOP: "M5.13231 6.72963L6.7233 5.13864L14.855 13.2704L13.264 14.8614L5.13231 6.72963Z", - BOTTOM: "M13.2704 5.13864L14.8614 6.72963L6.72963 14.8614L5.13864 13.2704L13.2704 5.13864Z" - }, - b: { - TOP: "M6.56666 11.0013L6.56666 8.96683L13.5667 8.96683L13.5667 11.0013L6.56666 11.0013Z", - BOTTOM: "M13.5582 8.96683L13.5582 11.0013L6.56192 11.0013L6.56192 8.96683L13.5582 8.96683Z" - }, - c: { - TOP: "M7.89561 14.8538L6.30462 13.2629L14.3099 5.25755L15.9009 6.84854L7.89561 14.8538Z", - BOTTOM: "M4.08643 11.0903L5.67742 9.49929L9.4485 13.2704L7.85751 14.8614L4.08643 11.0903Z" - } - }; - const SwitchInner = function (props) { - let reducedMotion = BDFDB.ReactUtils.useContext(LibraryModules.PreferencesContext.AccessibilityPreferencesContext).reducedMotion; - let ref = BDFDB.ReactUtils.useRef(null); - let state = BDFDB.ReactUtils.useState(false); - let animation = InternalComponents.LibraryComponents.Animations.useSpring({ - config: { - mass: 1, - tension: 250 - }, - opacity: props.disabled ? .3 : 1, - state: state[0] ? (props.value ? .7 : .3) : (props.value ? 1 : 0) - }); - let fill = animation.state.to({ - output: [props.uncheckedColor, props.checkedColor] - }); - let mini = props.size == InternalComponents.LibraryComponents.Switch.Sizes.MINI; - - return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.div, { - className: BDFDB.DOMUtils.formatClassName(props.className, BDFDB.disCN.switch, mini && BDFDB.disCN.switchmini), - onMouseDown: _ => { - return !props.disabled && state[1](true); - }, - onMouseUp: _ => { - return state[1](false); - }, - onMouseLeave: _ => { - return state[1](false); - }, - style: { - opacity: animation.opacity, - backgroundColor: animation.state.to({ - output: [props.uncheckedColor, props.checkedColor] - }) - }, - tabIndex: -1, - children: [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.svg, { - className: BDFDB.disCN.switchslider, - viewBox: "0 0 28 20", - preserveAspectRatio: "xMinYMid meet", - style: { - left: animation.state.to({ - range: [0, .3, .7, 1], - output: mini ? [-1, 2, 6, 9] : [-3, 1, 8, 12] - }) - }, - children: [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.rect, { - fill: "white", - x: animation.state.to({ - range: [0, .3, .7, 1], - output: [4, 0, 0, 4] - }), - y: animation.state.to({ - range: [0, .3, .7, 1], - output: [0, 1, 1, 0] - }), - height: animation.state.to({ - range: [0, .3, .7, 1], - output: [20, 18, 18, 20] - }), - width: animation.state.to({ - range: [0, .3, .7, 1], - output: [20, 28, 28, 20] - }), - rx: "10" - }), - BDFDB.ReactUtils.createElement("svg", { - viewBox: "0 0 20 20", - fill: "none", - children: [ - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.path, { - fill: fill, - d: animation.state.to({ - range: [0, .3, .7, 1], - output: reducedMotion.enabled ? [SwitchIconPaths.a.TOP, SwitchIconPaths.a.TOP, SwitchIconPaths.c.TOP, SwitchIconPaths.c.TOP] : [SwitchIconPaths.a.TOP, SwitchIconPaths.b.TOP, SwitchIconPaths.b.TOP, SwitchIconPaths.c.TOP] - }) - }), - BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.path, { - fill: fill, - d: animation.state.to({ - range: [0, .3, .7, 1], - output: reducedMotion.enabled ? [SwitchIconPaths.a.BOTTOM, SwitchIconPaths.a.BOTTOM, SwitchIconPaths.c.BOTTOM, SwitchIconPaths.c.BOTTOM] : [SwitchIconPaths.a.BOTTOM, SwitchIconPaths.b.BOTTOM, SwitchIconPaths.b.BOTTOM, SwitchIconPaths.c.BOTTOM] - }) - }) - ] - }) - ] - }), - BDFDB.ReactUtils.createElement("input", BDFDB.ObjectUtils.exclude(Object.assign({}, props, { - id: props.id, - type: "checkbox", - ref: ref, - className: BDFDB.DOMUtils.formatClassName(props.inputClassName, BDFDB.disCN.switchinner), - tabIndex: props.disabled ? -1 : 0, - onKeyDown: e => { - if (!props.disabled && !e.repeat && (e.key == " " || e.key == "Enter")) state[1](true); - }, - onKeyUp: e => { - if (!props.disabled && !e.repeat) { - state[1](false); - if (e.key == "Enter" && ref.current) ref.current.click(); } }, - onChange: e => { - state[1](false); - if (typeof props.onChange == "function") props.onChange(e.currentTarget.checked, e); - }, - checked: props.value, - disabled: props.disabled - }), "uncheckedColor", "checkedColor", "size", "value")) - ] - }); - }; - 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(SwitchInner, Object.assign({}, this.props, { - onChange: this.handleChange.bind(this) - })); - } - }; - InternalComponents.LibraryComponents.Switch.Sizes = { - DEFAULT: "default", - MINI: "mini", - }; - InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Switch, { - size: InternalComponents.LibraryComponents.Switch.Sizes.DEFAULT, - uncheckedColor: BDFDB.DiscordConstants.Colors.PRIMARY_DARK_400, - checkedColor: BDFDB.DiscordConstants.Colors.BRAND - }); - - 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(this.pressedTimeout); - this.pressedTimeout = BDFDB.TimeUtils.timeout(_ => { - delete this.props.focused; - BDFDB.ReactUtils.forceUpdate(this); - }, 1000); - this.props.focused = true; - this.handleChange.apply(this, [value]); - this.handleInput.apply(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.apply(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, - style: this.props.width ? {width: `${this.props.width}px`} : {}, - ref: this.props.inputRef - }), "errorMessage", "focused", "error", "success", "inputClassName", "inputChildren", "valuePrefix", "inputPrefix", "size", "editable", "inputRef", "style", "mode", "colorPickerOpen", "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.apply(this, [!color ? "" : (this.props.mode == "comp" ? BDFDB.ColorUtils.convert(color, "RGBCOMP").slice(0, 3).join(",") : BDFDB.ColorUtils.convert(color, this.props.noAlpha ? "RGB" : "RGBA"))]), - pickerOpen: this.props.colorPickerOpen, - onPickerOpen: _ => this.props.colorPickerOpen = true, - onPickerClose: _ => delete this.props.colorPickerOpen, - ref: this.props.controlsRef, - 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, - ref: this.props.controlsRef - }) : 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); + children: this.props.items.map(item => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Badges.TextBadge, { + className: BDFDB.disCN.inputlistitem, + color: "var(--bdfdb-blurple)", + style: {borderRadius: "3px"}, + text: [ + item, + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + className: BDFDB.disCN.inputlistdelete, + name: InternalComponents.LibraryComponents.SvgIcon.Names.CLOSE, + onClick: _ => { + BDFDB.ArrayUtils.remove(this.props.items, item); + BDFDB.ReactUtils.forceUpdate(this); + this.handleChange.apply(this, []); } }) ] - }) : 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.margintop8, - 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() { - let scrolling, scroll = _ => {}; - 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 => { - const ele = BDFDB.ReactUtils.findDOMNode(instance); - if (ele && ele.parentElement) { - const maxWidth = BDFDB.DOMUtils.getInnerWidth(ele.parentElement); - if (maxWidth > 50) ele.style.setProperty("max-width", `${maxWidth}px`); - if (!this.props.initiated) BDFDB.TimeUtils.timeout(_ => { - this.props.initiated = true; - if (document.contains(ele.parentElement)) BDFDB.ReactUtils.forceUpdate(this); - }, 3000); - const 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("display", v.value == 0 ? "inline" : "block", "important"); - ele.firstElementChild.style.setProperty("left", `${v.value}px`, "important"); - }); - scroll = p => { - const display = ele.firstElementChild.style.getPropertyValue("display"); - ele.firstElementChild.style.setProperty("display", "inline", "important"); - const innerWidth = BDFDB.DOMUtils.getRects(ele.firstElementChild).width; - const outerWidth = BDFDB.DOMUtils.getRects(ele).width; - ele.firstElementChild.style.setProperty("display", display, "important"); - - let w = p + parseFloat(ele.firstElementChild.style.getPropertyValue("left")) / (innerWidth - outerWidth); - w = isNaN(w) || !isFinite(w) ? p : w; - w *= innerWidth / (outerWidth * 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 || e.currentTarget.firstElementChild.style.getPropertyValue("display") != "inline") { - scrolling = true; - scroll(1); - } - }, - onMouseLeave: e => { - if (scrolling) { - scrolling = false; - 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 = (typeof this.props.children == "function" ? this.props.children() : (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 childProps = Object.assign({}, child.props); - let shown = false; - child.props.onMouseEnter = (e, childThis) => { - if (!shown && !e.currentTarget.BDFDBtooltipShown && !(this.props.onlyShowOnShift && !e.shiftKey) && !(this.props.onlyShowOnCtrl && !e.ctrlKey)) { - e.currentTarget.BDFDBtooltipShown = shown = true; - this.tooltip = BDFDB.TooltipUtils.create(e.currentTarget, typeof this.props.text == "function" ? this.props.text(this, e) : this.props.text, Object.assign({ - note: this.props.note, - delay: this.props.delay - }, this.props.tooltipConfig, { - onHide: (tooltip, anker) => { - delete anker.BDFDBtooltipShown; - shown = false; - if (this.props.tooltipConfig && typeof this.props.tooltipConfig.onHide == "function") this.props.tooltipConfig.onHide(tooltip, anker); - } - })); - if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this); - if (typeof childProps.onMouseEnter == "function") childProps.onMouseEnter(e, childThis); - } - }; - child.props.onMouseLeave = (e, childThis) => { - if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this); - if (typeof childProps.onMouseLeave == "function") childProps.onMouseLeave(e, childThis); - }; - child.props.onClick = (e, childThis) => { - if (typeof this.props.onClick == "function") this.props.onClick(e, this); - if (typeof childProps.onClick == "function") childProps.onClick(e, childThis); - if (typeof this.props.text == "function") this.updateTooltip(this.props.text(this, e)); - }; - child.props.onContextMenu = (e, childThis) => { - if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this); - if (typeof childProps.onContextMenu == "function") childProps.onContextMenu(e, childThis); - if (typeof this.props.text == "function") this.updateTooltip(this.props.text(this, e)); - }; - 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 => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.UserPopout, { - userId: this.props.userId, - channelId: this.props.channelId, - guildId: this.props.guildId - }), - }), "userId", "channelId", "guildId")); - } - }; - - const VideoInner = function (props) { - let ref = BDFDB.ReactUtils.useRef(null); - BDFDB.ReactUtils.useEffect(_ => { - if (ref.current) props.play ? ref.current.play() : ref.current.pause(); - }, [props.play]); - return props.naturalWidth <= BDFDB.DiscordConstants.MAX_VIDEO_WIDTH && props.naturalHeight <= BDFDB.DiscordConstants.MAX_VIDEO_HEIGHT || props.naturalWidth <= BDFDB.DiscordConstants.MAX_VIDEO_HEIGHT && props.naturalHeight <= BDFDB.DiscordConstants.MAX_VIDEO_WIDTH ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.VideoForwardRef, { - ref: ref, - className: props.className, - poster: props.poster, - src: props.src, - width: props.width, - height: props.height, - muted: true, - loop: true, - autoPlay: props.play, - preload: "none" - }) : BDFDB.ReactUtils.createElement("img", { - alt: "", - src: props.poster, - width: props.width, - height: props.height - }); - }; - InternalComponents.LibraryComponents.Video = reactInitialized && class BDFDB_Video extends LibraryModules.React.Component { - render() { - return BDFDB.ReactUtils.createElement(VideoInner, this.props); - } - }; - - 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 if (!InternalComponents.LibraryComponents[type][key]) InternalComponents.LibraryComponents[type][key] = InternalComponents.NativeSubComponents[type][key]; - } - BDFDB.LibraryComponents = Object.assign({}, InternalComponents.LibraryComponents); - - InternalBDFDB.createCustomControl = function (data) { - let controlButton = BDFDB.DOMUtils.create(``); - BDFDB.ReactUtils.render(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { - nativeClass: true, - name: data.svgName, - width: 20, - height: 20 - }), controlButton); - controlButton.addEventListener("click", _ => {if (typeof data.onClick == "function") data.onClick();}); - if (data.tooltipText) controlButton.addEventListener("mouseenter", _ => {BDFDB.TooltipUtils.create(controlButton, data.tooltipText);}); - return controlButton; - }; - InternalBDFDB.appendCustomControls = function (card) { - if (!card || card.querySelector(BDFDB.dotCN._repocontrolscustom)) return; - let checkbox = card.querySelector(BDFDB.dotCN._reposwitch); - if (!checkbox) return; - let props = BDFDB.ObjectUtils.get(BDFDB.ReactUtils.getInstance(card), "return.stateNode.props"); - let plugin = props && props.addon && (props.addon.plugin || props.addon.instance); - if (plugin && (plugin == libraryInstance || plugin.name && plugin.name && PluginStores.loaded[plugin.name] && PluginStores.loaded[plugin.name] == plugin)) { - let url = InternalBDFDB.getPluginURL(plugin); - let controls = []; - let footerControls = card.querySelector(BDFDB.dotCNS._repofooter + BDFDB.dotCN._repocontrols); - if (plugin.changeLog) controls.push(InternalBDFDB.createCustomControl({ - tooltipText: BDFDB.LanguageUtils.LanguageStrings.CHANGE_LOG, - svgName: InternalComponents.LibraryComponents.SvgIcon.Names.CHANGELOG, - onClick: _ => {BDFDB.PluginUtils.openChangeLog(plugin);} - })); - if (PluginStores.updateData.plugins[url] && PluginStores.updateData.plugins[url].outdated) controls.push(InternalBDFDB.createCustomControl({ - tooltipText: BDFDB.LanguageUtils.LanguageStrings.UPDATE_MANUALLY, - svgName: InternalComponents.LibraryComponents.SvgIcon.Names.DOWNLOAD, - onClick: _ => {BDFDB.PluginUtils.downloadUpdate(plugin.name, url);} - })); - if (footerControls) for (let control of controls) footerControls.insertBefore(control, footerControls.firstElementChild); - else for (let control of controls) checkbox.parentElement.insertBefore(control, checkbox.parentElement.firstElementChild); - } - }; - InternalBDFDB.addListObserver = function (layer) { - if (!layer) return; - BDFDB.ObserverUtils.connect(BDFDB, layer, {name: "cardObserver", instance: new MutationObserver(changes => {changes.forEach(change => {if (change.addedNodes) {change.addedNodes.forEach(n => { - if (BDFDB.DOMUtils.containsClass(n, BDFDB.disCN._repocard)) InternalBDFDB.appendCustomControls(n); - if (n.nodeType != Node.TEXT_NODE) for (let c of n.querySelectorAll(BDFDB.dotCN._repocard)) InternalBDFDB.appendCustomControls(c); - InternalBDFDB.appendCustomControls(BDFDB.DOMUtils.getParent(BDFDB.dotCN._repocard, n)); - });}});})}, {childList: true, subtree: true}); - for (let c of layer.querySelectorAll(BDFDB.dotCN._repocard)) InternalBDFDB.appendCustomControls(c); - } - - 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: { - SearchBar: "render", - EmojiPicker: "type", - EmojiPickerListRow: "default" - }, - after: { - useUserVolumeItem: "default", - useUserRolesItems : "default", - Menu: "default", - SettingsView: "componentDidMount", - Shakeable: "render", - Message: "default", - MessageHeader: "default", - MemberListItem: ["componentDidMount", "componentDidUpdate"], - PrivateChannel: ["componentDidMount", "componentDidUpdate"], - AnalyticsContext: ["componentDidMount", "componentDidUpdate"], - PeopleListItem: ["componentDidMount", "componentDidUpdate"], - DiscordTag: "default" - } - }; - - const menuExtraPatches = {}; - InternalBDFDB.processMenu = function (e) { - if (e.instance.props.navId) switch (e.instance.props.navId) { - case "guild-header-popout": - if (menuExtraPatches["guild-header-popout"]) return; - menuExtraPatches["guild-header-popout"] = true; - BDFDB.TimeUtils.interval((interval, count) => { - if (count > 20) return BDFDB.TimeUtils.clear(interval); - else { - let module = BDFDB.ModuleUtils.findByString("guild-header-popout"); - if (module) BDFDB.PatchUtils.patch(BDFDB, module.default.prototype, "render", {after: e => { - BDFDB.PatchUtils.patch(BDFDB, e.returnValue.type, "type", {after: e2 => { - InternalBDFDB.triggerQueuePatch("GuildHeaderContextMenu", { - arguments: e2.methodArguments, - instance: {props: e2.methodArguments[0]}, - returnvalue: e2.returnValue, - component: e.returnValue, - methodname: "type", - type: "GuildHeaderContextMenu" - }); - }}, {noCache: true}); - }}); - } - }, 500); - return; - case "dev-context": - if (menuExtraPatches["dev-context"]) return; - menuExtraPatches["dev-context"] = true; - BDFDB.PatchUtils.patch(BDFDB, (BDFDB.ModuleUtils.findByName("useCopyIdItem", false) || {}).exports, "default", {after: e => { - if (!e.returnValue) e.returnValue = false; - }}, {priority: 10}); - BDFDB.PatchUtils.patch(BDFDB, e.component, "default", {after: e => { - if (!e.returnValue.props.children) LibraryModules.ContextMenuUtils.closeContextMenu(); - }}, {priority: 10}); - return; - } - }; - + })) + }), "items")); + } + }; - InternalBDFDB.processSearchBar = function (e) { - if (typeof e.instance.props.query != "string") e.instance.props.query = ""; - }; - - InternalBDFDB.processSettingsView = function (e) { - if (e.node && e.node.parentElement && e.node.parentElement.getAttribute("aria-label") == BDFDB.DiscordConstants.Layers.USER_SETTINGS) InternalBDFDB.addListObserver(e.node.parentElement); - }; - - let AppViewExport = BDFDB.ModuleUtils.findByName("AppView", false); - if (AppViewExport) InternalBDFDB.processShakeable = function (e) { - let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {name: "AppView"}); - if (index > -1) children[index] = BDFDB.ReactUtils.createElement(AppViewExport.exports.default, children[index].props); - }; - - InternalBDFDB.processMessage = function (e) { - if (e.returnvalue && e.returnvalue.props && e.returnvalue.props.children && e.returnvalue.props.children.props) { - let message; - for (let key in e.instance.props) { - if (!message) message = BDFDB.ObjectUtils.get(e.instance.props[key], "props.message"); - else break; - } - if (message) { - e.returnvalue.props.children.props[InternalData.authorIdAttribute] = message.author.id; - if (LibraryModules.RelationshipStore.isFriend(message.author.id)) e.returnvalue.props.children.props[InternalData.authorFriendAttribute] = true; - if (message.author.id == BDFDB.UserUtils.me.id) e.returnvalue.props.children.props[InternalData.authorSelfAttribute] = true; - } - } - }; - - const BDFDB_Patrons = Object.assign({}, InternalData.BDFDB_Patrons), BDFDB_Patron_Tiers = Object.assign({}, InternalData.BDFDB_Patron_Tiers); - InternalBDFDB._processAvatarRender = function (user, avatar, className) { - if (BDFDB.ReactUtils.isValidElement(avatar) && BDFDB.ObjectUtils.is(user) && (avatar.props.className || "").indexOf(BDFDB.disCN.bdfdbbadgeavatar) == -1) { - avatar.props[InternalData.userIdAttribute] = user.id; - let role = "", note = "", color, link, addBadge = InternalBDFDB.settings.general.showSupportBadges; - if (BDFDB_Patrons[user.id] && BDFDB_Patrons[user.id].active) { - link = "https://www.patreon.com/MircoWittrien"; - role = BDFDB_Patrons[user.id].text || (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text; - note = BDFDB_Patrons[user.id].text && (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text; - color = BDFDB_Patrons[user.id].color; - className = BDFDB.DOMUtils.formatClassName(avatar.props.className, className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbsupporter, BDFDB.disCN[`bdfdbsupporter${BDFDB_Patrons[user.id].tier}`]); - } - if (user.id == InternalData.myId) { - addBadge = true; - role = `Theme ${BDFDB.LanguageUtils.LibraryStrings.developer}`; - className = BDFDB.DOMUtils.formatClassName(avatar.props.className, className, BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbdev); - } - if (role) { - delete avatar.props[InternalData.userIdAttribute]; - if (avatar.type == "img") avatar = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AvatarComponents.default, Object.assign({}, avatar.props, { - size: InternalComponents.LibraryComponents.AvatarComponents.Sizes.SIZE_40 - })); - delete avatar.props.className; - let newProps = { - className: className, - children: [avatar] + InternalComponents.LibraryComponents.PaginatedList = reactInitialized && class BDFDB_PaginatedList extends LibraryModules.React.Component { + constructor(props) { + super(props); + this.state = { + offset: props.offset }; - newProps[InternalData.userIdAttribute] = user.id; - avatar = BDFDB.ReactUtils.createElement("div", newProps); - if (addBadge) avatar.props.children.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { - text: role, - note: note, - tooltipConfig: {backgroundColor: color || ""}, - onClick: link ? (_ => BDFDB.DiscordUtils.openLink(link)) : (_ => {}), - children: BDFDB.ReactUtils.createElement("div", { - className: BDFDB.disCN.bdfdbbadge - }) - })); - return avatar; } - } - }; - InternalBDFDB._processAvatarMount = function (user, avatar, wrapper) { - if (!user) return; - if (wrapper) wrapper.setAttribute(InternalData.userIdAttribute, user.id); - if (Node.prototype.isPrototypeOf(avatar) && (avatar.className || "").indexOf(BDFDB.disCN.bdfdbbadgeavatar) == -1) { - avatar.setAttribute(InternalData.userIdAttribute, user.id); - let role = "", note = "", color, link, addBadge = InternalBDFDB.settings.general.showSupportBadges; - if (BDFDB_Patrons[user.id] && BDFDB_Patrons[user.id].active) { - link = "https://www.patreon.com/MircoWittrien"; - role = BDFDB_Patrons[user.id].text || (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text; - note = BDFDB_Patrons[user.id].text && (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text; - color = BDFDB_Patrons[user.id].color; - avatar.className = BDFDB.DOMUtils.formatClassName(avatar.className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbsupporter, BDFDB.disCN[`bdfdbsupporter${BDFDB_Patrons[user.id].tier}`]); - } - else if (user.id == InternalData.myId) { - addBadge = true; - role = `Theme ${BDFDB.LanguageUtils.LibraryStrings.developer}`; - avatar.className = BDFDB.DOMUtils.formatClassName(avatar.className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbdev); - } - if (addBadge && role && !avatar.querySelector(BDFDB.dotCN.bdfdbbadge)) { - let badge = document.createElement("div"); - badge.className = BDFDB.disCN.bdfdbbadge; - if (link) badge.addEventListener("click", _ => BDFDB.DiscordUtils.openLink(link)); - badge.addEventListener("mouseenter", _ => BDFDB.TooltipUtils.create(badge, role, {position: "top", note: note, backgroundColor: color || ""})); - avatar.appendChild(badge); - } - } - }; - InternalBDFDB._processUserInfoNode = function (user, wrapper) { - if (!user || !wrapper) return; - if (InternalData.UserBackgrounds[user.id]) for (let property in InternalData.UserBackgrounds[user.id]) wrapper.style.setProperty(property, InternalData.UserBackgrounds[user.id][property], "important"); - }; - 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 = BDFDB.TimeUtils.suppress((...args) => { - let renderedChildren = renderChildren(...args); - return InternalBDFDB._processAvatarRender(e.instance.props.message.author, renderedChildren, BDFDB.disCN.messageavatar) || renderedChildren; - }, "Error in Avatar Render of MessageHeader!"); - } - 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), e.node); - }; - InternalBDFDB.processPrivateChannel = function (e) { - InternalBDFDB._processAvatarMount(e.instance.props.user, e.node.querySelector(BDFDB.dotCN.avatarwrapper), e.node); - }; - InternalBDFDB.processAnalyticsContext = function (e) { - if (e.instance.props.section != BDFDB.DiscordConstants.AnalyticsSections.PROFILE_MODAL && e.instance.props.section != BDFDB.DiscordConstants.AnalyticsSections.PROFILE_POPOUT) return; - const user = BDFDB.ReactUtils.findValue(e.instance, "user"); - if (!user) return; - const wrapper = e.node.querySelector(BDFDB.dotCNC.userpopout + BDFDB.dotCN.userprofile) || e.node; - const avatar = e.node.querySelector(BDFDB.dotCN.avatarwrapper); - if (avatar) InternalBDFDB._processAvatarMount(user, e.instance.props.section == BDFDB.DiscordConstants.AnalyticsSections.PROFILE_POPOUT ? avatar.parentElement : avatar, wrapper); - InternalBDFDB._processUserInfoNode(user, wrapper); - }; - InternalBDFDB.processPeopleListItem = function (e) { - if (e.instance.props.user) e.node.setAttribute(InternalData.userIdAttribute, e.instance.props.user.id); - }; - 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.processEmojiPicker = function (e) { - if (BDFDB.ObjectUtils.toArray(PluginStores.loaded).filter(p => p.started).some(p => p.onSystemMessageOptionContextMenu || p.onSystemMessageOptionToolbar || p.onMessageOptionContextMenu || p.onMessageOptionToolbar)) e.instance.props.persistSearch = true; - }; - InternalBDFDB.processEmojiPickerListRow = function (e) { - if (e.instance.props.emojiDescriptors && InternalComponents.LibraryComponents.EmojiPickerButton.current && InternalComponents.LibraryComponents.EmojiPickerButton.current.props && InternalComponents.LibraryComponents.EmojiPickerButton.current.props.allowManagedEmojisUsage) for (let i in e.instance.props.emojiDescriptors) e.instance.props.emojiDescriptors[i] = Object.assign({}, e.instance.props.emojiDescriptors[i], {isDisabled: false}); - }; - - InternalBDFDB.addChunkObserver = function (pluginData, config) { - let module; - if (config.stringFind) module = BDFDB.ModuleUtils.findByString(config.stringFind, config.exported, true); - else if (config.propertyFind) module = BDFDB.ModuleUtils.findByProperties(config.propertyFind, config.exported, true); - else if (config.prototypeFind) module = BDFDB.ModuleUtils.findByPrototypes(config.prototypeFind, config.exported, true); - else module = BDFDB.ModuleUtils.findByName(config.name, config.exported, true); - if (module) { - let exports = !config.exported && module.exports || module; - exports = config.path && BDFDB.ObjectUtils.get(exports, config.path) || exports; - exports && InternalBDFDB.patchComponent(pluginData, InternalBDFDB.isMemoOrForwardRef(exports) ? exports.default : exports, config); - } - else { - if (!PluginStores.chunkObserver[config.mappedType]) { - PluginStores.chunkObserver[config.mappedType] = {query: [], config}; - let filter; - if (config.stringFind) filter = m => [config.stringFind].flat(10).filter(n => n).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) && m; - else if (config.propertyFind) filter = m => [config.propertyFind].flat(10).filter(n => n).every(prop => { - const value = m[prop]; - return value !== undefined && !(typeof value == "string" && !value); - }) && m; - else if (config.prototypeFind) filter = m => m.prototype && [config.prototypeFind].flat(10).filter(n => n).every(prop => { - const value = m.prototype[prop]; - return value !== undefined && !(typeof value == "string" && !value); - }) && m; - else filter = m => m.displayName === config.name && m || m.render && m.render.displayName === config.name && m || m[config.name] && m[config.name].displayName === name && m[config.name]; - PluginStores.chunkObserver[config.mappedType].filter = filter; - } - PluginStores.chunkObserver[config.mappedType].query.push(pluginData); - } - }; - const QueuedComponents = ["GuildHeaderContextMenu", "SystemMessageOptionContextMenu", "SystemMessageOptionToolbar", "MessageOptionContextMenu", "MessageOptionToolbar"]; - const ContextMenuTypes = ["UserSettingsCog", "UserProfileActions", "GroupDM", "DM", "User", "Developer", "Slate", "GuildSettingsRole", "GuildDirectoryEntry", "GuildFolder", "SystemMessage", "Message", "Native", "Role", "Guild", "Channel"]; - InternalBDFDB.addQueuePatches = function (plugin) { - plugin = plugin == BDFDB && InternalBDFDB || plugin; - for (let type of QueuedComponents) if (typeof plugin[`on${type}`] == "function") { - if (PluginStores.patchQueues[type].query.indexOf(plugin) == -1) { - PluginStores.patchQueues[type].query.push(plugin); - PluginStores.patchQueues[type].query.sort((x, y) => x.name < y.name ? -1 : x.name > y.name ? 1 : 0); - } - } - }; - InternalBDFDB.triggerQueuePatch = function (type, e) { - if (e.returnvalue && BDFDB.ObjectUtils.is(PluginStores.patchQueues[type]) && BDFDB.ArrayUtils.is(PluginStores.patchQueues[type].query)) { - for (let plugin of PluginStores.patchQueues[type].query) if(typeof plugin[`on${type}`] == "function") plugin[`on${type}`](e); - } - }; - InternalBDFDB.addContextChunkObservers = function (plugin) { - plugin = plugin == BDFDB && InternalBDFDB || plugin; - for (let type of ContextMenuTypes) { - type = `${type}ContextMenu`; - if (typeof plugin[`on${type}`] == "function") { - for (let module of PluginStores.contextChunkObserver[type].modules) InternalBDFDB.patchContextMenu(plugin, type, module); - if (PluginStores.contextChunkObserver[type].query.indexOf(plugin) == -1) { - PluginStores.contextChunkObserver[type].query.push(plugin); - PluginStores.contextChunkObserver[type].query.sort((x, y) => x.name < y.name ? -1 : x.name > y.name ? 1 : 0); + handleJump(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); } } - } - }; - InternalBDFDB.patchContextMenu = function (plugin, type, module) { - if (!module || !module.default) return; - plugin = plugin == BDFDB && InternalBDFDB || plugin; - const call = (args, props, returnValue, name) => { - if (!returnValue || !returnValue.props || !returnValue.props.children || returnValue.props.children.__BDFDBPatchesCalled && returnValue.props.children.__BDFDBPatchesCalled[plugin.name]) return; - returnValue.props.children.__BDFDBPatchesCalled = Object.assign({}, returnValue.props.children.__BDFDBPatchesCalled, {[plugin.name]: true}); - return plugin[`on${type}`]({ - arguments: args, - instance: {props: props}, - returnvalue: returnValue, - component: module, - methodname: "default", - type: name + renderPagination(bottom) { + 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.DOMUtils.formatClassName(BDFDB.disCN.pagination, bottom ? BDFDB.disCN.paginationbottom : BDFDB.disCN.paginationtop, this.props.mini && BDFDB.disCN.paginationmini), + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Paginator, { + totalCount: this.props.items.length, + currentPage: this.state.offset + 1, + pageSize: this.props.amount, + maxVisiblePages: this.props.maxVisiblePages, + onPageChange: page => {this.handleJump(isNaN(parseInt(page)) ? -1 : page - 1);} + }), + this.props.jump && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextInput, { + type: "number", + size: InternalComponents.LibraryComponents.TextInput.Sizes.MINI, + value: this.state.offset + 1, + min: 1, + max: maxOffset + 1, + onKeyDown: (event, instance) => {if (event.which == 13) this.handleJump(isNaN(parseInt(instance.props.value)) ? -1 : instance.props.value - 1);} + }), + ].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.Scrollers.Thin, { + 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(InternalComponents.LibraryComponents.Clickable, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.paginationlistalphabetchar, alphabet[key].disabled &&BDFDB.disCN.paginationlistalphabetchardisabled), + onClick: _ => {if (!alphabet[key].disabled) this.handleJump(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(true) + ].flat(10).filter(n => n) + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.PaginatedList, {amount: 50, offset: 0, mini: true, jump: true, maxVisiblePages: 7, copyToBottom: false, fade: true}); + + InternalComponents.LibraryComponents.Popout = reactInitialized && class BDFDB_Popout extends LibraryModules.React.Component { + componentDidMount() { + this.props.containerInstance.popout = this; + if (typeof this.props.onOpen == "function") this.props.onOpen(this.props.containerInstance, this); + } + componentWillUnmount() { + delete this.props.containerInstance.popout; + if (typeof this.props.onClose == "function") this.props.onClose(this.props.containerInstance, this); + } + render() { + if (!this.props.wrap) return this.props.children; + let pos = typeof this.props.position == "string" ? this.props.position.toLowerCase() : null; + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutFocusLock, { + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.popoutwrapper, this.props.className, this.props.themed && BDFDB.disCN.popoutthemedpopout, this.props.arrow && BDFDB.disCN.popoutarrow, this.props.arrow && (pos == "top" ? BDFDB.disCN.popoutarrowtop : BDFDB.disCN.popoutarrowbottom)), + id: this.props.id, + onClick: e => e.stopPropagation(), + style: BDFDB.ObjectUtils.extract(this.props, "padding", "height", "maxHeight", "minHeight", "width", "maxWidth", "minWidth"), + children: this.props.children + }); + } + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Popout, {themed: true, wrap: true}); + + InternalComponents.LibraryComponents.PopoutContainer = reactInitialized && class BDFDB_PopoutContainer extends LibraryModules.React.Component { + componentDidMount() { + this.toggle = this.toggle.bind(this); + this.onDocumentClicked = this.onDocumentClicked.bind(this); + this.domElementRef = BDFDB.ReactUtils.createRef(); + this.domElementRef.current = BDFDB.ReactUtils.findDOMNode(this); + } + onDocumentClicked() { + const node = BDFDB.ReactUtils.findDOMNode(this.popout); + if (!node || !document.contains(node) || node != event.target && document.contains(event.target) && !node.contains(event.target)) this.toggle(); + } + toggle() { + this.props.open = !this.props.open; + BDFDB.ReactUtils.forceUpdate(this); + } + render() { + const 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); + const childProps = Object.assign({}, child.props); + child.props.onClick = (e, childThis) => { + if ((this.props.openOnClick || this.props.openOnClick === undefined)) this.toggle(); + if (typeof this.props.onClick == "function") this.props.onClick(e, this); + if (typeof childProps.onClick == "function") childProps.onClick(e, childThis); + }; + child.props.onContextMenu = (e, childThis) => { + if (this.props.openOnContextMenu) this.toggle(); + if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this); + if (typeof childProps.onContextMenu == "function") childProps.onContextMenu(e, childThis); + }; + return BDFDB.ReactUtils.createElement(LibraryModules.React.Fragment, { + onClick: this.toggle, + children: [ + child, + this.props.open && BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AppReferencePositionLayer, { + onMount: _ => BDFDB.TimeUtils.timeout(_ => document.addEventListener("click", this.onDocumentClicked)), + onUnmount: _ => document.removeEventListener("click", this.onDocumentClicked), + position: this.props.position, + align: this.props.align, + reference: this.domElementRef, + children: _ => { + const popout = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Popout, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: this.props.popoutClassName, + containerInstance: this, + position: this.props.position, + style: this.props.popoutStyle, + onOpen: typeof this.props.onOpen == "function" ? this.props.onOpen.bind(this) : _ => {}, + onClose: typeof this.props.onClose == "function" ? this.props.onClose.bind(this) : _ => {}, + children: typeof this.props.renderPopout == "function" ? this.props.renderPopout(this) : null + }), "popoutStyle", "popoutClassName", "shouldShow", "changing", "renderPopout", "openOnClick", "onClick", "openOnContextMenu", "onContextMenu")); + const animation = Object.entries(InternalComponents.LibraryComponents.PopoutContainer.Animation).find(n => n[1] == this.props.animation); + return !animation || this.props.animation == InternalComponents.LibraryComponents.PopoutContainer.Animation.NONE ? popout : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PopoutCSSAnimator, { + position: this.props.position, + type: InternalComponents.LibraryComponents.PopoutCSSAnimator.Types[animation[0]], + children: popout + }); + } + }) + ] + }); + } + }; + 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, _ => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Menu, { + navId: "bdfdb-quickselect", + onClose: 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("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.selectwrapper), + children: BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.SearchableSelect, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: this.props.inputClassName, + autoFocus: this.props.autoFocus ? this.props.autoFocus : false, + maxVisibleItems: this.props.maxVisibleItems || 7, + renderOptionLabel: this.props.optionRenderer, + onChange: this.handleChange.bind(this) + }), "inputClassName", "optionRenderer")) + }); + } + }; + + 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(InternalComponents.LibraryComponents.Flex, { + className: this.props.className, + wrap: InternalComponents.LibraryComponents.Flex.Wrap.WRAP, + children: [this.props.includeDMs && {name: BDFDB.LanguageUtils.LanguageStrings.DIRECT_MESSAGES, acronym: "DMs", id: BDFDB.DiscordConstants.ME, getIconURL: _ => {}}].concat(LibraryModules.FolderStore.getFlattenedGuilds()).filter(n => n).map(guild => BDFDB.ReactUtils.createElement(InternalComponents.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(InternalComponents.LibraryComponents.GuildComponents.Icon, { + guild: guild, + size: this.props.size || InternalComponents.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 { + componentDidMount() { + this.props._instance = this; + let node = BDFDB.ReactUtils.findDOMNode(this); + if (node) this.props._node = node; + } + componentWillUnmount() { + if (BDFDB.ObjectUtils.is(this.props.addon) && typeof this.props.addon.onSettingsClosed == "function") this.props.addon.onSettingsClosed(); + } + render() { + let panelItems = [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AutoFocusCatcher, {}), + typeof this.props.children == "function" ? (_ => { + return this.props.children(this.props.collapseStates); + })() : this.props.children + ].flat(10).filter(n => n); + + return BDFDB.ReactUtils.createElement("div", { + key: this.props.addon && this.props.addon.name && `${this.props.addon.name}-settingsPanel`, + id: this.props.addon && this.props.addon.name && `${this.props.addon.name}-settings`, + className: BDFDB.disCN.settingspanel, + children: panelItems + }); + } + }; + + InternalComponents.LibraryComponents.SettingsPanelList = InternalComponents.LibraryComponents.SettingsPanelInner = reactInitialized && class BDFDB_SettingsPanelInner extends LibraryModules.React.Component { + render() { + return this.props.children ? BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingspanellistwrapper, this.props.mini && BDFDB.disCN.settingspanellistwrappermini), + children: [ + this.props.dividerTop ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { + className: this.props.mini ? BDFDB.disCN.marginbottom4 : 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("div", { + className: BDFDB.disCN.settingspanellist, + children: this.props.children + }), + this.props.dividerBottom ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.FormComponents.FormDivider, { + className: this.props.mini ? BDFDB.disCN.margintop4 : BDFDB.disCN.margintop8 + }) : 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; + let label = 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.SettingsLabel, { + className: BDFDB.DOMUtils.formatClassName(this.props.labelClassName), + mini: this.props.mini, + label: this.props.label + })) : null; + let margin = this.props.margin != null ? this.props.margin : (this.props.mini ? 0 : 8); + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(this.props.className, BDFDB.disCN.settingsrow, BDFDB.disCN.settingsrowcontainer, this.props.disabled && BDFDB.disCN.settingsrowdisabled, margin != null && (DiscordClasses[`marginbottom${margin}`] && BDFDB.disCN[`marginbottom${margin}`] || margin == 0 && BDFDB.disCN.marginreset)), + id: this.props.id, + 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("div", { + className: BDFDB.disCN.settingsrowlabel, + children: [ + label && !this.props.basis ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + grow: 1, + shrink: 1, + wrap: true, + children: label + }) : label, + this.props.labelChildren, + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + className: BDFDB.disCNS.settingsrowcontrol + BDFDB.disCN.flexchild, + 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) + }), "basis", "margin", "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.settingsrownote, + 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, BDFDB.disCN.settingsrowtitle, this.props.mini ? BDFDB.disCN.settingsrowtitlemini : BDFDB.disCN.settingsrowtitledefault, BDFDB.disCN.cursordefault), + speed: 2, + children: this.props.label + }); + } + }; + + InternalComponents.LibraryComponents.SettingsList = reactInitialized && class BDFDB_SettingsList extends LibraryModules.React.Component { + componentDidMount() { + this.checkList(); + } + componentDidUpdate() { + this.checkList(); + } + checkList() { + let list = BDFDB.ReactUtils.findDOMNode(this); + if (list && !this.props.configWidth) { + let headers = Array.from(list.querySelectorAll(BDFDB.dotCN.settingstableheader)); + headers.shift(); + if (BDFDB.DOMUtils.getRects(headers[0]).width == 0) BDFDB.TimeUtils.timeout(_ => {this.resizeList(headers);}); + else this.resizeList(headers); + } + } + resizeList(headers) { + let configWidth = 0, biggestWidth = 0; + if (!configWidth) { + for (let header of headers) { + header.style = ""; + let width = BDFDB.DOMUtils.getRects(header).width; + configWidth = width > configWidth ? width : configWidth; + } + configWidth += 4; + biggestWidth = configWidth; + } + if (headers.length * configWidth > 300) { + this.props.vertical = true; + configWidth = parseInt(290 / headers.length); + } + else if (configWidth < 36) { + configWidth = 36; + biggestWidth = configWidth; + } + this.props.configWidth = configWidth; + this.props.biggestWidth = biggestWidth; + BDFDB.ReactUtils.forceUpdate(this); + } + renderHeaderOption(props) { + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.DOMUtils.formatClassName(props.className, BDFDB.disCN.colorbase, BDFDB.disCN.size10, props.clickable && BDFDB.disCN.cursorpointer), + onClick: _ => {if (typeof this.props.onHeaderClick == "function") this.props.onHeaderClick(props.label, this);}, + onContextMenu: _ => {if (typeof this.props.onHeaderContextMenu == "function") this.props.onHeaderContextMenu(props.label, this);}, + children: BDFDB.ReactUtils.createElement("span", { + children: props.label + }) + }); + } + renderItem(props) { + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Card, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, { + className: BDFDB.DOMUtils.formatClassName([this.props.cardClassName, props.className].filter(n => n).join(" ").indexOf(BDFDB.disCN.card) == -1 && BDFDB.disCN.cardprimaryoutline, BDFDB.disCN.settingstablecard, this.props.cardClassName, props.className), + cardId: props.key, + backdrop: false, + horizontal: true, + style: Object.assign({}, this.props.cardStyle, props.style), + children: [ + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.settingstablecardlabel, + children: this.props.renderLabel(props) + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.settingstablecardconfigs, + style: { + width: props.wrapperWidth || null, + minWidth: props.wrapperWidth || null, + maxWidth: props.wrapperWidth || null + }, + children: this.props.settings.map(setting => BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.checkboxcontainer, + children: BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Checkbox, { + disabled: props.disabled, + cardId: props.key, + settingId: setting, + shape: InternalComponents.LibraryComponents.Checkbox.Shapes && InternalComponents.LibraryComponents.Checkbox.Shapes.ROUND, + type: InternalComponents.LibraryComponents.Checkbox.Types && InternalComponents.LibraryComponents.Checkbox.Types.INVERTED, + color: this.props.checkboxColor, + getColor: this.props.getCheckboxColor, + value: props[setting], + getValue: this.props.getCheckboxValue, + onChange: this.props.onCheckboxChange + }) + })).flat(10).filter(n => n) + }) + ] + }), "title", "data", "settings", "renderLabel", "cardClassName", "cardStyle", "checkboxColor", "getCheckboxColor", "getCheckboxValue", "onCheckboxChange", "configWidth", "biggestWidth", "pagination")); + } + 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 wrapperWidth = this.props.configWidth && this.props.configWidth * this.props.settings.length; + let isHeaderClickable = typeof this.props.onHeaderClick == "function" || typeof this.props.onHeaderContextMenu == "function"; + let usePagination = BDFDB.ObjectUtils.is(this.props.pagination); + + let header = BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.settingstableheaders, + style: this.props.vertical && this.props.biggestWidth ? { + marginTop: this.props.biggestWidth - 15 || 0 + } : {}, + children: [ + this.renderHeaderOption({ + className: BDFDB.disCN.settingstableheadername, + clickable: this.props.title && isHeaderClickable, + label: this.props.title || "" + }), + BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.settingstableheaderoptions, + style: { + width: wrapperWidth || null, + minWidth: wrapperWidth || null, + maxWidth: wrapperWidth || null + }, + children: this.props.settings.map(setting => this.renderHeaderOption({ + className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.settingstableheaderoption, this.props.vertical && BDFDB.disCN.settingstableheadervertical), + clickable: isHeaderClickable, + label: setting + })) + }) + ] + }); + 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(data => this.renderItem(Object.assign({}, data, {wrapperWidth}))) : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.PaginatedList, Object.assign({}, this.props.pagination, { + header: header, + items: this.props.data, + renderItem: data => this.renderItem(Object.assign({}, data, {wrapperWidth})), + 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 newC = ""; + for (let key of keys) newC += `{"${key}":`; + value = value != null && value.value != null ? value.value : value; + let isString = typeof value == "string"; + let marker = isString ? `"` : ``; + newC += (marker + (isString ? value.replace(/\\/g, "\\\\") : value) + marker) + "}".repeat(keys.length); + newC = JSON.parse(newC); + newC = BDFDB.ObjectUtils.is(newC) ? BDFDB.ObjectUtils.deepAssign({}, data, newC) : newC; + BDFDB.DataUtils.save(newC, this.props.plugin, option); + if (!this.props.plugin.settings) this.props.plugin.settings = {}; + this.props.plugin.settings[option] = newC; + 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.Scrollers.Thin, { + 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.Scrollers.Thin, { + 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, digits: 3}); + + InternalComponents.LibraryComponents.SvgIcon = reactInitialized && class BDFDB_Icon extends LibraryModules.React.Component { + render() { + if (BDFDB.ObjectUtils.is(this.props.name)) { + let calcClassName = []; + if (BDFDB.ObjectUtils.is(this.props.name.getClassName)) for (let path in this.props.name.getClassName) { + if (!path || BDFDB.ObjectUtils.get(this, path)) calcClassName.push(BDFDB.disCN[this.props.name.getClassName[path]]); + } + if (calcClassName.length || 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(calcClassName, 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 = InternalData.SvgIcons || {}; + + const SwitchIconPaths = { + a: { + TOP: "M5.13231 6.72963L6.7233 5.13864L14.855 13.2704L13.264 14.8614L5.13231 6.72963Z", + BOTTOM: "M13.2704 5.13864L14.8614 6.72963L6.72963 14.8614L5.13864 13.2704L13.2704 5.13864Z" + }, + b: { + TOP: "M6.56666 11.0013L6.56666 8.96683L13.5667 8.96683L13.5667 11.0013L6.56666 11.0013Z", + BOTTOM: "M13.5582 8.96683L13.5582 11.0013L6.56192 11.0013L6.56192 8.96683L13.5582 8.96683Z" + }, + c: { + TOP: "M7.89561 14.8538L6.30462 13.2629L14.3099 5.25755L15.9009 6.84854L7.89561 14.8538Z", + BOTTOM: "M4.08643 11.0903L5.67742 9.49929L9.4485 13.2704L7.85751 14.8614L4.08643 11.0903Z" + } + }; + const SwitchInner = function (props) { + let reducedMotion = BDFDB.ReactUtils.useContext(LibraryModules.PreferencesContext.AccessibilityPreferencesContext).reducedMotion; + let ref = BDFDB.ReactUtils.useRef(null); + let state = BDFDB.ReactUtils.useState(false); + let animation = InternalComponents.LibraryComponents.Animations.useSpring({ + config: { + mass: 1, + tension: 250 + }, + opacity: props.disabled ? .3 : 1, + state: state[0] ? (props.value ? .7 : .3) : (props.value ? 1 : 0) + }); + let fill = animation.state.to({ + output: [props.uncheckedColor, props.checkedColor] + }); + let mini = props.size == InternalComponents.LibraryComponents.Switch.Sizes.MINI; + + return BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.div, { + className: BDFDB.DOMUtils.formatClassName(props.className, BDFDB.disCN.switch, mini && BDFDB.disCN.switchmini), + onMouseDown: _ => { + return !props.disabled && state[1](true); + }, + onMouseUp: _ => { + return state[1](false); + }, + onMouseLeave: _ => { + return state[1](false); + }, + style: { + opacity: animation.opacity, + backgroundColor: animation.state.to({ + output: [props.uncheckedColor, props.checkedColor] + }) + }, + tabIndex: -1, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.svg, { + className: BDFDB.disCN.switchslider, + viewBox: "0 0 28 20", + preserveAspectRatio: "xMinYMid meet", + style: { + left: animation.state.to({ + range: [0, .3, .7, 1], + output: mini ? [-1, 2, 6, 9] : [-3, 1, 8, 12] + }) + }, + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.rect, { + fill: "white", + x: animation.state.to({ + range: [0, .3, .7, 1], + output: [4, 0, 0, 4] + }), + y: animation.state.to({ + range: [0, .3, .7, 1], + output: [0, 1, 1, 0] + }), + height: animation.state.to({ + range: [0, .3, .7, 1], + output: [20, 18, 18, 20] + }), + width: animation.state.to({ + range: [0, .3, .7, 1], + output: [20, 28, 28, 20] + }), + rx: "10" + }), + BDFDB.ReactUtils.createElement("svg", { + viewBox: "0 0 20 20", + fill: "none", + children: [ + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.path, { + fill: fill, + d: animation.state.to({ + range: [0, .3, .7, 1], + output: reducedMotion.enabled ? [SwitchIconPaths.a.TOP, SwitchIconPaths.a.TOP, SwitchIconPaths.c.TOP, SwitchIconPaths.c.TOP] : [SwitchIconPaths.a.TOP, SwitchIconPaths.b.TOP, SwitchIconPaths.b.TOP, SwitchIconPaths.c.TOP] + }) + }), + BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Animations.animated.path, { + fill: fill, + d: animation.state.to({ + range: [0, .3, .7, 1], + output: reducedMotion.enabled ? [SwitchIconPaths.a.BOTTOM, SwitchIconPaths.a.BOTTOM, SwitchIconPaths.c.BOTTOM, SwitchIconPaths.c.BOTTOM] : [SwitchIconPaths.a.BOTTOM, SwitchIconPaths.b.BOTTOM, SwitchIconPaths.b.BOTTOM, SwitchIconPaths.c.BOTTOM] + }) + }) + ] + }) + ] + }), + BDFDB.ReactUtils.createElement("input", BDFDB.ObjectUtils.exclude(Object.assign({}, props, { + id: props.id, + type: "checkbox", + ref: ref, + className: BDFDB.DOMUtils.formatClassName(props.inputClassName, BDFDB.disCN.switchinner), + tabIndex: props.disabled ? -1 : 0, + onKeyDown: e => { + if (!props.disabled && !e.repeat && (e.key == " " || e.key == "Enter")) state[1](true); + }, + onKeyUp: e => { + if (!props.disabled && !e.repeat) { + state[1](false); + if (e.key == "Enter" && ref.current) ref.current.click(); + } + }, + onChange: e => { + state[1](false); + if (typeof props.onChange == "function") props.onChange(e.currentTarget.checked, e); + }, + checked: props.value, + disabled: props.disabled + }), "uncheckedColor", "checkedColor", "size", "value")) + ] }); }; - BDFDB.PatchUtils.patch(plugin, module, "default", {after: e => { - if (typeof plugin[`on${type}`] != "function") return; - else if (e.returnValue && e.returnValue.props.children) { - if (BDFDB.ArrayUtils.is(e.returnValue.props.children)) call(e.methodArguments, e.methodArguments[0], e.returnValue, module.default.displayName); - else if (e.returnValue.props.children.type && e.returnValue.props.children.type.displayName) { - let name = e.returnValue.props.children.type.displayName; - let originalReturn = e.returnValue.props.children.type(e.returnValue.props.children.props); - if (!originalReturn || !originalReturn.type) return; - let newType = (...args) => { - const returnValue = BDFDB.ReactUtils.createElement(originalReturn.type, originalReturn.props); - if (returnValue.props.children) call(args, args[0], returnValue, name); - else BDFDB.PatchUtils.patch(plugin, returnValue, "type", {after: e2 => { - if (e2.returnValue && typeof plugin[`on${type}`] == "function") call(e2.methodArguments, e2.methodArguments[0], e2.returnValue, name); - }}, {noCache: true}); - return returnValue; - }; - newType.displayName = name; - e.returnValue.props.children = BDFDB.ReactUtils.createElement(newType, e.returnValue.props.children.props); - } + 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); } - else BDFDB.PatchUtils.patch(plugin, e.returnValue, "type", {after: e2 => { - if (e2.returnValue && typeof plugin[`on${type}`] == "function") call(e2.methodArguments, e2.methodArguments[0], e2.returnValue, module.default.displayName); - }}, {noCache: true}); - }}, {name: type}); - }; - - BDFDB.ReactUtils.instanceKey = Object.keys(document.querySelector(BDFDB.dotCN.app) || {}).some(n => n.startsWith("__reactInternalInstance")) ? "_reactInternalFiber" : "_reactInternals"; - - BDFDB.PluginUtils.load(BDFDB); - InternalBDFDB.settings = BDFDB.DataUtils.get(InternalBDFDB); - changeLogs = BDFDB.DataUtils.load(BDFDB, "changeLogs"); - BDFDB.PluginUtils.checkChangeLog(BDFDB); - - (_ => { - const chunkName = "webpackChunkdiscord_app"; - const originalPush = window[chunkName].push; - const patches = {}; - const handlePush = chunk => { - for (const id in chunk[1]) { - const origModule = chunk[1][id]; - chunk[1][id] = (module, exports, require) => { - Reflect.apply(origModule, null, [module, exports, require]); - const removedTypes = []; - for (const type in PluginStores.chunkObserver) { - const foundModule = PluginStores.chunkObserver[type].filter(exports) || exports.default && PluginStores.chunkObserver[type].filter(exports.default); - if (foundModule) { - InternalBDFDB.patchComponent(PluginStores.chunkObserver[type].query, PluginStores.chunkObserver[type].config.exported ? foundModule : exports, PluginStores.chunkObserver[type].config); - removedTypes.push(type); - break; + render() { + return BDFDB.ReactUtils.createElement(SwitchInner, Object.assign({}, this.props, { + onChange: this.handleChange.bind(this) + })); + } + }; + InternalComponents.LibraryComponents.Switch.Sizes = { + DEFAULT: "default", + MINI: "mini", + }; + InternalBDFDB.setDefaultProps(InternalComponents.LibraryComponents.Switch, { + size: InternalComponents.LibraryComponents.Switch.Sizes.DEFAULT, + uncheckedColor: BDFDB.DiscordConstants.Colors.PRIMARY_DARK_400, + checkedColor: BDFDB.DiscordConstants.Colors.BRAND + }); + + 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"); } } - while (removedTypes.length) delete PluginStores.chunkObserver[removedTypes.pop()]; - - let found = false, funcString = exports && exports.default && typeof exports.default == "function" && exports.default.toString(); - if (funcString && funcString.indexOf(".page") > -1 && funcString.indexOf(".section") > -1 && funcString.indexOf(".objectType") > -1) { - const returnValue = exports.default({}); - if (returnValue && returnValue.props && returnValue.props.object == BDFDB.DiscordConstants.AnalyticsObjects.CONTEXT_MENU) { - for (const type in PluginStores.contextChunkObserver) { - if (PluginStores.contextChunkObserver[type].filter(returnValue.props.children.type)) { - exports._BDFDB_ContextMenuWrap = type; - found = true; - if (PluginStores.contextChunkObserver[type].modules.indexOf(exports) == -1) PluginStores.contextChunkObserver[type].modules.push(exports); - for (const plugin of PluginStores.contextChunkObserver[type].query) InternalBDFDB.patchContextMenu(plugin, type, exports); - break; + }); + 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(this.pressedTimeout); + this.pressedTimeout = BDFDB.TimeUtils.timeout(_ => { + delete this.props.focused; + BDFDB.ReactUtils.forceUpdate(this); + }, 1000); + this.props.focused = true; + this.handleChange.apply(this, [value]); + this.handleInput.apply(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.apply(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, + style: this.props.width ? {width: `${this.props.width}px`} : {}, + ref: this.props.inputRef + }), "errorMessage", "focused", "error", "success", "inputClassName", "inputChildren", "valuePrefix", "inputPrefix", "size", "editable", "inputRef", "style", "mode", "colorPickerOpen", "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.apply(this, [!color ? "" : (this.props.mode == "comp" ? BDFDB.ColorUtils.convert(color, "RGBCOMP").slice(0, 3).join(",") : BDFDB.ColorUtils.convert(color, this.props.noAlpha ? "RGB" : "RGBA"))]), + pickerOpen: this.props.colorPickerOpen, + onPickerOpen: _ => this.props.colorPickerOpen = true, + onPickerClose: _ => delete this.props.colorPickerOpen, + ref: this.props.controlsRef, + 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, + ref: this.props.controlsRef + }) : 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.margintop8, + 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() { + let scrolling, scroll = _ => {}; + 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 => { + const ele = BDFDB.ReactUtils.findDOMNode(instance); + if (ele && ele.parentElement) { + const maxWidth = BDFDB.DOMUtils.getInnerWidth(ele.parentElement); + if (maxWidth > 50) ele.style.setProperty("max-width", `${maxWidth}px`); + if (!this.props.initiated) BDFDB.TimeUtils.timeout(_ => { + this.props.initiated = true; + if (document.contains(ele.parentElement)) BDFDB.ReactUtils.forceUpdate(this); + }, 3000); + const 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("display", v.value == 0 ? "inline" : "block", "important"); + ele.firstElementChild.style.setProperty("left", `${v.value}px`, "important"); + }); + scroll = p => { + const display = ele.firstElementChild.style.getPropertyValue("display"); + ele.firstElementChild.style.setProperty("display", "inline", "important"); + const innerWidth = BDFDB.DOMUtils.getRects(ele.firstElementChild).width; + const outerWidth = BDFDB.DOMUtils.getRects(ele).width; + ele.firstElementChild.style.setProperty("display", display, "important"); + + let w = p + parseFloat(ele.firstElementChild.style.getPropertyValue("left")) / (innerWidth - outerWidth); + w = isNaN(w) || !isFinite(w) ? p : w; + w *= innerWidth / (outerWidth * 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 || e.currentTarget.firstElementChild.style.getPropertyValue("display") != "inline") { + scrolling = true; + scroll(1); + } + }, + onMouseLeave: e => { + if (scrolling) { + scrolling = false; + 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 = (typeof this.props.children == "function" ? this.props.children() : (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 childProps = Object.assign({}, child.props); + let shown = false; + child.props.onMouseEnter = (e, childThis) => { + if (!shown && !e.currentTarget.BDFDBtooltipShown && !(this.props.onlyShowOnShift && !e.shiftKey) && !(this.props.onlyShowOnCtrl && !e.ctrlKey)) { + e.currentTarget.BDFDBtooltipShown = shown = true; + this.tooltip = BDFDB.TooltipUtils.create(e.currentTarget, typeof this.props.text == "function" ? this.props.text(this, e) : this.props.text, Object.assign({ + note: this.props.note, + delay: this.props.delay + }, this.props.tooltipConfig, { + onHide: (tooltip, anker) => { + delete anker.BDFDBtooltipShown; + shown = false; + if (this.props.tooltipConfig && typeof this.props.tooltipConfig.onHide == "function") this.props.tooltipConfig.onHide(tooltip, anker); + } + })); + if (typeof this.props.onMouseEnter == "function") this.props.onMouseEnter(e, this); + if (typeof childProps.onMouseEnter == "function") childProps.onMouseEnter(e, childThis); + } + }; + child.props.onMouseLeave = (e, childThis) => { + if (typeof this.props.onMouseLeave == "function") this.props.onMouseLeave(e, this); + if (typeof childProps.onMouseLeave == "function") childProps.onMouseLeave(e, childThis); + }; + child.props.onClick = (e, childThis) => { + if (typeof this.props.onClick == "function") this.props.onClick(e, this); + if (typeof childProps.onClick == "function") childProps.onClick(e, childThis); + if (typeof this.props.text == "function") this.updateTooltip(this.props.text(this, e)); + }; + child.props.onContextMenu = (e, childThis) => { + if (typeof this.props.onContextMenu == "function") this.props.onContextMenu(e, this); + if (typeof childProps.onContextMenu == "function") childProps.onContextMenu(e, childThis); + if (typeof this.props.text == "function") this.updateTooltip(this.props.text(this, e)); + }; + 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 => BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.UserPopout, { + userId: this.props.userId, + channelId: this.props.channelId, + guildId: this.props.guildId + }), + }), "userId", "channelId", "guildId")); + } + }; + + const VideoInner = function (props) { + let ref = BDFDB.ReactUtils.useRef(null); + BDFDB.ReactUtils.useEffect(_ => { + if (ref.current) props.play ? ref.current.play() : ref.current.pause(); + }, [props.play]); + return props.naturalWidth <= BDFDB.DiscordConstants.MAX_VIDEO_WIDTH && props.naturalHeight <= BDFDB.DiscordConstants.MAX_VIDEO_HEIGHT || props.naturalWidth <= BDFDB.DiscordConstants.MAX_VIDEO_HEIGHT && props.naturalHeight <= BDFDB.DiscordConstants.MAX_VIDEO_WIDTH ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.VideoForwardRef, { + ref: ref, + className: props.className, + poster: props.poster, + src: props.src, + width: props.width, + height: props.height, + muted: true, + loop: true, + autoPlay: props.play, + preload: "none" + }) : BDFDB.ReactUtils.createElement("img", { + alt: "", + src: props.poster, + width: props.width, + height: props.height + }); + }; + InternalComponents.LibraryComponents.Video = reactInitialized && class BDFDB_Video extends LibraryModules.React.Component { + render() { + return BDFDB.ReactUtils.createElement(VideoInner, this.props); + } + }; + + 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 if (!InternalComponents.LibraryComponents[type][key]) InternalComponents.LibraryComponents[type][key] = InternalComponents.NativeSubComponents[type][key]; + } + BDFDB.LibraryComponents = Object.assign({}, InternalComponents.LibraryComponents); + + InternalBDFDB.createCustomControl = function (data) { + let controlButton = BDFDB.DOMUtils.create(``); + BDFDB.ReactUtils.render(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.SvgIcon, { + nativeClass: true, + name: data.svgName, + width: 20, + height: 20 + }), controlButton); + controlButton.addEventListener("click", _ => {if (typeof data.onClick == "function") data.onClick();}); + if (data.tooltipText) controlButton.addEventListener("mouseenter", _ => {BDFDB.TooltipUtils.create(controlButton, data.tooltipText);}); + return controlButton; + }; + InternalBDFDB.appendCustomControls = function (card) { + if (!card || card.querySelector(BDFDB.dotCN._repocontrolscustom)) return; + let checkbox = card.querySelector(BDFDB.dotCN._reposwitch); + if (!checkbox) return; + let props = BDFDB.ObjectUtils.get(BDFDB.ReactUtils.getInstance(card), "return.stateNode.props"); + let plugin = props && props.addon && (props.addon.plugin || props.addon.instance); + if (plugin && (plugin == libraryInstance || plugin.name && plugin.name && PluginStores.loaded[plugin.name] && PluginStores.loaded[plugin.name] == plugin)) { + let url = InternalBDFDB.getPluginURL(plugin); + let controls = []; + let footerControls = card.querySelector(BDFDB.dotCNS._repofooter + BDFDB.dotCN._repocontrols); + if (plugin.changeLog) controls.push(InternalBDFDB.createCustomControl({ + tooltipText: BDFDB.LanguageUtils.LanguageStrings.CHANGE_LOG, + svgName: InternalComponents.LibraryComponents.SvgIcon.Names.CHANGELOG, + onClick: _ => {BDFDB.PluginUtils.openChangeLog(plugin);} + })); + if (PluginStores.updateData.plugins[url] && PluginStores.updateData.plugins[url].outdated) controls.push(InternalBDFDB.createCustomControl({ + tooltipText: BDFDB.LanguageUtils.LanguageStrings.UPDATE_MANUALLY, + svgName: InternalComponents.LibraryComponents.SvgIcon.Names.DOWNLOAD, + onClick: _ => {BDFDB.PluginUtils.downloadUpdate(plugin.name, url);} + })); + if (footerControls) for (let control of controls) footerControls.insertBefore(control, footerControls.firstElementChild); + else for (let control of controls) checkbox.parentElement.insertBefore(control, checkbox.parentElement.firstElementChild); + } + }; + InternalBDFDB.addListObserver = function (layer) { + if (!layer) return; + BDFDB.ObserverUtils.connect(BDFDB, layer, {name: "cardObserver", instance: new MutationObserver(changes => {changes.forEach(change => {if (change.addedNodes) {change.addedNodes.forEach(n => { + if (BDFDB.DOMUtils.containsClass(n, BDFDB.disCN._repocard)) InternalBDFDB.appendCustomControls(n); + if (n.nodeType != Node.TEXT_NODE) for (let c of n.querySelectorAll(BDFDB.dotCN._repocard)) InternalBDFDB.appendCustomControls(c); + InternalBDFDB.appendCustomControls(BDFDB.DOMUtils.getParent(BDFDB.dotCN._repocard, n)); + });}});})}, {childList: true, subtree: true}); + for (let c of layer.querySelectorAll(BDFDB.dotCN._repocard)) InternalBDFDB.appendCustomControls(c); + } + + 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: { + SearchBar: "render", + EmojiPicker: "type", + EmojiPickerListRow: "default" + }, + after: { + Menu: "default", + SettingsView: "componentDidMount", + Shakeable: "render", + Message: "default", + MessageHeader: "default", + MemberListItem: ["componentDidMount", "componentDidUpdate"], + PrivateChannel: ["componentDidMount", "componentDidUpdate"], + AnalyticsContext: ["componentDidMount", "componentDidUpdate"], + PeopleListItem: ["componentDidMount", "componentDidUpdate"], + DiscordTag: "default" + } + }; + + const menuExtraPatches = {}; + InternalBDFDB.processMenu = function (e) { + if (e.instance.props.navId) switch (e.instance.props.navId) { + case "guild-header-popout": + if (menuExtraPatches["guild-header-popout"]) return; + menuExtraPatches["guild-header-popout"] = true; + BDFDB.TimeUtils.interval((interval, count) => { + if (count > 20) return BDFDB.TimeUtils.clear(interval); + else { + let module = BDFDB.ModuleUtils.findByString("guild-header-popout"); + if (module) BDFDB.PatchUtils.patch(BDFDB, module.default.prototype, "render", {after: e => { + BDFDB.PatchUtils.patch(BDFDB, e.returnValue.type, "type", {after: e2 => { + InternalBDFDB.triggerQueuePatch("GuildHeaderContextMenu", { + arguments: e2.methodArguments, + instance: {props: e2.methodArguments[0]}, + returnvalue: e2.returnValue, + component: e.returnValue, + methodname: "type", + type: "GuildHeaderContextMenu" + }); + }}, {noCache: true}); + }}); + } + }, 500); + return; + case "dev-context": + if (menuExtraPatches["dev-context"]) return; + menuExtraPatches["dev-context"] = true; + BDFDB.PatchUtils.patch(BDFDB, (BDFDB.ModuleUtils.findByName("useCopyIdItem", false) || {}).exports, "default", {after: e => { + if (!e.returnValue) e.returnValue = false; + }}, {priority: 10}); + BDFDB.PatchUtils.patch(BDFDB, e.component, "default", {after: e => { + if (!e.returnValue.props.children) LibraryModules.ContextMenuUtils.closeContextMenu(); + }}, {priority: 10}); + return; + } + }; + + + InternalBDFDB.processSearchBar = function (e) { + if (typeof e.instance.props.query != "string") e.instance.props.query = ""; + }; + + InternalBDFDB.processSettingsView = function (e) { + if (e.node && e.node.parentElement && e.node.parentElement.getAttribute("aria-label") == BDFDB.DiscordConstants.Layers.USER_SETTINGS) InternalBDFDB.addListObserver(e.node.parentElement); + }; + + let AppViewExport = BDFDB.ModuleUtils.findByName("AppView", false); + if (AppViewExport) InternalBDFDB.processShakeable = function (e) { + let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {name: "AppView"}); + if (index > -1) children[index] = BDFDB.ReactUtils.createElement(AppViewExport.exports.default, children[index].props); + }; + + InternalBDFDB.processMessage = function (e) { + if (e.returnvalue && e.returnvalue.props && e.returnvalue.props.children && e.returnvalue.props.children.props) { + let message; + for (let key in e.instance.props) { + if (!message) message = BDFDB.ObjectUtils.get(e.instance.props[key], "props.message"); + else break; + } + if (message) { + e.returnvalue.props.children.props[InternalData.authorIdAttribute] = message.author.id; + if (LibraryModules.RelationshipStore.isFriend(message.author.id)) e.returnvalue.props.children.props[InternalData.authorFriendAttribute] = true; + if (message.author.id == BDFDB.UserUtils.me.id) e.returnvalue.props.children.props[InternalData.authorSelfAttribute] = true; + } + } + }; + + const BDFDB_Patrons = Object.assign({}, InternalData.BDFDB_Patrons), BDFDB_Patron_Tiers = Object.assign({}, InternalData.BDFDB_Patron_Tiers); + InternalBDFDB._processAvatarRender = function (user, avatar, className) { + if (BDFDB.ReactUtils.isValidElement(avatar) && BDFDB.ObjectUtils.is(user) && (avatar.props.className || "").indexOf(BDFDB.disCN.bdfdbbadgeavatar) == -1) { + avatar.props[InternalData.userIdAttribute] = user.id; + let role = "", note = "", color, link, addBadge = InternalBDFDB.settings.general.showSupportBadges; + if (BDFDB_Patrons[user.id] && BDFDB_Patrons[user.id].active) { + link = "https://www.patreon.com/MircoWittrien"; + role = BDFDB_Patrons[user.id].text || (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text; + note = BDFDB_Patrons[user.id].text && (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text; + color = BDFDB_Patrons[user.id].color; + className = BDFDB.DOMUtils.formatClassName(avatar.props.className, className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbsupporter, BDFDB.disCN[`bdfdbsupporter${BDFDB_Patrons[user.id].tier}`]); + } + if (user.id == InternalData.myId) { + addBadge = true; + role = `Theme ${BDFDB.LanguageUtils.LibraryStrings.developer}`; + className = BDFDB.DOMUtils.formatClassName(avatar.props.className, className, BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbdev); + } + if (role) { + delete avatar.props[InternalData.userIdAttribute]; + if (avatar.type == "img") avatar = BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.AvatarComponents.default, Object.assign({}, avatar.props, { + size: InternalComponents.LibraryComponents.AvatarComponents.Sizes.SIZE_40 + })); + delete avatar.props.className; + let newProps = { + className: className, + children: [avatar] + }; + newProps[InternalData.userIdAttribute] = user.id; + avatar = BDFDB.ReactUtils.createElement("div", newProps); + if (addBadge) avatar.props.children.push(BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TooltipContainer, { + text: role, + note: note, + tooltipConfig: {backgroundColor: color || ""}, + onClick: link ? (_ => BDFDB.DiscordUtils.openLink(link)) : (_ => {}), + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCN.bdfdbbadge + }) + })); + return avatar; + } + } + }; + InternalBDFDB._processAvatarMount = function (user, avatar, wrapper) { + if (!user) return; + if (wrapper) wrapper.setAttribute(InternalData.userIdAttribute, user.id); + if (Node.prototype.isPrototypeOf(avatar) && (avatar.className || "").indexOf(BDFDB.disCN.bdfdbbadgeavatar) == -1) { + avatar.setAttribute(InternalData.userIdAttribute, user.id); + let role = "", note = "", color, link, addBadge = InternalBDFDB.settings.general.showSupportBadges; + if (BDFDB_Patrons[user.id] && BDFDB_Patrons[user.id].active) { + link = "https://www.patreon.com/MircoWittrien"; + role = BDFDB_Patrons[user.id].text || (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text; + note = BDFDB_Patrons[user.id].text && (BDFDB_Patron_Tiers[BDFDB_Patrons[user.id].tier] || {}).text; + color = BDFDB_Patrons[user.id].color; + avatar.className = BDFDB.DOMUtils.formatClassName(avatar.className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbsupporter, BDFDB.disCN[`bdfdbsupporter${BDFDB_Patrons[user.id].tier}`]); + } + else if (user.id == InternalData.myId) { + addBadge = true; + role = `Theme ${BDFDB.LanguageUtils.LibraryStrings.developer}`; + avatar.className = BDFDB.DOMUtils.formatClassName(avatar.className, addBadge && BDFDB.disCN.bdfdbhasbadge, BDFDB.disCN.bdfdbbadgeavatar, BDFDB.disCN.bdfdbdev); + } + if (addBadge && role && !avatar.querySelector(BDFDB.dotCN.bdfdbbadge)) { + let badge = document.createElement("div"); + badge.className = BDFDB.disCN.bdfdbbadge; + if (link) badge.addEventListener("click", _ => BDFDB.DiscordUtils.openLink(link)); + badge.addEventListener("mouseenter", _ => BDFDB.TooltipUtils.create(badge, role, {position: "top", note: note, backgroundColor: color || ""})); + avatar.appendChild(badge); + } + } + }; + InternalBDFDB._processUserInfoNode = function (user, wrapper) { + if (!user || !wrapper) return; + if (InternalData.UserBackgrounds[user.id]) for (let property in InternalData.UserBackgrounds[user.id]) wrapper.style.setProperty(property, InternalData.UserBackgrounds[user.id][property], "important"); + }; + 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 = BDFDB.TimeUtils.suppress((...args) => { + let renderedChildren = renderChildren(...args); + return InternalBDFDB._processAvatarRender(e.instance.props.message.author, renderedChildren, BDFDB.disCN.messageavatar) || renderedChildren; + }, "Error in Avatar Render of MessageHeader!"); + } + 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), e.node); + }; + InternalBDFDB.processPrivateChannel = function (e) { + InternalBDFDB._processAvatarMount(e.instance.props.user, e.node.querySelector(BDFDB.dotCN.avatarwrapper), e.node); + }; + InternalBDFDB.processAnalyticsContext = function (e) { + if (e.instance.props.section != BDFDB.DiscordConstants.AnalyticsSections.PROFILE_MODAL && e.instance.props.section != BDFDB.DiscordConstants.AnalyticsSections.PROFILE_POPOUT) return; + const user = BDFDB.ReactUtils.findValue(e.instance, "user"); + if (!user) return; + const wrapper = e.node.querySelector(BDFDB.dotCNC.userpopout + BDFDB.dotCN.userprofile) || e.node; + const avatar = e.node.querySelector(BDFDB.dotCN.avatarwrapper); + if (avatar) InternalBDFDB._processAvatarMount(user, e.instance.props.section == BDFDB.DiscordConstants.AnalyticsSections.PROFILE_POPOUT ? avatar.parentElement : avatar, wrapper); + InternalBDFDB._processUserInfoNode(user, wrapper); + }; + InternalBDFDB.processPeopleListItem = function (e) { + if (e.instance.props.user) e.node.setAttribute(InternalData.userIdAttribute, e.instance.props.user.id); + }; + 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.processEmojiPicker = function (e) { + if (BDFDB.ObjectUtils.toArray(PluginStores.loaded).filter(p => p.started).some(p => p.onSystemMessageOptionContextMenu || p.onSystemMessageOptionToolbar || p.onMessageOptionContextMenu || p.onMessageOptionToolbar)) e.instance.props.persistSearch = true; + }; + InternalBDFDB.processEmojiPickerListRow = function (e) { + if (e.instance.props.emojiDescriptors && InternalComponents.LibraryComponents.EmojiPickerButton.current && InternalComponents.LibraryComponents.EmojiPickerButton.current.props && InternalComponents.LibraryComponents.EmojiPickerButton.current.props.allowManagedEmojisUsage) for (let i in e.instance.props.emojiDescriptors) e.instance.props.emojiDescriptors[i] = Object.assign({}, e.instance.props.emojiDescriptors[i], {isDisabled: false}); + }; + + InternalBDFDB.addChunkObserver = function (pluginData, config) { + let module; + if (config.stringFind) module = BDFDB.ModuleUtils.findByString(config.stringFind, config.exported, true); + else if (config.propertyFind) module = BDFDB.ModuleUtils.findByProperties(config.propertyFind, config.exported, true); + else if (config.prototypeFind) module = BDFDB.ModuleUtils.findByPrototypes(config.prototypeFind, config.exported, true); + else module = BDFDB.ModuleUtils.findByName(config.name, config.exported, true); + if (module) { + let exports = !config.exported && module.exports || module; + exports = config.path && BDFDB.ObjectUtils.get(exports, config.path) || exports; + exports && InternalBDFDB.patchComponent(pluginData, InternalBDFDB.isMemoOrForwardRef(exports) ? exports.default : exports, config); + } + else { + if (!PluginStores.chunkObserver[config.mappedType]) { + PluginStores.chunkObserver[config.mappedType] = {query: [], config}; + let filter; + if (config.stringFind) filter = m => [config.stringFind].flat(10).filter(n => n).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) && m; + else if (config.propertyFind) filter = m => [config.propertyFind].flat(10).filter(n => n).every(prop => { + const value = m[prop]; + return value !== undefined && !(typeof value == "string" && !value); + }) && m; + else if (config.prototypeFind) filter = m => m.prototype && [config.prototypeFind].flat(10).filter(n => n).every(prop => { + const value = m.prototype[prop]; + return value !== undefined && !(typeof value == "string" && !value); + }) && m; + else filter = m => m.displayName === config.name && m || m.render && m.render.displayName === config.name && m || m[config.name] && m[config.name].displayName === name && m[config.name]; + PluginStores.chunkObserver[config.mappedType].filter = filter; + } + PluginStores.chunkObserver[config.mappedType].query.push(pluginData); + } + }; + InternalBDFDB.addQueuePatches = function (plugin) { + if (!InternalData.ModuleUtilsConfig.QueuedComponents) return; + plugin = plugin == BDFDB && InternalBDFDB || plugin; + for (let type of InternalData.ModuleUtilsConfig.QueuedComponents) if (typeof plugin[`on${type}`] == "function") { + if (PluginStores.patchQueues[type].query.indexOf(plugin) == -1) { + PluginStores.patchQueues[type].query.push(plugin); + PluginStores.patchQueues[type].query.sort((x, y) => x.name < y.name ? -1 : x.name > y.name ? 1 : 0); + } + } + }; + InternalBDFDB.triggerQueuePatch = function (type, e) { + if (e.returnvalue && BDFDB.ObjectUtils.is(PluginStores.patchQueues[type]) && BDFDB.ArrayUtils.is(PluginStores.patchQueues[type].query)) { + for (let plugin of PluginStores.patchQueues[type].query) if(typeof plugin[`on${type}`] == "function") plugin[`on${type}`](e); + } + }; + InternalBDFDB.addContextChunkObservers = function (plugin) { + if (!InternalData.ModuleUtilsConfig.ContextMenuTypes) return; + plugin = plugin == BDFDB && InternalBDFDB || plugin; + for (let type of InternalData.ModuleUtilsConfig.ContextMenuTypes) { + type = `${type}ContextMenu`; + if (typeof plugin[`on${InternalData.ModuleUtilsConfig.ContextMenuTypesMap[type] || type}`] == "function") { + for (let module of PluginStores.contextChunkObserver[type].modules) InternalBDFDB.patchContextMenu(plugin, type, module); + if (PluginStores.contextChunkObserver[type].query.indexOf(plugin) == -1) { + PluginStores.contextChunkObserver[type].query.push(plugin); + PluginStores.contextChunkObserver[type].query.sort((x, y) => x.name < y.name ? -1 : x.name > y.name ? 1 : 0); + } + } + } + }; + InternalBDFDB.patchContextMenu = function (plugin, type, module) { + if (!module || !module.default) return; + plugin = plugin == BDFDB && InternalBDFDB || plugin; + const caller = `on${InternalData.ModuleUtilsConfig.ContextMenuTypesMap[type] || type}`; + if (!InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type]) { + const call = (args, props, returnValue, name) => { + if (!returnValue || !returnValue.props || !returnValue.props.children || returnValue.props.children.__BDFDBPatchesCalled && returnValue.props.children.__BDFDBPatchesCalled[plugin.name]) return; + returnValue.props.children.__BDFDBPatchesCalled = Object.assign({}, returnValue.props.children.__BDFDBPatchesCalled, {[plugin.name]: true}); + return plugin[caller]({ + arguments: args, + instance: {props: props}, + returnvalue: returnValue, + component: module, + methodname: "default", + type: name + }); + }; + BDFDB.PatchUtils.patch(plugin, module, "default", {after: e => { + if (typeof plugin[caller] != "function") return; + else if (e.returnValue && e.returnValue.props.children) { + if (BDFDB.ArrayUtils.is(e.returnValue.props.children)) call(e.methodArguments, e.methodArguments[0], e.returnValue, module.default.displayName); + else if (e.returnValue.props.children.type && e.returnValue.props.children.type.displayName) { + const name = e.returnValue.props.children.type.displayName; + const originalReturn = e.returnValue.props.children.type(e.returnValue.props.children.props); + if (!originalReturn || !originalReturn.type) return; + let newType = (...args) => { + const returnValue = BDFDB.ReactUtils.createElement(originalReturn.type, originalReturn.props); + if (returnValue.props.children) call(args, args[0], returnValue, name); + else BDFDB.PatchUtils.patch(plugin, returnValue, "type", {after: e2 => { + if (e2.returnValue && typeof plugin[`on${type}`] == "function") call(e2.methodArguments, e2.methodArguments[0], e2.returnValue, name); + }}, {noCache: true}); + return returnValue; + }; + newType.displayName = name; + e.returnValue.props.children = BDFDB.ReactUtils.createElement(newType, e.returnValue.props.children.props); + } + } + else BDFDB.PatchUtils.patch(plugin, e.returnValue, "type", {after: e2 => { + if (e2.returnValue && typeof plugin[caller] == "function") call(e2.methodArguments, e2.methodArguments[0], e2.returnValue, module.default.displayName); + }}, {noCache: true}); + }}, {name: type}); + } + else { + const getProps = (props, key) => { + const store = `${LibraryModules.StringUtils.upperCaseFirstChar(key)}Store`; + const getter = `get${LibraryModules.StringUtils.upperCaseFirstChar(key)}`; + return Object.assign({}, BDFDB.ObjectUtils.is(props) ? props : typeof props == "string" ? {id: props} : {}, {[key]: (props && props[key] || LibraryModules[store] && typeof LibraryModules[store][getter] == "function" && LibraryModules[store][getter](props && props.id || props))}); + }; + BDFDB.PatchUtils.patch(plugin, module, "default", {after: e => { + if (typeof plugin[caller] != "function") return; + e.returnValue = [e.returnValue].flat(10).filter(n => n); + return plugin[caller]({ + arguments: e.methodArguments, + instance: {props: InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type].key && getProps(e.methodArguments[0], InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type].key) || e.methodArguments[0]}, + returnvalue: e.returnValue, + component: module, + methodname: "default", + type: type, + subType: module.default.displayName + }); + }}, {name: type}); + } + }; + + BDFDB.ReactUtils.instanceKey = Object.keys(document.querySelector(BDFDB.dotCN.app) || {}).some(n => n.startsWith("__reactInternalInstance")) ? "_reactInternalFiber" : "_reactInternals"; + + BDFDB.PluginUtils.load(BDFDB); + InternalBDFDB.settings = BDFDB.DataUtils.get(InternalBDFDB); + changeLogs = BDFDB.DataUtils.load(BDFDB, "changeLogs"); + BDFDB.PluginUtils.checkChangeLog(BDFDB); + + (_ => { + const chunkName = "webpackChunkdiscord_app"; + const originalPush = window[chunkName].push; + const patches = {}; + const handlePush = chunk => { + for (const id in chunk[1]) { + const origModule = chunk[1][id]; + chunk[1][id] = (module, exports, require) => { + Reflect.apply(origModule, null, [module, exports, require]); + const removedTypes = []; + for (const type in PluginStores.chunkObserver) { + const foundModule = PluginStores.chunkObserver[type].filter(exports) || exports.default && PluginStores.chunkObserver[type].filter(exports.default); + if (foundModule) { + InternalBDFDB.patchComponent(PluginStores.chunkObserver[type].query, PluginStores.chunkObserver[type].config.exported ? foundModule : exports, PluginStores.chunkObserver[type].config); + removedTypes.push(type); + break; + } + } + while (removedTypes.length) delete PluginStores.chunkObserver[removedTypes.pop()]; + + let found = false, funcString = exports && exports.default && typeof exports.default == "function" && exports.default.toString(); + if (funcString && funcString.indexOf(".page") > -1 && funcString.indexOf(".section") > -1 && funcString.indexOf(".objectType") > -1) { + const returnValue = exports.default({}); + if (returnValue && returnValue.props && returnValue.props.object == BDFDB.DiscordConstants.AnalyticsObjects.CONTEXT_MENU) { + for (const type in PluginStores.contextChunkObserver) { + if (PluginStores.contextChunkObserver[type].filter(returnValue.props.children.type)) { + exports._BDFDB_ContextMenuWrap = type; + found = true; + if (PluginStores.contextChunkObserver[type].modules.indexOf(exports) == -1) PluginStores.contextChunkObserver[type].modules.push(exports); + for (const plugin of PluginStores.contextChunkObserver[type].query) InternalBDFDB.patchContextMenu(plugin, type, exports); + break; + } } } } - } - if (!found) for (const type in PluginStores.contextChunkObserver) { - if (PluginStores.contextChunkObserver[type].filter(exports.default)) { - if (PluginStores.contextChunkObserver[type].modules.indexOf(exports) == -1) PluginStores.contextChunkObserver[type].modules.push(exports); - for (const plugin of PluginStores.contextChunkObserver[type].query) InternalBDFDB.patchContextMenu(plugin, type, exports); - break; + if (!found) for (const type in PluginStores.contextChunkObserver) { + if (PluginStores.contextChunkObserver[type].filter(exports.default)) { + if (PluginStores.contextChunkObserver[type].modules.indexOf(exports) == -1) PluginStores.contextChunkObserver[type].modules.push(exports); + for (const plugin of PluginStores.contextChunkObserver[type].query) InternalBDFDB.patchContextMenu(plugin, type, exports); + break; + } } - } - }; - Object.assign(chunk[1][id], origModule, {toString: _ => origModule.toString()}); - patches[id] = [chunk, origModule]; - } - return Reflect.apply(originalPush, window[chunkName], [chunk]); - }; - - Object.defineProperty(window[chunkName], "push", { - configurable: true, - get: _ => handlePush, - set: newPush => { - originalPush = newPush; - Object.defineProperty(window[chunkName], "push", { - value: handlePush, - configurable: true, - writable: true - }); - } - }); - InternalBDFDB.removeChunkObserver = _ => { - for (let id in patches) { - patches[id][0] = patches[id][1]; - patches[id] = null; - } + }; + Object.assign(chunk[1][id], origModule, {toString: _ => origModule.toString()}); + patches[id] = [chunk, origModule]; + } + return Reflect.apply(originalPush, window[chunkName], [chunk]); + }; + Object.defineProperty(window[chunkName], "push", { configurable: true, - get: _ => (chunk => Reflect.apply(originalPush, window[chunkName], [chunk])) + get: _ => handlePush, + set: newPush => { + originalPush = newPush; + Object.defineProperty(window[chunkName], "push", { + value: handlePush, + configurable: true, + writable: true + }); + } }); - }; - })(); - - for (let type of ContextMenuTypes) { - type = `${type}ContextMenu`; - if (!PluginStores.contextChunkObserver[type]) { - PluginStores.contextChunkObserver[type] = {query: [], modules: []}; - PluginStores.contextChunkObserver[type].filter = m => m && (m.displayName && m.displayName.endsWith("ContextMenu") && `${ContextMenuTypes.find(t => m.displayName.indexOf(t) > -1)}ContextMenu` == type || m._BDFDB_ContextMenuWrap && m._BDFDB_ContextMenuWrap.endsWith("ContextMenu") && `${ContextMenuTypes.find(t => m._BDFDB_ContextMenuWrap.indexOf(t) > -1)}ContextMenu` == type) && m; - PluginStores.contextChunkObserver[type].modules = BDFDB.ModuleUtils.find(PluginStores.contextChunkObserver[type].filter, {all: true}); + InternalBDFDB.removeChunkObserver = _ => { + for (let id in patches) { + patches[id][0] = patches[id][1]; + patches[id] = null; + } + Object.defineProperty(window[chunkName], "push", { + configurable: true, + get: _ => (chunk => Reflect.apply(originalPush, window[chunkName], [chunk])) + }); + }; + })(); + + if (InternalData.ModuleUtilsConfig.ContextMenuTypes) for (let type of InternalData.ModuleUtilsConfig.ContextMenuTypes) { + type = `${type}ContextMenu`; + if (!PluginStores.contextChunkObserver[type]) { + PluginStores.contextChunkObserver[type] = {query: [], modules: []}; + if (!InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type]) PluginStores.contextChunkObserver[type].filter = m => m && (m.displayName && m.displayName.endsWith("ContextMenu") && `${InternalData.ModuleUtilsConfig.ContextMenuTypes.find(t => m.displayName.indexOf(t) > -1)}ContextMenu` == type || m._BDFDB_ContextMenuWrap && m._BDFDB_ContextMenuWrap.endsWith("ContextMenu") && `${InternalData.ModuleUtilsConfig.ContextMenuTypes.find(t => m._BDFDB_ContextMenuWrap.indexOf(t) > -1)}ContextMenu` == type) && m; + else PluginStores.contextChunkObserver[type].filter = m => m && m.displayName && InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type].items.indexOf(m.displayName) > -1 && m; + PluginStores.contextChunkObserver[type].modules = BDFDB.ModuleUtils.find(PluginStores.contextChunkObserver[type].filter, {all: true}); + } } - } - - InternalBDFDB.patchPlugin(BDFDB); - InternalBDFDB.addQueuePatches(BDFDB); - InternalBDFDB.addContextChunkObservers(BDFDB); - - for (let type of QueuedComponents) if (!PluginStores.patchQueues[type]) PluginStores.patchQueues[type] = {query: [], modules: []}; - - 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(PluginStores.loaded).filter(p => p.started).some(p => p.onSystemMessageOptionContextMenu || p.onSystemMessageOptionToolbar || 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}); - let isSystem = BDFDB.MessageUtils.isSystemMessage(e2.methodArguments[0] && e2.methodArguments[0].message); - InternalBDFDB.triggerQueuePatch(isSystem ? "SystemMessageOptionToolbar" : "MessageOptionToolbar", { - arguments: e2.methodArguments, - instance: {props: e2.methodArguments[0]}, - returnvalue: e2.returnValue, - methodname: "default", - type: isSystem ? "SystemMessageOptionToolbar" : "MessageOptionToolbar" + + InternalBDFDB.patchPlugin(BDFDB); + InternalBDFDB.addQueuePatches(BDFDB); + InternalBDFDB.addContextChunkObservers(BDFDB); + + if (InternalData.ModuleUtilsConfig.QueuedComponents) for (let type of InternalData.ModuleUtilsConfig.QueuedComponents) if (!PluginStores.patchQueues[type]) PluginStores.patchQueues[type] = {query: [], modules: []}; + + 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(PluginStores.loaded).filter(p => p.started).some(p => p.onSystemMessageOptionContextMenu || p.onSystemMessageOptionToolbar || 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}); + let isSystem = BDFDB.MessageUtils.isSystemMessage(e2.methodArguments[0] && e2.methodArguments[0].message); + InternalBDFDB.triggerQueuePatch(isSystem ? "SystemMessageOptionToolbar" : "MessageOptionToolbar", { + arguments: e2.methodArguments, + instance: {props: e2.methodArguments[0]}, + returnvalue: e2.returnValue, + methodname: "default", + type: isSystem ? "SystemMessageOptionToolbar" : "MessageOptionToolbar" + }); + if (menu && typeof menu.props.renderPopout == "function") { + let renderPopout = menu.props.renderPopout; + menu.props.renderPopout = BDFDB.TimeUtils.suppress((...args) => { + let renderedPopout = renderPopout(...args); + renderedPopout.props.updatePosition = _ => {}; + BDFDB.PatchUtils.patch(BDFDB, renderedPopout, "type", {after: e3 => { + let isSystem = BDFDB.MessageUtils.isSystemMessage(e3.methodArguments[0] && e3.methodArguments[0].message); + InternalBDFDB.triggerQueuePatch(isSystem ? "SystemMessageOptionContextMenu" : "MessageOptionContextMenu", { + arguments: e3.methodArguments, + instance: {props: e3.methodArguments[0]}, + returnvalue: e3.returnValue, + methodname: "default", + type: isSystem ? "SystemMessageOptionContextMenu" : "MessageOptionContextMenu" + }); + }}, {noCache: true}); + return renderedPopout; + }, "Error in Popout Render of MessageOptionToolbar!"); + } + }}, {once: true}); + }}); + + let languageChangeTimeout; + if (LibraryModules.SettingsUtilsOld) BDFDB.PatchUtils.patch(BDFDB, LibraryModules.SettingsUtilsOld, ["updateRemoteSettings", "updateLocalSettings"], {after: e => { + if (e.methodArguments[0] && e.methodArguments[0].locale) { + BDFDB.TimeUtils.clear(languageChangeTimeout); + languageChangeTimeout = BDFDB.TimeUtils.timeout(_ => { + for (let pluginName in PluginStores.loaded) if (PluginStores.loaded[pluginName].started) BDFDB.PluginUtils.translate(PluginStores.loaded[pluginName]); + }, 10000); + } + }}); + + InternalBDFDB.onSettingsClosed = function () { + if (InternalBDFDB.SettingsUpdated) { + delete InternalBDFDB.SettingsUpdated; + InternalBDFDB.forceUpdateAll(); + } + }; + + InternalBDFDB.forceUpdateAll = function () { + BDFDB.MessageUtils.rerenderAll(); + BDFDB.PatchUtils.forceAllUpdates(BDFDB); + }; + + 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" + })); + } + } }); - if (menu && typeof menu.props.renderPopout == "function") { - let renderPopout = menu.props.renderPopout; - menu.props.renderPopout = BDFDB.TimeUtils.suppress((...args) => { - let renderedPopout = renderPopout(...args); - renderedPopout.props.updatePosition = _ => {}; - BDFDB.PatchUtils.patch(BDFDB, renderedPopout, "type", {after: e3 => { - let isSystem = BDFDB.MessageUtils.isSystemMessage(e3.methodArguments[0] && e3.methodArguments[0].message); - InternalBDFDB.triggerQueuePatch(isSystem ? "SystemMessageOptionContextMenu" : "MessageOptionContextMenu", { - arguments: e3.methodArguments, - instance: {props: e3.methodArguments[0]}, - returnvalue: e3.returnValue, - methodname: "default", - type: isSystem ? "SystemMessageOptionContextMenu" : "MessageOptionContextMenu" + 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] == InternalData.myGuildId) e.returnValue.banner = `https://mwittrien.github.io/BetterDiscordAddons/Library/_res/BDFDB.banner.png`; + }}); + + BDFDB.PatchUtils.patch(BDFDB, LibraryModules.UserStore, "getUser", {after: e => { + if (e.returnValue && e.methodArguments[0] == InternalData.myId) e.returnValue.banner = `https://mwittrien.github.io/BetterDiscordAddons/Library/_res/DevilBro.banner.png`; + }}); + + BDFDB.PatchUtils.patch(BDFDB, LibraryModules.IconUtils, "getGuildBannerURL", {instead: e => { + return e.methodArguments[0].id == InternalData.myGuildId ? e.methodArguments[0].banner : e.callOriginalMethod(); + }}); + + BDFDB.PatchUtils.patch(BDFDB, LibraryModules.IconUtils, "getUserBannerURL", {instead: e => { + return e.methodArguments[0].id == InternalData.myId ? e.methodArguments[0].banner : e.callOriginalMethod(); + }}); + + BDFDB.PatchUtils.patch(BDFDB, LibraryModules.BannerUtils, "getUserBannerURLForContext", {instead: e => { + return e.methodArguments[0].user && e.methodArguments[0].user.id == InternalData.myId ? e.methodArguments[0].user.banner : e.callOriginalMethod(); + }}); + + BDFDB.PatchUtils.patch(BDFDB, LibraryModules.EmojiStateUtils, "getEmojiUnavailableReason", {after: e => { + if (InternalComponents.LibraryComponents.EmojiPickerButton.current && InternalComponents.LibraryComponents.EmojiPickerButton.current.props && InternalComponents.LibraryComponents.EmojiPickerButton.current.props.allowManagedEmojisUsage) return null; + }}); + + InternalBDFDB.forceUpdateAll(); + + const pluginQueue = window.BDFDB_Global && BDFDB.ArrayUtils.is(window.BDFDB_Global.pluginQueue) ? window.BDFDB_Global.pluginQueue : []; + + if (BDFDB.UserUtils.me.id == InternalData.myId || BDFDB.UserUtils.me.id == "350635509275557888") { + 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 = InternalBDFDB.generateClassId; + 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["function_" + 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.generateLanguageStrings = function (strings, config = {}) { + const language = config.language || "en"; + const languages = BDFDB.ArrayUtils.removeCopies(BDFDB.ArrayUtils.is(config.languages) ? config.languages : ["en"].concat((LibraryModules.LanguageStore.languages || LibraryModules.LanguageStore._languages).filter(n => n.enabled).map(n => { + if (BDFDB.LanguageUtils.languages[n.code]) return n.code; + else { + const code = n.code.split("-")[0]; + if (BDFDB.LanguageUtils.languages[code]) return code; + } + })).filter(n => n && !n.startsWith("en-") && !n.startsWith("$") && n != language)).sort(); + let translations = {}; + strings = BDFDB.ObjectUtils.sort(strings); + const stringKeys = Object.keys(strings); + translations[language] = BDFDB.ObjectUtils.toArray(strings); + let text = Object.keys(translations[language]).map(k => translations[language][k]).join("\n\n"); + + let fails = 0, next = lang => { + if (!lang) { + let formatTranslation = (l, s, i) => { + l = l == "en" ? "default" : l; + return config.cached && config.cached[l] && config.cached[l][stringKeys[i]] || (translations[language][i][0] == translations[language][i][0].toUpperCase() ? LibraryModules.StringUtils.upperCaseFirstChar(s) : s); + }; + let format = config.asObject ? ((l, isNotFirst) => { + return `${isNotFirst ? "," : ""}\n\t\t"${l == "en" ? "default" : l}": {${translations[l].map((s, i) => `\n\t\t\t"${stringKeys[i]}": "${formatTranslation(l, s, i)}"`).join(",")}\n\t\t}`; + }) : ((l, isNotFirst) => { + return `\n\t\t\t\t\t${l == "en" ? "default" : `case "${l}"`}:${l.length > 2 ? "\t" : "\t\t"}// ${BDFDB.LanguageUtils.languages[l].name}\n\t\t\t\t\t\treturn {${translations[l].map((s, i) => `\n\t\t\t\t\t\t\t${stringKeys[i]}:${"\t".repeat(10 - ((stringKeys[i].length + 2) / 4))}"${formatTranslation(l, s, i)}"`).join(",")}\n\t\t\t\t\t\t};`; }); - }}, {noCache: true}); - return renderedPopout; - }, "Error in Popout Render of MessageOptionToolbar!"); - } - }}, {once: true}); - }}); - - let languageChangeTimeout; - if (LibraryModules.SettingsUtilsOld) BDFDB.PatchUtils.patch(BDFDB, LibraryModules.SettingsUtilsOld, ["updateRemoteSettings", "updateLocalSettings"], {after: e => { - if (e.methodArguments[0] && e.methodArguments[0].locale) { - BDFDB.TimeUtils.clear(languageChangeTimeout); - languageChangeTimeout = BDFDB.TimeUtils.timeout(_ => { - for (let pluginName in PluginStores.loaded) if (PluginStores.loaded[pluginName].started) BDFDB.PluginUtils.translate(PluginStores.loaded[pluginName]); - }, 10000); - } - }}); - - InternalBDFDB.onSettingsClosed = function () { - if (InternalBDFDB.SettingsUpdated) { - delete InternalBDFDB.SettingsUpdated; - InternalBDFDB.forceUpdateAll(); - } - }; - - InternalBDFDB.forceUpdateAll = function () { - BDFDB.MessageUtils.rerenderAll(); - BDFDB.PatchUtils.forceAllUpdates(BDFDB); - }; - - 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] == InternalData.myGuildId) e.returnValue.banner = `https://mwittrien.github.io/BetterDiscordAddons/Library/_res/BDFDB.banner.png`; - }}); - - BDFDB.PatchUtils.patch(BDFDB, LibraryModules.UserStore, "getUser", {after: e => { - if (e.returnValue && e.methodArguments[0] == InternalData.myId) e.returnValue.banner = `https://mwittrien.github.io/BetterDiscordAddons/Library/_res/DevilBro.banner.png`; - }}); - - BDFDB.PatchUtils.patch(BDFDB, LibraryModules.IconUtils, "getGuildBannerURL", {instead: e => { - return e.methodArguments[0].id == InternalData.myGuildId ? e.methodArguments[0].banner : e.callOriginalMethod(); - }}); - - BDFDB.PatchUtils.patch(BDFDB, LibraryModules.IconUtils, "getUserBannerURL", {instead: e => { - return e.methodArguments[0].id == InternalData.myId ? e.methodArguments[0].banner : e.callOriginalMethod(); - }}); - - BDFDB.PatchUtils.patch(BDFDB, LibraryModules.BannerUtils, "getUserBannerURLForContext", {instead: e => { - return e.methodArguments[0].user && e.methodArguments[0].user.id == InternalData.myId ? e.methodArguments[0].user.banner : e.callOriginalMethod(); - }}); - - BDFDB.PatchUtils.patch(BDFDB, LibraryModules.EmojiStateUtils, "getEmojiUnavailableReason", {after: e => { - if (InternalComponents.LibraryComponents.EmojiPickerButton.current && InternalComponents.LibraryComponents.EmojiPickerButton.current.props && InternalComponents.LibraryComponents.EmojiPickerButton.current.props.allowManagedEmojisUsage) return null; - }}); - - InternalBDFDB.forceUpdateAll(); - - const pluginQueue = window.BDFDB_Global && BDFDB.ArrayUtils.is(window.BDFDB_Global.pluginQueue) ? window.BDFDB_Global.pluginQueue : []; - - if (BDFDB.UserUtils.me.id == InternalData.myId || BDFDB.UserUtils.me.id == "350635509275557888") { - 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 = InternalBDFDB.generateClassId; - 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["function_" + 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; + let result = Object.keys(translations).filter(n => n != "en").sort().map((l, i) => format(l, i)).join(""); + if (translations.en) result += format("en", result ? 1 : 0); + BDFDB.NotificationUtils.toast("Translation copied to clipboard", { + type: "success" + }); + LibraryRequires.electron.clipboard.write({text: result}); } - 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.generateLanguageStrings = function (strings, config = {}) { - const language = config.language || "en"; - const languages = BDFDB.ArrayUtils.removeCopies(BDFDB.ArrayUtils.is(config.languages) ? config.languages : ["en"].concat((LibraryModules.LanguageStore.languages || LibraryModules.LanguageStore._languages).filter(n => n.enabled).map(n => { - if (BDFDB.LanguageUtils.languages[n.code]) return n.code; - else { - const code = n.code.split("-")[0]; - if (BDFDB.LanguageUtils.languages[code]) return code; - } - })).filter(n => n && !n.startsWith("en-") && !n.startsWith("$") && n != language)).sort(); - let translations = {}; - strings = BDFDB.ObjectUtils.sort(strings); - const stringKeys = Object.keys(strings); - translations[language] = BDFDB.ObjectUtils.toArray(strings); - let text = Object.keys(translations[language]).map(k => translations[language][k]).join("\n\n"); - - let fails = 0, next = lang => { - if (!lang) { - let formatTranslation = (l, s, i) => { - l = l == "en" ? "default" : l; - return config.cached && config.cached[l] && config.cached[l][stringKeys[i]] || (translations[language][i][0] == translations[language][i][0].toUpperCase() ? LibraryModules.StringUtils.upperCaseFirstChar(s) : s); - }; - let format = config.asObject ? ((l, isNotFirst) => { - return `${isNotFirst ? "," : ""}\n\t\t"${l == "en" ? "default" : l}": {${translations[l].map((s, i) => `\n\t\t\t"${stringKeys[i]}": "${formatTranslation(l, s, i)}"`).join(",")}\n\t\t}`; - }) : ((l, isNotFirst) => { - return `\n\t\t\t\t\t${l == "en" ? "default" : `case "${l}"`}:${l.length > 2 ? "\t" : "\t\t"}// ${BDFDB.LanguageUtils.languages[l].name}\n\t\t\t\t\t\treturn {${translations[l].map((s, i) => `\n\t\t\t\t\t\t\t${stringKeys[i]}:${"\t".repeat(10 - ((stringKeys[i].length + 2) / 4))}"${formatTranslation(l, s, i)}"`).join(",")}\n\t\t\t\t\t\t};`; - }); - let result = Object.keys(translations).filter(n => n != "en").sort().map((l, i) => format(l, i)).join(""); - if (translations.en) result += format("en", result ? 1 : 0); - BDFDB.NotificationUtils.toast("Translation copied to clipboard", { - type: "success" - }); - LibraryRequires.electron.clipboard.write({text: result}); - } - else { - const callback = translation => { - BDFDB.LogUtils.log(lang); - if (!translation) { - console.warn("No Translation"); - fails++; - if (fails > 10) console.error("Skipped Language"); - else languages.unshift(lang); - } - else { - fails = 0; - translations[lang] = translation.split("\n\n"); - } - next(languages.shift()); - }; - LibraryRequires.request(`https://translate.googleapis.com/translate_a/single?client=gtx&sl=${language}&tl=${lang}&dt=t&dj=1&source=input&q=${encodeURIComponent(text)}`, (error, response, result) => { - if (!error && result && response.statusCode == 200) { - try {callback(JSON.parse(result).sentences.map(n => n && n.trans).filter(n => n).join(""));} - catch (err) {callback("");} - } - else { - if (response.statusCode == 429) { - BDFDB.NotificationUtils.toast("Too many Requests", { - type: "danger" - }); + else { + const callback = translation => { + BDFDB.LogUtils.log(lang); + if (!translation) { + console.warn("No Translation"); + fails++; + if (fails > 10) console.error("Skipped Language"); + else languages.unshift(lang); } else { - BDFDB.NotificationUtils.toast("Failed to translate Text", { - type: "danger" - }); - callback(""); + fails = 0; + translations[lang] = translation.split("\n\n"); } - } - }); - } + next(languages.shift()); + }; + LibraryRequires.request(`https://translate.googleapis.com/translate_a/single?client=gtx&sl=${language}&tl=${lang}&dt=t&dj=1&source=input&q=${encodeURIComponent(text)}`, (error, response, result) => { + if (!error && result && response.statusCode == 200) { + try {callback(JSON.parse(result).sentences.map(n => n && n.trans).filter(n => n).join(""));} + catch (err) {callback("");} + } + else { + if (response.statusCode == 429) { + BDFDB.NotificationUtils.toast("Too many Requests", { + type: "danger" + }); + } + else { + BDFDB.NotificationUtils.toast("Failed to translate Text", { + type: "danger" + }); + callback(""); + } + } + }); + } + }; + if (stringKeys.length) next(languages.shift()); }; - if (stringKeys.length) next(languages.shift()); - }; - BDFDB.DevUtils.req = InternalBDFDB.getWebModuleReq(); + BDFDB.DevUtils.req = InternalBDFDB.getWebModuleReq(); + + window.BDFDB = BDFDB; + } window.BDFDB = BDFDB; - } - - window.BDFDB = BDFDB; - - 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"; - } - - if (libraryCSS) BDFDB.DOMUtils.appendLocalStyle("BDFDB", libraryCSS.replace(/[\n\t\r]/g, "").replace(/\[REPLACE_CLASS_([A-z0-9_]+?)\]/g, (a, b) => BDFDB.dotCN[b])); - - BDFDB.LogUtils.log("Finished loading Library"); - - window.BDFDB_Global = Object.assign({ - started: true, - loaded: true, - PluginUtils: { - buildPlugin: BDFDB.PluginUtils.buildPlugin, - cleanUp: BDFDB.PluginUtils.cleanUp + + for (let obj in DiscordObjects) if (!DiscordObjects[obj]) { + DiscordObjects[obj] = function () {}; + BDFDB.DiscordObjects[obj] = function () {}; } - }, config); + 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"; + } + + if (libraryCSS) BDFDB.DOMUtils.appendLocalStyle("BDFDB", libraryCSS.replace(/[\n\t\r]/g, "").replace(/\[REPLACE_CLASS_([A-z0-9_]+?)\]/g, (a, b) => BDFDB.dotCN[b])); - while (PluginStores.delayed.loads.length) PluginStores.delayed.loads.shift().load(); - while (PluginStores.delayed.starts.length) PluginStores.delayed.starts.shift().start(); - while (pluginQueue.length) { - let pluginName = pluginQueue.shift(); - if (pluginName) BDFDB.TimeUtils.timeout(_ => BDFDB.BDUtils.reloadPlugin(pluginName)); + BDFDB.LogUtils.log("Finished loading Library"); + + window.BDFDB_Global = Object.assign({ + started: true, + loaded: true, + PluginUtils: { + buildPlugin: BDFDB.PluginUtils.buildPlugin, + cleanUp: BDFDB.PluginUtils.cleanUp + } + }, config); + + while (PluginStores.delayed.loads.length) PluginStores.delayed.loads.shift().load(); + while (PluginStores.delayed.starts.length) PluginStores.delayed.starts.shift().start(); + while (pluginQueue.length) { + let pluginName = pluginQueue.shift(); + if (pluginName) BDFDB.TimeUtils.timeout(_ => BDFDB.BDUtils.reloadPlugin(pluginName)); + } + }; + + const alreadyLoadedComponents = []; + if (InternalData.ForceLoadedComponents) { + let promises = []; + for (let name in InternalData.ForceLoadedComponents) { + let parentModule; + if (InternalData.ForceLoadedComponents[name].name) { + if (InternalData.ForceLoadedComponents[name].protos) parentModule = BDFDB.ModuleUtils.find(m => m && m.displayName == InternalData.ForceLoadedComponents[name].name && m.prototype && InternalData.ForceLoadedComponents[name].protos.every(proto => m.prototype[proto]) && m, {useExport: false}); + else parentModule = BDFDB.ModuleUtils.findByName(InternalData.ForceLoadedComponents[name].name, false, true); + } + else if (InternalData.ForceLoadedComponents[name].props) parentModule = BDFDB.ModuleUtils.findByProperties(InternalData.ForceLoadedComponents[name].props, false, true); + if (parentModule && parentModule.exports && alreadyLoadedComponents.indexOf(parentModule.id) > -1) { + alreadyLoadedComponents.push(parentModule.id); + promises.push(InternalBDFDB.lazyLoadModuleImports(parentModule.exports)); + } + } + Promise.all(promises).then(loadComponents); } + else loadComponents(); }; requestLibraryHashes(true); @@ -8895,7 +8947,7 @@ module.exports = (_ => { let toastInterval, toast = BDFDB.NotificationUtils.toast(loadingString, { type: "info", timeout: 0, - onClose: _ => {BDFDB.TimeUtils.clear(toastInterval);} + onClose: _ => BDFDB.TimeUtils.clear(toastInterval) }); toastInterval = BDFDB.TimeUtils.interval(_ => { currentLoadingString = currentLoadingString.endsWith(".....") ? loadingString : currentLoadingString + ".";