1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
use super::{app::AppActions, dialog::Dialog};
use crate::interactive::component::{Component, Frame};
use crossterm::event::{Event, KeyCode, KeyEvent};
use parking_lot::Mutex;
use std::sync::Arc;
use tui::layout::Rect;
pub struct ErrorMessage {
pub message: String,
pub ignorable: bool,
}
pub struct ErrorHandler<T: Component> {
actions: AppActions,
error: Arc<Mutex<Option<ErrorMessage>>>,
child: T,
}
impl<T: Component> ErrorHandler<T> {
pub fn new(actions: AppActions, receiver: flume::Receiver<ErrorMessage>, child: T) -> Self {
let new_error_handler = Self {
actions,
error: Arc::new(Mutex::new(None)),
child,
};
new_error_handler.listen_error_messages(receiver);
new_error_handler
}
fn listen_error_messages(&self, receiver: flume::Receiver<ErrorMessage>) {
let actions = self.actions.clone();
let error = self.error.clone();
tokio::spawn(async move {
while let Ok(new_error) = receiver.recv_async().await {
{
let mut error = error.lock();
*error = Some(new_error);
}
actions.redraw_async().await;
}
});
}
}
impl<T: Component> Component for ErrorHandler<T> {
fn draw(&mut self, f: &mut Frame<'_>, area: Rect) {
self.child.draw(f, area);
if let Some(ref error) = *self.error.lock() {
Dialog::new("An error occured", &error.message).draw(f, area);
}
}
fn handle_event(&mut self, event: Event) {
let mut error = self.error.lock();
if let Some(ErrorMessage { ignorable, .. }) = *error {
if ignorable && event == Event::Key(KeyEvent::from(KeyCode::Esc)) {
*error = None;
self.actions.redraw();
}
} else {
self.child.handle_event(event);
}
}
}
|