Move from tui to ratatui

Tui is no longer supported, ratatui is the new hotness. Fortunately
there is very little difference between the two, except I've noticed a
fun new bug in the help screen. (Maybe it's been there the whole time?)
This commit is contained in:
John Doty 2024-08-13 10:44:58 -07:00
parent 7e047626df
commit b381f71692
3 changed files with 423 additions and 236 deletions

617
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -17,18 +17,18 @@ bench = false
anyhow = "1.0" anyhow = "1.0"
bytes = "1" bytes = "1"
copypasta = "0.10.1" copypasta = "0.10.1"
crossterm = { version = "0.25", features = ["event-stream"] } crossterm = { version = "0.28.1", features = ["event-stream"] }
env_logger = { version = "0.11.5", default-features = false } env_logger = { version = "0.11.5", default-features = false }
home = "0.5.4" home = "0.5.4"
indoc = "1" indoc = "1"
log = { version = "0.4", features = ["std"] } log = { version = "0.4", features = ["std"] }
open = "3" open = "3"
rand = "0.8.5" rand = "0.8.5"
ratatui = "0.28.0"
thiserror = "1.0" thiserror = "1.0"
tokio = { version = "1", features = ["io-std", "io-util", "macros", "net", "process", "rt", "rt-multi-thread", "fs"] } tokio = { version = "1", features = ["io-std", "io-util", "macros", "net", "process", "rt", "rt-multi-thread", "fs"] }
tokio-stream = "0.1" tokio-stream = "0.1"
toml = "0.5" toml = "0.5"
tui = "0.19"
xdg = "2" xdg = "2"
[dev-dependencies] [dev-dependencies]

View file

@ -14,15 +14,8 @@ use crossterm::{
}, },
}; };
use log::{error, info, warn, Level, Metadata, Record}; use log::{error, info, warn, Level, Metadata, Record};
use std::collections::vec_deque::VecDeque; use ratatui::{
use std::collections::{HashMap, HashSet}; backend::CrosstermBackend,
use std::io::stdout;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc;
use tokio::sync::oneshot;
use tokio_stream::StreamExt;
use tui::{
backend::{Backend, CrosstermBackend},
layout::{Constraint, Direction, Layout, Margin, Rect}, layout::{Constraint, Direction, Layout, Margin, Rect},
style::{Color, Modifier, Style}, style::{Color, Modifier, Style},
widgets::{ widgets::{
@ -30,6 +23,13 @@ use tui::{
}, },
Frame, Terminal, Frame, Terminal,
}; };
use std::collections::vec_deque::VecDeque;
use std::collections::{HashMap, HashSet};
use std::io::stdout;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc;
use tokio::sync::oneshot;
use tokio_stream::StreamExt;
pub enum UIEvent { pub enum UIEvent {
Connected(u16), Connected(u16),
@ -301,7 +301,7 @@ impl UI {
Ok(code) Ok(code)
} }
fn render_connected<T: Backend>(&mut self, frame: &mut Frame<T>) { fn render_connected(&mut self, frame: &mut Frame) {
let constraints = if self.show_logs { let constraints = if self.show_logs {
vec![Constraint::Percentage(50), Constraint::Percentage(50)] vec![Constraint::Percentage(50), Constraint::Percentage(50)]
} else { } else {
@ -311,7 +311,7 @@ impl UI {
let chunks = Layout::default() let chunks = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.constraints(constraints) .constraints(constraints)
.split(frame.size()); .split(frame.area());
self.render_ports(frame, chunks[0]); self.render_ports(frame, chunks[0]);
if self.show_logs { if self.show_logs {
@ -322,7 +322,7 @@ impl UI {
} }
} }
fn render_ports<B: Backend>(&mut self, frame: &mut Frame<B>, size: Rect) { fn render_ports(&mut self, frame: &mut Frame, size: Rect) {
let enabled_port_style = Style::default(); let enabled_port_style = Style::default();
let disabled_port_style = Style::default().fg(Color::DarkGray); let disabled_port_style = Style::default().fg(Color::DarkGray);
let broken_port_style = let broken_port_style =
@ -358,17 +358,16 @@ impl UI {
Constraint::Length(size.width), Constraint::Length(size.width),
]; ];
let port_list = Table::new(rows) let port_list = Table::new(rows, &widths)
.header(Row::new(vec!["fwd", "Port", "Description"])) .header(Row::new(vec!["fwd", "Port", "Description"]))
.block(Block::default().title("Ports").borders(Borders::ALL)) .block(Block::default().title("Ports").borders(Borders::ALL))
.column_spacing(1) .column_spacing(1)
.widths(&widths)
.highlight_symbol(">> "); .highlight_symbol(">> ");
frame.render_stateful_widget(port_list, size, &mut self.selection); frame.render_stateful_widget(port_list, size, &mut self.selection);
} }
fn render_help<B: Backend>(&mut self, frame: &mut Frame<B>) { fn render_help(&mut self, frame: &mut Frame) {
let keybindings = vec![ let keybindings = vec![
Row::new(vec!["↑ / k", "Move cursor up"]), Row::new(vec!["↑ / k", "Move cursor up"]),
Row::new(vec!["↓ / j", "Move cursor down"]), Row::new(vec!["↓ / j", "Move cursor down"]),
@ -387,10 +386,10 @@ impl UI {
let help_popup_area = centered_rect( let help_popup_area = centered_rect(
65, 65,
keybindings.len() as u16 + border_lines, keybindings.len() as u16 + border_lines,
frame.size(), frame.area(),
); );
let inner_area = let inner_area =
help_popup_area.inner(&Margin { vertical: 1, horizontal: 1 }); help_popup_area.inner(Margin { vertical: 1, horizontal: 1 });
let key_width = 7; let key_width = 7;
let binding_width = inner_area.width.saturating_sub(key_width); let binding_width = inner_area.width.saturating_sub(key_width);
@ -398,8 +397,7 @@ impl UI {
Constraint::Length(key_width), Constraint::Length(key_width),
Constraint::Length(binding_width), Constraint::Length(binding_width),
]; ];
let keybindings = Table::new(keybindings) let keybindings = Table::new(keybindings, keybindings_widths)
.widths(keybindings_widths)
.column_spacing(1) .column_spacing(1)
.block(Block::default().title("Keys").borders(Borders::ALL)); .block(Block::default().title("Keys").borders(Borders::ALL));
@ -407,7 +405,7 @@ impl UI {
frame.render_widget(keybindings, inner_area); frame.render_widget(keybindings, inner_area);
} }
fn render_logs<B: Backend>(&mut self, frame: &mut Frame<B>, size: Rect) { fn render_logs(&mut self, frame: &mut Frame, size: Rect) {
let items: Vec<_> = let items: Vec<_> =
self.lines.iter().map(|l| ListItem::new(&l[..])).collect(); self.lines.iter().map(|l| ListItem::new(&l[..])).collect();