From c7cbd9856b42649ab2e9249d70f4c2126dd6f1e1 Mon Sep 17 00:00:00 2001 From: Joscha Date: Thu, 13 Apr 2023 01:33:08 +0200 Subject: [PATCH] Migrate nick list to AsyncWidget --- src/ui/euph/nick_list.rs | 79 ++++++++++++++++++++++++---------------- src/ui/euph/room.rs | 32 +++++++--------- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/ui/euph/nick_list.rs b/src/ui/euph/nick_list.rs index 05ef864..1396822 100644 --- a/src/ui/euph/nick_list.rs +++ b/src/ui/euph/nick_list.rs @@ -4,19 +4,21 @@ use std::iter; use crossterm::style::{Color, Stylize}; use euphoxide::api::{NickEvent, SessionId, SessionType, SessionView, UserId}; use euphoxide::conn::{Joined, SessionInfo}; -use toss::{Style, Styled}; +use toss::widgets::{BoxedAsync, Empty, Text}; +use toss::{Style, Styled, WidgetExt}; use crate::euph; -use crate::ui::widgets::background::Background; -use crate::ui::widgets::empty::Empty; -use crate::ui::widgets::list::{List, ListState}; -use crate::ui::widgets::text::Text; -use crate::ui::widgets::BoxedWidget; +use crate::ui::widgets2::{List, ListState}; +use crate::ui::UiError; -pub fn widget(state: &ListState, joined: &Joined, focused: bool) -> BoxedWidget { - let mut list = state.widget().focus(focused); - render_rows(&mut list, joined); - list.into() +pub fn widget<'a>( + list: &'a mut ListState, + joined: &Joined, + focused: bool, +) -> BoxedAsync<'a, UiError> { + let mut list = list.widget(); + render_rows(&mut list, joined, focused); + list.boxed_async() } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] @@ -57,7 +59,11 @@ impl HalfSession { } } -fn render_rows(list: &mut List, joined: &Joined) { +fn render_rows( + list: &mut List<'_, SessionId, BoxedAsync<'static, UiError>>, + joined: &Joined, + focused: bool, +) { let mut people = vec![]; let mut bots = vec![]; let mut lurkers = vec![]; @@ -82,17 +88,18 @@ fn render_rows(list: &mut List, joined: &Joined) { lurkers.sort_unstable(); nurkers.sort_unstable(); - render_section(list, "People", &people, &joined.session); - render_section(list, "Bots", &bots, &joined.session); - render_section(list, "Lurkers", &lurkers, &joined.session); - render_section(list, "Nurkers", &nurkers, &joined.session); + render_section(list, "People", &people, &joined.session, focused); + render_section(list, "Bots", &bots, &joined.session, focused); + render_section(list, "Lurkers", &lurkers, &joined.session, focused); + render_section(list, "Nurkers", &nurkers, &joined.session, focused); } fn render_section( - list: &mut List, + list: &mut List<'_, SessionId, BoxedAsync<'static, UiError>>, name: &str, sessions: &[HalfSession], own_session: &SessionView, + focused: bool, ) { if sessions.is_empty() { return; @@ -101,20 +108,25 @@ fn render_section( let heading_style = Style::new().bold(); if !list.is_empty() { - list.add_unsel(Empty::new()); + list.add_unsel(Empty::new().boxed_async()); } let row = Styled::new_plain(" ") .then(name, heading_style) .then_plain(format!(" ({})", sessions.len())); - list.add_unsel(Text::new(row)); + list.add_unsel(Text::new(row).boxed_async()); for session in sessions { - render_row(list, session, own_session); + render_row(list, session, own_session, focused); } } -fn render_row(list: &mut List, session: &HalfSession, own_session: &SessionView) { +fn render_row( + list: &mut List<'_, SessionId, BoxedAsync<'static, UiError>>, + session: &HalfSession, + own_session: &SessionView, + focused: bool, +) { let (name, style, style_inv, perms_style_inv) = if session.name.is_empty() { let name = "lurk"; let style = Style::new().grey(); @@ -146,15 +158,20 @@ fn render_row(list: &mut List, session: &HalfSession, own_session: &S " " }; - let normal = Styled::new_plain(owner) - .then(&name, style) - .then_plain(perms); - let selected = Styled::new_plain(owner) - .then(name, style_inv) - .then(perms, perms_style_inv); - list.add_sel( - session.session_id.clone(), - Text::new(normal), - Background::new(Text::new(selected)).style(style_inv), - ); + let widget = if focused && list.state().selected() == Some(&session.session_id) { + let text = Styled::new_plain(owner) + .then(name, style_inv) + .then(perms, perms_style_inv); + Text::new(text) + .background() + .with_style(style_inv) + .boxed_async() + } else { + let text = Styled::new_plain(owner) + .then(&name, style) + .then_plain(perms); + Text::new(text).boxed_async() + }; + + list.add_sel(session.session_id.clone(), widget); } diff --git a/src/ui/euph/room.rs b/src/ui/euph/room.rs index 9f9786d..f82e51a 100644 --- a/src/ui/euph/room.rs +++ b/src/ui/euph/room.rs @@ -17,9 +17,9 @@ use crate::macros::logging_unwrap; use crate::ui::chat::{ChatState, Reaction}; use crate::ui::input::{key, InputEvent, KeyBindingsList}; use crate::ui::widgets::editor::EditorState as OldEditorState; -use crate::ui::widgets::list::ListState as OldListState; use crate::ui::widgets::WidgetWrapper; -use crate::ui::{util, UiError, UiEvent}; +use crate::ui::widgets2::ListState; +use crate::ui::{util2, UiError, UiEvent}; use crate::vault::EuphRoomVault; use super::account::{self, AccountUiState}; @@ -60,7 +60,7 @@ pub struct EuphRoom { chat: EuphChatState, last_msg_sent: Option>, - nick_list: OldListState, + nick_list: ListState, } impl EuphRoom { @@ -80,7 +80,7 @@ impl EuphRoom { popups: VecDeque::new(), chat: ChatState::new(vault), last_msg_sent: None, - nick_list: OldListState::new(), + nick_list: ListState::new(), } } @@ -266,18 +266,14 @@ impl EuphRoom { fn widget_with_nick_list<'a>( chat: &'a mut EuphChatState, status_widget: impl AsyncWidget + Send + Sync + 'static, - nick_list: &mut OldListState, + nick_list: &'a mut ListState, joined: &Joined, focus: Focus, ) -> BoxedAsync<'a, UiError> { - let nick_list_widget = WidgetWrapper::new(nick_list::widget( - nick_list, - joined, - focus == Focus::NickList, - )) - .padding() - .with_right(1) - .border(); + let nick_list_widget = nick_list::widget(nick_list, joined, focus == Focus::NickList) + .padding() + .with_right(1) + .border(); let chat_widget = WidgetWrapper::new(chat.widget(joined.session.name.clone(), focus == Focus::Chat)); @@ -512,24 +508,24 @@ impl EuphRoom { } fn list_nick_list_focus_key_bindings(&self, bindings: &mut KeyBindingsList) { - util::list_list_key_bindings(bindings); + util2::list_list_key_bindings(bindings); bindings.binding("i", "inspect session"); } fn handle_nick_list_focus_input_event(&mut self, event: &InputEvent) -> bool { - if util::handle_list_input_event(&mut self.nick_list, event) { + if util2::handle_list_input_event(&mut self.nick_list, event) { return true; } if let key!('i') = event { if let Some(euph::State::Connected(_, conn::State::Joined(joined))) = self.room_state() { - if let Some(id) = self.nick_list.cursor() { - if id == joined.session.session_id { + if let Some(id) = self.nick_list.selected() { + if *id == joined.session.session_id { self.state = State::InspectSession(SessionInfo::Full(joined.session.clone())); - } else if let Some(session) = joined.listing.get(&id) { + } else if let Some(session) = joined.listing.get(id) { self.state = State::InspectSession(session.clone()); } }