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 {
StateChanged,
// TODO Add IdentificationRequired event
// TODO Add events for joining, parting, sending, ...
}

View file

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

View file

@ -1,7 +1,25 @@
mod users;
use tui::backend::Backend;
use tui::layout::Rect;
use tui::Frame;
use crate::cove::room::CoveRoom;
pub struct CoveUi {
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::*;
use super::RoomId;
pub enum Overlay {
SwitchRoom(SwitchRoomState),
}
@ -9,5 +11,5 @@ pub enum Overlay {
pub enum OverlayReaction {
Handled,
Close,
SwitchRoom(String),
SwitchRoom(RoomId),
}

View file

@ -4,8 +4,8 @@ use tui::layout::Rect;
use tui::widgets::{Block, Borders, Clear, StatefulWidget, Widget};
use crate::ui::input::EventHandler;
use crate::ui::layout;
use crate::ui::textline::{TextLine, TextLineReaction, TextLineState};
use crate::ui::{layout, RoomId};
use super::OverlayReaction;
@ -36,7 +36,12 @@ impl EventHandler for SwitchRoomState {
fn handle_key(&mut self, event: KeyEvent) -> Option<Self::Reaction> {
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 {

View file

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