diff --git a/client/src/modules/content.js b/client/src/modules/content.js
index 2200c30a..fdc6c463 100644
--- a/client/src/modules/content.js
+++ b/client/src/modules/content.js
@@ -91,9 +91,9 @@ export default class Content {
config: this.settings.strip().settings,
data: this.data
});
- this.settings.setSaved();
+ this.settings.setSaved();
} catch (err) {
- Logger.err(this.name, ['Failed to save configuration', err]);
+ Logger.err(this.name, ['Failed to save configuration', err]);
throw err;
}
}
diff --git a/client/src/modules/database.js b/client/src/modules/database.js
index 9b6e475d..1405b4aa 100644
--- a/client/src/modules/database.js
+++ b/client/src/modules/database.js
@@ -16,6 +16,12 @@ export default class {
return true;
}
+ /**
+ * Inserts or updates data in the database.
+ * @param {Object} args The record to find
+ * @param {Object} data The new record
+ * @return {Promise}
+ */
static async insertOrUpdate(args, data) {
try {
return ClientIPC.send('bd-dba', { action: 'update', args, data });
@@ -24,6 +30,11 @@ export default class {
}
}
+ /**
+ * Finds data in the database.
+ * @param {Object} args The record to find
+ * @return {Promise}
+ */
static async find(args) {
try {
return ClientIPC.send('bd-dba', { action: 'find', args });
diff --git a/client/src/modules/discordapi.js b/client/src/modules/discordapi.js
index 661976e9..948a73da 100644
--- a/client/src/modules/discordapi.js
+++ b/client/src/modules/discordapi.js
@@ -402,7 +402,7 @@ export default class DiscordApi {
static get currentChannel() {
const channel = Modules.ChannelStore.getChannel(Modules.SelectedChannelStore.getChannelId());
- return channel.isPrivate ? new PrivateChannel(channel) : new GuildChannel(channel);
+ if (channel) return channel.isPrivate() ? new PrivateChannel(channel) : new GuildChannel(channel);
}
static get currentUser() {
@@ -415,5 +415,5 @@ export default class DiscordApi {
for (const id of friends) returnUsers.push(User.fromId(id));
return returnUsers;
}
-
+
}
diff --git a/client/src/modules/eventhook.js b/client/src/modules/eventhook.js
index 9ae647f4..d6ba83b4 100644
--- a/client/src/modules/eventhook.js
+++ b/client/src/modules/eventhook.js
@@ -1,5 +1,5 @@
/**
- * BetterDiscord WebpackModules Module
+ * BetterDiscord Event Hook
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
* All rights reserved.
* https://betterdiscord.net
@@ -8,14 +8,13 @@
* LICENSE file in the root directory of this source tree.
*/
-import EventListener from './eventlistener';
-import { Utils } from 'common';
-import Events from './events';
+import { Utils, ClientLogger as Logger } from 'common';
import { WebpackModules } from './webpackmodules';
+import Events from './events';
+import EventListener from './eventlistener';
import * as SocketStructs from '../structs/socketstructs';
-
/**
* Discord socket event hook
* @extends {EventListener}
@@ -23,7 +22,7 @@ import * as SocketStructs from '../structs/socketstructs';
export default class extends EventListener {
init() {
- console.log(SocketStructs);
+ Logger.log('EventHook', SocketStructs);
this.hook();
}
@@ -44,11 +43,11 @@ export default class extends EventListener {
orig.call(this, ...args);
self.wsc = this;
self.emit(...args);
- }
+ };
}
get eventsModule() {
- return WebpackModules.getModuleByPrototypes(['setMaxListeners', 'emit']);
+ return WebpackModules.getModuleByName('Events');
}
/**
@@ -66,8 +65,8 @@ export default class extends EventListener {
/**
* Emit callback
- * @param {any} e Event Action
- * @param {any} d Event Args
+ * @param {any} event Event
+ * @param {any} data Event data
*/
dispatch(e, d) {
Events.emit('raw-event', { type: e, data: d });
@@ -143,7 +142,7 @@ export default class extends EventListener {
LFG_LISTING_CREATE: 'LFG_LISTING_CREATE', // No groups here
LFG_LISTING_DELETE: 'LFG_LISTING_DELETE', // Thank you
BRAINTREE_POPUP_BRIDGE_CALLBACK: 'BRAINTREE_POPUP_BRIDGE_CALLBACK' // What
- }
+ };
}
}
diff --git a/client/src/modules/events.js b/client/src/modules/events.js
index c60f8ee3..7021d33e 100644
--- a/client/src/modules/events.js
+++ b/client/src/modules/events.js
@@ -12,14 +12,39 @@ import { EventEmitter } from 'events';
const emitter = new EventEmitter();
export default class {
- static on(eventName, callBack) {
- emitter.on(eventName, callBack);
+
+ /**
+ * Adds an event listener.
+ * @param {String} event The event to listen for
+ * @param {Function} callback The function to call when the event is emitted
+ */
+ static on(event, callback) {
+ emitter.on(event, callback);
}
- static off(eventName, callBack) {
- emitter.removeListener(eventName, callBack);
+ /**
+ * Adds an event listener that is only called once.
+ * @param {String} event The event to listen for
+ * @param {Function} callback The function to call when the event is emitted
+ */
+ static once(event, callback) {
+ emitter.once(event, callback);
}
+ /**
+ * Removes an event listener.
+ * @param {String} event The event to remove
+ * @param {Function} callback The listener to remove
+ */
+ static off(event, callback) {
+ emitter.removeListener(event, callback);
+ }
+
+ /**
+ * Emits an event
+ * @param {String} event The event to emit
+ * @param {Any} ...data Data to pass to the event listeners
+ */
static emit(...args) {
emitter.emit(...args);
}
diff --git a/client/src/modules/eventswrapper.js b/client/src/modules/eventswrapper.js
index 49a654cd..8196e561 100644
--- a/client/src/modules/eventswrapper.js
+++ b/client/src/modules/eventswrapper.js
@@ -11,7 +11,8 @@
const eventemitters = new WeakMap();
export default class EventsWrapper {
- constructor(eventemitter) {
+
+ constructor(eventemitter, bind) {
eventemitters.set(this, eventemitter);
}
@@ -19,26 +20,33 @@ export default class EventsWrapper {
return this._eventSubs || (this._eventSubs = []);
}
+ get on() { return this.subscribe }
subscribe(event, callback) {
if (this.eventSubs.find(e => e.event === event && e.callback === callback)) return;
- this.eventSubs.push({
- event,
- callback
- });
- eventemitters.get(this).on(event, callback);
+ const boundCallback = () => callback.apply(this.bind, arguments);
+ this.eventSubs.push({ event, callback, boundCallback });
+ eventemitters.get(this).on(event, boundCallback);
}
+ once(event, callback) {
+ if (this.eventSubs.find(e => e.event === event && e.callback === callback)) return;
+ const boundCallback = () => this.off(event, callback) && callback.apply(this.bind, arguments);
+ this.eventSubs.push({ event, callback, boundCallback });
+ eventemitters.get(this).on(event, boundCallback);
+ }
+
+ get off() { return this.unsubscribe }
unsubscribe(event, callback) {
for (let index of this.eventSubs) {
- if (this.eventSubs[index].event !== event || (callback && this.eventSubs[index].callback === callback)) return;
- eventemitters.get(this).off(event, this.eventSubs[index].callback);
+ if (this.eventSubs[index].event !== event || (callback && this.eventSubs[index].callback === callback)) continue;
+ eventemitters.get(this).off(event, this.eventSubs[index].boundCallback);
this.eventSubs.splice(index, 1);
}
}
unsubscribeAll() {
for (let event of this.eventSubs) {
- eventemitters.get(this).off(event.event, event.callback);
+ eventemitters.get(this).off(event.event, event.boundCallback);
}
this.eventSubs.splice(0, this.eventSubs.length);
}
diff --git a/client/src/modules/module.js b/client/src/modules/module.js
index c786e366..c358662d 100644
--- a/client/src/modules/module.js
+++ b/client/src/modules/module.js
@@ -5,20 +5,19 @@
* https://github.com/JsSucks - 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.
-*/
-
-/*
-Base Module that every non-static module should extend
+ * LICENSE file in the root directory of this source tree.
*/
+/**
+ * Base Module that every non-static module should extend
+ */
export default class Module {
constructor(args) {
this.__ = {
state: args || {},
args
- }
+ };
this.setState = this.setState.bind(this);
this.initialize();
}
@@ -38,7 +37,6 @@ export default class Module {
set args(t) { }
get args() { return this.__.args; }
-
set state(state) { return this.__.state = state; }
get state() { return this.__.state; }
diff --git a/client/src/modules/modulemanager.js b/client/src/modules/modulemanager.js
index c1f69d51..99d9324c 100644
--- a/client/src/modules/modulemanager.js
+++ b/client/src/modules/modulemanager.js
@@ -18,6 +18,9 @@ import Updater from './updater';
*/
export default class {
+ /**
+ * An array of modules.
+ */
static get modules() {
return this._modules ? this._modules : (this._modules = [
new ProfileBadges(),
@@ -28,6 +31,10 @@ export default class {
]);
}
+ /**
+ * Initializes all modules.
+ * @return {Promise}
+ */
static async initModules() {
for (let module of this.modules) {
try {
diff --git a/client/src/modules/plugin.js b/client/src/modules/plugin.js
index 7b786eff..dcf26bef 100644
--- a/client/src/modules/plugin.js
+++ b/client/src/modules/plugin.js
@@ -15,12 +15,8 @@ export default class Plugin extends Content {
get type() { return 'plugin' }
- // Don't use - these will eventually be removed!
- get pluginPath() { return this.contentPath }
- get pluginConfig() { return this.config }
-
get start() { return this.enable }
- get stop() { return this.disable }
+ get stop() { return this.disable }
unload() {
PluginManager.unloadPlugin(this);
diff --git a/client/src/modules/pluginapi.js b/client/src/modules/pluginapi.js
index 3bb93be8..670a407c 100644
--- a/client/src/modules/pluginapi.js
+++ b/client/src/modules/pluginapi.js
@@ -1,5 +1,5 @@
/**
- * BetterDiscord Plugin Api
+ * BetterDiscord Plugin API
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
* All rights reserved.
* https://betterdiscord.net
@@ -8,7 +8,7 @@
* LICENSE file in the root directory of this source tree.
*/
-import { Utils, ClientLogger as Logger, ClientIPC } from 'common';
+import { Utils, ClientLogger as Logger, ClientIPC, AsyncEventEmitter } from 'common';
import Settings from './settings';
import ExtModuleManager from './extmodulemanager';
import PluginManager from './pluginmanager';
@@ -24,27 +24,20 @@ import { MonkeyPatch } from './patcher';
export default class PluginApi {
- constructor(pluginInfo) {
+ constructor(pluginInfo, pluginPath) {
this.pluginInfo = pluginInfo;
+ this.pluginPath = pluginPath;
+
this.Events = new EventsWrapper(Events);
+ Utils.defineSoftGetter(this.Events, 'bind', () => this.plugin);
+
this._menuItems = undefined;
this._injectedStyles = undefined;
this._modalStack = undefined;
}
- get Discord() {
- return DiscordApi;
- }
- get ReactComponents() {
- return ReactComponents;
- }
- get Reflection() {
- return Reflection;
- }
- get MonkeyPatch() {
- return module => MonkeyPatch(this.pluginInfo.id, module);
- }
+
get plugin() {
- return PluginManager.getPluginById(this.pluginInfo.id || this.pluginInfo.name.toLowerCase().replace(/[^a-zA-Z0-9-]/g, '-').replace(/--/g, '-'));
+ return PluginManager.getPluginByPath(this.pluginPath);
}
async bridge(plugin_id) {
@@ -61,15 +54,18 @@ export default class PluginApi {
get Api() { return this }
+ get AsyncEventEmitter() { return AsyncEventEmitter }
+ get EventsWrapper() { return EventsWrapper }
+
/**
* Logger
*/
- loggerLog(...message) { Logger.log(this.pluginInfo.name, message) }
- loggerErr(...message) { Logger.err(this.pluginInfo.name, message) }
- loggerWarn(...message) { Logger.warn(this.pluginInfo.name, message) }
- loggerInfo(...message) { Logger.info(this.pluginInfo.name, message) }
- loggerDbg(...message) { Logger.dbg(this.pluginInfo.name, message) }
+ loggerLog(...message) { Logger.log(this.plugin.name, message) }
+ loggerErr(...message) { Logger.err(this.plugin.name, message) }
+ loggerWarn(...message) { Logger.warn(this.plugin.name, message) }
+ loggerInfo(...message) { Logger.info(this.plugin.name, message) }
+ loggerDbg(...message) { Logger.dbg(this.plugin.name, message) }
get Logger() {
return {
log: this.loggerLog.bind(this),
@@ -381,6 +377,24 @@ export default class PluginApi {
});
}
+ /**
+ * DiscordApi
+ */
+
+ get Discord() {
+ return DiscordApi;
+ }
+
+ get ReactComponents() {
+ return ReactComponents;
+ }
+ get Reflection() {
+ return Reflection;
+ }
+ get MonkeyPatch() {
+ return module => MonkeyPatch(this.plugin.id, module);
+ }
+
}
// Stop plugins from modifying the plugin API for all plugins
diff --git a/client/src/modules/pluginmanager.js b/client/src/modules/pluginmanager.js
index 198d06e1..9275eda2 100644
--- a/client/src/modules/pluginmanager.js
+++ b/client/src/modules/pluginmanager.js
@@ -76,12 +76,12 @@ export default class extends ContentManager {
static async loadPlugin(paths, configs, info, main, dependencies, permissions) {
if (permissions && permissions.length > 0) {
for (let perm of permissions) {
- console.log(`Permission: ${Permissions.permissionText(perm).HEADER} - ${Permissions.permissionText(perm).BODY}`);
+ Logger.log(this.moduleName, `Permission: ${Permissions.permissionText(perm).HEADER} - ${Permissions.permissionText(perm).BODY}`);
}
try {
const allowed = await Modals.permissions(`${info.name} wants to:`, info.name, permissions).promise;
} catch (err) {
- return null;
+ return;
}
}
@@ -98,7 +98,7 @@ export default class extends ContentManager {
}
}
- const plugin = window.require(paths.mainPath)(Plugin, new PluginApi(info), Vendor, deps);
+ const plugin = window.require(paths.mainPath)(Plugin, new PluginApi(info, paths.contentPath), Vendor, deps);
if (!(plugin.prototype instanceof Plugin))
throw {message: `Plugin ${info.name} did not return a class that extends Plugin.`};
diff --git a/client/src/modules/settings.js b/client/src/modules/settings.js
index de4f4a0b..f382ec0d 100644
--- a/client/src/modules/settings.js
+++ b/client/src/modules/settings.js
@@ -8,22 +8,23 @@
* LICENSE file in the root directory of this source tree.
*/
-import defaultSettings from '../data/user.settings.default';
-import Globals from './globals';
-import CssEditor from './csseditor';
-import Events from './events';
import { Utils, FileUtils, ClientLogger as Logger } from 'common';
import { SettingsSet, SettingUpdatedEvent } from 'structs';
import path from 'path';
+import Globals from './globals';
+import CssEditor from './csseditor';
+import Events from './events';
+import defaultSettings from '../data/user.settings.default';
export default new class Settings {
+
constructor() {
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}`);
+ 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);
});
@@ -37,6 +38,9 @@ export default new class Settings {
});
}
+ /**
+ * Loads BetterDiscord's settings.
+ */
async loadSettings() {
try {
await FileUtils.ensureDirectory(this.dataPath);
@@ -48,7 +52,7 @@ export default new class Settings {
for (let set of this.settings) {
const newSet = settings.find(s => s.id === set.id);
if (!newSet) continue;
- set.merge(newSet);
+ await set.merge(newSet);
set.setSaved();
}
@@ -61,6 +65,9 @@ export default new class Settings {
}
}
+ /**
+ * Saves BetterDiscord's settings including CSS editor data.
+ */
async saveSettings() {
try {
await FileUtils.ensureDirectory(this.dataPath);
@@ -72,15 +79,10 @@ export default new class Settings {
css: CssEditor.css,
css_editor_files: CssEditor.files,
scss_error: CssEditor.error,
- css_editor_bounds: {
- width: CssEditor.editor_bounds.width,
- height: CssEditor.editor_bounds.height,
- x: CssEditor.editor_bounds.x,
- y: CssEditor.editor_bounds.y
- }
+ css_editor_bounds: CssEditor.editor_bounds
});
- for (let set of this.getSettings) {
+ for (let set of this.settings) {
set.setSaved();
}
} catch (err) {
@@ -90,8 +92,13 @@ export default new class Settings {
}
}
+ /**
+ * Finds one of BetterDiscord's settings sets.
+ * @param {String} set_id The ID of the set to find
+ * @return {SettingsSet}
+ */
getSet(set_id) {
- return this.getSettings.find(s => s.id === set_id);
+ return this.settings.find(s => s.id === set_id);
}
get core() { return this.getSet('core') }
@@ -100,39 +107,46 @@ export default new class Settings {
get css() { return this.getSet('css') }
get security() { return this.getSet('security') }
+ /**
+ * Finds a category in one of BetterDiscord's settings sets.
+ * @param {String} set_id The ID of the set to look in
+ * @param {String} category_id The ID of the category to find
+ * @return {SettingsCategory}
+ */
getCategory(set_id, category_id) {
const set = this.getSet(set_id);
return set ? set.getCategory(category_id) : undefined;
}
+ /**
+ * Finds a setting in one of BetterDiscord's settings sets.
+ * @param {String} set_id The ID of the set to look in
+ * @param {String} category_id The ID of the category to look in
+ * @param {String} setting_id The ID of the setting to find
+ * @return {Setting}
+ */
getSetting(set_id, category_id, setting_id) {
const set = this.getSet(set_id);
return set ? set.getSetting(category_id, setting_id) : undefined;
}
+ /**
+ * Returns a setting's value in one of BetterDiscord's settings sets.
+ * @param {String} set_id The ID of the set to look in
+ * @param {String} category_id The ID of the category to look in
+ * @param {String} setting_id The ID of the setting to find
+ * @return {Any}
+ */
get(set_id, category_id, setting_id) {
const set = this.getSet(set_id);
return set ? set.get(category_id, setting_id) : undefined;
}
- async mergeSettings(set_id, newSettings) {
- const set = this.getSet(set_id);
- if (!set) return;
-
- return await set.merge(newSettings);
- }
-
- setSetting(set_id, category_id, setting_id, value) {
- const setting = this.getSetting(set_id, category_id, setting_id);
- if (!setting) throw {message: `Tried to set ${set_id}/${category_id}/${setting_id}, which doesn't exist`};
- setting.value = value;
- }
-
- get getSettings() {
- return this.settings;
- }
-
+ /**
+ * The path to store user data in.
+ */
get dataPath() {
return Globals.getPath('data');
}
+
}
diff --git a/client/src/modules/socketproxy.js b/client/src/modules/socketproxy.js
index 745d32a8..e3657343 100644
--- a/client/src/modules/socketproxy.js
+++ b/client/src/modules/socketproxy.js
@@ -8,6 +8,7 @@
* LICENSE file in the root directory of this source tree.
*/
+import { ClientLogger as Logger } from 'common';
import EventListener from './eventlistener';
export default class SocketProxy extends EventListener {
@@ -19,7 +20,7 @@ export default class SocketProxy extends EventListener {
get eventBindings() {
return [
- { id: 'socket-created', 'callback': this.socketCreated }
+ { id: 'socket-created', callback: this.socketCreated }
];
}
@@ -29,11 +30,11 @@ export default class SocketProxy extends EventListener {
socketCreated(socket) {
this.activeSocket = socket;
- // socket.addEventListener('message', this.onMessage);
+ // socket.addEventListener('message', this.onMessage);
}
onMessage(e) {
- console.info(e);
+ Logger.info('SocketProxy', e);
}
}
diff --git a/client/src/modules/theme.js b/client/src/modules/theme.js
index b02ba3ed..bbabc810 100644
--- a/client/src/modules/theme.js
+++ b/client/src/modules/theme.js
@@ -31,10 +31,6 @@ export default class Theme extends Content {
get type() { return 'theme' }
get css() { return this.data.css }
- // Don't use - these will eventually be removed!
- get themePath() { return this.contentPath }
- get themeConfig() { return this.config }
-
/**
* Called when settings are updated.
* This can be overridden by other content types.
@@ -63,7 +59,7 @@ export default class Theme extends Content {
* @return {Promise}
*/
async compile() {
- console.log('Compiling CSS');
+ Logger.log(this.name, 'Compiling CSS');
if (this.info.type === 'sass') {
const config = await ThemeManager.getConfigAsSCSS(this.settings);
@@ -76,7 +72,7 @@ export default class Theme extends Content {
Logger.log(this.name, ['Finished compiling theme', new class Info {
get SCSS_variables() { console.log(config); }
get Compiled_SCSS() { console.log(result.css.toString()); }
- get Result() { console.log(result); }
+ get Result() { console.log(result); }
}]);
return {
@@ -121,6 +117,7 @@ export default class Theme extends Content {
*/
set files(files) {
this.data.files = files;
+
if (Settings.get('css', 'default', 'watch-files'))
this.watchfiles = files;
}
diff --git a/client/src/modules/thememanager.js b/client/src/modules/thememanager.js
index 81276c5d..dfaf7a37 100644
--- a/client/src/modules/thememanager.js
+++ b/client/src/modules/thememanager.js
@@ -74,6 +74,11 @@ export default class ThemeManager extends ContentManager {
return theme instanceof Theme;
}
+ /**
+ * Returns a representation of a settings set's values in SCSS.
+ * @param {SettingsSet} settingsset The set to convert to SCSS
+ * @return {Promise}
+ */
static async getConfigAsSCSS(settingsset) {
const variables = [];
@@ -87,6 +92,11 @@ export default class ThemeManager extends ContentManager {
return variables.join('\n');
}
+ /**
+ * Returns a representation of a settings set's values as an SCSS map.
+ * @param {SettingsSet} settingsset The set to convert to an SCSS map
+ * @return {Promise}
+ */
static async getConfigAsSCSSMap(settingsset) {
const variables = [];
@@ -100,6 +110,11 @@ export default class ThemeManager extends ContentManager {
return '(' + variables.join(', ') + ')';
}
+ /**
+ * Returns a setting's name and value as a string that can be included in SCSS.
+ * @param {Setting} setting The setting to convert to SCSS
+ * @return {Promise}
+ */
static async parseSetting(setting) {
const { type, id, value } = setting;
const name = id.replace(/[^a-zA-Z0-9-]/g, '-').replace(/--/g, '-');
@@ -108,6 +123,11 @@ export default class ThemeManager extends ContentManager {
if (scss) return [name, scss];
}
+ /**
+ * Escapes a string so it can be included in SCSS.
+ * @param {String} value The string to escape
+ * @return {String}
+ */
static toSCSSString(value) {
if (typeof value !== 'string' && value.toString) value = value.toString();
return `'${typeof value === 'string' ? value.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') : ''}'`;
diff --git a/client/src/modules/updater.js b/client/src/modules/updater.js
index 08efbc8c..36ec548d 100644
--- a/client/src/modules/updater.js
+++ b/client/src/modules/updater.js
@@ -22,6 +22,9 @@ export default class {
this.checkForUpdates = this.checkForUpdates.bind(this);
}
+ /**
+ * The interval to wait before checking for updates.
+ */
get interval() {
return 60 * 1000 * 30;
}
@@ -30,34 +33,51 @@ export default class {
this.updateInterval = setInterval(this.checkForUpdates, this.interval);
}
+ /**
+ * Installs an update.
+ * TODO
+ */
update() {
- // TODO
this.updatesAvailable = false;
Events.emit('update-check-end');
}
+ /**
+ * Checks for updates.
+ * @return {Promise}
+ */
checkForUpdates() {
- if (this.updatesAvailable) return;
- Events.emit('update-check-start');
- Logger.info('Updater', 'Checking for updates');
- $.ajax({
- type: 'GET',
- url: 'https://rawgit.com/JsSucks/BetterDiscordApp/master/package.json',
- cache: false,
- success: e => {
- try {
- Events.emit('update-check-end');
- Logger.info('Updater',
- `Latest Version: ${e.version} - Current Version: ${Globals.version}`);
- if (e.version !== Globals.version) {
- this.updatesAvailable = true;
- Events.emit('updates-available');
+ return new Promise((resolve, reject) => {
+ if (this.updatesAvailable) return resolve(true);
+ Events.emit('update-check-start');
+ Logger.info('Updater', 'Checking for updates');
+
+ $.ajax({
+ type: 'GET',
+ url: 'https://rawgit.com/JsSucks/BetterDiscordApp/master/package.json',
+ cache: false,
+ success: e => {
+ try {
+ Events.emit('update-check-end');
+ Logger.info('Updater', `Latest Version: ${e.version} - Current Version: ${Globals.getObject('version')}`);
+
+ if (e.version !== Globals.getObject('version')) {
+ this.updatesAvailable = true;
+ Events.emit('updates-available');
+ resolve(true);
+ }
+
+ resolve(false);
+ } catch (err) {
+ Events.emit('update-check-fail', err);
+ reject(err);
}
- } catch (err) {
+ },
+ fail: err => {
Events.emit('update-check-fail', err);
+ reject(err);
}
- },
- fail: e => Events.emit('update-check-fail', e)
+ });
});
}
diff --git a/client/src/modules/vendor.js b/client/src/modules/vendor.js
index 7ce84fa1..29d5a804 100644
--- a/client/src/modules/vendor.js
+++ b/client/src/modules/vendor.js
@@ -16,22 +16,21 @@ export { jQuery as $ };
export default class {
- static get jQuery() {
- return jQuery;
- }
+ /**
+ * jQuery
+ */
+ static get jQuery() { return jQuery }
+ static get $() { return this.jQuery }
- static get $() {
- return this.jQuery;
- }
-
- static get lodash() {
- return lodash;
- }
-
- static get _() {
- return this.lodash;
- }
+ /**
+ * Lodash
+ */
+ static get lodash() { return lodash }
+ static get _() { return this.lodash }
+ /**
+ * Moment
+ */
static get moment() {
return WebpackModules.getModuleByName('Moment');
}
diff --git a/client/src/modules/webpackmodules.js b/client/src/modules/webpackmodules.js
index 82906d67..71b03ecd 100644
--- a/client/src/modules/webpackmodules.js
+++ b/client/src/modules/webpackmodules.js
@@ -51,6 +51,8 @@ const KnownModules = {
React: Filters.byProperties(['createElement', 'cloneElement']),
ReactDOM: Filters.byProperties(['render', 'findDOMNode']),
+ Events: Filters.byPrototypeFields(['setMaxListeners', 'emit']),
+
/* Guild Info, Stores, and Utilities */
GuildStore: Filters.byProperties(['getGuild']),
SortedGuildStore: Filters.byProperties(['getSortedGuilds']),
@@ -207,37 +209,37 @@ const KnownModules = {
export class WebpackModules {
- /**
- * Finds a module using a filter function.
- * @param {Function} filter A function to use to filter modules
- * @param {Boolean} first Whether to return only the first matching module
- * @return {Any}
- */
- static getModule(filter, first = true) {
- const modules = this.getAllModules();
- const rm = [];
- for (let index in modules) {
- if (!modules.hasOwnProperty(index)) continue;
- const module = modules[index];
- const { exports } = module;
- let foundModule = null;
+ /**
+ * Finds a module using a filter function.
+ * @param {Function} filter A function to use to filter modules
+ * @param {Boolean} first Whether to return only the first matching module
+ * @return {Any}
+ */
+ static getModule(filter, first = true) {
+ const modules = this.getAllModules();
+ const rm = [];
+ for (let index in modules) {
+ if (!modules.hasOwnProperty(index)) continue;
+ const module = modules[index];
+ const { exports } = module;
+ let foundModule = null;
- if (!exports) continue;
- if (exports.__esModule && exports.default && filter(exports.default)) foundModule = exports.default;
- if (filter(exports)) foundModule = exports;
- if (!foundModule) continue;
- if (first) return foundModule;
- rm.push(foundModule);
- }
- return first || rm.length == 0 ? undefined : rm;
- }
+ if (!exports) continue;
+ if (exports.__esModule && exports.default && filter(exports.default)) foundModule = exports.default;
+ if (filter(exports)) foundModule = exports;
+ if (!foundModule) continue;
+ if (first) return foundModule;
+ rm.push(foundModule);
+ }
+ return first || rm.length == 0 ? undefined : rm;
+ }
- /**
- * Finds a module by it's name.
- * @param {String} name The name of the module
- * @param {Function} fallback A function to use to filter modules if not finding a known module
- * @return {Any}
- */
+ /**
+ * Finds a module by it's name.
+ * @param {String} name The name of the module
+ * @param {Function} fallback A function to use to filter modules if not finding a known module
+ * @return {Any}
+ */
static getModuleByName(name, fallback) {
if (Cache.hasOwnProperty(name)) return Cache[name];
if (KnownModules.hasOwnProperty(name)) fallback = KnownModules[name];
@@ -246,48 +248,48 @@ export class WebpackModules {
return module ? Cache[name] = module : undefined;
}
- /**
- * Finds a module by it's display name.
- * @param {String} name The display name of the module
- * @return {Any}
- */
+ /**
+ * Finds a module by it's display name.
+ * @param {String} name The display name of the module
+ * @return {Any}
+ */
static getModuleByDisplayName(name) {
return this.getModule(Filters.byDisplayName(name), true);
}
- /**
- * Finds a module using it's code.
- * @param {RegEx} regex A regular expression to use to filter modules
- * @param {Boolean} first Whether to return the only the first matching module
- * @return {Any}
- */
+ /**
+ * Finds a module using it's code.
+ * @param {RegEx} regex A regular expression to use to filter modules
+ * @param {Boolean} first Whether to return the only the first matching module
+ * @return {Any}
+ */
static getModuleByRegex(regex, first = true) {
return this.getModule(Filters.byCode(regex), first);
}
- /**
- * Finds a module using properties on it's prototype.
- * @param {Array} props Properties to use to filter modules
- * @param {Boolean} first Whether to return only the first matching module
- * @return {Any}
- */
+ /**
+ * Finds a module using properties on it's prototype.
+ * @param {Array} props Properties to use to filter modules
+ * @param {Boolean} first Whether to return only the first matching module
+ * @return {Any}
+ */
static getModuleByPrototypes(prototypes, first = true) {
return this.getModule(Filters.byPrototypeFields(prototypes), first);
}
- /**
- * Finds a module using it's own properties.
- * @param {Array} props Properties to use to filter modules
- * @param {Boolean} first Whether to return only the first matching module
- * @return {Any}
- */
+ /**
+ * Finds a module using it's own properties.
+ * @param {Array} props Properties to use to filter modules
+ * @param {Boolean} first Whether to return only the first matching module
+ * @return {Any}
+ */
static getModuleByProps(props, first = true) {
return this.getModule(Filters.byProperties(props), first);
}
- /**
- * Discord's __webpack_require__ function.
- */
+ /**
+ * Discord's __webpack_require__ function.
+ */
static get require() {
if (this._require) return this._require;
const id = 'bd-webpackmodules';
diff --git a/client/src/structs/events/error.js b/client/src/structs/events/error.js
index 04f8bf8f..4268c753 100644
--- a/client/src/structs/events/error.js
+++ b/client/src/structs/events/error.js
@@ -17,22 +17,37 @@ export default class ErrorEvent extends Event {
this.showStack = false; // For error modal
}
+ /**
+ * The module the error occured in.
+ */
get module() {
return this.args.module;
}
+ /**
+ * A message describing the error.
+ */
get message() {
return this.args.message;
}
+ /**
+ * The original error object.
+ */
get err() {
return this.args.err;
}
+ /**
+ * A trace showing which functions were called when the error occured.
+ */
get stackTrace() {
return this.err.stack;
}
+ /**
+ * The type of event.
+ */
get __eventType() {
return 'error';
}
diff --git a/client/src/structs/events/event.js b/client/src/structs/events/event.js
index 1159910e..cb26edf6 100644
--- a/client/src/structs/events/event.js
+++ b/client/src/structs/events/event.js
@@ -17,14 +17,23 @@ export default class Event {
};
}
+ /**
+ * An object containing information about the event.
+ */
get event() {
return this.__eventInfo;
}
+ /**
+ * The first argument that was passed to the constructor, which contains information about the event.
+ */
get args() {
return this.event.args[0];
}
- get __eventType() { return null; }
+ /**
+ * The type of event.
+ */
+ get __eventType() { return undefined; }
}
diff --git a/client/src/structs/events/settingsupdated.js b/client/src/structs/events/settingsupdated.js
index 99470ea7..8c8965ad 100644
--- a/client/src/structs/events/settingsupdated.js
+++ b/client/src/structs/events/settingsupdated.js
@@ -12,10 +12,16 @@ import Event from './event';
export default class SettingsUpdatedEvent extends Event {
+ /**
+ * An array of SettingUpdated events.
+ */
get updatedSettings() {
return this.args.updatedSettings;
}
+ /**
+ * The type of event.
+ */
get __eventType() {
return 'settings-updated';
}
diff --git a/client/src/structs/events/settingupdated.js b/client/src/structs/events/settingupdated.js
index 9edbb19f..c69e81db 100644
--- a/client/src/structs/events/settingupdated.js
+++ b/client/src/structs/events/settingupdated.js
@@ -12,38 +12,65 @@ import Event from './event';
export default class SettingUpdatedEvent extends Event {
+ /**
+ * The set containing the setting that was updated.
+ */
get set() {
return this.args.set;
}
+ /**
+ * The ID of the set containing the setting that was updated.
+ */
get set_id() {
- return this.args.set.id;
+ return this.set.id;
}
+ /**
+ * The category containing the setting that was updated.
+ */
get category() {
return this.args.category;
}
+ /**
+ * The ID of the category containing the setting that was updated.
+ */
get category_id() {
- return this.args.category.id;
+ return this.category.id;
}
+ /**
+ * The setting that was updated.
+ */
get setting() {
return this.args.setting;
}
+ /**
+ * The ID of the setting that was updated.
+ */
get setting_id() {
- return this.args.setting.id;
+ return this.setting.id;
}
+ /**
+ * The setting's new value.
+ */
get value() {
return this.args.value;
}
+ /**
+ * The setting's old value.
+ */
get old_value() {
return this.args.old_value;
}
+ /**
+ * The type of event.
+ */
get __eventType() {
return 'setting-updated';
}
diff --git a/client/src/structs/settings/multiplechoiceoption.js b/client/src/structs/settings/multiplechoiceoption.js
index 70f8abbe..3e583c91 100644
--- a/client/src/structs/settings/multiplechoiceoption.js
+++ b/client/src/structs/settings/multiplechoiceoption.js
@@ -14,22 +14,29 @@ export default class MultipleChoiceOption {
constructor(args) {
this.args = args.args || args;
+
+ Object.freeze(this);
}
+ /**
+ * This option's ID.
+ */
get id() {
return this.args.id || this.value;
}
+ /**
+ * A string describing this option.
+ */
get text() {
return this.args.text;
}
+ /**
+ * The value to return when this option is active.
+ */
get value() {
return this.args.value;
}
- clone() {
- return new MultipleChoiceOption(Utils.deepclone(this.args));
- }
-
}
diff --git a/client/src/structs/settings/settingsscheme.js b/client/src/structs/settings/settingsscheme.js
index 8f3d945a..2d4a14f6 100644
--- a/client/src/structs/settings/settingsscheme.js
+++ b/client/src/structs/settings/settingsscheme.js
@@ -24,26 +24,46 @@ export default class SettingsScheme {
Object.freeze(this);
}
+ /**
+ * The scheme's ID.
+ */
get id() {
return this.args.id;
}
+ /**
+ * The URL of the scheme's icon. This should be a base64 encoded data URI.
+ */
get icon_url() {
return this.args.icon_url;
}
+ /**
+ * The scheme's name.
+ */
get name() {
return this.args.name;
}
+ /**
+ * A string to be displayed under the scheme.
+ */
get hint() {
return this.args.hint;
}
+ /**
+ * An array of stripped settings categories this scheme manages.
+ */
get settings() {
return this.args.settings || [];
}
+ /**
+ * Checks if this scheme's values are currently applied to a set.
+ * @param {SettingsSet} set The set to check
+ * @return {Boolean}
+ */
isActive(set) {
for (let schemeCategory of this.settings) {
const category = set.categories.find(c => c.category === schemeCategory.category);
@@ -66,12 +86,13 @@ export default class SettingsScheme {
return true;
}
+ /**
+ * Applies this scheme's values to a set.
+ * @param {SettingsSet} set The set to merge this scheme's values into
+ * @return {Promise}
+ */
applyTo(set) {
- return set.merge({ settings: this.settings });
- }
-
- clone() {
- return new SettingsScheme(Utils.deepclone(this.args));
+ return set.merge(this);
}
}
diff --git a/client/src/structs/settings/settingsset.js b/client/src/structs/settings/settingsset.js
index 5b324a69..bb87fac9 100644
--- a/client/src/structs/settings/settingsset.js
+++ b/client/src/structs/settings/settingsset.js
@@ -446,7 +446,7 @@ export default class SettingsSet {
text: this.text,
headertext: this.headertext,
settings: this.categories.map(category => category.clone()),
- schemes: this.schemes.map(scheme => scheme.clone())
+ schemes: this.schemes
}, ...merge);
}
diff --git a/client/src/styles/partials/badges.scss b/client/src/styles/partials/badges.scss
index fee77077..fb5656df 100644
--- a/client/src/styles/partials/badges.scss
+++ b/client/src/styles/partials/badges.scss
@@ -25,16 +25,21 @@
width: 16px;
filter: brightness(10);
cursor: pointer;
- .theme-light [class*="topSectionNormal-"] & {
- background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FscXVlXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjAwMCAyMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAyMDAwIDIwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGZpbGw9IiMzRTgyRTUiIGQ9Ik0xNDAyLjIsNjMxLjdjLTkuNy0zNTMuNC0yODYuMi00OTYtNjQyLjYtNDk2SDY4LjR2NzE0LjFsNDQyLDM5OFY0OTAuN2gyNTdjMjc0LjUsMCwyNzQuNSwzNDQuOSwwLDM0NC45SDU5Ny42djMyOS41aDE2OS44YzI3NC41LDAsMjc0LjUsMzQ0LjgsMCwzNDQuOGgtNjk5djM1NC45aDY5MS4yYzM1Ni4zLDAsNjMyLjgtMTQyLjYsNjQyLjYtNDk2YzAtMTYyLjYtNDQuNS0yODQuMS0xMjIuOS0zNjguNkMxMzU3LjcsOTE1LjgsMTQwMi4yLDc5NC4zLDE0MDIuMiw2MzEuN3oiLz48cGF0aCBmaWxsPSIjYmJiYmJiIiBkPSJNMTI2Mi41LDEzNS4yTDEyNjIuNSwxMzUuMmwtNzYuOCwwYzI2LjYsMTMuMyw1MS43LDI4LjEsNzUsNDQuM2M3MC43LDQ5LjEsMTI2LjEsMTExLjUsMTY0LjYsMTg1LjNjMzkuOSw3Ni42LDYxLjUsMTY1LjYsNjQuMywyNjQuNmwwLDEuMnYxLjJjMCwxNDEuMSwwLDU5Ni4xLDAsNzM3LjF2MS4ybDAsMS4yYy0yLjcsOTktMjQuMywxODgtNjQuMywyNjQuNmMtMzguNSw3My44LTkzLjgsMTM2LjItMTY0LjYsMTg1LjNjLTIyLjYsMTUuNy00Ni45LDMwLjEtNzIuNiw0My4xaDcyLjVjMzQ2LjIsMS45LDY3MS0xNzEuMiw2NzEtNTY3LjlWNzE2LjdDMTkzMy41LDMxMi4yLDE2MDguNywxMzUuMiwxMjYyLjUsMTM1LjJ6Ii8+PC9nPjwvc3ZnPg==');
- filter: none;
- }
+}
+
+.theme-light [class*="topSectionNormal-"] .bd-profile-badge-developer,
+.theme-light [class*="topSectionNormal-"] .bd-profile-badge-contributor,
+.theme-light .bd-message-badge-developer,
+.theme-light .bd-message-badge-contributor {
+ background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FscXVlXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjAwMCAyMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAyMDAwIDIwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGZpbGw9IiMzRTgyRTUiIGQ9Ik0xNDAyLjIsNjMxLjdjLTkuNy0zNTMuNC0yODYuMi00OTYtNjQyLjYtNDk2SDY4LjR2NzE0LjFsNDQyLDM5OFY0OTAuN2gyNTdjMjc0LjUsMCwyNzQuNSwzNDQuOSwwLDM0NC45SDU5Ny42djMyOS41aDE2OS44YzI3NC41LDAsMjc0LjUsMzQ0LjgsMCwzNDQuOGgtNjk5djM1NC45aDY5MS4yYzM1Ni4zLDAsNjMyLjgtMTQyLjYsNjQyLjYtNDk2YzAtMTYyLjYtNDQuNS0yODQuMS0xMjIuOS0zNjguNkMxMzU3LjcsOTE1LjgsMTQwMi4yLDc5NC4zLDE0MDIuMiw2MzEuN3oiLz48cGF0aCBmaWxsPSIjYmJiYmJiIiBkPSJNMTI2Mi41LDEzNS4yTDEyNjIuNSwxMzUuMmwtNzYuOCwwYzI2LjYsMTMuMyw1MS43LDI4LjEsNzUsNDQuM2M3MC43LDQ5LjEsMTI2LjEsMTExLjUsMTY0LjYsMTg1LjNjMzkuOSw3Ni42LDYxLjUsMTY1LjYsNjQuMywyNjQuNmwwLDEuMnYxLjJjMCwxNDEuMSwwLDU5Ni4xLDAsNzM3LjF2MS4ybDAsMS4yYy0yLjcsOTktMjQuMywxODgtNjQuMywyNjQuNmMtMzguNSw3My44LTkzLjgsMTM2LjItMTY0LjYsMTg1LjNjLTIyLjYsMTUuNy00Ni45LDMwLjEtNzIuNiw0My4xaDcyLjVjMzQ2LjIsMS45LDY3MS0xNzEuMiw2NzEtNTY3LjlWNzE2LjdDMTkzMy41LDMxMi4yLDE2MDguNywxMzUuMiwxMjYyLjUsMTM1LjJ6Ii8+PC9nPjwvc3ZnPg==');
+ filter: none;
}
.bd-message-badges-wrap {
display: inline-block;
margin-left: 6px;
height: 11px;
+
.bd-message-badge-developer,
.bd-message-badge-contributor {
width: 12px;
diff --git a/client/src/styles/partials/bdsettings/tooltips.scss b/client/src/styles/partials/bdsettings/tooltips.scss
index 0ec5e69f..3eaa12d4 100644
--- a/client/src/styles/partials/bdsettings/tooltips.scss
+++ b/client/src/styles/partials/bdsettings/tooltips.scss
@@ -20,17 +20,17 @@ bd-tooltips {
word-wrap: break-word;
z-index: 9001;
margin-bottom: 10px;
-}
-.bd-tooltip:after {
- border: 5px solid transparent;
- content: " ";
- height: 0;
- pointer-events: none;
- width: 0;
- border-top-color: #000;
- left: 50%;
- margin-left: -5px;
- position: absolute;
- top: 100%;
+ .bd-tooltip-arrow {
+ border: 5px solid transparent;
+ content: " ";
+ height: 0;
+ pointer-events: none;
+ width: 0;
+ border-top-color: #000;
+ left: 50%;
+ margin-left: -5px;
+ position: absolute;
+ top: 100%;
+ }
}
diff --git a/client/src/ui/automanip.js b/client/src/ui/automanip.js
index 7331f66c..88f19651 100644
--- a/client/src/ui/automanip.js
+++ b/client/src/ui/automanip.js
@@ -8,37 +8,14 @@
* LICENSE file in the root directory of this source tree.
*/
-import { Events, WebpackModules, EventListener, ReactComponents, Renderer } from 'modules';
+import { Events, WebpackModules, EventListener, DiscordApi, ReactComponents, Renderer } from 'modules';
+import { ClientLogger as Logger } from 'common';
import Reflection from './reflection';
import DOM from './dom';
import VueInjector from './vueinjector';
import EditedTimeStamp from './components/common/EditedTimestamp.vue';
import Autocomplete from './components/common/Autocomplete.vue';
-class TempApi {
- static get currentGuildId() {
- try {
- return WebpackModules.getModuleByName('SelectedGuildStore').getGuildId();
- } catch (err) {
- return 0;
- }
- }
- static get currentChannelId() {
- try {
- return WebpackModules.getModuleByName('SelectedChannelStore').getChannelId();
- } catch (err) {
- return 0;
- }
- }
- static get currentUserId() {
- try {
- return WebpackModules.getModuleByName('UserStore').getCurrentUser().id;
- } catch (err) {
- return 0;
- }
- }
-}
-
export default class extends EventListener {
constructor(args) {
@@ -54,22 +31,19 @@ export default class extends EventListener {
}
get eventBindings() {
- return [{ id: 'gkh:keyup', callback: this.injectAutocomplete }];
- /*
return [
- { id: 'server-switch', callback: this.manipAll },
- { id: 'channel-switch', callback: this.manipAll },
- { id: 'discord:MESSAGE_CREATE', callback: this.markupInjector },
- { id: 'discord:MESSAGE_UPDATE', callback: this.markupInjector },
+ // { id: 'server-switch', callback: this.manipAll },
+ // { id: 'channel-switch', callback: this.manipAll },
+ // { id: 'discord:MESSAGE_CREATE', callback: this.markupInjector },
+ // { id: 'discord:MESSAGE_UPDATE', callback: this.markupInjector },
{ id: 'gkh:keyup', callback: this.injectAutocomplete }
];
- */
}
manipAll() {
try {
- this.appMount.setAttribute('guild-id', TempApi.currentGuildId);
- this.appMount.setAttribute('channel-id', TempApi.currentChannelId);
+ this.appMount.setAttribute('guild-id', DiscordApi.currentGuild.id);
+ this.appMount.setAttribute('channel-id', DiscordApi.currentChannel.id);
this.setIds();
this.makeMutable();
} catch (err) {
@@ -172,14 +146,14 @@ export default class extends EventListener {
const userTest = Reflection(msgGroup).prop('user');
if (!userTest) return;
msgGroup.setAttribute('data-author-id', userTest.id);
- if (userTest.id === TempApi.currentUserId) msgGroup.setAttribute('data-currentuser', true);
+ if (userTest.id === DiscordApi.currentUserId) msgGroup.setAttribute('data-currentuser', true);
return;
}
msg.setAttribute('data-message-id', messageid);
const msgGroup = msg.closest('.message-group');
if (!msgGroup) return;
msgGroup.setAttribute('data-author-id', authorid);
- if (authorid === TempApi.currentUserId) msgGroup.setAttribute('data-currentuser', true);
+ if (authorid === DiscordApi.currentUser.id) msgGroup.setAttribute('data-currentuser', true);
}
setUserId(user) {
@@ -187,7 +161,7 @@ export default class extends EventListener {
const userid = Reflection(user).prop('user.id');
if (!userid) return;
user.setAttribute('data-user-id', userid);
- const currentUser = userid === TempApi.currentUserId;
+ const currentUser = userid === DiscordApi.currentUser.id;
if (currentUser) user.setAttribute('data-currentuser', true);
Events.emit('ui:useridset', user);
}
@@ -218,4 +192,5 @@ export default class extends EventListener {
template: ''
});
}
+
}
diff --git a/client/src/ui/bdmenu.js b/client/src/ui/bdmenu.js
index c8f6cd60..0eb3a019 100644
--- a/client/src/ui/bdmenu.js
+++ b/client/src/ui/bdmenu.js
@@ -28,7 +28,14 @@ const BdMenuItems = new class {
this.add({category: 'External', contentid: 'themes', text: 'Themes'});
}
+ /**
+ * Adds an item to the menu.
+ * @param {Object} item The item to add to the menu
+ * @return {Object}
+ */
add(item) {
+ if (this.items.includes(item)) return item;
+
item.id = items++;
item.contentid = item.contentid || (items++ + '');
item.active = false;
@@ -39,6 +46,13 @@ const BdMenuItems = new class {
return item;
}
+ /**
+ * Adds a settings set to the menu.
+ * @param {String} category The category to display this item under
+ * @param {SettingsSet} set The settings set to display when this item is active
+ * @param {String} text The text to display in the menu (optional)
+ * @return {Object} The item that was added
+ */
addSettingsSet(category, set, text) {
return this.add({
category, set,
@@ -46,12 +60,23 @@ const BdMenuItems = new class {
});
}
+ /**
+ * Adds a Vue component to the menu.
+ * @param {String} category The category to display this item under
+ * @param {String} text The text to display in the menu
+ * @param {Object} component The Vue component to display when this item is active
+ * @return {Object} The item that was added
+ */
addVueComponent(category, text, component) {
return this.add({
category, text, component
});
}
+ /**
+ * Removes an item from the menu.
+ * @param {Object} item The item to remove from the menu
+ */
remove(item) {
Utils.removeFromArray(this.items, item);
}
diff --git a/client/src/ui/bdui.js b/client/src/ui/bdui.js
index 009a2905..458fcf12 100644
--- a/client/src/ui/bdui.js
+++ b/client/src/ui/bdui.js
@@ -8,48 +8,21 @@
* LICENSE file in the root directory of this source tree.
*/
+import { Events, WebpackModules, DiscordApi } from 'modules';
+import { Utils } from 'common';
+import { remote } from 'electron';
import DOM from './dom';
import Vue from './vue';
-import { BdSettingsWrapper } from './components';
-import BdModals from './components/bd/BdModals.vue';
-import { Events, WebpackModules } from 'modules';
-import { Utils } from 'common';
import AutoManip from './automanip';
-import { remote } from 'electron';
-
-class TempApi {
- static get currentGuild() {
- try {
- const currentGuildId = WebpackModules.getModuleByName('SelectedGuildStore').getGuildId();
- return WebpackModules.getModuleByName('GuildStore').getGuild(currentGuildId);
- } catch (err) {
- return null;
- }
- }
- static get currentChannel() {
- try {
- const currentChannelId = WebpackModules.getModuleByName('SelectedChannelStore').getChannelId();
- return WebpackModules.getModuleByName('ChannelStore').getChannel(currentChannelId);
- } catch (err) {
- return 0;
- }
- }
- static get currentUserId() {
- try {
- return WebpackModules.getModuleByName('UserStore').getCurrentUser().id;
- } catch (err) {
- return 0;
- }
- }
-}
+import { BdSettingsWrapper, BdModals } from './components';
export default class {
static initUiEvents() {
this.pathCache = {
isDm: null,
- server: TempApi.currentGuild,
- channel: TempApi.currentChannel
+ server: DiscordApi.currentGuild,
+ channel: DiscordApi.currentChannel
};
window.addEventListener('keyup', e => Events.emit('gkh:keyup', e));
this.autoManip = new AutoManip();
@@ -67,9 +40,9 @@ export default class {
if (!remote.BrowserWindow.getFocusedWindow()) return;
clearInterval(ehookInterval);
remote.BrowserWindow.getFocusedWindow().webContents.on('did-navigate-in-page', (e, url, isMainFrame) => {
- const { currentGuild, currentChannel } = TempApi;
+ const { currentGuild, currentChannel } = DiscordApi;
if (!this.pathCache.server) {
- Events.emit('server-switch', { 'server': currentGuild, 'channel': currentChannel });
+ Events.emit('server-switch', { server: currentGuild, channel: currentChannel });
this.pathCache.server = currentGuild;
this.pathCache.channel = currentChannel;
return;
@@ -84,7 +57,7 @@ export default class {
currentGuild.id &&
this.pathCache.server &&
this.pathCache.server.id !== currentGuild.id) {
- Events.emit('server-switch', { 'server': currentGuild, 'channel': currentChannel });
+ Events.emit('server-switch', { server: currentGuild, channel: currentChannel });
this.pathCache.server = currentGuild;
this.pathCache.channel = currentChannel;
return;
@@ -110,19 +83,19 @@ export default class {
DOM.createElement('div', null, 'bd-modals').appendTo(DOM.bdModals);
DOM.createElement('bd-tooltips').appendTo(DOM.bdBody);
- const modals = new Vue({
+ this.modals = new Vue({
el: '#bd-modals',
components: { BdModals },
- template: ''
+ template: ''
});
- const vueInstance = new Vue({
+ this.vueInstance = new Vue({
el: '#bd-settings',
components: { BdSettingsWrapper },
- template: ''
+ template: ''
});
- return vueInstance;
+ return this.vueInstance;
}
}
diff --git a/client/src/ui/components/bd/BdModals.vue b/client/src/ui/components/BdModals.vue
similarity index 92%
rename from client/src/ui/components/bd/BdModals.vue
rename to client/src/ui/components/BdModals.vue
index 60a85d32..78e04f3b 100644
--- a/client/src/ui/components/bd/BdModals.vue
+++ b/client/src/ui/components/BdModals.vue
@@ -19,13 +19,14 @@
+