Support choosing domain in room connection popup
This commit is contained in:
parent
f4967731a1
commit
970bc07ed9
3 changed files with 142 additions and 38 deletions
|
|
@ -1,3 +1,5 @@
|
|||
mod connect;
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::iter;
|
||||
|
|
@ -17,6 +19,8 @@ use crate::euph;
|
|||
use crate::macros::logging_unwrap;
|
||||
use crate::vault::{EuphVault, RoomIdentifier, Vault};
|
||||
|
||||
use self::connect::{ConnectResult, ConnectState};
|
||||
|
||||
use super::euph::room::EuphRoom;
|
||||
use super::widgets::{ListBuilder, ListState, Popup};
|
||||
use super::{key_bindings, util, UiError, UiEvent};
|
||||
|
|
@ -24,7 +28,7 @@ use super::{key_bindings, util, UiError, UiEvent};
|
|||
enum State {
|
||||
ShowList,
|
||||
ShowRoom(RoomIdentifier),
|
||||
Connect(EditorState),
|
||||
Connect(ConnectState),
|
||||
Delete(RoomIdentifier, EditorState),
|
||||
}
|
||||
|
||||
|
|
@ -242,10 +246,10 @@ impl Rooms {
|
|||
.await
|
||||
}
|
||||
|
||||
State::Connect(editor) => {
|
||||
State::Connect(connect) => {
|
||||
Self::rooms_widget(self.config, &mut self.list, self.order, &self.euph_rooms)
|
||||
.await
|
||||
.below(Self::new_room_widget(editor))
|
||||
.below(connect.widget())
|
||||
.desync()
|
||||
.boxed_async()
|
||||
}
|
||||
|
|
@ -261,20 +265,6 @@ impl Rooms {
|
|||
}
|
||||
}
|
||||
|
||||
fn new_room_widget(editor: &mut EditorState) -> impl Widget<UiError> + '_ {
|
||||
let room_style = Style::new().bold().blue();
|
||||
|
||||
let inner = Join2::horizontal(
|
||||
Text::new(("&", room_style)).segment().with_fixed(true),
|
||||
editor
|
||||
.widget()
|
||||
.with_highlight(|s| Styled::new(s, room_style))
|
||||
.segment(),
|
||||
);
|
||||
|
||||
Popup::new(inner, "Connect to")
|
||||
}
|
||||
|
||||
fn delete_room_widget<'a>(
|
||||
id: &RoomIdentifier,
|
||||
editor: &'a mut EditorState,
|
||||
|
|
@ -472,10 +462,6 @@ impl Rooms {
|
|||
)
|
||||
}
|
||||
|
||||
fn room_char(c: char) -> bool {
|
||||
c.is_ascii_alphanumeric() || c == '_'
|
||||
}
|
||||
|
||||
async fn handle_showlist_input_event(
|
||||
&mut self,
|
||||
event: &mut InputEvent<'_>,
|
||||
|
|
@ -534,7 +520,7 @@ impl Rooms {
|
|||
return true;
|
||||
}
|
||||
if event.matches(&keys.rooms.action.new) {
|
||||
self.state = State::Connect(EditorState::new());
|
||||
self.state = State::Connect(ConnectState::new());
|
||||
return true;
|
||||
}
|
||||
if event.matches(&keys.rooms.action.delete) {
|
||||
|
|
@ -574,28 +560,21 @@ impl Rooms {
|
|||
}
|
||||
}
|
||||
}
|
||||
State::Connect(editor) => {
|
||||
if event.matches(&keys.general.abort) {
|
||||
State::Connect(connect) => match connect.handle_input_event(event, keys) {
|
||||
ConnectResult::Close => {
|
||||
self.state = State::ShowList;
|
||||
return true;
|
||||
}
|
||||
if event.matches(&keys.general.confirm) {
|
||||
let name = editor.text().to_string();
|
||||
if !name.is_empty() {
|
||||
let room = RoomIdentifier {
|
||||
// TODO Remove hardcoded domain
|
||||
domain: "euphoria.leet.nu".to_string(),
|
||||
name,
|
||||
};
|
||||
self.connect_to_room(room.clone()).await;
|
||||
self.state = State::ShowRoom(room);
|
||||
}
|
||||
ConnectResult::Connect(room) => {
|
||||
self.connect_to_room(room.clone()).await;
|
||||
self.state = State::ShowRoom(room);
|
||||
return true;
|
||||
}
|
||||
if util::handle_editor_input_event(editor, event, keys, Self::room_char) {
|
||||
ConnectResult::Handled => {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ConnectResult::Unhandled => {}
|
||||
},
|
||||
State::Delete(id, editor) => {
|
||||
if event.matches(&keys.general.abort) {
|
||||
self.state = State::ShowList;
|
||||
|
|
@ -607,7 +586,7 @@ impl Rooms {
|
|||
self.state = State::ShowList;
|
||||
return true;
|
||||
}
|
||||
if util::handle_editor_input_event(editor, event, keys, Self::room_char) {
|
||||
if util::handle_editor_input_event(editor, event, keys, util::is_room_char) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
120
cove/src/ui/rooms/connect.rs
Normal file
120
cove/src/ui/rooms/connect.rs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
use cove_config::Keys;
|
||||
use cove_input::InputEvent;
|
||||
use crossterm::style::Stylize;
|
||||
use toss::widgets::{EditorState, Empty, Join2, Join3, Text};
|
||||
use toss::{Style, Styled, Widget, WidgetExt};
|
||||
|
||||
use crate::ui::widgets::Popup;
|
||||
use crate::ui::{util, UiError};
|
||||
use crate::vault::RoomIdentifier;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum Focus {
|
||||
Name,
|
||||
Domain,
|
||||
}
|
||||
|
||||
impl Focus {
|
||||
fn advance(self) -> Self {
|
||||
match self {
|
||||
Self::Name => Self::Domain,
|
||||
Self::Domain => Self::Name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConnectState {
|
||||
focus: Focus,
|
||||
name: EditorState,
|
||||
domain: EditorState,
|
||||
}
|
||||
|
||||
pub enum ConnectResult {
|
||||
Close,
|
||||
Connect(RoomIdentifier),
|
||||
Handled,
|
||||
Unhandled,
|
||||
}
|
||||
|
||||
impl ConnectState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
focus: Focus::Name,
|
||||
name: EditorState::new(),
|
||||
domain: EditorState::with_initial_text("euphoria.leet.nu".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_input_event(&mut self, event: &mut InputEvent<'_>, keys: &Keys) -> ConnectResult {
|
||||
if event.matches(&keys.general.abort) {
|
||||
return ConnectResult::Close;
|
||||
}
|
||||
|
||||
if event.matches(&keys.general.focus) {
|
||||
self.focus = self.focus.advance();
|
||||
return ConnectResult::Handled;
|
||||
}
|
||||
|
||||
if event.matches(&keys.general.confirm) {
|
||||
let id = RoomIdentifier {
|
||||
domain: self.domain.text().to_string(),
|
||||
name: self.name.text().to_string(),
|
||||
};
|
||||
if !id.domain.is_empty() && !id.name.is_empty() {
|
||||
return ConnectResult::Connect(id);
|
||||
}
|
||||
}
|
||||
|
||||
let handled = match self.focus {
|
||||
Focus::Name => {
|
||||
util::handle_editor_input_event(&mut self.name, event, keys, util::is_room_char)
|
||||
}
|
||||
Focus::Domain => {
|
||||
util::handle_editor_input_event(&mut self.domain, event, keys, util::is_room_char)
|
||||
}
|
||||
};
|
||||
|
||||
if handled {
|
||||
return ConnectResult::Handled;
|
||||
}
|
||||
|
||||
ConnectResult::Unhandled
|
||||
}
|
||||
|
||||
pub fn widget(&mut self) -> impl Widget<UiError> + '_ {
|
||||
let room_style = Style::new().bold().blue();
|
||||
let domain_style = Style::new().grey();
|
||||
|
||||
let name = Join2::horizontal(
|
||||
Text::new(Styled::new_plain("Room: ").then("&", room_style))
|
||||
.with_wrap(false)
|
||||
.segment()
|
||||
.with_fixed(true),
|
||||
self.name
|
||||
.widget()
|
||||
.with_highlight(|s| Styled::new(s, room_style))
|
||||
.with_focus(self.focus == Focus::Name)
|
||||
.segment(),
|
||||
);
|
||||
|
||||
let domain = Join3::horizontal(
|
||||
Text::new("Domain:")
|
||||
.with_wrap(false)
|
||||
.segment()
|
||||
.with_fixed(true),
|
||||
Empty::new().with_width(1).segment().with_fixed(true),
|
||||
self.domain
|
||||
.widget()
|
||||
.with_highlight(|s| Styled::new(s, domain_style))
|
||||
.with_focus(self.focus == Focus::Domain)
|
||||
.segment(),
|
||||
);
|
||||
|
||||
let inner = Join2::vertical(
|
||||
name.segment().with_fixed(true),
|
||||
domain.segment().with_fixed(true),
|
||||
);
|
||||
|
||||
Popup::new(inner, "Connect to")
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,11 @@ use toss::widgets::EditorState;
|
|||
|
||||
use super::widgets::ListState;
|
||||
|
||||
/// Test if a character is allowed to be typed in a room name.
|
||||
pub fn is_room_char(c: char) -> bool {
|
||||
c.is_ascii_alphanumeric() || c == '_'
|
||||
}
|
||||
|
||||
//////////
|
||||
// List //
|
||||
//////////
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue