1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 22:00:03 -04:00

eframe web: detect and report panics during startup (#2992)

* Detect panics during initialization and show them to the user

* PanicHandler now also logs the panics

* Add example of how to call into your app from JS

* Refactor: break out AppRunner and AppRunnerRef to own files

* Hide AppRunner

* Simplify user code

* AppRunnerRef -> WebRunner

* Better docs

* Don't paint until first animation frame

* Update multiple_apps.html

* Update web demo

* Cleanup and fixes

* left-align panic message in html
This commit is contained in:
Emil Ernerfeldt
2023-05-16 22:22:09 +02:00
committed by GitHub
parent ff8e4826b3
commit ea71b7f20b
15 changed files with 791 additions and 716 deletions

View File

@@ -1,30 +1,11 @@
use super::*;
// ------------------------------------------------------------------------
/// Calls `request_animation_frame` to schedule repaint.
///
/// It will only paint if needed, but will always call `request_animation_frame` immediately.
pub fn paint_and_schedule(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
fn paint_if_needed(runner: &mut AppRunner) -> Result<(), JsValue> {
if runner.needs_repaint.when_to_repaint() <= now_sec() {
runner.needs_repaint.clear();
let (repaint_after, clipped_primitives) = runner.logic()?;
runner.paint(&clipped_primitives)?;
runner
.needs_repaint
.repaint_after(repaint_after.as_secs_f64());
runner.auto_save_if_needed();
}
Ok(())
}
fn request_animation_frame(runner_ref: AppRunnerRef) -> Result<(), JsValue> {
let window = web_sys::window().unwrap();
let closure = Closure::once(move || paint_and_schedule(&runner_ref));
window.request_animation_frame(closure.as_ref().unchecked_ref())?;
closure.forget(); // We must forget it, or else the callback is canceled on drop
Ok(())
}
fn paint_and_schedule(runner_ref: &WebRunner) -> Result<(), JsValue> {
// Only paint and schedule if there has been no panic
if let Some(mut runner_lock) = runner_ref.try_lock() {
paint_if_needed(&mut runner_lock)?;
@@ -35,7 +16,30 @@ pub fn paint_and_schedule(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
Ok(())
}
pub fn install_document_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
fn paint_if_needed(runner: &mut AppRunner) -> Result<(), JsValue> {
if runner.needs_repaint.when_to_repaint() <= now_sec() {
runner.needs_repaint.clear();
let (repaint_after, clipped_primitives) = runner.logic();
runner.paint(&clipped_primitives)?;
runner
.needs_repaint
.repaint_after(repaint_after.as_secs_f64());
runner.auto_save_if_needed();
}
Ok(())
}
pub fn request_animation_frame(runner_ref: WebRunner) -> Result<(), JsValue> {
let window = web_sys::window().unwrap();
let closure = Closure::once(move || paint_and_schedule(&runner_ref));
window.request_animation_frame(closure.as_ref().unchecked_ref())?;
closure.forget(); // We must forget it, or else the callback is canceled on drop
Ok(())
}
// ------------------------------------------------------------------------
pub fn install_document_events(runner_ref: &WebRunner) -> Result<(), JsValue> {
let document = web_sys::window().unwrap().document().unwrap();
{
@@ -185,7 +189,7 @@ pub fn install_document_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue>
Ok(())
}
pub fn install_window_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
pub fn install_window_events(runner_ref: &WebRunner) -> Result<(), JsValue> {
let window = web_sys::window().unwrap();
// Save-on-close
@@ -207,7 +211,7 @@ pub fn install_window_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
Ok(())
}
pub fn install_color_scheme_change_event(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
pub fn install_color_scheme_change_event(runner_ref: &WebRunner) -> Result<(), JsValue> {
let window = web_sys::window().unwrap();
if let Some(media_query_list) = prefers_color_scheme_dark(&window)? {
@@ -226,7 +230,7 @@ pub fn install_color_scheme_change_event(runner_ref: &AppRunnerRef) -> Result<()
Ok(())
}
pub fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
pub fn install_canvas_events(runner_ref: &WebRunner) -> Result<(), JsValue> {
let canvas = canvas_element(runner_ref.try_lock().unwrap().canvas_id()).unwrap();
{