From 4c5300be1264636b86b261f9b94cf213c9c9a87a Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 00:23:08 +0300 Subject: [PATCH 01/11] Custom context menu --- client/src/index.js | 4 +- .../styles/partials/generic/contextmenu.scss | 184 ++++++++++++++++++ client/src/styles/partials/generic/index.scss | 1 + .../src/styles/partials/generic/layouts.scss | 4 + client/src/ui/bdui.js | 7 +- client/src/ui/components/BdContextMenu.vue | 50 +++++ .../src/ui/components/contextmenu/Button.vue | 23 +++ .../src/ui/components/contextmenu/Group.vue | 59 ++++++ .../src/ui/components/contextmenu/Toggle.vue | 27 +++ client/src/ui/components/index.js | 1 + client/src/ui/contextmenus.js | 25 +++ client/src/ui/dom.js | 1 + client/src/ui/ui.js | 1 + 13 files changed, 384 insertions(+), 3 deletions(-) create mode 100644 client/src/styles/partials/generic/contextmenu.scss create mode 100644 client/src/ui/components/BdContextMenu.vue create mode 100644 client/src/ui/components/contextmenu/Button.vue create mode 100644 client/src/ui/components/contextmenu/Group.vue create mode 100644 client/src/ui/components/contextmenu/Toggle.vue create mode 100644 client/src/ui/contextmenus.js diff --git a/client/src/index.js b/client/src/index.js index 98331530..3999c550 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -8,7 +8,7 @@ * LICENSE file in the root directory of this source tree. */ -import { DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications } from 'ui'; +import { DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, BdContextMenu } from 'ui'; import BdCss from './styles/index.scss'; import { Events, CssEditor, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, Vendor, WebpackModules, Patcher, MonkeyPatch, ReactComponents, ReactHelpers, ReactAutoPatcher, DiscordApi, BdWebApi, Connectivity, Cache } from 'modules'; import { ClientLogger as Logger, ClientIPC, Utils } from 'common'; @@ -28,7 +28,7 @@ class BetterDiscord { Logger.log('main', 'BetterDiscord starting'); this._bd = { - DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, + DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, BdContextMenu, Events, CssEditor, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, diff --git a/client/src/styles/partials/generic/contextmenu.scss b/client/src/styles/partials/generic/contextmenu.scss new file mode 100644 index 00000000..71b05797 --- /dev/null +++ b/client/src/styles/partials/generic/contextmenu.scss @@ -0,0 +1,184 @@ +.bd-cm { + background: #18191c; + box-shadow: 0 0 1px rgba(0,0,0,.82), 0 1px 4px rgba(0,0,0,.1); + border-radius: 5px; + position: fixed; + width: 170px; + z-index: 1005; + user-select: none; + + &.bd-cmRenderLeft { + .bd-cm { + margin-left: -170px; + } + } + + .bd-cm { + left: 170px; + max-height: 270px; + overflow-y: auto; + contain: layout; + flex: 1; + min-height: 1px; + margin-left: 170px; + + &::-webkit-scrollbar { + height: 8px; + width: 8px; + } + + &::-webkit-scrollbar-thumb { + background-clip: padding-box; + background-color: rgba(32,34,37,.6); + border: 2px solid transparent; + border-radius: 4px; + cursor: move; + } + + &::-webkit-scrollbar-track { + background-clip: padding-box; + border-radius: 7px; + border: 2px solid transparent; + } + } + + .bd-cmGroup:not(:first-child):not(:empty) { + &:not(:first-child) { + &:not(:empty) { + border-top: 1px solid hsla(0,0%, 96.1%, .08); + } + } + } + + .bd-cmSub { + .bd-materialDesignIcon { + position: absolute; + right: 0; + bottom: 2px; + fill: hsla(0, 0%, 100%, .6); + + svg { + height: 20px; + transform: rotate(-90deg); + } + } + + &:hover { + svg { + fill: #fff; + } + } + } + + .bd-cmItem { + cursor: default; + color: hsla(0,0%,100%,.6); + border-radius: 5px; + box-sizing: border-box; + font-size: 13px; + font-weight: 500; + line-height: 16px; + margin: 2px 0; + overflow: hidden; + padding: 6px 9px; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + display: flex; + + .bd-cmHint { + opacity: .8; + color: hsla(0,0%,100%,.6); + } + + span { + max-width: 140px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex-grow: 1; + } + + img { + height: 16px; + } + + &:hover { + background: #040405; + color: #fff; + } + } + + .bd-cmToggle { + align-items: center; + display: flex; + justify-content: space-between; + padding: 5px 9px; + + .bd-cmLabel { + overflow: hidden; + padding-right: 4px; + text-overflow: ellipsis; + white-space: nowrap; + } + + .bd-cmCheckbox { + cursor: pointer; + margin-left: 3px; + pointer-events: none; + align-items: center; + cursor: pointer; + display: flex; + + .bd-cmCheckboxInner { + flex-shrink: 0; + height: 18px; + position: relative; + vertical-align: top; + width: 18px; + + &:before, + &:after { + content: ''; + } + + input { + display: none; + + &:checked { + + span { + background-color: #7289da; + border-color: #7289da; + + &:after { + border-color: #fff; + border-style: solid; + border-width: 0 2px 2px 0; + content: ""; + display: table; + height: 10px; + left: 4px; + position: absolute; + top: 0; + transform: rotate(45deg); + width: 4px; + } + } + } + } + + span { + border: 2px solid hsla(0,0%,100%,.2); + border-radius: 2px; + bottom: 0; + box-sizing: border-box; + left: 0; + position: absolute; + right: 0; + top: 0; + transition: .24s; + } + } + } + } +} diff --git a/client/src/styles/partials/generic/index.scss b/client/src/styles/partials/generic/index.scss index f8472f62..d6d5aa5e 100644 --- a/client/src/styles/partials/generic/index.scss +++ b/client/src/styles/partials/generic/index.scss @@ -13,3 +13,4 @@ @import './toasts'; @import './badges'; @import './notifications'; +@import './contextmenu'; diff --git a/client/src/styles/partials/generic/layouts.scss b/client/src/styles/partials/generic/layouts.scss index 17c3beba..b9741d9a 100644 --- a/client/src/styles/partials/generic/layouts.scss +++ b/client/src/styles/partials/generic/layouts.scss @@ -29,3 +29,7 @@ .bd-inline { display: inline; } + +.bd-hidden { + display: none; +} diff --git a/client/src/ui/bdui.js b/client/src/ui/bdui.js index c57e918e..1ca7656a 100644 --- a/client/src/ui/bdui.js +++ b/client/src/ui/bdui.js @@ -12,7 +12,7 @@ import { Events, DiscordApi, Settings } from 'modules'; import { remote } from 'electron'; import DOM from './dom'; import Vue from './vue'; -import { BdSettingsWrapper, BdModals, BdToasts, BdNotifications } from './components'; +import { BdSettingsWrapper, BdModals, BdToasts, BdNotifications, BdContextMenu } from './components'; export default class { @@ -53,6 +53,7 @@ export default class { DOM.createElement('div', null, 'bd-modals').appendTo(DOM.bdModals); DOM.createElement('div', null, 'bd-toasts').appendTo(DOM.bdToasts); DOM.createElement('div', null, 'bd-notifications').appendTo(DOM.bdNotifications); + DOM.createElement('div', null, 'bd-contextmenu').appendTo(DOM.bdContextMenu); DOM.createElement('bd-tooltips').appendTo(DOM.bdBody); this.toasts = new (Vue.extend(BdToasts))({ @@ -71,6 +72,10 @@ export default class { el: '#bd-notifications' }); + this.contextmenu = new (Vue.extend(BdContextMenu))({ + el: '#bd-contextmenu' + }); + return this.vueInstance; } diff --git a/client/src/ui/components/BdContextMenu.vue b/client/src/ui/components/BdContextMenu.vue new file mode 100644 index 00000000..be46ee56 --- /dev/null +++ b/client/src/ui/components/BdContextMenu.vue @@ -0,0 +1,50 @@ +/** + * BetterDiscord Context Menu Component + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + + + + diff --git a/client/src/ui/components/contextmenu/Button.vue b/client/src/ui/components/contextmenu/Button.vue new file mode 100644 index 00000000..995e950a --- /dev/null +++ b/client/src/ui/components/contextmenu/Button.vue @@ -0,0 +1,23 @@ +/** + * BetterDiscord Context Menu Button Component + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + + + + diff --git a/client/src/ui/components/contextmenu/Group.vue b/client/src/ui/components/contextmenu/Group.vue new file mode 100644 index 00000000..0cfc3486 --- /dev/null +++ b/client/src/ui/components/contextmenu/Group.vue @@ -0,0 +1,59 @@ +/** + * BetterDiscord Context Menu Group Component + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + + + + diff --git a/client/src/ui/components/contextmenu/Toggle.vue b/client/src/ui/components/contextmenu/Toggle.vue new file mode 100644 index 00000000..25e4f7ae --- /dev/null +++ b/client/src/ui/components/contextmenu/Toggle.vue @@ -0,0 +1,27 @@ +/** + * BetterDiscord Context Menu Toggle Component + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + + + + diff --git a/client/src/ui/components/index.js b/client/src/ui/components/index.js index 60616b7a..f4b8d7ab 100644 --- a/client/src/ui/components/index.js +++ b/client/src/ui/components/index.js @@ -3,3 +3,4 @@ export { default as BdSettings } from './BdSettings.vue'; export { default as BdModals } from './BdModals.vue'; export { default as BdToasts } from './BdToasts.vue'; export { default as BdNotifications } from './BdNotifications.vue'; +export { default as BdContextMenu } from './BdContextMenu.vue'; diff --git a/client/src/ui/contextmenus.js b/client/src/ui/contextmenus.js new file mode 100644 index 00000000..cd95b070 --- /dev/null +++ b/client/src/ui/contextmenus.js @@ -0,0 +1,25 @@ +/* + * BetterDiscord Context Menus + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + +export class BdContextMenu { + + /** + * Show a context menu + * @param {Object[]} grops Groups of items to show in context menu + */ + static show(groups) { + this.activeMenu.menu = { groups }; + } + + static get activeMenu() { + return this._activeMenu || (this._activeMenu = { menu: null }); + } + +} diff --git a/client/src/ui/dom.js b/client/src/ui/dom.js index 91d311f1..e7b0ae43 100644 --- a/client/src/ui/dom.js +++ b/client/src/ui/dom.js @@ -186,6 +186,7 @@ export default class DOM { static get bdModals() { return this.getElement('bd-modals') || this.createElement('bd-modals').appendTo(this.bdBody) } static get bdToasts() { return this.getElement('bd-toasts') || this.createElement('bd-toasts').appendTo(this.bdBody) } static get bdNotifications() { return this.getElement('bd-notifications') || this.createElement('bd-notifications').appendTo(this.bdBody) } + static get bdContextMenu() { return this.getElement('bd-contextmenu') || this.createElement('bd-contextmenu').appendTo(this.bdBody) } static getElement(e) { if (e instanceof BdNode) return e.element; diff --git a/client/src/ui/ui.js b/client/src/ui/ui.js index 8b29f2f6..11c54468 100644 --- a/client/src/ui/ui.js +++ b/client/src/ui/ui.js @@ -4,6 +4,7 @@ export { default as BdMenu, BdMenuItems } from './bdmenu'; export { default as Modals } from './modals'; export { default as Toasts } from './toasts'; export { default as Notifications } from './notifications'; +export * from './contextmenus'; export { default as VueInjector } from './vueinjector'; export { default as Reflection } from './reflection'; From 8637f176c1bb5f372ea66f5ba759ab0a05ffd862 Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 00:34:13 +0300 Subject: [PATCH 02/11] Lint --- .../styles/partials/generic/contextmenu.scss | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/client/src/styles/partials/generic/contextmenu.scss b/client/src/styles/partials/generic/contextmenu.scss index 71b05797..dc2aa280 100644 --- a/client/src/styles/partials/generic/contextmenu.scss +++ b/client/src/styles/partials/generic/contextmenu.scss @@ -1,6 +1,6 @@ .bd-cm { background: #18191c; - box-shadow: 0 0 1px rgba(0,0,0,.82), 0 1px 4px rgba(0,0,0,.1); + box-shadow: 0 0 1px rgba(0, 0, 0, .82), 0 1px 4px rgba(0, 0, 0, .1); border-radius: 5px; position: fixed; width: 170px; @@ -29,7 +29,7 @@ &::-webkit-scrollbar-thumb { background-clip: padding-box; - background-color: rgba(32,34,37,.6); + background-color: rgba(32, 34, 37, .6); border: 2px solid transparent; border-radius: 4px; cursor: move; @@ -42,10 +42,10 @@ } } - .bd-cmGroup:not(:first-child):not(:empty) { + .bd-cmGroup { &:not(:first-child) { &:not(:empty) { - border-top: 1px solid hsla(0,0%, 96.1%, .08); + border-top: 1px solid hsla(0, 0%, 96.1%, .08); } } } @@ -72,7 +72,7 @@ .bd-cmItem { cursor: default; - color: hsla(0,0%,100%,.6); + color: hsla(0, 0%, 100%, .6); border-radius: 5px; box-sizing: border-box; font-size: 13px; @@ -88,7 +88,7 @@ .bd-cmHint { opacity: .8; - color: hsla(0,0%,100%,.6); + color: hsla(0, 0%, 100%, .6); } span { @@ -123,7 +123,6 @@ } .bd-cmCheckbox { - cursor: pointer; margin-left: 3px; pointer-events: none; align-items: center; @@ -137,8 +136,8 @@ vertical-align: top; width: 18px; - &:before, - &:after { + &::before, + &::after { content: ''; } @@ -150,11 +149,11 @@ background-color: #7289da; border-color: #7289da; - &:after { + &::after { border-color: #fff; border-style: solid; border-width: 0 2px 2px 0; - content: ""; + content: ''; display: table; height: 10px; left: 4px; @@ -168,7 +167,7 @@ } span { - border: 2px solid hsla(0,0%,100%,.2); + border: 2px solid hsla(0, 0%, 100%, .2); border-radius: 2px; bottom: 0; box-sizing: border-box; From ef5a1c223c7f423881ecf01c00b783b5966b0e9c Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 01:27:50 +0300 Subject: [PATCH 03/11] Get position from passed event|object --- client/src/ui/components/BdContextMenu.vue | 8 ++------ client/src/ui/contextmenus.js | 7 +++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/client/src/ui/components/BdContextMenu.vue b/client/src/ui/components/BdContextMenu.vue index be46ee56..cd2c41cc 100644 --- a/client/src/ui/components/BdContextMenu.vue +++ b/client/src/ui/components/BdContextMenu.vue @@ -33,18 +33,14 @@ methods: { calculatePosition() { if (!this.activeMenu.menu.groups.length) return {}; + this.mouseX = this.activeMenu.menu.x; + this.mouseY = this.activeMenu.menu.y; const height = this.activeMenu.menu.groups.reduce((total, group) => total + group.items.length, 0) * 28; this.top = window.innerHeight - this.mouseY - height < 0 ? this.mouseY - height : this.mouseY; this.left = window.innerWidth - this.mouseX - 170 < 0 ? this.mouseX - 170 : this.mouseX; this.renderLeft = (this.left + 170 * 2) > window.innerWidth; return { top: `${this.top}px`, left: `${this.left}px` }; } - }, - mounted() { - window.addEventListener('contextmenu', e => { - this.mouseX = e.clientX; - this.mouseY = e.clientY; - }); } } diff --git a/client/src/ui/contextmenus.js b/client/src/ui/contextmenus.js index cd95b070..6c0c1f81 100644 --- a/client/src/ui/contextmenus.js +++ b/client/src/ui/contextmenus.js @@ -12,10 +12,13 @@ export class BdContextMenu { /** * Show a context menu + * @param {MouseEvent|Object} e MouseEvent or Object { x: 0, y: 0 } * @param {Object[]} grops Groups of items to show in context menu */ - static show(groups) { - this.activeMenu.menu = { groups }; + static show(e, groups) { + const x = e.x || e.clientX; + const y = e.y || e.clientY; + this.activeMenu.menu = { x, y, groups }; } static get activeMenu() { From 242fbfaaa78ec47ab4aef85163e37228c0d4192b Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 01:35:46 +0300 Subject: [PATCH 04/11] Match notifications with context menu style --- client/src/styles/partials/generic/notifications.scss | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/src/styles/partials/generic/notifications.scss b/client/src/styles/partials/generic/notifications.scss index 1722ac58..d6fd0e55 100644 --- a/client/src/styles/partials/generic/notifications.scss +++ b/client/src/styles/partials/generic/notifications.scss @@ -6,12 +6,12 @@ .bd-notificationContainer { position: relative; - background: #202225; + background: #18191c; width: 280px; height: 130px; top: 30px; border-radius: 5px; - box-shadow: 0 0 20px #202225; + box-shadow: 0 0 20px #18191c; .bd-notificationHeader { height: 10px; @@ -70,6 +70,10 @@ padding: 5px; justify-content: flex-end; + &:not(:empty) { + border-top: 1px solid hsla(0, 0%, 96.1%, .08) + } + .bd-notificationBtn { cursor: pointer; height: 10px; @@ -79,11 +83,10 @@ color: #aeaeae; padding: 5px 10px; border-radius: 3px; - background: rgba(0, 0, 0, .2); + background: transparent; margin-left: 5px; &:hover { - background: rgba(0, 0, 0, .3); color: #fff; } } From 25aecf82a6366303f976e4944d3858bffc4c3524 Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 01:42:14 +0300 Subject: [PATCH 05/11] Fix chevron position --- client/src/styles/partials/generic/contextmenu.scss | 9 +++++++-- client/src/styles/partials/generic/notifications.scss | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/client/src/styles/partials/generic/contextmenu.scss b/client/src/styles/partials/generic/contextmenu.scss index dc2aa280..68ba6e1b 100644 --- a/client/src/styles/partials/generic/contextmenu.scss +++ b/client/src/styles/partials/generic/contextmenu.scss @@ -52,10 +52,11 @@ .bd-cmSub { .bd-materialDesignIcon { - position: absolute; - right: 0; + position: relative; bottom: 2px; fill: hsla(0, 0%, 100%, .6); + display: flex; + justify-content: flex-end; svg { height: 20px; @@ -86,6 +87,10 @@ width: 100%; display: flex; + &.bd-cmSub { + padding: 6px 0 6px 9px; + } + .bd-cmHint { opacity: .8; color: hsla(0, 0%, 100%, .6); diff --git a/client/src/styles/partials/generic/notifications.scss b/client/src/styles/partials/generic/notifications.scss index d6fd0e55..73f8f0e5 100644 --- a/client/src/styles/partials/generic/notifications.scss +++ b/client/src/styles/partials/generic/notifications.scss @@ -71,7 +71,7 @@ justify-content: flex-end; &:not(:empty) { - border-top: 1px solid hsla(0, 0%, 96.1%, .08) + border-top: 1px solid hsla(0, 0%, 96.1%, .08); } .bd-notificationBtn { From 07fc98670c80425faefecd64c4ae1414db0a8cf1 Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 02:03:18 +0300 Subject: [PATCH 06/11] Hide cm when clicked outside --- client/src/ui/components/BdContextMenu.vue | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/client/src/ui/components/BdContextMenu.vue b/client/src/ui/components/BdContextMenu.vue index cd2c41cc..647d9c74 100644 --- a/client/src/ui/components/BdContextMenu.vue +++ b/client/src/ui/components/BdContextMenu.vue @@ -9,8 +9,8 @@ */ @@ -39,7 +39,17 @@ this.top = window.innerHeight - this.mouseY - height < 0 ? this.mouseY - height : this.mouseY; this.left = window.innerWidth - this.mouseX - 170 < 0 ? this.mouseX - 170 : this.mouseX; this.renderLeft = (this.left + 170 * 2) > window.innerWidth; + window.addEventListener('mouseup', this.clickHide); return { top: `${this.top}px`, left: `${this.left}px` }; + }, + hide() { + window.removeEventListener('mouseup', this.clickHide); + this.activeMenu.menu = null; + }, + clickHide(e) { + if (!this.$refs.root) return; + if (this.$refs.root.contains(e.target)) return; + this.hide(); } } } From bb37b89d359ca1622396deb6da1d519ae7b50ba6 Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 10:53:20 +0300 Subject: [PATCH 07/11] Discord contextmenu patching --- client/src/index.js | 4 +- .../styles/partials/generic/contextmenu.scss | 6 ++- client/src/ui/contextmenus.js | 51 +++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/client/src/index.js b/client/src/index.js index 3999c550..f7d6fb70 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -8,7 +8,7 @@ * LICENSE file in the root directory of this source tree. */ -import { DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, BdContextMenu } from 'ui'; +import { DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, BdContextMenu, DiscordContextMenu } from 'ui'; import BdCss from './styles/index.scss'; import { Events, CssEditor, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, Vendor, WebpackModules, Patcher, MonkeyPatch, ReactComponents, ReactHelpers, ReactAutoPatcher, DiscordApi, BdWebApi, Connectivity, Cache } from 'modules'; import { ClientLogger as Logger, ClientIPC, Utils } from 'common'; @@ -28,7 +28,7 @@ class BetterDiscord { Logger.log('main', 'BetterDiscord starting'); this._bd = { - DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, BdContextMenu, + DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, BdContextMenu, DiscordContextMenu, Events, CssEditor, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, diff --git a/client/src/styles/partials/generic/contextmenu.scss b/client/src/styles/partials/generic/contextmenu.scss index 68ba6e1b..782d968b 100644 --- a/client/src/styles/partials/generic/contextmenu.scss +++ b/client/src/styles/partials/generic/contextmenu.scss @@ -1,4 +1,5 @@ -.bd-cm { +.bd-cm, +.da-contextMenu { background: #18191c; box-shadow: 0 0 1px rgba(0, 0, 0, .82), 0 1px 4px rgba(0, 0, 0, .1); border-radius: 5px; @@ -7,7 +8,8 @@ z-index: 1005; user-select: none; - &.bd-cmRenderLeft { + &.bd-cmRenderLeft, + &.da-invertChildX { .bd-cm { margin-left: -170px; } diff --git a/client/src/ui/contextmenus.js b/client/src/ui/contextmenus.js index 6c0c1f81..700b9822 100644 --- a/client/src/ui/contextmenus.js +++ b/client/src/ui/contextmenus.js @@ -8,6 +8,10 @@ * LICENSE file in the root directory of this source tree. */ +import { ReactComponents, WebpackModules, MonkeyPatch } from 'modules'; +import { VueInjector, Toasts } from 'ui'; +import CMGroup from './components/contextmenu/Group.vue'; + export class BdContextMenu { /** @@ -26,3 +30,50 @@ export class BdContextMenu { } } + +export class DiscordContextMenu { + + static add(target, groups) { + if (!this.patched) this.patch(); + this.menus.push({ target, groups }); + } + + static get menus() { + return this._menus || (this._menus = []); + } + + static async patch() { + if (this.patched) return; + this.patched = true; + const self = this; + MonkeyPatch('BD:DiscordCMOCM', WebpackModules.getModuleByProps(['openContextMenu'])).instead('openContextMenu', (_, [e, fn], originalFn) => { + const overrideFn = function (...args) { + const res = fn(...args); + if (!res.hasOwnProperty('type')) return res; + if (!res.type.prototype || !res.type.prototype.render || res.type.prototype.render.__patched) return res; + MonkeyPatch('BD:DiscordCMRender', res.type.prototype).after('render', (c, a, r) => self.renderCm(c, a, r, res)); + res.type.prototype.render.__patched = true; + return res; + } + return originalFn(e, overrideFn); + }); + } + + static renderCm(component, args, retVal, res) { + if (!retVal.props || !res.props) return; + const { target } = res.props; + const { top, left } = retVal.props.style; + if (!target || !top || !left) return; + if (!retVal.props.children) return; + if (!(retVal.props.children instanceof Array)) retVal.props.children = [retVal.props.children]; + for (const menu of this.menus.filter(menu => menu.target(target))) { + retVal.props.children.push(VueInjector.createReactElement(CMGroup, { + top, + left, + closeMenu: () => WebpackModules.getModuleByProps(['closeContextMenu']).closeContextMenu(), + items: menu.groups + })); + } + } + +} From ed55e060aa150a925e5667a853f47faa943841a7 Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 10:55:18 +0300 Subject: [PATCH 08/11] Linter warnings --- client/src/styles/partials/generic/contextmenu.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/styles/partials/generic/contextmenu.scss b/client/src/styles/partials/generic/contextmenu.scss index 782d968b..6aa573fa 100644 --- a/client/src/styles/partials/generic/contextmenu.scss +++ b/client/src/styles/partials/generic/contextmenu.scss @@ -1,5 +1,5 @@ .bd-cm, -.da-contextMenu { +.da-contextMenu { // sass-lint:disable-line class-name-format background: #18191c; box-shadow: 0 0 1px rgba(0, 0, 0, .82), 0 1px 4px rgba(0, 0, 0, .1); border-radius: 5px; @@ -9,7 +9,7 @@ user-select: none; &.bd-cmRenderLeft, - &.da-invertChildX { + &.da-invertChildX { // sass-lint:disable-line class-name-format .bd-cm { margin-left: -170px; } From 9db6ddaf985b9cae6dff6607e92ed2073110095b Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 12:06:53 +0300 Subject: [PATCH 09/11] Make filter optional --- client/src/ui/contextmenus.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/ui/contextmenus.js b/client/src/ui/contextmenus.js index 700b9822..2f3c37dd 100644 --- a/client/src/ui/contextmenus.js +++ b/client/src/ui/contextmenus.js @@ -33,9 +33,9 @@ export class BdContextMenu { export class DiscordContextMenu { - static add(target, groups) { + static add(items, filter) { if (!this.patched) this.patch(); - this.menus.push({ target, groups }); + this.menus.push({ items, filter }); } static get menus() { @@ -66,12 +66,12 @@ export class DiscordContextMenu { if (!target || !top || !left) return; if (!retVal.props.children) return; if (!(retVal.props.children instanceof Array)) retVal.props.children = [retVal.props.children]; - for (const menu of this.menus.filter(menu => menu.target(target))) { + for (const menu of this.menus.filter(menu => { if (!menu.filter) return true; return menu.filter(target)})) { retVal.props.children.push(VueInjector.createReactElement(CMGroup, { top, left, closeMenu: () => WebpackModules.getModuleByProps(['closeContextMenu']).closeContextMenu(), - items: menu.groups + items: menu.items })); } } From b4fa9c2934ad6ea8cf8b1c5a23e10a08727aeede Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 12:07:32 +0300 Subject: [PATCH 10/11] add docs --- client/src/ui/contextmenus.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/src/ui/contextmenus.js b/client/src/ui/contextmenus.js index 2f3c37dd..018c8178 100644 --- a/client/src/ui/contextmenus.js +++ b/client/src/ui/contextmenus.js @@ -33,6 +33,11 @@ export class BdContextMenu { export class DiscordContextMenu { + /** + * add items to Discord context menu + * @param {any} items items to add + * @param {Function} [filter] filter function for target filtering + */ static add(items, filter) { if (!this.patched) this.patch(); this.menus.push({ items, filter }); From cd84f6329aab1eb6fac6ebf80ee33ff8e639f3f7 Mon Sep 17 00:00:00 2001 From: Jiiks Date: Wed, 22 Aug 2018 12:08:56 +0300 Subject: [PATCH 11/11] add a test contextmenu item --- client/src/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/src/index.js b/client/src/index.js index f7d6fb70..612902fc 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -108,6 +108,13 @@ class BetterDiscord { ]); } showDummyNotif(); + + DiscordContextMenu.add([ + { + text: 'Hello', + onClick: () => { Toasts.info('Hello!'); } + } + ]); } catch (err) { Logger.err('main', ['FAILED TO LOAD!', err]); }