revamp customcss start publicservers

This commit is contained in:
Zack Rauen 2019-06-14 22:11:19 -04:00
parent 1a132c0f90
commit ed145df94b
21 changed files with 504 additions and 453 deletions

View File

@ -101,9 +101,18 @@
@keyframes open-window {
from {
transform: scale(0.9);
}
to {
transform: none;
}
}
.floating-window {
animation: open-window 200ms ease;
min-width: 200px;
min-height: 300px;
box-shadow: 0 2px 10px 0 rgba(0,0,0,.2);
@ -111,6 +120,14 @@
flex-direction: column;
-webkit-app-region: no-drag;
position: fixed;
z-index: 1001;
}
.floating-window.resizable {
overflow: auto;
resize: both;
padding-bottom: 10px;
background: #202225;
}
.floating-window-titlebar {
@ -118,9 +135,8 @@
display: flex;
justify-content: space-between;
align-items: center;
background: #2F3129;/*#2F3129*/
background: #202225;/*#2F3129background-color: #202225;*/
color: white;
padding: 2px 0;
border-bottom: 1px solid #272822;
}
@ -135,21 +151,24 @@
/* font-weight: bold; */
flex: 1;
text-align: center;
}
.floating-window-buttons {
float: right;
padding: 2px 0;
}
.floating-window-buttons .button {
cursor: pointer;
padding: 0 2px;
}
.theme-no-transform {
transform: none!important;
left: unset!important;
top: unset!important;
margin: 0!important;
.floating-window-buttons .close-button svg {
margin-top: 1.5px;
}
.floating-window-buttons .close-button:hover {
background-color: #f04747;
}
.floating-window-buttons .close-button:hover svg path.fill {
fill: white;
}
@ -176,9 +195,9 @@
flex: 1;
}
.floating-window #bd-customcss-attach-controls {
.floating-window #bd-editor-controls {
height: auto;
background: #272822;
background: #202225;
border: none;
box-shadow: 0px 1px 0px 0px #2F3129 inset;
}
@ -706,197 +725,106 @@ color: #f6f6f7;
/* BEGIN CSS EDITOR */
/* ================ */
.standardSidebarView-3F1I7i #bd-customcss-attach-controls button,
.bd-detached-css-editor #bd-customcss-attach-controls button {
margin: 0;
width: 100px;
background: #2F3129;
#bd-editor-panel {
display: flex;
flex-direction: column;
}
#bd-editor-controls button {
margin: 0 5px 0 0;
background: none;
color: #FFF;
height: 26px;
font-weight: 600;
margin-top: 5px;
border-radius: 3px;
display: flex;
align-items: center;
}
.standardSidebarView-3F1I7i #bd-customcss-attach-controls button:hover,
.bd-detached-css-editor #bd-customcss-attach-controls button:hover {
background: rgb(59,61,51);
#bd-editor-controls button:hover {
background: rgba(255,255,255,0.05);
}
.contentRegion-3nDuYy #bd-customcss-attach-controls,
#bd-customcss-detach-container #bd-customcss-attach-controls {
#bd-editor-controls button svg {
fill: white;
}
#bd-editor-controls button:last-of-type {
margin-right: 0;
}
#bd-editor-controls {
display: flex;
align-items: center;
justify-content: space-between;
background: #272822;
color: #FFF;
border: none;
box-shadow: 0px 1px 0px 0px #2F3129 inset;
padding: 5px;
}
.contentRegion-3nDuYy #bd-customcss-pane,
.contentRegion-3nDuYy #bd-customcss-innerpane,
#bd-customcss-detach-container #bd-customcss-pane,
#bd-customcss-detach-container #bd-customcss-innerpane {
min-height: calc(80vh - 165px);
}
.standardSidebarView-3F1I7i #editor-detached h3 {
color: #87909c;
font-weight: 600;
font-size: 22px;
}
.standardSidebarView-3F1I7i #editor-detached button {
margin: auto;
margin-left: calc(50% - 100px);
margin-top: 20px;
background: #7289da;
color: #FFF;
font-weight: 600;
border-radius: 5px;
font-size: 20px;
}
.editor-wrapper {
display: flex;
}
.line-numbers, .ace_editor {
.ace_editor {
line-height: normal;
font-family: Consolas, monospace;
box-sizing: border-box;
height: calc(100vh - 250px);
font-size: 14px;
}
.line-numbers {
white-space: pre;
color: gray;
padding: 10px 5px 0 5px;
background: #24262a;
overflow: hidden;
}
.ace_editor {
width: 100%;
}
.bd-monokai .editor .ace_gutter {
background: #2F3136;
}
.bd-monokai .ace_editor {
background: #292B2F;
outline: none;
color: white;
padding: 10px;
resize: none;
}
#bd-customcss-detach-container .editor-wrapper,
#bd-customcss-detach-container .line-numbers,
#bd-customcss-detach-container .ace_editor {
height: 100%;
.bd-monokai #bd-editor-controls {
background: #202225;
}
.bd-detached-editor .app-2rEoOp {
width: 70%;
}
.bd-detached-editor #bd-customcss-detach-container {
display: block;
}
#bd-customcss-detach-container {
display: none;
position: absolute;
width: 30%;
top: 0;
right: 0;
bottom: 0;
background-color: #36393e;
}
#bd-customcss-detach-editor {
height: calc(100% - 87px);
}
#bd-customcss-detach-editor #bd-customcss-innerpane, #bd-customcss-detach-editor .CodeMirror {
height: 100%;
}
#bd-customcss-detach-controls {
background: #E8E8E8;
border-top: 1px solid #ADADAD;
box-shadow: inset 0px 1px 0px 0px white;
height: 100%;
padding: 5px;
}
#bd-customcss-detach-controls .checkbox-group li {
margin-top: 5px;
display: inline-block;
}
#bd-customcss-detach-controls button {
width: 90px;
height: 30px;
margin-top: 8px;
background-color: #738bd7;
color: #fff;
font-size: 19px;
}
#bd-customcss-detach-controls-buttons {
bottom: 5px;
}
#editor-detached {
margin-top: 50px;
}
#editor-detached h3 {
text-align: center;
font-size: 30px;
}
#editor-detached .btn {
left: 50%;
margin-left: -100px;
margin-top: 10px;
width: 200px;
height: 60px;
}
#bd-customcss-attach-controls {
.theme-light #bd-editor-controls {
background: #E8E8E8;
border: 1px solid #FFF;
border-top: 1px solid #ADADAD;
box-shadow: inset 0px 1px 0px 0px white;
height: 100%;
padding: 5px;
}
#bd-customcss-attach-controls .checkbox-group {
margin-bottom: 0;
}
#bd-customcss-attach-controls .checkbox-group li {
margin-top: 5px;
display: inline-block;
}
#bd-customcss-attach-controls button {
margin: 0;
width: 100px;
border-radius: 0px;
border-left: 2px solid rgb(63, 65, 70);
}
#bd-customcss-attach-controls button:first-of-type {
border-radius: 3px 0px 0px 3px;
border-left: none;
.controls-section {
display: flex;
align-items: center
}
#bd-customcss-attach-controls button:last-of-type {
border-radius: 0px 3px 3px 0px;
.controls-section .checkbox-inner {
width: 14px;
height: 14px;
}
#bd-customcss-detach-container #bd-customcss-detach-controls-buttons button {
width: 90px;
height: 30px;
margin-top: 8px;
background-color: #738bd7;
color: #fff;
font-size: 19px;
.controls-section .checkbox-inner .checkbox:checked+span::after {
left: 2px;
top: -2px;
}
#bd-customcss-attach-controls .small-notice {
font-size: 10px;
margin-left: 5px;
.controls-section .checkbox-label {
font-size: 14px;
}
#floating-editor-window {
min-width: 340px;
min-height: 280px;
max-height: 900px;
max-width: 750px;
}
/* Ace Editor Settings */
@ -929,13 +857,13 @@ body .ace_closeButton:active {
}
/* editor help text */
#bd-customcss-attach-controls .help-text {
#bd-editor-controls .help-text {
margin-top: 8px;
margin-bottom: 3px;
font-size: 14px;
}
#bd-customcss-attach-controls .help-text .inline {
#bd-editor-controls .help-text .inline {
background: #2F3129;
padding: .2em;
margin: -.2em 0;

