Add some error handling

This commit is contained in:
Matthew Gordon 2025-06-12 10:53:10 -03:00
parent 072b54cafe
commit 0d98b4016c
3 changed files with 44 additions and 15 deletions

View File

@ -23,6 +23,6 @@ pub fn main() {
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
#[wasm_bindgen] #[wasm_bindgen]
pub async fn init_pteropus() -> wasm::PteropusCanvas { pub async fn init_pteropus() -> Result<wasm::PteropusCanvas, wasm::PteropusInitError> {
run(App::new(), Rc::new(Model::new())).await run(App::new(), Rc::new(Model::new())).await
} }

View File

@ -9,7 +9,7 @@ use {
use crate::{ use crate::{
app::{App, Model}, app::{App, Model},
mvu, mvu,
mvu::{Event, File, MvuApp, Size2i}, mvu::{Event, MvuApp, Size2i},
}; };
struct FrameTimer { struct FrameTimer {
@ -52,9 +52,23 @@ pub struct PteropusCanvas {
model: Rc<Model>, model: Rc<Model>,
} }
#[wasm_bindgen(getter_with_clone)]
#[derive(Clone)]
pub struct PteropusInitError {
pub message: String,
}
impl PteropusInitError {
fn new<M: Into<String>>(message: M) -> Self {
Self {
message: message.into(),
}
}
}
#[wasm_bindgen] #[wasm_bindgen]
impl PteropusCanvas { impl PteropusCanvas {
async fn init(&self) { async fn init(&self) -> Result<(), PteropusInitError> {
let html_canvas = self.get_canvas(); let html_canvas = self.get_canvas();
let size = Size2i { let size = Size2i {
width: html_canvas.client_width() as u32, width: html_canvas.client_width() as u32,
@ -62,15 +76,17 @@ impl PteropusCanvas {
}; };
let instance = wgpu::Instance::default(); let instance = wgpu::Instance::default();
let surface_target = SurfaceTarget::Canvas(html_canvas); let surface_target = SurfaceTarget::Canvas(html_canvas);
let surface = instance let surface = instance.create_surface(surface_target).map_err(|_| {
.create_surface(surface_target) PteropusInitError::new(
.expect("create graphics surface for canvas"); "Could not initialize canvas. This browser may not support WebGPU.",
)
})?;
self.app self.app
.lock() .lock()
.expect("get app mutex") .expect("get app mutex")
.init(&instance, surface, size, Box::new(FrameTimer::new())) .init(&instance, surface, size, Box::new(FrameTimer::new()))
.await; .await;
Ok(())
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -134,11 +150,11 @@ impl PteropusCanvas {
} }
} }
pub async fn run(app: App, model: Rc<Model>) -> PteropusCanvas { pub async fn run(app: App, model: Rc<Model>) -> Result<PteropusCanvas, PteropusInitError> {
let app = Rc::new(Mutex::new(app)); let app = Rc::new(Mutex::new(app));
std::panic::set_hook(Box::new(console_error_panic_hook::hook)); std::panic::set_hook(Box::new(console_error_panic_hook::hook));
console_log::init_with_level(log::Level::Info).expect("Couldn't initialize logger"); console_log::init_with_level(log::Level::Info).expect("Couldn't initialize logger");
let pteropus_canvas = PteropusCanvas { app, model }; let pteropus_canvas = PteropusCanvas { app, model };
pteropus_canvas.init().await; pteropus_canvas.init().await?;
pteropus_canvas Ok(pteropus_canvas)
} }

View File

@ -1,4 +1,4 @@
import init, {init_pteropus} from '../pkg/pteropus.js'; import init, {init_pteropus, PteropusInitError} from '../pkg/pteropus.js';
function fileDragOverHandler(event) { function fileDragOverHandler(event) {
event.preventDefault(); event.preventDefault();
@ -7,13 +7,26 @@ function fileDragOverHandler(event) {
async function run() { async function run() {
await init(); await init();
let pteropus = await init_pteropus(); try {
let pteropus = await init_pteropus();
} catch(e) {
const errorParagraph = document.createElement("p");
if(e instanceof PteropusInitError) {
const errorMessage = document.createTextNode(e.message);
errorParagraph.appendChild(errorMessage);
} else {
const errorMessage = document.createTextNode("Something unexpected happened.");
errorParagraph.appendChild(errorMessage);
}
document.getElementById("whole-window").replaceWith(errorParagraph);
return;
}
let test_file_data = null; let test_file_data = null;
let needs_resize = true; let needs_resize = true;
let clear_scene = false; let clear_scene = false;
let mainCanvas = document.getElementById("pteropus-canvas"); const mainCanvas = document.getElementById("pteropus-canvas");
mainCanvas.addEventListener("drop", async (event) => { mainCanvas.addEventListener("drop", async (event) => {
event.preventDefault(); event.preventDefault();
test_file_data = event.dataTransfer.files[0] test_file_data = event.dataTransfer.files[0]
@ -24,7 +37,7 @@ async function run() {
}); });
resizeObserver.observe(mainCanvas); resizeObserver.observe(mainCanvas);
let fileUploadButton = document.getElementById("file-upload-file-input"); const fileUploadButton = document.getElementById("file-upload-file-input");
fileUploadButton.addEventListener("change", () => { fileUploadButton.addEventListener("change", () => {
const files = fileUploadButton.files; const files = fileUploadButton.files;
if(files.length > 0) { if(files.length > 0) {
@ -32,7 +45,7 @@ async function run() {
} }
}); });
let clearSceneButton = document.getElementById("clear-scene-button"); const clearSceneButton = document.getElementById("clear-scene-button");
clearSceneButton.addEventListener("click", () => { clearSceneButton.addEventListener("click", () => {
clear_scene = true; clear_scene = true;
}); });