`), app);\n return true;\n }\n\n render() {\n const self = this;\n return BDV2.react.createElement(\n \"div\",\n {className: \"bd-detached-css-editor\", id: \"bd-customcss-detach-editor\"},\n BDV2.react.createElement(\n \"div\",\n {id: \"bd-customcss-innerpane\"},\n BDV2.react.createElement(\"div\", {className: \"editor-wrapper\"},\n BDV2.react.createElement(\"div\", {id: \"bd-customcss-editor-detached\", className: \"editor\", ref: \"editor\"}, self.css)\n ),\n BDV2.react.createElement(\n \"div\",\n {id: \"bd-customcss-attach-controls\"},\n BDV2.react.createElement(\n \"ul\",\n {className: \"checkbox-group\"},\n BDV2.react.createElement(Checkbox, {id: \"live-update\", text: \"Live Update\", onChange: self.onChange, checked: settingsCookie[\"bda-css-0\"]})\n ),\n BDV2.react.createElement(\n \"div\",\n {id: \"bd-customcss-detach-controls-button\"},\n BDV2.react.createElement(\n \"button\",\n {style: {borderRadius: \"3px 0 0 3px\", borderRight: \"1px solid #3f4146\"}, className: \"btn btn-primary\", onClick: () => {\n self.onClick(\"update\");\n }},\n \"Update\"\n ),\n BDV2.react.createElement(\n \"button\",\n {style: {borderRadius: \"0\", borderLeft: \"1px solid #2d2d2d\", borderRight: \"1px solid #2d2d2d\"}, className: \"btn btn-primary\", onClick: () => {\n self.onClick(\"save\");\n }},\n \"Save\"\n ),\n BDV2.react.createElement(\n \"button\",\n {style: {borderRadius: \"0 3px 3px 0\", borderLeft: \"1px solid #3f4146\"}, className: \"btn btn-primary\", onClick: () => {\n self.onClick(\"attach\");\n }},\n \"Attach\"\n ),\n BDV2.react.createElement(\n \"span\",\n {style: {fontSize: \"10px\", marginLeft: \"5px\"}},\n \"Unsaved changes are lost on attach\"\n )\n )\n )\n )\n );\n }\n\n onChange(id, checked) {\n switch (id) {\n case \"live-update\":\n settingsCookie[\"bda-css-0\"] = checked;\n Settings.saveSettings();\n break;\n }\n }\n\n onClick(id) {\n const self = this;\n switch (id) {\n case \"attach\":\n if (DOM.query(\"#editor-detached\")) self.props.attach();\n BDV2.reactDom.unmountComponentAtNode(self.root);\n self.root.remove();\n break;\n case \"update\":\n self.updateCss();\n break;\n case \"save\":\n self.saveCss();\n break;\n }\n }\n\n updateCss() {\n DOM.removeStyle(\"customcss\");\n DOM.addStyle(\"customcss\", this.editor.session.getValue());\n }\n\n saveCss() {\n DataStore.setBDData(\"bdcustomcss\", Buffer.from(this.editor.session.getValue(), \"utf-8\").toString(\"base64\"));\n }\n}","import {settingsCookie} from \"../0globals\";\nimport Settings from \"../modules/settingsPanel\";\nimport BDV2 from \"../modules/v2\";\nimport DataStore from \"../modules/dataStore\";\nimport DOM from \"../modules/domtools\";\nimport Utils from \"../modules/utils\"\n\nimport SettingsTitle from \"./settingsTitle\";\nimport Checkbox from \"./checkbox\";\nimport V2C_CssEditorDetached from \"./cssEditorDetached\";\n\nexport default class V2C_CssEditor extends BDV2.reactComponent {\n\n constructor(props) {\n super(props);\n const self = this;\n self.props.lines = 0;\n self.setInitialState();\n self.attach = self.attach.bind(self);\n self.detachedEditor = BDV2.react.createElement(V2C_CssEditorDetached, {attach: self.attach});\n self.onClick = self.onClick.bind(self);\n self.updateCss = self.updateCss.bind(self);\n self.saveCss = self.saveCss.bind(self);\n self.detach = self.detach.bind(self);\n }\n\n setInitialState() {\n this.state = {\n detached: this.props.detached || BDV2.editorDetached\n };\n }\n\n componentDidMount() {\n // this.updateLineCount();\n this.editor = ace.edit(\"bd-customcss-editor\");\n this.editor.setTheme(\"ace/theme/discord\");\n this.editor.session.setMode(\"ace/mode/css\");\n this.editor.setShowPrintMargin(false);\n this.editor.setFontSize(14);\n this.editor.on(\"change\", () => {\n if (!settingsCookie[\"bda-css-0\"]) return;\n this.saveCss();\n this.updateCss();\n });\n }\n\n componentWillUnmount() {\n this.editor.destroy();\n }\n\n componentDidUpdate(prevProps, prevState) {\n const self = this;\n if (prevState.detached && !self.state.detached) {\n BDV2.reactDom.unmountComponentAtNode(self.detachedRoot);\n }\n }\n\n codeMirror() {\n }\n\n get options() {\n return {\n lineNumbers: true,\n mode: \"css\",\n indentUnit: 4,\n theme: \"material\",\n scrollbarStyle: \"simple\"\n };\n }\n\n get css() {\n const _ccss = DataStore.getBDData(\"bdcustomcss\");\n let ccss = \"\";\n if (_ccss && _ccss !== \"\") {\n ccss = Buffer.from(_ccss, \"base64\").toString(\"utf8\");\n }\n return ccss;\n }\n\n updateLineCount() {\n const lineCount = this.refs.editor.value.split(\"\\n\").length;\n if (lineCount == this.props.lines) return;\n this.refs.lines.textContent = Array.from(new Array(lineCount), (_, i) => i + 1).join(\".\\n\") + \".\";\n this.props.lines = lineCount;\n }\n\n render() {\n const self = this;\n\n const {detached} = self.state;\n return [\n detached && BDV2.react.createElement(\n \"div\",\n {id: \"editor-detached\"},\n BDV2.react.createElement(SettingsTitle, {text: \"Custom CSS Editor\"}),\n BDV2.react.createElement(\n \"h3\",\n null,\n \"Editor Detached\"\n ),\n BDV2.react.createElement(\n \"button\",\n {className: \"btn btn-primary\", onClick: () => {\n self.attach();\n }},\n \"Attach\"\n )\n ),\n !detached && BDV2.react.createElement(\n \"div\",\n null,\n BDV2.react.createElement(SettingsTitle, {text: \"Custom CSS Editor\"}),\n BDV2.react.createElement(\"div\", {className: \"editor-wrapper\"},\n BDV2.react.createElement(\"div\", {id: \"bd-customcss-editor\", className: \"editor\", ref: \"editor\"}, self.css)\n ),\n BDV2.react.createElement(\n \"div\",\n {id: \"bd-customcss-attach-controls\"},\n BDV2.react.createElement(\n \"ul\",\n {className: \"checkbox-group\"},\n BDV2.react.createElement(Checkbox, {id: \"live-update\", text: \"Live Update\", onChange: this.onChange, checked: settingsCookie[\"bda-css-0\"]})\n ),\n BDV2.react.createElement(\n \"div\",\n {id: \"bd-customcss-detach-controls-button\"},\n BDV2.react.createElement(\n \"button\",\n {style: {borderRadius: \"3px 0 0 3px\", borderRight: \"1px solid #3f4146\"}, className: \"btn btn-primary\", onClick: () => {\n self.onClick(\"update\");\n }},\n \"Update\"\n ),\n BDV2.react.createElement(\n \"button\",\n {style: {borderRadius: \"0\", borderLeft: \"1px solid #2d2d2d\", borderRight: \"1px solid #2d2d2d\"}, className: \"btn btn-primary\", onClick: () => {\n self.onClick(\"save\");\n }},\n \"Save\"\n ),\n BDV2.react.createElement(\n \"button\",\n {style: {borderRadius: \"0 3px 3px 0\", borderLeft: \"1px solid #3f4146\"}, className: \"btn btn-primary\", onClick: () => {\n self.onClick(\"detach\");\n }},\n \"Detach\"\n ),\n BDV2.react.createElement(\n \"span\",\n {style: {fontSize: \"10px\", marginLeft: \"5px\"}},\n \"Unsaved changes are lost on detach\"\n ),\n BDV2.react.createElement(\"div\", {className: \"help-text\"},\n \"Press \",\n BDV2.react.createElement(\"code\", {className: \"inline\"}, \"ctrl\"),\n \"+\",\n BDV2.react.createElement(\"span\", {className: \"inline\"}, \",\"),\n \" with the editor focused to access the editor's settings.\"\n )\n )\n )\n )\n ]\n }\n\n onClick(arg) {\n const self = this;\n switch (arg) {\n case \"update\":\n self.updateCss();\n break;\n case \"save\":\n self.saveCss();\n break;\n case \"detach\":\n self.detach();\n break;\n }\n }\n\n onChange(id, checked) {\n switch (id) {\n case \"live-update\":\n settingsCookie[\"bda-css-0\"] = checked;\n Settings.saveSettings();\n break;\n }\n }\n\n updateCss() {\n DOM.removeStyle(\"customcss\");\n DOM.addStyle(\"customcss\", this.editor.session.getValue());\n }\n\n saveCss() {\n DataStore.setBDData(\"bdcustomcss\", Buffer.from(this.editor.session.getValue(), \"utf-8\").toString(\"base64\"));\n }\n\n detach() {\n const self = this;\n self.setState({\n detached: true\n });\n const droot = self.detachedRoot;\n if (!droot) {\n console.log(\"FAILED TO INJECT ROOT: .app\");\n return;\n }\n BDV2.reactDom.render(self.detachedEditor, droot);\n }\n\n get detachedRoot() {\n const _root = DOM.query(\"#bd-customcss-detach-container\");\n if (!_root) {\n if (!this.injectDetachedRoot()) return null;\n return this.detachedRoot;\n }\n return _root;\n }\n\n injectDetachedRoot() {\n const app = DOM.query(\".app, .\"+Utils.removeDa(BDModules.get(e => e.app && e.layers)[0].app));\n if (!app) return false;\n DOM.insertAfter(DOM.createElement(`
`), app);\n return true;\n }\n\n attach() {\n const self = this;\n self.setState({\n detached: false\n });\n }\n}","import BDV2 from \"../modules/v2\";\r\n\r\nexport default class BDErrorBoundary extends BDV2.reactComponent {\r\n constructor(props) {\r\n super(props);\r\n this.state = {hasError: false};\r\n }\r\n\r\n componentDidCatch() {\r\n this.setState({hasError: true});\r\n }\r\n\r\n render() {\r\n if (this.state.hasError) return BDV2.react.createElement(\"div\", {className: \"react-error\"}, \"Component Error\"); \r\n return this.props.children; \r\n }\r\n}\r\n\r\nconst originalRender = BDErrorBoundary.prototype.render;\r\nObject.defineProperty(BDErrorBoundary.prototype, \"render\", {\r\n enumerable: false,\r\n configurable: false,\r\n set: function() {console.warn(\"Addon policy for plugins #5 https://github.com/rauenzi/BetterDiscordApp/wiki/Addon-Policies#plugins\");},\r\n get: () => originalRender\r\n}); ","import BDV2 from \"../modules/v2\";\r\n\r\nexport default class V2C_ContentColumn extends BDV2.reactComponent {\r\n constructor(props) {\r\n super(props);\r\n }\r\n\r\n static get displayName() {return \"ContentColumn\";}\r\n\r\n render() {\r\n //let contentModule = BDModules.get(e => e.contentColumn)[0]\r\n let title = this.props.title ? BDV2.react.createElement(\"h2\", {className: \"ui-form-title h2 margin-reset margin-bottom-20\"}, this.props.title) : null\r\n return [\r\n title,\r\n this.props.children\r\n ]\r\n return BDV2.react.createElement(\r\n \"div\",\r\n {className: contentModule.contentColumn + \" \"+contentModule.contentColumnDefault+\" content-column default\", style: {padding: \"60px 40px 0px\"}},\r\n title,\r\n this.props.children\r\n );\r\n }\r\n}","import BDV2 from \"../modules/v2\";\r\n\r\nexport default class V2C_ReloadIcon extends BDV2.reactComponent {\r\n constructor(props) {\r\n super(props);\r\n }\r\n\r\n render() {\r\n return BDV2.react.createElement(\"svg\", {\r\n xmlns: \"http://www.w3.org/2000/svg\",\r\n viewBox: \"0 0 24 24\",\r\n fill: \"#dcddde\",\r\n className: \"bd-reload \" + this.props.className,\r\n onClick: this.props.onClick,\r\n style: {width: this.props.size || \"24px\", height: this.props.size || \"24px\"}\r\n },\r\n BDV2.react.createElement(\"path\", {d: \"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"}),\r\n BDV2.react.createElement(\"path\", {fill: \"none\", d: \"M0 0h24v24H0z\"})\r\n );\r\n }\r\n}","import BDV2 from \"../modules/v2\";\r\n\r\nexport default class V2C_XSvg extends BDV2.reactComponent {\r\n constructor(props) {\r\n super(props);\r\n }\r\n\r\n render() {\r\n return BDV2.react.createElement(\r\n \"svg\",\r\n {xmlns: \"http://www.w3.org/2000/svg\", viewBox: \"0 0 12 12\", style: {width: \"18px\", height: \"18px\"}},\r\n BDV2.react.createElement(\r\n \"g\",\r\n {className: \"background\", fill: \"none\", fillRule: \"evenodd\"},\r\n BDV2.react.createElement(\"path\", {d: \"M0 0h12v12H0\"}),\r\n BDV2.react.createElement(\"path\", {className: \"fill\", fill: \"#dcddde\", d: \"M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6\"})\r\n )\r\n );\r\n }\r\n}","import BDV2 from \"../../modules/v2\";\n\nconst React = BDV2.React;\n\nexport default class Edit extends React.Component {\n render() {\n const size = this.props.size || \"24px\";\n return
;\n }\n}","import BDV2 from \"../../modules/v2\";\n\nconst React = BDV2.React;\n\nexport default class Delete extends React.Component {\n render() {\n const size = this.props.size || \"24px\";\n return
;\n }\n}","import {settingsCookie} from \"../0globals\";\nimport BDV2 from \"../modules/v2\";\nimport Utils from \"../modules/utils\";\nimport DOM from \"../modules/domtools\";\n\nimport XSvg from \"./xSvg\";\nimport ReloadIcon from \"./reloadIcon\";\nimport EditIcon from \"./icons/edit\";\nimport DeleteIcon from \"./icons/delete\";\nimport Switch from \"./components/switch\";\nimport TooltipWrap from \"./tooltipWrap\";\nimport { processFile } from \"../modules/pluginCertifier\";\nimport contentManager from \"../modules/contentManager\";\nimport { resolve } from \"path\";\n\nconst React = BDV2.React;\nconst anchorClasses = BDV2.anchorClasses;\n\nexport default class V2C_PluginCard extends BDV2.reactComponent {\n\n constructor(props) {\n super(props);\n this.onChange = this.onChange.bind(this);\n this.showSettings = this.showSettings.bind(this);\n this.setInitialState();\n this.hasSettings = this.props.addon.plugin && typeof(this.props.addon.plugin.getSettingsPanel) === \"function\";\n this.settingsPanel = \"\";\n\n this.edit = this.edit.bind(this);\n this.delete = this.delete.bind(this);\n this.reload = this.reload.bind(this);\n }\n\n setInitialState() {\n this.state = {\n checked: this.props.enabled,\n settings: false,\n reloads: 0,\n trusted: false\n };\n }\n\n showSettings() {\n if (!this.hasSettings) return;\n this.setState({settings: true});\n }\n\n closeSettings() {\n this.panelRef.current.innerHTML = \"\";\n this.setState({settingsOpen: false});\n }\n\n componentDidUpdate() {\n if (!this.state.settings) return;\n if (typeof this.settingsPanel === \"object\") {\n this.refs.settingspanel.appendChild(this.settingsPanel);\n }\n\n if (!settingsCookie[\"fork-ps-3\"]) return;\n setImmediate(() => {\n const isHidden = (container, element) => {\n if(!container){\n console.error(new Error(`Container is undefined.`))\n return false\n }\n const cTop = container.scrollTop;\n const cBottom = cTop + container.clientHeight;\n const eTop = element.offsetTop;\n const eBottom = eTop + element.clientHeight;\n return (eTop < cTop || eBottom > cBottom);\n };\n\n const thisNode = this.refs.cardNode;\n const container = thisNode.closest(\"div[class*=\\\"contentRegionScroller-\\\"]\")\n if (!isHidden(container, thisNode)) return;\n const thisNodeOffset = DOM.offset(thisNode);\n const containerOffset = DOM.offset(container);\n const original = container.scrollTop;\n const endPoint = thisNodeOffset.top - containerOffset.top + container.scrollTop - 30;\n DOM.animate({\n duration: 300,\n update: function(progress) {\n if (endPoint > original) container.scrollTop = original + (progress * (endPoint - original));\n else container.scrollTop = original - (progress * (original - endPoint));\n }\n });\n });\n }\n\n\n getString(value) {\n if (!value) return \"???\";\n return typeof value == \"string\" ? value : value.toString();\n }\n\n get settingsComponent() {\n try { this.settingsPanel = this.props.addon.plugin.getSettingsPanel(); }\n catch (err) { Utils.err(\"Plugins\", \"Unable to get settings panel for \" + this.name + \".\", err); }\n\n return BDV2.react.createElement(\"div\", {className: \"bd-card bd-addon-card settings-open ui-switch-item\", ref: \"cardNode\"},\n BDV2.react.createElement(\"div\", {style: {\"float\": \"right\", \"cursor\": \"pointer\"}, onClick: () => {\n this.refs.settingspanel.innerHTML = \"\";\n this.setState({settings: false});\n }},\n BDV2.react.createElement(XSvg, null)\n ),\n typeof this.settingsPanel === \"object\" && BDV2.react.createElement(\"div\", {id: `plugin-settings-${this.name}`, className: \"plugin-settings\", ref: \"settingspanel\"}),\n typeof this.settingsPanel !== \"object\" && BDV2.react.createElement(\"div\", {id: `plugin-settings-${this.name}`, className: \"plugin-settings\", ref: \"settingspanel\", dangerouslySetInnerHTML: {__html: this.settingsPanel}})\n );\n }\n\n buildTitle(name, version, author) {\n const title = \"{{name}} v{{version}} by {{author}}\".split(/({{[A-Za-z]+}})/);\n const nameIndex = title.findIndex(s => s == \"{{name}}\");\n if (nameIndex) title[nameIndex] = React.createElement(\"span\", {className: \"name bda-name\"}, name);\n const versionIndex = title.findIndex(s => s == \"{{version}}\");\n if (nameIndex) title[versionIndex] = React.createElement(\"span\", {className: \"version bda-version\"}, version);\n const authorIndex = title.findIndex(s => s == \"{{author}}\");\n if (nameIndex) {\n const props = {className: \"author bda-author\"};\n if (author.link || author.id) {\n props.className += ` ${anchorClasses.anchor} ${anchorClasses.anchorUnderlineOnHover}`;\n props.target = \"_blank\";\n\n if (author.link) props.href = author.link;\n if (author.id) props.onClick = () => {BDV2.LayerStack.popLayer(); BDV2.openDM(author.id);};\n }\n title[authorIndex] = React.createElement(author.link || author.id ? \"a\" : \"span\", props, author.name);\n }\n return title.flat();\n }\n\n makeLink(title, url) {\n const props = {className: \"bda-link bda-link-website\", target: \"_blank\"};\n if (typeof(url) == \"string\") props.href = url;\n if (typeof(url) == \"function\") props.onClick = (event) => {event.preventDefault(); event.stopPropagation(); url();};\n return BDV2.react.createElement(\"a\", props, title);\n }\n\n makeButton(title, children, action) {\n return
\n {children}
\n ;\n }\n\n componentWillUnmount(){\n this.unmounted = true\n }\n\n get links() {\n const links = [];\n const addon = this.props.addon;\n if (addon.website) links.push(this.makeLink(\"Website\", addon.website));\n if (addon.source) links.push(this.makeLink(\"Source\", addon.source));\n if (addon.invite) {\n links.push(this.makeLink(\"Support Server\", () => {\n const tester = /\\.gg\\/(.*)$/;\n let code = addon.invite;\n if (tester.test(code)) code = code.match(tester)[1];\n BDV2.LayerStack.popLayer();\n BDV2.InviteActions.acceptInviteAndTransitionToInviteChannel(code);\n }));\n }\n if (addon.donate) links.push(this.makeLink(\"Donate\", addon.donate));\n if (addon.patreon) links.push(this.makeLink(\"Patreon\", addon.patreon));\n return links;\n }\n\n get footer() {\n const links = this.links;\n return (links.length || this.hasSettings) && BDV2.react.createElement(\"div\", {className: \"bd-card-footer bda-footer\"},\n BDV2.react.createElement(\"span\", {className: \"bd-addon-links bda-links\"},\n ...(links.map((element, index) => index < links.length - 1 ? [element, \" | \"] : element).flat())\n ),\n this.hasSettings && BDV2.react.createElement(\"button\", {onClick: this.showSettings, className: \"bd-button bda-settings-button\", disabled: !this.state.checked}, \"Settings\")\n );\n }\n\n onChange() {\n this.props.toggle && this.props.toggle(this.name);\n this.setState({checked: !this.state.checked});\n }\n\n edit() {this.props.edit(this.name);}\n delete() {this.props.remove(this.name);}\n reload() {this.props.reload(this.name);}\n\n get name() {return this.getString(this.props.addon.plugin ? this.props.addon.plugin.getName() : this.props.addon.name);}\n get author() {return this.getString(this.props.addon.plugin ? this.props.addon.plugin.getAuthor() : this.props.addon.author);}\n get description() {return this.getString(this.props.addon.plugin ? this.props.addon.plugin.getDescription() : this.props.addon.description);}\n get version() {return this.getString(this.props.addon.plugin ? this.props.addon.plugin.getVersion() : this.props.addon.version);}\n\n render() {\n if (this.state.settings) return this.settingsComponent;\n const {authorId, authorLink} = this.props.addon;\n\n const style = {}\n if(settingsCookie[\"fork-ps-6\"]){\n if(!this.isScanning){\n this.isScanning = true\n processFile(resolve(this.props.addon.filename.endsWith(\".plugin.js\") ? contentManager.pluginsFolder : contentManager.themesFolder, this.props.addon.filename), (result) => {\n if(this.unmounted)return\n \n this.setState({\n isTrusted: result.suspect ? \"suspect\" : true\n })\n }, () => {})\n }else{\n if(this.state.isTrusted === true){\n style.borderColor = \"#4087ed\"\n }\n if(this.state.isTrusted === \"suspect\"){\n style.borderColor = \"rgb(240, 71, 71)\"\n }\n }\n }\n \n return BDV2.react.createElement(\"div\", {className: \"bd-card bd-addon-card settings-closed ui-switch-item\", style},\n BDV2.react.createElement(\"div\", {className: \"bd-addon-header bda-header\"},\n BDV2.react.createElement(\"div\", {className: \"bd-card-title bda-header-title\"}, this.buildTitle(this.name, this.version, {name: this.author, id: authorId, link: authorLink})),\n BDV2.react.createElement(\"div\", {className: \"bd-addon-controls bda-controls\"},\n this.props.edit && this.makeButton(\"Edit\",
, this.edit),\n this.props.remove && this.makeButton(\"Delete\",
, this.delete),\n this.props.reload && this.makeButton(\"Reload\",
, this.reload),\n React.createElement(Switch, {onChange: this.onChange, checked: this.state.checked})\n )\n ),\n BDV2.react.createElement(\"div\", {className: \"bd-scroller-wrap bda-description-wrap scroller-wrap fade\"},\n BDV2.react.createElement(\"div\", {className: \"bd-scroller bd-addon-description bda-description scroller\"}, this.description)\n ),\n this.footer\n );\n }\n}\n\nconst originalRender = V2C_PluginCard.prototype.render;\nObject.defineProperty(V2C_PluginCard.prototype, \"render\", {\n enumerable: false,\n configurable: false,\n set: function() {console.warn(\"Addon policy for plugins #5 https://github.com/rauenzi/BetterDiscordApp/wiki/Addon-Policies#plugins\");},\n get: () => originalRender\n});","import BDV2 from \"../../modules/v2\";\n\nconst React = BDV2.React;\n\nexport default class DownArrow extends React.Component {\n render() {\n const size = this.props.size || \"16px\";\n return
;\n }\n}","import BDV2 from \"../../modules/v2\";\r\nimport Arrow from \"../icons/downarrow\";\r\n\r\nconst React = BDV2.React;\r\n\r\n\r\nexport default class Select extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {open: false, value: this.props.value || this.props.options[0].value};\r\n this.dropdown = React.createRef();\r\n this.onChange = this.onChange.bind(this);\r\n this.showMenu = this.showMenu.bind(this);\r\n this.hideMenu = this.hideMenu.bind(this);\r\n }\r\n\r\n showMenu(event) {\r\n event.preventDefault();\r\n this.setState({open: true}, () => {\r\n document.addEventListener(\"click\", this.hideMenu);\r\n });\r\n }\r\n\r\n hideMenu() {\r\n this.setState({open: false}, () => {\r\n document.removeEventListener(\"click\", this.hideMenu);\r\n });\r\n }\r\n\r\n onChange(value) {\r\n this.setState({value});\r\n if (this.props.onChange) this.props.onChange(value);\r\n }\r\n\r\n get selected() {return this.props.options.find(o => o.value == this.state.value);}\r\n\r\n get options() {\r\n const selected = this.selected;\r\n return
\r\n {this.props.options.map(opt => \r\n
{opt.label}
\r\n )}\r\n
;\r\n }\r\n\r\n render() {\r\n const style = this.props.style == \"transparent\" ? \" bd-select-transparent\" : \"\";\r\n const isOpen = this.state.open ? \" menu-open\" : \"\";\r\n return
\r\n
{this.selected.label}
\r\n
\r\n {this.state.open && this.options}\r\n
;\r\n }\r\n}\r\n\r\n// return
\r\n//
\r\n//
\r\n//
\r\n//
{this.selected.label}
\r\n//
\r\n//
\r\n//
\r\n// {this.state.open && this.options}\r\n//
;","import BDV2 from \"../../modules/v2\";\n\nconst React = BDV2.React;\n\nexport default class Search extends React.Component {\n render() {\n const size = this.props.size || \"16px\";\n return
;\n }\n}","import BDV2 from \"../../modules/v2\";\nimport SearchIcon from \"../icons/search\";\n\nconst React = BDV2.React;\n\nexport default class Search extends React.Component {\n constructor(props){\n super(props)\n this.state = {\n focused: false\n }\n }\n render() {\n const className = [\"bd-search-wrapper\"]\n if(this.state.focused)className.push(\"focused\")\n return
\n {\n this.setState({focused: true})\n }} onBlur={() => {\n this.setState({focused: false})\n }}/>\n \n
;\n }\n}","import ErrorBoundary from \"./errorBoundary\";\nimport ContentColumn from \"./contentColumn\";\nimport ReloadIcon from \"./reloadIcon\";\nimport AddonCard from \"./addoncard\";\nimport Dropdown from \"./components/dropdown\";\nimport Search from \"./components/search\";\n\nimport {settingsCookie, pluginCookie, themeCookie, bdplugins, bdthemes} from \"../0globals\";\nimport ContentManager from \"../modules/contentManager\";\nimport BDV2 from \"../modules/v2\";\nimport pluginModule from \"../modules/pluginModule\";\nimport themeModule from \"../modules/themeModule\";\nimport WebpackModules from \"../modules/webpackModules\";\nimport BdApi from \"../modules/bdApi\";\nimport Utils from \"../modules/utils\";\nimport TooltipWrap from \"./tooltipWrap\";\nimport bdEvents from \"../modules/bdEvents\";\nimport EmulatedTooltip from \"./tooltip\";\n\nconst Tooltip = WebpackModules.findByDisplayName(\"Tooltip\");\n\nconst React = BDV2.react;\n\nexport default class CardList extends BDV2.reactComponent {\n constructor(props) {\n super(props);\n this.state = {sort: \"name\", ascending: true, query: \"\"};\n this.isPlugins = this.props.type == \"plugins\";\n this.cookie = this.isPlugins ? pluginCookie : themeCookie;\n this.manager = this.isPlugins ? pluginModule : themeModule;\n\n this.sort = this.sort.bind(this);\n this.reverse = this.reverse.bind(this);\n this.search = this.search.bind(this);\n\n this.onAddonChanges = function(){\n this.forceUpdate()\n }\n this.onAddonChanges = this.onAddonChanges.bind(this)\n }\n\n componentDidMount(){\n const type = (this.isPlugins ? \"plugin\" : \"theme\") + \"-\"\n bdEvents.on(`${type}loaded`, this.onAddonChanges)\n bdEvents.on(`${type}unloaded`, this.onAddonChanges)\n bdEvents.on(`${type}reloaded`, this.onAddonChanges)\n }\n\n componentWillUnmount(){\n const type = (this.isPlugins ? \"plugin\" : \"theme\") + \"-\"\n bdEvents.off(`${type}loaded`, this.onAddonChanges)\n bdEvents.off(`${type}unloaded`, this.onAddonChanges)\n bdEvents.off(`${type}reloaded`, this.onAddonChanges)\n }\n\n openFolder() {\n const shell = require(\"electron\").shell;\n const open = shell.openPath || shell.openItem;\n open(this.isPlugins ? ContentManager.pluginsFolder : ContentManager.themesFolder);\n }\n\n edit(name) {\n console.log(name);\n this.manager.edit(name);\n }\n\n async delete(name) {\n const shouldDelete = await this.confirmDelete(name);\n if (!shouldDelete) return;\n this.manager.delete(name);\n }\n\n confirmDelete(name) {\n return new Promise(resolve => {\n BdApi.showConfirmationModal(\"Are You Sure?\", `Are you sure you want to delete ${name}?`, {\n danger: true,\n confirmText: \"Delete\",\n onConfirm: () => {resolve(true);},\n onCancel: () => {resolve(false);}\n });\n });\n }\n\n get sortOptions() {\n return [\n {label: \"Name\", value: \"name\"},\n {label: \"Author\", value: \"author\"},\n {label: \"Version\", value: \"version\"},\n {label: \"Recently Added\", value: \"added\"},\n {label: \"Last Modified\", value: \"modified\"},\n {label: \"File Size\", value: \"size\"},\n ];\n }\n\n get directions() {\n return [\n {label: \"Ascending\", value: true},\n {label: \"Descending\", value: false}\n ];\n }\n\n reverse(value) {\n this.setState({ascending: value});\n }\n\n sort(value) {\n this.setState({sort: value});\n }\n\n search(event) {\n this.setState({query: event.target.value.toLocaleLowerCase()});\n }\n\n getProps(addon) {\n return {\n key: this.getName(addon),\n enabled: this.cookie[this.getName(addon)],\n toggle: this.manager.toggle.bind(this.manager),\n edit: settingsCookie[\"fork-ps-7\"] ? this.edit.bind(this) : null,\n remove: this.delete.bind(this),\n addon: addon,\n hash: addon.hash\n };\n }\n\n getString(value) {\n if (!value) return \"???\";\n return typeof value == \"string\" ? value : value.toString();\n }\n\n get list(){\n return this.props.type === \"plugins\" ? Object.values(bdplugins) : Object.values(bdthemes);\n }\n\n getAddons() {\n const sortedAddons = this.list.sort((a, b) => {\n const cap = this.state.sort.charAt(0).toUpperCase() + this.state.sort.slice(1);\n const first = a.plugin && a.plugin[`get${cap}`] ? this.getString(a.plugin[`get${cap}`]()) : this.getString(a[this.state.sort]);\n const second = b.plugin && b.plugin[`get${cap}`] ? this.getString(b.plugin[`get${cap}`]()) : this.getString(b[this.state.sort]);\n if (typeof(first) == \"string\") return first.toLocaleLowerCase().localeCompare(second.toLocaleLowerCase());\n if (first > second) return 1;\n if (second > first) return -1;\n return 0;\n });\n if (!this.state.ascending) sortedAddons.reverse();\n const rendered = [];\n for (let a = 0; a < sortedAddons.length; a++) {\n const addon = sortedAddons[a];\n if (this.state.query) {\n let matches = null;\n const name = this.getName(addon);\n const author = this.getAuthor(addon);\n const description = this.getDescription(addon);\n const version = this.getVersion(addon);\n if (name) matches = name.toLocaleLowerCase().includes(this.state.query);\n if (author) matches = matches || author.toLocaleLowerCase().includes(this.state.query);\n if (description) matches = matches || description.toLocaleLowerCase().includes(this.state.query);\n if (version) matches = matches || version.toLocaleLowerCase().includes(this.state.query);\n if (!matches) continue;\n }\n const props = this.getProps(addon);\n rendered.push(
);\n }\n return rendered;\n }\n\n getName(addon) {return this.getString(addon.plugin ? addon.plugin.getName() : addon.name);}\n getAuthor(addon) {return this.getString(addon.plugin ? addon.plugin.getAuthor() : addon.author);}\n getDescription(addon) {return this.getString(addon.plugin ? addon.plugin.getDescription() : addon.description);}\n getVersion(addon) {return this.getString(addon.plugin ? addon.plugin.getVersion() : addon.version);}\n\n renderCheckUpdates(){\n if(!window.ZeresPluginLibrary)return null\n if(!window.PluginUpdates)return null\n if(typeof window.PluginUpdates.checkAll !== \"function\")return null\n if(!this.isPlugins)return null\n\n let tooltipIsShowing = false\n let tooltip\n return
\n {\n tooltipIsShowing = false\n tooltip.hide()\n }}>\n {\n try{\n Utils.showToast(\"Plugin update check in progress.\", {type: \"info\"})\n window.PluginUpdates.checkAll()\n .then(() => {\n Utils.showToast(\"Plugin update check complete.\", {type: \"success\"})\n }).catch(err => {\n console.error(err)\n Utils.showToast(\"An error occured while checking update.\", {type: \"error\"})\n })\n }catch(e){\n console.error(e)\n Utils.showToast(\"An error occured while checking update.\", {type: \"error\"})\n }\n }} wrapper={false} disabled={false} onRightClick={() => {\n if(!this.refs.checkUpdateButton)return\n if (!window.PluginUpdates || !window.PluginUpdates.plugins) return;\n if(tooltipIsShowing)return\n tooltip = new EmulatedTooltip(this.refs.checkUpdateButton.refs.original.refs.button, Object.values(window.PluginUpdates.plugins).map(p => p.name).join(\", \"), {\n side: \"bottom\",\n attachEvents: false\n })\n tooltip.show()\n tooltipIsShowing = true\n }}>\n Check for Updates\n \n \n \n }\n\n render() {\n const refreshIcon =
\n {(props) => \n {\n if (this.isPlugins) pluginModule.updatePluginList();\n else themeModule.updateThemeList();\n this.forceUpdate();\n }} />\n };\n const addonCards = this.getAddons();\n\n return
\n \n Open {this.isPlugins ? \"Plugin\" : \"Theme\"} Folder\n \n {this.renderCheckUpdates()}\n {!settingsCookie[\"fork-ps-5\"] && refreshIcon}\n \n
\n
\n
\n \n \n
\n
\n \n \n
\n \n
\n
\n {addonCards}
\n \n }\n}\n\nconst originalRender = CardList.prototype.render;\nObject.defineProperty(CardList.prototype, \"render\", {\n enumerable: false,\n configurable: false,\n set: function() {console.warn(\"Addon policy for plugins #5 https://github.com/rauenzi/BetterDiscordApp/wiki/Addon-Policies#plugins\");},\n get: () => originalRender\n});","import {settingsRPC, defaultRPC} from \"../0globals\";\r\n\r\nconst dispatcher = BDModules.get(m=>m.Dispatcher&&m.default&&m.default.dispatch)[0].default\r\nconst ActionTypes = BDModules.get(m=>m.ActionTypes)[0].ActionTypes\r\n\r\nconst socketId = \"lightcord-spoof-socket\"\r\nconst pid = process.pid\r\n\r\nexport default new class CustomRichPresence {\r\n constructor(){\r\n this.enabled = false\r\n\r\n this.game = settingsRPC\r\n }\r\n \r\n get formatedGame(){\r\n if(!this.game)return null\r\n if(this.enabled === false)return null\r\n let game = {\r\n name: this.game.name || defaultRPC.name,\r\n application_id: this.game.application_id || defaultRPC.application_id,\r\n details: this.game.details || undefined,\r\n state: this.game.state || undefined,\r\n timestamps: this.game[\"timestamps.start\"] ? {\r\n start: this.game[\"timestamps.start\"]\r\n } : undefined,\r\n assets: this.game[\"assets.large\"] ? {\r\n large_image: this.game[\"assets.large\"],\r\n small_image: this.game[\"assets.small\"] || undefined\r\n } : undefined\r\n }\r\n return game\r\n }\r\n\r\n sendGame(){\r\n dispatcher.dispatch({\r\n type: ActionTypes.LOCAL_ACTIVITY_UPDATE,\r\n socketId,\r\n pid,\r\n activity: this.formatedGame\r\n }) \r\n }\r\n\r\n enable() {\r\n if(this.enabled)return\r\n this.enabled = true\r\n console.log(\"Enabling custom RichPresence\")\r\n\r\n this.set(settingsRPC || Object.create(defaultRPC))\r\n\r\n this.sendGame()\r\n }\r\n\r\n disable() {\r\n if(!this.enabled)return\r\n this.enabled = false\r\n console.log(\"Disabling custom RichPresence\")\r\n\r\n this.sendGame()\r\n }\r\n\r\n async fetchAssets(applicationId){\r\n let assets = await BDModules.get(e => e.getAssets)[0].getAssets(applicationId)\r\n if(assets.undefined && typeof assets.undefined === \"number\"){\r\n throw new Error(\"Unknown Application\")\r\n }\r\n return assets\r\n }\r\n\r\n set(activity){\r\n this.game = activity\r\n\r\n this.sendGame()\r\n }\r\n}","import BDV2 from \"../modules/v2\";\nimport V2C_SettingsTitle from \"./settingsTitle\";\nimport V2C_SettingsGroup from \"./settingsGroup\";\nimport dataStore from \"../modules/dataStore\";\nimport { defaultRPC, settingsRPC } from \"../0globals\";\nimport CustomRichPresence from \"../modules/CustomRichPresence\"\nimport { remote } from \"electron\";\nimport MarginTop from \"./margintop\";\nimport Utils from \"../modules/utils\";\n\nconst React = BDV2.React;\n\nlet V2C_PresenceSettingsModules\nexport default class V2C_PresenceSettings extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n data: dataStore.getSettingGroup(\"rpc\") || defaultRPC,\n assets: []\n }\n\n this.preview = null\n this.isfetching = false\n if(this.state.data.application_id){\n this.fetchAssets()\n }\n\n this.assetComponents = new Set()\n }\n\n updateWhenFetched(comp){\n this.assetComponents.add(comp)\n }\n\n /**\n * \n * @param {InputText} setting \n */\n onChange(setting, value){\n let defaultSetting = RPCProps.find(e => e.id === setting.props.id)\n\n this.setState({\n data: Object.assign(settingsRPC, this.state.data, {\n [defaultSetting.id]: !!value ? value : null\n }),\n assets: this.state.assets\n })\n if(setting.props.id === \"application_id\"){\n this.fetchAssets()\n }\n\n dataStore.setSettingGroup(\"rpc\", settingsRPC);\n this.preview.forceUpdate()\n CustomRichPresence.set(settingsRPC)\n }\n\n fetchAssets(){\n if(this.isfetching === true){\n let app = this.state.data.application_id\n setTimeout(() => {\n if(this.state.data.application_id !== app){\n return\n }\n this.fetchAssets()\n }, 5000);\n }\n if(!this.state.data.application_id){\n this.setState({\n data: this.state.data,\n assets: []\n })\n this.forceUpdate()\n this.assetComponents.forEach(e => e.forceUpdate())\n return\n }\n this.isfetching = true\n CustomRichPresence.fetchAssets(this.state.data.application_id)\n .then(assets => {\n this.isfetching = false\n this.setState({\n data: this.state.data,\n assets: Object.keys(assets).map(k => {\n let asset = assets[k]\n return {\n id: asset.id,\n name: asset.name,\n type: asset.type\n }\n })\n })\n this.forceUpdate()\n this.assetComponents.forEach(e => e.forceUpdate())\n }).catch(() => {\n this.isfetching = false\n this.setState({\n data: this.state.data,\n assets: []\n })\n this.forceUpdate()\n this.assetComponents.forEach(e => e.forceUpdate())\n })\n }\n\n updatePreview(data){\n this.setState({\n data\n })\n }\n\n get modules(){\n return V2C_PresenceSettingsModules || (V2C_PresenceSettingsModules = [\n BDModules.get(e => e.marginBottom20)[0]\n ])\n }\n\n render() {\n let [\n marginModule\n ] = this.modules\n return [\n
,\n ,\n ,\n \n {/** options */}\n {this.optionsComponents}\n
,\n \n \n \n {/** preview */}\n \n
,\n ,\n ,\n \n ]\n }\n\n get optionsComponents(){\n return this._optionsComponents || (this._optionsComponents = RPCProps.map(e => {\n if(e.type === \"text\"){\n return \n }else if(e.type === \"number\"){\n let array = []/*\n if(e.id === \"timestamps.start\"){\n array.unshift( {\n DiscordNative.clipboard.copy(Date.now()+\"\")\n }} />)\n }*/\n return array\n }else if(e.type === \"choice\"){\n if([\"assets.small\", \"assets.large\"].includes(e.id)){\n return {\n return {\n value: \"asset-\"+e.id,\n label: e.name\n }\n }))}/>\n }else{\n return \"Unknown choice.\"\n }\n }\n }))\n }\n}\nconst RPCProps = [\n {\n title: \"Application ID\",\n id: \"application_id\",\n type: \"number\",\n placeholder: \"711416957718757418\"\n },\n {\n title: \"Name\",\n id: \"name\",\n type: \"text\",\n placeholder: \"Lightcord\"\n },\n {\n title: \"Details\",\n id: \"details\",\n type: \"text\",\n placeholder: \"Browsing Discord\"\n },\n {\n title: \"State\",\n id: \"state\",\n type: \"text\",\n placeholder: \"Lightcord Client\"\n },\n {\n title: \"Timestamp Start\",\n id: \"timestamps.start\",\n type: \"number\",\n get placeholder(){\n return Date.now()\n }\n },\n {\n title: \"LargeAsset\",\n id: \"assets.large\",\n type: \"choice\"\n },\n {\n title: \"SmallAsset\",\n id: \"assets.small\",\n type: \"choice\"\n },\n]\n\nlet inputTextModules\nclass InputText extends React.PureComponent {\n get modules(){\n if(inputTextModules && inputTextModules[0])return inputTextModules\n return inputTextModules = [\n BDModules.get(e => e.removeKeybind)[0],\n BDModules.get(e => e.marginBottom20)[0],\n BDModules.get(e => e.defaultMarginh5)[0],\n BDModules.get(e => e.colorStandard)[0],\n BDModules.get(e => e.size32)[0],\n BDModules.get(e => e._horizontal)[0],\n BDModules.get(e => e.inputMini)[0],\n BDModules.get(e => e.size16 && e.size20)[0],\n ]\n }\n\n constructor(props){\n super(props)\n let setting = this.props.setting\n this.state = {\n data: this.props.manager.state.data[setting.id]\n }\n\n this.input = {\n this.setState({\n data: value\n })\n if(!this.lastEdited || this.lastEdited < Date.now() - 500){\n this.props.manager.onChange(this, value)\n this.lastEdited = Date.now()\n }else if(!this.isTiming){\n this.isTiming = setTimeout(() => {\n this.props.manager.onChange(this, this.state.data)\n this.isTiming = null\n this.lastEdited = Date.now()\n }, 500);\n }\n }} type=\"text\"/>\n }\n\n render(){\n let setting = this.props.setting\n\n let [\n rowModule,\n marginModule,\n marginModule2,\n colorModule,\n sizeModule,\n flexModule,\n inputModule,\n sizeModule2,\n ] = this.modules\n\n return (\n
\n
\n {setting.title}\n
\n {this.input}\n \n
\n
)\n }\n}\n\nlet InputNumberModules\nclass InputNumber extends React.PureComponent {\n get modules(){\n return InputNumberModules || (InputNumberModules = [\n BDModules.get(e => e.removeKeybind)[0],\n BDModules.get(e => e.marginBottom20)[0],\n BDModules.get(e => e.defaultMarginh5)[0],\n BDModules.get(e => e.colorStandard)[0],\n BDModules.get(e => e.size32)[0],\n BDModules.get(e => e._horizontal)[0],\n BDModules.get(e => e.inputMini)[0],\n BDModules.get(e => e.size16 && e.size20)[0],\n BDModules.get(e => e.colorTransparent)[0],\n ])\n }\n\n constructor(props){\n super(props)\n let setting = this.props.setting\n this.state = {\n data: this.props.manager.state.data[setting.id]\n }\n\n this.input = {\n value = value.replace(/[^\\d]+/g, \"\")\n if(value == this.state.data){\n input.setValue(value)\n return\n }\n\n if(!this.lastEdited || this.lastEdited < Date.now() - 500){\n this.props.manager.onChange(this, value)\n this.lastEdited = Date.now()\n }else if(!this.isTiming){\n this.isTiming = setTimeout(() => {\n this.props.manager.onChange(this, this.state.data)\n this.isTiming = null\n this.lastEdited = Date.now()\n }, 500);\n }\n this.setState({\n data: value\n })\n }} type=\"text\"/>\n }\n\n render(){\n let setting = this.props.setting\n\n let [\n rowModule,\n marginModule,\n marginModule2,\n colorModule,\n sizeModule,\n flexModule,\n ] = this.modules\n\n\n return (\n
\n
\n {setting.title}\n
\n {this.input}\n {setting.id === \"timestamps.start\" ? \n {\n DiscordNative.clipboard.copy(Date.now()+\"\")\n }} color=\"brand\">Copy current timestamp : null}\n \n
\n
)\n }\n}\n\nlet InputChoiceModules\nclass InputChoice extends React.PureComponent {\n constructor(props){\n super(props)\n let setting = this.props.setting\n this.state = {\n data: this.props.manager.state.data[setting.id] ? \"asset-\"+this.props.manager.state.data[setting.id] : \"none\"\n }\n this.props.manager.updateWhenFetched(this)\n }\n\n onChange(value){\n if(!this.lastEdited || this.lastEdited < Date.now() - 500){\n this.props.manager.onChange(this, value === \"none\" ? null : value.replace(\"asset-\", \"\"))\n this.lastEdited = Date.now()\n }else if(!this.isTiming){\n this.isTiming = setTimeout(() => {\n this.props.manager.onChange(this, this.state.data === \"none\" ? null : this.state.data.replace(\"asset-\", \"\"))\n this.isTiming = null\n this.lastEdited = Date.now()\n }, 500);\n }\n this.setState({\n data: value\n })\n this.forceUpdate()\n }\n \n get modules(){\n return InputChoiceModules || (InputChoiceModules = [\n BDModules.get(e => e.removeKeybind)[0],\n BDModules.get(e => e.marginBottom20)[0],\n BDModules.get(e => e.defaultMarginh5)[0],\n BDModules.get(e => e.colorStandard)[0],\n BDModules.get(e => e.size32)[0],\n BDModules.get(e => e._horizontal)[0]\n ])\n }\n\n render(){\n let setting = this.props.setting\n\n let [\n rowModule,\n marginModule,\n marginModule2,\n colorModule,\n sizeModule,\n flexModule\n ] = this.modules\n \n let options = this.props.manager.state.assets.map(e => {\n return {\n value: \"asset-\"+e.id,\n label: e.name\n }\n })\n\n options.unshift({\n value: \"none\",\n label: \"No assets\"\n })\n\n return (\n
\n
\n {setting.title}\n
\n \n {/*\n
\n
)\n }\n}\n\nlet DividerModules = []\nclass Divider extends React.PureComponent {\n get modules(){\n return DividerModules&&DividerModules[0] ? DividerModules : (DividerModules = [\n BDModules.get(e => e.divider && Object.keys(e).length === 1)[0],\n BDModules.get(e => e.dividerDefault)[0]\n ])\n }\n\n render(){\n let [\n divider,\n dividerDefault\n ] = this.modules\n\n return \n }\n}\n\nclass DiscordButton extends React.Component {\n render(){\n let rowModule = BDModules.get(e => e.removeKeybind)[0]\n let marginModule = BDModules.get(e => e.marginBottom20)[0]\n let flexModule = BDModules.get(e => e._horizontal)[0]\n\n return (\n
\n \n {this.props.title}\n \n
\n
)\n }\n}\n\nclass RpcPreview extends React.Component {\n constructor(props = {}){\n super(props)\n this.state = {\n active: \"profile\"\n }\n this.tabs = []\n\n this.props.settings.preview = this\n }\n\n changeTab(tab){\n let ancientTab = this.state.active\n if(ancientTab === tab.props.id)return\n\n this.tabs.forEach(e => {\n e.setActive(false)\n })\n tab.setActive(true)\n this.setState({\n active: tab.props.id\n })\n }\n\n render(){\n return ()\n } \n\n isActive(tab){\n return this.state.active === tab\n }\n\n get preview(){\n if(this.state.active === \"profile\")return Profile\n return Popout\n }\n}\n\nclass Tab extends React.Component {\n constructor(props){\n super(props)\n\n this.state = {\n active: props.preview.isActive(props.id)\n }\n props.preview.tabs.push(this)\n }\n\n setActive(isActive){\n this.setState({\n active: !!isActive\n })\n }\n\n render(){\n let className = `lc-navItem`\n if(this.state.active){\n className += ` lc-navItemActive`\n }else{\n className += ` lc-navItemInactive`\n }\n return ({\n this.props.preview.changeTab(this)\n }}>\n {this.props.title}\n
)\n }\n}\n\nlet emptyClasses\nclass PresenceErrorCatcher extends React.Component {\n componentDidCatch(err, errInfo){\n console.error(err, errInfo)\n this.setState({\n error: true\n })\n }\n render(){\n if(!this.state){\n this.state = {\n error: false\n }\n }\n if(!this.state.error){\n try{\n const preview = new this.props.preview(this.props.props)\n preview.setState(this.props.state)\n return preview.render()\n }catch(err){\n console.error(err)\n this.state.error = true\n return this.render()\n }\n }else{\n emptyClasses = emptyClasses || BDV2.WebpackModules.find(e => e.emptyStateImage && e.emptyState)\n if(!emptyClasses){\n Utils.showToast(\"An error occured. Please check the console for more informations.\")\n return null\n }\n return \n }\n }\n}\n\nlet popoutModules\nlet UserPopoutComponent\nlet PopoutProps\nclass Popout extends React.Component {\n get modules(){\n return popoutModules || (popoutModules = [\n BDV2.WebpackModules.find(e => e.default && e.default.displayName === \"UserPopout\"),\n BDV2.WebpackModules.find(e => e.default && e.default.getCurrentUser)\n ])\n }\n\n getComponent(){\n let [\n UserPopout,\n userModule\n ] = this.modules\n\n const user = userModule.default.getCurrentUser()\n return React.createElement(() => {\n let render1 = UserPopout.default({\n userId: user.id, \n guildId: null, \n channelId: null, \n disableUserProfileLink: true\n })\n UserPopoutComponent = render1.type\n PopoutProps = render1.props\n return this.render()\n }, null)\n }\n\n render(){\n if(!UserPopoutComponent)return this.getComponent()\n let [\n _UserPopout,\n userModule\n ] = this.modules\n\n const user = userModule.default.getCurrentUser()\n\n let data = Object.assign({}, defaultRPC, this.props.preview.props.settings.state.data)\n const activity = (function(){\n if(!this.game)return null\n let game = {\n name: this.game.name || defaultRPC.name,\n application_id: this.game.application_id || defaultRPC.application_id,\n details: this.game.details || undefined,\n state: this.game.state || undefined,\n timestamps: this.game[\"timestamps.start\"] ? {\n start: this.game[\"timestamps.start\"]\n } : undefined,\n assets: this.game[\"assets.large\"] ? {\n large_image: this.game[\"assets.large\"],\n small_image: this.game[\"assets.small\"] || undefined\n } : undefined,\n type: 0\n }\n return game\n }).call({\n game: data\n })\n\n const popout = new UserPopoutComponent(Object.assign({}, PopoutProps, {\n activity: activity,\n userId: user.id\n })).render().props.children // bypass tracking\n\n // remove the stop propagation shit.\n const container = \n\n return \n {container}\n
\n }\n}\n\nlet profileModules\nlet UserProfileComponent\nlet ProfileProps\nlet connectedProfileStore\nclass Profile extends React.Component {\n get modules(){\n return profileModules || (profileModules = [\n BDV2.WebpackModules.find(e => e.default && e.default.displayName === \"UserProfile\"),\n BDV2.WebpackModules.find(e => e.default && e.default.getCurrentUser)\n ])\n }\n\n render(){\n let [\n UserProfile,\n userModule\n ] = this.modules\n\n const user = userModule.default.getCurrentUser()\n if(!UserProfileComponent){\n const render1 = new UserProfile.default({\n user: user\n }).render()\n connectedProfileStore = render1.type\n const render2 = new render1.type(render1.props).render()\n const render3 = render2.type.render(render2.props, null)\n const render4 = new render3.type(render3.props).render()\n UserProfileComponent = render4.type\n }\n if(!UserProfileComponent)throw new Error(`Couldn't find the UserProfileComponent component.`)\n\n let data = Object.assign({}, defaultRPC, this.props.preview.props.settings.state.data)\n const activity = (function(){\n if(!this.game)return null\n let game = {\n name: this.game.name || defaultRPC.name,\n application_id: this.game.application_id || defaultRPC.application_id,\n details: this.game.details || undefined,\n state: this.game.state || undefined,\n timestamps: this.game[\"timestamps.start\"] ? {\n start: this.game[\"timestamps.start\"]\n } : undefined,\n assets: this.game[\"assets.large\"] ? {\n large_image: this.game[\"assets.large\"],\n small_image: this.game[\"assets.small\"] || undefined\n } : undefined,\n type: 0\n }\n return game\n }).call({\n game: data\n })\n\n ProfileProps = new connectedProfileStore({\n user: user,\n close: () => {}\n }).render().props\n const profile = new UserProfileComponent(Object.assign({}, ProfileProps, {\n activity: activity\n })).render().props.children // bypass tracking\n\n profile.props.style = {\n width: \"auto\"\n }\n\n return \n {profile}\n
\n }\n}","import BDV2 from \"../modules/v2\";\nimport V2C_SettingsTitle from \"./settingsTitle\";\n\n/**\n * @type {typeof import(\"react\")}\n */\nconst React = BDV2.React;\n\nlet marginModule2 = BDModules.get(e => e.defaultMarginh5)[0]\nlet colorModule = BDModules.get(e => e.colorStandard)[0]\nlet sizeModule = BDModules.get(e => e.size32)[0]\nlet scrollbarModule1 = BDModules.get(e => e.scrollbarGhostHairline)[0]\nconst GuildModule = BDModules.get(e => e.default && e.default.getGuilds)[0].default\nconst relationShipModule = BDModules.get(e => e.default && e.default.getRelationships)[0].default\nconst sessionModule = BDModules.get(e => e.default && e.default.getSessions)[0].default\nconst userModule = BDModules.get(e => e.default && e.default.getCurrentUser)[0].default\n\nexport default class V2C_AccountInfos extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n if(!marginModule2)marginModule2 = BDModules.get(e => e.defaultMarginh5)[0]\n if(!colorModule)colorModule = BDModules.get(e => e.colorStandard)[0]\n if(!sizeModule)sizeModule = BDModules.get(e => e.size32)[0]\n return [\n ,\n \n
\n Profile\n
\n \n \n Statistics\n
\n \n \n Connected Sessions\n
\n \n ,\n e.marginBottom20)[0].marginBottom20}>
\n ]\n }\n\n getSessionValue(){\n const sessionsRaw = sessionModule.getSessions()\n const sessions = Object.keys(sessionsRaw).filter(e => e !== \"all\").map(e => sessionsRaw[e])\n\n if(sessions.length === 0)return \"- No session detected. Please try in a few seconds\"\n \n return sessions.map(e => {\n return `+ id: ${e.sessionId}\n+ os: ${e.clientInfo.os[0].toUpperCase()+e.clientInfo.os.slice(1)}\n+ client: ${e.clientInfo.client}\n+ status: ${e.status}\n+ Activities: ${e.activities.length}`\n }).join(\"\\n\"+\"-\".repeat(38)+\"\\n\")\n }\n\n getProfileValue(){\n const user = userModule.getCurrentUser()\n /**\n * @type {Date}\n */\n const createdAt = user.createdAt\n\n let avatarURL = user.avatarURL\n if(user.avatar && user.avatar.startsWith(\"a_\")){\n avatarURL = user.getAvatarURL(\"gif\")\n }\n\n if(avatarURL.startsWith(\"/\")){\n avatarURL = \"https://discord.com\"+avatarURL\n }\n if(avatarURL.endsWith(\"?size=128\")){\n avatarURL = avatarURL.replace(\"?size=128\", \"?size=4096\")\n }\n\n return `+ Username: ${user.username}\n+ Discriminator: ${user.discriminator}\n+ Tag: ${user.tag}\n+ ID: ${user.id}\n+ Avatar: ${user.avatar}\n+ Avatar URL: ${avatarURL}\n+ Creation Date: ${(createdAt.getDate()).toString().padStart(2, \"0\")}/${(createdAt.getMonth()+1).toString().padStart(2, \"0\")}/${(createdAt.getFullYear()).toString().padStart(2, \"0\")} ${createdAt.getHours().toString().padStart(2, \"0\")}h ${createdAt.getMinutes().toString().padStart(2, \"0\")}min ${createdAt.getSeconds()}s\n+ Flags: ${user.flags}\n+ Has Nitro: ${user.hasPremiumSubscription ? \"Yes\" : \"No\"}\n- Email: ${user.email}\n- 2FA: ${user.mfaEnabled ? \"Yes\" : \"No\"}\n- Has Been On Mobile: ${user.mobile ? \"Yes\" : \"No\"}\n- Phone: ${user.phone || \"None\"}\n- Verified: ${user.verified}\n- Can See NSFW Channels: ${user.nsfwAllowed}`;\n }\n\n getStatistics(){\n\n const guilds = Object.values(GuildModule.getGuilds())\n const relations = Object.keys(relationShipModule.getRelationships())\n const friends = relations.filter(e => relationShipModule.isFriend(e))\n const blocked = relations.filter(e => relationShipModule.isBlocked(e))\n\n return `+ Server Count: ${guilds.length} servers\n+ Relations: ${relations.length} relations\n+ Friends Count: ${friends.length} friends\n- Blocked Users Count: ${blocked.length} blocked users`\n }\n}\n\n\nlet hightlightJS = BDModules.get(e => e.highlight)[0]\nlet messageModule1 = BDModules.get(e => e.markup)[0]\nlet messageModule2 = BDModules.get(e => e.messageContent)[0]\n\nclass CodeContent extends React.Component {\n render(){\n if(!messageModule1)messageModule1 = BDModules.get(e => e.markup)[0]\n if(!messageModule2)messageModule2 = BDModules.get(e => e.messageContent)[0]\n if(!scrollbarModule1)scrollbarModule1 = BDModules.get(e => e.scrollbarGhostHairline)[0]\n if(!hightlightJS)hightlightJS = BDModules.get(e => e.listLanguages)[0]\n return (\n
\n \n\n
\n
\n
e.marginBottom8)[0].marginBottom8}>
\n
)\n }\n}","import Utils from \"./utils\"\n\nconst dispatcher = window.Lightcord.DiscordModules.dispatcher\nconst ChannelModule = BDModules.get(e => e.default && e.default.getChannel && e.default.hasChannel)[0].default\nlet relationShipModule = BDModules.get(e => e.default && e.default.addRelationship)[0]\nlet DMModule = BDModules.get(e => e.default && e.default.closePrivateChannel)[0]\n\nconst blocked = {}\n\nlet userModule = BDModules.get(e => e.default && e.default.getCurrentUser)[0]\nfunction getCurrentUser(){\n if(userModule)return userModule.default.getCurrentUser()\n return null\n}\n\nexport default new class AntiBotDM {\n constructor(){\n this.antiDM = this.antiDM.bind(this)\n this.enabled = false\n }\n\n enable(){\n if(this.enabled)return\n this.enabled = true\n\n dispatcher.subscribe(\"MESSAGE_CREATE\", this.antiDM)\n }\n\n disable(){\n if(!this.enabled)return\n this.enabled = false\n\n dispatcher.unsubscribe(\"MESSAGE_CREATE\", this.antiDM)\n }\n\n antiDM(ev){\n if(!ev.message.author.bot)return\n if(ev.message.author.id === getCurrentUser().id)\n if(ev.message.guild_id)return\n\n const channel = ChannelModule.getChannel(ev.message.channel_id)\n if(!channel)return // might be broken\n\n if(channel.type !== 1)return\n\n if(blocked[ev.message.author.id])return // If the user unblock the bot, Don't block it again.\n\n if(scanMessage(ev.message)){\n blocked[ev.message.author.id] = true\n Utils.showToast(`[AdBlock]: Blocked ${ev.message.author.username}#${ev.message.author.discriminator}`, {\n \"type\": \"warning\"\n })\n if(!relationShipModule)relationShipModule = BDModules.get(e => e.default && e.default.addRelationship)[0]\n relationShipModule.default.addRelationship(ev.message.author.id, {\n location: \"ContextMenu\"\n }, 2)\n if(!DMModule)DMModule = BDModules.get(e => e.default && e.default.closePrivateChannel)[0]\n DMModule.default.closePrivateChannel(channel.id, false)\n }\n }\n}\n\nfunction scanMessage(message){\n if(/(discord\\.gg|discord\\.com\\/invite\\/|discordapp\\.com\\/invite\\/)/g.test(message.content))return true\n if(EmbedsContains(message, \"discord.gg/\") || EmbedsContains(message, \"discord.com/invite/\") || EmbedsContains(message, \"discordapp.com/invite/\"))return true\n\n return false\n}\nfunction EmbedsContains(message, search){\n let embeds = message.embeds || []\n if(embeds.length === 0)return false\n return embeds.map(embed => {\n if(embed.type !== \"rich\")return false\n if((embed.title || \"\").includes(search))return true\n if((embed.description || \"\").includes(search))return true\n if(((embed.footer || \"\") && embed.footer.text || \"\").includes(search))return true\n if((embed.fields || []).map(e => {\n return e.value.includes(search) || e.name.includes(search)\n }).includes(true))return true\n return false\n\n }).includes(true)\n}","/**\n * Credits to @hellbound1337 on github for the css\n */\n\nimport DOMTools from \"./domtools\"\nimport Utils from \"./utils\"\n\nlet selectors\nconst removeDa = Utils.removeDa\nfunction getSelectors(){\n let standardSidebarView = BDModules.get(e => e.standardSidebarView)[0]\n if(!standardSidebarView)return null\n let defaultClassName = removeDa(standardSidebarView.standardSidebarView)\n let selects = []\n let userSettingsAccount = BDModules.get(e => e.userSettingsAccount)[0]\n const children = BDModules.get(e => typeof e.children === \"string\")[0]\n selects.push(`#app-mount .${defaultClassName} .payment-info .${removeDa(BDModules.get(e => e.description && typeof e.description === \"string\" && e.description.includes(\"formText\"))[0].description)}`)\n selects.push(`#app-mount .${defaultClassName} .${removeDa(BDModules.get(e => e.paymentSourceRow)[0].paymentSourceRow)} .${removeDa(BDModules.get(e => e.subText && e.descriptionWrapper)[0].subText)}`)\n if(userSettingsAccount){\n selects.push(`#app-mount .${defaultClassName} .${removeDa(userSettingsAccount.userSettingsAccount)} div:nth-child(2)>div:nth-child(2)>.${removeDa(BDModules.get(e => e.viewBody)[0].viewBody)}`)\n selects.push(`.${removeDa(userSettingsAccount.userSettingsSecurity)} .${removeDa(children.children)} > div:nth-child(2)`)\n }\n return selects\n}\n\nexport default new class BlurPrivate {\n constructor(){\n this.enabled = false\n }\n\n enable(){\n if(this.enabled)return\n this.enabled = true\n selectors = selectors || getSelectors()\n\n if(!selectors)console.error(new Error(\"Couldn't find selectors to blur personnal informations.\"))\n DOMTools.addStyle(\"blurPrivate\", `\n${selectors.join(\", \")} {\n transition: all 150ms cubic-bezier(.55,.085,.68,.53);\n filter: blur(4px);\n opacity: .8;\n}\n\n${selectors.map(e => e+\":hover\").join(\", \")} {\n transition: all 150ms cubic-bezier(.55,.09,.68,.53);\n filter: none;\n opacity: 1;\n}`)\n }\n\n disable(){\n if(!this.enabled)return\n this.enabled = false\n DOMTools.removeStyle(\"blurPrivate\")\n }\n}","export default new class DisableTyping {\r\n constructor(){\r\n window.Lightcord.Api.ensureExported(e => e.default && e.default.startTyping)\r\n .then(typingModule => {\r\n let self = this\r\n const startTyping = typingModule.default.startTyping\r\n typingModule.default.startTyping = function(){\r\n if(self.disabled)return startTyping.call(this, ...arguments)\r\n }\r\n const stopTyping = typingModule.default.stopTyping\r\n typingModule.default.stopTyping = function(){\r\n if(self.disabled)return stopTyping.call(this, ...arguments)\r\n }\r\n this.disabled = true\r\n })\r\n window.Lightcord.BetterDiscord.DisableTyping = this\r\n }\r\n\r\n disable(){\r\n this.disabled = true\r\n }\r\n\r\n enable(){\r\n this.disabled = false\r\n }\r\n}","// Good luck to read my code, Even me can't read it properly.\n\nimport { stat } from \"fs\"\nimport { uuidv4 } from \"../modules/distant\"\nimport webpackModules from \"../modules/webpackModules\"\nimport { remote } from \"electron\"\nimport MarginTop from \"./margintop\"\n\nlet formModule\nexport default class ApiPreview extends React.PureComponent {\n constructor(){\n super(...arguments)\n this.state = {\n states: []\n }\n }\n\n render(){\n if(!formModule)formModule = webpackModules.find(e => e.FormSection)\n /** \n * @type {Function[]}\n */\n const allComponents = [...new Set(Object.keys(window.Lightcord.Api.Components).map(e => {\n return Object.keys(window.Lightcord.Api.Components[e]).map(k => window.Lightcord.Api.Components[e][k])\n }).flat())]\n return [\n \n \n These components are here for the plugin devs. They can quickly embed any component below with this panel.\n \n All these components have error handling. If you want none, add `.original` after the component path.\n We do not recommend modifying these component with plugins. Only do this if you know what you are doing.\n \n \n {\n remote.shell.openExternal(\"https://lightcord.org/LightcordApi/\")\n }} wrapper={false}>\n Documentation\n \n ,\n allComponents.map(comp => {\n const compName = comp.displayName || comp.name\n const compPath = `Lightcord.Api.Components.${Object.keys(window.Lightcord.Api.Components).find(e => window.Lightcord.Api.Components[e][compName])}.${compName}`\n return \n })\n ]\n }\n\n get renders(){\n\n }\n}\n\nclass ComponentPreview extends React.Component {\n constructor(props){\n super(props)\n this.state = {\n tab: \"preview\",\n elem: props.comp,\n options: {}\n }\n }\n\n render(){\n const comp = this.props.comp\n let AllPreviews = []\n if(comp.AllPreviews)AllPreviews = comp.AllPreviews\n let state = this.state\n let getProps = () => {\n let final = {}\n AllPreviews.forEach(category => {\n final[Object.keys(category[0])[0]] = category[0][Object.keys(category[0])[0]]\n })\n Object.keys(state.options).forEach(key => {\n final[key] = AllPreviews.find(e => e.find(e => e[key]))[state.options[key]][key]\n })\n return final\n }\n let renderPreview = () => {\n return \n
\n {React.createElement(comp, getProps())}\n
\n
\n }\n let renderCode = () => {\n return \n
\n \n JSX\n \n \n {React.createElement(() => {\n return \n })}\n \n \n React\n \n \n {React.createElement(() => {\n return \n })}\n \n
\n
\n }\n let getStrForProp = (value, compPath, lang) => {\n if(typeof value === \"string\"){\n return value\n }else if(typeof value === \"boolean\"){\n return String(value)\n }else if(typeof value === \"function\"){\n return value.toString()\n }else if(typeof value === \"object\"){\n if(value && value.$$typeof && (value.$$typeof === Symbol.for(\"react.element\") || value.$$typeof === 0xeac7)){\n if(compPath === \"Lightcord.Api.Components.general.Tabs\"){\n if(lang === \"react\"){\n return `React.createElement(\"div\", {style: {\nmarginTop: \"20px\", marginBottom: \"20px\"\n}},\nReact.createElement(\"div\", {style: {\nbackgroundColor: \"var(--background-secondary)\",\npadding: \"30px 30px\",\nborderRadius: \"8px\"\n}, className: \"lc-tab-box-shadow\" },\nReact.createElement(Lightcord.Api.Components.general.Title, null, \"Preview tabs\")\n)\n)`\n }else if(lang === \"jsx\"){\n return ``\n }\n }\n return \"Your components here.\"\n }\n return JSON.stringify(value, null, \" \")\n }else if(typeof value === \"number\"){\n return String(value)\n }\n return String(value)\n }\n let generateCode = function(lang){ // code formatting is hard\n const compName = comp.displayName || comp.name\n let categories = Object.keys(window.Lightcord.Api.Components)\n const compCategory = categories.find(e => window.Lightcord.Api.Components[e][compName])\n const compPath = `Lightcord.Api.Components.${compCategory}.${compName}`\n const props = getProps()\n\n if(lang === \"jsx\"){\n let propStrings = []\n let childrenProp = null\n Object.keys(props).forEach(key => {\n if(key == \"children\"){\n childrenProp = getStrForProp(props[key], compPath, lang)\n }else{\n let str = key+\"=\"\n if(typeof props[key] === \"string\"){\n str += JSON.stringify(props[key])\n }else{\n str += `{${getStrForProp(props[key], compPath, lang)}}`\n }\n propStrings.push(str)\n }\n })\n let openTag\n if(childrenProp){\n openTag = `<${compPath} ${propStrings.join(\" \")}>`\n let closeTag = `${compPath}>`\n return `${openTag}\\n ${childrenProp}\\n${closeTag}`\n }else{\n openTag = `<${compPath} ${propStrings.join(\" \")}/>`\n return openTag\n }\n }else if(lang === \"react\"){\n let children = props.children || null\n delete props.children\n if(children && children.$$typeof && (children.$$typeof === Symbol.for(\"react.element\") || children.$$typeof === 0xeac7)){\n children = getStrForProp(children, compPath, lang)\n }\n let propStrings = []\n Object.keys(props).forEach(key => {\n let visibleKey = /[^\\w\\d_]/g.test(key) ? JSON.stringify(key) : key\n let str = visibleKey+\": \"\n if(typeof props[key] === \"string\"){\n str += JSON.stringify(props[key])\n }else{\n str += getStrForProp(props[key], compPath, lang).split(\"\\n\").map((str, i) => {\n if(i === 0)return str\n return \" \" + str\n }).join(\"\\n\")\n }\n propStrings.push(str)\n })\n let propObject = \"{\"\n if(propStrings.length){\n propStrings.forEach((str, i) => {\n let isLast = i === propStrings.length - 1\n let isFirst = i === 0\n if(!isFirst){\n propObject += \",\"\n }\n propObject += \"\\n \"\n propObject += str\n if(isLast){\n propObject +=\"\\n}\"\n }\n })\n }else{\n propObject += \"}\"\n }\n let childrenData = typeof children === \"string\" && children.startsWith(\"React.createElement\") ? children : JSON.stringify(children)\n return `React.createElement(${compPath}, ${propObject}, ${childrenData})`\n }\n }\n let help = comp.help || {}\n let info = help.info ? \n {help.info}\n : null\n let warn = help.warn ? \n {help.warn}\n : null\n let danger = help.danger ? \n {help.danger}\n : null\n let error = help.error ? \n {help.error}\n : null\n let success = help.success ? \n {help.success}\n : null\n return (\n
\n {comp.displayName || comp.name}\n \n {info}\n {success}\n {warn}\n {error}\n {danger}\n {AllPreviews.map(category => {\n if(category[0].onClick)return null\n if(category[0].text)return null\n if(category[0].children)return null\n if(category.length === 1)return null\n \n let key = Object.keys(category[0])[0]\n return [\n
\n {key}\n ,\n
{\n return {\n value: \"opt-\"+index,\n label: JSON.stringify(e[Object.keys(e)[0]])\n }\n })} value={\"opt-\"+(state.options[key] || \"0\")} onChange={(value) => {\n this.setState({\n options: Object.assign({}, state.options, {\n [key]: (value.value || \"0\").replace(\"opt-\", \"\")\n })\n })\n }} searchable={true}/>,\n \n ]\n })}\n {\n this.setState({\n tab\n })\n }}/>\n )\n }\n}","{/* */}\n\nimport BDV2 from \"../../modules/v2\";\n\nconst React = BDV2.React;\n\nexport default class History extends React.Component {\n render() {\n const size = this.props.size || \"18px\";\n return ;\n }\n}","import { themeCookie } from \"../0globals\"\nimport bdEvents from \"./bdEvents\"\nimport DOM from \"./domtools\"\n\nexport default new class popoutWindow {\n constructor(){\n /**\n * @type {Map}\n */\n this.windows = new Map()\n this.enabled = false\n this.init()\n }\n\n async init(){\n let popoutModule = await window.Lightcord.Api.ensureExported(e => e.default && e.default.getWindow)\n window.Lightcord.DiscordModules.dispatcher.subscribe(\"POPOUT_WINDOW_OPEN\", (ev) => {\n setImmediate(() => {\n /**\n * @type {Window}\n */\n const window = popoutModule.default.getWindow(ev.key)\n this.windows.set(ev.key, window)\n\n let classList = window.document.body.classList\n classList.add(\"window-popout\")\n classList.add(\"lightcord\")\n classList.add(\"lightcord\")\n\n this.update(ev.key)\n })\n })\n window.Lightcord.DiscordModules.dispatcher.subscribe(\"POPOUT_WINDOW_CLOSE\", (ev) => {\n setImmediate(() => {\n this.windows.delete(ev.key)\n })\n })\n bdEvents.on(\"theme-enabled\", () => {\n this.update()\n })\n bdEvents.on(\"theme-disabled\", () => {\n this.update()\n })\n bdEvents.on(\"theme-reloaded\", () => {\n this.update()\n })\n bdEvents.on(\"theme-unloaded\", () => {\n this.update()\n })\n bdEvents.on(\"theme-loaded\", () => {\n this.update()\n })\n }\n\n enable(){\n this.enabled = true\n this.update()\n }\n\n disable(){\n this.enabled = false\n this.update()\n }\n\n update(key){\n if(!this.windows.size)return\n if(!this.enabled){\n return this.removeThemes(key)\n }else{\n return this.applyThemes(key)\n }\n }\n\n removeThemes(key){\n if(this.enabled)return\n if(key){\n let window = this.windows.get(key)\n if(!window)return\n let document = window.document\n\n for(let style of document.querySelectorAll(\"style[data-lightcord-theme=true]\")){\n style.remove()\n }\n }else{\n for(let key of this.windows.keys()){\n this.removeThemes(key)\n }\n }\n }\n\n applyThemes(key){\n if(!this.enabled)return\n if(key){\n let window = this.windows.get(key)\n if(!window)return\n let document = window.document\n\n for(let style of document.querySelectorAll(\"style[data-lightcord-theme=true]\")){\n style.setAttribute(\"will-remove\", \"true\")\n }\n\n Object.keys(bdthemes)\n .forEach(themeName => {\n if(!themeCookie[themeName])return // theme disabled\n const theme = bdthemes[themeName]\n if(!theme)return //:shrug:\n\n let existing = document.querySelector(\"style[data-lightcord-theme=true]#\"+DOM.escapeID(theme.id))\n if(existing){\n existing.innerHTML = unescape(theme.css)\n existing.removeAttribute(\"will-remove\")\n }else{\n const style = document.createElement(\"style\")\n style.id = DOM.escapeID(theme.id)\n style.innerHTML = unescape(theme.css)\n style.setAttribute(\"data-lightcord-theme\", \"true\")\n document.head.append(style)\n }\n })\n\n for(let style of document.querySelectorAll(\"style[will-remove=true]\")){\n style.remove()\n }\n }else{\n for(let key of this.windows.keys()){\n this.applyThemes(key)\n }\n }\n }\n}","import BDV2 from \"../../modules/v2\";\r\n\r\nconst React = BDV2.React;\r\n\r\nexport default class TextInput extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {value: this.props.value};\r\n this.onChange = this.onChange.bind(this);\r\n this.emitChange = this.emitChange.bind(this);\r\n this.input = \r\n }\r\n\r\n onChange(value) {\r\n console.log(value, this.props)\r\n if (this.props.disabled) return;\r\n this.props.onChange(value);\r\n this.setState({value: value});\r\n }\r\n\r\n emitChange(){\r\n console.log(`Should emit changes.`)\r\n }\r\n\r\n render() {\r\n return this.input\r\n }\r\n}","import BDV2 from \"../modules/v2\";\r\nimport TextInput from \"./components/textinput\";\r\n\r\nlet classnames = []\r\nfunction getClassName(name){\r\n let className = classnames.find(e => e.startsWith(name+\"-\"))\r\n if(className)return className\r\n className = BDModules.get(e => e[name])[0][name]\r\n classnames.push(className)\r\n return className\r\n}\r\n\r\nexport default class TextInputSetting extends BDV2.reactComponent {\r\n\r\n constructor(props) {\r\n super(props);\r\n this.onChange = this.onChange.bind(this);\r\n }\r\n\r\n onChange(value) {\r\n this.props.onChange(this.props.id, value);\r\n }\r\n\r\n render() {\r\n let {text, info} = this.props.data;\r\n if(this.props.data.experimental){\r\n if(!classnames.find(e => e.startsWith(\"beta-\"))){\r\n classnames.push(BDModules.get(e => e.beta && (!e.container && !e.userSettingsVoice))[0].beta)\r\n }\r\n info = [\r\n info,\r\n (EXPERIMENTAL)\r\n ]\r\n }\r\n return \r\n
\r\n
\r\n {text}\r\n
\r\n \r\n \r\n
\r\n {info}\r\n
\r\n
\r\n }\r\n}","import {settings, settingsCookie, settingsRPC, lightcordSettings} from \"../0globals\";\nimport DataStore from \"./dataStore\";\nimport V2_SettingsPanel_Sidebar from \"./settingsPanelSidebar\";\nimport Utils from \"./utils\";\nimport BDV2 from \"./v2\";\nimport ContentManager from \"./contentManager\";\nimport coloredText from \"./coloredText\";\nimport tfHour from \"./24hour\";\nimport DOM from \"./domtools\";\n\nimport publicServersModule from \"./publicServers\";\nimport voiceMode from \"./voiceMode\";\nimport ClassNormalizer from \"./classNormalizer\";\nimport dMode from \"./devMode\";\n\nimport SectionedSettingsPanel from \"../ui/sectionedSettingsPanel\";\nimport CssEditor from \"../ui/cssEditor\";\nimport CardList from \"../ui/addonlist\";\nimport V2C_PresenceSettings from \"../ui/presenceSettings\";\nimport CustomRichPresence from \"./CustomRichPresence\";\nimport V2C_AccountInfos from \"../ui/AccountInfos\";\nimport { remote, ipcRenderer } from \"electron\";\nimport AntiAdDM from \"./AntiAdDM\";\nimport blurPrivate from \"./blurPrivate\";\nimport disableTyping from \"./disableTyping\";\nimport ApiPreview from \"../ui/ApiPreview\";\nimport Switch from \"../ui/switch\";\nimport MarginTop from \"../ui/margintop\";\nimport webpackModules from \"./webpackModules\";\nimport tooltipWrap from \"../ui/tooltipWrap\";\nimport History from \"../ui/icons/history\";\nimport core from \"./core\";\nimport popoutWindow from \"./popoutWindow\";\nimport TextInputSetting from \"../ui/TextInputSetting\";\n\nclass BDSidebarHeader extends React.PureComponent {\n render(){\n let sidebarComponents = webpackModules.find(e => e.Separator && e.Header && e.Item)\n\n const changelogButton = React.createElement(tooltipWrap, {color: \"black\", side: \"top\", text: \"Changelog\"}, \n React.createElement(\"span\", {style: {float: \"right\", cursor: \"pointer\"}, className: \"bd-changelog-button\", onClick: () => {Utils.showChangelogModal(bbdChangelog);}},\n React.createElement(History, {className: \"bd-icon\", size: \"16px\"})\n )\n );\n let rendered = new sidebarComponents.Header({\n children: React.createElement(\"span\", null, \"Bandaged BD\", changelogButton),\n className: \"ui-tab-bar-header\"\n })\n return rendered\n }\n}\n\nlet isClearingCache = false\n\nexport default new class V2_SettingsPanel {\n\n constructor() {\n this.onChange = this.onChange.bind(this);\n this.updateSettings = this.updateSettings.bind(this);\n this.sidebar = new V2_SettingsPanel_Sidebar();\n\n this.registerComponents()\n }\n\n registerComponents(){\n /** Lightcord */\n this.sidebar.register(\"lightcord\", makeComponent(this.lightcordComponent.bind(this)))\n this.sidebar.register(\"status\", makeComponent(this.PresenceComponent.bind(this)))\n this.sidebar.register(\"accountinfo\", makeComponent(this.AccountInfosComponent.bind(this)))\n this.sidebar.register(\"lcapipreview\", makeComponent(this.ApiPreviewComponent.bind(this)))\n\n /* Bandaged BD */\n this.sidebar.register(\"BDChangelogTitle\", makeComponent(() => {\n return new BDSidebarHeader().render()\n }))\n this.sidebar.register(\"core\", makeComponent(this.coreComponent.bind(this)))\n this.sidebar.register(\"customcss\", makeComponent(this.customCssComponent.bind(this)))\n this.sidebar.register(\"plugins\", makeComponent(this.renderAddonPane(\"plugins\")))\n this.sidebar.register(\"themes\", makeComponent(this.renderAddonPane(\"themes\")))\n }\n \n get coreSettings() {\n const settings = this.getSettings(\"core\");\n const categories = [...new Set(settings.map(s => s.category))];\n const sections = categories.map(c => {return {title: c, settings: settings.filter(s => s.category == c)};});\n return sections;\n }\n\n get lightcordSettings() {\n const settings = this.getSettings(\"lightcord\");\n const categories = [...new Set(settings.map(s => s.category))];\n const sections = categories.map(c => {return {title: c, settings: settings.filter(s => s.category == c)};});\n return sections;\n }\n\n get PresenceSettings() {\n return this.getSettings(\"status\")\n }\n\n getSettings(category) {\n return Object.keys(settings).reduce((arr, key) => {\n const setting = settings[key];\n if (setting.cat === category && setting.implemented && !setting.hidden) {\n setting.text = key;\n arr.push(setting);\n }\n return arr;\n }, []);\n }\n\n\n onChange(id, checked, sidebar) {\n this.updateSettings(id, checked, sidebar);\n }\n\n updateSettings(id, enabled, sidebar) {\n if(![\"lightcord-8\", \"no_window_bound\", \"enable_glasstron\", \"lightcord-10\", \"lightcord-11\"].includes(id))settingsCookie[id] = enabled;\n\n if (id == \"bda-gs-2\") {\n if (enabled) DOM.addClass(document.body, \"bd-minimal\");\n else DOM.removeClass(document.body, \"bd-minimal\");\n }\n\n if (id == \"bda-gs-3\") {\n if (enabled) DOM.addClass(document.body, \"bd-minimal-chan\");\n else DOM.removeClass(document.body, \"bd-minimal-chan\");\n }\n\n if (id == \"bda-gs-1\") {\n if (enabled) publicServersModule.addButton();\n else publicServersModule.removeButton();\n }\n\n if (id == \"bda-gs-4\") {\n if (enabled) voiceMode.start();\n else voiceMode.stop();\n }\n\n if (id == \"bda-gs-5\") {\n if (enabled) DOM.addClass(DOM.query(\"#app-mount\"), \"bda-dark\");\n else DOM.removeClass(DOM.query(\"#app-mount\"), \"bda-dark\");\n }\n\n if (enabled && id == \"bda-gs-6\") tfHour.inject24Hour();\n\n if (id == \"bda-gs-7\") {\n if (enabled) coloredText.injectColoredText();\n else coloredText.removeColoredText();\n }\n\n if (id == \"fork-ps-4\") {\n if (enabled) ClassNormalizer.start();\n else ClassNormalizer.stop();\n }\n\n if (id == \"fork-ps-5\") {\n if (enabled) {\n ContentManager.watchContent(\"plugin\");\n ContentManager.watchContent(\"theme\");\n }\n else {\n ContentManager.unwatchContent(\"plugin\");\n ContentManager.unwatchContent(\"theme\");\n }\n }\n\n if (id == \"fork-wp-1\") {\n Utils.setWindowPreference(\"transparent\", enabled);\n if (enabled) Utils.setWindowPreference(\"backgroundColor\", null);\n else Utils.setWindowPreference(\"backgroundColor\", \"#2f3136\");\n }\n\n\n if (id == \"bda-gs-8\") {\n if (enabled) dMode.startDebugListener();\n else dMode.stopDebugListener();\n }\n\n if (id == \"fork-dm-1\") {\n if (enabled) dMode.startCopySelector();\n else dMode.stopCopySelector();\n }\n\n if (id === \"lightcord-1\") {\n if (enabled) window.Lightcord.Settings.devMode = true\n else window.Lightcord.Settings.devMode = false\n sidebar.forceUpdate()\n }\n if (id === \"lightcord-2\") {\n if (enabled) window.Lightcord.Settings.callRingingBeat = true\n else window.Lightcord.Settings.callRingingBeat = false\n }\n if (id === \"lightcord-presence-1\") {\n if (enabled) {\n CustomRichPresence.enable()\n const settingsStore = BDModules.get(e => e.default && typeof e.default === \"object\" && \"showCurrentGame\" in e.default)[0]\n if(settingsStore && !settingsStore.default.showCurrentGame){\n BDModules.get(e => e.default && e.default.updateRemoteSettings)[0].default.updateRemoteSettings({\n showCurrentGame: true\n })\n }\n }\n else CustomRichPresence.disable()\n }\n if (id === \"lightcord-3\") {\n ipcRenderer.sendSync(\"LIGHTCORD_SET_ALWAYS_ON_TOP\", enabled)\n }\n if (id === \"lightcord-4\") {\n if(enabled){\n AntiAdDM.enable()\n }else{\n AntiAdDM.disable()\n }\n }\n if (id === \"lightcord-6\") {\n if(enabled){\n blurPrivate.enable()\n }else{\n blurPrivate.disable()\n }\n }\n if (id === \"lightcord-7\") {\n if(enabled){\n disableTyping.enable()\n }else{\n disableTyping.disable()\n }\n }\n if (id === \"lightcord-8\"){\n let appSettings = window.Lightcord.Api.settings\n appSettings.set(\"isTabs\", enabled)\n appSettings.save()\n DiscordNative.app.relaunch()\n }\n if (id === \"lightcord-9\") {\n popoutWindow[enabled ? \"enable\" : \"disable\"]()\n }\n if (id === \"lightcord-10\"){\n core.methods.NotificationsUseShim(enabled)\n return\n }\n if (id === \"no_window_bound\"){\n let appSettings = window.Lightcord.Api.settings\n appSettings.set(\"NO_WINDOWS_BOUND\", enabled)\n\n appSettings.delete(\"IS_MAXIMIZED\")\n appSettings.delete(\"IS_MINIMIZED\") \n appSettings.delete(\"WINDOW_BOUNDS\")\n \n appSettings.save()\n DiscordNative.app.relaunch()\n }\n if (id === \"enable_glasstron\"){\n let appSettings = window.Lightcord.Api.settings\n appSettings.set(\"GLASSTRON\", enabled)\n appSettings.save()\n DiscordNative.app.relaunch()\n }\n \n if(id === \"lightcord-11\"){\n let appSettings = window.Lightcord.Api.settings\n if(!enabled){\n appSettings.delete(\"BD_\"+id)\n appSettings.save()\n return\n }\n appSettings.set(\"BD_\"+id, enabled)\n appSettings.save()\n return\n }\n\n this.saveSettings();\n }\n\n async initializeSettings() {\n if (settingsCookie[\"bda-gs-2\"]) DOM.addClass(document.body, \"bd-minimal\");\n if (settingsCookie[\"bda-gs-3\"]) DOM.addClass(document.body, \"bd-minimal-chan\");\n if (settingsCookie[\"bda-gs-1\"]) publicServersModule.addButton();\n if (settingsCookie[\"bda-gs-4\"]) voiceMode.start();\n if (settingsCookie[\"bda-gs-5\"]) DOM.addClass(DOM.query(\"#app-mount\"), \"bda-dark\");\n if (settingsCookie[\"bda-gs-6\"]) tfHour.inject24Hour();\n if (settingsCookie[\"bda-gs-7\"]) coloredText.injectColoredText();\n if (settingsCookie[\"fork-ps-4\"]) ClassNormalizer.start();\n if (settingsCookie[\"lightcord-1\"]) window.Lightcord.Settings.devMode = true\n if (settingsCookie[\"lightcord-2\"]) window.Lightcord.Settings.callRingingBeat = true\n if (settingsCookie[\"lightcord-presence-1\"]) CustomRichPresence.enable()\n if (settingsCookie[\"lightcord-3\"]) ipcRenderer.sendSync(\"LIGHTCORD_SET_ALWAYS_ON_TOP\", true)\n if (settingsCookie[\"lightcord-4\"]) AntiAdDM.enable()\n if (settingsCookie[\"lightcord-6\"]) blurPrivate.enable()\n if (settingsCookie[\"lightcord-7\"]) disableTyping.enable()\n if (settingsCookie[\"lightcord-9\"]) popoutWindow.enable()\n\n if (settingsCookie[\"fork-ps-5\"]) {\n ContentManager.watchContent(\"plugin\");\n ContentManager.watchContent(\"theme\");\n }\n\n if (settingsCookie[\"bda-gs-8\"]) dMode.startDebugListener();\n if (settingsCookie[\"fork-dm-1\"]) dMode.startCopySelector();\n\n this.saveSettings();\n }\n\n saveSettings() {\n DataStore.setSettingGroup(\"settings\", settingsCookie);\n DataStore.setSettingGroup(\"rpc\", settingsRPC);\n }\n\n loadSettings() {\n Object.assign(settingsCookie, DataStore.getSettingGroup(\"settings\"));\n Object.assign(settingsRPC, DataStore.getSettingGroup(\"rpc\"));\n }\n\n renderSidebar(sidebar) {\n return this.sidebar.render(sidebar);\n }\n\n coreComponent() {\n return BDV2.react.createElement(SectionedSettingsPanel, {key: \"cspanel\", onChange: this.onChange, sections: this.coreSettings})\n }\n\n lightcordComponent(sidebar, forceUpdate) {\n let appSettings = window.Lightcord.Api.settings\n return [\n this.lightcordSettings.map((section, i) => {\n return [\n (i === 0 ? null : BDV2.react.createElement(MarginTop)),\n BDV2.react.createElement(\"h2\", {className: \"ui-form-title h2 margin-reset margin-bottom-20\"}, section.title),\n section.settings.map(setting => {\n let isChecked = settingsCookie[setting.id]\n let value = appSettings.get(\"BD_\"+setting.id, setting.default || \"\")\n if(setting.id === \"lightcord-8\")isChecked = appSettings.get(\"isTabs\", false);\n if(setting.id === \"no_window_bound\")isChecked = appSettings.get(\"NO_WINDOWS_BOUND\", false)\n if(setting.id === \"enable_glasstron\")isChecked = appSettings.get(\"GLASSTRON\", true)\n if(setting.id === \"lightcord-10\")isChecked = !appSettings.get(\"DEFAULT_NOTIFICATIONS\", true)\n let returnValue\n if([\"lightcord-11\"].includes(setting.id)){\n returnValue = BDV2.react.createElement(TextInputSetting, {id: setting.id, key: setting.id, data: setting, value, placeholder: setting.default || null, onChange: (id, value) => {\n this.onChange(id, value, sidebar);\n }})\n }else{\n returnValue = BDV2.react.createElement(Switch, {id: setting.id, key: setting.id, data: setting, checked: isChecked, onChange: (id, checked) => {\n this.onChange(id, checked, sidebar);\n }})\n }\n if(setting.id == \"lightcord-8\" && isChecked){\n return [\n returnValue,\n React.createElement(Lightcord.Api.Components.inputs.Button, {\n color: \"green\",\n look: \"outlined\",\n size: \"small\",\n hoverColor: \"brand\",\n onClick: () => {\n DiscordNative.ipc.send(\"NEW_TAB\")\n },\n wrapper: false,\n disabled: false\n }, \"Open a new Tab\")\n ]\n }\n if(setting.id === \"enable_glasstron\" && isChecked){\n if(process.platform !== \"linux\"){\n let choices = []\n let actual = null\n if(process.platform === \"win32\"){\n choices.push(\"blurbehind\", \"acrylic\", \"transparent\")\n actual = appSettings.get(\"GLASSTRON_BLUR\", \"blurbehind\")\n }else if(process.platform === \"darwin\"){\n choices.push(\"titlebar\", \n \"selection\", \n \"menu\", \n \"popover\", \n \"sidebar\", \n \"header\", \n \"sheet\", \n \"window\", \n \"hud\", \n \"fullscreen-ui\", \n \"tooltip\", \n \"content\", \n \"under-window\", \n \"under-page\", \n \"none\"\n )\n actual = appSettings.get(\"GLASSTRON_VIBRANCY\", \"fullscreen-ui\")\n }\n return [\n returnValue,\n React.createElement(Lightcord.Api.Components.general.SettingSubTitle, {}, \"Glasstron Blur\"),\n React.createElement(Lightcord.Api.Components.inputs.Dropdown, {\n options: choices.map(e => {\n return {\n value: e,\n label: e\n }\n }),\n value: actual,\n disabled: false,\n searchable: true,\n clearable: false,\n onChange: (value) => {\n if(process.platform === \"win32\"){\n ipcRenderer.invoke(\"LIGHTCORD_SET_BLUR_TYPE\", value)\n }else{\n ipcRenderer.invoke(\"LIGHTCORD_SET_VIBRANCY\", value)\n }\n }\n }, null)\n ]\n }\n }\n return returnValue\n })\n ]\n }), \n BDV2.react.createElement(window.Lightcord.Api.Components.inputs.Button, {\n color: \"yellow\",\n look: \"ghost\",\n size: \"medium\",\n hoverColor: \"red\",\n onClick(){\n ipcRenderer.sendSync(\"LIGHTCORD_RELAUNCH_APP\", {\n args: remote.process.argv.slice(1).concat([\"--disable-betterdiscord\"])\n })\n },\n wrapper: true\n }, \"Relaunch without BetterDiscord\"),\n React.createElement(Lightcord.Api.Components.inputs.Button, {\n color: \"yellow\",\n look: \"ghost\",\n size: \"medium\",\n hoverColor: \"red\",\n onClick: () => {\n if(isClearingCache)return\n isClearingCache = true\n Utils.showToast(\"Clearing cache...\", {\n type: \"info\"\n })\n forceUpdate()\n remote.getCurrentWebContents().session.clearCache()\n .then(() => {\n Utils.showToast(\"Cache is cleared !\", {\n type: \"success\"\n })\n isClearingCache = false\n forceUpdate()\n }).catch(err => {\n console.error(err)\n Utils.showToast(\"An error occured. Check console for more informations.\", {\n type: \"error\"\n })\n isClearingCache = false\n forceUpdate()\n })\n },\n wrapper: true,\n disabled: isClearingCache\n }, \"Clear cache\")\n ]\n }\n\n PresenceComponent() {\n return BDV2.react.createElement(V2C_PresenceSettings, {\n key: \"lppannel\",\n onChange: this.onChange, \n settings: this.PresenceSettings\n })\n }\n\n AccountInfosComponent() {\n return BDV2.react.createElement(V2C_AccountInfos, {\n key: \"lapannel\"\n })\n }\n\n ApiPreviewComponent() {\n return BDV2.react.createElement(ApiPreview, {\n key: \"lapipannel\"\n })\n }\n\n customCssComponent() {\n return BDV2.react.createElement(CssEditor, {key: \"csseditor\"})\n }\n\n renderAddonPane(type) {\n // I know this shouldn't be here, but when it isn't,\n // React refuses to change the button when going\n // between plugins and themes page... something\n // to debug later.\n class ContentList extends BDV2.react.Component {\n constructor(props) {\n super(props);\n this.prefix = this.props.type.replace(\"s\", \"\");\n }\n \n onChange() {\n this.props.onChange(this.props.type);\n }\n \n render() {return this.props.children;}\n }\n const originalRender = ContentList.prototype.render;\n Object.defineProperty(ContentList.prototype, \"render\", {\n enumerable: false,\n configurable: false,\n set: function() {console.warn(\"Addon policy for plugins #5 https://github.com/rauenzi/BetterDiscordApp/wiki/Addon-Policies#plugins\");},\n get: () => originalRender\n });\n return function(){\n return BDV2.react.createElement(ContentList, {type}, BDV2.react.createElement(CardList, {type}))\n }\n }\n};\n\n/**\n * No need to export settingsPanel on window\n */\n\nfunction makeComponent(children){\n class SettingComponent extends React.Component {\n render(){\n return children(sidebar, () => this.forceUpdate())\n }\n }\n let sidebar\n return (s) => {\n sidebar = s\n return SettingComponent\n }\n}","import BDV2 from \"../modules/v2\";\r\n\r\nexport default class BDLogo extends BDV2.reactComponent {\r\n render() {\r\n return BDV2.react.createElement(\r\n \"svg\",\r\n {height: \"100%\", width: this.props.size || \"16px\", className: \"bd-logo \" + this.props.className, style: {fillRule: \"evenodd\", clipRule: \"evenodd\", strokeLinecap: \"round\", strokeLinejoin: \"round\"}, viewBox: \"0 0 2000 2000\"},\r\n BDV2.react.createElement(\"metadata\", null),\r\n BDV2.react.createElement(\"defs\", null,\r\n BDV2.react.createElement(\"filter\", {id: \"shadow1\"}, BDV2.react.createElement(\"feDropShadow\", {\"dx\": \"20\", \"dy\": \"0\", \"stdDeviation\": \"20\", \"flood-color\": \"rgba(0,0,0,0.35)\"})),\r\n BDV2.react.createElement(\"filter\", {id: \"shadow2\"}, BDV2.react.createElement(\"feDropShadow\", {\"dx\": \"15\", \"dy\": \"0\", \"stdDeviation\": \"20\", \"flood-color\": \"rgba(255,255,255,0.15)\"})),\r\n BDV2.react.createElement(\"filter\", {id: \"shadow3\"}, BDV2.react.createElement(\"feDropShadow\", {\"dx\": \"10\", \"dy\": \"0\", \"stdDeviation\": \"20\", \"flood-color\": \"rgba(0,0,0,0.35)\"}))\r\n ),\r\n BDV2.react.createElement(\"g\", null,\r\n BDV2.react.createElement(\"path\", {style: {filter: \"url(#shadow3)\"}, d: \"M1195.44+135.442L1195.44+135.442L997.6+136.442C1024.2+149.742+1170.34+163.542+1193.64+179.742C1264.34+228.842+1319.74+291.242+1358.24+365.042C1398.14+441.642+1419.74+530.642+1422.54+629.642L1422.54+630.842L1422.54+632.042C1422.54+773.142+1422.54+1228.14+1422.54+1369.14L1422.54+1370.34L1422.54+1371.54C1419.84+1470.54+1398.24+1559.54+1358.24+1636.14C1319.74+1709.94+1264.44+1772.34+1193.64+1821.44C1171.04+1837.14+1025.7+1850.54+1000+1863.54L1193.54+1864.54C1539.74+1866.44+1864.54+1693.34+1864.54+1296.64L1864.54+716.942C1866.44+312.442+1541.64+135.442+1195.44+135.442Z\", fill: \"#171717\", opacity: \"1\"}),\r\n BDV2.react.createElement(\"path\", {style: {filter: \"url(#shadow2)\"}, d: \"M1695.54+631.442C1685.84+278.042+1409.34+135.442+1052.94+135.442L361.74+136.442L803.74+490.442L1060.74+490.442C1335.24+490.442+1335.24+835.342+1060.74+835.342L1060.74+1164.84C1150.22+1164.84+1210.53+1201.48+1241.68+1250.87C1306.07+1353+1245.76+1509.64+1060.74+1509.64L361.74+1863.54L1052.94+1864.54C1409.24+1864.54+1685.74+1721.94+1695.54+1368.54C1695.54+1205.94+1651.04+1084.44+1572.64+999.942C1651.04+915.542+1695.54+794.042+1695.54+631.442Z\", fill: \"#3E82E5\", opacity: \"1\"}),\r\n BDV2.react.createElement(\"path\", {style: {filter: \"url(#shadow1)\"}, d: \"M1469.25+631.442C1459.55+278.042+1183.05+135.442+826.65+135.442L135.45+135.442L135.45+1004C135.45+1004+135.427+1255.21+355.626+1255.21C575.825+1255.21+575.848+1004+575.848+1004L577.45+490.442L834.45+490.442C1108.95+490.442+1108.95+835.342+834.45+835.342L664.65+835.342L664.65+1164.84L834.45+1164.84C923.932+1164.84+984.244+1201.48+1015.39+1250.87C1079.78+1353+1019.47+1509.64+834.45+1509.64L135.45+1509.64L135.45+1864.54L826.65+1864.54C1182.95+1864.54+1459.45+1721.94+1469.25+1368.54C1469.25+1205.94+1424.75+1084.44+1346.35+999.942C1424.75+915.542+1469.25+794.042+1469.25+631.442Z\", fill: \"#FFFFFF\", opacity: \"1\"})\r\n )\r\n );\r\n }\r\n}","export default class LightcordLogo extends React.Component {\r\n render(){\r\n const props = this.props\r\n return (\r\n \r\n )\r\n }\r\n}","import BDV2 from \"./v2\";\r\nimport Utils from \"./utils\";\r\nimport { settings } from \"../0globals\";\r\n\r\nconst Constants = {\r\n EmojiRegex: //g\r\n}\r\n\r\nlet CustomEmojiModule = BDModules.get(e => e.CustomEmoji)[0]\r\nlet EmojiModuleApi = BDModules.get(e => e.default && e.default.getCustomEmojiById)[0]\r\nlet AutocompleteModule = BDModules.get(e => e.default && e.default.displayName === \"Autocomplete\")[0]\r\nlet AutoCompletionTemplates = BDModules.get(e => e.getAutocompleteOptions)[0]\r\nlet EmojiModuleQuery = BDModules.get(e => e.default && e.default.queryEmojiResults)[0]\r\nlet Messages = BDModules.get(e => e.default && e.default.Messages && e.default.Messages.EMOJI_MATCHING)[0]\r\nlet guildModule = BDModules.get(e => e.default && e.default.getGuild && e.default.getGuilds && !e.default.isFetching)[0]\r\nlet emojiSearch = BDModules.get(e => e.default && e.default.getDisambiguatedEmojiContext)\r\nconst appSettings = Lightcord.Api.settings\r\n\r\nexport default new class EmojiModule {\r\n constructor(){\r\n this.init().catch(err => Utils.err(\"EmojiModule\", \"An error occured\", err)) // better logging\r\n }\r\n\r\n async init(){\r\n /** Emoji AutoComplete */\r\n if(!AutocompleteModule)AutocompleteModule = await window.Lightcord.Api.ensureExported(e => e.default && e.default.displayName === \"Autocomplete\")\r\n if(!AutoCompletionTemplates)AutoCompletionTemplates = await window.Lightcord.Api.ensureExported(e => e.getAutocompleteOptions)\r\n if(!EmojiModuleQuery)EmojiModuleQuery = await window.Lightcord.Api.ensureExported(e => e.default && e.default.queryEmojiResults)\r\n if(!Messages)Messages = await window.Lightcord.Api.ensureExported(e => e.default && e.default.Messages && e.default.Messages.EMOJI_MATCHING)\r\n if(!guildModule)guildModule = await window.Lightcord.Api.ensureExported(e => e.default && e.default.getGuild && e.default.getGuilds && !e.default.isFetching)\r\n if(!emojiSearch)emojiSearch = await window.Lightcord.Api.ensureExported(e => e.default && e.default.getDisambiguatedEmojiContext)\r\n\r\n const setting = settings[\"Emoji Prefix\"]\r\n const getValue = () => {\r\n const value = appSettings.get(\"BD_\"+setting.id, setting.default)\r\n if(typeof value !== \"string\")return setting.default\r\n return value\r\n }\r\n\r\n if(AutocompleteModule && AutoCompletionTemplates && EmojiModuleQuery && Messages && guildModule && emojiSearch){\r\n console.log(`Patching getAutocompleteOptions of AutoCompletionTemplates`, AutoCompletionTemplates)\r\n const getAutocompleteOptions = AutoCompletionTemplates.getAutocompleteOptions\r\n AutoCompletionTemplates.getAutocompleteOptions = function(e, t, n, r, a){\r\n const value = getAutocompleteOptions.call(this, ...arguments)\r\n value.LIGHTCORD_EMOJIS = {\r\n matches(arg1, arg2){\r\n let condition = arg2.length > 1 && getValue() === arg1\r\n setEmojiUsable(condition)\r\n return condition\r\n },\r\n queryResults(t){\r\n let results = EmojiModuleQuery.default.queryEmojiResults(t, e)\r\n return results\r\n },\r\n renderResults(e, t, n, r, a){\r\n return D(e, t, a.emojis, n, r, Messages.default.Messages.EMOJI_MATCHING, Messages.default.Messages.EMOJI, AutocompleteModule.default.Emoji, (function(e) {\r\n return {\r\n emoji: e,\r\n key: e.id || e.uniqueName || e.name,\r\n sentinel: getValue(),\r\n guild: null != e.guildId ? guildModule.default.getGuild(e.guildId) : null\r\n }\r\n }), (function(e) {\r\n return getValue() + e + getValue()\r\n }))\r\n },\r\n getPlainText(id, guild){\r\n var emojis = guild.emojis;\r\n if (null == emojis || null == emojis[id]) return \"\";\r\n var emoji = emojis[id],\r\n isAnimated = emoji.animated ? \"a\" : \"\";\r\n return emoji.managed || null == emoji.id ? \".\" + emoji.name + \".\" : \"<\" + isAnimated + \".\" + (emoji.originalName || emoji.name) + \".\" + emoji.id + \">\"\r\n },\r\n getRawText(id, guild){\r\n var emojis = guild.emojis;\r\n if (null == emojis || null == emojis[id]) return \"\";\r\n var emoji = emojis[id],\r\n isAnimated = emoji.animated ? \"a\" : \"\";\r\n return emoji.managed || null == emoji.id ? \".\" + emoji.name + \".\" : \"<\" + isAnimated + \".\" + (emoji.originalName || emoji.name) + \".\" + emoji.id + \">\"\r\n }\r\n }\r\n return value\r\n }\r\n }else{\r\n console.error(new Error(\"Couldn't start autocompletion of Lightcord's emojis.\"))\r\n }\r\n\r\n /** Emoji display */\r\n while (!BDV2.MessageComponent) await new Promise(resolve => setTimeout(resolve, 100));\r\n\r\n if (!this.cancelEmojiRender){ // TODO: Proper emoji formatting / rendering\r\n this.cancelEmoteRender = Utils.monkeyPatch(BDV2.MessageComponent, \"default\", {before: (data) => {\r\n const message = Utils.getNestedProp(data.methodArguments[0], \"childrenMessageContent.props.message\")\r\n if(!message)return\r\n const content = Utils.getNestedProp(data.methodArguments[0], \"childrenMessageContent.props.content\")\r\n if(!content || !content.length)return\r\n \r\n /**\r\n * @type {{\r\n * raw: string,\r\n * name: string,\r\n * id: string,\r\n * animated: boolean\r\n * }[]}\r\n */\r\n let emojis = []\r\n \r\n const newContent = []\r\n for(let node of content){\r\n if (typeof(node) !== \"string\") {\r\n newContent.push(node)\r\n continue\r\n };\r\n let parsed;\r\n let hasParsed = false\r\n \r\n do {\r\n parsed = Constants.EmojiRegex.exec(node);\r\n if (parsed) {\r\n hasParsed = true\r\n if(!EmojiModuleApi)EmojiModuleApi = BDModules.get(e => e.default && e.default.getCustomEmojiById)[0]\r\n const emoji = EmojiModuleApi.default.getCustomEmojiById(parsed[2])\r\n if(emoji){\r\n emojis.push({\r\n animated: emoji.animated,\r\n name: emoji.name,\r\n id: emoji.id,\r\n raw: parsed[0]\r\n })\r\n }else{\r\n emojis.push({\r\n animated: parsed[0].startsWith(\" {\r\n if(!word)return \"\"\r\n const emoji = emojis.find(e => e.raw == word)\r\n if(!emoji)return word\r\n if(!CustomEmojiModule)CustomEmojiModule = BDModules.get(e => e.CustomEmoji)[0]\r\n return React.createElement(CustomEmojiModule.CustomEmoji, {\r\n emoji: {\r\n name: `${getValue()}${emoji.name}${getValue()}`,\r\n emojiId: emoji.id,\r\n animated: emoji.animated,\r\n jumboable: arr.length === 1 && content.length === 1\r\n }\r\n })\r\n }).reduce((previous, current) => {\r\n if(previous.length === 0)return [current]\r\n if(typeof current === \"string\"){\r\n if(typeof previous[previous.length - 1] === \"string\"){\r\n previous[previous.length - 1] += ` ${current}`\r\n return previous\r\n }\r\n previous.push(\" \"+current)\r\n return previous\r\n }\r\n previous.push(\" \", current)\r\n return previous\r\n }, [])\r\n newContent.push(...words)\r\n }else{\r\n newContent.push(node)\r\n }\r\n }\r\n while(data.methodArguments[0].childrenMessageContent.props.content[0]){\r\n data.methodArguments[0].childrenMessageContent.props.content.shift()\r\n }\r\n while(newContent[0]){\r\n data.methodArguments[0].childrenMessageContent.props.content.push(newContent.shift())\r\n }\r\n }});\r\n }/*\r\n let userModule\r\n window.Lightcord.Api.ensureExported(e => e.default && e.default.displayName === \"EmojiPickerListRow\")\r\n .then(EmojiPickerListRow => {\r\n let classs = EmojiPickerListRow.default\r\n EmojiPickerListRow.default = class EmojiPickerListRow extends React.Component {\r\n constructor(props){\r\n super(props)\r\n }\r\n\r\n render(){\r\n if(!userModule)userModule = BDModules.get(e => e.default && e.default.getCurrentUser)[0]\r\n if(!userModule)return React.createElement(classs, this.props)\r\n let user = userModule.default.getCurrentUser()\r\n if(!user.hasPremiumSubscription)return React.createElement(classs, this.props)\r\n\r\n return React.createElement(classs, Object.assign({}, this.props, {\r\n emojiDescriptors: this.props.emojiDescriptors.map(e => {\r\n e.isDisabled = false\r\n })\r\n })) \r\n }\r\n }\r\n EmojiPickerListRow.default.displayName = \"EmojiPickerListRow\"\r\n })*/\r\n }\r\n\r\n disable(){\r\n if (!this.cancelEmoteRender) return;\r\n this.cancelEmoteRender();\r\n this.cancelEmoteRender = null;\r\n }\r\n\r\n start(){\r\n \r\n }\r\n}\r\n\r\nfunction D(e, t, n, r, o, i, s, u, l, c) {\r\n if (null == n || 0 === n.length) return null;\r\n var d = n.map((function(e, n) {\r\n return React.createElement(u, Object.assign({\r\n onClick: o,\r\n onHover: r,\r\n selected: t === n,\r\n index: n\r\n }, l(e, n)))\r\n }));\r\n return [R(i, s, e, c), d]\r\n}\r\n\r\nfunction R(e, t, n, r) {\r\n var a = (n.length > 0 ? e.format({\r\n prefix: r(n)\r\n }) : t)\r\n if(Array.isArray(a)){\r\n a.unshift(React.createElement(\"strong\", {}, \"[Lightcord] \"))\r\n }else{\r\n a = \"[LIGHTCORD] \"+a\r\n }\r\n return React.createElement(AutocompleteModule.default.Title, {\r\n title: a\r\n }, a)\r\n}\r\nR.displayName = \"renderHeader\";\r\n\r\nlet EmojiFilterModule = BDModules.get(e => e.default && e.default.isEmojiDisabled)[0]\r\nlet isEmojiDisabled = EmojiFilterModule && EmojiFilterModule.default.isEmojiDisabled\r\nlet isUsable = false\r\nlet hasPatched = false\r\n\r\nfunction setEmojiUsable(usable){\r\n isUsable = usable\r\n if(hasPatched)return\r\n if(!EmojiFilterModule)EmojiFilterModule = BDModules.get(e => e.default && e.default.isEmojiDisabled)[0]\r\n if(!EmojiFilterModule)return\r\n if(!isEmojiDisabled)isEmojiDisabled = EmojiFilterModule.default.isEmojiDisabled\r\n\r\n hasPatched = true\r\n EmojiFilterModule.default.isEmojiDisabled = function(emoji){\r\n if(isUsable){\r\n if(emoji.surrogates || emoji.diversity)return true\r\n return false\r\n }\r\n return isEmojiDisabled.call(this, ...arguments)\r\n }\r\n}","import {bdConfig, minSupportedVersion, bbdVersion, settingsCookie, bdpluginErrors, bdthemeErrors, bbdChangelog, defaultCookie, currentDiscordVersion, defaultRPC, settingsRPC, lightcordSettings} from \"../0globals\";\nimport Utils from \"./utils\";\n\nimport BDV2 from \"./v2\";\nimport settingsPanel from \"./settingsPanel\";\nimport pluginModule from \"./pluginModule\";\nimport themeModule from \"./themeModule\";\nimport DataStore from \"./dataStore\";\nimport WebpackModules from \"./webpackModules\";\nimport DOM from \"./domtools\";\n\nimport BDLogo from \"../ui/bdLogo\";\nimport TooltipWrap from \"../ui/tooltipWrap\";\nimport LightcordLogo from \"../svg/Lightcord\";\nimport PluginCertifier from \"./pluginCertifier\";\nimport distant, { uuidv4 } from \"./distant\";\nimport EmojiModule from \"./emojiModule\"\nimport * as electron from \"electron\"\nimport v2 from \"./v2\";\nimport contentManager from \"./contentManager\";\n\nlet methods\nfunction Core() {}\n\n\nCore.prototype.setConfig = function(config) {\n if (this.hasStarted) return;\n Object.assign(bdConfig, config);\n};\n\nObject.defineProperty(Core.prototype, \"methods\", {\n get(){\n return methods\n }\n})\n\nCore.prototype.setMethods = function(m) {\n if (this.hasStarted) return;\n methods = m\n};\n\nCore.prototype.init = async function() {\n if (this.hasStarted) return;\n this.hasStarted = true;\n\n if (!Array.prototype.flat) {\n Utils.alert(\"Not Supported\", \"BetterDiscord v\" + bbdVersion + \" does not support this old version (\" + currentDiscordVersion + \") of Discord. Please update your Discord installation before proceeding.\");\n return;\n }\n\n if (bdConfig.version < minSupportedVersion) {\n Utils.alert(\"Not Supported\", \"BetterDiscord v\" + bdConfig.version + \" (your version)\" + \" is not supported by the latest js (\" + bbdVersion + \").
Please download the latest version from GitHub\");\n return;\n }\n\n if (window.ED) {\n Utils.alert(\"Not Supported\", \"BandagedBD does not work with EnhancedDiscord. Please uninstall one of them.\");\n return;\n }\n\n if (window.WebSocket && window.WebSocket.name && window.WebSocket.name.includes(\"Patched\")) {\n Utils.alert(\"Not Supported\", \"BandagedBD does not work with Powercord. Please uninstall one of them.\");\n return;\n }\n\n Utils.suppressErrors(this.patchAttributes.bind(this), \"LC Plugin Certifier Patch\")();\n\n Utils.log(\"Startup\", \"Initializing Settings\");\n this.initSettings();\n\n await this.checkForGuilds();\n BDV2.initialize();\n Utils.log(\"Startup\", \"Updating Settings\");\n settingsPanel.initializeSettings();\n\n Utils.log(\"Startup\", \"Loading Addons Cache\")\n await contentManager.loadAddonCertifierCache()\n\n Utils.log(\"Startup\", \"Loading Plugins\");\n await pluginModule.loadPlugins();\n\n Utils.log(\"Startup\", \"Loading Themes\");\n await themeModule.loadThemes();\n\n DOM.addStyle(\"customcss\", Buffer.from(DataStore.getBDData(\"bdcustomcss\"), \"base64\").toString(\"utf8\"));\n\n window.addEventListener(\"beforeunload\", function() {\n if (settingsCookie[\"bda-dc-0\"]) document.querySelector(\".btn.btn-disconnect\").click();\n });\n\n PluginCertifier.start()\n\n Utils.log(\"Startup\", \"Removing Loading Icon\");\n if (document.getElementsByClassName(\"bd-loaderv2\").length) document.getElementsByClassName(\"bd-loaderv2\")[0].remove();\n Utils.log(\"Startup\", \"Initializing Main Observer\");\n this.initObserver();\n\n // Show loading errors\n if (settingsCookie[\"fork-ps-1\"]) {\n Utils.log(\"Startup\", \"Collecting Startup Errors\");\n Utils.showContentErrors({plugins: bdpluginErrors, themes: bdthemeErrors});\n }\n\n const previousVersion = DataStore.getBDData(\"version\");\n if (bbdVersion > previousVersion) {\n if (bbdChangelog) this.showChangelogModal(bbdChangelog);\n DataStore.setBDData(\"version\", bbdVersion);\n }\n\n EmojiModule.start()\n\n Utils.suppressErrors(this.patchSocial.bind(this), \"BD Social Patch\")();\n Utils.suppressErrors(this.patchGuildPills.bind(this), \"BD Guild Pills Patch\")();\n Utils.suppressErrors(this.patchGuildListItems.bind(this), \"BD Guild List Items Patch\")();\n Utils.suppressErrors(this.patchGuildSeparator.bind(this), \"BD Guild Separator Patch\")();\n Utils.suppressErrors(this.patchMessageHeader.bind(this), \"BD Badge Chat Patch\")();\n Utils.suppressErrors(this.patchMemberList.bind(this), \"BD Badge Member List Patch\")();\n Utils.suppressErrors(this.patchAttachment.bind(this), \"LC Plugin Certifier Patch\")();\n\n if(bdConfig.haveInstalledDefault){\n let alert = Utils.alert(\"First Installation\", \"As it is the first time you install Lightcord, We added two default themes and one default plugin in your plugin/theme folder. Check it in the Plugin/Theme settings.\")\n await new Promise((resolve) => {\n alert.onClose(resolve)\n })\n }\n const logo = document.querySelector(\"#app-mount > div.typeWindows-1za-n7.withFrame-haYltI.titleBar-AC4pGV.horizontalReverse-3tRjY7.flex-1O1GKY.directionRowReverse-m8IjIq.justifyStart-2NDFzi.alignStretch-DpGPf3.da-typeWindows.da-withFrame.da-titleBar.da-horizontalReverse.da-flex.da-directionRowReverse.da-justifyStart.da-alignStretch > div.wordmarkWindows-1v0lYD.wordmark-2iDDfm.da-wordmarkWindows.da-wordmark\")\n if(logo){\n logo.style.top = \"3px\"\n logo.innerHTML = ``\n }\n};\n\nCore.prototype.patchAttributes = async function() {\n let attribsPatchs = []\n this.cancelPatchAttributes = function() {\n attribsPatchs.forEach(e => e())\n }\n\n while(!v2.MessageComponent)await new Promise(resolve => setTimeout(resolve, 100))\n \n // TODO: try to patch correctly the user popout on a next update\n const Anchor = WebpackModules.find(m => m.displayName == \"Anchor\");\n window.Lightcord.Api.ensureExported(e => e.default && e.default.displayName === \"DiscordTag\")\n .then(DiscordTag => {\n let DiscordTagComp = DiscordTag.default\n DiscordTag.default = function(props){\n let returnValue = DiscordTagComp(props)\n\n let id = uuidv4()\n\n let badgeDiv = BDV2.React.createElement(\"div\", {\n style: {\n display: \"inline\",\n marginTop: \"5px\"\n }\n }, BDV2.React.createElement(\"span\", {\n id: \"badges-\"+id,\n key: \"badges-\"+id,\n style: {\n display: \"inherit\"\n }\n }))\n\n let children = [returnValue]\n\n if (props.user.id === \"249746236008169473\") { // Rauenzi: BandagedBD Developer\n children.push(\n BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: \"BandagedBD Developer\"},\n BDV2.React.createElement(Anchor, {className: \"bd-chat-badge\", href: \"https://github.com/rauenzi/BetterDiscordApp\", title: \"BandagedBD\", target: \"_blank\"},\n BDV2.React.createElement(BDLogo, {size: \"16px\", className: \"bd-logo\"})\n )\n )\n );\n } else if (props.user.id === \"696481194443014174\" || props.user.id === \"696003456611385396\"){ // Not Thomiz: Lightcord Developer, Phorcys: Lightcord Developer\n children.push(\n BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: \"Lightcord Developer\"},\n BDV2.React.createElement(Anchor, {className: \"bd-chat-badge\", href: \"https://github.com/Lightcord/Lightcord\", title: \"Lightcord\", target: \"_blank\"},\n BDV2.React.createElement(LightcordLogo, {size: \"16px\", className: \"bd-logo\"})\n )\n )\n );\n }\n\n children.push(badgeDiv)\n let div = BDV2.React.createElement(\"div\", {\n style: {\n display: \"block\"\n }\n }, children)\n applyBadges(id, props.user, false)\n\n return div\n }\n DiscordTag.default.displayName = DiscordTagComp.displayName\n })\n\n attribsPatchs.push(Utils.monkeyPatch(v2.MessageComponent, \"default\", {after: (data) => {\n if(data.methodArguments[0].childrenMessageContent.props.message){ // this can be a blocked message (not opened)\n data.returnValue.props[\"data-message-id\"] = data.methodArguments[0].childrenMessageContent.props.message.id\n }\n }}))\n /*\n attribsPatchs.push(Utils.monkeyPatch(v2.MessageComponent, \"default\", {after: (data) => {\n data.returnValue.props[\"message-id\"] = data.methodArguments[0].childrenMessageContent.props.message.id\n }}))*/\n}\n\nCore.prototype.checkForGuilds = function() {\n let timesChecked = 0;\n return new Promise(resolve => {\n const checkForGuilds = function() {\n const wrapper = BDV2.guildClasses.wrapper.split(\" \")[0];\n if (document.querySelectorAll(`.${wrapper}`).length > 0) timesChecked++;\n const guild = BDV2.guildClasses.listItem.split(\" \")[0];\n const blob = BDV2.guildClasses.blobContainer.split(\" \")[0];\n if (document.querySelectorAll(`.${wrapper} .${guild} .${blob}`).length > 0) return resolve(bdConfig.deferLoaded = true);\n else if (timesChecked >= 50) return resolve(bdConfig.deferLoaded = true);\n setTimeout(checkForGuilds, 100);\n };\n if (document.readyState != \"loading\") setTimeout(checkForGuilds, 100);\n document.addEventListener(\"DOMContentLoaded\", () => {setTimeout(checkForGuilds, 100);});\n });\n};\n\nCore.prototype.injectExternals = async function() {\n // No externals\n};\n\nCore.prototype.initSettings = function () {\n DataStore.initialize();\n if(!DataStore.getSettingGroup(\"rpc\")){\n Object.assign(settingsRPC, defaultRPC);\n }\n if(!DataStore.getSettingGroup(\"settings\")){\n Object.assign(settingsCookie, defaultCookie);\n settingsPanel.saveSettings();\n } else {\n settingsPanel.loadSettings();\n for (const setting in defaultCookie) {\n if (settingsCookie[setting] == undefined) {\n settingsCookie[setting] = defaultCookie[setting];\n settingsPanel.saveSettings();\n }\n }\n }\n window.Lightcord.Api.ensureExported(e => e.default && e.default.prototype && e.default.prototype.getPredicateSections)\n .then(settingModule => {\n\n let getPredicateSections = settingModule.default.prototype.getPredicateSections\n settingModule.default.prototype.getPredicateSections = function(){\n let result = getPredicateSections.call(this, ...arguments)\n\n if(!result[1])return result\n if(result[1].section === \"My Account\"){ // user settings, not guild settings\n let poped = []\n \n poped.push(result.pop())\n poped.push(result.pop())\n poped.push(result.pop())\n poped.push(result.pop())\n\n result.push(...settingsPanel.renderSidebar(this))\n\n while(poped[0]){\n result.push(poped.pop())\n }\n }\n console.log(result)\n return result\n }\n })\n};\n\n\nlet classNameLayer\nlet classNameSocialLinks\nlet classNameModal\n\nCore.prototype.initObserver = function () {\n const mainObserver = new MutationObserver((mutations) => {\n for (let i = 0, mlen = mutations.length; i < mlen; i++) {\n const mutation = mutations[i];\n if (typeof pluginModule !== \"undefined\") pluginModule.rawObserver(mutation);\n\n // if there was nothing added, skip\n if (!mutation.addedNodes.length || !(mutation.addedNodes[0] instanceof Element)) continue;\n\n const node = mutation.addedNodes[0];\n\n if(!classNameLayer)classNameLayer = BDModules.get((e) => e.layer && typeof e.layer === \"string\" && e.animating)[0].layer\n if(!classNameSocialLinks)classNameSocialLinks = BDModules.get((e) => e.socialLinks && typeof e.socialLinks === \"string\")[0].socialLinks\n if(!classNameModal)classNameModal = BDModules.get((e) => e.modal && typeof e.modal === \"string\" && e.inner && typeof e.inner === \"string\" && !e.responsiveWidthMobile)[0].modal\n\n if (node.classList.contains(classNameLayer)) {\n if (node.getAttribute(\"aria-label\") === \"GUILD_SETTINGS\"){\n node.setAttribute(\"layer-id\", \"server-settings\");\n node.setAttribute(\"id\", \"server-settings\");\n }\n\n if (node.getElementsByClassName(classNameSocialLinks).length) {\n node.setAttribute(\"layer-id\", \"user-settings\");\n node.setAttribute(\"id\", \"user-settings\");\n }\n }\n\n if (node.parentElement == document.body && node.querySelector(\"#ace_settingsmenu\")) node.id = \"ace_settingsmenu_container\";\n\n // Emoji Picker\n //node.getElementsByClassName(\"emojiPicker-3m1S-j\").length && !node.querySelector(\".emojiPicker-3m1S-j\").parentElement.classList.contains(\"animatorLeft-1EQxU0\")\n //if (node.classList.contains(classNameLayer2) && node.getElementsByClassName(classNameEmojiPicker).length && !node.querySelector(\".\"+classNameEmojiPicker).parentElement.classList.contains(classNameAnimatorLeft)) quickEmoteMenu.obsCallback(node);\n\n }\n });\n\n mainObserver.observe(document, {\n childList: true,\n subtree: true\n });\n};\n\nCore.prototype.showChangelogModal = function(options = {}) {\n return Utils.showChangelogModal(options);\n};\n\nCore.prototype.alert = function(title, content) {\n return Utils.alert(title, content);\n};\n\nCore.prototype.patchSocial = function() {\n if (this.socialPatch) return;\n const TabBar = WebpackModules.find(m => m.displayName == \"TabBar\");\n const Anchor = WebpackModules.find(m => m.displayName == \"Anchor\");\n if (!TabBar) return;\n this.socialPatch = Utils.monkeyPatch(TabBar.prototype, \"render\", {after: (data) => {\n const children = data.returnValue.props.children;\n if (!children || !children.length || children.length < 3) return;\n if (children[children.length - 3].type.displayName !== \"Separator\") return;\n if (!children[children.length - 2].type.toString().includes(\"socialLinks\")) return;\n if (Anchor) {\n let socialModule1 = BDModules.get(e => e.socialLinks)[0]\n const original = children[children.length - 2].type;\n const newOne = function() {\n const returnVal = original(...arguments);\n returnVal.props.children.push(\n BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: \"Lightcord\"},\n BDV2.React.createElement(Anchor, {className: \"bd-social-link \"+socialModule1.link, href: \"https://github.com/Lightcord/Lightcord\", title: \"Lightcord\", target: \"_blank\"},\n BDV2.React.createElement(LightcordLogo, {size: \"16px\", className: \"bd-social-logo\"})\n )\n )\n );\n returnVal.props.children.push(\n BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: \"BandagedBD\"},\n BDV2.React.createElement(Anchor, {className: \"bd-social-link \"+socialModule1.link, href: \"https://github.com/rauenzi/BetterDiscordApp\", title: \"BandagedBD\", target: \"_blank\"},\n BDV2.React.createElement(BDLogo, {size: \"16px\", className: \"bd-social-logo\"})\n )\n )\n );\n return returnVal;\n };\n children[children.length - 2].type = newOne;\n }\n\n let [\n classNameColorMuted,\n sizes,\n classNameVersionHash\n ] = [\n BDModules.get(e => e.colorMuted)[0].colorMuted,\n BDModules.get(e => e.size32)[0],\n BDModules.get(e => e.versionHash)[0].versionHash\n ]\n\n const versionHash = `(${bdConfig.hash ? bdConfig.hash.substring(0, 7) : bdConfig.branch})`;\n const buildInfo = electron.ipcRenderer.sendSync(\"LIGHTCORD_GET_BUILD_INFOS\")\n const additional = [\n BDV2.react.createElement(\"div\", {className: `${classNameColorMuted} ${sizes.size12}`}, `Lightcord ${buildInfo.version} `, BDV2.react.createElement(\"span\", {className: classNameVersionHash+\" da-versionHash\"}, `(${(buildInfo.commit || \"Unknown\").slice(0, 7)})`)),\n BDV2.react.createElement(\"div\", {className: `${classNameColorMuted} ${sizes.size12}`}, `BBD ${bbdVersion} `, BDV2.react.createElement(\"span\", {className: classNameVersionHash+\" da-versionHash\"}, versionHash))\n ]\n \n\n const originalVersions = children[children.length - 1].type;\n children[children.length - 1].type = function() {\n const returnVal = originalVersions(...arguments);\n returnVal.props.children.splice(1, 0, additional);\n return returnVal;\n };\n }});\n};\n\nconst getGuildClasses = function() {\n const guildsWrapper = WebpackModules.findByProps(\"wrapper\", \"unreadMentionsBar\");\n const guilds = WebpackModules.findByProps(\"guildsError\", \"selected\");\n const pill = WebpackModules.findByProps(\"blobContainer\");\n return Object.assign({}, guildsWrapper, guilds, pill);\n};\n\nCore.prototype.patchGuildListItems = function() {\n if (this.guildListItemsPatch) return;\n const GuildClasses = getGuildClasses();\n const listItemClass = GuildClasses.listItem.split(\" \")[0];\n const blobClass = GuildClasses.blobContainer.split(\" \")[0];\n const reactInstance = BDV2.getInternalInstance(document.querySelector(`.${listItemClass} .${blobClass}`).parentElement);\n const GuildComponent = reactInstance.return.type;\n if (!GuildComponent) return;\n this.guildListItemsPatch = Utils.monkeyPatch(GuildComponent.prototype, \"render\", {after: (data) => {\n if (data.returnValue && data.thisObject) {\n const returnValue = data.returnValue;\n const guildData = data.thisObject.props;\n let className = returnValue.props.className\n className += \" bd-guild\";\n if (guildData.unread) className += \" bd-unread\";\n if (guildData.selected) className += \" bd-selected\";\n if (guildData.audio) className += \" bd-audio\";\n if (guildData.video) className += \" bd-video\";\n if (guildData.badge) className += \" bd-badge\";\n if (guildData.animatable) className += \" bd-animatable\";\n returnValue.props.className = className\n return returnValue;\n }\n }});\n};\n\nCore.prototype.patchGuildPills = function() {\n if (this.guildPillPatch) return;\n const guildPill = WebpackModules.find(m => m.default && !m.default.displayName && m.default.toString && m.default.toString().includes(\"translate3d\"));\n if (!guildPill) return;\n this.guildPillPatch = Utils.monkeyPatch(guildPill, \"default\", {after: (data) => {\n const props = data.methodArguments[0];\n if (props.unread) data.returnValue.props.className += \" bd-unread\";\n if (props.selected) data.returnValue.props.className += \" bd-selected\";\n if (props.hovered) data.returnValue.props.className += \" bd-hovered\";\n return data.returnValue;\n }});\n};\n\nCore.prototype.patchGuildSeparator = function() {\n if (this.guildSeparatorPatch) return;\n const Guilds = WebpackModules.findByDisplayName(\"Guilds\");\n const guildComponents = WebpackModules.findByProps(\"renderListItem\");\n if (!guildComponents || !Guilds) return;\n const GuildSeparator = function() {\n const returnValue = guildComponents.Separator(...arguments);\n returnValue.props.className += \" bd-guild-separator\";\n return returnValue;\n };\n this.guildSeparatorPatch = Utils.monkeyPatch(Guilds.prototype, \"render\", {after: (data) => {\n data.returnValue.props.children[1].props.children[3].type = GuildSeparator;\n }});\n};\n\nCore.prototype.patchAttachment = function() {\n if (this.AttachmentPatch) return;\n const Attachment = BDModules.get(e => e.default && e.default.displayName === \"Attachment\")[0] // temporary\n const Anchor = WebpackModules.find(m => m.displayName == \"Anchor\");\n if (!Anchor || !Attachment || !Attachment.default) return;\n this.AttachmentPatch = Utils.monkeyPatch(Attachment, \"default\", {after: (data) => {\n if(!settingsCookie[\"fork-ps-6\"])return\n const attachment = data.methodArguments[0] || null\n const children = Utils.getNestedProp(data.returnValue, \"props.children\");\n\n if (!children || !attachment || !attachment.url)return\n if (!Array.isArray(children)) return;\n\n const id = uuidv4()\n children.push(BDV2.react.createElement(\"span\", {\n id: \"certified-\"+id\n }))\n PluginCertifier.patch(attachment, \"certified-\"+id)\n }})\n}\n\nCore.prototype.patchMessageHeader = function() {\n if (this.messageHeaderPatch) return;\n const MessageHeader = WebpackModules.findByProps(\"MessageTimestamp\");\n const Anchor = WebpackModules.find(m => m.displayName == \"Anchor\");\n if (!Anchor || !MessageHeader || !MessageHeader.default) return;\n this.messageHeaderPatch = Utils.monkeyPatch(MessageHeader, \"default\", {after: (data) => {\n const author = Utils.getNestedProp(data.methodArguments[0], \"message.author\");\n // const header = Utils.getNestedProp(data.returnValue, \"props.children.1.props\");\n const children = Utils.getNestedProp(data.returnValue, \"props.children.1.props.children.1.props.children\");\n if (!children || !author || !author.id)return\n // if (header && header.className) header.className += \" \"\n if (!Array.isArray(children)) return;\n if (author.id === \"249746236008169473\") { // Rauenzi: BandagedBD Developer\n children.push(\n BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: \"BandagedBD Developer\"},\n BDV2.React.createElement(Anchor, {className: \"bd-chat-badge\", href: \"https://github.com/rauenzi/BetterDiscordApp\", title: \"BandagedBD\", target: \"_blank\"},\n BDV2.React.createElement(BDLogo, {size: \"16px\", className: \"bd-logo\"})\n )\n )\n );\n } else if (author.id === \"696481194443014174\" || author.id === \"696003456611385396\"){ // Not Thomiz: Lightcord Developer, Phorcys: Lightcord Developer\n children.push(\n BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: \"Lightcord Developer\"},\n BDV2.React.createElement(Anchor, {className: \"bd-chat-badge\", href: \"https://github.com/Lightcord/Lightcord\", title: \"Lightcord\", target: \"_blank\"},\n BDV2.React.createElement(LightcordLogo, {size: \"16px\", className: \"bd-logo\"})\n )\n )\n );\n }\n const id = uuidv4()\n children.push(\n BDV2.React.createElement(\"div\", {\n id: \"badges-\"+id,\n style: {\n display: \"inline\"\n }\n })\n )\n applyBadges(id, author, true)\n }});\n};\n\nfunction applyBadges(id, user, chat){\n process.nextTick(() => {\n const div = document.getElementById(\"badges-\"+id)\n if(!div || div.childNodes.length > 0)return\n if(div.childNodes.length)return\n let blockDiv = document.createElement(\"div\")\n blockDiv.style.display = \"none\"\n div.appendChild(blockDiv)\n\n const Anchor = WebpackModules.find(m => m.displayName == \"Anchor\");\n\n distant.getBadges(user.id)\n .then(badges => {\n badges.forEach(badge => {\n const props = {\n svg: {\n size: \"16px\", \n className: \"bd-logo\",\n width: \"16px\", \n }\n }\n badge.scopes.forEach(scope => {\n if(scope === \"user\"){// require user\n props.user = user\n }\n }) \n if(!badge.href){\n props.Anchor = Anchor\n props.href = {\n className: chat ? \"bd-chat-badge\" : \"bd-member-badge\", \n title: badge.name, \n target: \"_blank\"\n }\n }\n const element = BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: badge.name},\n badge.href ? BDV2.react.createElement(Anchor, {\n href: badge.href,\n className: chat ? \"bd-chat-badge\" : \"bd-member-badge\", \n title: badge.name, \n target: \"_blank\"\n }, BDV2.React.createElement(badge.component, props)) : BDV2.React.createElement(badge.component, props)\n )\n const div2 = document.createElement(\"div\")\n BDV2.reactDom.render(element, div2)\n div2.childNodes.forEach(node => {\n div.appendChild(node)\n })\n })\n })\n })\n}\n\nCore.prototype.patchMemberList = function() {\n if (this.memberListPatch) return;\n const MemberListItem = WebpackModules.findByDisplayName(\"MemberListItem\");\n const Anchor = WebpackModules.find(m => m.displayName == \"Anchor\");\n if (!Anchor || !MemberListItem || !MemberListItem.prototype || !MemberListItem.prototype.renderDecorators) return;\n this.memberListPatch = Utils.monkeyPatch(MemberListItem.prototype, \"renderDecorators\", {after: (data) => {\n const user = Utils.getNestedProp(data.thisObject, \"props.user\");\n const children = Utils.getNestedProp(data.returnValue, \"props.children\");\n if (!children || !user || !user.id)return\n // if (header && header.className) header.className += \" \"\n if (!Array.isArray(children)) return;\n if (user.id === \"249746236008169473\") {\n children.push(\n BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: \"BandagedBD Developer\"},\n BDV2.React.createElement(Anchor, {className: \"bd-member-badge\", href: \"https://github.com/rauenzi/BetterDiscordApp\", title: \"BandagedBD\", target: \"_blank\"},\n BDV2.React.createElement(BDLogo, {size: \"16px\", className: \"bd-logo\"})\n )\n )\n );\n } else if (user.id === \"696481194443014174\" || user.id === \"696003456611385396\"){\n children.push(\n BDV2.React.createElement(TooltipWrap, {color: \"black\", side: \"top\", text: \"Lightcord Developer\"},\n BDV2.React.createElement(Anchor, {className: \"bd-member-badge\", href: \"https://github.com/Lightcord/Lightcord\", title: \"Lightcord\", target: \"_blank\"},\n BDV2.React.createElement(LightcordLogo, {size: \"16px\", className: \"bd-logo\"})\n )\n )\n );\n }\n const id = uuidv4()\n children.push(\n BDV2.React.createElement(\"div\", {id: \"badges-\"+id})\n )\n applyBadges(id, user, false)\n }});\n};\n\nCore.prototype.updateInjector = async function() {\n // There will never be an injection path, so we do not need the code below. \n // Insert comments so it will be erased when production.\n \n const injectionPath = DataStore.injectionPath;\n if (!injectionPath) return false;\n\n /*\n\n const fs = require(\"fs\");\n const path = require(\"path\");\n const rmrf = require(\"rimraf\");\n const yauzl = require(\"yauzl\");\n const mkdirp = require(\"mkdirp\");\n const request = require(\"request\");\n\n const parentPath = path.resolve(injectionPath, \"..\");\n const folderName = path.basename(injectionPath);\n const zipLink = \"https://github.com/rauenzi/BetterDiscordApp/archive/injector.zip\";\n const savedZip = path.resolve(parentPath, \"injector.zip\");\n const extractedFolder = path.resolve(parentPath, \"BetterDiscordApp-injector\");\n\n // Download the injector zip file\n Utils.log(\"InjectorUpdate\", \"Downloading \" + zipLink);\n let success = await new Promise(resolve => {\n request.get({url: zipLink, encoding: null}, async (error, response, body) => {\n if (error || response.statusCode !== 200) return resolve(false);\n // Save a backup in case someone has their own copy\n const alreadyExists = await new Promise(res => fs.exists(savedZip, res));\n if (alreadyExists) await new Promise(res => fs.rename(savedZip, `${savedZip}.bak${Math.round(performance.now())}`, res));\n\n Utils.log(\"InjectorUpdate\", \"Writing \" + savedZip);\n fs.writeFile(savedZip, body, err => resolve(!err));\n });\n });\n if (!success) return success;\n\n // Check and delete rename extraction\n const alreadyExists = await new Promise(res => fs.exists(extractedFolder, res));\n if (alreadyExists) await new Promise(res => fs.rename(extractedFolder, `${extractedFolder}.bak${Math.round(performance.now())}`, res));\n \n // Unzip the downloaded zip file\n const zipfile = await new Promise(r => yauzl.open(savedZip, {lazyEntries: true}, (err, zip) => r(zip)));\n zipfile.on(\"entry\", function(entry) {\n // Skip directories, they are handled with mkdirp\n if (entry.fileName.endsWith(\"/\")) return zipfile.readEntry();\n\n Utils.log(\"InjectorUpdate\", \"Extracting \" + entry.fileName);\n // Make any needed parent directories\n const fullPath = path.resolve(parentPath, entry.fileName);\n mkdirp.sync(path.dirname(fullPath));\n zipfile.openReadStream(entry, function(err, readStream) {\n if (err) return success = false;\n readStream.on(\"end\", function() {zipfile.readEntry();}); // Go to next file after this\n readStream.pipe(fs.createWriteStream(fullPath));\n });\n });\n zipfile.readEntry(); // Start reading\n\n // Wait for the final file to finish\n await new Promise(resolve => zipfile.once(\"end\", resolve));\n\n // Save a backup in case something goes wrong during final step\n const backupFolder = path.resolve(parentPath, `${folderName}.bak${Math.round(performance.now())}`);\n await new Promise(resolve => fs.rename(injectionPath, backupFolder, resolve));\n\n // Rename the extracted folder to what it should be\n Utils.log(\"InjectorUpdate\", `Renaming ${path.basename(extractedFolder)} to ${folderName}`);\n success = await new Promise(resolve => fs.rename(extractedFolder, injectionPath, err => resolve(!err)));\n if (!success) {\n Utils.err(\"InjectorUpdate\", \"Failed to rename the final directory\");\n return success;\n }\n\n // If rename had issues, delete what we tried to rename and restore backup\n if (!success) {\n Utils.err(\"InjectorUpdate\", \"Something went wrong... restoring backups.\");\n await new Promise(resolve => rmrf(extractedFolder, resolve));\n await new Promise(resolve => fs.rename(backupFolder, injectionPath, resolve));\n return success;\n }\n\n // If we've gotten to this point, everything should have gone smoothly.\n // Cleanup the backup folder then remove the zip\n await new Promise(resolve => rmrf(backupFolder, resolve));\n await new Promise(resolve => fs.unlink(savedZip, resolve));\n\n Utils.log(\"InjectorUpdate\", \"Injector Updated!\");\n return success;*/\n};\n\nexport default new Core();\n\n/**\n * Don't expose core - could be dangerous for now\n */","import {pluginCookie, themeCookie, bdplugins, bdthemes, settingsCookie, settings} from \"../0globals\";\nimport mainCore from \"./core\";\nimport Utils from \"./utils\";\nimport BDV2 from \"./v2\";\nimport DataStore from \"./dataStore\";\nimport pluginModule from \"./pluginModule\";\nimport themeModule from \"./themeModule\";\nimport settingsPanel from \"./settingsPanel\";\nimport DOM from \"./domtools\";\n\nconst BdApi = {\n get React() { return BDV2.React; },\n get ReactDOM() { return BDV2.ReactDom; },\n get ReactComponent() {return BDV2.ReactComponent;},\n get WindowConfigFile() {return Utils.WindowConfigFile;},\n get settings() {return settings;},\n get emotes() {return null}, // deprecated, deleted all emotes from betterdiscord.\n get screenWidth() { return Math.max(document.documentElement.clientWidth, window.innerWidth || 0); },\n get screenHeight() { return Math.max(document.documentElement.clientHeight, window.innerHeight || 0); }\n};\n\nBdApi.getAllWindowPreferences = function() {\n return Utils.getAllWindowPreferences();\n};\n\nBdApi.getWindowPreference = function(key) {\n return Utils.getWindowPreference(key);\n};\n\nBdApi.setWindowPreference = function(key, value) {\n return Utils.setWindowPreference(key, value);\n};\n\n//Inject CSS to document head\n//id = id of element\n//css = custom css\nBdApi.injectCSS = function (id, css) {\n DOM.addStyle(DOM.escapeID(id), css);\n};\n\n//Clear css/remove any element\n//id = id of element\nBdApi.clearCSS = function (id) {\n DOM.removeStyle(DOM.escapeID(id));\n};\n\n//Inject CSS to document head\n//id = id of element\n//css = custom css\nBdApi.linkJS = function (id, url) {\n DOM.addScript(DOM.escapeID(id), url);\n};\n\n//Clear css/remove any element\n//id = id of element\nBdApi.unlinkJS = function (id) {\n DOM.removeScript(DOM.escapeID(id));\n};\n\n//Get another plugin\n//name = name of plugin\nBdApi.getPlugin = function (name) {\n if (bdplugins.hasOwnProperty(name)) {\n return bdplugins[name].plugin;\n }\n return null;\n};\n\n//Get BetterDiscord Core\nBdApi.getCore = function () {\n Utils.warn(\"Deprecation Notice\", `BdApi.getCore() will be removed in future versions.`);\n return mainCore;\n};\n\n/**\n * Shows a generic but very customizable modal.\n * @param {string} title - title of the modal\n * @param {string} content - a string of text to display in the modal\n */\nBdApi.alert = function (title, content) {\n return Utils.showConfirmationModal(title, content, {cancelText: null});\n};\n\n/**\n * Shows a generic but very customizable confirmation modal with optional confirm and cancel callbacks.\n * @param {string} title - title of the modal\n * @param {(string|ReactElement|Array)} children - a single or mixed array of react elements and strings. Every string is wrapped in Discord's `Markdown` component so strings will show and render properly.\n * @param {object} [options] - options to modify the modal\n * @param {boolean} [options.danger=false] - whether the main button should be red or not\n * @param {string} [options.confirmText=Okay] - text for the confirmation/submit button\n * @param {string} [options.cancelText=Cancel] - text for the cancel button\n * @param {callable} [options.onConfirm=NOOP] - callback to occur when clicking the submit button\n * @param {callable} [options.onCancel=NOOP] - callback to occur when clicking the cancel button\n * @param {string} [options.key] - key used to identify the modal. If not provided, one is generated and returned\n * @returns {string} - the key used for this modal\n */\nBdApi.showConfirmationModal = function (title, content, options = {}) {\n return Utils.showConfirmationModal(title, content, options);\n};\n\n//Show toast alert\nBdApi.showToast = function(content, options = {}) {\n Utils.showToast(content, options);\n};\n\n// Finds module\nBdApi.findModule = function(filter) {\n return BDV2.WebpackModules.find(filter);\n};\n\n// Finds module\nBdApi.findAllModules = function(filter) {\n return BDV2.WebpackModules.findAll(filter);\n};\n\n// Finds module\nBdApi.findModuleByProps = function(...props) {\n return BDV2.WebpackModules.findByUniqueProperties(props);\n};\n\nBdApi.findModuleByPrototypes = function(...protos) {\n return BDV2.WebpackModules.findByPrototypes(protos);\n};\n\nBdApi.findModuleByDisplayName = function(name) {\n return BDV2.WebpackModules.findByDisplayName(name);\n};\n\n// Gets react instance\nBdApi.getInternalInstance = function(node) {\n if (!(node instanceof window.jQuery) && !(node instanceof Element)) return undefined;\n if (node instanceof jQuery) node = node[0];\n return BDV2.getInternalInstance(node);\n};\n\n// Gets data\nBdApi.loadData = function(pluginName, key) {\n return DataStore.getPluginData(pluginName, key);\n};\n\nBdApi.getData = BdApi.loadData;\n\n// Sets data\nBdApi.saveData = function(pluginName, key, data) {\n return DataStore.setPluginData(pluginName, key, data);\n};\n\nBdApi.setData = BdApi.saveData;\n\n// Deletes data\nBdApi.deleteData = function(pluginName, key) {\n return DataStore.deletePluginData(pluginName, key);\n};\n\n// Patches other functions\nBdApi.monkeyPatch = function(what, methodName, options) {\n return Utils.monkeyPatch(what, methodName, options);\n};\n\n// Event when element is removed\nBdApi.onRemoved = function(node, callback) {\n return Utils.onRemoved(node, callback);\n};\n\n// Wraps function in try..catch\nBdApi.suppressErrors = function(method, message) {\n return Utils.suppressErrors(method, message);\n};\n\n// Tests for valid JSON\nBdApi.testJSON = function(data) {\n return Utils.testJSON(data);\n};\n\nBdApi.isPluginEnabled = function(name) {\n return !!pluginCookie[name];\n};\n\nBdApi.isThemeEnabled = function(name) {\n return !!themeCookie[name];\n};\n\nBdApi.isSettingEnabled = function(id) {\n return !!settingsCookie[id];\n};\n\nBdApi.enableSetting = function(id) {\n return settingsPanel.onChange(id, true);\n};\n\nBdApi.disableSetting = function(id) {\n return settingsPanel.onChange(id, false);\n};\n\nBdApi.toggleSetting = function(id) {\n return settingsPanel.onChange(id, !settingsCookie[id]);\n};\n\n// Gets data\nBdApi.getBDData = function(key) {\n return DataStore.getBDData(key);\n};\n\n// Sets data\nBdApi.setBDData = function(key, data) {\n return DataStore.setBDData(key, data);\n};\n\n\n\nconst makeAddonAPI = (cookie, list, manager) => new class AddonAPI {\n\n get folder() {return manager.folder;}\n\n isEnabled(name) {\n return !!cookie[name];\n }\n\n enable(name) {\n return manager.enable(name);\n }\n\n disable(name) {\n return manager.disable(name);\n }\n\n toggle(name) {\n if (cookie[name]) this.disable(name);\n else this.enable(name);\n }\n\n reload(name) {\n return manager.reload(name);\n }\n\n get(name) {\n if (list.hasOwnProperty(name)) {\n if (list[name].plugin) return list[name].plugin;\n return list[name];\n }\n return null;\n }\n\n getAll() {\n return Object.keys(list).map(k => this.get(k)).filter(a => a);\n }\n};\n\nBdApi.Plugins = makeAddonAPI(pluginCookie, bdplugins, pluginModule);\nBdApi.Themes = makeAddonAPI(themeCookie, bdthemes, themeModule);\n\nexport default BdApi;\n\nwindow.Lightcord.BetterDiscord.BdApi = BdApi","export default function() {\r\n const contentWindowGetter = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, \"contentWindow\").get;\r\n Object.defineProperty(HTMLIFrameElement.prototype, \"contentWindow\", {\r\n get: function () {\r\n const contentWindow = Reflect.apply(contentWindowGetter, this, arguments);\r\n return new Proxy(contentWindow, {\r\n getOwnPropertyDescriptor: function(obj, prop) {\r\n if (prop === \"localStorage\") return undefined;\r\n return Object.getOwnPropertyDescriptor(obj, prop);\r\n },\r\n get: function(obj, prop) {\r\n if (prop === \"localStorage\") return null;\r\n const val = obj[prop];\r\n if (typeof val === \"function\") return val.bind(obj);\r\n return val;\r\n }\r\n });\r\n }\r\n });\r\n\r\n // Prevent interception by patching Reflect.apply and Function.prototype.bind\r\n Object.defineProperty(Reflect, \"apply\", {value: Reflect.apply, writable: false, configurable: false});\r\n Object.defineProperty(Function.prototype, \"bind\", {value: Function.prototype.bind, writable: false, configurable: false});\r\n\r\n const oOpen = XMLHttpRequest.prototype.open;\r\n XMLHttpRequest.prototype.open = function() {\r\n const url = arguments[1];\r\n if (url.toLowerCase().includes(\"api/webhooks\")) return null;\r\n return Reflect.apply(oOpen, this, arguments);\r\n };\r\n}","import localStorageFix from \"./localStorageFix\";\nimport loadingIcon from \"./loadingIcon\";\nlocalStorageFix();\nloadingIcon();\n\nconst deprecateGlobal = (key, value) => {\n Object.defineProperty(window, key, {\n get() {\n Utils.warn(\"Deprecated Global\", `\"${key}\" will be removed in future versions. Please only use BdApi.`);\n return value;\n }\n }); \n};\n\n\nimport * as Globals from \"./0globals\";\n\nconst globalKeys = Object.keys(Globals);\nfor (const key of globalKeys) deprecateGlobal(key, Globals[key]);\n\n\nimport BdApi from \"./modules/bdApi\";\nimport BDV2 from \"./modules/v2\";\nimport pluginModule from \"./modules/pluginModule\";\nimport themeModule from \"./modules/themeModule\";\nimport Utils from \"./modules/utils\";\nimport BDEvents from \"./modules/bdEvents\";\nimport settingsPanel from \"./modules/settingsPanel\";\nimport DataStore from \"./modules/dataStore\";\nimport ContentManager from \"./modules/contentManager\";\nimport ClassNormalizer from \"./modules/classNormalizer\";\n\ndeprecateGlobal(\"BDV2\", BDV2);\ndeprecateGlobal(\"pluginModule\", pluginModule);\ndeprecateGlobal(\"themeModule\", themeModule);\ndeprecateGlobal(\"Utils\", Utils);\ndeprecateGlobal(\"BDEvents\", BDEvents);\ndeprecateGlobal(\"settingsPanel\", settingsPanel);\ndeprecateGlobal(\"DataStore\", DataStore);\ndeprecateGlobal(\"ContentManager\", ContentManager);\ndeprecateGlobal(\"ClassNormalizer\", ClassNormalizer);\n\nwindow.BdApi = BdApi;\n\nimport Core from \"./modules/core\";\ndeprecateGlobal(\"mainCore\", Core);\n\n// TODO: Change Init mode and stop using CoreWrapper.\nexport default class CoreWrapper {\n constructor(bdConfig, methods) {\n Core.setConfig(bdConfig);\n Core.setMethods(methods);\n }\n\n init() {\n // deprecateGlobal(\"mainCore\", this.mainCore);\n Core.init();\n }\n}","export default () => {\r\n const v2Loader = document.createElement(\"div\");\r\n v2Loader.className = \"bd-loaderv2\";\r\n v2Loader.title = \"BandagedBD is loading...\";\r\n document.body.appendChild(v2Loader);\r\n};"],"sourceRoot":""}