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, pub context: Context,
timer: thread::JoinHandle<()>, timer: thread::JoinHandle<()>,
ui_dialogs: Vec<Box<dyn Component>>,
display_messages: SmallVec<[DisplayMessage; 8]>, display_messages: SmallVec<[DisplayMessage; 8]>,
display_messages_expiration_start: Option<UnixTimestamp>, display_messages_expiration_start: Option<UnixTimestamp>,
display_messages_active: bool, 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 */ /* 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()); areas.sort_by(|a, b| (a.0).0.partial_cmp(&(b.0).0).unwrap());
@ -743,90 +771,77 @@ impl State {
} }
/// Convert user commands to actions/method calls. /// Convert user commands to actions/method calls.
fn parse_command(&mut self, cmd: &str) { fn exec_command(&mut self, cmd: Action) {
let result = parse_command(&cmd.as_bytes()).to_full_result(); match cmd {
SetEnv(key, val) => {
if let Ok(v) = result { env::set_var(key.as_str(), val.as_str());
match v { }
SetEnv(key, val) => { PrintEnv(key) => {
env::set_var(key.as_str(), val.as_str()); self.context
} .replies
PrintEnv(key) => { .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
.context
.accounts
.iter_mut()
.find(|a| a.name() == account_name)
{
match account.folder_operation(op) {
Err(err) => {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(err.to_string()),
));
}
Ok(msg) => {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!("`{}`: {}", account_name, msg)),
));
}
}
} else {
self.context.replies.push_back(UIEvent::StatusEvent( self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage( StatusEvent::DisplayMessage(format!(
env::var(key.as_str()).unwrap_or_else(|e| e.to_string()), "Account with name `{}` not found.",
), account_name
)),
)); ));
} }
Folder(account_name, op) => { }
if let Some(account) = self AccountAction(ref account_name, ReIndex) => {
.context #[cfg(feature = "sqlite3")]
.accounts match crate::sqlite3::index(&mut self.context, account_name) {
.iter_mut() Ok(()) => {
.find(|a| a.name() == account_name)
{
match account.folder_operation(op) {
Err(err) => {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(err.to_string()),
));
}
Ok(msg) => {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
"`{}`: {}",
account_name, msg
)),
));
}
}
} else {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
"Account with name `{}` not found.",
account_name
)),
));
}
}
AccountAction(ref account_name, ReIndex) => {
#[cfg(feature = "sqlite3")]
match crate::sqlite3::index(&mut self.context, account_name) {
Ok(()) => {
self.context.replies.push_back(UIEvent::Notification(
None,
"Message index rebuild started.".to_string(),
Some(NotificationType::INFO),
));
}
Err(e) => {
self.context.replies.push_back(UIEvent::Notification(
None,
format!("Message index rebuild failed: {}.", e),
Some(NotificationType::ERROR),
));
}
}
#[cfg(not(feature = "sqlite3"))]
{
self.context.replies.push_back(UIEvent::Notification( self.context.replies.push_back(UIEvent::Notification(
None, None,
"Message index rebuild failed: meli is not built with sqlite3 support." "Message index rebuild started.".to_string(),
.to_string(), Some(NotificationType::INFO),
));
}
Err(e) => {
self.context.replies.push_back(UIEvent::Notification(
None,
format!("Message index rebuild failed: {}.", e),
Some(NotificationType::ERROR), Some(NotificationType::ERROR),
)); ));
} }
} }
v => { #[cfg(not(feature = "sqlite3"))]
self.rcv_event(UIEvent::Action(v)); {
self.context.replies.push_back(UIEvent::Notification(
None,
"Message index rebuild failed: meli is not built with sqlite3 support."
.to_string(),
Some(NotificationType::ERROR),
));
} }
} }
} else { v => {
self.context self.rcv_event(UIEvent::Action(v));
.replies }
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
"invalid command".to_string(),
)));
} }
} }
@ -841,7 +856,33 @@ impl State {
match event { match event {
// Command type is handled only by State. // Command type is handled only by State.
UIEvent::Command(cmd) => { 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; return;
} }
UIEvent::Fork(ForkType::Finished) => { UIEvent::Fork(ForkType::Finished) => {
@ -908,6 +949,18 @@ impl State {
self.display_messages_active = true; self.display_messages_active = true;
self.display_messages_pos = self.display_messages.len() - 1; 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 */ /* inform each component */