From 0bbd7b506a9f674cd4a202817f428c993b66fbfd Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Wed, 7 Mar 2018 19:57:00 +0000 Subject: [PATCH 01/12] Add option to ignore content manager errors --- client/src/data/user.settings.default.json | 7 +++ client/src/index.js | 13 +++-- package-lock.json | 60 ++++++++++++++++++++++ 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/client/src/data/user.settings.default.json b/client/src/data/user.settings.default.json index fc35312f..fb847d6d 100644 --- a/client/src/data/user.settings.default.json +++ b/client/src/data/user.settings.default.json @@ -45,6 +45,13 @@ "hint": "BetterDiscord developer mode", "value": false, "disabled": true + }, + { + "id": "ignore-content-manager-errors", + "type": "bool", + "text": "Ignore content manager errors", + "hint": "Only when starting Discord. It gets annoying when you're reloading Discord often and have plugins that are meant to fail.", + "value": false } ] } diff --git a/client/src/index.js b/client/src/index.js index f37523b5..e6620fcc 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -29,7 +29,9 @@ class BetterDiscord { window.bdmodals = Modals; window.bdlogs = Logger; window.emotes = EmoteModule; + EmoteModule.observe(); + DOM.injectStyle(BdCss, 'bdmain'); Events.on('global-ready', this.globalReady.bind(this)); } @@ -42,20 +44,21 @@ class BetterDiscord { await ExtModuleManager.loadAllModules(true); await PluginManager.loadAllPlugins(true); await ThemeManager.loadAllThemes(true); - Modals.showContentManagerErrors(); + + if (!Settings.get('core', 'advanced', 'ignore-content-manager-errors')) + Modals.showContentManagerErrors(); + Events.emit('ready'); Events.emit('discord-ready'); } catch (err) { - console.log('FAILED TO LOAD!', err); + Logger.err('main', ['FAILED TO LOAD!', err]); } } globalReady() { BdUI.initUiEvents(); this.vueInstance = BdUI.injectUi(); - (async () => { - this.init(); - })(); + this.init(); } } diff --git a/package-lock.json b/package-lock.json index b6bca9da..75b7dd91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1323,6 +1323,15 @@ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, + "binary-search-tree": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/binary-search-tree/-/binary-search-tree-0.2.5.tgz", + "integrity": "sha1-fbs7IQ/coIJFDa0jNMMErzm9x4Q=", + "dev": true, + "requires": { + "underscore": "1.4.4" + } + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -5652,6 +5661,12 @@ "integrity": "sha1-YSKJv7PCIOGGpYEYYY1b6MG6sCE=", "dev": true }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -6293,6 +6308,15 @@ "type-check": "0.3.2" } }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "dev": true, + "requires": { + "immediate": "3.0.6" + } + }, "liftoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", @@ -6347,6 +6371,15 @@ "json5": "0.5.1" } }, + "localforage": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.6.0.tgz", + "integrity": "sha1-iwBZvus4dcSBJChsp/2/I9UrjJc=", + "dev": true, + "requires": { + "lie": "3.1.1" + } + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -6979,6 +7012,27 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "nedb": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/nedb/-/nedb-1.8.0.tgz", + "integrity": "sha1-DjUCzYLABNU1WkPJ5VV3vXvZHYg=", + "dev": true, + "requires": { + "async": "0.2.10", + "binary-search-tree": "0.2.5", + "localforage": "1.6.0", + "mkdirp": "0.5.1", + "underscore": "1.4.4" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, "neo-async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", @@ -10569,6 +10623,12 @@ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "dev": true + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", From 5e259f50f8a5853c1e781e6b62d641e9dcfe9f6e Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Wed, 7 Mar 2018 20:19:02 +0000 Subject: [PATCH 02/12] Refactor settings menu Adds support for dynamically adding items --- client/src/modules/settings.js | 40 +++++++++------- client/src/ui/bdmenu.js | 61 ++++++++++++++++++++++++ client/src/ui/bdui.js | 1 + client/src/ui/components/BdSettings.vue | 63 ++++++++++++++----------- client/src/ui/ui.js | 1 + common/modules/utils.js | 7 +++ 6 files changed, 129 insertions(+), 44 deletions(-) create mode 100644 client/src/ui/bdmenu.js diff --git a/client/src/modules/settings.js b/client/src/modules/settings.js index 49e0dc91..f03117bd 100644 --- a/client/src/modules/settings.js +++ b/client/src/modules/settings.js @@ -18,7 +18,23 @@ import path from 'path'; export default new class Settings { constructor() { - this.settings = []; + this.settings = defaultSettings.map(_set => { + const set = new SettingsSet(_set); + + set.on('setting-updated', event => { + const { category, setting, value, old_value } = event; + Logger.log('Settings', `${set.id}/${category.id}/${setting.id} was changed from ${old_value} to ${value}`); + Events.emit('setting-updated', event); + Events.emit(`setting-updated-${set.id}_${category.id}_${setting.id}`, event); + }); + + set.on('settings-updated', async (event) => { + await this.saveSettings(); + Events.emit('settings-updated', event); + }); + + return set; + }); } async loadSettings() { @@ -29,22 +45,12 @@ export default new class Settings { const user_config = await FileUtils.readJsonFromFile(settingsPath); const { settings, scss, css, css_editor_files, scss_error, css_editor_bounds } = user_config; - this.settings = defaultSettings.map(set => { - const newSet = new SettingsSet(set); - newSet.merge(settings.find(s => s.id === newSet.id)); - newSet.setSaved(); - newSet.on('setting-updated', event => { - const { category, setting, value, old_value } = event; - Logger.log('Settings', `${newSet.id}/${category.id}/${setting.id} was changed from ${old_value} to ${value}`); - Events.emit('setting-updated', event); - Events.emit(`setting-updated-${newSet.id}_${category.id}_${setting.id}`, event); - }); - newSet.on('settings-updated', async (event) => { - await this.saveSettings(); - Events.emit('settings-updated', event); - }); - return newSet; - }); + for (let set of this.settings) { + const newSet = settings.find(s => s.id === set.id); + if (!newSet) continue; + set.merge(newSet); + set.setSaved(); + } CssEditor.setState(scss, css, css_editor_files, scss_error); CssEditor.editor_bounds = css_editor_bounds || {}; diff --git a/client/src/ui/bdmenu.js b/client/src/ui/bdmenu.js new file mode 100644 index 00000000..c8f6cd60 --- /dev/null +++ b/client/src/ui/bdmenu.js @@ -0,0 +1,61 @@ +/** + * BetterDiscord Menu Module + * 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. +*/ + +import { Utils } from 'common'; + +let items = 0; + +const BdMenuItems = new class { + + constructor() { + window.bdmenu = this; + + this.items = []; + + this.addSettingsSet('Internal', 'core', 'Core'); + this.addSettingsSet('Internal', 'ui', 'UI'); + this.addSettingsSet('Internal', 'emotes', 'Emotes'); + + this.add({category: 'Internal', contentid: 'css', text: 'CSS Editor'}); + this.add({category: 'External', contentid: 'plugins', text: 'Plugins'}); + this.add({category: 'External', contentid: 'themes', text: 'Themes'}); + } + + add(item) { + item.id = items++; + item.contentid = item.contentid || (items++ + ''); + item.active = false; + item.hidden = item.hidden || false; + item._type = item._type || 'button'; + + this.items.push(item); + return item; + } + + addSettingsSet(category, set, text) { + return this.add({ + category, set, + text: text || set.text + }); + } + + addVueComponent(category, text, component) { + return this.add({ + category, text, component + }); + } + + remove(item) { + Utils.removeFromArray(this.items, item); + } + +}; + +export { BdMenuItems }; diff --git a/client/src/ui/bdui.js b/client/src/ui/bdui.js index 44341cc7..e25031ce 100644 --- a/client/src/ui/bdui.js +++ b/client/src/ui/bdui.js @@ -86,4 +86,5 @@ export default class { return vueInstance; } + } diff --git a/client/src/ui/components/BdSettings.vue b/client/src/ui/components/BdSettings.vue index da976a86..0fbff82d 100644 --- a/client/src/ui/components/BdSettings.vue +++ b/client/src/ui/components/BdSettings.vue @@ -16,7 +16,10 @@ ESC - +
v2.0.0a by Jiiks/JsSucks @@ -31,19 +34,21 @@
-
- - +
+ + + + -
-
- -
-
- -
-
- + + + + + + +
@@ -53,32 +58,22 @@ // Imports import { shell } from 'electron'; import { Settings } from 'modules'; + import { BdMenuItems } from 'ui'; import { SidebarView, Sidebar, SidebarItem, ContentColumn } from './sidebar'; import { SettingsWrapper, SettingsPanel, CssEditorView, PluginsView, ThemesView } from './bd'; import { SvgX, MiGithubCircle, MiWeb, MiClose, MiTwitterCircle } from './common'; - // Constants - const sidebarItems = [ - { text: 'Internal', _type: 'header' }, - { id: 0, contentid: "core", text: 'Core', active: false, _type: 'button' }, - { id: 1, contentid: "ui", text: 'UI', active: false, _type: 'button' }, - { id: 2, contentid: "emotes", text: 'Emotes', active: false, _type: 'button' }, - { id: 3, contentid: "css", text: 'CSS Editor', active: false, _type: 'button' }, - { text: 'External', _type: 'header' }, - { id: 4, contentid: "plugins", text: 'Plugins', active: false, _type: 'button' }, - { id: 5, contentid: "themes", text: 'Themes', active: false, _type: 'button' } - ]; - export default { data() { return { - sidebarItems, + BdMenuItems, activeIndex: -1, lastActiveIndex: -1, animating: false, first: true, Settings, - timeout: null + timeout: null, + SettingsWrapper } }, props: ['active', 'close'], @@ -87,6 +82,20 @@ SettingsWrapper, SettingsPanel, CssEditorView, PluginsView, ThemesView, MiGithubCircle, MiWeb, MiClose, MiTwitterCircle }, + computed: { + sidebarItems() { + return this.BdMenuItems.items; + }, + sidebar() { + const categories = {}; + for (let item of this.sidebarItems) { + if (item.hidden) continue; + const category = categories[item.category] || (categories[item.category] = []); + category.push(item); + } + return categories; + } + }, methods: { itemOnClick(id) { if (this.animating || id === this.activeIndex) return; diff --git a/client/src/ui/ui.js b/client/src/ui/ui.js index 4a24e0cb..7c3d8b7f 100644 --- a/client/src/ui/ui.js +++ b/client/src/ui/ui.js @@ -1,5 +1,6 @@ export { default as DOM } from './dom'; export { default as BdUI } from './bdui'; export { default as VueInjector } from './vueinjector'; +export * from './bdmenu'; export { default as Modals } from './modals'; export { default as ProfileBadges } from './profilebadges'; diff --git a/common/modules/utils.js b/common/modules/utils.js index 2f1e829a..d032b264 100644 --- a/common/modules/utils.js +++ b/common/modules/utils.js @@ -159,6 +159,13 @@ export class Utils { return object; } + + static removeFromArray(array, item) { + let index; + while ((index = array.indexOf(item)) > -1) + array.splice(index, 1); + return array; + } } export class FileUtils { From e78089a5092515b2d1f0f62cc3da22bb225080b3 Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Wed, 7 Mar 2018 20:32:04 +0000 Subject: [PATCH 03/12] Add menu items to the plugin API --- client/src/modules/pluginapi.js | 50 +++++++++++++++++++++++++++++++- tests/plugins/Example 4/index.js | 33 ++++++++++++++++++--- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/client/src/modules/pluginapi.js b/client/src/modules/pluginapi.js index dd07cf35..c9529c7c 100644 --- a/client/src/modules/pluginapi.js +++ b/client/src/modules/pluginapi.js @@ -16,7 +16,7 @@ import ThemeManager from './thememanager'; import Events from './events'; import WebpackModules from './webpackmodules'; import { SettingsSet, SettingsCategory, Setting, SettingsScheme } from 'structs'; -import { Modals, DOM } from 'ui'; +import { BdMenuItems, Modals, DOM } from 'ui'; import SettingsModal from '../ui/components/bd/modals/SettingsModal.vue'; class EventsWrapper { @@ -153,6 +153,54 @@ export default class PluginApi { }; } + /** + * BdMenu + */ + + get BdMenu() { + return { + BdMenuItems: this.BdMenuItems + }; + } + + /** + * BdMenuItems + */ + + get menuItems() { + return this._menuItems || (this._menuItems = []); + } + addMenuItem(item) { + return BdMenuItems.add(item); + } + addMenuSettingsSet(category, set, text) { + const item = BdMenuItems.addSettingsSet(category, set, text); + return this.menuItems.push(item); + } + addMenuVueComponent(category, text, component) { + const item = BdMenuItems.addVueComponent(category, text, component); + return this.menuItems.push(item); + } + removeMenuItem(item) { + BdMenuItems.remove(item); + Utils.removeFromArray(this.menuItems, item); + } + removeAllMenuItems() { + for (let item of this.menuItems) + BdMenuItems.remove(item); + } + get BdMenuItems() { + return Object.defineProperty({ + add: this.addMenuItem.bind(this), + addSettingsSet: this.addMenuSettingsSet.bind(this), + addVueComponent: this.addMenuVueComponent.bind(this), + remove: this.removeMenuItem.bind(this), + removeAll: this.removeAllMenuItems.bind(this) + }, 'items', { + get: () => this.menuItems + }); + } + /** * CssUtils */ diff --git a/tests/plugins/Example 4/index.js b/tests/plugins/Example 4/index.js index a42c60ed..35b6968d 100644 --- a/tests/plugins/Example 4/index.js +++ b/tests/plugins/Example 4/index.js @@ -1,4 +1,4 @@ -module.exports = (Plugin, { Logger, Settings }) => class extends Plugin { +module.exports = (Plugin, { Logger, Settings, BdMenu: { BdMenuItems }, Api }) => class extends Plugin { async onstart() { // Some array event examples const arraySetting = this.settings.getSetting('default', 'array-1'); @@ -7,8 +7,10 @@ module.exports = (Plugin, { Logger, Settings }) => class extends Plugin { arraySetting.on('item-updated', event => Logger.log('Item', event.item, 'of the array setting was updated', event)); arraySetting.on('item-removed', event => Logger.log('Item', event.item, 'removed from the array setting')); - // Create a new settings set and show it in a modal - const set = Settings.createSet({}); + // Create a new settings set and add it to the menu + const set = Settings.createSet({ + text: this.name + }); const category = await set.addCategory({ id: 'default' }); const setting = await category.addSetting({ @@ -33,6 +35,29 @@ module.exports = (Plugin, { Logger, Settings }) => class extends Plugin { set.setSaved(); }) - set.showModal('Custom settings panel'); + const setting2 = await category.addSetting({ + id: 'setting-2', + type: 'text', + text: 'Enter some text', + fullwidth: true + }); + + setting2.on('setting-updated', event => Logger.log('Setting 2 was changed to', event.value)); + + this.menuItem = BdMenuItems.addSettingsSet('Plugins', set, 'Plugin 4'); + + this.menuItem2 = BdMenuItems.addVueComponent('Plugins', 'Also Plugin 4', { + template: ` +

Test

+
`, + props: ['SettingsWrapper'], + data() { return { + Api, plugin: Api.plugin + }; } + }); + } + + onstop() { + BdMenuItems.removeAll(); } }; From 0229482be847ba4b09164bc36970a0f940cf10fe Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Thu, 8 Mar 2018 02:38:12 +0000 Subject: [PATCH 04/12] Add keybind setting --- client/src/structs/settings/setting.js | 24 +++--- client/src/structs/settings/types/keybind.js | 28 +++++++ .../{colourpicker.scss => colourpickers.scss} | 0 .../styles/partials/generic/forms/index.scss | 5 +- .../partials/generic/forms/keybinds.scss | 52 +++++++++++++ .../styles/partials/generic/forms/main.scss | 7 +- .../src/ui/components/bd/setting/Keybind.vue | 78 +++++++++++++++++++ .../src/ui/components/bd/setting/Setting.vue | 27 ++++--- package-lock.json | 6 ++ package.json | 1 + tests/plugins/Example 4/config.json | 7 ++ tests/plugins/Example 4/index.js | 8 ++ 12 files changed, 215 insertions(+), 28 deletions(-) create mode 100644 client/src/structs/settings/types/keybind.js rename client/src/styles/partials/generic/forms/{colourpicker.scss => colourpickers.scss} (100%) create mode 100644 client/src/styles/partials/generic/forms/keybinds.scss create mode 100644 client/src/ui/components/bd/setting/Keybind.vue diff --git a/client/src/structs/settings/setting.js b/client/src/structs/settings/setting.js index 2927b342..7785e03b 100644 --- a/client/src/structs/settings/setting.js +++ b/client/src/structs/settings/setting.js @@ -17,27 +17,29 @@ import DropdownSetting from './types/dropdown'; import RadioSetting from './types/radio'; import SliderSetting from './types/slider'; import ColourSetting from './types/colour'; +import KeybindSetting from './types/keybind'; import FileSetting from './types/file'; import ArraySetting from './types/array'; import CustomSetting from './types/custom'; export default class Setting { - constructor(args) { + constructor(args, ...merge) { args = args.args || args; if (args.type === 'color') args.type = 'colour'; - if (args.type === 'bool') return new BoolSetting(args); - else if (args.type === 'text') return new StringSetting(args); - else if (args.type === 'number') return new NumberSetting(args); - else if (args.type === 'dropdown') return new DropdownSetting(args); - else if (args.type === 'radio') return new RadioSetting(args); - else if (args.type === 'slider') return new SliderSetting(args); - else if (args.type === 'colour') return new ColourSetting(args); - else if (args.type === 'file') return new FileSetting(args); - else if (args.type === 'array') return new ArraySetting(args); - else if (args.type === 'custom') return new CustomSetting(args); + if (args.type === 'bool') return new BoolSetting(args, ...merge); + else if (args.type === 'text') return new StringSetting(args, ...merge); + else if (args.type === 'number') return new NumberSetting(args, ...merge); + else if (args.type === 'dropdown') return new DropdownSetting(args, ...merge); + else if (args.type === 'radio') return new RadioSetting(args, ...merge); + else if (args.type === 'slider') return new SliderSetting(args, ...merge); + else if (args.type === 'colour') return new ColourSetting(args, ...merge); + else if (args.type === 'keybind') return new KeybindSetting(args, ...merge); + else if (args.type === 'file') return new FileSetting(args, ...merge); + else if (args.type === 'array') return new ArraySetting(args, ...merge); + else if (args.type === 'custom') return new CustomSetting(args, ...merge); else throw {message: `Setting type ${args.type} unknown`}; } diff --git a/client/src/structs/settings/types/keybind.js b/client/src/structs/settings/types/keybind.js new file mode 100644 index 00000000..efbe3f90 --- /dev/null +++ b/client/src/structs/settings/types/keybind.js @@ -0,0 +1,28 @@ +/** + * BetterDiscord Keybind Setting Struct + * 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. + */ + +import Setting from './basesetting'; +import Combokeys from 'combokeys'; + +export default class KeybindSetting extends Setting { + + constructor(args, ...merge) { + super(args, ...merge); + + this.combokeys = new Combokeys(document); + this.combokeys.bind(this.value, event => this.emit('keybind-activated', event)); + } + + setValueHook() { + this.combokeys.reset(); + this.combokeys.bind(this.value, event => this.emit('keybind-activated', event)); + } + +} diff --git a/client/src/styles/partials/generic/forms/colourpicker.scss b/client/src/styles/partials/generic/forms/colourpickers.scss similarity index 100% rename from client/src/styles/partials/generic/forms/colourpicker.scss rename to client/src/styles/partials/generic/forms/colourpickers.scss diff --git a/client/src/styles/partials/generic/forms/index.scss b/client/src/styles/partials/generic/forms/index.scss index e1154656..e6cef62f 100644 --- a/client/src/styles/partials/generic/forms/index.scss +++ b/client/src/styles/partials/generic/forms/index.scss @@ -1,9 +1,10 @@ @import './main.scss'; +@import './switches.scss'; @import './text.scss'; @import './files.scss'; @import './dropdowns.scss'; @import './radios.scss'; @import './sliders.scss'; -@import './switches.scss'; +@import './colourpickers.scss'; +@import './keybinds.scss'; @import './arrays.scss'; -@import './colourpicker.scss'; diff --git a/client/src/styles/partials/generic/forms/keybinds.scss b/client/src/styles/partials/generic/forms/keybinds.scss new file mode 100644 index 00000000..49bea00c --- /dev/null +++ b/client/src/styles/partials/generic/forms/keybinds.scss @@ -0,0 +1,52 @@ +.bd-keybind { + padding: 10px; + display: flex; + // width: 180px; + margin-top: 10px; + background-color: rgba(0,0,0,.1); + border: 1px solid rgba(0,0,0,.3); + transition: border .15s ease; + border-radius: 3px; + box-sizing: border-box; + min-height: 40px; + + .bd-keybind-selected { + flex: 1 1 auto; + color: #f6f6f7; + font-size: 14px; + } + + &.bd-keybind-unset { + .bd-keybind-selected { + color: hsla(240,6%,97%,.3); + font-weight: 600; + } + } + + .bd-button { + border-radius: 2px; + margin: -4px -4px -4px 10px; + padding: 2px 20px; + transition: background-color .2s ease-in-out, color .2s ease-in-out; + font-size: 14px; + font-weight: 500; + flex: 0 0 auto; + cursor: pointer; + } + + &.bd-active { + border-color: $colerr; + animation: bd-keybind-pulse 1s infinite; + + .bd-button { + color: $colerr; + background-color: rgba($colerr, .3); + } + } +} + +@keyframes bd-keybind-pulse { + 0% { box-shadow: 0 0 6px rgba(240,71,71,.3) } + 50% { box-shadow: 0 0 10px rgba(240,71,71,.6) } + 100% { box-shadow: 0 0 6px rgba(240,71,71,.3) } +} diff --git a/client/src/styles/partials/generic/forms/main.scss b/client/src/styles/partials/generic/forms/main.scss index 9ac4e8ce..470e6379 100644 --- a/client/src/styles/partials/generic/forms/main.scss +++ b/client/src/styles/partials/generic/forms/main.scss @@ -1,12 +1,13 @@ +.bd-setting-switch, .bd-form-textinput, .bd-form-textarea, -.bd-form-fileinput, +.bd-form-numberinput, .bd-form-dropdown, .bd-form-radio, -.bd-form-numberinput, .bd-form-slider, .bd-form-colourpicker, -.bd-setting-switch, +.bd-form-keybind, +.bd-form-fileinput, .bd-form-settingsarray { .bd-title { display: flex; diff --git a/client/src/ui/components/bd/setting/Keybind.vue b/client/src/ui/components/bd/setting/Keybind.vue new file mode 100644 index 00000000..e59b3b35 --- /dev/null +++ b/client/src/ui/components/bd/setting/Keybind.vue @@ -0,0 +1,78 @@ +/** + * BetterDiscord Setting Keybind 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/bd/setting/Setting.vue b/client/src/ui/components/bd/setting/Setting.vue index 4132f44d..147060c0 100644 --- a/client/src/ui/components/bd/setting/Setting.vue +++ b/client/src/ui/components/bd/setting/Setting.vue @@ -10,17 +10,18 @@ @@ -33,10 +34,11 @@ import StringSetting from './String.vue'; import MultilineTextSetting from './Multiline.vue'; import SliderSetting from './Slider.vue'; + import ColourSetting from './Colour.vue'; + import KeybindSetting from './Keybind.vue'; import FileSetting from './File.vue'; import ArraySetting from './Array.vue'; import CustomSetting from './Custom.vue'; - import ColourSetting from './Colour.vue'; export default { props: [ @@ -50,10 +52,11 @@ StringSetting, MultilineTextSetting, SliderSetting, + ColourSetting, + KeybindSetting, FileSetting, ArraySetting, - CustomSetting, - ColourSetting + CustomSetting }, computed: { changed() { diff --git a/package-lock.json b/package-lock.json index 75b7dd91..15334a32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2032,6 +2032,12 @@ "delayed-stream": "1.0.0" } }, + "combokeys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/combokeys/-/combokeys-3.0.0.tgz", + "integrity": "sha1-lVxZo5Wa9A0mhGq2/DxoJEjnVy4=", + "dev": true + }, "commander": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", diff --git a/package.json b/package.json index 55e0f401..d31ba623 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "codemirror": "^5.23.0", + "combokeys": "^3.0.0", "css-loader": "^0.28.9", "electron": "^1.6.15", "electron-rebuild": "^1.7.3", diff --git a/tests/plugins/Example 4/config.json b/tests/plugins/Example 4/config.json index c38da573..1c06afe2 100644 --- a/tests/plugins/Example 4/config.json +++ b/tests/plugins/Example 4/config.json @@ -77,6 +77,13 @@ ] } ] + }, + { + "id": "keybind-1", + "type": "keybind", + "value": "mod+.", + "text": "Test Keybind Setting 1", + "hint": "Test Keybind Setting Hint 1" } ] } diff --git a/tests/plugins/Example 4/index.js b/tests/plugins/Example 4/index.js index 35b6968d..38cdb3dc 100644 --- a/tests/plugins/Example 4/index.js +++ b/tests/plugins/Example 4/index.js @@ -7,6 +7,14 @@ module.exports = (Plugin, { Logger, Settings, BdMenu: { BdMenuItems }, Api }) => arraySetting.on('item-updated', event => Logger.log('Item', event.item, 'of the array setting was updated', event)); arraySetting.on('item-removed', event => Logger.log('Item', event.item, 'removed from the array setting')); + // Keybind setting examples + const keybindSetting = this.settings.getSetting('default', 'keybind-1'); + Logger.log('Keybind setting', keybindSetting); + keybindSetting.on('keybind-activated', event => { + Logger.log('Keybind pressed', event); + Modals.basic('Example Plugin 4', 'Test keybind activated.'); + }); + // Create a new settings set and add it to the menu const set = Settings.createSet({ text: this.name From dfd0208394583f368591af5fdfbbeb2fb03aa9a2 Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Thu, 8 Mar 2018 02:41:47 +0000 Subject: [PATCH 05/12] Fix theme loading --- client/src/modules/thememanager.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/modules/thememanager.js b/client/src/modules/thememanager.js index 9c404121..8c4bf97d 100644 --- a/client/src/modules/thememanager.js +++ b/client/src/modules/thememanager.js @@ -45,8 +45,11 @@ export default class ThemeManager extends ContentManager { mainPath: paths.mainPath } }); - if (!instance.css) instance.recompile(); - else if (instance.enabled) instance.enable(); + if (instance.enabled) { + instance.userConfig.enabled = false; + instance.enable(); + if (!instance.css) instance.recompile(); + } return instance; } catch (err) { throw err; From 68c0133381a43a44e8910387000531bd8e90a82c Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Thu, 8 Mar 2018 02:42:06 +0000 Subject: [PATCH 06/12] Make menu keybind customisable --- client/src/data/user.settings.default.json | 6 ++++++ client/src/ui/components/BdSettingsWrapper.vue | 14 ++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/client/src/data/user.settings.default.json b/client/src/data/user.settings.default.json index fb847d6d..be4d3676 100644 --- a/client/src/data/user.settings.default.json +++ b/client/src/data/user.settings.default.json @@ -30,6 +30,12 @@ "hint": "Disconnect from voice server when Discord closes", "value": false, "disabled": true + }, + { + "id": "menu-keybind", + "type": "keybind", + "text": "Menu keybind", + "value": "mod+b" } ] }, diff --git a/client/src/ui/components/BdSettingsWrapper.vue b/client/src/ui/components/BdSettingsWrapper.vue index facb0333..49b273ec 100644 --- a/client/src/ui/components/BdSettingsWrapper.vue +++ b/client/src/ui/components/BdSettingsWrapper.vue @@ -20,7 +20,8 @@