Reimplement room interactions for new rooms

This commit is contained in:
Joscha 2022-03-05 16:36:10 +01:00
parent e81900caac
commit c36f35747f
6 changed files with 136 additions and 88 deletions

View file

@ -35,6 +35,7 @@ pub enum Error {
pub enum Event { pub enum Event {
StateChanged, StateChanged,
// TODO Add IdentificationRequired event
// TODO Add events for joining, parting, sending, ... // TODO Add events for joining, parting, sending, ...
} }

View file

@ -7,6 +7,7 @@ mod rooms;
mod styles; mod styles;
mod textline; mod textline;
use std::collections::hash_map::Entry;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Stdout; use std::io::Stdout;
@ -19,6 +20,7 @@ use tui::layout::{Constraint, Direction, Layout, Rect};
use tui::{Frame, Terminal}; use tui::{Frame, Terminal};
use crate::config::Config; use crate::config::Config;
use crate::cove::room::CoveRoom;
use crate::ui::overlays::OverlayReaction; use crate::ui::overlays::OverlayReaction;
use self::cove::CoveUi; use self::cove::CoveUi;
@ -33,6 +35,7 @@ pub type Backend = CrosstermBackend<Stdout>;
pub enum UiEvent { pub enum UiEvent {
Term(Event), Term(Event),
Redraw, Redraw,
// TODO Add room events
} }
impl From<crate::cove::conn::Event> for UiEvent { impl From<crate::cove::conn::Event> for UiEvent {
@ -41,6 +44,11 @@ impl From<crate::cove::conn::Event> for UiEvent {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum RoomId {
Cove(String),
}
enum EventHandleResult { enum EventHandleResult {
Continue, Continue,
Stop, Stop,
@ -51,11 +59,11 @@ pub struct Ui {
event_tx: UnboundedSender<UiEvent>, event_tx: UnboundedSender<UiEvent>,
cove_rooms: HashMap<String, CoveUi>, cove_rooms: HashMap<String, CoveUi>,
room: Option<RoomId>,
rooms_pane: PaneInfo, rooms_pane: PaneInfo,
users_pane: PaneInfo, users_pane: PaneInfo,
// room: Option<RoomInfo>,
overlay: Option<Overlay>, overlay: Option<Overlay>,
last_area: Rect, last_area: Rect,
@ -66,12 +74,13 @@ impl Ui {
Self { Self {
config, config,
event_tx, event_tx,
cove_rooms: HashMap::new(), cove_rooms: HashMap::new(),
room: None,
rooms_pane: PaneInfo::default(), rooms_pane: PaneInfo::default(),
users_pane: PaneInfo::default(), users_pane: PaneInfo::default(),
// room: None,
overlay: None, overlay: None,
last_area: Rect::default(), last_area: Rect::default(),
@ -172,18 +181,18 @@ impl Ui {
self.overlay = Some(Overlay::SwitchRoom(SwitchRoomState::default())); self.overlay = Some(Overlay::SwitchRoom(SwitchRoomState::default()));
CONTINUE CONTINUE
} }
// KeyCode::Char('J') => { KeyCode::Char('J') => {
// self.switch_to_next_room(); self.switch_to_next_room();
// CONTINUE CONTINUE
// } }
// KeyCode::Char('K') => { KeyCode::Char('K') => {
// self.switch_to_prev_room(); self.switch_to_prev_room();
// CONTINUE CONTINUE
// } }
// KeyCode::Char('D') => { KeyCode::Char('D') => {
// self.remove_current_room(); self.remove_current_room();
// CONTINUE CONTINUE
// } }
_ => CONTINUE, _ => CONTINUE,
} }
} }
@ -192,12 +201,9 @@ impl Ui {
match reaction { match reaction {
OverlayReaction::Handled => {} OverlayReaction::Handled => {}
OverlayReaction::Close => self.overlay = None, OverlayReaction::Close => self.overlay = None,
OverlayReaction::SwitchRoom(name) => { OverlayReaction::SwitchRoom(id) => {
let name = name.trim(); self.overlay = None;
if !name.is_empty() { self.switch_to_room(id).await;
self.overlay = None;
// self.switch_to_room(name.to_string()).await;
}
} }
} }
} }
@ -250,16 +256,14 @@ impl Ui {
let users_pane_area = areas[4]; let users_pane_area = areas[4];
// Main pane and users pane // Main pane and users pane
// if let Some(room) = &mut self.room { self.render_room(frame, main_pane_area, users_pane_area)
// room.render_main(frame, main_pane_area).await; .await;
// room.render_users(frame, users_pane_area).await;
// }
// Rooms pane // Rooms pane
let mut rooms = Rooms::new(&self.cove_rooms); let mut rooms = Rooms::new(&self.cove_rooms);
// if let Some(room) = &self.room { if let Some(RoomId::Cove(name)) = &self.room {
// rooms = rooms.select(room.name()); rooms = rooms.select(name);
// } }
frame.render_widget(rooms, rooms_pane_area); frame.render_widget(rooms, rooms_pane_area);
// Pane borders and width // Pane borders and width
@ -282,69 +286,87 @@ impl Ui {
Ok(()) Ok(())
} }
// async fn switch_to_room(&mut self, name: String) { async fn render_room(
// let room = match self.rooms.entry(name.clone()) { &mut self,
// Entry::Occupied(entry) => entry.get().clone(), frame: &mut Frame<'_, Backend>,
// Entry::Vacant(entry) => { main_pane_area: Rect,
// let identity = self.config.cove_identity.clone(); users_pane_area: Rect,
// let room = Room::new(name.clone(), identity, None, self.config).await; ) {
// entry.insert(room.clone()); match &self.room {
// room Some(RoomId::Cove(name)) => {
// } if let Some(ui) = self.cove_rooms.get_mut(name) {
// }; ui.render_main(frame, main_pane_area).await;
ui.render_users(frame, users_pane_area).await;
} else {
self.room = None;
}
}
None => {
// TODO Render welcome screen
}
}
}
// self.room = Some(RoomInfo::new(name, room)) async fn switch_to_room(&mut self, id: RoomId) {
// } match &id {
RoomId::Cove(name) => {
if let Entry::Vacant(entry) = self.cove_rooms.entry(name.clone()) {
let room =
CoveRoom::new(self.config, self.event_tx.clone(), name.clone()).await;
entry.insert(CoveUi::new(room));
}
}
}
self.room = Some(id);
}
// fn get_room_index(&self) -> Option<(usize, &str)> { fn rooms_in_order(&self) -> Vec<RoomId> {
// let name = self.room.as_ref()?.name(); let mut rooms = vec![];
rooms.extend(self.cove_rooms.keys().cloned().map(RoomId::Cove));
rooms.sort();
rooms
}
// let mut rooms = self.rooms.keys().collect::<Vec<_>>(); fn get_room_index(&self, rooms: &[RoomId]) -> Option<(usize, RoomId)> {
// if rooms.is_empty() { let id = self.room.clone()?;
// return None; let index = rooms.iter().position(|room| room == &id)?;
// } Some((index, id))
// rooms.sort(); }
// let index = rooms.iter().position(|n| n as &str == name)?; fn set_room_index(&mut self, rooms: &[RoomId], index: usize) {
if rooms.is_empty() {
self.room = None;
return;
}
// Some((index, name)) let id = rooms[index & rooms.len()].clone();
// } self.room = Some(id);
}
// fn set_room_index(&mut self, index: usize) { fn switch_to_next_room(&mut self) {
// let mut rooms = self.rooms.keys().collect::<Vec<_>>(); let rooms = self.rooms_in_order();
// if rooms.is_empty() { if let Some((index, _)) = self.get_room_index(&rooms) {
// self.room = None; self.set_room_index(&rooms, index + 1);
// return; }
// } }
// rooms.sort();
// let name = rooms[index % rooms.len()]; fn switch_to_prev_room(&mut self) {
// let room = self.rooms[name].clone(); let rooms = self.rooms_in_order();
// self.room = Some(RoomInfo::new(name.clone(), room)) if let Some((index, _)) = self.get_room_index(&rooms) {
// } self.set_room_index(&rooms, index + rooms.len() - 1);
}
}
// fn switch_to_next_room(&mut self) { fn remove_current_room(&mut self) {
// if let Some((index, _)) = self.get_room_index() { let rooms = self.rooms_in_order();
// self.set_room_index(index + 1); if let Some((index, id)) = self.get_room_index(&rooms) {
// } match id {
// } RoomId::Cove(name) => self.cove_rooms.remove(&name),
};
// fn switch_to_prev_room(&mut self) { let rooms = self.rooms_in_order();
// if let Some((index, _)) = self.get_room_index() { let max_index = if rooms.is_empty() { 0 } else { rooms.len() - 1 };
// self.set_room_index(index + self.rooms.len() - 1); self.set_room_index(&rooms, index.min(max_index));
// } }
// } }
// fn remove_current_room(&mut self) {
// if let Some((index, name)) = self.get_room_index() {
// let name = name.to_string();
// self.rooms.remove(&name);
// let index = if self.rooms.is_empty() {
// 0
// } else {
// index.min(self.rooms.len() - 1)
// };
// self.set_room_index(index);
// }
// }
} }

