Set nick and join room

While entering a nick and while present, events seem to get swallowed by
the room. I'll need to rethink my event handling strategy and key
bindings. For the key bindings, I'll either need global bindings that
don't interfere with text boxes, or I'll need modal editing or something
similar where pressing ESC enough brings you back to the global focus.
Global key bindings are things like switching rooms and quitting.
This commit is contained in:
Joscha 2022-03-05 23:34:12 +01:00
parent 32959cf691
commit 168acbf6dc
4 changed files with 54 additions and 17 deletions

View file

@ -91,6 +91,10 @@ impl CoveRoom {
&self.name &self.name
} }
pub async fn identify(&self, nick: &str, identity: &str) {
self.conn().await.identify(nick, identity).await;
}
// TODO Disallow modification via this MutexGuard // TODO Disallow modification via this MutexGuard
pub async fn conn(&self) -> MutexGuard<'_, CoveConn> { pub async fn conn(&self) -> MutexGuard<'_, CoveConn> {
self.conn.lock().await self.conn.lock().await

View file

@ -267,11 +267,14 @@ impl Ui {
event: KeyEvent, event: KeyEvent,
) -> Option<EventHandleResult> { ) -> Option<EventHandleResult> {
match &self.room { match &self.room {
Some(RoomId::Cove(name)) => self Some(RoomId::Cove(name)) => {
.cove_rooms if let Some(ui) = self.cove_rooms.get_mut(name) {
.get_mut(name) ui.handle_key(event).await;
.and_then(|ui| ui.handle_key(event)) Some(EventHandleResult::Continue)
.and(Some(EventHandleResult::Continue)), } else {
None
}
}
None => None, None => None,
} }
} }

View file

@ -10,7 +10,7 @@ use tui::Frame;
use crate::client::cove::room::CoveRoom; use crate::client::cove::room::CoveRoom;
use self::body::Body; use self::body::{Body, Reaction};
use self::users::CoveUsers; use self::users::CoveUsers;
use super::input::EventHandler; use super::input::EventHandler;
@ -78,12 +78,14 @@ impl CoveUi {
frame.render_widget(CoveUsers::new(present), area); frame.render_widget(CoveUsers::new(present), area);
} }
} }
}
impl EventHandler for CoveUi { pub async fn handle_key(&mut self, event: KeyEvent) -> Option<()> {
type Reaction = (); match self.body.handle_key(event)? {
Reaction::Handled => Some(()),
fn handle_key(&mut self, event: KeyEvent) -> Option<Self::Reaction> { Reaction::Identify(nick) => {
None self.room.identify(&nick, &nick).await;
Some(())
}
}
} }
} }

View file

@ -1,3 +1,4 @@
use crossterm::event::{KeyCode, KeyEvent};
use tui::backend::Backend; use tui::backend::Backend;
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect}; use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
use tui::text::Span; use tui::text::Span;
@ -7,6 +8,7 @@ use unicode_width::UnicodeWidthStr;
use crate::client::cove::conn::{State, Status}; use crate::client::cove::conn::{State, Status};
use crate::client::cove::room::CoveRoom; use crate::client::cove::room::CoveRoom;
use crate::ui::input::EventHandler;
use crate::ui::textline::{TextLine, TextLineState}; use crate::ui::textline::{TextLine, TextLineState};
use crate::ui::{layout, styles}; use crate::ui::{layout, styles};
@ -86,10 +88,11 @@ impl Body {
let text_area = areas[1]; let text_area = areas[1];
frame.render_widget( frame.render_widget(
Paragraph::new(Span::styled("Choose a nick:", styles::title())), Paragraph::new(Span::styled("Choose a nick:", styles::title()))
.alignment(Alignment::Center),
title_area, title_area,
); );
frame.render_stateful_widget(TextLine, text_area, nick); frame.render_stateful_widget(TextLine, layout::centered(50, 1, text_area), nick);
} }
Body::ChooseNick { Body::ChooseNick {
nick, nick,
@ -109,12 +112,14 @@ impl Body {
let error_area = areas[2]; let error_area = areas[2];
frame.render_widget( frame.render_widget(
Paragraph::new(Span::styled("Choose a nick:", styles::title())), Paragraph::new(Span::styled("Choose a nick:", styles::title()))
.alignment(Alignment::Center),
title_area, title_area,
); );
frame.render_stateful_widget(TextLine, text_area, nick); frame.render_stateful_widget(TextLine, layout::centered(50, 1, text_area), nick);
frame.render_widget( frame.render_widget(
Paragraph::new(Span::styled(error as &str, styles::error())), Paragraph::new(Span::styled(error as &str, styles::error()))
.alignment(Alignment::Center),
error_area, error_area,
); );
} }
@ -131,3 +136,26 @@ impl Body {
} }
} }
} }
pub enum Reaction {
Handled,
Identify(String),
}
impl EventHandler for Body {
type Reaction = Reaction;
fn handle_key(&mut self, event: KeyEvent) -> Option<Self::Reaction> {
match self {
Body::ChooseNick { nick, .. } => {
if event.code == KeyCode::Enter {
Some(Reaction::Identify(nick.content().to_string()))
} else {
nick.handle_key(event).and(Some(Reaction::Handled))
}
}
Body::Present => None, // TODO Implement
_ => None,
}
}
}