From f34bf63be4563dd2d92ad4fe4c2dfd66ad79dc70 Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 27 Feb 2022 00:16:36 +0100 Subject: [PATCH] Show users if room knows them Also selects the current room in the rooms list --- cove-core/src/id.rs | 2 +- cove-core/src/macros.rs | 2 +- cove-tui/src/room.rs | 10 ++++-- cove-tui/src/ui.rs | 16 ++++++--- cove-tui/src/ui/room.rs | 22 ++++++++++-- cove-tui/src/ui/room/users.rs | 63 +++++++++++++++++++++++++++++++++++ cove-tui/src/ui/rooms.rs | 16 --------- 7 files changed, 104 insertions(+), 27 deletions(-) create mode 100644 cove-tui/src/ui/room/users.rs diff --git a/cove-core/src/id.rs b/cove-core/src/id.rs index 87e7d41..2986927 100644 --- a/cove-core/src/id.rs +++ b/cove-core/src/id.rs @@ -8,7 +8,7 @@ use crate::macros::id_alias; // TODO Use base64 representation instead -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] struct Id(#[serde(with = "hex")] [u8; 32]); impl Id { diff --git a/cove-core/src/macros.rs b/cove-core/src/macros.rs index 882062a..822d5e7 100644 --- a/cove-core/src/macros.rs +++ b/cove-core/src/macros.rs @@ -3,7 +3,7 @@ macro_rules! id_alias { ($name:ident) => { - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)] + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] pub struct $name(Id); impl $name { diff --git a/cove-tui/src/room.rs b/cove-tui/src/room.rs index ef7eea1..647830b 100644 --- a/cove-tui/src/room.rs +++ b/cove-tui/src/room.rs @@ -36,9 +36,9 @@ struct Connected { } /// State for when a client has fully joined a room. -struct Present { - session: Session, - others: HashMap, +pub struct Present { + pub session: Session, + pub others: HashMap, } enum Status { @@ -95,6 +95,10 @@ impl Room { room } + pub fn present(&self) -> Option<&Present> { + self.present.as_ref() + } + async fn bg_task(room: Arc>, config: &'static Config) { let mut room_verified = false; loop { diff --git a/cove-tui/src/ui.rs b/cove-tui/src/ui.rs index e0a1364..71b05d1 100644 --- a/cove-tui/src/ui.rs +++ b/cove-tui/src/ui.rs @@ -237,10 +237,18 @@ impl Ui { let users_pane_border = areas[3]; let users_pane_area = areas[4]; - // Rooms pane - frame.render_widget(Rooms::new(&self.rooms), rooms_pane_area); + // 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; + } - // TODO Main pane and users pane + // Rooms pane + let mut rooms = Rooms::new(&self.rooms); + if let Some(room) = &self.room { + rooms = rooms.select(room.name()); + } + frame.render_widget(rooms, rooms_pane_area); // Pane borders and width self.rooms_pane.restrict_width(rooms_pane_area.width); @@ -248,7 +256,7 @@ impl Ui { self.users_pane.restrict_width(users_pane_area.width); frame.render_widget(self.users_pane.border(), users_pane_border); - // Overlays + // Overlay if let Some(overlay) = &mut self.overlay { match overlay { Overlay::JoinRoom(state) => { diff --git a/cove-tui/src/ui/room.rs b/cove-tui/src/ui/room.rs index 7270e60..c09a954 100644 --- a/cove-tui/src/ui/room.rs +++ b/cove-tui/src/ui/room.rs @@ -1,12 +1,17 @@ +mod users; + use std::sync::Arc; use tokio::sync::Mutex; use tui::backend::Backend; use tui::layout::Rect; +use tui::widgets::{Block, BorderType, Borders}; use tui::Frame; use crate::room::Room; +use self::users::Users; + pub struct RoomInfo { name: String, room: Arc>, @@ -21,11 +26,24 @@ impl RoomInfo { &self.name } - pub async fn render_messages(&mut self, frame: &mut Frame<'_, B>, area: Rect) { + pub async fn render_main(&mut self, frame: &mut Frame<'_, B>, area: Rect) { // TODO Implement + frame.render_widget( + Block::default() + .borders(Borders::TOP) + .border_type(BorderType::Double), + Rect { + x: area.x, + y: area.y + 1, + width: area.width, + height: 1, + }, + ); } pub async fn render_users(&mut self, frame: &mut Frame<'_, B>, area: Rect) { - // TODO Implement + if let Some(present) = self.room.lock().await.present() { + frame.render_widget(Users::new(present), area); + } } } diff --git a/cove-tui/src/ui/room/users.rs b/cove-tui/src/ui/room/users.rs new file mode 100644 index 0000000..0ca9583 --- /dev/null +++ b/cove-tui/src/ui/room/users.rs @@ -0,0 +1,63 @@ +use std::collections::HashSet; +use std::iter; + +use cove_core::{Identity, Session}; +use tui::buffer::Buffer; +use tui::layout::Rect; +use tui::style::{Modifier, Style}; +use tui::text::{Span, Spans}; +use tui::widgets::{Paragraph, Widget}; + +use crate::room::Present; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +struct UserInfo { + nick: String, + identity: Identity, +} + +impl From<&Session> for UserInfo { + fn from(s: &Session) -> Self { + UserInfo { + nick: s.nick.clone(), + identity: s.identity, + } + } +} + +pub struct Users { + users: Vec, +} + +impl Users { + pub fn new(present: &Present) -> Self { + let mut users: Vec = iter::once(&present.session) + .chain(present.others.values()) + .map(<&Session as Into>::into) + .collect(); + users.sort(); + Self { users } + } +} + +impl Widget for Users { + fn render(self, area: Rect, buf: &mut Buffer) { + let title_style = Style::default().add_modifier(Modifier::BOLD); + + let sessions = self.users.len(); + let identities = self + .users + .iter() + .map(|i| i.identity) + .collect::>() + .len(); + let title = format!("Users ({identities}/{sessions})"); + + let mut lines = vec![Spans::from(Span::styled(title, title_style))]; + for user in self.users { + // TODO Colour users based on identity + lines.push(Spans::from(Span::from(user.nick))); + } + Paragraph::new(lines).render(area, buf); + } +} diff --git a/cove-tui/src/ui/rooms.rs b/cove-tui/src/ui/rooms.rs index 2a28162..9d9cba6 100644 --- a/cove-tui/src/ui/rooms.rs +++ b/cove-tui/src/ui/rooms.rs @@ -41,22 +41,6 @@ impl Rooms { } self } - - pub fn dummy() -> Self { - fn r(s: &str) -> RoomInfo { - RoomInfo { - name: s.to_string(), - } - } - - let mut rooms = vec![r("xkcd"), r("test"), r("welcome"), r("music")]; - rooms.sort(); - Rooms { - rooms, - selected: None, - } - .select("welcome") - } } impl Widget for Rooms {