Reimplement room interactions for new rooms
This commit is contained in:
parent
e81900caac
commit
c36f35747f
6 changed files with 136 additions and 88 deletions
|
|
@ -35,6 +35,7 @@ pub enum Error {
|
|||
|
||||
pub enum Event {
|
||||
StateChanged,
|
||||
// TODO Add IdentificationRequired event
|
||||
// TODO Add events for joining, parting, sending, ...
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue