import {React, Logger, Strings, WebpackModules, DOM, DiscordModules} from "modules"; import CloseButton from "../icons/close"; import ReloadIcon from "../icons/reload"; import EditIcon from "../icons/edit"; import DeleteIcon from "../icons/delete"; import Switch from "./components/switch"; import ErrorBoundary from "../errorboundary"; const Tooltip = WebpackModules.getByDisplayName("Tooltip"); export default class AddonCard extends React.Component { constructor(props) { super(props); this.state = { settingsOpen: false }; this.settingsPanel = ""; this.panelRef = React.createRef(); this.onChange = this.onChange.bind(this); this.reload = this.reload.bind(this); this.showSettings = this.showSettings.bind(this); this.closeSettings = this.closeSettings.bind(this); } reload() { if (!this.props.reload) return; this.props.addon = this.props.reload(this.props.addon.id); this.forceUpdate(); } componentDidUpdate() { if (!this.state.settingsOpen) return; if (this.settingsPanel instanceof Node) this.panelRef.current.appendChild(this.settingsPanel); setImmediate(() => { const isHidden = (container, element) => { const cTop = container.scrollTop; const cBottom = cTop + container.clientHeight; const eTop = element.offsetTop; const eBottom = eTop + element.clientHeight; return (eTop < cTop || eBottom > cBottom); }; const thisNode = this.panelRef.current; const container = thisNode.closest(".scroller"); if (!isHidden(container, thisNode)) return; const thisNodeOffset = DOM.offset(thisNode); const containerOffset = DOM.offset(container); const original = container.scrollTop; const endPoint = thisNodeOffset.top - containerOffset.top + container.scrollTop - 30; DOM.animate({ duration: 300, update: function(progress) { if (endPoint > original) container.scrollTop = original + (progress * (endPoint - original)); else container.scrollTop = original - (progress * (original - endPoint)); } }); }); } getString(value) {return typeof value == "string" ? value : value.toString();} onChange() { this.props.onChange && this.props.onChange(this.props.addon.id); this.props.enabled = !this.props.enabled; } showSettings() { if (!this.props.hasSettings) return; this.setState({settingsOpen: true}); } closeSettings() { this.panelRef.current.innerHTML = ""; this.setState({settingsOpen: false}); } buildTitle(name, version, author) { const title = Strings.Addons.title.split(/({{[A-Za-z]+}})/); const nameIndex = title.findIndex(s => s == "{{name}}"); if (nameIndex) title[nameIndex] = React.createElement("span", {className: "bd-name"}, name); const versionIndex = title.findIndex(s => s == "{{version}}"); if (nameIndex) title[versionIndex] = React.createElement("span", {className: "bd-version"}, version); const authorIndex = title.findIndex(s => s == "{{author}}"); if (nameIndex) title[authorIndex] = React.createElement("span", {className: "bd-author"}, author); return title.flat(); } get settingsComponent() { const addon = this.props.addon; const name = this.getString(addon.name); try { this.settingsPanel = this.props.getSettingsPanel(); } catch (err) { Logger.stacktrace("Addon Settings", "Unable to get settings panel for " + name + ".", err); } const props = {id: `${name}-settings`, className: "addon-settings", ref: this.panelRef}; if (typeof(settingsPanel) == "string") { Logger.warn("Addon Settings", "Using a DOMString is officially deprecated."); props.dangerouslySetInnerHTML = this.settingsPanel; } return