Extract nick dialog into module

This commit is contained in:
Joscha 2022-08-21 02:30:12 +02:00
parent 4e0509b08e
commit 9ad550f98c
3 changed files with 108 additions and 57 deletions

View file

@ -1,3 +1,4 @@
mod nick;
mod nick_list; mod nick_list;
mod popup; mod popup;
pub mod room; pub mod room;

83
src/ui/euph/nick.rs Normal file
View file

@ -0,0 +1,83 @@
use std::sync::Arc;
use crossterm::event::KeyCode;
use euphoxide::conn::{Joined, Status};
use parking_lot::FairMutex;
use toss::styled::Styled;
use toss::terminal::Terminal;
use crate::euph::{self, Room};
use crate::ui::input::{key, InputEvent, KeyBindingsList, KeyEvent};
use crate::ui::util;
use crate::ui::widgets::editor::EditorState;
use crate::ui::widgets::padding::Padding;
use crate::ui::widgets::popup::Popup;
use crate::ui::widgets::BoxedWidget;
use super::room::RoomStatus;
pub fn new(joined: Joined) -> EditorState {
EditorState::with_initial_text(joined.session.name)
}
pub fn stable(status: &RoomStatus) -> bool {
matches!(status, RoomStatus::Connected(Status::Joined(_)))
}
pub fn widget(editor: &EditorState) -> BoxedWidget {
let editor = editor
.widget()
.highlight(|s| Styled::new(s, euph::nick_style(s)));
Popup::new(Padding::new(editor).left(1))
.title("Choose nick")
.inner_padding(false)
.build()
}
fn nick_char(c: char) -> bool {
c != '\n'
}
pub fn list_key_bindings(bindings: &mut KeyBindingsList) {
bindings.binding("esc", "abort");
bindings.binding("enter", "set nick");
util::list_editor_key_bindings(bindings, nick_char, false);
}
pub enum EventResult {
NotHandled,
Handled,
ResetState,
}
pub fn handle_input_event(
terminal: &mut Terminal,
crossterm_lock: &Arc<FairMutex<()>>,
event: &InputEvent,
room: &Option<Room>,
editor: &EditorState,
) -> EventResult {
match event {
key!(Esc) => EventResult::ResetState,
key!(Enter) => {
if let Some(room) = &room {
let _ = room.nick(editor.text());
}
EventResult::ResetState
}
_ => {
if util::handle_editor_input_event(
editor,
terminal,
crossterm_lock,
event,
nick_char,
false,
) {
EventResult::Handled
} else {
EventResult::NotHandled
}
}
}
}

View file

