aboutsummaryrefslogtreecommitdiff
path: root/src_frontend/stores/IDEStore.js
diff options
context:
space:
mode:
authorjakob.stendahl <jakob.stendahl@infomedia.dk>2022-12-05 12:27:41 +0100
committerJakob Stendahl <jakob.stendahl@outlook.com>2022-12-05 12:27:41 +0100
commitb1b8b9605d804793f557c92e2d7b1f659d8c99f0 (patch)
tree3ba82d71490f1e222080b11c8636b6457bf3ab14 /src_frontend/stores/IDEStore.js
parent7beca23767641c8e52d22109069909f6380cb99b (diff)
downloadLuxcena-Neo-b1b8b9605d804793f557c92e2d7b1f659d8c99f0.tar.gz
Luxcena-Neo-b1b8b9605d804793f557c92e2d7b1f659d8c99f0.zip
Move IDE components into its own store, fix some state issues, change state update method to push instead of pull
Diffstat (limited to 'src_frontend/stores/IDEStore.js')
-rw-r--r--src_frontend/stores/IDEStore.js235
1 files changed, 235 insertions, 0 deletions
diff --git a/src_frontend/stores/IDEStore.js b/src_frontend/stores/IDEStore.js
new file mode 100644
index 0000000..ce4308c
--- /dev/null
+++ b/src_frontend/stores/IDEStore.js
@@ -0,0 +1,235 @@
+import { writable, derived, get } from "svelte/store";
+import { notif } from "./notifs";
+import { authorizedSocket, authorizedSocketNeeded, openSocketConnected } from "./socketStore";
+authorizedSocketNeeded.set(true)
+
+import { EditorState, basicSetup } from "@codemirror/basic-setup"
+import { EditorView, keymap } from "@codemirror/view"
+import { indentWithTab } from "@codemirror/commands"
+import { indentUnit } from '@codemirror/language'
+import { python } from "@codemirror/lang-python"
+import { HighlightStyle, tags as t } from "@codemirror/highlight"
+
+export let socketListenersAdded = writable(false);
+export let debuggerInitialised = writable(false);
+export let procIsRunning = writable(false);
+export let state = writable(null);
+export let codeEditorViewEl = writable(null);
+export let codeEditorView = writable(null);
+export let codeEditorHasChanges = writable(false);
+
+export function attachCodeEditorView(node) {
+ codeEditorViewEl.set(node);
+ let _codeEditorView = get(codeEditorView);
+ if (_codeEditorView == null) {
+ console.warn("Attempted to attach codeEditorView, but it is not initialized");
+ return;
+ }
+ node.appendChild(_codeEditorView.dom);
+ console.debug(`Attached code editor to`, node);
+}
+
+export function initDebugger(modeId) {
+ if (get(debuggerInitialised)) { return; }
+ debuggerInitialised.set(true);
+ console.debug("emitting editor:open");
+ authorizedSocket.emit("editor:open", `user/${modeId}`, (res) => {
+ if (!res.success) { notifErr(res); };
+ });
+}
+
+export function closeDebugger() {
+ saveCode((res) => {
+ if (!res.success) { notifErr(res); };
+ console.debug("emitting editor:close");
+ authorizedSocket.emit("editor:close", res => {
+ if (!res.success) { notifErr(res); };
+ debuggerInitialised.set(false);
+
+ get(codeEditorView).destroy();
+ codeEditorView.set(null);
+ });
+ });
+}
+
+export function saveCode(fn) {
+ if (get(codeEditorView) == null) { return; }
+ console.debug("emitting editor:save");
+ authorizedSocket.emit("editor:save", get(state).mode, get(codeEditorView).state.doc.toString(), res => {
+ console.debug("save:code callback", res);
+ if (!res.success) { notifErr(res); };
+ if (fn != null) { fn(res) }
+ });
+ codeEditorHasChanges.set(false);
+}
+
+export function notifErr(err) {
+ console.error(err);
+ if (err.hasOwnProperty("detail")) {
+ notif({title: err.reason, type: "danger"});
+ } else {
+ notif({title: err.reason, text: err.detail, type: "danger"});
+ }
+}
+
+function addSocketListeners() {
+ if (get(socketListenersAdded)) { return; }
+ socketListenersAdded.set(true);
+ authorizedSocket.on("editor:debugger:state", onEditorDebuggerState);
+ authorizedSocket.on("editor:code", createCodeEditor);
+ console.debug("Listeners attemted added");
+}
+
+function removeSocketListeners() {
+ if (!get(socketListenersAdded)) { return; }
+ socketListenersAdded.set(false);
+ authorizedSocket.off("editor:debugger:state", onEditorDebuggerState);
+ authorizedSocket.off("editor:code", createCodeEditor);
+ console.debug("Listeners attempted removed");
+}
+
+function onEditorDebuggerState(_state) {
+ state.set(_state);
+ procIsRunning.set(_state.running);
+}
+
+function createCodeEditor(modeId, code) {
+ console.debug(`received editor:code for mode ${modeId}`);
+ if (get(codeEditorView) != null) {
+ get(codeEditorView).destroy();
+ codeEditorView.set(null);
+ }
+ const chalky = "#e5c07b",
+ coral = "#e06c75",
+ cyan = "#56b6c2",
+ invalid = "#ffffff",
+ ivory = "#abb2bf",
+ stone = "#7d8799",
+ malibu = "#61afef",
+ sage = "#98c379",
+ whiskey = "#d19a66",
+ violet = "#c678dd",
+ darkBackground = "#21252b",
+ highlightBackground = "#2c313a",
+ background = "#282c34",
+ selection = "#3E4451",
+ cursor = "#528bff"
+
+ let _codeEditorView = new EditorView({
+ state: EditorState.create({
+ extensions: [
+ basicSetup,
+ keymap.of([indentWithTab]),
+ python(),
+ indentUnit.of(" "),
+ EditorView.updateListener.of(update => {
+ if (update.docChanged) {
+ codeEditorHasChanges.set(true);
+ }
+ }),
+ EditorView.theme({
+ "&": {
+ color: ivory,
+ },
+
+ ".cm-content": {
+ caretColor: cursor
+ },
+
+ "&.cm-focused .cm-cursor": {borderLeftColor: cursor},
+ "&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection": {backgroundColor: selection},
+
+ ".cm-panels": {backgroundColor: darkBackground, color: ivory},
+ ".cm-panels.cm-panels-top": {borderBottom: "2px solid black"},
+ ".cm-panels.cm-panels-bottom": {borderTop: "2px solid black"},
+
+ ".cm-searchMatch": {
+ backgroundColor: "#72a1ff59",
+ outline: "1px solid #457dff"
+ },
+ ".cm-searchMatch.cm-searchMatch-selected": {
+ backgroundColor: "#6199ff2f"
+ },
+
+ ".cm-activeLine": {backgroundColor: highlightBackground},
+ ".cm-selectionMatch": {backgroundColor: "#aafe661a"},
+
+ ".cm-matchingBracket, .cm-nonmatchingBracket": {
+ backgroundColor: "#bad0f847",
+ outline: "1px solid #515a6b"
+ },
+
+ ".cm-gutters": {
+ backgroundColor: "transparent",
+ color: stone,
+ border: "none"
+ },
+
+ ".cm-activeLineGutter": {
+ backgroundColor: highlightBackground
+ },
+
+ ".cm-foldPlaceholder": {
+ backgroundColor: "transparent",
+ border: "none",
+ color: "#ddd"
+ },
+
+ ".cm-tooltip": {
+ border: "1px solid #181a1f",
+ backgroundColor: darkBackground
+ },
+ ".cm-tooltip-autocomplete": {
+ "& > ul > li[aria-selected]": {
+ backgroundColor: highlightBackground,
+ color: ivory
+ }
+ }
+ }, {dark:true}),
+ HighlightStyle.define([
+ {tag: t.keyword,
+ color: violet},
+ {tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
+ color: coral},
+ {tag: [t.function(t.variableName), t.labelName],
+ color: malibu},
+ {tag: [t.color, t.constant(t.name), t.standard(t.name)],
+ color: whiskey},
+ {tag: [t.definition(t.name), t.separator],
+ color: ivory},
+ {tag: [t.typeName, t.className, t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],
+ color: chalky},
+ {tag: [t.operator, t.operatorKeyword, t.url, t.escape, t.regexp, t.link, t.special(t.string)],
+ color: cyan},
+ {tag: [t.meta, t.comment],
+ color: stone},
+ {tag: t.strong,
+ fontWeight: "bold"},
+ {tag: t.emphasis,
+ fontStyle: "italic"},
+ {tag: t.strikethrough,
+ textDecoration: "line-through"},
+ {tag: t.link,
+ color: stone,
+ textDecoration: "underline"},
+ {tag: t.heading,
+ fontWeight: "bold",
+ color: coral},
+ {tag: [t.atom, t.bool, t.special(t.variableName)],
+ color: whiskey },
+ {tag: [t.processingInstruction, t.string, t.inserted],
+ color: sage},
+ {tag: t.invalid,
+ color: invalid},
+ ]),
+ ],
+ doc: code
+ })
+ });
+ codeEditorView.set(_codeEditorView);
+ if (get(codeEditorViewEl) != null) {
+ attachCodeEditorView(get(codeEditorViewEl));
+ }
+}
+
+addSocketListeners();