gonna just plop tui.rs in here
This commit is contained in:
parent
b3b137b86a
commit
09eafd0f3f
10 changed files with 315 additions and 144 deletions
85
Cargo.lock
generated
85
Cargo.lock
generated
|
@ -279,6 +279,12 @@ version = "1.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
|
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cassowary"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cast5"
|
name = "cast5"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
@ -434,31 +440,6 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossterm"
|
|
||||||
version = "0.19.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.2.1",
|
|
||||||
"crossterm_winapi",
|
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
|
||||||
"mio",
|
|
||||||
"parking_lot",
|
|
||||||
"signal-hook",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossterm_winapi"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "3.0.2"
|
version = "3.0.2"
|
||||||
|
@ -1189,6 +1170,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numtoa"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc"
|
name = "objc"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
@ -1250,7 +1237,6 @@ dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"chrono",
|
"chrono",
|
||||||
"crossterm",
|
|
||||||
"fern",
|
"fern",
|
||||||
"format-bytes",
|
"format-bytes",
|
||||||
"futures",
|
"futures",
|
||||||
|
@ -1265,11 +1251,13 @@ dependencies = [
|
||||||
"rustls-connector",
|
"rustls-connector",
|
||||||
"serde",
|
"serde",
|
||||||
"structopt",
|
"structopt",
|
||||||
|
"termion",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml",
|
"toml",
|
||||||
|
"tui",
|
||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
"xdg",
|
"xdg",
|
||||||
]
|
]
|
||||||
|
@ -1634,6 +1622,15 @@ dependencies = [
|
||||||
"bitflags 1.2.1",
|
"bitflags 1.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_termios"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
|
||||||
|
dependencies = [
|
||||||
|
"redox_syscall 0.2.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
@ -1899,17 +1896,6 @@ dependencies = [
|
||||||
"opaque-debug 0.3.0",
|
"opaque-debug 0.3.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook"
|
|
||||||
version = "0.1.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"mio",
|
|
||||||
"signal-hook-registry",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -2087,6 +2073,18 @@ dependencies = [
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termion"
|
||||||
|
version = "1.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"numtoa",
|
||||||
|
"redox_syscall 0.2.5",
|
||||||
|
"redox_termios",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
@ -2215,6 +2213,19 @@ dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tui"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ced152a8e9295a5b168adc254074525c17ac4a83c90b2716274cc38118bddc9"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.2.1",
|
||||||
|
"cassowary",
|
||||||
|
"termion",
|
||||||
|
"unicode-segmentation",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "twofish"
|
name = "twofish"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
|
@ -12,11 +12,11 @@ license = "GPL-3.0-or-later"
|
||||||
members = ["imap", "smtp"]
|
members = ["imap", "smtp"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
# crossterm = "0.19.0"
|
||||||
anyhow = "1.0.38"
|
anyhow = "1.0.38"
|
||||||
async-trait = "0.1.42"
|
async-trait = "0.1.42"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
chrono = "0.4.19"
|
chrono = "0.4.19"
|
||||||
crossterm = "0.19.0"
|
|
||||||
fern = { version = "0.6.0", features = ["colored"] }
|
fern = { version = "0.6.0", features = ["colored"] }
|
||||||
format-bytes = "0.2.0"
|
format-bytes = "0.2.0"
|
||||||
futures = "0.3.13"
|
futures = "0.3.13"
|
||||||
|
@ -34,8 +34,11 @@ tokio-rustls = "0.22.0"
|
||||||
tokio-stream = { version = "0.1.3", features = ["sync"] }
|
tokio-stream = { version = "0.1.3", features = ["sync"] }
|
||||||
tokio-util = { version = "0.6.3", features = ["full"] }
|
tokio-util = { version = "0.6.3", features = ["full"] }
|
||||||
toml = "0.5.8"
|
toml = "0.5.8"
|
||||||
|
# tui = { version = "0.14.0", default-features = false, features = ["crossterm"] }
|
||||||
webpki-roots = "0.21.0"
|
webpki-roots = "0.21.0"
|
||||||
xdg = "2.2.0"
|
xdg = "2.2.0"
|
||||||
|
tui = "0.14.0"
|
||||||
|
termion = "1.5.6"
|
||||||
|
|
||||||
[dependencies.panorama-imap]
|
[dependencies.panorama-imap]
|
||||||
path = "imap"
|
path = "imap"
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate anyhow;
|
extern crate anyhow;
|
||||||
#[macro_use]
|
// #[macro_use]
|
||||||
extern crate crossterm;
|
// extern crate crossterm;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate format_bytes;
|
extern crate format_bytes;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
95
src/ui/events.rs
Normal file
95
src/ui/events.rs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
use std::io;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
use std::sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc,
|
||||||
|
};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use termion::event::Key;
|
||||||
|
use termion::input::TermRead;
|
||||||
|
|
||||||
|
pub enum Event<I> {
|
||||||
|
Input(I),
|
||||||
|
Tick,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A small event handler that wrap termion input and tick events. Each event
|
||||||
|
/// type is handled in its own thread and returned to a common `Receiver`
|
||||||
|
pub struct Events {
|
||||||
|
rx: mpsc::Receiver<Event<Key>>,
|
||||||
|
input_handle: thread::JoinHandle<()>,
|
||||||
|
ignore_exit_key: Arc<AtomicBool>,
|
||||||
|
tick_handle: thread::JoinHandle<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Config {
|
||||||
|
pub exit_key: Key,
|
||||||
|
pub tick_rate: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Config {
|
||||||
|
Config {
|
||||||
|
exit_key: Key::Char('q'),
|
||||||
|
tick_rate: Duration::from_millis(250),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Events {
|
||||||
|
pub fn new() -> Events {
|
||||||
|
Events::with_config(Config::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_config(config: Config) -> Events {
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
let ignore_exit_key = Arc::new(AtomicBool::new(false));
|
||||||
|
let input_handle = {
|
||||||
|
let tx = tx.clone();
|
||||||
|
let ignore_exit_key = ignore_exit_key.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let stdin = io::stdin();
|
||||||
|
for evt in stdin.keys() {
|
||||||
|
if let Ok(key) = evt {
|
||||||
|
if let Err(err) = tx.send(Event::Input(key)) {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !ignore_exit_key.load(Ordering::Relaxed) && key == config.exit_key {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
let tick_handle = {
|
||||||
|
thread::spawn(move || loop {
|
||||||
|
if tx.send(Event::Tick).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
thread::sleep(config.tick_rate);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
Events {
|
||||||
|
rx,
|
||||||
|
ignore_exit_key,
|
||||||
|
input_handle,
|
||||||
|
tick_handle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&self) -> Result<Event<Key>, mpsc::RecvError> {
|
||||||
|
self.rx.recv()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_exit_key(&mut self) {
|
||||||
|
self.ignore_exit_key.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_exit_key(&mut self) {
|
||||||
|
self.ignore_exit_key.store(false, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
147
src/ui/mod.rs
147
src/ui/mod.rs
|
@ -1,121 +1,62 @@
|
||||||
//! UI module
|
//! UI library
|
||||||
|
|
||||||
mod drawbuf;
|
mod events;
|
||||||
mod table;
|
|
||||||
mod tabs;
|
|
||||||
mod widget;
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::io::Stdout;
|
||||||
use std::io::{Stdout, Write};
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use chrono::Local;
|
use termion::{event::Key, screen::AlternateScreen};
|
||||||
use crossterm::{
|
use tokio::sync::mpsc;
|
||||||
cursor::{self, MoveTo},
|
use tui::{
|
||||||
event::{self, Event, KeyCode, KeyEvent},
|
backend::TermionBackend,
|
||||||
style::{self, Color, SetBackgroundColor, SetForegroundColor},
|
layout::{Constraint, Direction, Layout},
|
||||||
terminal::{self, Clear, ClearType},
|
widgets::{Block, Borders, Widget},
|
||||||
|
Terminal,
|
||||||
};
|
};
|
||||||
use tokio::time;
|
|
||||||
|
|
||||||
use crate::ExitSender;
|
use self::events::{Config, Event, Events};
|
||||||
|
|
||||||
use self::drawbuf::DrawBuf;
|
/// Main entrypoint for the UI
|
||||||
use self::table::Table;
|
pub async fn run_ui(stdout: Stdout, exit_tx: mpsc::Sender<()>) -> Result<()> {
|
||||||
use self::tabs::Tabs;
|
let stdout = AlternateScreen::from(stdout);
|
||||||
use self::widget::Widget;
|
let backend = TermionBackend::new(stdout);
|
||||||
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
const FRAME_DURATION: Duration = Duration::from_millis(20);
|
let events = Events::with_config(Config {
|
||||||
|
tick_rate: Duration::from_millis(17),
|
||||||
/// Type alias for the screen object we're drawing to
|
..Config::default()
|
||||||
pub type Screen = Stdout;
|
});
|
||||||
|
|
||||||
/// Rectangle
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct Rect {
|
|
||||||
pub x: u16,
|
|
||||||
pub y: u16,
|
|
||||||
pub w: u16,
|
|
||||||
pub h: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rect {
|
|
||||||
/// Construct a new rectangle from (x, y) and (w, h)
|
|
||||||
pub fn new(x: u16, y: u16, w: u16, h: u16) -> Self {
|
|
||||||
Rect { x, y, w, h }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// UI entrypoint.
|
|
||||||
pub async fn run_ui(mut w: Stdout, exit: ExitSender) -> Result<()> {
|
|
||||||
execute!(w, cursor::Hide, terminal::EnterAlternateScreen)?;
|
|
||||||
terminal::enable_raw_mode()?;
|
|
||||||
|
|
||||||
let (term_width, term_height) = terminal::size()?;
|
|
||||||
let bounds = Rect::new(0, 0, term_width, term_height);
|
|
||||||
let mut drawbuf = DrawBuf::new(bounds);
|
|
||||||
|
|
||||||
let mut table = Table::default();
|
|
||||||
table.push_row(vec!["ur mom Lol!".to_owned()]);
|
|
||||||
table.push_row(vec!["hek".to_owned()]);
|
|
||||||
|
|
||||||
let mut tabs = Tabs::new();
|
|
||||||
tabs.add_tab("Mail", table);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
queue!(
|
terminal.draw(|f| {
|
||||||
w,
|
let chunks = Layout::default()
|
||||||
SetBackgroundColor(Color::Reset),
|
.direction(Direction::Vertical)
|
||||||
SetForegroundColor(Color::Reset),
|
.margin(1)
|
||||||
Clear(ClearType::All),
|
.constraints(
|
||||||
MoveTo(0, 0),
|
[
|
||||||
)?;
|
Constraint::Percentage(10),
|
||||||
|
Constraint::Percentage(80),
|
||||||
|
Constraint::Percentage(10),
|
||||||
|
]
|
||||||
|
.as_ref(),
|
||||||
|
)
|
||||||
|
.split(f.size());
|
||||||
|
let block = Block::default().title("Block").borders(Borders::ALL);
|
||||||
|
f.render_widget(block, chunks[0]);
|
||||||
|
let block = Block::default().title("Block 2").borders(Borders::ALL);
|
||||||
|
f.render_widget(block, chunks[1]);
|
||||||
|
})?;
|
||||||
|
|
||||||
// let now = Local::now();
|
if let Event::Input(input) = events.next()? {
|
||||||
// println!("time {}", now);
|
match input {
|
||||||
|
Key::Char('q') => {
|
||||||
let (term_width, term_height) = terminal::size()?;
|
|
||||||
let bounds = Rect::new(5, 5, term_width - 10, term_height - 10);
|
|
||||||
// table.draw(&mut w, bounds)?;
|
|
||||||
// tabs.draw(&mut w, bounds)?;
|
|
||||||
drawbuf.draw(&mut w)?;
|
|
||||||
w.flush()?;
|
|
||||||
|
|
||||||
// approx 60fps
|
|
||||||
time::sleep(FRAME_DURATION).await;
|
|
||||||
|
|
||||||
// check to see if there's even an event this frame. otherwise, just keep going
|
|
||||||
let event = if event::poll(FRAME_DURATION)? {
|
|
||||||
let event = event::read()?;
|
|
||||||
// table.update(&event);
|
|
||||||
|
|
||||||
if let Event::Key(KeyEvent {
|
|
||||||
code: KeyCode::Char('q'),
|
|
||||||
..
|
|
||||||
}) = event
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
Some(event)
|
}
|
||||||
} else {
|
}
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
tabs.update(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
execute!(
|
|
||||||
w,
|
|
||||||
style::ResetColor,
|
|
||||||
cursor::Show,
|
|
||||||
terminal::LeaveAlternateScreen
|
|
||||||
)?;
|
|
||||||
terminal::disable_raw_mode()?;
|
|
||||||
|
|
||||||
exit.send(()).await?;
|
|
||||||
debug!("sent exit");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
121
src/ui_custom/mod.rs
Normal file
121
src/ui_custom/mod.rs
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
//! UI module
|
||||||
|
|
||||||
|
mod drawbuf;
|
||||||
|
mod table;
|
||||||
|
mod tabs;
|
||||||
|
mod widget;
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::io::{Stdout, Write};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use chrono::Local;
|
||||||
|
use crossterm::{
|
||||||
|
cursor::{self, MoveTo},
|
||||||
|
event::{self, Event, KeyCode, KeyEvent},
|
||||||
|
style::{self, Color, SetBackgroundColor, SetForegroundColor},
|
||||||
|
terminal::{self, Clear, ClearType},
|
||||||
|
};
|
||||||
|
use tokio::time;
|
||||||
|
|
||||||
|
use crate::ExitSender;
|
||||||
|
|
||||||
|
use self::drawbuf::DrawBuf;
|
||||||
|
use self::table::Table;
|
||||||
|
use self::tabs::Tabs;
|
||||||
|
use self::widget::Widget;
|
||||||
|
|
||||||
|
const FRAME_DURATION: Duration = Duration::from_millis(20);
|
||||||
|
|
||||||
|
/// Type alias for the screen object we're drawing to
|
||||||
|
pub type Screen = Stdout;
|
||||||
|
|
||||||
|
/// Rectangle
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub struct Rect {
|
||||||
|
pub x: u16,
|
||||||
|
pub y: u16,
|
||||||
|
pub w: u16,
|
||||||
|
pub h: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rect {
|
||||||
|
/// Construct a new rectangle from (x, y) and (w, h)
|
||||||
|
pub fn new(x: u16, y: u16, w: u16, h: u16) -> Self {
|
||||||
|
Rect { x, y, w, h }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// UI entrypoint.
|
||||||
|
pub async fn run_ui(mut w: Stdout, exit: ExitSender) -> Result<()> {
|
||||||
|
execute!(w, cursor::Hide, terminal::EnterAlternateScreen)?;
|
||||||
|
terminal::enable_raw_mode()?;
|
||||||
|
|
||||||
|
let (term_width, term_height) = terminal::size()?;
|
||||||
|
let bounds = Rect::new(0, 0, term_width, term_height);
|
||||||
|
let mut drawbuf = DrawBuf::new(bounds);
|
||||||
|
|
||||||
|
let mut table = Table::default();
|
||||||
|
table.push_row(vec!["ur mom Lol!".to_owned()]);
|
||||||
|
table.push_row(vec!["hek".to_owned()]);
|
||||||
|
|
||||||
|
let mut tabs = Tabs::new();
|
||||||
|
tabs.add_tab("Mail", table);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
queue!(
|
||||||
|
w,
|
||||||
|
SetBackgroundColor(Color::Reset),
|
||||||
|
SetForegroundColor(Color::Reset),
|
||||||
|
Clear(ClearType::All),
|
||||||
|
MoveTo(0, 0),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// let now = Local::now();
|
||||||
|
// println!("time {}", now);
|
||||||
|
|
||||||
|
let (term_width, term_height) = terminal::size()?;
|
||||||
|
let bounds = Rect::new(5, 5, term_width - 10, term_height - 10);
|
||||||
|
// table.draw(&mut w, bounds)?;
|
||||||
|
// tabs.draw(&mut w, bounds)?;
|
||||||
|
drawbuf.draw(&mut w)?;
|
||||||
|
w.flush()?;
|
||||||
|
|
||||||
|
// approx 60fps
|
||||||
|
time::sleep(FRAME_DURATION).await;
|
||||||
|
|
||||||
|
// check to see if there's even an event this frame. otherwise, just keep going
|
||||||
|
let event = if event::poll(FRAME_DURATION)? {
|
||||||
|
let event = event::read()?;
|
||||||
|
// table.update(&event);
|
||||||
|
|
||||||
|
if let Event::Key(KeyEvent {
|
||||||
|
code: KeyCode::Char('q'),
|
||||||
|
..
|
||||||
|
}) = event
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(event)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
tabs.update(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
execute!(
|
||||||
|
w,
|
||||||
|
style::ResetColor,
|
||||||
|
cursor::Show,
|
||||||
|
terminal::LeaveAlternateScreen
|
||||||
|
)?;
|
||||||
|
terminal::disable_raw_mode()?;
|
||||||
|
|
||||||
|
exit.send(()).await?;
|
||||||
|
debug!("sent exit");
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in a new issue