maybe i shouldn't be using a widget impl?
This commit is contained in:
parent
84cd7ae0f4
commit
f0e5042a76
4 changed files with 98 additions and 31 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
19
src/ui/mail_tab.rs
Normal 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) {
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue