diff --git a/client/package.json b/client/package.json index 59553fc4..a6989a28 100644 --- a/client/package.json +++ b/client/package.json @@ -2,7 +2,7 @@ "name": "bdclient", "description": "BetterDiscord client package", "author": "Jiiks", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "homepage": "https://betterdiscord.net", "license": "MIT", "main": "dist/betterdiscord.client.js", diff --git a/client/src/index.js b/client/src/index.js index de27de87..eea4c0da 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -11,14 +11,13 @@ import { DOM, BdUI, BdMenu, Modals, Toasts, Notifications, BdContextMenu, DiscordContextMenu } from 'ui'; 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 } from 'common'; +import { ClientLogger as Logger, ClientIPC, Utils, Axi } from 'common'; import { BuiltinManager, EmoteModule, ReactDevtoolsModule, VueDevtoolsModule, TrackingProtection, E2EE } from 'builtin'; import electron from 'electron'; import path from 'path'; -import { setTimeout } from 'timers'; const tests = typeof PRODUCTION === 'undefined'; -const ignoreExternal = true; +const ignoreExternal = tests && true; class BetterDiscord { @@ -39,7 +38,7 @@ class BetterDiscord { BdWebApi, Connectivity, Cache, - Logger, ClientIPC, Utils, + Logger, ClientIPC, Utils, Axi, plugins: PluginManager.localContent, themes: ThemeManager.localContent, diff --git a/client/src/modules/globals.js b/client/src/modules/globals.js index 7c40a19a..0c9da1d6 100644 --- a/client/src/modules/globals.js +++ b/client/src/modules/globals.js @@ -102,7 +102,7 @@ export default new class extends Module { } get version() { - return this.config.version; + return this.config.versions.core; } } diff --git a/client/src/modules/imodule.js b/client/src/modules/imodule.js index b16b9ee8..bff59c68 100644 --- a/client/src/modules/imodule.js +++ b/client/src/modules/imodule.js @@ -39,7 +39,7 @@ export default class Module { } setState(newState) { - const oldState = this.state; + const oldState = Object.assign({}, this.state); Object.assign(this.state, newState); if (this.stateChanged) this.stateChanged(oldState, newState); } diff --git a/client/src/modules/updater.js b/client/src/modules/updater.js index 76b4ca29..a48c32c8 100644 --- a/client/src/modules/updater.js +++ b/client/src/modules/updater.js @@ -8,81 +8,183 @@ * LICENSE file in the root directory of this source tree. */ -import Events from './events'; -import Globals from './globals'; -import { ClientLogger as Logger } from 'common'; -import request from 'request-promise-native'; +import { Notifications } from 'ui'; +import { Reflection, Globals } from 'modules'; -export default new class { +import Events from './events'; +import Module from './imodule'; + +export default new class extends Module { + + get updates() { return this.state.updates } + get bdUpdates() { return this.state.updates.bd } + get error() { return null; } + get updatesAvailable() { return this.state.updatesAvailable; } constructor() { - this.updatesAvailable = false; - this.latestVersion = undefined; - this.error = undefined; - - this.init = this.init.bind(this); - this.checkForUpdates = this.checkForUpdates.bind(this); + super({ + updatesAvailable: false, + error: null, + updates: { bd: [] }, + updating: false + }); } - /** - * The interval to wait before checking for updates. - */ - get interval() { - return 60 * 1000 * 30; + bindings() { + this.restartNotif = this.restartNotif.bind(this); + this.reloadNotif = this.reloadNotif.bind(this); + this.startUpdate = this.startUpdate.bind(this); + this.setUpdateStatus = this.setUpdateStatus.bind(this); + this.testUi = this.testUi.bind(this); } - init() { - this.updateInterval = setInterval(this.checkForUpdates, this.interval); + restartNotif() { + Notifications.add('Updates Finished!', 'Restart required.', [ + { + text: 'Restart Later', + onClick: () => { setTimeout(this.restartNotif, 5 * 60000); return true; } + }, + { + text: 'Restart Now', + onClick: () => { + try { + const { remote } = Globals.require('electron'); + window.close(); + Reflection.module.byProps('showToken', 'hideToken').showToken(); + remote.app.relaunch(); + remote.app.exit(0); + } catch (err) { + console.err(err); + return true; + } + } + } + ]); } - /** - * Installs an update. - * TODO - */ - async update() { - try { - await new Promise(resolve => setTimeout(resolve, 5000)); - - this.updatesAvailable = false; - this.latestVersion = Globals.version; - Events.emit('update-check-end'); - } catch (err) { - this.error = err; - this.checkForUpdates(); - throw err; - } + reloadNotif() { + Notifications.add('Updates Finished!', 'Reload required.', [ + { + text: 'Reload Later', + onClick: () => { setTimeout(this.reloadNotif, 5 * 60000); return true; } + }, + { + text: 'Reload Now', + onClick: () => { + document.location.reload(); + } + } + ]); } - /** - * Checks for updates. - * @return {Promise} - */ - async checkForUpdates() { - if (this.updatesAvailable) return true; - Events.emit('update-check-start'); - Logger.info('Updater', 'Checking for updates'); + events(ipc) { + ipc.on('updater-checkForUpdates', () => { + if (this.state.updating) return; // We're already updating. Updater should be paused anyways at this point. + Events.emit('update-check-start'); + }); - try { - const response = await request({ - uri: 'https://rawgit.com/JsSucks/BetterDiscordApp/master/package.json', - json: true + ipc.on('updater-noUpdates', () => { + if (this.state.updatesAvailable) return; // If for some reason we get this even though we have updates already. + this.setState({ + updatesAvailable: false, + updates: {} }); + }); - this.latestVersion = response.version; - Events.emit('update-check-end'); - Logger.info('Updater', `Latest Version: ${response.version} - Current Version: ${Globals.version}`); + ipc.on('updater-updatesAvailable', (_, updates) => { + console.log(updates); + if (this.state.updating) return; // If for some reason we get more updates when we're already updating + updates.bd = updates.bd.map(update => { + update.text = `${update.id.charAt(0).toUpperCase()}${update.id.slice(1)}`; + update.hint = `Current: ${update.currentVersion} | Latest: ${update.version}`; + update.status = { + update: true, + updating: false, + updated: false, + error: null + }; - if (this.latestVersion !== Globals.version) { - this.updatesAvailable = true; - Events.emit('updates-available'); - return true; + return update; + }); + this.setState({ + updates, + updatesAvailable: true + }); + }); + + ipc.on('updater-updated', (_, info) => { + const { reloadRequired, restartRequired } = info; + if (restartRequired) { + this.restartNotif(); + return; } - return false; - } catch (err) { - Events.emit('update-check-fail', err); - throw err; + if (reloadRequired) { + this.reloadNotif(); + return; + } + }); + + ipc.on('updater-updateFinished', (_, update) => { + this.setUpdateStatus(update.id, 'updated', true); + }); + + ipc.on('updater-updateError', (_, update) => { + this.setUpdateStatus(update.id, 'error', update.error); + }); + } + + stateChanged(oldState, newState) { + if (!newState.updatesAvailable) return Events.emit('update-check-end'); + if (!oldState.updatesAvailable && newState.updatesAvailable) { + Events.emit('updates-available'); + Notifications.add('', 'Updates Available!', [ + { + text: 'Ignore', + onClick: () => { return true; } + }, + { + text: 'Show Updates', + onClick: () => { + Events.emit('bd-open-menu', 'updater'); + return true; + } + } + ]); } } + setUpdateStatus(updateId, statusChild, statusValue) { + for (const u of this.bdUpdates) { + if (u.id === updateId) { + u.status[statusChild] = statusValue; + return; + } + } + } + + toggleUpdate(update) { + update.status.update = !update.status.update; + } + + async startUpdate() { + console.log('start update'); + const updates = { bd: [] }; + for (const update of this.bdUpdates) { + if (update.status.update) { + update.status.updating = true; + updates.bd.push(update); + } + } + console.log(updates); + this.send('updater-startUpdate', updates); + } + + testUi(updates) { + this.setState({ + updates, + updatesAvailable: true + }); + } + } diff --git a/client/src/modules/vendor.js b/client/src/modules/vendor.js index efdf35c7..2c1d584a 100644 --- a/client/src/modules/vendor.js +++ b/client/src/modules/vendor.js @@ -11,6 +11,7 @@ import jQuery from 'jquery'; import lodash from 'lodash'; import Vue from 'vue'; +import { Axi } from 'common'; import request from 'request-promise-native'; @@ -40,6 +41,8 @@ export default class { */ static get Vue() { return Vue } + static get axios() { return Axi.axios } + static get request() { return request } static get Combokeys() { return Combokeys } diff --git a/client/src/styles/partials/bdsettings/devview.scss b/client/src/styles/partials/bdsettings/devview.scss new file mode 100644 index 00000000..5e32088d --- /dev/null +++ b/client/src/styles/partials/bdsettings/devview.scss @@ -0,0 +1,9 @@ +.bd-contentColumn .bd-devview { + display: grid; + grid-template-columns: 33% 33% 33%; + + .bd-button { + font-size: 10px; + height: 20px; + } +} diff --git a/client/src/styles/partials/bdsettings/index.scss b/client/src/styles/partials/bdsettings/index.scss index 4bcde300..0fbda29f 100644 --- a/client/src/styles/partials/bdsettings/index.scss +++ b/client/src/styles/partials/bdsettings/index.scss @@ -10,3 +10,4 @@ @import './kvp'; @import './collection'; @import './e2ee'; +@import './devview'; diff --git a/client/src/styles/partials/bdsettings/updater.scss b/client/src/styles/partials/bdsettings/updater.scss index 3e239974..8428036a 100644 --- a/client/src/styles/partials/bdsettings/updater.scss +++ b/client/src/styles/partials/bdsettings/updater.scss @@ -3,4 +3,22 @@ margin: 0 0 10px; color: #fff; } + + .bd-settingSwitch { + .bd-spinner7 { + height: 24px; + } + + .bd-updaterStatus { + text-align: right; + + &.bd-err { + color: $colerr; + } + + &.bd-ok { + color: $colok; + } + } + } } diff --git a/client/src/ui/components/BdSettings.vue b/client/src/ui/components/BdSettings.vue index 398437c7..ec1daae0 100644 --- a/client/src/ui/components/BdSettings.vue +++ b/client/src/ui/components/BdSettings.vue @@ -20,10 +20,11 @@ +
- v2.0.0a by Jiiks/JsSucks + {{versionString}}
@@ -37,7 +38,8 @@ -
+ +
@@ -63,11 +65,11 @@ diff --git a/client/src/ui/components/bd/UpdaterStatus.vue b/client/src/ui/components/bd/UpdaterStatus.vue new file mode 100644 index 00000000..76ef0b24 --- /dev/null +++ b/client/src/ui/components/bd/UpdaterStatus.vue @@ -0,0 +1,28 @@ +/** + * BetterDiscord Updater Status 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/UpdaterToggle.vue b/client/src/ui/components/bd/UpdaterToggle.vue new file mode 100644 index 00000000..43f016fd --- /dev/null +++ b/client/src/ui/components/bd/UpdaterToggle.vue @@ -0,0 +1,28 @@ +/** + * BetterDiscord Updater Switch 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/UpdaterView.vue b/client/src/ui/components/bd/UpdaterView.vue index 6c24e7a3..e9457d9a 100644 --- a/client/src/ui/components/bd/UpdaterView.vue +++ b/client/src/ui/components/bd/UpdaterView.vue @@ -11,19 +11,22 @@ @@ -32,7 +35,8 @@ import { Globals, Updater } from 'modules'; import { ClientLogger as Logger } from 'common'; import SettingsWrapper from './SettingsWrapper.vue'; - import { FormButton } from '../common'; + import UpdaterToggle from './UpdaterToggle.vue'; + import UpdaterStatus from './UpdaterStatus.vue'; export default { data() { @@ -44,26 +48,29 @@ }, components: { SettingsWrapper, - FormButton + UpdaterToggle, + UpdaterStatus }, computed: { updatesAvailable() { return this.updater.updatesAvailable; }, newVersion() { - return this.updater.latestVersion; + return '2.0.0-beta.4'; }, error() { return this.updater.error; + }, + updates() { + return this.updater.updates; + }, + bdUpdates() { + return this.updater.bdUpdates; } }, methods: { - async install() { - this.updating = true; - try { - await this.updater.update(); - } catch (err) {} - this.updating = false; + update() { + this.updater.startUpdate(); } } } diff --git a/client/src/ui/components/bd/index.js b/client/src/ui/components/bd/index.js index 5744e2ad..29b20c86 100644 --- a/client/src/ui/components/bd/index.js +++ b/client/src/ui/components/bd/index.js @@ -4,5 +4,8 @@ export { default as CssEditorView } from './CssEditor.vue'; export { default as PluginsView } from './PluginsView.vue'; export { default as ThemesView } from './ThemesView.vue'; export { default as UpdaterView } from './UpdaterView.vue'; +export { default as UpdaterStatus } from './UpdaterStatus.vue'; +export { default as UpdaterToggle } from './UpdaterToggle.vue'; export { default as BdBadge } from './BdBadge.vue'; export { default as ConnectivityView } from './ConnectivityView.vue'; +export { default as SuperSecretView } from './SuperSecretView.vue'; diff --git a/client/webpack.base.config.js b/client/webpack.base.config.js index 1e266fc9..acd514f9 100644 --- a/client/webpack.base.config.js +++ b/client/webpack.base.config.js @@ -28,7 +28,6 @@ module.exports = { }, externals: { electron: 'require("electron")', - asar: 'require("asar")', fs: 'require("fs")', path: 'require("path")', util: 'require("util")', diff --git a/client/webpack.config.js b/client/webpack.config.js index 06f40f34..878cb51f 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -13,7 +13,10 @@ const config = { }, plugins: [ new webpack.NamedModulesPlugin() - ] + ], + externals: { + asar: 'require("asar")' + } }; module.exports = merge(baseconfig, config); diff --git a/client/webpack.production.config.js b/client/webpack.production.config.js index 57bc0555..620a1b53 100644 --- a/client/webpack.production.config.js +++ b/client/webpack.production.config.js @@ -15,7 +15,10 @@ const config = { new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true) }) - ] + ], + externals: { + sparkplug: 'require("./sparkplug")' + } }; module.exports = merge(baseconfig, config); diff --git a/common/modules/axi.js b/common/modules/axi.js new file mode 100644 index 00000000..0d215063 --- /dev/null +++ b/common/modules/axi.js @@ -0,0 +1,51 @@ +/** + * BetterDiscord axios wrapper + * 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 axios from 'axios'; + +export default class AxiosWrapper { + + static get axios() { return axios; } + + static get github() { + return this._github ? this._github : ( + this._github = { + main: this.create('https://github.com'), + api: this.create('https://api.github.com') + } + ); + } + + static get zl() { + return this._zl ? this._zl : (this._zl = { + api: this.create('https://zl', 1000, this.zlHeaders), + cdn: this.create('https://zl', 1000, this.zlHeaders) + }); + } + + static create(baseUrl, timeout = 1000, headers = null) { + return axios.create({ baseURL: baseUrl, timeout, headers: headers ? headers : this.defaultHeaders }); + } + + static get defaultHeaders() { + return { + 'User-Agent': 'BetterDiscordApp User' + }; + } + + static get zlHeaders() { + return { + 'User-Agent': 'BetterDiscordApp User', + 'X-ZL-Apikey': '1a20cce89a2dbd163fc9570f3246c20891e62b2818ada55f82fa3d1d96fa7ef4', + 'X-ZL-User': 'anonymous' + } + } + +} diff --git a/common/modules/common.js b/common/modules/common.js index 3ae581aa..96fe4b72 100644 --- a/common/modules/common.js +++ b/common/modules/common.js @@ -3,3 +3,4 @@ export { default as Filters } from './filters'; export { default as Logger, ClientLogger } from './logger'; export { default as ClientIPC } from './bdipc'; export { default as AsyncEventEmitter } from './async-eventemitter'; +export { default as Axi } from './axi'; diff --git a/core/package.json b/core/package.json index 74868db5..6bf2a7ac 100644 --- a/core/package.json +++ b/core/package.json @@ -2,7 +2,7 @@ "name": "bdcore", "description": "BetterDiscord core package", "author": "Jiiks", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "homepage": "https://betterdiscord.net", "license": "MIT", "main": "dist/main.js", diff --git a/core/src/csp.json b/core/src/csp.json new file mode 100644 index 00000000..60cda831 --- /dev/null +++ b/core/src/csp.json @@ -0,0 +1,25 @@ +{ + "img-src": [ + "https://cdn.betterttv.net", + "https://cdn.frankerfacez.com", + "https://i.imgur.com" + ], + "style-src": [ + "https://fonts.googleapis.com" + ], + "script-src": [ + "'sha256-fSHKdpQGCHaIqWP3SpJOuUHrLp49jy4dWHzZ/RBJ/p4='", + "'sha256-VFJcfKY5B3EBkFDgQnv3CozPwBlZcxwssfLVWlPFfZU='", + "'sha256-VzDmLZ4PxPkOS/KY7ITzLQsSWhfCnvUrNculcj8UNgE='", + "'sha256-l6K+77Z1cmldR9gIvaVWlboF/zr5MXCQHcsEHfnr5TU='" + ], + "connect-src": [ + "https://github.com", + "https://api.github.com", + "https://betterdiscord.net", + "https://api.betterdiscord.net", + "https://cdn.betterdiscord.net", + "https://api.supersecretbdapiandcdn.net", + "https://cdn.supersecretbdapiandcdn.net" + ] +} diff --git a/core/src/csp.txt b/core/src/csp.txt new file mode 100644 index 00000000..cac197d7 --- /dev/null +++ b/core/src/csp.txt @@ -0,0 +1,3 @@ +React Devtools: sha256-fSHKdpQGCHaIqWP3SpJOuUHrLp49jy4dWHzZ/RBJ/p4= +Vue Devtools: sha256-VFJcfKY5B3EBkFDgQnv3CozPwBlZcxwssfLVWlPFfZU= +Vue Detector: sha256-l6K+77Z1cmldR9gIvaVWlboF/zr5MXCQHcsEHfnr5TU= diff --git a/core/src/main.js b/core/src/main.js index 58cbfa66..18cd626a 100644 --- a/core/src/main.js +++ b/core/src/main.js @@ -8,11 +8,24 @@ * LICENSE file in the root directory of this source tree. */ +/*PRODUCTION*/ const TESTS = typeof PRODUCTION === 'undefined'; const TEST_ARGS = () => { const _basePath = path.resolve(__dirname, '..', '..'); - const _baseDataPath = path.resolve(_basePath, 'tests'); + const _baseDataPath = path.resolve(_basePath, 'tests'); + + const _corePkg = require(path.resolve(_basePath, 'core', 'package.json')); + const _clientPkg = require(path.resolve(_basePath, 'client', 'package.json')); + const _editorPkg = require(path.resolve(_basePath, 'editor', 'package.json')); + + const coreVersion = _corePkg.version; + const clientVersion = _clientPkg.version; + const editorVersion = _editorPkg.version; + return { + coreVersion, + clientVersion, + editorVersion, 'options': { 'autoInject': true, 'commonCore': true, @@ -26,7 +39,7 @@ const TEST_ARGS = () => { } } } -const TEST_EDITOR = true; +const TEST_EDITOR = TESTS && true; import path from 'path'; import sass from 'node-sass'; @@ -35,21 +48,14 @@ import deepmerge from 'deepmerge'; import ContentSecurityPolicy from 'csp-parse'; import keytar from 'keytar'; -import { FileUtils, BDIpc, Config, WindowUtils, CSSEditor, Editor, Database } from './modules'; +import { FileUtils, BDIpc, Config, WindowUtils, Updater, Editor, Database } from './modules'; const packageJson = require(path.resolve(__dirname, 'package.json')); const sparkplug = path.resolve(__dirname, 'sparkplug.js'); let configProxy; -const CSP = { - 'img-src': ['https://cdn.betterttv.net', 'https://cdn.frankerfacez.com'], - 'script-src': [ - `'sha256-fSHKdpQGCHaIqWP3SpJOuUHrLp49jy4dWHzZ/RBJ/p4='`, // React Devtools - `'sha256-VFJcfKY5B3EBkFDgQnv3CozPwBlZcxwssfLVWlPFfZU='`, // Vue Devtools - `'sha256-VzDmLZ4PxPkOS/KY7ITzLQsSWhfCnvUrNculcj8UNgE=' 'sha256-l6K+77Z1cmldR9gIvaVWlboF/zr5MXCQHcsEHfnr5TU='` // Vue Detector - ] -}; +const CSP = TESTS ? require('../src/csp.json') : require('./csp.json'); class Comms { constructor(bd) { @@ -195,6 +201,8 @@ export class BetterDiscord { get config() { return this._config ? this._config : (this._config = new Config(this._args)); } get window() { return this.windowUtils ? this.windowUtils.window : undefined; } get editor() { return this._editor ? this._editor : (this._editor = new Editor(this, this.config.getPath('editor'))); } + get updater() { return this._updater ? this._updater : (this._updater = new Updater(this)); } + get sendToDiscord() { return this.windowUtils.send; } constructor(args) { if (TESTS) args = TEST_ARGS(); @@ -209,13 +217,16 @@ export class BetterDiscord { this.config.compatibility(); this.bindings(); - this.parseClientPackage(); this.extraPaths(); + this.parseClientPackage(); + this.parseEditorPackage(); + this.parseCorePackage(); this.database.init(); configProxy = () => this.config; const autoInitComms = this.comms; const autoInitEditor = this.editor; + this.updater.start(); this.init(); } @@ -280,7 +291,7 @@ export class BetterDiscord { */ parseClientPackage() { const clientPath = this.config.getPath('client'); - const clientPkg = TESTS ? require(`${path.resolve(clientPath, '..')}/package.json`) :require(`${clientPath}/package.json`); + const clientPkg = TESTS ? require(`${path.resolve(clientPath, '..')}/package.json`) : require(`${clientPath}/package.json`); const { version } = clientPkg; const main = TESTS ? 'betterdiscord.client.js' : clientPkg.main; this.config.addPath('client_script', `${clientPath}/${main}`); @@ -288,6 +299,20 @@ export class BetterDiscord { console.log(`[BetterDiscord] Client v${this.config.clientVersion} - ${this.config.getPath('client_script')}`); } + parseCorePackage() { + const corePath = this.config.getPath('core'); + const corePkg = TESTS ? require(`${path.resolve(corePath, '..')}/package.json`) : require(`${corePath}/package.json`); + const { version } = corePkg; + this.config.setCoreVersion(version); + } + + parseEditorPackage() { + const editorPath = this.config.getPath('editor'); + const editorPkg = TESTS ? require(`${path.resolve(editorPath, '..')}/package.json`) : require(`${editorPath}/package.json`); + const { version } = editorPkg; + this.config.setEditorVersion(version); + } + /** * Add extra paths to config */ diff --git a/core/src/modules/axi.js b/core/src/modules/axi.js new file mode 100644 index 00000000..84023088 --- /dev/null +++ b/core/src/modules/axi.js @@ -0,0 +1,53 @@ +/** + * BetterDiscord axios wrapper + * 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 axios from 'axios'; + +export default class AxiosWrapper { + + static get axios() { return axios; } + + static get(url) { return axios.get(url) } + + static get github() { + return this._github ? this._github : ( + this._github = { + main: this.create('https://github.com'), + api: this.create('https://api.github.com') + } + ); + } + + static get zl() { + return this._zl ? this._zl : (this._zl = { + api: this.create('https://zl', 1000, this.zlHeaders), + cdn: this.create('https://zl', 1000, this.zlHeaders) + }); + } + + static create(baseUrl, timeout = 1000, headers = null) { + return axios.create({ baseURL: baseUrl, timeout, headers: headers ? headers : this.defaultHeaders }); + } + + static get defaultHeaders() { + return { + 'User-Agent': 'BetterDiscordApp User' + }; + } + + static get zlHeaders() { + return { + 'User-Agent': 'BetterDiscordApp User', + 'X-ZL-Apikey': '1a20cce89a2dbd163fc9570f3246c20891e62b2818ada55f82fa3d1d96fa7ef4', + 'X-ZL-User': 'anonymous' + } + } + +} diff --git a/core/src/modules/config.js b/core/src/modules/config.js index c81ba5de..43559729 100644 --- a/core/src/modules/config.js +++ b/core/src/modules/config.js @@ -16,12 +16,36 @@ export default class Config extends Module { return this.args.version; } + get versions() { + return { + core: this.coreVersion, + client: this.clientVersion, + editor: this.editorVersion + }; + } + + get coreVersion() { + return this.state.coreVersion; + } + get clientVersion() { - return this.args.clientVersion; + return this.state.clientVersion; + } + + get editorVersion() { + return this.state.editorVersion; } setClientVersion(clientVersion) { - this.args.clientVersion = clientVersion; + this.state.clientVersion = clientVersion; + } + + setCoreVersion(coreVersion) { + this.state.coreVersion = coreVersion; + } + + setEditorVersion(editorVersion) { + this.state.editorVersion = editorVersion; } get paths() { @@ -41,6 +65,7 @@ export default class Config extends Module { get config() { return { version: this.version, + versions: this.versions, paths: this.paths }; } diff --git a/core/src/modules/index.js b/core/src/modules/index.js index 4a56e948..2b98833e 100644 --- a/core/src/modules/index.js +++ b/core/src/modules/index.js @@ -4,3 +4,4 @@ export { default as Config } from './config'; export { default as CSSEditor } from './csseditor'; export { default as Editor } from './editor'; export { default as Database } from './database'; +export { default as Updater } from './updater'; diff --git a/core/src/modules/modulebase.js b/core/src/modules/modulebase.js index 5623e3e9..6a630548 100644 --- a/core/src/modules/modulebase.js +++ b/core/src/modules/modulebase.js @@ -11,6 +11,9 @@ /** * Base Module that every non-static module should extend. */ + +import { default as BDIpc } from './bdipc'; + export default class Module { constructor(args) { @@ -24,6 +27,7 @@ export default class Module { init() { if (this.bindings) this.bindings(); if (this.setInitialState) this.setInitialState(this.state); + if (this.events) this.events(BDIpc); } set args(t) {} diff --git a/core/src/modules/updater.js b/core/src/modules/updater.js new file mode 100644 index 00000000..4c82f032 --- /dev/null +++ b/core/src/modules/updater.js @@ -0,0 +1,287 @@ +/** + * BetterDiscord Updater Module + * Copyright (c) 2015-present JsSucks - https://github.com/JsSucks + * All rights reserved. + * 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. +*/ + + +import Module from './modulebase'; +import { FileUtils } from './utils'; +import semver from 'semver'; +import Axi from './axi'; +import zlib from 'zlib'; +import tarfs from 'tar-fs'; + +const TEST_UPDATE = [ + { + 'id': 'core', + 'version': '2.0.0-beta.5' + }, + { + 'id': 'client', + 'version': '2.0.0-beta.5' + }, + { + 'id': 'editor', + 'version': '0.4.1' + } +]; + +class ReleaseInfo { + + constructor(versions) { + this.versions = versions; + } + + get core() { + const f = this.files.find(f => f.id === 'core'); + f.upToDate = semver.satisfies(this.versions.core, `>=${f.version}`, { includePrerelease: true }); + f.currentVersion = this.versions.core; + return f; + } + + get client() { + const f = this.files.find(f => f.id === 'client'); + f.upToDate = semver.satisfies(this.versions.client, `>=${f.version}`, { includePrerelease: true }); + f.currentVersion = this.versions.client; + return f; + } + + get editor() { + const f = this.files.find(f => f.id === 'editor'); + f.upToDate = semver.satisfies(this.versions.editor, `>=${f.version}`, { includePrerelease: true }); + f.currentVersion = this.versions.editor; + return f; + } + + test() { + this.files = TEST_UPDATE; + } + +} + +export default class Updater extends Module { + + constructor(bd) { + super(); + this.bd = bd; + } + + bindings() { + this.checkForUpdates = this.checkForUpdates.bind(this); + this.checkForBdUpdates = this.checkForBdUpdates.bind(this); + this.updateAll = this.updateAll.bind(this); + this.updateFinished = this.updateFinished.bind(this); + this.start = this.start.bind(this); + } + + events(ipc) { + ipc.on('updater-startUpdate', (_, updates) => { + clearInterval(this.updaterThread); + this.updateAll(updates); + }); + ipc.on('debug-updater-forceUpdate', () => { + this.checkForUpdates(true); + }); + } + + async updateBd(update) { + try { + console.log('[BetterDiscord:Updater] Updating', update.id); + await this.downloadTarGz(`https://github.com/JsSucks/BetterDiscordApp${update.remote}`, this.bd.config.getPath('base')); + this.updateFinished(update); + // Cleanup + await FileUtils.rm(`${this.bd.config.getPath(update.id)}_old`); + } catch (err) { + console.log('[BetterDiscord:Updater] Failed to update', update.id); + console.log(err); + update.error = err; + this.bd.sendToDiscord('updater-updateError', update); + } + } + + async updateAll(updates) { + const bd = updates.bd || []; + const plugins = updates.plugins || []; + const themes = updates.themes || []; + const modules = updates.modules || []; + + this.restartRequired = this.reloadRequired = false; + this.finishedUpdates = 0; + this.totalUpdates = bd.length + plugins.length + themes.length + modules.length; + + const renamed = []; + // TODO cleaner + if (bd.length) { + for (const update of bd) { + try { + await FileUtils.rm(`${this.bd.config.getPath(update.id)}_old`); + // Try to rename dirs first + await FileUtils.rn(this.bd.config.getPath(update.id), `${this.bd.config.getPath(update.id)}_old`); + renamed.push({ 'old': this.bd.config.getPath(update.id), 'new': `${this.bd.config.getPath(update.id)}_old`}); + } catch (err) { + if (renamed.length) { + // Restore dirs + for (const r of renamed) { + await FileUtils.rn(r.new, r.old); + } + } + + throw err; + } + } + + for (const update of bd) { + this.updateBd(update); + } + } + + } + + updateFinished(update) { + if (update.id === 'core') this.restartRequired = true; + if (update.id === 'client') this.reloadRequired = true; + + console.log('[BetterDiscord:Updater] Finished updating', update.id); + this.bd.sendToDiscord('updater-updateFinished', update); + + this.finishedUpdates++; + if (this.finishedUpdates >= this.totalUpdates) { + this.bd.sendToDiscord('updater-updated', { restartRequired: this.restartRequired, reloadRequired: this.reloadRequired }); + } + } + + start(interval = 30) { + this.updaterThread = setInterval(this.checkForUpdates, interval * 60 * 1000); + } + + validate(releaseInfo) { + return releaseInfo && + typeof releaseInfo === 'object' && + releaseInfo.files && + Array.isArray(releaseInfo.files) && + releaseInfo.files.length >= 4; + } + + async latestRelease() { + try { + const release = await Axi.github.api.get('repos/JsSucks/BetterDiscordApp/releases/latest'); // TODO replace with config + const releaseInfoAsset = release.data.assets.find(asset => asset.name === 'releaseinfo.json'); + const releaseInfo = await Axi.get(releaseInfoAsset['browser_download_url']); + + if (this.validate(releaseInfo.data)) return releaseInfo.data; + return this.latestReleaseFallback(); + } catch (err) { + console.log(err); + return this.latestReleaseFallback(); + } + } + + async latestReleaseFallback() { + console.log('fallback'); + } + + async checkForBdUpdates(forced = false) { + try { + const { coreVersion, clientVersion, editorVersion } = this.bd.config; + const releaseInfo = new ReleaseInfo({ core: coreVersion, client: clientVersion, editor: editorVersion }); + + const latestRelease = await this.latestRelease(); + + if (forced) { + latestRelease.files = latestRelease.files.map(file => { + file.version = '10.0.0'; + return file; + }); + } + + releaseInfo.files = latestRelease.files; + + const updates = []; + + const { core, client, editor } = releaseInfo; + if (!core.upToDate) updates.push(core); + if (!client.upToDate) updates.push(client); + if (!editor.upToDate) updates.push(editor); + + return updates; + + } catch (err) { + console.log('[BetterDiscord:Updater]', err); + return []; + } + } + + async checkForUpdates(forced = false) { + console.log('[BetterDiscord:Updater] Checking for updates'); + this.bd.sendToDiscord('updater-checkForUpdates', ''); + + try { + const bd = await this.checkForBdUpdates(forced); + const updates = { bd, haveUpdates: false }; + + if (bd.length) updates.haveUpdates = true; + + if (!updates.haveUpdates) { + this.bd.sendToDiscord('updater-noUpdates', ''); + return true; + } + + this.bd.sendToDiscord('updater-updatesAvailable', updates); + + return true; + + } catch (err) { + console.log('[BetterDiscord:Updater]', err); + this.bd.sendToDiscord('updater-error', err); + return 'err'; + } + } + + async downloadTarGz(url, dest, responseType = 'stream', headers = null) { + try { + const stream = await Axi.axios({ + url, + type: 'GET', + responseType, + headers: headers || + { + 'Content-Type': 'application/octet-stream', + 'Accept': 'application/octet-stream' + } + }); + + return new Promise((resolve, reject) => { + stream.data.pipe(zlib.createGunzip()).pipe(tarfs.extract(dest)).on('finish', resolve).on('error', reject); + }); + } catch (err) { + throw err; + } + } + + debug(releaseInfo) { + const { core, client, editor } = releaseInfo; + if (!core.upToDate) { + console.log(`[BetterDiscord:Updater] Core update available: ${core.currentVersion} > ${core.version}`); + } else { + console.log(`[BetterDiscord:Updater] Core up to date: ${core.currentVersion} = ${core.version}`); + } + + if (!client.upToDate) { + console.log(`[BetterDiscord:Updater] Client update available: ${client.currentVersion} > ${client.version}`); + } else { + console.log(`[BetterDiscord:Updater] Client up to date: ${client.currentVersion} = ${client.version}`); + } + + if (!editor.upToDate) { + console.log(`[BetterDiscord:Updater] Editor update available: ${editor.currentVersion} > ${editor.version}`); + } else { + console.log(`[BetterDiscord:Updater] Editor up to date: ${editor.currentVersion} = ${editor.version}`); + } + } + +} diff --git a/csseditor/package.json b/csseditor/package.json deleted file mode 100644 index 1692bb58..00000000 --- a/csseditor/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "bdcsseditor", - "description": "BetterDiscord css editor package", - "author": "Jiiks", - "version": "0.4.0", - "homepage": "https://betterdiscord.net", - "license": "MIT", - "main": "dist/csseditor.js", - "contributors": [ - "Jiiks", - "Pohky" - ], - "repository": { - "type": "git", - "url": "https://github.com/JsSucks/BetterDiscordApp.git" - }, - "private": false, - "scripts": { - "build": "webpack --progress --colors", - "watch": "webpack --progress --colors --watch", - "release": "webpack --progress --colors --config=webpack.production.config.js" - } -} diff --git a/csseditor/src/Editor.vue b/csseditor/src/Editor.vue deleted file mode 100644 index e6b8324c..00000000 --- a/csseditor/src/Editor.vue +++ /dev/null @@ -1,191 +0,0 @@ - - - diff --git a/csseditor/src/index.js b/csseditor/src/index.js deleted file mode 100644 index 9146bd05..00000000 --- a/csseditor/src/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// const styles = require('./styles/index.scss'); - -import Vue from 'vue'; -import VueCodemirror from 'vue-codemirror'; - -import Editor from './Editor.vue'; -import styles from './styles/index.scss'; - -Vue.use(VueCodemirror, {}); - -window.cmCommands = VueCodemirror.CodeMirror.commands; - -const mount = document.createElement('div'); -mount.classList.add('container'); -document.body.appendChild(mount); - -const vue = new Vue({ - el: mount, - components: { Editor }, - template: '' -}); - -const style = document.createElement('style'); -style.id = 'bd-main'; -style.type = 'text/css'; -style.appendChild(document.createTextNode(styles)); -document.head.appendChild(style); diff --git a/csseditor/src/styles/codemirror.scss b/csseditor/src/styles/codemirror.scss deleted file mode 100644 index b945ac14..00000000 --- a/csseditor/src/styles/codemirror.scss +++ /dev/null @@ -1,105 +0,0 @@ -.CodeMirror-scroll { - cursor: text; -} - -.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler { - background: #38444a; -} - -.CodeMirror-overlayscroll-horizontal div, -.CodeMirror-overlayscroll-vertical div { - background: rgb(41, 43, 47); -} - -.CodeMirror-overlayscroll-horizontal, -.CodeMirror-overlayscroll-horizontal div { - height: 10px; -} - -.CodeMirror-overlayscroll-vertical, -.CodeMirror-overlayscroll-vertical div { - width: 10px; -} - -.CodeMirror-scrollbar-filler { - width: 10px; - height: 10px; - background: rgb(41, 43, 47); -} - -.cm-s-material.CodeMirror { - background: #36393f; -} - -.CodeMirror-scroll { - cursor: text; -} - -.cm-s-material .CodeMirror-gutters { - background: #292b2f; -} - -.CodeMirror-gutter { - min-width: 34px; - border-right: 1px solid hsla(218,5%,47%,.3); - cursor: default; -} - -.CodeMirror-hints { - /*background: #1e262a;*/ - background: #292b2f; - box-shadow: 2px 3px 5px rgba(4, 4, 4, 0.22); - border: 1px solid #262f33; - - &::-webkit-scrollbar { - background: transparent; - } - - &::-webkit-scrollbar-thumb { - background-color: rgba(0,0,0,.4); - border-color: transparent; - } - - &::-webkit-scrollbar-thumb, - &::-webkit-scrollbar-track { - background-clip: padding-box; - border-width: 3px; - border-style: solid; - border-radius: 7px; - } - - &::-webkit-scrollbar-track { - background-color: transparent; - border-color: transparent; - } -} - -.CodeMirror-linenumber, -.CodeMirror-line { - padding: 0 5px !important; -} - -.CodeMirror-linenumber { - cursor: text; -} - -.cm-s-material .CodeMirror-linenumber { - color: #f6f6f7; -} - -.CodeMirror-hint { - color: #bac9d2; -} - -li.CodeMirror-hint-active { - color: #bac9d2; - /*background: #3b4950;*/ - background: #36393f; -} - -.CodeMirror-dialog-top { - bottom: 0; - top: auto; - border: none; - background: #1e262a; -} diff --git a/csseditor/src/styles/editor.scss b/csseditor/src/styles/editor.scss deleted file mode 100644 index a46844dc..00000000 --- a/csseditor/src/styles/editor.scss +++ /dev/null @@ -1,17 +0,0 @@ -.editor { - display: flex; - flex-direction: column; - flex-grow: 1; - overflow: hidden; - - .vue-codemirror { - display: flex; - flex-direction: column; - flex-grow: 1; - overflow: hidden; - - &, & .CodeMirror { - flex-grow: 1; - } - } -} diff --git a/csseditor/src/styles/images.scss b/csseditor/src/styles/images.scss deleted file mode 100644 index 202ab708..00000000 --- a/csseditor/src/styles/images.scss +++ /dev/null @@ -1,2 +0,0 @@ -$logoSmallGw: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkltYWdlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDUxMiA1MTI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGUgdHlwZT0idGV4dC9jc3MiPi5zdDB7ZGlzcGxheTpub25lO30uc3Qxe2Rpc3BsYXk6aW5saW5lO2ZpbGw6IzAyMDAzNTtzdHJva2U6IzAwMDAwMDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9LnN0MntmaWxsOiMzRUNDOUU7fS5zdDN7ZmlsbDojRkZGRkZGO308L3N0eWxlPjxnIGlkPSJMYXllcl8yIiBjbGFzcz0ic3QwIj48cmVjdCB4PSItNjQiIHk9Ii0zMiIgY2xhc3M9InN0MSIgd2lkdGg9IjYxOCIgaGVpZ2h0PSI1NzIiLz48L2c+PGcgaWQ9IkxheWVyXzEiIHhtbG5zOnZlY3Rvcm5hdG9yPSJodHRwOi8vdmVjdG9ybmF0b3IuaW8iPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik03MCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3YyMzMuNkM0Mi43LDM5Ny43LDEzNy45LDQ5MywyNTYsNDkzYzI5LjcsMCw1OC02LjEsODMuNi0xN1YzNDEuNWMtMTksMjUuNi00OS4zLDQyLjItODMuNiw0Mi4yYy01Ny42LDAtMTA0LjEtNDYuNS0xMDQuMS0xMDQuMVY0Ni4xYzAtMTMuNy0xMy43LTI3LjMtMjcuMy0yNy4zSDcweiIvPjxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0zODcuNCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3Y0Ny4zQzMyOS4zLDc2LjIsMjkzLjksNjYuMywyNTYsNjYuM2MtMjkuOCwwLTU3LjksNi4zLTgzLjYsMTcuM3YxMzQuMmMxOS0yNS42LDQ5LjMtNDIuMiw4My42LTQyLjJjNTcuNiwwLDEwNC4xLDQ2LjUsMTA0LjEsMTA0LjF2MTg2LjJjNjUuMi0zNi40LDEwOS4yLTEwNiwxMDkuMi0xODYuMlY0Ni4xYzAtMTguOC0xMy43LTI3LjMtMjcuMy0yNy4zSDM4Ny40eiIvPjwvZz48L3N2Zz4=); -$bdicon: $logoSmallGw; diff --git a/csseditor/src/styles/index.scss b/csseditor/src/styles/index.scss deleted file mode 100644 index a3ed0e36..00000000 --- a/csseditor/src/styles/index.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import '../../../node_modules/codemirror/lib/codemirror.css'; -@import '../../../node_modules/codemirror/theme/material.css'; -@import '../../../node_modules/codemirror/addon/scroll/simplescrollbars.css'; -@import '../../../node_modules/codemirror/addon/dialog/dialog.css'; -@import '../../../node_modules/codemirror/addon/hint/show-hint.css'; - -@import './images.scss'; -@import './main.scss'; -@import './titlebar.scss'; -@import './spinner.scss'; -@import './editor.scss'; -@import './tools.scss'; -@import './codemirror.scss'; diff --git a/csseditor/src/styles/main.scss b/csseditor/src/styles/main.scss deleted file mode 100644 index 20c89ea8..00000000 --- a/csseditor/src/styles/main.scss +++ /dev/null @@ -1,36 +0,0 @@ -html, body { - margin: 0; - padding: 0; - max-height: 100%; - height: 100%; - background: #2c383e; - min-width: 700px; - min-height: 400px; -} - -* { - outline: none; -} - -.flex-spacer { - flex-grow: 1; -} - -.flex-row { - display: flex; - flex-direction: row; -} - -.valign { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); -} - -.container { - display: flex; - flex-grow: 1; - flex-direction: column; - height: 100%; -} diff --git a/csseditor/src/styles/spinner.scss b/csseditor/src/styles/spinner.scss deleted file mode 100644 index 97acdd91..00000000 --- a/csseditor/src/styles/spinner.scss +++ /dev/null @@ -1,14 +0,0 @@ -#spinner { - background: rgba(51, 48, 48, 0.41); - position: absolute; - top: 34px; - left: 0; - right: 0; - bottom: 0; - color: #bac9d2; - font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif; - font-weight: 600; - font-size: 2em; - z-index: 90000; - user-select: none; -} diff --git a/csseditor/src/styles/titlebar.scss b/csseditor/src/styles/titlebar.scss deleted file mode 100644 index b837087a..00000000 --- a/csseditor/src/styles/titlebar.scss +++ /dev/null @@ -1,71 +0,0 @@ -.titlebar { - display: flex; - height: 25px; - padding: 4px 5px; - background: #292b2f; - border-bottom: 1px solid hsla(218,5%,47%,.3); - user-select: none; - cursor: default; - - .icon { - width: 31px; - height: 25px; - - .inner { - width: 25px; - height: 25px; - background-image: $bdicon; - background-size: 22px 22px; - background-repeat: no-repeat; - background-position: center; - } - } - - .title { - color: #bac9d2; - font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif; - line-height: 25px; - font-size: 15px; - } - - .controls { - margin: 0 0 0 2px; - font-size: 0; - - button { - -webkit-app-region: no-drag; - border-radius: 3px; - width: 25px; - font-size: 12px; - font-weight: 600; - background: #36393f; - color: #bac9d2; - font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif; - transition: background-color .2s ease, color .2s ease; - cursor: default; - border: 0; - height: 25px; - z-index: 900062; - padding: 0; - margin: 0 0 0 4px; - - &:hover { - background: #44474e; - color: #FFF; - } - - &.active { - background: #3a71c1; - } - } - } - - .draggable { - top: 0; - left: 0; - right: 63px; - position: absolute; - height: 33px; - -webkit-app-region: drag; - } -} diff --git a/csseditor/src/styles/tools.scss b/csseditor/src/styles/tools.scss deleted file mode 100644 index 2a4ae589..00000000 --- a/csseditor/src/styles/tools.scss +++ /dev/null @@ -1,66 +0,0 @@ -.parser-error { - padding: 4px 6px; - background: #292b2f; - border-top: 1px solid hsla(218,5%,47%,.3); - color: #d84040; - font-family: monospace; - white-space: pre-wrap; - font-size: 12px; -} - -.tools { - height: 36px; - background: #292b2f; - border-top: 1px solid hsla(218,5%,47%,.3); - display: flex; - flex-direction: column; - user-select: none; - - .flex-row { - flex-grow: 1; - padding: 4px 5px; - } - - button { - border-radius: 3px; - width: 100px; - padding: 3px 10px; - font-size: 12px; - font-weight: 600; - background: #36393f; - color: #bac9d2; - font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif; - transition: background-color .2s ease, color .2s ease; - cursor: pointer; - border: 0; - margin-right: 4px; - flex: 0 0 auto; - - &:hover { - background: #44474e; - color: #fff; - } - } - - #chkboxLiveUpdate { - padding: 3px 10px; - line-height: 22px; - flex: 0 0 auto; - - label { - cursor: pointer; - } - - input[type="checkbox"] { - margin: 0 6px 0 0; - cursor: pointer; - } - - span { - font-size: 12px; - font-weight: 500; - color: #bac9d2; - font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif; - } - } -} diff --git a/csseditor/webpack.config.js b/csseditor/webpack.config.js deleted file mode 100644 index 67f86166..00000000 --- a/csseditor/webpack.config.js +++ /dev/null @@ -1,43 +0,0 @@ -const path = require('path'); -const VueLoaderPlugin = require('vue-loader/lib/plugin'); - -const vueLoader = { - test: /\.(vue)$/, - exclude: /node_modules/, - use: 'vue-loader' -}; - -const scssLoader = { - test: /\.(css|scss)$/, - use: ['css-loader', 'sass-loader'] -}; - -module.exports = { - entry: './src/index.js', - mode: 'development', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'csseditor.js' - }, - module: { - rules: [vueLoader, scssLoader] - }, - externals: { - electron: 'window.require("electron")', - fs: 'window.require("fs")', - util: 'window.require("util")', - process: 'require("process")' - }, - resolve: { - alias: { - vue$: path.resolve('..', 'node_modules', 'vue', 'dist', 'vue.esm.js') - }, - modules: [ - path.resolve('..', 'node_modules'), - path.resolve('..', 'common', 'modules') - ] - }, - plugins: [ - new VueLoaderPlugin() - ] -}; diff --git a/csseditor/webpack.production.config.js b/csseditor/webpack.production.config.js deleted file mode 100644 index 780c7111..00000000 --- a/csseditor/webpack.production.config.js +++ /dev/null @@ -1,47 +0,0 @@ -const path = require('path'); -const webpack = require('webpack'); -const VueLoaderPlugin = require('vue-loader/lib/plugin'); - -const vueLoader = { - test: /\.(vue)$/, - exclude: /node_modules/, - use: 'vue-loader' -}; - -const scssLoader = { - test: /\.(css|scss)$/, - use: ['css-loader', 'sass-loader'] -}; - -module.exports = { - entry: './src/index.js', - mode: 'production', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'csseditor-release.js' - }, - module: { - rules: [vueLoader, scssLoader] - }, - externals: { - electron: 'window.require("electron")', - fs: 'window.require("fs")', - util: 'window.require("util")', - process: 'require("process")' - }, - resolve: { - alias: { - vue$: path.resolve('..', 'node_modules', 'vue', 'dist', 'vue.esm.js') - }, - modules: [ - path.resolve('..', 'node_modules'), - path.resolve('..', 'common', 'modules') - ] - }, - plugins: [ - new webpack.DefinePlugin({ - PRODUCTION: JSON.stringify(true) - }), - new VueLoaderPlugin() - ] -}; diff --git a/editor/package.json b/editor/package.json index 0e692209..c60c3397 100644 --- a/editor/package.json +++ b/editor/package.json @@ -5,7 +5,7 @@ "version": "0.4.0", "homepage": "https://betterdiscord.net", "license": "MIT", - "main": "dist/csseditor.js", + "main": "dist/editor.js", "contributors": [ "Jiiks", "Pohky" diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 10b89c8b..1f1c3332 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -4,6 +4,7 @@ import del from 'del'; import copy from 'gulp-copy'; import rename from 'gulp-rename'; import inject from 'gulp-inject-string'; +import replace from 'gulp-replace'; import copydeps from './scripts/copydeps'; import file from 'gulp-file'; import editjson from 'gulp-json-editor'; @@ -14,10 +15,10 @@ import editorpkg from './editor/package'; // core-release > -gulp.task('core-main', function () { +gulp.task('core-main', function() { return pump([ gulp.src('core/dist/main.js'), - inject.after(`'use strict';\n`, 'const PRODUCTION = true;\n'), + replace('/*PRODUCTION*/', 'const PRODUCTION = true;'), rename(`core.${corepkg.version}.js`), gulp.dest('release/core') ]); @@ -36,27 +37,34 @@ gulp.task('core-pkg', function() { ]); }); -gulp.task('core-modules', function () { +gulp.task('core-modules', function() { return pump([ gulp.src('core/dist/modules/**/*'), copy('release/core', { prefix: 2 }) ]); }); -gulp.task('core-sparkplug', function () { +gulp.task('core-sparkplug', function() { return pump([ gulp.src('core/dist/sparkplug.js'), gulp.dest('release/core') ]); }); -gulp.task('core-release', gulp.parallel('core-main', 'core-pkg', 'core-sparkplug', 'core-modules')); +gulp.task('core-extras', function() { + return pump([ + gulp.src(['core/src/csp.json']), + gulp.dest('release/core') + ]); +}); + +gulp.task('core-release', gulp.parallel('core-main', 'core-pkg', 'core-sparkplug', 'core-modules', 'core-extras')); // < core-release // client -gulp.task('client-main', function () { +gulp.task('client-main', function() { return pump([ gulp.src('client/dist/*.client-release.js'), rename(`client.${clientpkg.version}.js`), @@ -76,7 +84,7 @@ gulp.task('client-pkg', function() { ]); }); -gulp.task('client-sparkplug', function () { +gulp.task('client-sparkplug', function() { return pump([ gulp.src('core/dist/sparkplug.js'), gulp.dest('release/client') @@ -87,7 +95,7 @@ gulp.task('client-release', gulp.parallel('client-main', 'client-pkg', 'client-s // Editor -gulp.task('editor-main', function () { +gulp.task('editor-main', function() { return pump([ gulp.src('editor/dist/editor.release.js'), rename(`editor.${editorpkg.version}.js`), @@ -95,10 +103,10 @@ gulp.task('editor-main', function () { ]); }); -gulp.task('editor-pkg', function () { +gulp.task('editor-pkg', function() { return pump([ gulp.src('editor/package.json'), - editjson(function (pkg) { + editjson(function(pkg) { pkg.main = `editor.${editorpkg.version}.js`; delete pkg.scripts; return pkg; @@ -118,18 +126,18 @@ gulp.task('node-modules', function() { ]); }); -gulp.task('node-sass-bindings', gulp.series(function () { +gulp.task('node-sass-bindings', gulp.series(function() { return del(['release/node_modules/node-sass/vendor']); -}, function () { +}, function() { return pump([ gulp.src('other/node_sass_bindings/**/*'), copy('release/core/node_modules/node-sass/vendor', { prefix: 2 }) ]); })); -gulp.task('keytar-bindings', gulp.series(function () { +gulp.task('keytar-bindings', gulp.series(function() { return del(['release/node_modules/keytar/build']); -}, function () { +}, function() { return pump([ gulp.src('other/keytar/**/*'), copy('release/core/node_modules/keytar/build/Release', { prefix: 2 }) @@ -144,4 +152,4 @@ gulp.task('del-release', function() { gulp.task('dependencies', gulp.series('node-modules', gulp.parallel('node-sass-bindings', 'keytar-bindings'))); gulp.task('build-release', gulp.parallel('core-release', 'client-release', 'editor-release', 'dependencies')); -gulp.task('release', gulp.series('del-release', 'build-release')); \ No newline at end of file +gulp.task('release', gulp.series('del-release', 'build-release')); diff --git a/other/keytar/keytar.node/keytar-4.4.1/win32-ia32-69.node b/other/keytar/keytar.node/keytar-4.4.1/win32-ia32-69.node new file mode 100644 index 00000000..6d726e46 Binary files /dev/null and b/other/keytar/keytar.node/keytar-4.4.1/win32-ia32-69.node differ diff --git a/other/node_sass_bindings/win32-ia32-69/binding.node b/other/node_sass_bindings/win32-ia32-69/binding.node new file mode 100644 index 00000000..3dfbc1e2 Binary files /dev/null and b/other/node_sass_bindings/win32-ia32-69/binding.node differ diff --git a/package-lock.json b/package-lock.json index facf7bc9..e198080c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "betterdiscord", - "version": "2.0.0-beta", + "version": "2.0.0-beta.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1583,6 +1583,15 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" + } + }, "babel-loader": { "version": "8.0.5", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz", @@ -1776,6 +1785,12 @@ "underscore": "~1.4.4" } }, + "binaryextensions": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.2.tgz", + "integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==", + "dev": true + }, "bl": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", @@ -3022,6 +3037,12 @@ "object.defaults": "^1.1.0" } }, + "easy-stack": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.0.tgz", + "integrity": "sha1-EskbMIWjfwuqM26UhurEv5Tj54g=", + "dev": true + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3031,6 +3052,12 @@ "safer-buffer": "^2.1.0" } }, + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", + "dev": true + }, "editorconfig": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.2.tgz", @@ -3706,6 +3733,12 @@ "es5-ext": "~0.10.14" } }, + "event-pubsub": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", + "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", + "dev": true + }, "event-stream": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", @@ -4188,6 +4221,29 @@ "readable-stream": "^2.3.6" } }, + "follow-redirects": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", + "requires": { + "debug": "^3.2.6" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -5343,6 +5399,17 @@ "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", "dev": true }, + "gulp-replace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", + "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", + "dev": true, + "requires": { + "istextorbinary": "2.2.1", + "readable-stream": "^2.0.1", + "replacestream": "^4.0.0" + } + }, "gulp-watch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.1.tgz", @@ -6396,6 +6463,17 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "dev": true, + "requires": { + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" + } + }, "jquery": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", @@ -6438,6 +6516,21 @@ "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", "dev": true }, + "js-message": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz", + "integrity": "sha1-IwDSSxrwjondCVvBpMnJz8uJLRU=", + "dev": true + }, + "js-queue": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.0.tgz", + "integrity": "sha1-NiITz4YPRo8BJfxslqvBdCUx+Ug=", + "dev": true, + "requires": { + "easy-stack": "^1.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6757,6 +6850,12 @@ "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", "dev": true }, + "lodash.endswith": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.endswith/-/lodash.endswith-4.2.1.tgz", + "integrity": "sha1-/tWawXOO0+I27dcGTsRWRIs3vAk=", + "dev": true + }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", @@ -7355,6 +7454,17 @@ } } }, + "node-ipc": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.1.1.tgz", + "integrity": "sha512-FAyICv0sIRJxVp3GW5fzgaf9jwwRQxAKDJlmNFUL5hOy+W4X/I5AypyHoq0DXXbo9o/gt79gj++4cMr4jVWE/w==", + "dev": true, + "requires": { + "event-pubsub": "4.3.0", + "js-message": "1.0.5", + "js-queue": "2.0.0" + } + }, "node-libs-browser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", @@ -7908,6 +8018,59 @@ "readable-stream": "^2.1.5" } }, + "parallel-webpack": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/parallel-webpack/-/parallel-webpack-2.3.0.tgz", + "integrity": "sha512-RCIDF+YOqyAJeM8NumtOQ8JYjUXexDRIN4slFNfvUp1RxLB1zLeLZMAwlP6s7l9LhuR5xJ2pv8ckIsdESzSqog==", + "dev": true, + "requires": { + "ajv": "^4.9.2", + "bluebird": "^3.0.6", + "chalk": "^1.1.1", + "interpret": "^1.0.1", + "lodash.assign": "^4.0.8", + "lodash.endswith": "^4.0.1", + "lodash.flatten": "^4.2.0", + "minimist": "^1.2.0", + "node-ipc": "^9.1.0", + "pluralize": "^1.2.1", + "supports-color": "^3.1.2", + "worker-farm": "^1.3.1" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, "param-case": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", @@ -8347,6 +8510,28 @@ "end-of-stream": "^1.1.0", "once": "^1.3.1" } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } } } }, @@ -8473,7 +8658,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -8849,6 +9033,17 @@ "remove-trailing-separator": "^1.1.0" } }, + "replacestream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + } + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -10105,23 +10300,44 @@ } }, "tar-fs": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", - "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz", + "integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==", "requires": { - "chownr": "^1.0.1", + "chownr": "^1.1.1", "mkdirp": "^0.5.1", - "pump": "^1.0.0", - "tar-stream": "^1.1.2" + "pump": "^3.0.0", + "tar-stream": "^2.0.0" }, "dependencies": { - "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "bl": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", + "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "readable-stream": "^3.0.1" + } + }, + "readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "tar-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.0.1.tgz", + "integrity": "sha512-I6OJF7wE62BC6zNPdHDtseK0D0187PBjbKSLYY4ffvVkBM6tyBn2O9plDvVM2229/mozfEL/X3++qSvYYQE2xw==", + "requires": { + "bl": "^3.0.0", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" } } } @@ -10264,6 +10480,12 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "textextensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz", + "integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==", + "dev": true + }, "throttleit": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", diff --git a/package.json b/package.json index fb89baa6..f16a6191 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "betterdiscord", "description": "BetterDiscord", "author": "Jiiks", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "homepage": "https://betterdiscord.net", "license": "MIT", "main": "core/dist/main.js", @@ -17,6 +17,7 @@ "private": false, "dependencies": { "asar": "^1.0.0", + "axios": "^0.18.0", "chokidar": "^2.1.2", "csp-parse": "github:macropodhq/csp-parse", "deepmerge": "^3.2.0", @@ -24,7 +25,9 @@ "keytar": "^4.4.1", "nedb": "^1.8.0", "node-sass": "^4.11.0", - "original-fs": "^1.0.0" + "original-fs": "^1.0.0", + "semver": "^5.6.0", + "tar-fs": "^2.0.0" }, "devDependencies": { "@babel/core": "^7.3.4", @@ -51,6 +54,7 @@ "gulp-inject-string": "^1.1.2", "gulp-json-editor": "^2.5.1", "gulp-rename": "^1.4.0", + "gulp-replace": "^1.0.0", "gulp-watch": "^5.0.1", "hash-files": "^1.1.1", "html-webpack-plugin": "^3.2.0", @@ -58,6 +62,7 @@ "lodash": "^4.17.11", "mkdirp": "^0.5.1", "node-gyp": "^3.8.0", + "parallel-webpack": "^2.3.0", "pump": "^3.0.0", "request-promise-native": "1.0.5", "sass-lint": "^1.12.1", @@ -82,6 +87,8 @@ "watch_core": "npm run watch --prefix core", "build_editor": "npm run build --prefix editor", "watch_editor": "npm run watch --prefix editor", + "build_all": "parallel-webpack --progress --colors --config=webpack.all.config.js", + "watch_all": "parallel-webpack --progress --colors --watch --config=webpack.all.config.js", "lint": "eslint -f unix client/src core/src editor/src common && npm run sasslint", "lint_fix": "eslint -f unix client/src core/src", "sasslint": "sass-lint client/src/styles/**/*.scss -v", @@ -91,7 +98,8 @@ "package_release": "node scripts/package-release.js", "gulp_release": "gulp release", "release": "npm run lint && npm run build_release && gulp release && npm run package_release", - "update_release": "npm run build_release && gulp build-release", + "release_test": "npm run build_release && gulp release", + "update_release": "npm run build_release && gulp release", "inject": "node scripts/inject.js" } } diff --git a/scripts/package-release.js b/scripts/package-release.js index f69db474..de13c9a3 100644 --- a/scripts/package-release.js +++ b/scripts/package-release.js @@ -53,6 +53,7 @@ async function archiveCore(out = './release/core.tar.gz') { coreArchive.file('./release/core/package.json', { name: 'core/package.json' }); coreArchive.file('./release/core/index.js', { name: 'core/index.js' }); coreArchive.file(`./release/core/${mainFn}`, { name: `core/${mainFn}` }); + coreArchive.file('./release/core/csp.json', { name: 'core/csp.json' }); coreArchive.file('./release/core/sparkplug.js', { name: 'core/sparkplug.js' }); coreArchive.directory('./release/core/modules', 'core/modules'); coreArchive.directory('./release/core/node_modules', 'core/node_modules'); diff --git a/webpack.all.config.js b/webpack.all.config.js new file mode 100644 index 00000000..b66dc79a --- /dev/null +++ b/webpack.all.config.js @@ -0,0 +1,28 @@ +const path = require('path'); + +const editor = require('./editor/webpack.config'); + +editor.output.path = path.resolve('editor', 'dist'); +editor.entry = path.resolve('editor', editor.entry); +editor.resolve.alias['vue$'] = path.resolve('node_modules', 'vue', 'dist', 'vue.esm.js'); +editor.resolve.modules = [ + path.resolve('node_modules'), + path.resolve('common', 'modules') +]; + +const client = require('./client/webpack.config'); + +client.output.path = path.resolve('client', 'dist'); +client.entry = path.resolve('client', client.entry); +client.resolve.alias['vue$'] = path.resolve('node_modules', 'vue', 'dist', 'vue.esm.js'); +client.resolve.modules = [ + path.resolve('node_modules'), + path.resolve('common', 'modules'), + path.resolve('client', 'src', 'modules'), + path.resolve('client', 'src', 'ui'), + path.resolve('client', 'src', 'plugins'), + path.resolve('client', 'src', 'structs'), + path.resolve('client', 'src', 'builtin') +]; + +module.exports = [editor, client];