show compile errors in ui

This commit is contained in:
Moritz Hölting 2024-06-27 00:08:20 +02:00
parent a623308496
commit 664dbf4f6b
4 changed files with 84 additions and 18 deletions

View File

@ -1,6 +1,8 @@
import { useEffect, useState } from "react";
import { useMonaco, type Monaco } from "@monaco-editor/react";
import { useImmer, type Updater } from "use-immer";
import ThemeProvider from "@mui/material/styles/ThemeProvider";
import ErrorDisplay from "./playground/ErrorDisplay";
import FileView from "./playground/FileView";
import Editor from "./playground/Editor";
import Header from "./playground/Header";
@ -16,7 +18,6 @@ import "@styles/playground.scss";
import mainFileContent from "@assets/playground/main.shu?raw";
import packTomlContent from "@assets/playground/pack.toml?raw";
import ThemeProvider from "@mui/material/styles/ThemeProvider";
const FILE_STORAGE_KEY = "playground-files";
const DEFAULT_FILES = {
@ -40,6 +41,18 @@ const DEFAULT_FILES = {
};
export default function Playground({ lang }: { lang: PlaygroundLang }) {
const [errorMsg, setErrorMsg] = useState<string | null>(null);
useEffect(() => {
(window as any).playground = {
showError: (message: string) => {
if (message.length > 0) {
setErrorMsg(message);
}
},
};
}, []);
initWasm().catch((err) => {
console.error(err);
});
@ -63,8 +76,6 @@ export default function Playground({ lang }: { lang: PlaygroundLang }) {
},
} as Directory;
loadFiles(monaco, updateRootDir, withRoot);
} else {
alert("Compilation failed");
}
} else {
console.error("monaco has not loaded");
@ -79,8 +90,6 @@ export default function Playground({ lang }: { lang: PlaygroundLang }) {
a.href = data;
a.download = "shulkerscript-pack.zip";
a.click();
} else {
alert("Compilation failed");
}
} else {
console.error("monaco has not loaded");
@ -167,6 +176,7 @@ export default function Playground({ lang }: { lang: PlaygroundLang }) {
marginTop: "0.5cm",
}}
>
<ErrorDisplay error={errorMsg} setError={setErrorMsg} />
<Header
lang={lang.header}
onSave={onSave}

View File

@ -0,0 +1,40 @@
import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
export default function ErrorDisplay({
error,
setError,
}: {
error: string | null;
setError: (error: string | null) => void;
}) {
return (
<Dialog open={error !== null} onClose={() => setError(null)}>
<DialogTitle>Error during compilation!</DialogTitle>
<DialogContent>
<div
style={{
backgroundColor: "black",
padding: "15px",
borderRadius: "15px",
fontSize: "1.2em",
}}
>
<code
style={{
whiteSpace: "break-spaces",
fontFamily: "monospace",
}}
dangerouslySetInnerHTML={{ __html: error ?? "" }}
></code>
</div>
</DialogContent>
<DialogActions>
<Button onClick={() => setError(null)}>Close</Button>
</DialogActions>
</Dialog>
);
}

View File

@ -17,3 +17,5 @@ anyhow = "1.0.86"
zip = { version = "2.1.3", default-features = false, features = ["deflate"] }
base64 = "0.22.1"
console_error_panic_hook = "0.1.7"
ansi-to-html = "0.2.1"
colored = "2.1.0"

View File

@ -1,8 +1,8 @@
use std::{
cell::Cell,
fmt::Display,
io::{Cursor, Write},
path::PathBuf,
sync::Mutex,
};
use anyhow::Result;
@ -24,6 +24,9 @@ extern "C" {
fn log(s: &str);
#[wasm_bindgen(js_namespace = console, js_name = error)]
fn log_err(s: &str);
#[wasm_bindgen(js_namespace = ["window", "playground"], js_name = showError)]
fn show_err(s: &str);
}
/// Compiles the given directory into datapack files.
@ -57,38 +60,38 @@ pub fn compile_zip(root_dir: JsValue) -> Option<String> {
// write each file to the zip archive
for (path, file) in virtual_files {
writer
.start_file(path, SimpleFileOptions::default())
.unwrap();
writer.start_file(path, SimpleFileOptions::default()).ok()?;
match file {
VFile::Text(text) => {
writer.write_all(text.as_bytes()).unwrap();
writer.write_all(text.as_bytes()).ok()?;
}
VFile::Binary(data) => {
writer.write_all(data).unwrap();
writer.write_all(data).ok()?;
}
}
}
writer.set_comment("Data pack created with Shulkerscript web compiler");
writer.finish().unwrap();
writer.finish().ok()?;
Some(BASE64_STANDARD.encode(buffer.into_inner()))
}
fn _compile(root_dir: &VFolder) -> Result<VFolder> {
colored::control::set_override(true);
let printer = Printer::new();
util::compile(&printer, root_dir, &get_script_paths(root_dir))
let res = util::compile(&printer, root_dir, &get_script_paths(root_dir));
printer.display();
res
}
struct Printer {
printed: Cell<bool>,
queue: Mutex<Vec<String>>,
}
impl<T: Display> Handler<T> for Printer {
fn receive<E: Into<T>>(&self, error: E) {
log_err(&error.into().to_string());
self.printed.set(true);
self.queue.lock().unwrap().push(format!("{}", error.into()));
}
fn has_received(&self) -> bool {
@ -99,12 +102,23 @@ impl Printer {
/// Creates a new [`Printer`].
fn new() -> Self {
Self {
printed: Cell::new(false),
queue: Mutex::new(Vec::new()),
}
}
fn display(self) {
let queue = self
.queue
.into_inner()
.unwrap()
.into_iter()
.map(|el| ansi_to_html::convert(&el).unwrap())
.collect::<Vec<_>>();
show_err(&queue.join("\n\n"));
}
fn has_printed(&self) -> bool {
self.printed.get()
!self.queue.lock().unwrap().is_empty()
}
}