diff --git a/cove-tui/src/config.rs b/cove-tui/src/config.rs index 5ec701b..38955f3 100644 --- a/cove-tui/src/config.rs +++ b/cove-tui/src/config.rs @@ -1,4 +1,4 @@ -use std::time::Duration; +use std::time::{Duration, Instant}; use clap::Parser; @@ -10,6 +10,7 @@ pub struct Args { pub struct Config { pub cove_url: String, + pub cove_identity: String, pub timeout: Duration, } @@ -18,6 +19,8 @@ impl Config { let args = Args::parse(); Self { cove_url: args.cove_url, + // TODO Load identity from file oslt + cove_identity: format!("{:?}", Instant::now()), timeout: Duration::from_secs(10), } } diff --git a/cove-tui/src/main.rs b/cove-tui/src/main.rs index 627d63e..ac32f85 100644 --- a/cove-tui/src/main.rs +++ b/cove-tui/src/main.rs @@ -6,6 +6,7 @@ mod ui; use std::io; +use config::Config; use crossterm::event::{DisableMouseCapture, EnableMouseCapture}; use crossterm::execute; use crossterm::terminal::{EnterAlternateScreen, LeaveAlternateScreen}; @@ -15,6 +16,8 @@ use ui::Ui; #[tokio::main] async fn main() -> anyhow::Result<()> { + let config = Box::leak(Box::new(Config::load())); + let mut terminal = Terminal::new(CrosstermBackend::new(io::stdout()))?; crossterm::terminal::enable_raw_mode()?; @@ -25,7 +28,7 @@ async fn main() -> anyhow::Result<()> { )?; // Defer error handling so the terminal always gets restored properly - let result = Ui::run(&mut terminal).await; + let result = Ui::run(config, &mut terminal).await; execute!( terminal.backend_mut(), diff --git a/cove-tui/src/ui.rs b/cove-tui/src/ui.rs index ac68068..4cb4801 100644 --- a/cove-tui/src/ui.rs +++ b/cove-tui/src/ui.rs @@ -4,6 +4,7 @@ mod overlays; mod rooms; mod textline; +use std::collections::hash_map::Entry; use std::collections::HashMap; use std::io::Stdout; use std::sync::Arc; @@ -15,9 +16,9 @@ use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; use tokio::sync::Mutex; use tui::backend::CrosstermBackend; use tui::layout::{Constraint, Direction, Layout}; -use tui::widgets::Paragraph; use tui::{Frame, Terminal}; +use crate::config::Config; use crate::room::Room; use crate::ui::overlays::OverlayReaction; @@ -43,6 +44,7 @@ enum Overlay { } pub struct Ui { + config: &'static Config, event_tx: UnboundedSender, rooms: HashMap>>, rooms_state: RoomsState, @@ -50,8 +52,9 @@ pub struct Ui { } impl Ui { - fn new(event_tx: UnboundedSender) -> Self { + fn new(config: &'static Config, event_tx: UnboundedSender) -> Self { Self { + config, event_tx, rooms: HashMap::new(), rooms_state: RoomsState::default(), @@ -59,9 +62,12 @@ impl Ui { } } - pub async fn run(terminal: &mut Terminal) -> anyhow::Result<()> { + pub async fn run( + config: &'static Config, + terminal: &mut Terminal, + ) -> anyhow::Result<()> { let (event_tx, mut event_rx) = mpsc::unbounded_channel(); - let mut ui = Self::new(event_tx.clone()); + let mut ui = Self::new(config, event_tx.clone()); tokio::select! { e = ui.run_main(terminal, &mut event_rx) => e, @@ -134,14 +140,7 @@ impl Ui { Overlay::JoinRoom(state) => state.handle_key(event), }; if let Some(reaction) = reaction { - match reaction { - OverlayReaction::Handled => {} - OverlayReaction::Close => self.overlay = None, - OverlayReaction::JoinRoom(name) => { - self.overlay = None; - // TODO Join room - } - } + self.handle_overlay_reaction(reaction).await; } return CONTINUE; } @@ -160,6 +159,20 @@ impl Ui { } } + async fn handle_overlay_reaction(&mut self, reaction: OverlayReaction) { + match reaction { + OverlayReaction::Handled => {} + OverlayReaction::Close => self.overlay = None, + OverlayReaction::JoinRoom(name) => { + let name = name.trim(); + if !name.is_empty() { + self.overlay = None; + self.switch_to_room(name.to_string()).await; + } + } + } + } + async fn handle_mouse_event(&mut self, event: MouseEvent) -> anyhow::Result { let rooms_width = event.column + 1; let over_rooms = self.rooms_state.width() == rooms_width; @@ -210,4 +223,15 @@ impl Ui { Ok(()) } + + async fn switch_to_room(&mut self, name: String) { + match self.rooms.entry(name.clone()) { + Entry::Occupied(_) => {} + Entry::Vacant(entry) => { + entry.insert( + Room::new(name, self.config.cove_identity.clone(), None, self.config).await, + ); + } + } + } }