Skip to content

Commit

Permalink
show alert dialog on error
Browse files Browse the repository at this point in the history
  • Loading branch information
rhysd committed Nov 7, 2023
1 parent 1adb1b2 commit d1bba0d
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 24 deletions.
2 changes: 1 addition & 1 deletion v2/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ impl UserConfig {
match fs::read(&path) {
Ok(bytes) =>
return serde_yaml::from_slice(&bytes)
.with_context(|| format!("Could not parse config file as YAML: {:?}. To reset config file, try --generate-config-file", path)),
.with_context(|| format!("Could not parse a configuration file at {:?}. To reset config file, try --generate-config-file", path)),
Err(err) => {
log::debug!("Could not read config file from {:?}: {}", path, err);
}
Expand Down
19 changes: 14 additions & 5 deletions v2/src/dialog.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
use crate::config::FileExtensions;
use rfd::FileDialog;
use rfd::{FileDialog, MessageDialog, MessageLevel};
use std::path::{Path, PathBuf};

pub trait Dialog: Default {
fn pick_file(&mut self, dir: &Path, extensions: &FileExtensions) -> Option<PathBuf>;
fn pick_dir(&mut self, dir: &Path) -> Option<PathBuf>;
fn pick_file(&self, dir: &Path, extensions: &FileExtensions) -> Option<PathBuf>;
fn pick_dir(&self, dir: &Path) -> Option<PathBuf>;
fn alert(&self, title: impl Into<String>, message: impl Into<String>);
}

#[derive(Default)]
pub struct SystemDialog;

impl Dialog for SystemDialog {
fn pick_file(&mut self, dir: &Path, extensions: &FileExtensions) -> Option<PathBuf> {
fn pick_file(&self, dir: &Path, extensions: &FileExtensions) -> Option<PathBuf> {
// `FileDialog::add_filter` requires `&[&str]` but we have `Vec<String>` in config
let extensions: Vec<&str> = extensions.as_slice().iter().map(String::as_str).collect();
FileDialog::new().add_filter("Markdown", &extensions).set_directory(dir).pick_file()
}

fn pick_dir(&mut self, dir: &Path) -> Option<PathBuf> {
fn pick_dir(&self, dir: &Path) -> Option<PathBuf> {
FileDialog::new().set_directory(dir).pick_folder()
}

fn alert(&self, title: impl Into<String>, message: impl Into<String>) {
MessageDialog::new()
.set_level(MessageLevel::Error)
.set_title(title.into())
.set_description(message.into())
.show();
}
}
1 change: 1 addition & 0 deletions v2/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,5 @@ pub trait EventHandler {
fn handle_user_event(&mut self, event: UserEvent) -> Result<RenderingFlow>;
fn handle_menu_event(&mut self, item: MenuItem) -> Result<RenderingFlow>;
fn handle_exit(&self) -> Result<()>;
fn handle_error(&self, err: Error) -> RenderingFlow;
}
28 changes: 25 additions & 3 deletions v2/src/shiba.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use crate::renderer::{
RenderingFlow, UserEvent,
};
use crate::watcher::{PathFilter, Watcher};
use anyhow::{Context as _, Result};
use anyhow::{Context as _, Error, Result};
use std::collections::VecDeque;
use std::fmt::Write as _;
use std::fs;
use std::mem;
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
Expand Down Expand Up @@ -188,6 +189,17 @@ impl PreviewContent {
}
}

fn alert_error<D: Dialog>(dialog: &D, error: &Error) {
let mut errs = error.chain();
let title = format!("Error: {}", errs.next().unwrap());
let mut message = title.clone();
for err in errs {
write!(message, "\n Caused by: {}", err).unwrap();
}
log::error!("{}", message);
dialog.alert(title, message);
}

pub struct Shiba<R: Rendering, O, W, D> {
renderer: R::Renderer,
opener: O,
Expand All @@ -210,8 +222,13 @@ where
where
Self: 'static,
{
let mut rendering = R::new()?;
let dog = Self::new(options, &mut rendering)?;
fn on_err<D: Dialog>(err: Error) -> Error {
let err = err.context("Could not launch application");
alert_error(&D::default(), &err);
err
}
let mut rendering = R::new().map_err(on_err::<D>)?;
let dog = Self::new(options, &mut rendering).map_err(on_err::<D>)?;
rendering.start(dog)
}

Expand Down Expand Up @@ -506,4 +523,9 @@ where
data_dir.save_recent_files(self.history.iter(), self.config.max_recent_files())?;
Ok(())
}

fn handle_error(&self, err: Error) -> RenderingFlow {
alert_error(&self.dialog, &err);
RenderingFlow::Continue
}
}
19 changes: 4 additions & 15 deletions v2/src/wry/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::config::Config;
use crate::renderer::{EventHandler, Rendering, RenderingFlow, UserEvent, UserEventSender};
use crate::wry::menu::{Menu, MenuEvents};
use crate::wry::webview::{EventLoop, WebViewRenderer};
use anyhow::{Error, Result};
use anyhow::Result;
use wry::application::event::{Event, StartCause, WindowEvent};
use wry::application::event_loop::{ControlFlow, EventLoopBuilder, EventLoopProxy};

Expand Down Expand Up @@ -73,12 +73,6 @@ impl Rendering for Wry {
H: EventHandler + 'static,
{
self.event_loop.run(move |event, _, control| {
fn log_causes(err: Error) {
for err in err.chain() {
log::error!(" Caused by: {}", err);
}
}

let flow = match event {
Event::NewEvents(StartCause::Init) => {
log::debug!("Application has started");
Expand All @@ -89,9 +83,7 @@ impl Rendering for Wry {
RenderingFlow::Exit
}
Event::UserEvent(event) => handler.handle_user_event(event).unwrap_or_else(|err| {
log::error!("Could not handle user event");
log_causes(err);
RenderingFlow::Continue
handler.handle_error(err.context("Could not handle user event"))
}),
_ => self
.menu_events
Expand All @@ -101,9 +93,7 @@ impl Rendering for Wry {
None => Ok(RenderingFlow::Continue),
})
.unwrap_or_else(|err| {
log::error!("Could not handle menu event");
log_causes(err);
RenderingFlow::Continue
handler.handle_error(err.context("Could not handle menu event"))
}),
};

Expand All @@ -112,8 +102,7 @@ impl Rendering for Wry {
RenderingFlow::Exit => match handler.handle_exit() {
Ok(()) => ControlFlow::Exit,
Err(err) => {
log::error!("Could not handle application exit correctly");
log_causes(err);
handler.handle_error(err.context("Could not handle application exit"));
ControlFlow::ExitWithCode(1)
}
},
Expand Down

0 comments on commit d1bba0d

Please sign in to comment.