diff --git a/components/Button.jsx b/components/Button.jsx index 21594c6..6e0a7ef 100644 --- a/components/Button.jsx +++ b/components/Button.jsx @@ -1,6 +1,7 @@ const { React, getModule, i18n: { Messages } } = require('powercord/webpack'); -const { ContextMenu } = require('powercord/components'); -const { camelCaseify, findInReactTree } = require('powercord/util'); +const ContextMenu = require('../modules/PowerCord-libs/components/ContextMenu'); +const { findInReactTree } = require('powercord/util'); +const camelCaseify = require('../modules/PowerCord-libs/util/camelCaseify'); const getDefaultSaveDir = require('../utils/getDefaultSaveDir'); const buttonStructure = require('../structures/button'); diff --git a/modules/PowerCord-libs/components/ContextMenu.jsx b/modules/PowerCord-libs/components/ContextMenu.jsx new file mode 100644 index 0000000..8ba66b4 --- /dev/null +++ b/modules/PowerCord-libs/components/ContextMenu.jsx @@ -0,0 +1,176 @@ +const { React, getModule, contextMenu: { closeContextMenu } } = require('powercord/webpack'); +const { getOwnerInstance, waitFor } = require('powercord/util'); + +class ContextMenu extends React.PureComponent { + constructor (props) { // @todo: deprecate this + super(props); + this.state = {}; + } + + static renderRawItems (items) { + const cm = new ContextMenu(); + const res = cm.renderItems(items, { + standalone: true, + depth: 0, + group: 0, + i: 0 + }); + return res; + } + + render () { + if (this.props.items) { // Just assume we're rendering just a simple part of a context menu + return this.renderItems(this.props.items, { + depth: 0, + group: 0, + i: 0 + }); + } + + const { default: Menu, MenuGroup } = getModule([ 'MenuGroup' ], false); + return ( + + {this.props.itemGroups.map((items, i) => ( + + {this.renderItems(items, { + depth: 0, + group: i, + i: 0 + })} + + ))} + + ); + } + + renderItems (items, ctx) { + return items.map(item => { + ctx.i++; + switch (item.type) { + case 'button': + return this.renderButton(item, ctx); + + case 'checkbox': + return this.renderCheckbox(item, ctx); + + case 'slider': + return this.renderSlider(item, ctx); + + case 'submenu': + return this.renderSubMenu(item, ctx); + + default: + return null; + } + }); + } + + renderButton (item, ctx) { + const { MenuItem } = getModule([ 'MenuGroup' ], false); + return ( + { + if (item.disabled) { + waitFor('#app-mount > div[class] > div').then(app => getOwnerInstance(app).shake(600, 5)); + } else if (item.onClick) { + item.onClick(); + } + }} + /> + ); + } + + renderCheckbox (item, ctx) { + const { MenuCheckboxItem } = getModule([ 'MenuGroup' ], false); + const elementKey = `active-${ctx.group}-${ctx.depth}-${ctx.i}`; + const isStandalone = !!ctx.standalone; + const active = this.state[elementKey] !== void 0 + ? this.state[elementKey] + : item.defaultState; + + return ( + { + const newActive = !active; + if (item.onToggle) { + item.onToggle(newActive); + } + if (isStandalone) { + const el = e.target.closest('[role="menu"]'); + setImmediate(() => getOwnerInstance(el).forceUpdate()); + } else { + this.setState({ [elementKey]: newActive }); + } + }} + /> + ); + } + + renderSlider (item, ctx) { + const { MenuControlItem } = getModule([ 'MenuGroup' ], false); + const Slider = getModule(m => m.render && m.render.toString().includes('sliderContainer'), false); + return ( + } + /> + ); + } + + renderSubMenu (item, ctx) { + const { MenuItem } = getModule([ 'MenuGroup' ], false); + const elementKey = `items-${ctx.group}-${ctx.depth}-${ctx.i}`; + let items = this.state[elementKey]; + if (items === void 0) { + items = item.getItems(); + this.setState({ [elementKey]: items }); + if (items instanceof Promise) { + items.then(fetchedItems => this.setState({ [elementKey]: fetchedItems })); + } + } + return ( + + {items && !(items instanceof Promise) && items.length !== 0 && !item.disabled && this.renderItems(items, { + depth: ctx.depth + 1, + group: 0, + i: 0 + })} + + ); + } +} + +module.exports = ContextMenu; diff --git a/modules/PowerCord-libs/readme.txt b/modules/PowerCord-libs/readme.txt new file mode 100644 index 0000000..6b7c30a --- /dev/null +++ b/modules/PowerCord-libs/readme.txt @@ -0,0 +1,3 @@ +https://github.com/powercord-org/powercord/tree/v2/src/fake_node_modules/powercord + +modules taken to maintain compatibility diff --git a/modules/PowerCord-libs/util/camelCaseify.js b/modules/PowerCord-libs/util/camelCaseify.js new file mode 100644 index 0000000..65f25a7 --- /dev/null +++ b/modules/PowerCord-libs/util/camelCaseify.js @@ -0,0 +1,9 @@ +module.exports = (str) => + str + .split('-') + .map((s, i) => ( + i === 0 + ? s + : s[0].toUpperCase() + s.slice(1) + )) + .join(''); diff --git a/tools/Lens/Settings.jsx b/tools/Lens/Settings.jsx index 1c1258d..2298c14 100644 --- a/tools/Lens/Settings.jsx +++ b/tools/Lens/Settings.jsx @@ -1,5 +1,5 @@ const { React } = require('powercord/webpack'); -const { ContextMenu } = require('powercord/components'); +const ContextMenu = require('../../modules/PowerCord-libs/components/ContextMenu'); const settings = require('../../structures/lensSettings'); module.exports = class LensSettings extends React.PureComponent {