feature (UI): made message compose in main ui a TextArea

This commit is contained in:
antifallobst 2023-06-29 15:13:11 +02:00
parent 82bd751ac8
commit af7c79ac75
1 changed files with 58 additions and 24 deletions

View File

@ -1,3 +1,4 @@
use std::cmp;
use crate::app::{App};
use crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event, read},
@ -24,8 +25,20 @@ enum SetupInputPosition {
Ok
}
pub struct UI {
#[derive(Clone, Copy)]
enum MainInputPosition {
Status,
Rooms,
Messages,
MessageCompose,
RoomInfo
}
pub struct UI<'a> {
terminal: Terminal<CrosstermBackend<Stdout>>,
input_position: MainInputPosition,
message_compose: TextArea<'a>,
}
fn terminal_prepare() -> Result<Stdout> {
@ -43,8 +56,7 @@ fn draw_main_status_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: Rec
content.extend(Text::styled("settings", Style::default().fg(Color::LightMagenta).add_modifier(Modifier::ITALIC | Modifier::UNDERLINED)));
let panel = Paragraph::new(content)
.block(
Block::default()
.block(Block::default()
.title("Status")
.borders(Borders::ALL))
.alignment(Alignment::Left);
@ -79,8 +91,7 @@ fn draw_main_messages_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: R
};
let panel = Paragraph::new(messages)
.block(
Block::default()
.block(Block::default()
.title("Messages")
.borders(Borders::ALL))
.alignment(Alignment::Left)
@ -90,14 +101,6 @@ fn draw_main_messages_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: R
frame.render_widget(panel, area);
}
fn draw_main_message_compose_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: Rect) {
let panel = Block::default()
.title("Message Compose")
.borders(Borders::ALL);
frame.render_widget(panel, area);
}
fn draw_main_room_info_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: Rect) {
let panel = Block::default()
.title("Room Info")
@ -106,6 +109,10 @@ fn draw_main_room_info_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area:
frame.render_widget(panel, area);
}
fn draw_main_message_compose_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: Rect, textarea: &TextArea) {
frame.render_widget(textarea.widget(), area);
}
fn textarea_activate(textarea: &mut TextArea) {
textarea.set_cursor_line_style(Style::default().add_modifier(Modifier::UNDERLINED));
textarea.set_cursor_style(Style::default().add_modifier(Modifier::REVERSED));
@ -129,7 +136,7 @@ fn textarea_inactivate(textarea: &mut TextArea) {
}
impl UI {
impl UI<'_> {
pub fn new() -> Self {
let stdout = terminal_prepare().expect("failed to prepare terminal");
let backend = CrosstermBackend::new(stdout);
@ -137,12 +144,22 @@ impl UI {
terminal.clear().expect("failed to clear screen");
let mut message_compose = TextArea::default();
message_compose.set_block(
Block::default()
.title("Message Compose")
.borders(Borders::ALL));
Self {
terminal
terminal,
input_position: MainInputPosition::Rooms,
message_compose,
}
}
fn draw_main(&mut self, app: &App) -> Result<()> {
pub fn main_update(&'_ mut self, app: &App) -> Result<()> {
// TODO: make thread safe
let chunk = self.terminal.size()?;
let main_chunks = Layout::default()
@ -157,7 +174,7 @@ impl UI {
let middle_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(4), Constraint::Length(3)].as_ref())
.constraints([Constraint::Min(4), Constraint::Length(cmp::min(2 + self.message_compose.lines().len() as u16, 8))].as_ref())
.split(main_chunks[1]);
let right_chunks = Layout::default()
@ -165,12 +182,11 @@ impl UI {
.constraints([Constraint::Min(4)].as_ref())
.split(main_chunks[2]);
self.terminal.draw(|frame| {
draw_main_status_block(frame, left_chunks[0], app);
draw_main_rooms_block(frame, left_chunks[1]);
draw_main_messages_block(frame, middle_chunks[0], app);
draw_main_message_compose_block(frame, middle_chunks[1]);
draw_main_message_compose_block(frame, middle_chunks[1], &self.message_compose);
draw_main_room_info_block(frame, right_chunks[0]);
})?;
@ -178,15 +194,34 @@ impl UI {
}
pub async fn main(&mut self, app: &mut App) -> Result<()> {
self.draw_main(app)?;
Ok(())
textarea_activate(&mut self.message_compose);
loop {
self.main_update(app)?;
match Input::from(read()?.clone()) {
Input { key: Key::Esc, .. } => return Ok(()),
Input {
key: Key::Tab,
..
} => {
// TODO: calc input_position
self.input_position = MainInputPosition::MessageCompose;
}
input => {
match self.input_position {
MainInputPosition::MessageCompose => { self.message_compose.input(input); },
_ => continue,
}
}
};
}
}
pub async fn setup(&mut self, app: &mut App) -> Result<()> {
let mut input_index = SetupInputPosition::Homeserver;
let mut strings: Vec<String> = Vec::new();
strings.resize(3, "".to_string());
self.terminal.show_cursor()?;
let content_ok_active = Span::styled("OK", Style::default().add_modifier(Modifier::UNDERLINED));
let content_ok_inactive = Span::styled("OK", Style::default().fg(Color::DarkGray));
@ -223,8 +258,7 @@ impl UI {
let mut ok = Paragraph::new(match input_index {
SetupInputPosition::Ok => content_ok_active.clone(),
_ => content_ok_inactive.clone(),
})
.alignment(Alignment::Center);
}).alignment(Alignment::Center);
// define a 32 * 6 chunk in the middle of the screen
let mut chunk = self.terminal.size()?;