abstract editor
This commit is contained in:
parent
f3122dae51
commit
1a132c0f90
|
@ -156,6 +156,12 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.floating-window-content #bd-editor-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.floating-window-content {
|
.floating-window-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
16
js/main.js
16
js/main.js
File diff suppressed because one or more lines are too long
|
@ -1,15 +1,12 @@
|
||||||
import Builtin from "../structs/builtin";
|
import Builtin from "../structs/builtin";
|
||||||
import {Settings, DataStore, React, Utilities, WebpackModules} from "modules";
|
import {Settings, DataStore, React, Utilities, WebpackModules} from "modules";
|
||||||
import CSSEditor from "../ui/customcss/editor";
|
import CSSEditor from "../ui/customcss/csseditor";
|
||||||
import FloatingWindow from "../ui/customcss/detached";
|
import FloatingWindow from "../ui/customcss/detached";
|
||||||
|
|
||||||
import SettingsTitle from "../ui/settings/title";
|
import SettingsTitle from "../ui/settings/title";
|
||||||
|
|
||||||
const electron = require("electron");
|
const electron = require("electron");
|
||||||
const PopoutStack = WebpackModules.getByProps("open", "closeAll");
|
const PopoutStack = WebpackModules.getByProps("open", "closeAll");
|
||||||
const PopoutOpener = WebpackModules.getByProps("openPopout");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default new class CustomCSS extends Builtin {
|
export default new class CustomCSS extends Builtin {
|
||||||
get name() {return "Custom CSS";}
|
get name() {return "Custom CSS";}
|
||||||
|
@ -20,7 +17,8 @@ export default new class CustomCSS extends Builtin {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.css = "";
|
this.savedCss = "";
|
||||||
|
this.insertedCss = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
async enabled() {
|
async enabled() {
|
||||||
|
@ -32,7 +30,7 @@ export default new class CustomCSS extends Builtin {
|
||||||
Settings.registerPanel(this.id, this.name, {
|
Settings.registerPanel(this.id, this.name, {
|
||||||
order: 2,
|
order: 2,
|
||||||
element: () => [<SettingsTitle text="Custom CSS Editor" />, React.createElement(CSSEditor, {
|
element: () => [<SettingsTitle text="Custom CSS Editor" />, React.createElement(CSSEditor, {
|
||||||
css: this.css,
|
css: this.savedCss,
|
||||||
save: this.saveCSS.bind(this),
|
save: this.saveCSS.bind(this),
|
||||||
update: this.insertCSS.bind(this),
|
update: this.insertCSS.bind(this),
|
||||||
openNative: this.openNative.bind(this),
|
openNative: this.openNative.bind(this),
|
||||||
|
@ -45,7 +43,7 @@ export default new class CustomCSS extends Builtin {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.loadCSS();
|
this.loadCSS();
|
||||||
this.insertCSS();
|
this.insertCSS(this.savedCss);
|
||||||
}
|
}
|
||||||
|
|
||||||
disabled() {
|
disabled() {
|
||||||
|
@ -53,11 +51,12 @@ export default new class CustomCSS extends Builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCSS() {
|
loadCSS() {
|
||||||
this.css = DataStore.loadCustomCSS();
|
this.savedCss = DataStore.loadCustomCSS();
|
||||||
}
|
}
|
||||||
|
|
||||||
insertCSS(newCss) {
|
insertCSS(newCss) {
|
||||||
if (typeof(newCss) === "undefined") newCss = this.css;
|
if (typeof(newCss) === "undefined") newCss = this.insertedCss;
|
||||||
|
else this.insertedCss = newCss;
|
||||||
if ($("#customcss").length == 0) {
|
if ($("#customcss").length == 0) {
|
||||||
$("head").append("<style id=\"customcss\"></style>");
|
$("head").append("<style id=\"customcss\"></style>");
|
||||||
}
|
}
|
||||||
|
@ -65,8 +64,8 @@ export default new class CustomCSS extends Builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveCSS(newCss) {
|
saveCSS(newCss) {
|
||||||
if (typeof(newCss) !== "undefined") this.css = newCss;
|
if (typeof(newCss) !== "undefined") this.savedCss = newCss;
|
||||||
DataStore.saveCustomCSS(this.css);
|
DataStore.saveCustomCSS(this.savedCss);
|
||||||
}
|
}
|
||||||
|
|
||||||
openNative() {
|
openNative() {
|
||||||
|
@ -98,8 +97,8 @@ export default new class CustomCSS extends Builtin {
|
||||||
width: 500,
|
width: 500,
|
||||||
center: true
|
center: true
|
||||||
}), React.createElement(CSSEditor, {
|
}), React.createElement(CSSEditor, {
|
||||||
editorId: "bd-floating-editor",
|
id: "bd-floating-editor",
|
||||||
css: this.css,
|
css: this.savedCss,
|
||||||
save: this.saveCSS.bind(this),
|
save: this.saveCSS.bind(this),
|
||||||
update: this.insertCSS.bind(this),
|
update: this.insertCSS.bind(this),
|
||||||
openNative: this.openNative.bind(this)
|
openNative: this.openNative.bind(this)
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import {React, Settings} from "modules";
|
||||||
|
|
||||||
|
import Editor from "./editor";
|
||||||
|
// import Checkbox from "./checkbox";
|
||||||
|
|
||||||
|
export default class CssEditor extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.toggleLiveUpdate = this.toggleLiveUpdate.bind(this);
|
||||||
|
this.updateCss = this.updateCss.bind(this);
|
||||||
|
this.saveCss = this.saveCss.bind(this);
|
||||||
|
this.openDetached = this.props.openDetached ? this.openDetached.bind(this) : null;
|
||||||
|
this.openNative = this.openNative.bind(this);
|
||||||
|
|
||||||
|
this.checkboxes = [{label: "Live Update", onChange: this.toggleLiveUpdate, checked: Settings.get("settings", "customcss", "liveUpdate")}];
|
||||||
|
this.buttons = [
|
||||||
|
{label: "Update", onClick: this.updateCss},
|
||||||
|
{label: "Save", onClick: this.saveCss},
|
||||||
|
{label: "Open Natively", onClick: this.openNative},
|
||||||
|
{label: "Settings", onClick: "showSettings"}
|
||||||
|
];
|
||||||
|
if (this.openDetached) this.buttons.push({label: "Detach", onClick: this.openDetached});
|
||||||
|
this.notice = this.openDetached ? "Unsaved changes are lost on detach" : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <Editor id={this.props.id || "bd-customcss-editor"} notice={this.openDetached ? this.notice : null} checkboxes={this.checkboxes} buttons={this.buttons} showHelp={true} value={this.props.css} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleLiveUpdate(checked) {
|
||||||
|
Settings.set("settings", "customcss", "liveUpdate", checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCss() {
|
||||||
|
const newCss = this.editor.session.getValue();
|
||||||
|
if (this.props.update) this.props.update(newCss);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveCss() {
|
||||||
|
const newCss = this.editor.session.getValue();
|
||||||
|
if (this.props.save) this.props.save(newCss);
|
||||||
|
}
|
||||||
|
|
||||||
|
openDetached() {
|
||||||
|
if (this.props.openDetached) this.props.openDetached();
|
||||||
|
}
|
||||||
|
|
||||||
|
openNative() {
|
||||||
|
if (this.props.openNative) this.props.openNative();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +1,42 @@
|
||||||
import {React, Settings} from "modules";
|
import {React} from "modules";
|
||||||
|
|
||||||
import Checkbox from "./checkbox";
|
import Checkbox from "./checkbox";
|
||||||
import SettingsTitle from "../settings/title";
|
|
||||||
|
|
||||||
export default class CssEditor extends React.Component {
|
const languages = ["abap", "abc", "actionscript", "ada", "apache_conf", "asciidoc", "assembly_x86", "autohotkey", "batchfile", "bro", "c_cpp", "c9search", "cirru", "clojure", "cobol", "coffee", "coldfusion", "csharp", "csound_document", "csound_orchestra", "csound_score", "css", "curly", "d", "dart", "diff", "dockerfile", "dot", "drools", "dummy", "dummysyntax", "eiffel", "ejs", "elixir", "elm", "erlang", "forth", "fortran", "ftl", "gcode", "gherkin", "gitignore", "glsl", "gobstones", "golang", "graphqlschema", "groovy", "haml", "handlebars", "haskell", "haskell_cabal", "haxe", "hjson", "html", "html_elixir", "html_ruby", "ini", "io", "jack", "jade", "java", "javascript", "json", "jsoniq", "jsp", "jssm", "jsx", "julia", "kotlin", "latex", "less", "liquid", "lisp", "livescript", "logiql", "lsl", "lua", "luapage", "lucene", "makefile", "markdown", "mask", "matlab", "maze", "mel", "mushcode", "mysql", "nix", "nsis", "objectivec", "ocaml", "pascal", "perl", "pgsql", "php", "pig", "powershell", "praat", "prolog", "properties", "protobuf", "python", "r", "razor", "rdoc", "red", "rhtml", "rst", "ruby", "rust", "sass", "scad", "scala", "scheme", "scss", "sh", "sjs", "smarty", "snippets", "soy_template", "space", "sql", "sqlserver", "stylus", "svg", "swift", "tcl", "tex", "text", "textile", "toml", "tsx", "twig", "typescript", "vala", "vbscript", "velocity", "verilog", "vhdl", "wollok", "xml", "xquery", "yaml", "django"];
|
||||||
|
const themes = ["chrome", "clouds", "crimson_editor", "dawn", "dreamweaver", "eclipse", "github", "iplastic", "solarized_light", "textmate", "tomorrow", "xcode", "kuroir", "katzenmilch", "sqlserver", "ambiance", "chaos", "clouds_midnight", "cobalt", "gruvbox", "gob", "idle_fingers", "kr_theme", "merbivore", "merbivore_soft", "mono_industrial", "monokai", "pastel_on_dark", "solarized_dark", "terminal", "tomorrow_night", "tomorrow_night_blue", "tomorrow_night_bright", "tomorrow_night_eighties", "twilight", "vibrant_ink"];
|
||||||
|
|
||||||
|
export default class CodeEditor extends React.Component {
|
||||||
|
static get defaultId() {return "bd-editor";}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
for (const button of this.props.buttons) {
|
||||||
|
if (button.onClick == "showSettings") button.onClick = this.showSettings.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
this.toggleLiveUpdate = this.toggleLiveUpdate.bind(this);
|
this.props.theme = this.props.theme.toLowerCase().replace(/ /g, "_");
|
||||||
this.updateCss = this.updateCss.bind(this);
|
if (!themes.includes(this.props.theme)) this.props.theme = this.defaultProps.theme;
|
||||||
this.saveCss = this.saveCss.bind(this);
|
|
||||||
this.openDetached = this.props.openDetached ? this.openDetached.bind(this) : null;
|
this.props.language = this.props.language.toLowerCase().replace(/ /g, "_");
|
||||||
this.openNative = this.openNative.bind(this);
|
if (!languages.includes(this.props.language)) this.props.language = this.defaultProps.language;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get defaultProps() {
|
||||||
|
return {
|
||||||
|
buttons: [],
|
||||||
|
checkboxes: [],
|
||||||
|
theme: "monokai",
|
||||||
|
language: "css",
|
||||||
|
id: this.defaultId,
|
||||||
|
fontSize: 14
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static get themes() {return themes;}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.editor = ace.edit(this.props.editorId || "bd-customcss-editor");
|
this.editor = ace.edit(this.props.id);
|
||||||
|
|
||||||
// Add id to the ace menu container
|
// Add id to the ace menu container
|
||||||
const originalShow = this.editor.keyBinding.$defaultHandler.commands.showSettingsMenu.exec;
|
const originalShow = this.editor.keyBinding.$defaultHandler.commands.showSettingsMenu.exec;
|
||||||
|
@ -34,63 +54,49 @@ export default class CssEditor extends React.Component {
|
||||||
observer.observe(document.body, {childList: true});
|
observer.observe(document.body, {childList: true});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.editor.setTheme("ace/theme/monokai");
|
this.editor.setTheme(`ace/theme/${this.props.theme}`);
|
||||||
this.editor.session.setMode("ace/mode/css");
|
this.editor.session.setMode(`ace/mode/${this.props.language}`);
|
||||||
this.editor.setShowPrintMargin(false);
|
this.editor.setShowPrintMargin(false);
|
||||||
this.editor.setFontSize(14);
|
this.editor.setFontSize(this.props.fontSize);
|
||||||
this.editor.on("change", () => {
|
if (this.props.onChange) {
|
||||||
if (!Settings.get("settings", "customcss", "liveUpdate")) return;
|
this.editor.on("change", () => {
|
||||||
this.saveCss();
|
this.props.onChange(this.value);
|
||||||
this.updateCss();
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.editor.destroy();
|
this.editor.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get value() {return this.editor.session.getValue();}
|
||||||
|
|
||||||
|
showSettings() {return this.editor.keyBinding.$defaultHandler.commands.showSettingsMenu.exec(this.editor);}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
return [
|
const buttons = this.props.buttons.map(button =>
|
||||||
<div className="editor-wrapper">
|
<button className="btn btn-primary" onClick={(event) => {button.onClick(event, this.value);}}>{button.label}</button>
|
||||||
<div id={this.props.editorId || "bd-customcss-editor"} className="editor">{this.props.css}</div>
|
);
|
||||||
</div>,
|
|
||||||
<div id="bd-customcss-attach-controls">
|
const checkboxes = this.props.checkboxes.map(checkbox =>
|
||||||
<div className="checkbox-group">
|
<Checkbox text={checkbox.label} onChange={checkbox.onChange} checked={checkbox.checked} />
|
||||||
<Checkbox text="Live Update" onChange={this.toggleLiveUpdate} checked={Settings.get("settings", "customcss", "liveUpdate")} />
|
);
|
||||||
</div>
|
|
||||||
<div id="bd-customcss-detach-controls-button">
|
return <div id="bd-editor-panel">
|
||||||
<button className="btn btn-primary" onClick={this.updateCss}>Update</button>
|
<div className="editor-wrapper">
|
||||||
<button className="btn btn-primary" onClick={this.saveCss}>Save</button>
|
<div id={this.props.id} className="editor">{this.props.value}</div>
|
||||||
<button className="btn btn-primary" onClick={this.openNative}>Open Natively</button>
|
|
||||||
{this.openDetached && [<button className="btn btn-primary" onClick={this.openDetached}>Detach</button>, <span className="small-notice">Unsaved changes are lost on detach</span>]}
|
|
||||||
<div className="help-text">
|
|
||||||
Press <code className="inline">ctrl</code>+<code className="inline">,</code> with the editor focused to access the editor's settings.
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div id="bd-editor-controls">
|
||||||
</div>
|
{checkboxes.length && <div className="checkbox-group">{checkboxes}</div>}
|
||||||
];
|
<div id="bd-editor-buttons">
|
||||||
}
|
{buttons}
|
||||||
|
{this.props.notice && <span className="small-notice">{this.props.notice}</span>}
|
||||||
toggleLiveUpdate(checked) {
|
</div>
|
||||||
Settings.set("settings", "customcss", "liveUpdate", checked);
|
{this.props.showHelp && <div className="help-text">
|
||||||
}
|
Press <code className="inline">ctrl</code>+<code className="inline">,</code> with the editor focused to access the editor's settings.
|
||||||
|
</div>}
|
||||||
updateCss() {
|
</div>
|
||||||
const newCss = this.editor.session.getValue();
|
</div>;
|
||||||
if (this.props.update) this.props.update(newCss);
|
|
||||||
}
|
|
||||||
|
|
||||||
saveCss() {
|
|
||||||
const newCss = this.editor.session.getValue();
|
|
||||||
if (this.props.save) this.props.save(newCss);
|
|
||||||
}
|
|
||||||
|
|
||||||
openDetached() {
|
|
||||||
if (this.props.openDetached) this.props.openDetached();
|
|
||||||
}
|
|
||||||
|
|
||||||
openNative() {
|
|
||||||
if (this.props.openNative) this.props.openNative();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue