This commit is contained in:
Samuel Elliott 2019-03-16 19:09:15 +00:00 committed by GitHub
commit 2ecd372d1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 126 additions and 12 deletions

View File

@ -8,7 +8,7 @@
* LICENSE file in the root directory of this source tree.
*/
import { Settings, Cache, Events } from 'modules';
import { Settings, Cache, Events, Globals } from 'modules';
import BuiltinModule from '../BuiltinModule';
import { Reflection, ReactComponents, DiscordApi, Security } from 'modules';
import { VueInjector, Modals, Toasts } from 'ui';
@ -62,7 +62,7 @@ export default new class E2EE extends BuiltinModule {
/* Methods */
async fetchMasterKey() {
try {
if (Settings.get('security', 'default', 'use-keytar')) {
if (Settings.get('security', 'default', 'use-keytar') && !Globals.nativeModuleErrors.keytar) {
const master = await ClientIPC.getPassword('betterdiscord', 'master');
if (master) return this.setMaster(master);

View File

@ -13,6 +13,7 @@ import BdCss from './styles/index.scss';
import { Events, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, Vendor, Patcher, MonkeyPatch, ReactComponents, ReactHelpers, ReactAutoPatcher, DiscordApi, BdWebApi, Connectivity, Cache, Reflection, PackageInstaller } from 'modules';
import { ClientLogger as Logger, ClientIPC, Utils, Axi } from 'common';
import { BuiltinManager, EmoteModule, ReactDevtoolsModule, VueDevtoolsModule, TrackingProtection, E2EE } from 'builtin';
import { ErrorEvent } from 'structs';
import electron from 'electron';
import path from 'path';
@ -70,6 +71,9 @@ class BetterDiscord {
this.globalReady = this.globalReady.bind(this);
Events.on('global-ready', this.globalReady);
Globals.initg();
this.showNativeModuleErrors = this.showNativeModuleErrors.bind(this);
Events.on('show-native-module-errors', this.showNativeModuleErrors);
}
globalReady() {
@ -80,6 +84,9 @@ class BetterDiscord {
async init() {
try {
Logger.log('main', ['Native module errors', Globals.nativeModuleErrors]);
Events.emit('show-native-module-errors');
await Database.init();
await Settings.loadSettings();
await ModuleManager.initModules();
@ -87,6 +94,10 @@ class BetterDiscord {
if (tests) this.initTests();
if (Globals.nativeModuleErrors.keytar) {
Settings.getSetting('security', 'default', 'use-keytar').disabled = true;
}
if (!ignoreExternal) {
await ExtModuleManager.loadAllModules(true);
await PluginManager.loadAllPlugins(true);
@ -96,13 +107,30 @@ class BetterDiscord {
Events.emit('ready');
Events.emit('discord-ready');
if (!Settings.get('core', 'advanced', 'ignore-content-manager-errors'))
if (!Settings.get('core', 'advanced', 'ignore-content-manager-errors') && !Globals.nativeModuleErrorCount)
Modals.showContentManagerErrors();
} catch (err) {
Logger.err('main', ['FAILED TO LOAD!', err]);
}
}
showNativeModuleErrors() {
if (!Globals.nativeModuleErrorCount) return;
return Modals.error({
header: `${Globals.nativeModuleErrorCount} native module${Globals.nativeModuleErrorCount !== 1 ? 's' : ''} failed to load`,
module: 'core',
type: 'err',
message: 'Some features will be unavailable. This normally happens when Discord updates Electron. Make sure you\'re running the latest version of Discord and BetterDiscord and try again.'
+ (tests ? ' You can also try recompiling native modules.' : ''),
content: Object.entries(Globals.nativeModuleErrors).map(([name, err]) => new ErrorEvent({
module: name,
message: `Failed to load ${name}`,
err
}))
});
}
initTests() {
let notifications = 0;
function showDummyNotif() { // eslint-disable-line no-inner-declarations

View File

@ -38,6 +38,9 @@ export default new class extends Module {
const config = await ClientIPC.send('getConfig');
this.setState({ config });
const nativeModuleErrors = await ClientIPC.getNativeModuleErrors();
this.setState({ nativeModuleErrors });
// This is for Discord to stop error reporting :3
window.BetterDiscord = {
version: config.version,
@ -101,4 +104,12 @@ export default new class extends Module {
return this.config.versions.core;
}
get nativeModuleErrors() {
return this.state.nativeModuleErrors;
}
get nativeModuleErrorCount() {
return Object.keys(this.nativeModuleErrors).length;
}
}

View File

@ -58,6 +58,20 @@
}
}
.bd-sidebarMessage {
display: flex;
padding: 6px 10px;
cursor: pointer;
.bd-materialDesignIcon {
margin-right: 10px;
}
&.bd-err svg {
fill: $colerr;
}
}
.bd-info {
display: flex;
align-items: flex-end;

View File

@ -16,6 +16,15 @@
<MiClose size="17"/>
<span class="bd-xText">ESC</span>
</div>
<div v-if="nativeModuleErrorCount" class="bd-sidebarMessage bd-err" @click="showNativeModuleErrors">
<MiError size="20" />
<div>
<strong>{{ nativeModuleErrorCount }} native module{{ nativeModuleErrorCount !== 1 ? 's' : '' }} failed to load.</strong>
Some features will be unavailable.
</div>
</div>
<template v-for="(category, text) in sidebar">
<SidebarItem :item="{text, type: 'header'}" />
<SidebarItem v-for="i in category" :key="i.id" :item="i" :active="item && i.id === item.id" @click="itemOnClick(i.id)" />
@ -68,7 +77,7 @@
import { shell } from 'electron';
import { SidebarView, Sidebar, SidebarItem, ContentColumn } from './sidebar';
import { SettingsWrapper, SettingsPanel, CssEditorView, PluginsView, ThemesView, UpdaterView, ConnectivityView, SuperSecretView } from './bd';
import { SvgX, MiGithubCircle, MiWeb, MiClose, MiTwitterCircle } from './common';
import { SvgX, MiGithubCircle, MiWeb, MiClose, MiTwitterCircle, MiError } from './common';
export default {
data() {
@ -85,7 +94,7 @@
components: {
SidebarView, Sidebar, SidebarItem, ContentColumn,
SettingsWrapper, SettingsPanel, CssEditorView, PluginsView, ThemesView, UpdaterView, ConnectivityView,
MiGithubCircle, MiWeb, MiClose, MiTwitterCircle
MiGithubCircle, MiWeb, MiClose, MiTwitterCircle, MiError
},
computed: {
sidebar() {
@ -99,6 +108,9 @@
},
versionString() {
return Globals.version;
},
nativeModuleErrorCount() {
return Globals.nativeModuleErrorCount;
}
},
methods: {
@ -116,6 +128,9 @@
},
openTwitter() {
shell.openExternal('https://twitter.com/Jiiksi');
},
showNativeModuleErrors() {
Events.emit('show-native-module-errors');
}
},
watch: {

View File

@ -3,6 +3,8 @@
:class="{'bd-err': modal.event.type && modal.event.type === 'err'}">
<MiError v-if="modal.event.type === 'err'" slot="icon" size="20"/>
<div slot="body">
<p v-if="modal.event.message">{{ modal.event.message }}</p>
<div v-for="(content, index) in modal.event.content">
<div class="bd-modalError" :class="{'bd-open': content.showStack}">
<div class="bd-modalErrorTitle bd-flex">

View File

@ -104,6 +104,10 @@ const ClientIPC = new class ClientIPC {
return this.send('native-open', options);
}
getNativeModuleErrors() {
return this.send('getNativeModuleErrors');
}
compileSass(options) {
return this.send('compileSass', options);
}

View File

@ -46,13 +46,12 @@ const TEST_EDITOR = TESTS && true;
import process from 'process';
import os from 'os';
import path from 'path';
import sass from 'node-sass';
import { BrowserWindow as OriginalBrowserWindow, dialog, session, shell } from 'electron';
import deepmerge from 'deepmerge';
import ContentSecurityPolicy from 'csp-parse';
import keytar from 'keytar';
import { FileUtils, BDIpc, Config, WindowUtils, Updater, Editor, Database } from './modules';
import { sass, keytar, native_module_errors } from './modules';
const sparkplug = path.resolve(__dirname, 'sparkplug.js');
@ -83,7 +82,14 @@ class Comms {
});
});
BDIpc.on('bd-getNativeModuleErrors', () => native_module_errors, true);
BDIpc.on('bd-compileSass', (event, options) => {
if (!sass) {
event.reject(native_module_errors['node-sass']);
return;
}
if (typeof options.path === 'string' && typeof options.data === 'string') {
options.data = `${options.data} @import '${options.path.replace(/\\/g, '\\\\').replace(/'/g, '\\\'')}';`;
options.path = undefined;
@ -97,10 +103,22 @@ class Comms {
BDIpc.on('bd-dba', (event, options) => this.bd.database.exec(options), true);
BDIpc.on('bd-keytar-get', (event, { service, account }) => keytar.getPassword(service, account), true);
BDIpc.on('bd-keytar-set', (event, { service, account, password }) => keytar.setPassword(service, account, password), true);
BDIpc.on('bd-keytar-delete', (event, { service, account }) => keytar.deletePassword(service, account), true);
BDIpc.on('bd-keytar-find-credentials', (event, { service }) => keytar.findCredentials(service), true);
BDIpc.on('bd-keytar-get', (event, { service, account }) => {
if (!keytar) throw native_module_errors.keytar;
return keytar.getPassword(service, account);
}, true);
BDIpc.on('bd-keytar-set', (event, { service, account, password }) => {
if (!keytar) throw native_module_errors.keytar;
return keytar.setPassword(service, account, password);
}, true);
BDIpc.on('bd-keytar-delete', (event, { service, account }) => {
if (!keytar) throw native_module_errors.keytar;
return keytar.deletePassword(service, account);
}, true);
BDIpc.on('bd-keytar-find-credentials', (event, { service }) => {
if (!keytar) throw native_module_errors.keytar;
return keytar.findCredentials(service);
}, true);
BDIpc.on('bd-readDataFile', async (event, fileName) => {
const rf = await FileUtils.readFile(path.resolve(configProxy().getPath('data'), fileName));

View File

@ -14,9 +14,10 @@ import { BrowserWindow } from 'electron';
import Module from './modulebase';
import { WindowUtils, FileUtils } from './utils';
import BDIpc from './bdipc';
import sass from 'node-sass';
import chokidar from 'chokidar';
import { sass, native_module_errors } from '.';
export default class Editor extends Module {
constructor(bd, path) {
@ -123,6 +124,11 @@ export default class Editor extends Module {
return;
}
if (!sass) {
event.reject(native_module_errors['node-sass']);
return;
}
style = await Promise.all(style.split('\n').map(async(line) => {
if (!line.startsWith('@import')) return line;
const filename = line.split(' ')[1].replace(/'|"|;/g, '');

View File

@ -5,3 +5,19 @@ export { default as CSSEditor } from './csseditor';
export { default as Editor } from './editor';
export { default as Database } from './database';
export { default as Updater } from './updater';
export const native_module_errors = {};
try {
exports.sass = require('node-sass');
} catch (err) {
console.error('[BetterDiscord] Error loading node-sass', err);
native_module_errors['node-sass'] = err instanceof Error ? {message: err.message, stack: err.stack} : err;
}
try {
exports.keytar = require('keytar');
} catch (err) {
console.error('[BetterDiscord] Error loading keytar', err);
native_module_errors.keytar = err instanceof Error ? {message: err.message, stack: err.stack} : err;
}