diff --git a/src/mail/mod.rs b/src/mail/mod.rs index e3db850..77e66ae 100644 --- a/src/mail/mod.rs +++ b/src/mail/mod.rs @@ -12,7 +12,10 @@ use panorama_imap::{ }, command::Command as ImapCommand, }; -use tokio::{sync::mpsc::UnboundedReceiver, task::JoinHandle}; +use tokio::{ + sync::mpsc::{UnboundedReceiver, UnboundedSender}, + task::JoinHandle, +}; use tokio_stream::wrappers::WatchStream; use crate::config::{Config, ConfigWatcher, ImapAuth, MailAccountConfig, TlsMethod}; @@ -26,10 +29,14 @@ pub enum MailCommand { Raw(ImapCommand), } +/// Possible events returned from the server that should be sent to the UI +pub enum MailEvent {} + /// Main entrypoint for the mail listener. pub async fn run_mail( mut config_watcher: ConfigWatcher, - _cmd_in: UnboundedReceiver, + ui2mail_rx: UnboundedReceiver, + mail2ui_tx: UnboundedSender, ) -> Result<()> { let mut curr_conn: Vec> = Vec::new(); @@ -53,6 +60,8 @@ pub async fn run_mail( for acct in config.mail_accounts.into_iter() { let handle = tokio::spawn(async move { // debug!("opening imap connection for {:?}", acct); + + // this loop is to make sure accounts are restarted on error loop { match imap_main(acct.clone()).await { Ok(_) => {} @@ -62,6 +71,13 @@ pub async fn run_mail( } warn!("connection dropped, retrying"); + + // wait a bit so we're not hitting the server really fast if the fail happens + // early on + // + // TODO: some kind of smart exponential backoff that considers some time + // threshold to be a failing case? + tokio::time::sleep(std::time::Duration::from_secs(5)).await; } }); curr_conn.push(handle); @@ -96,9 +112,12 @@ async fn imap_main(acct: MailAccountConfig) -> Result<()> { debug!("preparing to auth"); // check if the authentication method is supported - let mut authed = match acct.imap.auth { + let mut authed = match &acct.imap.auth { ImapAuth::Plain { username, password } => { - let auth = auth::Plain { username, password }; + let auth = auth::Plain { + username: username.clone(), + password: password.clone(), + }; auth.perform_auth(unauth).await? } }; @@ -118,7 +137,22 @@ async fn imap_main(acct: MailAccountConfig) -> Result<()> { loop { idle_stream.next().await; debug!("got an event"); + + if false { + break; + } + } + + if false { + break; } } + + // wait a bit so we're not hitting the server really fast if the fail happens + // early on + // + // TODO: some kind of smart exponential backoff that considers some time + // threshold to be a failing case? + tokio::time::sleep(std::time::Duration::from_secs(5)).await; } } diff --git a/src/main.rs b/src/main.rs index abc4ecb..800f057 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,12 +49,15 @@ async fn run(opt: Opt) -> Result<()> { // used to notify the runtime that the process should exit let (exit_tx, mut exit_rx) = mpsc::channel::<()>(1); - // used to send commands to the mail service - let (_mail_tx, mail_rx) = mpsc::unbounded_channel(); + // send messages from the UI thread to the mail thread + let (ui2mail_tx, ui2mail_rx) = mpsc::unbounded_channel(); + + // send messages from the mail thread to the UI thread + let (mail2ui_tx, mail2ui_rx) = mpsc::unbounded_channel(); tokio::spawn(async move { let config_update = config_update.clone(); - mail::run_mail(config_update, mail_rx) + mail::run_mail(config_update, ui2mail_rx, mail2ui_tx) .unwrap_or_else(report_err) .await; }); diff --git a/src/ui/mail_tab.rs b/src/ui/mail_tab.rs new file mode 100644 index 0000000..2e0c4e2 --- /dev/null +++ b/src/ui/mail_tab.rs @@ -0,0 +1,19 @@ +use tui::{widgets::{Widget, StatefulWidget}, buffer::Buffer, layout::Rect}; + +pub struct MailTabState { +} + +impl MailTabState { + pub fn new() -> Self { + MailTabState{} + } +} + +pub struct MailTab; + +impl StatefulWidget for MailTab { + type State = MailTabState; + + fn render(self, rect: Rect, buffer: &mut Buffer, state: &mut Self::State) { + } +} diff --git a/src/ui/mod.rs b/src/ui/mod.rs index c04a358..80fff29 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,5 +1,7 @@ //! UI library +mod mail_tab; + use std::io::Stdout; use std::mem; use std::time::Duration; @@ -17,9 +19,14 @@ use tui::{ style::{Color, Modifier, Style}, text::Spans, widgets::*, + Frame, Terminal, }; +use self::mail_tab::{MailTabState, MailTab}; + +// pub(crate) type FrameType<'a> = Frame<'a, CrosstermBackend>; + const FRAME_DURATION: Duration = Duration::from_millis(17); /// Main entrypoint for the UI @@ -28,10 +35,12 @@ pub async fn run_ui(mut stdout: Stdout, exit_tx: mpsc::Sender<()>) -> Result<()> terminal::enable_raw_mode()?; let backend = CrosstermBackend::new(&mut stdout); - let mut terminal = Terminal::new(backend)?; + let mut term = Terminal::new(backend)?; + + let mut mail_state = MailTabState::new(); loop { - terminal.draw(|f| { + term.draw(|f| { let chunks = Layout::default() .direction(Direction::Vertical) .margin(0) @@ -44,35 +53,37 @@ pub async fn run_ui(mut stdout: Stdout, exit_tx: mpsc::Sender<()>) -> Result<()> ]) .split(f.size()); - let chunks2 = Layout::default() - .direction(Direction::Horizontal) - .margin(0) - .constraints([ - Constraint::Length(20), - Constraint::Max(5000), - // - ]) - .split(chunks[1]); + // let chunks2 = Layout::default() + // .direction(Direction::Horizontal) + // .margin(0) + // .constraints([ + // Constraint::Length(20), + // Constraint::Max(5000), + // // + // ]) + // .split(chunks[1]); // this is the title bar let titles = vec!["hellosu"].into_iter().map(Spans::from).collect(); let tabs = Tabs::new(titles); f.render_widget(tabs, chunks[0]); + let mail_tab = MailTab; + f.render_stateful_widget(mail_tab, chunks[1], &mut mail_state); // TODO: check active tab - let items = [ - ListItem::new("Osu"), - ListItem::new("Game").style(Style::default().add_modifier(Modifier::BOLD)), - ]; - let dirlist = List::new(items) - .block(Block::default().title("List").borders(Borders::ALL)) - .style(Style::default().fg(Color::White)) - .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) - .highlight_symbol(">>"); - f.render_widget(dirlist, chunks2[0]); + // let items = [ + // ListItem::new("Osu"), + // ListItem::new("Game").style(Style::default().add_modifier(Modifier::BOLD)), + // ]; + // let dirlist = List::new(items) + // .block(Block::default().title("List").borders(Borders::ALL)) + // .style(Style::default().fg(Color::White)) + // .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + // .highlight_symbol(">>"); + // f.render_widget(dirlist, chunks2[0]); - let block = Block::default().title("Block").borders(Borders::ALL); - f.render_widget(block, chunks2[1]); + // let block = Block::default().title("Block").borders(Borders::ALL); + // f.render_widget(block, chunks2[1]); // let block = Block::default().title("Block 2").borders(Borders::ALL); // f.render_widget(block, chunks[1]); @@ -108,7 +119,7 @@ pub async fn run_ui(mut stdout: Stdout, exit_tx: mpsc::Sender<()>) -> Result<()> // } } - mem::drop(terminal); + mem::drop(term); execute!( stdout,