diff --git a/Cargo.lock b/Cargo.lock index 73b94e3..683c497 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "atty" version = "0.2.14" @@ -188,6 +197,7 @@ dependencies = [ "clap", "cove-core", "crossterm", + "palette", "thiserror", "tokio", "tokio-tungstenite", @@ -269,6 +279,15 @@ dependencies = [ "termcolor", ] +[[package]] +name = "find-crate" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2" +dependencies = [ + "toml", +] + [[package]] name = "fnv" version = "1.0.7" @@ -566,6 +585,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.1" @@ -603,6 +631,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "palette" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9735f7e1e51a3f740bacd5dc2724b61a7806f23597a8736e679f38ee3435d18" +dependencies = [ + "approx", + "num-traits", + "palette_derive", + "phf", +] + +[[package]] +name = "palette_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7799c3053ea8a6d8a1193c7ba42f534e7863cf52e378a7f90406f4a645d33bad" +dependencies = [ + "find-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -634,6 +686,50 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "phf" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ac8b67553a7ca9457ce0e526948cad581819238f4a9d1ea74545851fa24f37" +dependencies = [ + "phf_macros", + "phf_shared", + "proc-macro-hack", +] + +[[package]] +name = "phf_generator" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d43f3220d96e0080cc9ea234978ccd80d904eafb17be31bb0f76daaea6493082" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b706f5936eb50ed880ae3009395b43ed19db5bff2ebd459c95e7bf013a89ab86" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68318426de33640f02be62b4ae8eb1261be2efbc337b60c54d845bf4484e0d9" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.8" @@ -676,6 +772,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + [[package]] name = "proc-macro2" version = "1.0.36" @@ -948,6 +1050,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" + [[package]] name = "slab" version = "0.4.5" @@ -1101,6 +1209,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + [[package]] name = "tui" version = "0.17.0" diff --git a/cove-tui/Cargo.toml b/cove-tui/Cargo.toml index 28dde89..1c3e858 100644 --- a/cove-tui/Cargo.toml +++ b/cove-tui/Cargo.toml @@ -9,6 +9,7 @@ clap = { version = "3.1.0", features = ["derive"] } cove-core = { path = "../cove-core" } crossterm = "0.22.1" # futures = "0.3.21" +palette = "0.6.0" # serde_json = "1.0.78" thiserror = "1.0.30" tokio = { version = "1.16.1", features = ["full"] } diff --git a/cove-tui/src/main.rs b/cove-tui/src/main.rs index 25ba203..6317956 100644 --- a/cove-tui/src/main.rs +++ b/cove-tui/src/main.rs @@ -1,7 +1,7 @@ -mod replies; -mod room; mod config; mod never; +mod replies; +mod room; use std::io::{self, Stdout}; use std::time::Duration; @@ -10,17 +10,109 @@ use config::Config; use crossterm::event::{DisableMouseCapture, EnableMouseCapture}; use crossterm::execute; use crossterm::terminal::{EnterAlternateScreen, LeaveAlternateScreen}; +use palette::rgb::Rgb; +use palette::{FromColor, Hsl, Hsv, Saturate, Srgb}; use tokio::time; use tui::backend::CrosstermBackend; -use tui::widgets::{Block, Borders}; +use tui::layout::{Constraint, Corner, Direction, Layout}; +use tui::style::{Color, Modifier, Style}; +use tui::symbols::line::VERTICAL; +use tui::text::{Span, Spans}; +use tui::widgets::{Block, Borders, Cell, List, ListItem, ListState, Paragraph, Row, Table, Tabs}; use tui::Terminal; async fn run(terminal: &mut Terminal>) -> anyhow::Result<()> { terminal.draw(|f| { - let block = Block::default().title("Block").borders(Borders::ALL); - f.render_widget(block, f.size()); + let hchunks = Layout::default() + .direction(Direction::Horizontal) + .constraints([ + Constraint::Length(20), + Constraint::Length(2), + Constraint::Min(0), + Constraint::Length(2), + Constraint::Length(20), + ]) + .split(f.size()); + + // Borders + f.render_widget(Block::default().borders(Borders::LEFT), hchunks[1]); + f.render_widget(Block::default().borders(Borders::LEFT), hchunks[3]); + + // Room list + let room_style = Style::default().fg(Color::LightBlue); + let mut state = ListState::default(); + // state.select(Some(1)); + f.render_stateful_widget( + List::new(vec![ + ListItem::new(Span::styled( + "Cove", + Style::default().add_modifier(Modifier::BOLD), + )), + ListItem::new(Span::styled("&dunno", room_style)), + ListItem::new(Span::styled("&test", room_style)), + ListItem::new(" "), + ListItem::new(Span::styled( + "Euphoria", + Style::default().add_modifier(Modifier::BOLD), + )), + ListItem::new(Span::styled("&xkcd", room_style)), + ListItem::new(Span::styled("&music", room_style)), + ListItem::new(Span::styled("&bots", room_style)), + ListItem::new(" "), + ListItem::new(Span::styled( + "Instant", + Style::default().add_modifier(Modifier::BOLD), + )), + ListItem::new(Span::styled("&welcome", room_style)), + ]), + // .highlight_style(Style::default().add_modifier(Modifier::BOLD)) + // .highlight_symbol(">"), + hchunks[0], + &mut state, + ); + // f.render_widget(Paragraph::new("foo"), hchunks[0]); + + // Nick list + let nchunks = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Length(1), Constraint::Min(0)]) + .split(hchunks[4]); + f.render_widget( + Paragraph::new(Spans::from(vec![ + Span::styled("Users", Style::default().add_modifier(Modifier::BOLD)), + Span::raw(" "), + Span::styled("(13)", Style::default().fg(Color::Gray)), + ])), + nchunks[0], + ); + fn userstyle(r: u8, g: u8, b: u8) -> Style { + let rgb = Srgb::new(r, g, b).into_format::(); + let mut hsl = Hsl::from_color(rgb); + hsl.saturation = 1.0; + hsl.lightness = 0.7; + let rgb = Rgb::from_color(hsl).into_format::(); + Style::default().fg(Color::Rgb(rgb.red, rgb.green, rgb.blue)) + } + f.render_widget( + List::new([ + ListItem::new(Span::styled("TerryTvType", userstyle(192, 242, 238))), + ListItem::new(Span::styled("r*4", userstyle(192, 211, 242))), + ListItem::new(Span::styled("Swedish", userstyle(192, 242, 207))), + ListItem::new(Span::styled("Garmy", userstyle(242, 225, 192))), + ListItem::new(Span::styled("SRP", userstyle(242, 219, 192))), + ListItem::new(Span::styled("C", userstyle(192, 218, 242))), + ListItem::new(Span::styled("fill", userstyle(192, 197, 242))), + ListItem::new(Span::styled("ohnezo", userstyle(242, 203, 192))), + ListItem::new(Span::styled("Sumärzru", userstyle(242, 223, 192))), + ListItem::new(Span::styled("SuperGeek", userstyle(192, 242, 203))), + ListItem::new(Span::styled("certainlyhominid", userstyle(192, 242, 209))), + ListItem::new(Span::styled("Plugh", userstyle(192, 242, 215))), + ListItem::new(Span::styled("🎼\u{fe0e}🎷🎷🎷🎼\u{fe0e}", userstyle(242, 192, 192))), + ]), + nchunks[1], + ); })?; - time::sleep(Duration::from_secs(1)).await; + let _ = crossterm::event::read(); Ok(()) } diff --git a/cove-tui/src/room.rs b/cove-tui/src/room.rs index 3ba7929..4c4f708 100644 --- a/cove-tui/src/room.rs +++ b/cove-tui/src/room.rs @@ -162,6 +162,7 @@ impl Room { Rpl::Room(RoomRpl::Success) => { *room_verified = true; if let Some(nick) = &self.initial_nick { + // TODO Use previous nick if there is one tokio::spawn(Self::identify( room.clone(), nick.clone(),