File diff suppressed because one or more lines are too long

View File

@ -1,12 +1,14 @@
import Builtin from "../structs/builtin";
import {Settings, DataStore, React, Utilities, WebpackModules} from "modules";
import {Settings, DataStore, React, Utilities, WebpackModules, Events} from "modules";
import CSSEditor from "../ui/customcss/csseditor";
import FloatingWindow from "../ui/customcss/detached";
import FloatingWindowContainer from "../ui/floating/container";
import SettingsTitle from "../ui/settings/title";
const fs = require("fs");
const electron = require("electron");
const PopoutStack = WebpackModules.getByProps("open", "closeAll");
const UserSettings = WebpackModules.getByProps("updateAccount");
const Dispatcher = WebpackModules.getByProps("dirtyDispatch");
const ActionTypes = WebpackModules.getByProps("ActionTypes").ActionTypes;
export default new class CustomCSS extends Builtin {
get name() {return "Custom CSS";}
@ -19,6 +21,7 @@ export default new class CustomCSS extends Builtin {
super();
this.savedCss = "";
this.insertedCss = "";
this.isDetached = false;
}
async enabled() {
@ -34,20 +37,67 @@ export default new class CustomCSS extends Builtin {
save: this.saveCSS.bind(this),
update: this.insertCSS.bind(this),
openNative: this.openNative.bind(this),
openDetached: this.openDetached.bind(this)
openDetached: this.openDetached.bind(this),
onChange: this.onChange.bind(this)
})],
onClick: (thisObject) => {
if (this.isDetached) return;
if (this.nativeOpen) this.openNative();
else if (this.startDetached) this.openDetached();
else thisObject._reactInternalFiber.child.memoizedProps.children.props.onSetSection(this.name);
this.setSection = thisObject._reactInternalFiber.child.memoizedProps.children.props.onSetSection;
}
});
this.loadCSS();
this.insertCSS(this.savedCss);
this.watchContent();
}
disabled() {
Settings.removePanel(this.id);
this.unwatchContent();
}
//* {outline: 1px solid red;}
//DataStore.customCSS
watchContent() {
if (this.watcher) return this.error("Already watching content.");
const timeCache = {};
this.log("Starting to watch content.");
this.watcher = fs.watch(DataStore.customCSS, {persistent: false}, async (eventType, filename) => {
if (!eventType || !filename) return;
await new Promise(r => setTimeout(r, 50));
try {fs.statSync(DataStore.customCSS);}
catch (err) {
if (err.code !== "ENOENT") return;
delete timeCache[filename];
this.saveCSS("");
}
const stats = fs.statSync(DataStore.customCSS);
if (!stats || !stats.mtime || !stats.mtime.getTime()) return;
if (typeof(stats.mtime.getTime()) !== "number") return;
if (timeCache[filename] == stats.mtime.getTime()) return;
timeCache[filename] = stats.mtime.getTime();
if (eventType == "change") {
const newCSS = DataStore.loadCustomCSS();
if (newCSS == this.savedCss) return;
this.savedCss = newCSS;
this.insertCSS(this.savedCss);
Events.emit("customcss-updated", this.savedCss);
}
});
}
unwatchContent() {
if (!this.watcher) return this.error("Was not watching content.");
this.watcher.close();
delete this.watcher;
this.log("No longer watching content.");
}
onChange(value) {
if (!Settings.get("settings", "customcss", "liveUpdate")) return;
this.insertCSS(value);
this.saveCSS(value);
}
loadCSS() {
@ -72,71 +122,34 @@ export default new class CustomCSS extends Builtin {
electron.shell.openExternal(`file://${DataStore.customCSS}`);
}
openDetached() {
this.log("Should open detached");
PopoutStack.open({
animationType: "none",
arrowAlignment: "top",
backdrop: false,
closeOnScroll: false,
key: this.id,
forceTheme: "no-transform",
position: "top",
preventCloseFromModal: true,
preventClickPropagation: true,
preventCloseOnUnmount: true,
preventInvert: false,
render: (props) => {
return React.createElement(FloatingWindow, Object.assign({}, props, {
close: () => {PopoutStack.close(this.id);},
isPopout: true,
title: "Custom CSS Editor",
className: "testme",
id: "test",
height: 400,
width: 500,
center: true
}), React.createElement(CSSEditor, {
id: "bd-floating-editor",
css: this.savedCss,
save: this.saveCSS.bind(this),
update: this.insertCSS.bind(this),
openNative: this.openNative.bind(this)
}));
},
shadow: false,
showArrow: false,
zIndexBoost: 0
openDetached(currentCSS) {
const editorRef = React.createRef();
const editor = React.createElement(CSSEditor, {
id: "bd-floating-editor",
editorRef: editorRef,
css: currentCSS,
save: this.saveCSS.bind(this),
update: this.insertCSS.bind(this),
openNative: this.openNative.bind(this),
onChange: this.onChange.bind(this)
});
FloatingWindowContainer.open({
onClose: () => {this.isDetached = false;},
onResize: () => {
if (!editorRef || !editorRef.current || !editorRef.current.resize) return;
editorRef.current.resize();
},
title: "Custom CSS Editor",
id: "floating-editor-window",
height: 470,
width: 410,
center: true,
resizable: true,
children: editor
});
this.isDetached = true;
UserSettings.close();
Dispatcher.dirtyDispatch({type: ActionTypes.LAYER_POP});
}
};
// const test = {
// animationType: "default",
// arrowAlignment: "top",
// backdrop: false,
// clickPos: 74,
// closeOnScroll: false,
// containerClass: undefined,
// dependsOn: undefined,
// forceTheme: undefined,
// key: "floating-window",
// offsetX: 15,
// offsetY: 0,
// position: "left",
// preventCloseFromModal: false,
// preventClickPropagation: true,
// preventInvert: false,
// render: function() {
// console.log(arguments);
// return DiscordModules.React.createElement("div", Object.assign({}, arguments[0], {className: "testme", id: "test"}));
// },
// shadow: false,
// showArrow: false,
// target: $("div.memberOnline-1CIh-0.member-3W1lQa.da-memberOnline.da-member")[0],
// targetHeight: 40,
// targetWidth: 224,
// x: 1211,
// y: 357,
// zIndexBoost: 0
// }
};

View File

@ -1,6 +1,8 @@
import Builtin from "../structs/builtin";
import {BDV2, DiscordModules} from "modules";
import {PublicServers as PSComponents} from "ui";
import {BDV2, DiscordModules, WebpackModules} from "modules";
import {PublicServersMenu} from "ui";
const LayerStack = WebpackModules.getByProps("pushLayer");
export default new class PublicServers extends Builtin {
get name() {return "PublicServers";}
@ -17,37 +19,8 @@ export default new class PublicServers extends Builtin {
$("#bd-pub-li").remove();
}
get component() {
return DiscordModules.React.createElement(PSComponents.Layer, {
rootId: "pubslayerroot",
id: "pubslayer"
}, DiscordModules.React.createElement(PSComponents.Menu, {rootId: "pubslayerroot"}));
}
get root() {
const _root = document.getElementById("pubslayerroot");
if (!_root) {
if (!this.injectRoot()) return null;
return this.root;
}
return _root;
}
injectRoot() {
if (!$(".layers, .layers-3iHuyZ").length) return false;
$(".layers, .layers-3iHuyZ").append($("<div/>", {
id: "pubslayerroot"
}));
return true;
}
render() {
const root = this.root;
if (!root) {
this.error("FAILED TO LOCATE ROOT: .layers");
return;
}
DiscordModules.ReactDOM.render(this.component, root);
openPublicServers() {
LayerStack.pushLayer(() => DiscordModules.React.createElement(PublicServersMenu, {close: LayerStack.popLayer}));
}
get button() {
@ -58,7 +31,7 @@ export default new class PublicServers extends Builtin {
"class": "wrapper-25eVIn " + BDV2.guildClasses.circleButtonMask,
"text": "public",
"id": "bd-pub-button",
"click": () => { this.render(); }
"click": () => { this.openPublicServers(); }
}));
return btn;

View File

@ -1,7 +1,12 @@
import {React, Settings} from "modules";
import {React, Settings, Events} from "modules";
import Editor from "./editor";
// import Checkbox from "./checkbox";
import Refresh from "../icons/reload";
import Save from "../icons/save";
import Edit from "../icons/edit";
import Cog from "../icons/cog";
import Detach from "../icons/detach";
export default class CssEditor extends React.Component {
@ -13,38 +18,56 @@ export default class CssEditor extends React.Component {
this.saveCss = this.saveCss.bind(this);
this.openDetached = this.props.openDetached ? this.openDetached.bind(this) : null;
this.openNative = this.openNative.bind(this);
this.updateEditor = this.updateEditor.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"}
this.controls = [
{label: React.createElement(Refresh, {size: "18px"}), tooltip: "Update", onClick: this.updateCss},
{label: React.createElement(Save, {size: "18px"}), tooltip: "Save", onClick: this.saveCss},
{label: React.createElement(Edit, {size: "18px"}), tooltip: "Open in System Editor", onClick: this.openNative},
{label: React.createElement(Cog, {size: "18px"}), tooltip: "Editor Settings", onClick: "showSettings"},
{label: "Live Update", type:"checkbox", onChange: this.toggleLiveUpdate, checked: Settings.get("settings", "customcss", "liveUpdate"), side: "right"}
];
if (this.openDetached) this.buttons.push({label: "Detach", onClick: this.openDetached});
this.notice = this.openDetached ? "Unsaved changes are lost on detach" : null;
if (this.openDetached) this.controls.push({label: React.createElement(Detach, {size: "18px"}), tooltip: "Detach Editor", onClick: this.openDetached, side: "right"});
}
componentDidMount() {
Events.on("customcss-updated", this.updateEditor);
}
componentWillUnmount() {
Events.off("customcss-updated", this.updateEditor);
}
updateEditor(newCSS) {
if (!this.editor) return;
this.editor.value = newCSS;
}
setEditorRef(editor) {
this.editor = editor;
if (this.props.editorRef && typeof(this.props.editorRef.current) !== "undefined") this.props.editorRef.current = editor;
else if (this.props.editorRef) this.props.editorRef = editor;
}
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} />;
return <Editor ref={this.setEditorRef.bind(this)} readOnly={this.props.readOnly} id={this.props.id || "bd-customcss-editor"} onChange={this.props.onChange} controls={this.controls} value={this.props.css} />;
}
toggleLiveUpdate(checked) {
Settings.set("settings", "customcss", "liveUpdate", checked);
}
updateCss() {
const newCss = this.editor.session.getValue();
updateCss(event, newCss) {
if (this.props.update) this.props.update(newCss);
}
saveCss() {
const newCss = this.editor.session.getValue();
saveCss(event, newCss) {
if (this.props.save) this.props.save(newCss);
}
openDetached() {
if (this.props.openDetached) this.props.openDetached();
openDetached(event, currentCSS) {
if (!this.props.openDetached) return;
this.props.openDetached(currentCSS);
}
openNative() {

View File

@ -1,7 +1,9 @@
import {React} from "modules";
import {React, WebpackModules} from "modules";
import Checkbox from "./checkbox";
const Tooltip = WebpackModules.getByDisplayName("Tooltip");
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"];
@ -11,22 +13,24 @@ export default class CodeEditor extends React.Component {
constructor(props) {
super(props);
for (const button of this.props.buttons) {
if (button.onClick == "showSettings") button.onClick = this.showSettings.bind(this);
for (const control of this.props.controls) {
if (control.type == "checkbox") continue;
if (control.onClick == "showSettings") control.onClick = this.showSettings.bind(this);
}
this.props.theme = this.props.theme.toLowerCase().replace(/ /g, "_");
if (!themes.includes(this.props.theme)) this.props.theme = this.defaultProps.theme;
if (!themes.includes(this.props.theme)) this.props.theme = CodeEditor.defaultProps.theme;
this.props.language = this.props.language.toLowerCase().replace(/ /g, "_");
if (!languages.includes(this.props.language)) this.props.language = this.defaultProps.language;
if (!languages.includes(this.props.language)) this.props.language = CodeEditor.defaultProps.language;
this.onChange = this.onChange.bind(this);
}
static get defaultProps() {
return {
buttons: [],
checkboxes: [],
theme: "monokai",
controls: [],
theme: "bd-monokai",
language: "css",
id: this.defaultId,
fontSize: 14
@ -54,15 +58,12 @@ export default class CodeEditor extends React.Component {
observer.observe(document.body, {childList: true});
};
this.editor.setTheme(`ace/theme/${this.props.theme}`);
const theme = this.props.theme == CodeEditor.defaultProps.theme ? this.props.theme.split("-")[1] : this.props.theme;
this.editor.setTheme(`ace/theme/${theme}`);
this.editor.session.setMode(`ace/mode/${this.props.language}`);
this.editor.setShowPrintMargin(false);
this.editor.setFontSize(this.props.fontSize);
if (this.props.onChange) {
this.editor.on("change", () => {
this.props.onChange(this.value);
});
}
this.editor.on("change", this.onChange);
}
componentWillUnmount() {
@ -70,32 +71,51 @@ export default class CodeEditor extends React.Component {
}
get value() {return this.editor.session.getValue();}
set value(newValue) {
this.editor.setValue(newValue);
}
onChange() {
if (this.props.onChange) this.props.onChange(this.value);
}
showSettings() {return this.editor.keyBinding.$defaultHandler.commands.showSettingsMenu.exec(this.editor);}
resize() {return this.editor.resize();}
buildControl(control) {
if (control.type == "checkbox") return this.makeCheckbox(control);
return this.makeButton(control);
}
makeCheckbox(checkbox) {
return <Checkbox text={checkbox.label} onChange={checkbox.onChange} checked={checkbox.checked} />;
}
makeButton(button) {
return <Tooltip color="black" position="top" text={button.tooltip}>
{props => {
return <button {...props} className="btn btn-primary" onClick={(event) => {button.onClick(event, this.value);}}>{button.label}</button>;
}}
</Tooltip>;
}
render() {
if (this.editor && this.editor.resize) this.editor.resize();
const buttons = this.props.buttons.map(button =>
<button className="btn btn-primary" onClick={(event) => {button.onClick(event, this.value);}}>{button.label}</button>
);
const controlsLeft = this.props.controls.filter(c => c.side != "right").map(this.buildControl.bind(this));
const controlsRight = this.props.controls.filter(c => c.side == "right").map(this.buildControl.bind(this));
const checkboxes = this.props.checkboxes.map(checkbox =>
<Checkbox text={checkbox.label} onChange={checkbox.onChange} checked={checkbox.checked} />
);
return <div id="bd-editor-panel">
<div className="editor-wrapper">
<div id={this.props.id} className="editor">{this.props.value}</div>
</div>
return <div id="bd-editor-panel" className={this.props.theme}>
<div id="bd-editor-controls">
{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>}
<div className="controls-section controls-left">
{controlsLeft}
</div>
{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&apos;s settings.
</div>}
<div className="controls-section controls-right">
{controlsRight}
</div>
</div>
<div className="editor-wrapper">
<div id={this.props.id} className={"editor " + this.props.theme}>{this.props.value}</div>
</div>
</div>;
}

View File

@ -0,0 +1,65 @@
import {React, Utilities} from "modules";
import FloatingWindow from "./window";
class FloatingWindowContainer extends React.Component {
constructor(props) {
super(props);
this.state = {windows: []};
}
render() {
return this.state.windows.map(window =>
<FloatingWindow onResize={window.onResize} close={this.close.bind(this, window.id)} title={window.title} id={window.id} height={window.height} width={window.width} center={window.center} resizable={window.resizable}>
{window.children}
</FloatingWindow>
);
}
open(window) {
this.setState({
windows: [...this.state.windows, window]
});
// this.windows.push(window);
// this.forceUpdate();
}
close(id) {
this.setState({
windows: this.state.windows.filter(w => {
if (w.id == id && w.onClose) w.onClose();
return w.id != id;
})
});
// const index = this.windows.findIndex(w => w.id == id);
// if (index < 0) return;
// this.windows.splice(index, 1);
// this.forceUpdate();
}
static get id() {return "floating-windows";}
static get root() {
if (this._root) return this._root;
const container = document.createElement("div");
container.id = this.id;
document.body.append(container);
return this._root = container;
}
}
const containerRef = React.createRef();
const container = <FloatingWindowContainer ref={containerRef} />;
// ReactDOM.render(container, FloatingWindowContainer.root);
const App = document.querySelector(".app-19_DXt").__reactInternalInstance$.return.return.return.return.return.return.return.return.return;
Utilities.monkeyPatch(App.type.prototype, "render", {after: (data) => {
data.returnValue.props.children.props.children.props.children.props.children[4].props.children[1].props.children.push(container);
}});
App.stateNode.forceUpdate();
export default containerRef.current;
// patch App component
//
//document.querySelector(".app-19_DXt").__reactInternalInstance$.return.return.return.return.return.return.return.return.return.type
//props.children.props.children.props.children.props.children[4].props.children[1].props.children[""0""].push( SELF )
// forceupdate app component

View File

@ -27,33 +27,48 @@ export default class FloatingWindow extends React.Component {
this.onDrag = this.onDrag.bind(this);
this.onDragStart = this.onDragStart.bind(this);
this.onDragStop = this.onDragStop.bind(this);
this.onResizeStart = this.onResizeStart.bind(this);
}
componentDidMount() {
if (this.props.isPopout) {
console.log(this);
const popout = this._reactInternalFiber.return.return.return.stateNode;
// console.log(this);
const popout = this._reactInternalFiber.return.return.return.return.stateNode;//_reactInternalFiber.return.return.return.return.stateNode
setImmediate(() => {
document.removeEventListener("click", popout.close, true);
if (!this.props.close) this.props.close = popout.close;
});
}
this.window.current.addEventListener("mousedown", this.onResizeStart, false);
this.titlebar.current.addEventListener("mousedown", this.onDragStart, false);
document.addEventListener("mouseup", this.onDragStop, false);
}
onDragStop(e) {
onResizeStart() {
this.currentWidth = this.window.current.style.width;
this.currentHeight = this.window.current.style.height;
}
onDragStop() {
// e.preventDefault();
// e.stopPropagation();
document.removeEventListener("mousemove", this.onDrag, true);
if (this.props.onResize) {
const width = this.window.current.style.width;
const height = this.window.current.style.height;
if (width != this.currentWidth || height != this.currentHeight) this.props.onResize();
this.currentWidth = width;
this.currentHeight = height;
}
}
onDragStart(e) {
// e.preventDefault();
// e.stopPropagation();
const div = this.window.current;
console.log(div.offsetTop, div.offsetLeft);
// console.log(div.offsetTop, div.offsetLeft);
this.offY = e.clientY - parseInt(div.offsetTop);
this.offX = e.clientX - parseInt(div.offsetLeft);
document.addEventListener("mousemove", this.onDrag, true);
@ -76,9 +91,10 @@ export default class FloatingWindow extends React.Component {
render() {
const top = this.props.center ? (Screen.height / 2) - (this.props.height / 2) : this.props.top;
const left = this.props.center ? (Screen.width / 2) - (this.props.width / 2) : this.props.left ;
console.log(top, left);
// console.log(top, left);
const className = `floating-window ${this.props.className || ""} ${this.props.resizable ? "resizable" : ""}`;
const styles = {height: this.props.height, width: this.props.width, left: left || 0, top: top || 0};
return <div id={this.props.id} className={"floating-window " + this.props.className} ref={this.window} style={styles}>
return <div id={this.props.id} className={className} ref={this.window} style={styles}>
<div className="floating-window-titlebar" ref={this.titlebar}>
<span className="title">{this.props.title}</span>
<div className="floating-window-buttons">
@ -94,7 +110,7 @@ export default class FloatingWindow extends React.Component {
}
close() {
console.log("click close");
// console.log("click close");
if (this.props.close) this.props.close();
}
}

11
src/ui/icons/cog.jsx Normal file
View File

@ -0,0 +1,11 @@
import {React} from "modules";
export default class Cog extends React.Component {
render() {
const size = this.props.size || "20px";
return <svg viewBox="0 0 20 20" style={{width: size, height: size}}>
<path fill="none" d="M0 0h20v20H0V0z" />
<path d="M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z" />
</svg>;
}
}

11
src/ui/icons/detach.jsx Normal file
View File

@ -0,0 +1,11 @@
import {React} from "modules";
export default class Detach extends React.Component {
render() {
const size = this.props.size || "24px";
return <svg viewBox="0 0 24 24" style={{width: size, height: size}}>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z" />
</svg>;
}
}

11
src/ui/icons/edit.jsx Normal file
View File

@ -0,0 +1,11 @@
import {React} from "modules";
export default class Edit extends React.Component {
render() {
const size = this.props.size || "24px";
return <svg viewBox="0 0 24 24" style={{width: size, height: size}}>
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
<path d="M0 0h24v24H0z" fill="none" />
</svg>;
}
}

View File

@ -3,7 +3,7 @@ import {React} from "modules";
export default class ReloadIcon extends React.Component {
render() {
const size = this.props.size || "24px";
return <svg className={"bd-reload " + this.props.className} onClick={this.props.onClick} fill="#dcddde" viewBox="0 0 24 24" style={{width: size, height: size}}>
return <svg className={this.props.className || ""} onClick={this.props.onClick} fill="#dcddde" viewBox="0 0 24 24" style={{width: size, height: size}}>
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
<path fill="none" d="M0 0h24v24H0z" />
</svg>;

11
src/ui/icons/save.jsx Normal file
View File

@ -0,0 +1,11 @@
import {React} from "modules";
export default class Save extends React.Component {
render() {
const size = this.props.size || "24px";
return <svg viewBox="0 0 24 24" style={{width: size, height: size}}>
<path fill="none" d="M0 0h24v24H0V0z" />
<path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm2 16H5V5h11.17L19 7.83V19zm-7-7c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zM6 6h9v4H6z" />
</svg>;
}
}

View File

@ -1,62 +0,0 @@
import {React, ReactDOM} from "modules";
export default class Layer extends React.Component {
constructor(props) {
super(props);
this.rootRef = React.createRef();
}
componentDidMount() {
$(window).on(`keyup.${this.props.id}`, e => {
if (e.which === 27) {
ReactDOM.unmountComponentAtNode(this.rootRef.current.parentNode);
}
});
$(`#${this.props.id}`).animate({opacity: 1}, {
step: function(now) {
$(this).css("transform", `scale(${1.1 - 0.1 * now}) translateZ(0px)`);
},
duration: 200,
done: () => {$(`#${this.props.id}`).css("opacity", "").css("transform", "");}
});
}
componentWillUnmount() {
$(window).off(`keyup.${this.props.id}`);
$(`#${this.props.id}`).animate({opacity: 0}, {
step: function(now) {
$(this).css("transform", `scale(${1.1 - 0.1 * now}) translateZ(0px)`);
},
duration: 200,
done: () => {$(`#${this.props.rootId}`).remove();}
});
$("[class*=\"layer-\"]").removeClass("publicServersOpen").animate({opacity: 1}, {
step: function(now) {
$(this).css("transform", `scale(${0.07 * now + 0.93}) translateZ(0px)`);
},
duration: 200,
done: () => {$("[class*=\"layer-\"]").css("opacity", "").css("transform", "");}
});
}
UNSAFE_componentWillMount() {
$("[class*=\"layer-\"]").addClass("publicServersOpen").animate({opacity: 0}, {
step: function(now) {
$(this).css("transform", `scale(${0.07 * now + 0.93}) translateZ(0px)`);
},
duration: 200
});
}
render() {
return React.createElement(
"div",
{className: "layer bd-layer layer-3QrUeG", id: this.props.id, ref: this.rootRef, style: {opacity: 0, transform: "scale(1.1) translateZ(0px)"}},
this.props.children
);
}
}

View File

@ -1,4 +1,4 @@
import {React, ReactDOM, WebpackModules} from "modules";
import {React, WebpackModules} from "modules";
import SidebarView from "./sidebarview";
import Tools from "./exitbutton";
import TabBar from "./tabbar";
@ -39,7 +39,7 @@ export default class PublicServers extends React.Component {
}
close() {
ReactDOM.unmountComponentAtNode(document.getElementById(this.props.rootId));
this.props.close();
}
search(query, clear) {
@ -232,7 +232,7 @@ export default class PublicServers extends React.Component {
}
render() {
return React.createElement(SidebarView, {ref: "sbv"}, this.component);
return React.createElement(SidebarView, {id: "pubslayer", ref: "sbv"}, this.component);
}
get component() {
@ -252,7 +252,7 @@ export default class PublicServers extends React.Component {
get sidebar() {
return React.createElement(
"div",
{className: "sidebar", key: "ps"},
{className: "sidebar-CFHs9e da-sidebar sidebar", key: "ps"},
React.createElement(
"div",
{className: "ui-tab-bar SIDE"},

View File

@ -1,5 +0,0 @@
import Menu from "./menu";
import Card from "./card";
import Layer from "./layer";
export {Menu, Card, Layer};

View File

@ -9,7 +9,8 @@ export default class SidebarView extends React.Component {
render() {
const {sidebar, content, tools} = this.props.children;
return React.createElement(
return React.createElement("div", {className: this.props.className || "", id: this.props.id || ""},
React.createElement(
"div",
{className: "standardSidebarView-3F1I7i ui-standard-sidebar-view"},
React.createElement(
@ -22,6 +23,6 @@ export default class SidebarView extends React.Component {
React.createElement(Scroller, {key: "contentScroller", contentColumn: true, fade: content.fade || true, dark: content.dark || true}, content.component, tools.component)
)
)
);
));
}
}

View File

@ -26,7 +26,7 @@ export default class ContentList extends React.Component {
const showReloadIcon = !Settings.get("settings", "content", "autoReload");
const button = folder ? {title: `Open ${title} Folder`, onClick: () => {require("electron").shell.openItem(folder);}} : null;
return [
<SettingsTitle key="title" text={title} button={button} otherChildren={showReloadIcon && <ReloadIcon onClick={this.reload.bind(this)} />} />,
<SettingsTitle key="title" text={title} button={button} otherChildren={showReloadIcon && <ReloadIcon className="bd-reload" onClick={this.reload.bind(this)} />} />,
<ul key="ContentList" className={"bda-slist"}>
{contentList.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())).map(content => {
const CardType = content.type ? PluginCard : ThemeCard;

View File

@ -96,7 +96,7 @@ export default class PluginCard extends React.Component {
React.createElement("span", {className: "bda-author"}, author)
),
React.createElement("div", {className: "bda-controls"},
!Settings.get("settings", "content", "autoReload") && React.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}),
!Settings.get("settings", "content", "autoReload") && React.createElement(ReloadIcon, {className: "bd-reload bd-reload-card", onClick: this.reload}),
React.createElement("label", {className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}},
React.createElement("input", {checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox"}),
React.createElement("div", {className: this.state.checked ? "ui-switch checked" : "ui-switch"})

View File

@ -39,7 +39,7 @@ export default class ThemeCard extends React.Component {
React.createElement("span", {className: "bda-author"}, author)
),
React.createElement("div", {className: "bda-controls"},
!Settings.get("settings", "content", "autoReload") && React.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}),
!Settings.get("settings", "content", "autoReload") && React.createElement(ReloadIcon, {className: "bd-reload bd-reload-card", onClick: this.reload}),
React.createElement("label", {className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}},
React.createElement("input", {checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox"}),
React.createElement("div", {className: this.state.checked ? "ui-switch checked" : "ui-switch"})

View File

@ -1,5 +1,4 @@
import SettingsPanel from "./settings/settings";
import * as PublicServers from "./publicservers/publicservers";
export {default as SettingsPanel} from "./settings/settings";
export {default as PublicServersMenu} from "./publicservers/menu";
export {default as Toasts} from "./toasts";
export {default as Modals} from "./modals";
export {SettingsPanel, PublicServers};
export {default as Modals} from "./modals";