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,
|
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 tokio_stream::wrappers::WatchStream;
|
||||||
|
|
||||||
use crate::config::{Config, ConfigWatcher, ImapAuth, MailAccountConfig, TlsMethod};
|
use crate::config::{Config, ConfigWatcher, ImapAuth, MailAccountConfig, TlsMethod};
|
||||||
|
@ -26,10 +29,14 @@ pub enum MailCommand {
|
||||||
Raw(ImapCommand),
|
Raw(ImapCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Possible events returned from the server that should be sent to the UI
|
||||||
|
pub enum MailEvent {}
|
||||||
|
|
||||||
/// Main entrypoint for the mail listener.
|
/// Main entrypoint for the mail listener.
|
||||||
pub async fn run_mail(
|
pub async fn run_mail(
|
||||||
mut config_watcher: ConfigWatcher,
|
mut config_watcher: ConfigWatcher,
|
||||||
_cmd_in: UnboundedReceiver<MailCommand>,
|
ui2mail_rx: UnboundedReceiver<MailCommand>,
|
||||||
|
mail2ui_tx: UnboundedSender<MailEvent>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut curr_conn: Vec<JoinHandle<_>> = Vec::new();
|
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() {
|
for acct in config.mail_accounts.into_iter() {
|
||||||
let handle = tokio::spawn(async move {
|
let handle = tokio::spawn(async move {
|
||||||
// debug!("opening imap connection for {:?}", acct);
|
// debug!("opening imap connection for {:?}", acct);
|
||||||
|
|
||||||
|
// this loop is to make sure accounts are restarted on error
|
||||||
loop {
|
loop {
|
||||||
match imap_main(acct.clone()).await {
|
match imap_main(acct.clone()).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
@ -62,6 +71,13 @@ pub async fn run_mail(
|
||||||
}
|
}
|
||||||
|
|
||||||
warn!("connection dropped, retrying");
|
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);
|
curr_conn.push(handle);
|
||||||
|
@ -96,9 +112,12 @@ async fn imap_main(acct: MailAccountConfig) -> Result<()> {
|
||||||
|
|
||||||
debug!("preparing to auth");
|
debug!("preparing to auth");
|
||||||
// check if the authentication method is supported
|
// 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 } => {
|
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?
|
auth.perform_auth(unauth).await?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -118,7 +137,22 @@ async fn imap_main(acct: MailAccountConfig) -> Result<()> {
|
||||||
loop {
|
loop {
|
||||||
idle_stream.next().await;
|
idle_stream.next().await;
|
||||||
debug!("got an event");
|
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
|
// used to notify the runtime that the process should exit
|
||||||
let (exit_tx, mut exit_rx) = mpsc::channel::<()>(1);
|
let (exit_tx, mut exit_rx) = mpsc::channel::<()>(1);
|
||||||
|
|
||||||
// used to send commands to the mail service
|
// send messages from the UI thread to the mail thread
|
||||||
let (_mail_tx, mail_rx) = mpsc::unbounded_channel();
|
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 {
|
tokio::spawn(async move {
|
||||||
let config_update = config_update.clone();
|
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)
|
.unwrap_or_else(report_err)
|
||||||
.await;
|
.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
|
//! UI library
|
||||||
|
|
||||||
|
mod mail_tab;
|
||||||
|
|
||||||
use std::io::Stdout;
|
use std::io::Stdout;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -17,9 +19,14 @@ use tui::{
|
||||||
style::{Color, Modifier, Style},
|
style::{Color, Modifier, Style},
|
||||||
text::Spans,
|
text::Spans,
|
||||||
widgets::*,
|
widgets::*,
|
||||||
|
Frame,
|
||||||
Terminal,
|
Terminal,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use self::mail_tab::{MailTabState, MailTab};
|
||||||
|
|
||||||
|
// pub(crate) type FrameType<'a> = Frame<'a, CrosstermBackend<Stdout>>;
|
||||||
|
|
||||||
const FRAME_DURATION: Duration = Duration::from_millis(17);
|
const FRAME_DURATION: Duration = Duration::from_millis(17);
|
||||||
|
|
||||||
/// Main entrypoint for the UI
|
/// 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()?;
|
terminal::enable_raw_mode()?;
|
||||||
|
|
||||||
let backend = CrosstermBackend::new(&mut stdout);
|
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 {
|
loop {
|
||||||
terminal.draw(|f| {
|
term.draw(|f| {
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.margin(0)
|
.margin(0)
|
||||||
|
@ -44,35 +53,37 @@ pub async fn run_ui(mut stdout: Stdout, exit_tx: mpsc::Sender<()>) -> Result<()>
|
||||||
])
|
])
|
||||||
.split(f.size());
|
.split(f.size());
|
||||||
|
|
||||||
let chunks2 = Layout::default()
|
// let chunks2 = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
// .direction(Direction::Horizontal)
|
||||||
.margin(0)
|
// .margin(0)
|
||||||
.constraints([
|
// .constraints([
|
||||||
Constraint::Length(20),
|
// Constraint::Length(20),
|
||||||
Constraint::Max(5000),
|
// Constraint::Max(5000),
|
||||||
//
|
// //
|
||||||
])
|
// ])
|
||||||
.split(chunks[1]);
|
// .split(chunks[1]);
|
||||||
|
|
||||||
// this is the title bar
|
// this is the title bar
|
||||||
let titles = vec!["hellosu"].into_iter().map(Spans::from).collect();
|
let titles = vec!["hellosu"].into_iter().map(Spans::from).collect();
|
||||||
let tabs = Tabs::new(titles);
|
let tabs = Tabs::new(titles);
|
||||||
f.render_widget(tabs, chunks[0]);
|
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
|
// TODO: check active tab
|
||||||
let items = [
|
// let items = [
|
||||||
ListItem::new("Osu"),
|
// ListItem::new("Osu"),
|
||||||
ListItem::new("Game").style(Style::default().add_modifier(Modifier::BOLD)),
|
// ListItem::new("Game").style(Style::default().add_modifier(Modifier::BOLD)),
|
||||||
];
|
// ];
|
||||||
let dirlist = List::new(items)
|
// let dirlist = List::new(items)
|
||||||
.block(Block::default().title("List").borders(Borders::ALL))
|
// .block(Block::default().title("List").borders(Borders::ALL))
|
||||||
.style(Style::default().fg(Color::White))
|
// .style(Style::default().fg(Color::White))
|
||||||
.highlight_style(Style::default().add_modifier(Modifier::ITALIC))
|
// .highlight_style(Style::default().add_modifier(Modifier::ITALIC))
|
||||||
.highlight_symbol(">>");
|
// .highlight_symbol(">>");
|
||||||
f.render_widget(dirlist, chunks2[0]);
|
// f.render_widget(dirlist, chunks2[0]);
|
||||||
|
|
||||||
let block = Block::default().title("Block").borders(Borders::ALL);
|
// let block = Block::default().title("Block").borders(Borders::ALL);
|
||||||
f.render_widget(block, chunks2[1]);
|
// f.render_widget(block, chunks2[1]);
|
||||||
|
|
||||||
// let block = Block::default().title("Block 2").borders(Borders::ALL);
|
// let block = Block::default().title("Block 2").borders(Borders::ALL);
|
||||||
// f.render_widget(block, chunks[1]);
|
// 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!(
|
execute!(
|
||||||
stdout,
|
stdout,
|
||||||
|
|
Loading…
Reference in a new issue