diff --git a/client/src/index.js b/client/src/index.js
index 59015317..47d0519d 100644
--- a/client/src/index.js
+++ b/client/src/index.js
@@ -16,6 +16,7 @@ import { ClientLogger as Logger } from 'common';
class BetterDiscord {
constructor() {
+ window.css = CssEditor;
window.pm = PluginManager;
window.events = Events;
window.wpm = WebpackModules;
diff --git a/client/src/modules/contentmanager.js b/client/src/modules/contentmanager.js
index d9ceca08..d409e76e 100644
--- a/client/src/modules/contentmanager.js
+++ b/client/src/modules/contentmanager.js
@@ -12,9 +12,14 @@ import Globals from './globals';
import { FileUtils, ClientLogger as Logger } from 'common';
import path from 'path';
import { Events } from 'modules';
+import { Error } from 'structs';
export default class {
+ static get errors() {
+ return this._errors || (this._errors = []);
+ }
+
static get localContent() {
return this._localContent ? this._localContent : (this._localContent = []);
}
@@ -32,16 +37,26 @@ export default class {
try {
await this.preloadContent(dir);
} catch (err) {
- //We don't want every plugin/theme to fail loading when one does
- Events.emit('bd-error', {
- header: `${this.moduleName} - Failed to load plugin: ${dir}`,
- text: err.message,
- type: 'err'
- });
+ this.errors.push(new Error({
+ module: this.moduleName,
+ message: `Failed to load ${dir}`,
+ err
+ }));
+
Logger.err(this.moduleName, err);
}
}
+ if (this.errors.length) {
+ Events.emit('bd-error', {
+ header: `${this.moduleName} - one or more ${this.contentType}(s) failed to load`,
+ module: this.moduleName,
+ type: 'err',
+ content: this.errors
+ });
+ }
+ this._errors = [];
+
return this.localContent;
} catch (err) {
throw err;
diff --git a/client/src/modules/pluginmanager.js b/client/src/modules/pluginmanager.js
index dfcd70a5..4e7a7cd9 100644
--- a/client/src/modules/pluginmanager.js
+++ b/client/src/modules/pluginmanager.js
@@ -19,6 +19,10 @@ export default class extends ContentManager {
return this.localContent;
}
+ static get contentType() {
+ return 'plugin';
+ }
+
static get moduleName() {
return 'PluginManager';
}
diff --git a/client/src/structs/error.js b/client/src/structs/error.js
new file mode 100644
index 00000000..df6a8c16
--- /dev/null
+++ b/client/src/structs/error.js
@@ -0,0 +1,38 @@
+/**
+ * BetterDiscord Error 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.
+*/
+
+export class Error {
+
+ constructor(args) {
+ this.args = args;
+ this.showStack = false; // For error modal
+ }
+
+ get module() {
+ return this.args.module;
+ }
+
+ get message() {
+ return this.args.message;
+ }
+
+ get err() {
+ return this.args.err;
+ }
+
+ get stackTrace() {
+ return this.err.stack;
+ }
+
+ get _type() {
+ return 'err';
+ }
+
+}
diff --git a/client/src/structs/structs.js b/client/src/structs/structs.js
new file mode 100644
index 00000000..93ae819e
--- /dev/null
+++ b/client/src/structs/structs.js
@@ -0,0 +1 @@
+export * from './error';
diff --git a/client/src/styles/partials/generic/modals.scss b/client/src/styles/partials/generic/modals.scss
index eac7f0dc..2ae89057 100644
--- a/client/src/styles/partials/generic/modals.scss
+++ b/client/src/styles/partials/generic/modals.scss
@@ -197,4 +197,69 @@
}
}
}
-}
\ No newline at end of file
+}
+
+.bd-modal-error .bd-modal-error-title {
+ padding: 5px;
+ background: rgba(0,0,0,.3);
+ border-radius: 3px 3px 0 0;
+}
+
+.bd-modal-error {
+ margin-top: 5px;
+
+ .bd-scroller-wrap {
+ background: rgba(0,0,0,.2);
+
+ .bd-scroller {
+ overflow-x: auto;
+ padding: 0;
+
+ &::-webkit-scrollbar-corner {
+ background: transparent;
+ }
+ }
+ }
+}
+
+.bd-modal-error .bd-scroller-wrap {
+ opacity: 0;
+}
+
+.bd-modal-error.bd-open {
+ .bd-modal-error-body {
+ transform: scaleY(1) translateY(0%);
+ margin-top: 0%;
+ opacity: 1;
+ user-select: all;
+ span {
+ font-weight: 700;
+ }
+ }
+ .bd-scroller-wrap {
+ opacity: 1;
+ }
+}
+
+.bd-modal-error .bd-modal-error-body {
+ white-space: pre-wrap;
+ font-size: 12px;
+ font-family: 'Consolas';
+ padding: 0 5px;
+ border-radius: 3px;
+ max-height: 100px;
+ width: auto;
+ transition: transform 0.2s ease, margin-top 0.2s ease, opacity 0.2s ease;
+ transform: scaleY(0) translateY(0%);
+ margin-top: -50%;
+ opacity: 0;
+}
+
+.bd-modal-titlelink {
+ cursor: pointer;
+ color: $colbdblue;
+ &:hover {
+ text-decoration: underline;
+ color: lighten($colbdblue, 5%);
+ }
+}
diff --git a/client/src/ui/components/bd/BdModals.vue b/client/src/ui/components/bd/BdModals.vue
index e31c4e71..61e7995f 100644
--- a/client/src/ui/components/bd/BdModals.vue
+++ b/client/src/ui/components/bd/BdModals.vue
@@ -19,7 +19,9 @@
:class="[{'bd-err': modal.type && modal.type === 'err'}, {'bd-modal-out': modal.closing}]">