View file

@ -1,7 +1,25 @@
mod users; mod users;
use tui::backend::Backend;
use tui::layout::Rect;
use tui::Frame;
use crate::cove::room::CoveRoom; use crate::cove::room::CoveRoom;
pub struct CoveUi { pub struct CoveUi {
room: CoveRoom, room: CoveRoom,
} }
impl CoveUi {
pub fn new(room: CoveRoom) -> Self {
Self { room }
}
pub async fn render_main<B: Backend>(&mut self, frame: &mut Frame<'_, B>, area: Rect) {
// TODO Implement
}
pub async fn render_users<B: Backend>(&mut self, frame: &mut Frame<'_, B>, area: Rect) {
// TODO Implement
}
}

View file

@ -2,6 +2,8 @@ mod switch_room;
pub use switch_room::*; pub use switch_room::*;
use super::RoomId;
pub enum Overlay { pub enum Overlay {
SwitchRoom(SwitchRoomState), SwitchRoom(SwitchRoomState),
} }
@ -9,5 +11,5 @@ pub enum Overlay {
pub enum OverlayReaction { pub enum OverlayReaction {
Handled, Handled,
Close, Close,
SwitchRoom(String), SwitchRoom(RoomId),
} }

View file

@ -4,8 +4,8 @@ use tui::layout::Rect;
use tui::widgets::{Block, Borders, Clear, StatefulWidget, Widget}; use tui::widgets::{Block, Borders, Clear, StatefulWidget, Widget};
use crate::ui::input::EventHandler; use crate::ui::input::EventHandler;
use crate::ui::layout;
use crate::ui::textline::{TextLine, TextLineReaction, TextLineState}; use crate::ui::textline::{TextLine, TextLineReaction, TextLineState};
use crate::ui::{layout, RoomId};
use super::OverlayReaction; use super::OverlayReaction;
@ -36,7 +36,12 @@ impl EventHandler for SwitchRoomState {
fn handle_key(&mut self, event: KeyEvent) -> Option<Self::Reaction> { fn handle_key(&mut self, event: KeyEvent) -> Option<Self::Reaction> {
if event.code == KeyCode::Enter { if event.code == KeyCode::Enter {
return Some(Self::Reaction::SwitchRoom(self.room.content())); let name = self.room.content().trim();
if name.is_empty() {
return Some(Self::Reaction::Handled);
}
let id = RoomId::Cove(name.to_string());
return Some(Self::Reaction::SwitchRoom(id));
} }
self.room.handle_key(event).map(|r| match r { self.room.handle_key(event).map(|r| match r {

View file

@ -34,8 +34,8 @@ pub struct TextLineState {
} }
impl TextLineState { impl TextLineState {
pub fn content(&self) -> String { pub fn content(&self) -> &str {
self.content.clone() &self.content
} }
/// The cursor's position from when the widget was last rendered. /// The cursor's position from when the widget was last rendered.