feature (UI): made message compose in main ui a TextArea
This commit is contained in:
parent
82bd751ac8
commit
af7c79ac75
|
@ -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()?;
|
||||
|
|
Reference in New Issue