@ -29,8 +29,8 @@ use crate::ui::widgets::BoxedWidget;
use crate::ui::{util, UiEvent}; use crate::ui::{util, UiEvent};
use crate::vault::EuphVault; use crate::vault::EuphVault;
use super::nick_list;
use super::popup::RoomPopup; use super::popup::RoomPopup;
use super::{nick, nick_list};
enum State { enum State {
Normal, Normal,
@ -166,9 +166,7 @@ impl EuphRoom {
{ {
self.state = State::Normal self.state = State::Normal
} }
State::Nick(_) if !matches!(status, RoomStatus::Connected(Status::Joined(_))) => { State::Nick(_) if !nick::stable(status) => self.state = State::Normal,
self.state = State::Normal
}
_ => {} _ => {}
} }
} }
@ -193,7 +191,7 @@ impl EuphRoom {
match &self.state { match &self.state {
State::Normal => {} State::Normal => {}
State::Auth(_) => layers.push(Self::auth_widget()), State::Auth(_) => layers.push(Self::auth_widget()),
State::Nick(editor) => layers.push(Self::nick_widget(editor)), State::Nick(editor) => layers.push(nick::widget(editor)),
} }
for popup in &self.popups { for popup in &self.popups {
@ -216,16 +214,6 @@ impl EuphRoom {
.build() .build()
} }
fn nick_widget(editor: &EditorState) -> BoxedWidget {
let editor = editor
.widget()
.highlight(|s| Styled::new(s, euph::nick_style(s)));
Popup::new(Padding::new(editor).left(1))
.title("Choose nick")
.inner_padding(false)
.build()
}
async fn widget_without_nick_list(&self, status: &RoomStatus) -> BoxedWidget { async fn widget_without_nick_list(&self, status: &RoomStatus) -> BoxedWidget {
VJoin::new(vec![ VJoin::new(vec![
Segment::new(Border::new( Segment::new(Border::new(
@ -288,10 +276,6 @@ impl EuphRoom {
Text::new(info).into() Text::new(info).into()
} }
fn nick_char(c: char) -> bool {
c != '\n'
}
pub async fn list_key_bindings(&self, bindings: &mut KeyBindingsList) { pub async fn list_key_bindings(&self, bindings: &mut KeyBindingsList) {
bindings.heading("Room"); bindings.heading("Room");
@ -305,14 +289,14 @@ impl EuphRoom {
bindings.binding("esc", "leave room"); bindings.binding("esc", "leave room");
let can_compose = if let Some(room) = &self.room { let can_compose = if let Some(room) = &self.room {
match room.status().await { match room.status().await.ok().flatten() {
Ok(Some(Status::Joining(Joining { Some(Status::Joining(Joining {
bounce: Some(_), .. bounce: Some(_), ..
}))) => { })) => {
bindings.binding("a", "authenticate"); bindings.binding("a", "authenticate");
false false
} }
Ok(Some(Status::Joined(_))) => { Some(Status::Joined(_)) => {
bindings.binding("n", "change nick"); bindings.binding("n", "change nick");
true true
} }
@ -328,13 +312,9 @@ impl EuphRoom {
State::Auth(_) => { State::Auth(_) => {
bindings.binding("esc", "abort"); bindings.binding("esc", "abort");
bindings.binding("enter", "authenticate"); bindings.binding("enter", "authenticate");
util::list_editor_key_bindings(bindings, Self::nick_char, false); util::list_editor_key_bindings(bindings, |_| true, false);
}
State::Nick(_) => {
bindings.binding("esc", "abort");
bindings.binding("enter", "set nick");
util::list_editor_key_bindings(bindings, Self::nick_char, false);
} }
State::Nick(_) => nick::list_key_bindings(bindings),
} }
} }
@ -376,18 +356,15 @@ impl EuphRoom {
} }
} }
match status { match status.ok().flatten() {
Ok(Some(Status::Joining(Joining { Some(Status::Joining(Joining {
bounce: Some(_), .. bounce: Some(_), ..
}))) if matches!(event, key!('a') | key!('A')) => { })) if matches!(event, key!('a') | key!('A')) => {
self.state = State::Auth(EditorState::new()); self.state = State::Auth(EditorState::new());
true true
} }
Ok(Some(Status::Joined(joined))) Some(Status::Joined(joined)) if matches!(event, key!('n') | key!('N')) => {
if matches!(event, key!('n') | key!('N')) => self.state = State::Nick(nick::new(joined));
{
let name = joined.session.name;
self.state = State::Nick(EditorState::with_initial_text(name));
true true
} }
_ => false, _ => false,
@ -416,31 +393,21 @@ impl EuphRoom {
terminal, terminal,
crossterm_lock, crossterm_lock,
event, event,
Self::nick_char, |_| true,
false, false,
), ),
}, },
State::Nick(ed) => match event { State::Nick(editor) => {
key!(Esc) => { match nick::handle_input_event(terminal, crossterm_lock, event, &self.room, editor)
{
nick::EventResult::NotHandled => false,
nick::EventResult::Handled => true,
nick::EventResult::ResetState => {
self.state = State::Normal; self.state = State::Normal;
true true
} }
key!(Enter) => {
if let Some(room) = &self.room {
let _ = room.nick(ed.text());
} }
self.state = State::Normal;
true
} }
_ => util::handle_editor_input_event(
ed,
terminal,
crossterm_lock,
event,
Self::nick_char,
false,
),
},
} }
} }