use std::time::Duration;
use crossbeam_channel::Sender;
use maildir::Maildir as ExtMaildir;
use serde_derive::Deserialize;
use crate::blocks::{Block, ConfigBlock, Update};
use crate::config::SharedConfig;
use crate::de::deserialize_duration;
use crate::errors::*;
use crate::scheduler::Task;
use crate::util::expand_string;
use crate::widgets::text::TextWidget;
use crate::widgets::{I3BarWidget, State};
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum MailType {
New,
Cur,
All,
}
impl MailType {
fn count_mail(&self, maildir: &ExtMaildir) -> usize {
match self {
MailType::New => maildir.count_new(),
MailType::Cur => maildir.count_cur(),
MailType::All => maildir.count_new() + maildir.count_cur(),
}
}
}
pub struct Maildir {
text: TextWidget,
update_interval: Duration,
inboxes: Vec<String>,
threshold_warning: usize,
threshold_critical: usize,
display_type: MailType,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields, default)]
pub struct MaildirConfig {
#[serde(deserialize_with = "deserialize_duration")]
pub interval: Duration,
pub inboxes: Vec<String>,
pub threshold_warning: usize,
pub threshold_critical: usize,
pub display_type: MailType,
pub icon: bool,
}
impl Default for MaildirConfig {
fn default() -> Self {
Self {
interval: Duration::from_secs(5),
inboxes: Vec::new(),
threshold_warning: 1,
threshold_critical: 10,
display_type: MailType::New,
icon: true,
}
}
}
impl ConfigBlock for Maildir {
type Config = MaildirConfig;
fn new(
id: usize,
mut block_config: Self::Config,
shared_config: SharedConfig,
_tx_update_request: Sender<Task>,
) -> Result<Self> {
for inbox in &mut block_config.inboxes {
*inbox = expand_string(inbox)?;
}
let widget = TextWidget::new(id, 0, shared_config).with_text("");
Ok(Maildir {
update_interval: block_config.interval,
text: if block_config.icon {
widget.with_icon("mail")?
} else {
widget
},
inboxes: block_config.inboxes,
threshold_warning: block_config.threshold_warning,
threshold_critical: block_config.threshold_critical,
display_type: block_config.display_type,
})
}
}
impl Block for Maildir {
fn name(&self) -> &'static str {
"maildir"
}
fn update(&mut self) -> Result<Option<Update>> {
let mut newmails = 0;
for inbox in &self.inboxes {
let isl: &str = &inbox[..];
let maildir = ExtMaildir::from(isl);
newmails += self.display_type.count_mail(&maildir)
}
let mut state = State::Idle;
if newmails >= self.threshold_critical {
state = State::Critical;
} else if newmails >= self.threshold_warning {
state = State::Warning;
}
self.text.set_state(state);
self.text.set_text(format!("{}", newmails));
Ok(Some(self.update_interval.into()))
}
fn view(&self) -> Vec<&dyn I3BarWidget> {
vec![&self.text]
}
}