Merge pull request #30 from JsSucks/csseditor

Merge current css editor
This commit is contained in:
Alexei Stukov 2018-01-21 11:18:29 +02:00 committed by GitHub
commit d57b394768
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1000 additions and 5 deletions

View File

@ -11,7 +11,7 @@
'use strict'; 'use strict';
const styles = require('./styles/index.scss'); const styles = require('./styles/index.scss');
const { Global, Logger, Utils, PluginManager, BDIpc, WebpackModules, SocketProxy, Events } = require('./modules'); const { Global, Logger, Utils, PluginManager, BDIpc, WebpackModules, SocketProxy, Events, CssEditor } = require('./modules');
//const { UI } = require('./modules/ui/index.jsx'); //const { UI } = require('./modules/ui/index.jsx');
class BetterDiscord { class BetterDiscord {
@ -19,6 +19,7 @@ class BetterDiscord {
constructor() { constructor() {
window.bdUtils = Utils; window.bdUtils = Utils;
window.wpm = WebpackModules; window.wpm = WebpackModules;
window.cssEditor = CssEditor;
Events.on('global-ready', e => { Events.on('global-ready', e => {
const { UI } = require('./modules/ui/vueui.js'); const { UI } = require('./modules/ui/vueui.js');
this.ui = new UI(); this.ui = new UI();

View File

@ -11,6 +11,9 @@
const { ipcRenderer } = require('electron'); const { ipcRenderer } = require('electron');
class BDIpc { class BDIpc {
static on(channel, cb) {
ipcRenderer.on(channel, (event, message) => cb(event, message));
}
static async send(channel, message) { static async send(channel, message) {
channel = channel.startsWith('bd-') ? channel : `bd-${channel}`; channel = channel.startsWith('bd-') ? channel : `bd-${channel}`;

View File

@ -0,0 +1,34 @@
/**
* BetterDiscord CSS Editor
* 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.
*/
const { Module } = require('./modulebase');
const { BDIpc } = require('./bdipc');
const $ = require('jquery');
class CssEditor extends Module {
setInitialState() {
this.state = {
css: ''
}
this.customcss = $('<style id="customcss">').appendTo("head");
window.cssEditor = this;
BDIpc.on("bd-update-css", (_, css) => this.customcss.text(css));
BDIpc.on("bd-save-css", (_, css) => this.setState({css}));
}
show() {
BDIpc.send('openCssEditor', {}).then(() => BDIpc.send('setCss', {css: this.state.css}));
}
}
const _instance = new CssEditor();
module.exports = { 'CssEditor': _instance }

View File

@ -5,4 +5,5 @@ export { Pluging } from './core/plugin';
export { BDIpc } from './core/bdipc'; export { BDIpc } from './core/bdipc';
export { WebpackModules } from './core/webpackmodules'; export { WebpackModules } from './core/webpackmodules';
export { Events } from './core/events'; export { Events } from './core/events';
export { SocketProxy } from './core/discordsocket'; export { SocketProxy } from './core/discordsocket';
export { CssEditor } from './core/csseditor';

View File

@ -23,7 +23,7 @@ const __DEV = {
const __pluginPath = path.resolve(__dirname, '..', '..', 'tests', 'plugins'); const __pluginPath = path.resolve(__dirname, '..', '..', 'tests', 'plugins');
const __themePath = path.resolve(__dirname, '..', '..', 'tests', 'themes'); const __themePath = path.resolve(__dirname, '..', '..', 'tests', 'themes');
const { Utils, FileUtils, BDIpc, Config, WindowUtils } = require('./modules'); const { Utils, FileUtils, BDIpc, Config, WindowUtils, CSSEditor } = require('./modules');
const { BrowserWindow } = require('electron'); const { BrowserWindow } = require('electron');
const Common = {}; const Common = {};
@ -51,6 +51,9 @@ class Comms {
o.reply(Common.Config.config); o.reply(Common.Config.config);
}); });
BDIpc.on('bd-openCssEditor', o => CSSEditor.openEditor(o));
BDIpc.on('bd-setCss', o => CSSEditor.setCSS(o.args));
BDIpc.on('bd-readFile', this.readFile); BDIpc.on('bd-readFile', this.readFile);
BDIpc.on('bd-readJson', o => this.readFile(o, true)); BDIpc.on('bd-readJson', o => this.readFile(o, true));
} }
@ -102,6 +105,7 @@ class BetterDiscord {
this.windowUtils.send('did-navigate-in-page', { event, url, isMainFrame }); this.windowUtils.send('did-navigate-in-page', { event, url, isMainFrame });
}); });
BDIpc.on('bd-sendToDiscord', event => this.windowUtils.send(event.args.channel, event.args.message))
setTimeout(() => { setTimeout(() => {
if (__DEV) { this.injectScripts(); } if (__DEV) { this.injectScripts(); }

View File

@ -0,0 +1,62 @@
/**
* BetterDiscord CSSEditor 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.
*/
const path = require('path');
const { BrowserWindow } = require('electron');
const { Module } = require('./modulebase');
class CSSEditor extends Module {
openEditor(o) {
if (this.editor && this.editor.open) {
this.editor.focus();
this.editor.flashFrame(true);
o.reply(true);
}
this.editor = new BrowserWindow(this.options);
this.editor.loadURL(`file://${this.editorPath}/index.html`);
this.editor.open = true;
this.editor.webContents.on('close', () => {
this.editor.open = false;
});
this.editor.webContents.on('did-finish-load', () => {
o.reply(true);
});
}
setCSS(css) {
this.editor.webContents.send("set-css", css);
}
set alwaysOnTop(state) {
this.editor.setAlwaysOnTop(state);
}
//TODO user options from config
get options() {
return {
width: 800,
height: 600,
frame: false
};
}
//TODO Currently uses a development path
get editorPath() {
return path.resolve(__dirname, '..', '..', '..', 'tests', 'csseditor');
}
}
module.exports = { 'CSSEditor': new CSSEditor() };

View File

@ -1,3 +1,4 @@
export { BDIpc } from './bdipc'; export { BDIpc } from './bdipc';
export { Utils, FileUtils, WindowUtils } from './utils'; export { Utils, FileUtils, WindowUtils } from './utils';
export { Config } from './config'; export { Config } from './config';
export { CSSEditor } from './csseditor';

View File

@ -0,0 +1,51 @@
<html>
<head>
<title>CSS Editor</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/codemirror.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/theme/material.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/scroll/simplescrollbars.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.18.2/addon/dialog/dialog.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/hint/show-hint.min.css" />
<link rel="stylesheet" href="./main.css" />
</head>
<body>
<div class="container">
<div class="titlebar">
<div class="draggable"></div>
<div class="icon">
<div class="inner"></div>
</div>
<div class="title">CSS Editor</div>
<div class="flex-spacer"></div>
<div class="controls">
<button title="Toggle always on top" id="toggleaot">P</button>
<button title="Close CSS Editor" id="closeeditor">X</button>
</div>
</div>
<div id="spinner"><div class="valign">Loading Please Wait...</div></div>
<div class="editor" id="editor">
</div>
<div class="tools">
<div class="flex-row">
<button id="btnSave">Save</button>
<button id="btnUpdate">Update</button>
<div id="chkboxLiveUpdate"><input type="checkbox"><span>Live Update</span></div>
</div>
<div class="flex-row">
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/mode/css/css.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/scroll/simplescrollbars.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/search/search.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/search/searchcursor.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/search/jump-to-line.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/dialog/dialog.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/hint/show-hint.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/hint/css-hint.min.js"></script>
<script src="./main.js"></script>
</body>
</html>

254
tests/csseditor/main.css Normal file
View File

@ -0,0 +1,254 @@
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%;
}
.titlebar {
display: flex;
height: 40px;
background: #292b2f;
border-bottom: 1px solid hsla(218,5%,47%,.3);
}
.titlebar .icon {
width: 45px;
height: 40px;
}
.titlebar .icon .inner {
width: 40px;
height: 40px;
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FscXVlXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjAwMCAyMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAyMDAwIDIwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGZpbGw9IiMzRTgyRTUiIGQ9Ik0xNDAyLjIsNjMxLjdjLTkuNy0zNTMuNC0yODYuMi00OTYtNjQyLjYtNDk2SDY4LjR2NzE0LjFsNDQyLDM5OFY0OTAuN2gyNTdjMjc0LjUsMCwyNzQuNSwzNDQuOSwwLDM0NC45SDU5Ny42djMyOS41aDE2OS44YzI3NC41LDAsMjc0LjUsMzQ0LjgsMCwzNDQuOGgtNjk5djM1NC45aDY5MS4yYzM1Ni4zLDAsNjMyLjgtMTQyLjYsNjQyLjYtNDk2YzAtMTYyLjYtNDQuNS0yODQuMS0xMjIuOS0zNjguNkMxMzU3LjcsOTE1LjgsMTQwMi4yLDc5NC4zLDE0MDIuMiw2MzEuN3oiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNMTI2Mi41LDEzNS4yTDEyNjIuNSwxMzUuMmwtNzYuOCwwYzI2LjYsMTMuMyw1MS43LDI4LjEsNzUsNDQuM2M3MC43LDQ5LjEsMTI2LjEsMTExLjUsMTY0LjYsMTg1LjNjMzkuOSw3Ni42LDYxLjUsMTY1LjYsNjQuMywyNjQuNmwwLDEuMnYxLjJjMCwxNDEuMSwwLDU5Ni4xLDAsNzM3LjF2MS4ybDAsMS4yYy0yLjcsOTktMjQuMywxODgtNjQuMywyNjQuNmMtMzguNSw3My44LTkzLjgsMTM2LjItMTY0LjYsMTg1LjNjLTIyLjYsMTUuNy00Ni45LDMwLjEtNzIuNiw0My4xaDcyLjVjMzQ2LjIsMS45LDY3MS0xNzEuMiw2NzEtNTY3LjlWNzE2LjdDMTkzMy41LDMxMi4yLDE2MDguNywxMzUuMiwxMjYyLjUsMTM1LjJ6Ii8+PC9nPjwvc3ZnPg==);
background-size: 30px 30px;
background-repeat: no-repeat;
background-position: center;
}
.titlebar .title {
color: #bac9d2;
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
line-height: 41px;
}
.titlebar .controls {
margin: 4px 4px 0 0;
}
.titlebar .controls button {
-webkit-app-region: no-drag;
border-radius: 3px;
width: 25px;
font-size: 12px;
font-weight: 600;
/*background: #263238;*/
background: #36393f;
color: #bac9d2;
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
transition: background-color .2s ease;
cursor: pointer;
border: 0;
height: 25px;
z-index: 900062;
padding: 0;
margin: 0;
}
.titlebar .controls button:hover {
background: #44474e;
color: #FFF;
}
.titlebar .controls button.active {
background: #3a71c1;
}
.titlebar .draggable {
top: 4px;
left: 4px;
right: 62px;
position: absolute;
height: 36px;
-webkit-app-region: drag;
}
#spinner {
background: rgba(51, 48, 48, 0.41);
position: absolute;
top: 41px;
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;
}
.editor {
display: flex;
flex-direction: column;
flex-grow: 1;
overflow: hidden;
}
.editor .CodeMirror {
flex-grow: 1;
}
.tools {
height: 60px;
background: #292b2f;
border-top: 1px solid hsla(218,5%,47%,.3);
display: flex;
flex-direction: column;
}
.tools .flex-row {
flex-grow: 1;
padding: 3px 0;
}
.tools 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;
cursor: pointer;
border: 0;
margin-left: 5px;
}
.tools button:hover {
background: #44474e;
color: #FFF;
}
.tools #chkboxLiveUpdate span {
font-size: 12px;
font-weight: 600;
color: #bac9d2;
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
}
/*CodeMirror styling*/
.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;
}
.cm-s-material .CodeMirror-gutters {
background: #292b2f;
}
.CodeMirror-hints {
/*background: #1e262a;*/
background: #292b2f;
box-shadow: 2px 3px 5px rgba(4, 4, 4, 0.22);
border: 1px solid #262f33;
}
.CodeMirror-hints::-webkit-scrollbar {
background: transparent;
}
.CodeMirror-hints::-webkit-scrollbar-thumb {
background-color: rgba(0,0,0,.4);
border-color: transparent;
}
.CodeMirror-hints::-webkit-scrollbar-thumb,
.CodeMirror-hints::-webkit-scrollbar-track {
background-clip: padding-box;
border-width: 3px;
border-style: solid;
border-radius: 7px;
}
.CodeMirror-hints::-webkit-scrollbar-track {
background-color: transparent;
border-color: transparent;
}
.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;
}

130
tests/csseditor/main.js Normal file
View File

@ -0,0 +1,130 @@
const { remote, ipcRenderer } = require('electron');
const { BDIpc } = require('../frontend/main.js');
//Options
const options = {
alwaysOnTop: false,
liveUpdate: false
};
function sendToDiscord(channel, message) {
BDIpc.send('bd-sendToDiscord', {channel, message});
}
//Elements
const
$spinner = $('#spinner'),
$toggleaot = $('#toggleaot'),
$closeeditor = $('#closeeditor'),
$editor = $('#editor'),
$btnSave = $('#btnSave'),
$btnUpdate = $('#btnUpdate'),
$chkboxLiveUpdate = $("#chkboxLiveUpdate input");
$toggleaot.on('click', e => {
$toggleaot.toggleClass("active");
remote.getCurrentWindow().setAlwaysOnTop(options.alwaysOnTop = !options.alwaysOnTop);
});
$closeeditor.on('click', e => window.close());
$btnSave.on('click', () => sendToDiscord("save-css", codeMirror.getValue()));
$btnUpdate.on('click', () => sendToDiscord("update-css", codeMirror.getValue()));
$chkboxLiveUpdate.on('click', () => options.liveUpdate = $chkboxLiveUpdate[0].checked);
BDIpc.on("set-css", (_, data) => {
if (data.error) {
alert(data.error);
return;
}
setCss(data.css);
$spinner.hide();
});
function setCss(css) {
codeMirror.setValue(css);
}
function alert(message) {}
const codeMirror = CodeMirror($editor[0], {
lineNumbers: true,
mode: 'css',
indentUnit: 4,
theme: 'material',
scrollbarStyle: 'overlay',
extraKeys: { 'Ctrl-Space': 'autocomplete' },
dialog: { 'position': 'bottom' }
});
codeMirror.on('change', () => {
if (options.liveUpdate)
sendToDiscord("update-css", codeMirror.getValue());
});
codeMirror.on('keyup', function (editor, event) {
if (window.controlDown) return;
if (ExcludedIntelliSenseTriggerKeys[event.keyCode]) return;
CodeMirror.commands.autocomplete(editor, null, { completeSingle: false });
});
const ExcludedIntelliSenseTriggerKeys = {
'8': 'backspace',
'9': 'tab',
'13': 'enter',
'16': 'shift',
'17': 'ctrl',
'18': 'alt',
'19': 'pause',
'20': 'capslock',
'27': 'escape',
'33': 'pageup',
'34': 'pagedown',
'35': 'end',
'36': 'home',
'37': 'left',
'38': 'up',
'39': 'right',
'40': 'down',
'45': 'insert',
'46': 'delete',
'91': 'left window key',
'92': 'right window key',
'93': 'select',
'107': 'add',
'109': 'subtract',
'110': 'decimal point',
'111': 'divide',
'112': 'f1',
'113': 'f2',
'114': 'f3',
'115': 'f4',
'116': 'f5',
'117': 'f6',
'118': 'f7',
'119': 'f8',
'120': 'f9',
'121': 'f10',
'122': 'f11',
'123': 'f12',
'144': 'numlock',
'145': 'scrolllock',
'186': 'semicolon',
'187': 'equalsign',
'188': 'comma',
'189': 'dash',
'190': 'period',
'191': 'slash',
'192': 'graveaccent',
'220': 'backslash',
'222': 'quote'
}

448
tests/csseditor/mainold.css Normal file

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,10 @@ const { ipcRenderer } = require('electron');
class BDIpc { class BDIpc {
static on(channel, cb) {
ipcRenderer.on(channel, (event, args) => cb(event, args));
}
static async send(channel, message) { static async send(channel, message) {
const __eid = Date.now().toString(); const __eid = Date.now().toString();
ipcRenderer.send( ipcRenderer.send(
@ -17,4 +21,6 @@ class BDIpc {
}); });
} }
} }
module.exports = { BDIpc };