maybe i shouldn't be using a widget impl?

This commit is contained in:
Michael Zhang 2021-03-01 03:50:20 -06:00
parent 84cd7ae0f4
commit f0e5042a76
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
4 changed files with 98 additions and 31 deletions

View file

@ -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<MailCommand>,
ui2mail_rx: UnboundedReceiver<MailCommand>,
mail2ui_tx: UnboundedSender<MailEvent>,
) -> Result<()> {
let mut curr_conn: Vec<JoinHandle<_>> = 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;
}
}

View file

@ -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;
});

19
src/ui/mail_tab.rs Normal file
View file

@ -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) {
}
}

View file

@ -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<Stdout>>;
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,