Add ui_dialogs in State

async
Manos Pitsidianakis 2020-02-19 17:01:13 +02:00
parent a806571322
commit e3abd458ce
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
1 changed files with 127 additions and 74 deletions

View File

@ -194,6 +194,7 @@ pub struct State {
pub context: Context,
timer: thread::JoinHandle<()>,
ui_dialogs: Vec<Box<dyn Component>>,
display_messages: SmallVec<[DisplayMessage; 8]>,
display_messages_expiration_start: Option<UnixTimestamp>,
display_messages_active: bool,
@ -493,6 +494,33 @@ impl State {
));
}
}
if !self.ui_dialogs.is_empty() {
let area = center_area(
(
(0, 0),
(self.cols.saturating_sub(1), self.rows.saturating_sub(1)),
),
(
if self.cols / 3 > 30 {
self.cols / 3
} else {
self.cols
},
if self.rows / 5 > 10 {
self.rows / 5
} else {
self.rows
},
),
);
areas.push(area);
let area = create_box(&mut self.overlay_grid, area);
self.ui_dialogs.get_mut(0).unwrap().draw(
&mut self.overlay_grid,
area,
&mut self.context,
);
}
/* Sort by x_start, ie upper_left corner's x coordinate */
areas.sort_by(|a, b| (a.0).0.partial_cmp(&(b.0).0).unwrap());
@ -743,20 +771,17 @@ impl State {
}
/// Convert user commands to actions/method calls.
fn parse_command(&mut self, cmd: &str) {
let result = parse_command(&cmd.as_bytes()).to_full_result();
if let Ok(v) = result {
match v {
fn exec_command(&mut self, cmd: Action) {
match cmd {
SetEnv(key, val) => {
env::set_var(key.as_str(), val.as_str());
}
PrintEnv(key) => {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(
self.context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
env::var(key.as_str()).unwrap_or_else(|e| e.to_string()),
),
));
)));
}
Folder(account_name, op) => {
if let Some(account) = self
@ -773,10 +798,7 @@ impl State {
}
Ok(msg) => {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
"`{}`: {}",
account_name, msg
)),
StatusEvent::DisplayMessage(format!("`{}`: {}", account_name, msg)),
));
}
}
@ -821,13 +843,6 @@ impl State {
self.rcv_event(UIEvent::Action(v));
}
}
} else {
self.context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
"invalid command".to_string(),
)));
}
}
/// The application's main loop sends `UIEvents` to state via this method.
@ -841,7 +856,33 @@ impl State {
match event {
// Command type is handled only by State.
UIEvent::Command(cmd) => {
self.parse_command(&cmd);
if let Ok(action) = parse_command(&cmd.as_bytes()).to_full_result() {
if action.needs_confirmation() {
let action = std::sync::Arc::new(action);
self.ui_dialogs.push(Box::new(UIConfirmationDialog::new(
"You sure?",
vec![(true, "yes".to_string()), (false, "no".to_string())],
true,
std::sync::Arc::new(move |result: bool| {
if result {
Some(UIEvent::FinishedUIDialog(
ComponentId::nil(),
Box::new(action.clone()),
))
} else {
None
}
}),
&mut self.context,
)));
} else {
self.exec_command(action);
}
} else {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage("invalid command".to_string()),
));
}
return;
}
UIEvent::Fork(ForkType::Finished) => {
@ -908,6 +949,18 @@ impl State {
self.display_messages_active = true;
self.display_messages_pos = self.display_messages.len() - 1;
}
UIEvent::FinishedUIDialog(ref id, ref mut results)
if self.ui_dialogs.get(0).map(|c| c.id()) == Some(*id) =>
{
if let Some(ref mut action) = results.downcast_mut::<Action>() {
self.exec_command(std::mem::replace(action, Action::ToggleThreadSnooze));
return;
}
}
UIEvent::GlobalUIDialog(dialog) => {
self.ui_dialogs.push(dialog);
return;
}
_ => {}
}
/* inform each component */