Unrecoverable errors as native dialogs

This commit is contained in:
Jonathan Johnson 2024-10-07 08:06:07 -07:00
parent 06c3391379
commit f96a5d2055
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
3 changed files with 80 additions and 42 deletions

View file

@ -68,6 +68,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `WrapperWidget::activate`'s default implementation now activates the wrapped
widget.
- `Space` now intercepts mouse events if its color has a non-zero alpha channel.
- `Image` now honors `CornerRadius`. Thanks to @danbulant for this change!
### Fixed
@ -203,6 +204,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `Dimension::is_unbounded` is a new helper that returns true if neither the
start or end is bounded.
- `&String` and `Cow<'_, str>` now implement `MakeWidget`.
- Cargo feature `native-dialogs` has been added to enable native dialogs to be
shown by Cushy applications.
- `PendingApp::with_on_unrecoverable_error` allows overriding the default
behavior when an unrecoverable error occurs. Previously, all unrecoverable
errors resulted in a panic. The new default behavior uses the `native-dialogs`
feature when enabled to display the error using a system-native message
dialog.
- `MessageBox` displays a prompt to the user in a `Modal` layer, above a
`WindowHandle`, or in an `App`. When shown above a window or app, the `rfd`
crate is used to use the native system dialogs.

71
Cargo.lock generated
View file

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "ab_glyph"
version = "0.2.28"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79faae4620f45232f599d9bc7b290f88247a0834162c4495ab2f02d60004adfb"
checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0"
dependencies = [
"ab_glyph_rasterizer",
"owned_ttf_parser",
@ -124,7 +124,7 @@ checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]]
name = "appit"
version = "0.4.0"
source = "git+https://github.com/khonsulabs/appit#662cebf193a9adc1b2f19cf048fb8a359f74059a"
source = "git+https://github.com/khonsulabs/appit#be6918d5ebb6a2ad7911f621bb7db3676ce8b290"
dependencies = [
"darkmode",
"winit",
@ -617,9 +617,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.1.24"
version = "1.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938"
checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1"
dependencies = [
"jobserver",
"libc",
@ -1267,24 +1267,24 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.30"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.30"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-io"
version = "0.3.30"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-lite"
@ -1301,9 +1301,9 @@ dependencies = [
[[package]]
name = "futures-macro"
version = "0.3.30"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
@ -1312,21 +1312,21 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.30"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
name = "futures-task"
version = "0.3.30"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-util"
version = "0.3.30"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-core",
"futures-io",
@ -1729,7 +1729,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "kludgine"
version = "0.11.0"
source = "git+https://github.com/khonsulabs/kludgine#58e83f1200375673300918c82f622c499a4028fa"
source = "git+https://github.com/khonsulabs/kludgine#3ce7d43f8870a3455f46ab2c2fba997ca36a1f60"
dependencies = [
"ahash",
"alot",
@ -2412,12 +2412,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.20.1"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1"
dependencies = [
"portable-atomic",
]
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "orbclient"
@ -2446,11 +2443,11 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "owned_ttf_parser"
version = "0.24.0"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490d3a563d3122bf7c911a59b0add9389e5ec0f5f0c3ac6b91ff235a0e6a7f90"
checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4"
dependencies = [
"ttf-parser 0.24.1",
"ttf-parser 0.25.0",
]
[[package]]
@ -2562,18 +2559,18 @@ dependencies = [
[[package]]
name = "pin-project"
version = "1.1.5"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8"
dependencies = [
"proc-macro2",
"quote",
@ -2661,12 +2658,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
[[package]]
name = "portable-atomic"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
@ -3598,9 +3589,9 @@ checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8"
[[package]]
name = "ttf-parser"
version = "0.24.1"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a"
checksum = "5902c5d130972a0000f60860bfbf46f7ca3db5391eddfedd1b8728bd9dc96c0e"
[[package]]
name = "typenum"

View file

@ -6,7 +6,7 @@ use std::time::Duration;
use arboard::Clipboard;
use kludgine::app::winit::error::EventLoopError;
use kludgine::app::{AppEvent, AsApplication, ExecutingApp, Monitors};
use kludgine::app::{AppEvent, AsApplication, ExecutingApp, Monitors, UnrecoverableError};
use parking_lot::{Mutex, MutexGuard};
use crate::fonts::FontCollection;
@ -59,12 +59,34 @@ impl PendingApp {
/// [`with_tracing()`](Self::with_tracing)/[`initialize_tracing()`](Self::initialize_tracing)
/// to enable Cushy's built-in trace handling.
pub fn new<Runtime: AppRuntime>(runtime: Runtime) -> Self {
let mut app = kludgine::app::PendingApp::default();
app.on_unrecoverable_error(Self::unrecoverable_error);
Self {
app: kludgine::app::PendingApp::default(),
app,
cushy: Cushy::new(BoxedRuntime(Box::new(runtime))),
}
}
/// Sets the error handler that is invoked when Cushy encounters an error
/// that it cannot recover from.
///
/// # Default Behavior
///
/// If `native-dialogs` is enabled, the default handler will display the
/// error using a system-native message dialog. Otherwise, the default
/// handler will panic.
///
/// Calling this function will override the default behavior with
/// `on_error`.
#[must_use]
pub fn with_on_unrecoverable_error<F>(mut self, on_error: F) -> Self
where
F: FnMut(UnrecoverableError) + 'static,
{
self.app.on_unrecoverable_error(on_error);
self
}
/// Installs a global `tracing` Subscriber and returns self.
#[must_use]
pub fn with_tracing(self) -> Self {
@ -110,6 +132,23 @@ impl PendingApp {
});
});
}
#[cfg(feature = "native-dialogs")]
#[allow(clippy::needless_pass_by_value)]
fn unrecoverable_error(err: UnrecoverableError) {
let _ = rfd::MessageDialog::new()
.set_title("An unrecoverable error has occurred")
.set_description(err.to_string())
.set_level(rfd::MessageLevel::Error)
.show();
exit(-1);
}
#[cfg(not(feature = "native-dialogs"))]
#[allow(clippy::needless_pass_by_value)]
fn unrecoverable_error(err: UnrecoverableError) {
unreachable!("error initializing window: {err}");
}
}
impl Run for PendingApp {