forked from trinitrix/core
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 crate::app::{App};
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
event::{self, DisableMouseCapture, EnableMouseCapture, Event, read},
|
event::{self, DisableMouseCapture, EnableMouseCapture, Event, read},
|
||||||
|
@ -24,8 +25,20 @@ enum SetupInputPosition {
|
||||||
Ok
|
Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UI {
|
#[derive(Clone, Copy)]
|
||||||
|
enum MainInputPosition {
|
||||||
|
Status,
|
||||||
|
Rooms,
|
||||||
|
Messages,
|
||||||
|
MessageCompose,
|
||||||
|
RoomInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UI<'a> {
|
||||||
terminal: Terminal<CrosstermBackend<Stdout>>,
|
terminal: Terminal<CrosstermBackend<Stdout>>,
|
||||||
|
|
||||||
|
input_position: MainInputPosition,
|
||||||
|
message_compose: TextArea<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_prepare() -> Result<Stdout> {
|
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)));
|
content.extend(Text::styled("settings", Style::default().fg(Color::LightMagenta).add_modifier(Modifier::ITALIC | Modifier::UNDERLINED)));
|
||||||
|
|
||||||
let panel = Paragraph::new(content)
|
let panel = Paragraph::new(content)
|
||||||
.block(
|
.block(Block::default()
|
||||||
Block::default()
|
|
||||||
.title("Status")
|
.title("Status")
|
||||||
.borders(Borders::ALL))
|
.borders(Borders::ALL))
|
||||||
.alignment(Alignment::Left);
|
.alignment(Alignment::Left);
|
||||||
|
@ -79,8 +91,7 @@ fn draw_main_messages_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: R
|
||||||
};
|
};
|
||||||
|
|
||||||
let panel = Paragraph::new(messages)
|
let panel = Paragraph::new(messages)
|
||||||
.block(
|
.block(Block::default()
|
||||||
Block::default()
|
|
||||||
.title("Messages")
|
.title("Messages")
|
||||||
.borders(Borders::ALL))
|
.borders(Borders::ALL))
|
||||||
.alignment(Alignment::Left)
|
.alignment(Alignment::Left)
|
||||||
|
@ -90,14 +101,6 @@ fn draw_main_messages_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: R
|
||||||
frame.render_widget(panel, area);
|
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) {
|
fn draw_main_room_info_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area: Rect) {
|
||||||
let panel = Block::default()
|
let panel = Block::default()
|
||||||
.title("Room Info")
|
.title("Room Info")
|
||||||
|
@ -106,6 +109,10 @@ fn draw_main_room_info_block(frame: &mut Frame<CrosstermBackend<Stdout>>, area:
|
||||||
frame.render_widget(panel, 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) {
|
fn textarea_activate(textarea: &mut TextArea) {
|
||||||
textarea.set_cursor_line_style(Style::default().add_modifier(Modifier::UNDERLINED));
|
textarea.set_cursor_line_style(Style::default().add_modifier(Modifier::UNDERLINED));
|
||||||
textarea.set_cursor_style(Style::default().add_modifier(Modifier::REVERSED));
|
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 {
|
pub fn new() -> Self {
|
||||||
let stdout = terminal_prepare().expect("failed to prepare terminal");
|
let stdout = terminal_prepare().expect("failed to prepare terminal");
|
||||||
let backend = CrosstermBackend::new(stdout);
|
let backend = CrosstermBackend::new(stdout);
|
||||||
|
@ -137,12 +144,22 @@ impl UI {
|
||||||
|
|
||||||
terminal.clear().expect("failed to clear screen");
|
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 {
|
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 chunk = self.terminal.size()?;
|
||||||
|
|
||||||
let main_chunks = Layout::default()
|
let main_chunks = Layout::default()
|
||||||
|
@ -157,7 +174,7 @@ impl UI {
|
||||||
|
|
||||||
let middle_chunks = Layout::default()
|
let middle_chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.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]);
|
.split(main_chunks[1]);
|
||||||
|
|
||||||
let right_chunks = Layout::default()
|
let right_chunks = Layout::default()
|
||||||
|
@ -165,12 +182,11 @@ impl UI {
|
||||||
.constraints([Constraint::Min(4)].as_ref())
|
.constraints([Constraint::Min(4)].as_ref())
|
||||||
.split(main_chunks[2]);
|
.split(main_chunks[2]);
|
||||||
|
|
||||||
|
|
||||||
self.terminal.draw(|frame| {
|
self.terminal.draw(|frame| {
|
||||||
draw_main_status_block(frame, left_chunks[0], app);
|
draw_main_status_block(frame, left_chunks[0], app);
|
||||||
draw_main_rooms_block(frame, left_chunks[1]);
|
draw_main_rooms_block(frame, left_chunks[1]);
|
||||||
draw_main_messages_block(frame, middle_chunks[0], app);
|
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]);
|
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<()> {
|
pub async fn main(&mut self, app: &mut App) -> Result<()> {
|
||||||
self.draw_main(app)?;
|
textarea_activate(&mut self.message_compose);
|
||||||
Ok(())
|
|
||||||
|
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<()> {
|
pub async fn setup(&mut self, app: &mut App) -> Result<()> {
|
||||||
let mut input_index = SetupInputPosition::Homeserver;
|
let mut input_index = SetupInputPosition::Homeserver;
|
||||||
let mut strings: Vec<String> = Vec::new();
|
let mut strings: Vec<String> = Vec::new();
|
||||||
strings.resize(3, "".to_string());
|
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_active = Span::styled("OK", Style::default().add_modifier(Modifier::UNDERLINED));
|
||||||
let content_ok_inactive = Span::styled("OK", Style::default().fg(Color::DarkGray));
|
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 {
|
let mut ok = Paragraph::new(match input_index {
|
||||||
SetupInputPosition::Ok => content_ok_active.clone(),
|
SetupInputPosition::Ok => content_ok_active.clone(),
|
||||||
_ => content_ok_inactive.clone(),
|
_ => content_ok_inactive.clone(),
|
||||||
})
|
}).alignment(Alignment::Center);
|
||||||
.alignment(Alignment::Center);
|
|
||||||
|
|
||||||
// define a 32 * 6 chunk in the middle of the screen
|
// define a 32 * 6 chunk in the middle of the screen
|
||||||
let mut chunk = self.terminal.size()?;
|
let mut chunk = self.terminal.size()?;
|
||||||
|
|
Loading…
Reference in New Issue