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 {
|
pub enum Event {
|
||||||
StateChanged,
|
StateChanged,
|
||||||
|
// TODO Add IdentificationRequired event
|
||||||
// TODO Add events for joining, parting, sending, ...
|
// TODO Add events for joining, parting, sending, ...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
|
||||||
if !name.is_empty() {
|
|
||||||
self.overlay = None;
|
self.overlay = None;
|
||||||
// self.switch_to_room(name.to_string()).await;
|
self.switch_to_room(id).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);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue