diff --git a/frontend/pages/app.ejs b/frontend/pages/app.ejs
index cfa8e3c..df459eb 100644
--- a/frontend/pages/app.ejs
+++ b/frontend/pages/app.ejs
@@ -1,30 +1,81 @@
-
+
<%= config.name %> - Riju
+
-
-
-
-
+
<% if (fathomSiteId) { %>
<% } %>
+
+
+
+
diff --git a/frontend/src/app.js b/frontend/src/app.js
index c899bb7..de9f1d3 100644
--- a/frontend/src/app.js
+++ b/frontend/src/app.js
@@ -21,6 +21,21 @@ import "xterm/css/xterm.css";
const DEBUG = window.location.hash === "#debug";
const config = window.rijuConfig;
+const formatButton = document.getElementById("formatButton");
+
+function closeModal() {
+ document.querySelector("html").classList.remove("is-clipped");
+ document.getElementById("modal").classList.remove("is-active");
+}
+
+function showError({ message, data }) {
+ document.getElementById("modal-title").innerText = message;
+ document.getElementById("modal-data").innerText =
+ data || "(no output on stderr)";
+ document.getElementById("modal").classList.add("is-active");
+ document.querySelector("html").classList.add("is-clipped");
+}
+
class RijuMessageReader extends AbstractMessageReader {
constructor(socket) {
super();
@@ -101,6 +116,9 @@ class RijuMessageWriter extends AbstractMessageWriter {
}
async function main() {
+ let serviceLogBuffers = {};
+ let serviceLogLines = {};
+
const term = new Terminal();
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
@@ -126,9 +144,10 @@ async function main() {
}
function tryConnect() {
+ serviceLogBuffers = {};
+ serviceLogLines = {};
let clientDisposable = null;
let servicesDisposable = null;
- const serviceLogBuffers = {};
console.log("Connecting to server...");
socket = new WebSocket(
(document.location.protocol === "http:" ? "ws://" : "wss://") +
@@ -169,6 +188,8 @@ async function main() {
term.write(message.output);
return;
case "formattedCode":
+ formatButton.disabled = false;
+ formatButton.classList.remove("is-loading");
if (
typeof message.code !== "string" ||
typeof message.originalCode !== "string"
@@ -235,19 +256,32 @@ async function main() {
console.error("Unexpected message from server:", message);
return;
}
- if (DEBUG) {
- let buffer = serviceLogBuffers[message.service] || "";
- buffer += message.output;
- while (buffer.includes("\n")) {
- const idx = buffer.indexOf("\n");
- const line = buffer.slice(0, idx);
- buffer = buffer.slice(idx + 1);
+ let buffer = serviceLogBuffers[message.service] || "";
+ let lines = serviceLogLines[message.service] || [];
+ buffer += message.output;
+ while (buffer.includes("\n")) {
+ const idx = buffer.indexOf("\n");
+ const line = buffer.slice(0, idx);
+ buffer = buffer.slice(idx + 1);
+ lines.push(line);
+ if (DEBUG) {
console.log(`${message.service.toUpperCase()} || ${line}`);
}
- serviceLogBuffers[message.service] = buffer;
}
+ serviceLogBuffers[message.service] = buffer;
+ serviceLogLines[message.service] = lines;
return;
- case "serviceCrashed":
+ case "serviceFailed":
+ if (typeof message.service !== "string") {
+ console.error("Unexpected message from server:", message);
+ return;
+ }
+ formatButton.disabled = false;
+ formatButton.classList.remove("is-loading");
+ showError({
+ message: "Could not prettify code!",
+ data: serviceLogLines["formatter"].join("\n"),
+ });
return;
default:
console.error("Unexpected message from server:", message);
@@ -288,6 +322,15 @@ async function main() {
minimap: { enabled: false },
scrollbar: { verticalScrollbarSize: 0 },
});
+ editor.addAction({
+ id: "runCode",
+ label: "Run",
+ keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
+ contextMenuGroupId: "2_execution",
+ run: () => {
+ sendMessage({ event: "runCode", code: editor.getValue() });
+ },
+ });
window.addEventListener("resize", () => editor.layout());
editor.getModel().setValue(config.template + "\n");
monaco.editor.setModelLanguage(
@@ -299,11 +342,25 @@ async function main() {
sendMessage({ event: "runCode", code: editor.getValue() });
});
if (config.format) {
- document.getElementById("formatButton").classList.add("visible");
- document.getElementById("formatButton").addEventListener("click", () => {
+ formatButton.classList.remove("is-hidden");
+ formatButton.addEventListener("click", () => {
+ formatButton.classList.add("is-loading");
+ formatButton.disabled = true;
+ serviceLogBuffers["formatter"] = "";
+ serviceLogLines["formatter"] = [];
sendMessage({ event: "formatCode", code: editor.getValue() });
});
}
+ if (config.lsp) {
+ document.getElementById("lspButton").classList.remove("is-hidden");
+ document.getElementById("lspButton").addEventListener("click", () => {
+ // Do stuff here
+ });
+ }
+
+ for (const elt of document.querySelectorAll(".will-close-modal")) {
+ elt.addEventListener("click", closeModal);
+ }
}
main().catch(console.error);
diff --git a/frontend/styles/app.css b/frontend/styles/app.css
index 6d5efc5..511ba7b 100644
--- a/frontend/styles/app.css
+++ b/frontend/styles/app.css
@@ -1,45 +1,7 @@
-body {
- margin: 0;
- height: 100vh;
+.xterm {
+ padding: 12px;
}
-#app {
- height: 100%;
-}
-
-.column {
- width: 50%;
- height: 100%;
- float: left;
-}
-
-#editor {
- overflow: hidden;
-}
-
-#terminal {
- background: black;
-}
-
-#runButton {
- position: absolute;
- top: 25px;
- right: calc(50% + 25px);
-}
-
-#formatButton {
- position: absolute;
- bottom: 25px;
- right: calc(50% + 25px);
- visibility: hidden;
-}
-
-#formatButton.visible {
- visibility: visible;
-}
-
-#backButton {
- position: absolute;
- left: 25px;
- bottom: 25px;
+#header .button {
+ border-radius: 0;
}