feature (ui): added a cli panel to contoll the UI similar to what you have when hitting colon in vim

This commit is contained in:
antifallobst 2023-07-10 00:10:51 +02:00
parent 8d6e7c976e
commit 200b9143b3
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
3 changed files with 99 additions and 5 deletions

View File

@ -132,6 +132,13 @@ impl Event {
}) => {
app.ui.cycle_main_input_position_rev();
}
crossterm::event::Event::Key(KeyEvent {
code: KeyCode::Char('c'),
modifiers: KeyModifiers::CONTROL,
..
}) => {
app.ui.cli_enable();
}
input => match app.ui.input_position() {
ui::MainInputPosition::MessageCompose => {
match input {
@ -239,6 +246,23 @@ impl Event {
_ => (),
};
}
ui::MainInputPosition::CLI => {
if let Some(cli) = &mut app.ui.cli {
match input {
crossterm::event::Event::Key(KeyEvent {
code: KeyCode::Enter,
..
}) => {
let cli_event = cli.lines()[0].clone();
app.status.cli_event(cli_event);
app.ui.cli_disable();
}
_ => {
cli.input(tui_textarea::Input::from(input));
}
};
};
}
_ => (),
},
};

View File

@ -206,4 +206,8 @@ impl Status {
pub fn set_state(&mut self, state: State) {
self.state = state;
}
pub fn cli_event(&mut self, event: String) {
info!("CLI Event: {}", event);
}
}

View File

@ -32,13 +32,14 @@ pub enum SetupInputPosition {
Ok,
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq)]
pub enum MainInputPosition {
Status,
Rooms,
Messages,
MessageCompose,
RoomInfo,
CLI,
}
pub struct SetupUI<'a> {
@ -55,6 +56,7 @@ pub struct UI<'a> {
input_position: MainInputPosition,
pub rooms_state: ListState,
pub message_compose: TextArea<'a>,
pub cli: Option<TextArea<'a>>,
pub setup_ui: Option<SetupUI<'a>>,
}
@ -266,6 +268,7 @@ impl UI<'_> {
input_position: MainInputPosition::Rooms,
rooms_state: ListState::default(),
message_compose,
cli: None,
setup_ui: None,
}
}
@ -276,17 +279,25 @@ impl UI<'_> {
MainInputPosition::Rooms => MainInputPosition::Messages,
MainInputPosition::Messages => MainInputPosition::MessageCompose,
MainInputPosition::MessageCompose => MainInputPosition::RoomInfo,
MainInputPosition::RoomInfo => MainInputPosition::Status,
MainInputPosition::RoomInfo => match self.cli {
Some(_) => MainInputPosition::CLI,
None => MainInputPosition::Status,
},
MainInputPosition::CLI => MainInputPosition::Status,
};
}
pub fn cycle_main_input_position_rev(&mut self) {
self.input_position = match self.input_position {
MainInputPosition::Status => MainInputPosition::RoomInfo,
MainInputPosition::Status => match self.cli {
Some(_) => MainInputPosition::CLI,
None => MainInputPosition::RoomInfo,
},
MainInputPosition::Rooms => MainInputPosition::Status,
MainInputPosition::Messages => MainInputPosition::Rooms,
MainInputPosition::MessageCompose => MainInputPosition::Messages,
MainInputPosition::RoomInfo => MainInputPosition::MessageCompose,
MainInputPosition::CLI => MainInputPosition::RoomInfo,
};
}
@ -303,8 +314,31 @@ impl UI<'_> {
);
}
pub fn cli_enable(&mut self) {
self.input_position = MainInputPosition::CLI;
if self.cli.is_some() {
return;
}
let mut cli = TextArea::default();
cli.set_block(Block::default().borders(Borders::ALL));
self.cli = Some(cli);
}
pub fn cli_disable(&mut self) {
if self.input_position == MainInputPosition::CLI {
self.cycle_main_input_position();
}
self.cli = None;
}
pub async fn update(&mut self, status: &Status) -> Result<()> {
let chunk = self.terminal.size()?;
let chunks = match self.cli {
Some(_) => Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(10), Constraint::Length(3)].as_ref())
.split(self.terminal.size()?),
None => vec![self.terminal.size()?],
};
let main_chunks = Layout::default()
.direction(Direction::Horizontal)
@ -316,7 +350,7 @@ impl UI<'_> {
]
.as_ref(),
)
.split(chunk);
.split(chunks[0]);
let left_chunks = Layout::default()
.direction(Direction::Vertical)
@ -450,6 +484,9 @@ impl UI<'_> {
let colors = match self.input_position {
MainInputPosition::Status => {
textarea_inactivate(&mut self.message_compose);
if let Some(cli) = &mut self.cli {
textarea_inactivate(cli);
}
vec![
Color::White,
Color::DarkGray,
@ -460,6 +497,9 @@ impl UI<'_> {
}
MainInputPosition::Rooms => {
textarea_inactivate(&mut self.message_compose);
if let Some(cli) = &mut self.cli {
textarea_inactivate(cli);
}
vec![
Color::DarkGray,
Color::White,
@ -470,6 +510,9 @@ impl UI<'_> {
}
MainInputPosition::Messages => {
textarea_inactivate(&mut self.message_compose);
if let Some(cli) = &mut self.cli {
textarea_inactivate(cli);
}
vec![
Color::DarkGray,
Color::DarkGray,
@ -480,6 +523,9 @@ impl UI<'_> {
}
MainInputPosition::MessageCompose => {
textarea_activate(&mut self.message_compose);
if let Some(cli) = &mut self.cli {
textarea_inactivate(cli);
}
vec![
Color::DarkGray,
Color::DarkGray,
@ -490,6 +536,9 @@ impl UI<'_> {
}
MainInputPosition::RoomInfo => {
textarea_inactivate(&mut self.message_compose);
if let Some(cli) = &mut self.cli {
textarea_inactivate(cli);
}
vec![
Color::DarkGray,
Color::DarkGray,
@ -498,6 +547,19 @@ impl UI<'_> {
Color::White,
]
}
MainInputPosition::CLI => {
textarea_inactivate(&mut self.message_compose);
if let Some(cli) = &mut self.cli {
textarea_activate(cli);
}
vec![
Color::DarkGray,
Color::DarkGray,
Color::DarkGray,
Color::DarkGray,
Color::DarkGray,
]
}
};
// initiate the widgets
@ -555,6 +617,10 @@ impl UI<'_> {
frame.render_stateful_widget(rooms_panel, left_chunks[1], &mut self.rooms_state);
frame.render_stateful_widget(messages_panel, middle_chunks[0], &mut messages_state);
frame.render_widget(self.message_compose.widget(), middle_chunks[1]);
match &self.cli {
Some(cli) => frame.render_widget(cli.widget(), chunks[1]),
None => (),
};
frame.render_widget(room_info_panel, right_chunks[0]);
})?;