Cleanup core
This commit is contained in:
parent
a4a130bfc6
commit
dc44af6968
138
core/src/main.js
138
core/src/main.js
|
@ -15,43 +15,40 @@ const { FileUtils, BDIpc, Config, WindowUtils, CSSEditor, Database } = require('
|
|||
const { BrowserWindow, dialog } = require('electron');
|
||||
|
||||
const tests = true;
|
||||
const _basePath = __dirname;
|
||||
|
||||
const _basePath = tests ? path.resolve(__dirname, '..', '..') : __dirname;
|
||||
const _baseDataPath = tests ? path.resolve(_basePath, 'tests') : _basePath;
|
||||
|
||||
const sparkplug = path.resolve(__dirname, 'sparkplug.js');
|
||||
|
||||
const _clientScript = tests
|
||||
? path.resolve(__dirname, '..', '..', 'client', 'dist', 'betterdiscord.client.js')
|
||||
: path.resolve(__dirname, 'betterdiscord.client.js');
|
||||
const _dataPath = tests
|
||||
? path.resolve(__dirname, '..', '..', 'tests', 'data')
|
||||
: path.resolve(__dirname, 'data');
|
||||
const _extPath = tests
|
||||
? path.resolve(__dirname, '..', '..', 'tests', 'ext')
|
||||
: path.resolve(__dirname, 'ext');
|
||||
const _pluginPath = path.resolve(_extPath, 'plugins');
|
||||
const _themePath = path.resolve(_extPath, 'themes');
|
||||
const _modulePath = path.resolve(_extPath, 'modules');
|
||||
? path.resolve(_basePath, 'client', 'dist', 'betterdiscord.client.js')
|
||||
: path.resolve(_basePath, 'betterdiscord.client.js');
|
||||
const _cssEditorPath = tests
|
||||
? path.resolve(__dirname, '..', '..', 'csseditor', 'dist')
|
||||
: path.resolve(__dirname, 'csseditor');
|
||||
|
||||
const _dataPath = path.resolve(_baseDataPath, 'data');
|
||||
const _extPath = path.resolve(_baseDataPath, 'ext');
|
||||
const _pluginPath = path.resolve(_extPath, 'plugins');
|
||||
const _themePath = path.resolve(_extPath, 'themes');
|
||||
const _modulePath = path.resolve(_extPath, 'modules');
|
||||
|
||||
const paths = [
|
||||
{ id: 'base', path: _basePath.replace(/\\/g, '/') },
|
||||
{ id: 'cs', path: _clientScript.replace(/\\/g, '/') },
|
||||
{ id: 'data', path: _dataPath.replace(/\\/g, '/') },
|
||||
{ id: 'ext', path: _extPath.replace(/\\/g, '/') },
|
||||
{ id: 'plugins', path: _pluginPath.replace(/\\/g, '/') },
|
||||
{ id: 'themes', path: _themePath.replace(/\\/g, '/') },
|
||||
{ id: 'modules', path: _modulePath.replace(/\\/g, '/') },
|
||||
{ id: 'csseditor', path: _cssEditorPath.replace(/\\/g, '/') }
|
||||
{ id: 'base', path: _basePath },
|
||||
{ id: 'cs', path: _clientScript },
|
||||
{ id: 'data', path: _dataPath },
|
||||
{ id: 'ext', path: _extPath },
|
||||
{ id: 'plugins', path: _pluginPath },
|
||||
{ id: 'themes', path: _themePath },
|
||||
{ id: 'modules', path: _modulePath },
|
||||
{ id: 'csseditor', path: _cssEditorPath }
|
||||
];
|
||||
|
||||
const sparkplug = path.resolve(__dirname, 'sparkplug.js').replace(/\\/g, '/');
|
||||
|
||||
const Common = {};
|
||||
const globals = {
|
||||
version: '2.0.0a',
|
||||
paths
|
||||
}
|
||||
|
||||
const dbInstance = new Database(paths.find(path => path.id === 'data').path);
|
||||
};
|
||||
|
||||
class Comms {
|
||||
|
||||
|
@ -61,9 +58,7 @@ class Comms {
|
|||
}
|
||||
|
||||
initListeners() {
|
||||
BDIpc.on('bd-getConfig', o => {
|
||||
o.reply(Common.Config.config);
|
||||
});
|
||||
BDIpc.on('bd-getConfig', o => o.reply(this.bd.config.config));
|
||||
|
||||
BDIpc.on('bd-sendToDiscord', event => this.bd.windowUtils.send(event.args.channel, event.args.message));
|
||||
|
||||
|
@ -71,9 +66,6 @@ class Comms {
|
|||
// BDIpc.on('bd-setScss', o => this.bd.csseditor.setSCSS(o.args.scss));
|
||||
BDIpc.on('bd-sendToCssEditor', o => this.bd.csseditor.send(o.args.channel, o.args.data));
|
||||
|
||||
BDIpc.on('bd-readFile', this.readFile);
|
||||
BDIpc.on('bd-readJson', o => this.readFile(o, true));
|
||||
|
||||
BDIpc.on('bd-native-open', o => {
|
||||
dialog.showOpenDialog(BrowserWindow.fromWebContents(o.ipcEvent.sender), o.args, filenames => {
|
||||
o.reply(filenames);
|
||||
|
@ -88,19 +80,15 @@ class Comms {
|
|||
}
|
||||
|
||||
sass.render(o.args, (err, result) => {
|
||||
if (err) {
|
||||
o.reply({ err });
|
||||
return;
|
||||
}
|
||||
o.reply(result);
|
||||
if (err) return o.reply({ err });
|
||||
else o.reply(result);
|
||||
});
|
||||
});
|
||||
|
||||
BDIpc.on('bd-dba', o => {
|
||||
(async () => {
|
||||
try {
|
||||
const ret = await dbInstance.exec(o.args);
|
||||
o.reply(ret);
|
||||
o.reply(await this.bd.dbInstance.exec(o.args));
|
||||
} catch (err) {
|
||||
o.reply({ err });
|
||||
}
|
||||
|
@ -108,16 +96,6 @@ class Comms {
|
|||
});
|
||||
}
|
||||
|
||||
async readFile(o, json) {
|
||||
const { path } = o.args;
|
||||
try {
|
||||
const readFile = json ? await FileUtils.readJsonFromFile(path) : await FileUtils.readFile(path);
|
||||
o.reply(readFile);
|
||||
} catch (err) {
|
||||
o.reply(err);
|
||||
}
|
||||
}
|
||||
|
||||
async send(channel, message) {
|
||||
BDIpc.send(channel, message);
|
||||
}
|
||||
|
@ -135,23 +113,25 @@ class BetterDiscord {
|
|||
|
||||
this.injectScripts = this.injectScripts.bind(this);
|
||||
this.ignite = this.ignite.bind(this);
|
||||
Common.Config = new Config(globals);
|
||||
|
||||
this.config = new Config(args || globals);
|
||||
this.dbInstance = new Database(this.config.paths.find(path => path.id === 'data').path);
|
||||
this.comms = new Comms(this);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
const window = await this.waitForWindow();
|
||||
this.windowUtils = new WindowUtils({ window });
|
||||
await this.waitForWindowUtils();
|
||||
|
||||
await FileUtils.ensureDirectory(paths.find(path => path.id === 'ext').path);
|
||||
await FileUtils.ensureDirectory(this.config.paths.find(path => path.id === 'ext').path);
|
||||
|
||||
this.csseditor = new CSSEditor(this, paths.find(path => path.id === 'csseditor').path);
|
||||
this.csseditor = new CSSEditor(this, this.config.paths.find(path => path.id === 'csseditor').path);
|
||||
|
||||
this.windowUtils.events('did-get-response-details', () => this.ignite(this.windowUtils.window));
|
||||
this.windowUtils.events('did-finish-load', e => this.injectScripts(true));
|
||||
this.windowUtils.on('did-get-response-details', () => this.ignite());
|
||||
this.windowUtils.on('did-finish-load', e => this.injectScripts(true));
|
||||
|
||||
this.windowUtils.events('did-navigate-in-page', (event, url, isMainFrame) => {
|
||||
this.windowUtils.on('did-navigate-in-page', (event, url, isMainFrame) => {
|
||||
this.windowUtils.send('did-navigate-in-page', { event, url, isMainFrame });
|
||||
});
|
||||
|
||||
|
@ -166,10 +146,8 @@ class BetterDiscord {
|
|||
const defer = setInterval(() => {
|
||||
const windows = BrowserWindow.getAllWindows();
|
||||
|
||||
if (windows.length > 0) {
|
||||
windows.forEach(window => {
|
||||
self.ignite(window);
|
||||
});
|
||||
for (let window of windows) {
|
||||
BetterDiscord.ignite(window);
|
||||
}
|
||||
|
||||
if (windows.length === 1 && windows[0].webContents.getURL().includes('discordapp.com')) {
|
||||
|
@ -180,23 +158,45 @@ class BetterDiscord {
|
|||
});
|
||||
}
|
||||
|
||||
ignite(window) {
|
||||
//Hook things that Discord removes from global. These will be removed again in the client script
|
||||
window.webContents.executeJavaScript(`require("${sparkplug}");`);
|
||||
async waitForWindowUtils() {
|
||||
if (this.windowUtils) return this.windowUtils;
|
||||
const window = await this.waitForWindow();
|
||||
return this.windowUtils = new WindowUtils({ window });
|
||||
}
|
||||
|
||||
get window() {
|
||||
return this.windowUtils ? this.windowUtils.window : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks things that Discord removes from global. These will be removed again in the client script.
|
||||
*/
|
||||
ignite() {
|
||||
return BetterDiscord.ignite(this.window);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks things that Discord removes from global. These will be removed again in the client script.
|
||||
* @param {BrowserWindow} window The window to inject the sparkplug script into
|
||||
*/
|
||||
static ignite(window) {
|
||||
return WindowUtils.injectScript(window, sparkplug);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the client script into the main window.
|
||||
* @param {Boolean} reload Whether the main window was reloaded
|
||||
*/
|
||||
async injectScripts(reload = false) {
|
||||
console.log(`RELOAD? ${reload}`);
|
||||
if (!tests) {
|
||||
const files = await FileUtils.listDirectory(paths.find(path => path.id === 'base').path);
|
||||
const files = await FileUtils.listDirectory(this.config.paths.find(path => path.id === 'base').path);
|
||||
const latestCs = FileUtils.resolveLatest(files, file => file.endsWith('.js') && file.startsWith('client.'), file => file.replace('client.', '').replace('.js', ''), 'client.', '.js');
|
||||
paths.find(path => path.id === 'cs').path = path.resolve(paths.find(path => path.id === 'base').path, latestCs).replace(/\\/g, '/');
|
||||
this.config.paths.find(path => path.id === 'cs').path = path.resolve(this.config.paths.find(path => path.id === 'base').path, latestCs);
|
||||
}
|
||||
this.windowUtils.injectScript(paths.find(path => path.id === 'cs').path);
|
||||
return this.windowUtils.injectScript(this.config.paths.find(path => path.id === 'cs').path);
|
||||
}
|
||||
|
||||
get fileUtils() { return FileUtils; }
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
const { Module } = require('./modulebase');
|
||||
|
||||
const { ipcMain } = require('electron');
|
||||
|
@ -34,7 +35,6 @@ class BDIpcEvent extends Module {
|
|||
}
|
||||
|
||||
class BDIpc {
|
||||
|
||||
static on(channel, cb) {
|
||||
ipcMain.on(channel, (event, args) => cb(new BDIpcEvent(event, args)));
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ class Config extends Module {
|
|||
|
||||
get config() {
|
||||
return {
|
||||
'version': this.version,
|
||||
'paths': this.paths
|
||||
version: this.version,
|
||||
paths: this.paths
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@ class CSSEditor extends Module {
|
|||
this.bd = bd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an editor and replies to an IPC event.
|
||||
* @param {BDIpcEvent} event
|
||||
*/
|
||||
openEditor(o) {
|
||||
if (this.editor) {
|
||||
if (this.editor.isFocused()) return;
|
||||
|
@ -32,12 +36,7 @@ class CSSEditor extends Module {
|
|||
return;
|
||||
}
|
||||
|
||||
const options = this.options;
|
||||
for (let option in o.args) {
|
||||
if (o.args.hasOwnProperty(option)) {
|
||||
options[option] = o.args[option];
|
||||
}
|
||||
}
|
||||
const options = Object.assign({}, this.options, o.message);
|
||||
|
||||
this.editor = new BrowserWindow(options);
|
||||
this.editor.loadURL('about:blank');
|
||||
|
@ -59,20 +58,34 @@ class CSSEditor extends Module {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SCSS in the editor.
|
||||
*/
|
||||
setSCSS(scss) {
|
||||
this.send('set-scss', scss);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends data to the editor.
|
||||
* @param {String} channel
|
||||
* @param {Any} data
|
||||
*/
|
||||
send(channel, data) {
|
||||
if (!this.editor) return;
|
||||
this.editor.webContents.send(channel, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CSS editor's always on top flag.
|
||||
*/
|
||||
set alwaysOnTop(state) {
|
||||
if (!this.editor) return;
|
||||
this.editor.setAlwaysOnTop(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default options to pass to BrowserWindow.
|
||||
*/
|
||||
get options() {
|
||||
return {
|
||||
width: 800,
|
||||
|
|
|
@ -8,17 +8,16 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/*
|
||||
Base Module that every non-static module should extend
|
||||
/**
|
||||
* Base Module that every non-static module should extend.
|
||||
*/
|
||||
|
||||
class Module {
|
||||
|
||||
constructor(args) {
|
||||
this.__ = {
|
||||
state: args,
|
||||
args
|
||||
}
|
||||
};
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,43 +10,35 @@
|
|||
|
||||
// TODO Use common
|
||||
|
||||
const
|
||||
path = require('path'),
|
||||
fs = require('fs');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const { Module } = require('./modulebase');
|
||||
|
||||
class Utils {
|
||||
|
||||
static async tryParseJson(jsonString) {
|
||||
try {
|
||||
return JSON.parse(jsonString);
|
||||
} catch (err) {
|
||||
throw ({
|
||||
'message': 'Failed to parse json',
|
||||
message: 'Failed to parse json',
|
||||
err
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static get timestamp() {
|
||||
return 'Timestamp';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FileUtils {
|
||||
|
||||
static async fileExists(path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.stat(path, (err, stats) => {
|
||||
if(err) return reject({
|
||||
'message': `No such file or directory: ${err.path}`,
|
||||
message: `No such file or directory: ${err.path}`,
|
||||
err
|
||||
});
|
||||
|
||||
if(!stats.isFile()) return reject({
|
||||
'message': `Not a file: ${path}`,
|
||||
message: `Not a file: ${path}`,
|
||||
stats
|
||||
});
|
||||
|
||||
|
@ -59,12 +51,12 @@ class FileUtils {
|
|||
return new Promise((resolve, reject) => {
|
||||
fs.stat(path, (err, stats) => {
|
||||
if(err) return reject({
|
||||
'message': `Directory does not exist: ${path}`,
|
||||
message: `Directory does not exist: ${path}`,
|
||||
err
|
||||
});
|
||||
|
||||
if(!stats.isDirectory()) return reject({
|
||||
'message': `Not a directory: ${path}`,
|
||||
message: `Not a directory: ${path}`,
|
||||
stats
|
||||
});
|
||||
|
||||
|
@ -77,13 +69,13 @@ class FileUtils {
|
|||
try {
|
||||
await this.fileExists(path);
|
||||
} catch (err) {
|
||||
throw(err);
|
||||
throw err;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(path, 'utf-8', (err, data) => {
|
||||
if(err) reject({
|
||||
'message': `Could not read file: ${path}`,
|
||||
if(err) return reject({
|
||||
message: `Could not read file: ${path}`,
|
||||
err
|
||||
});
|
||||
|
||||
|
@ -97,14 +89,13 @@ class FileUtils {
|
|||
try {
|
||||
readFile = await this.readFile(path);
|
||||
} catch(err) {
|
||||
throw(err);
|
||||
throw err;
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = await Utils.tryParseJson(readFile);
|
||||
return parsed;
|
||||
return await Utils.tryParseJson(readFile);
|
||||
} catch (err) {
|
||||
throw(Object.assign(err, { path }));
|
||||
throw Object.assign(err, { path });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,8 +104,8 @@ class FileUtils {
|
|||
await this.directoryExists(path);
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readdir(path, (err, files) => {
|
||||
if (err) return reject(err);
|
||||
resolve(files);
|
||||
if (err) reject(err);
|
||||
else resolve(files);
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
|
@ -145,11 +136,8 @@ class FileUtils {
|
|||
static async createDirectory(path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.mkdir(path, err => {
|
||||
if (err) {
|
||||
if (err.code === 'EEXIST') return resolve();
|
||||
else return reject(err);
|
||||
}
|
||||
resolve();
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -170,7 +158,6 @@ class FileUtils {
|
|||
}
|
||||
|
||||
class WindowUtils extends Module {
|
||||
|
||||
bindings() {
|
||||
this.openDevTools = this.openDevTools.bind(this);
|
||||
this.executeJavascript = this.executeJavascript.bind(this);
|
||||
|
@ -194,16 +181,20 @@ class WindowUtils extends Module {
|
|||
}
|
||||
|
||||
injectScript(fpath, variable) {
|
||||
console.log(`Injecting: ${fpath}`);
|
||||
return WindowUtils.injectScript(this.window, fpath, variable);
|
||||
}
|
||||
|
||||
static injectScript(window, fpath, variable) {
|
||||
// console.log(`Injecting: ${fpath}`);
|
||||
|
||||
const escaped_path = fpath.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
||||
const escaped_variable = variable ? variable.replace(/\\/g, '\\\\').replace(/"/g, '\\"') : null;
|
||||
|
||||
if (variable) this.executeJavascript(`window["${escaped_variable}"] = require("${escaped_path}");`);
|
||||
else this.executeJavascript(`require("${escaped_path}");`);
|
||||
if (variable) window.executeJavaScript(`window["${escaped_variable}"] = require("${escaped_path}");`);
|
||||
else window.executeJavaScript(`require("${escaped_path}");`);
|
||||
}
|
||||
|
||||
events(event, callback) {
|
||||
on(event, callback) {
|
||||
this.webContents.on(event, callback);
|
||||
}
|
||||
|
||||
|
@ -211,7 +202,6 @@ class WindowUtils extends Module {
|
|||
channel = channel.startsWith('bd-') ? channel : `bd-${channel}`;
|
||||
this.webContents.send(channel, message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -33,18 +33,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import '../../node_modules/codemirror/addon/scroll/simplescrollbars.js';
|
||||
import '../../node_modules/codemirror/mode/css/css.js';
|
||||
import '../../node_modules/codemirror/addon/hint/css-hint.js';
|
||||
import '../../node_modules/codemirror/addon/search/search.js';
|
||||
import '../../node_modules/codemirror/addon/search/searchcursor.js';
|
||||
import '../../node_modules/codemirror/addon/search/jump-to-line.js';
|
||||
import '../../node_modules/codemirror/addon/dialog/dialog.js';
|
||||
import '../../node_modules/codemirror/addon/hint/show-hint.js';
|
||||
|
||||
import BDIpc from './BDIpc';
|
||||
|
||||
const { remote } = window.require('electron');
|
||||
import { remote } from 'electron';
|
||||
|
||||
import 'codemirror/addon/scroll/simplescrollbars.js';
|
||||
import 'codemirror/mode/css/css.js';
|
||||
import 'codemirror/addon/hint/css-hint.js';
|
||||
import 'codemirror/addon/search/search.js';
|
||||
import 'codemirror/addon/search/searchcursor.js';
|
||||
import 'codemirror/addon/search/jump-to-line.js';
|
||||
import 'codemirror/addon/dialog/dialog.js';
|
||||
import 'codemirror/addon/hint/show-hint.js';
|
||||
|
||||
const ExcludedIntelliSenseTriggerKeys = {
|
||||
'8': 'backspace',
|
||||
|
|
Loading…
Reference in New Issue