From a9144f0ce64b6c716b420248a975613a75444762 Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Wed, 6 Aug 2025 10:59:13 -0700 Subject: [PATCH] done with text sending widget --- Cargo.lock | 1 + Cargo.toml | 1 + src/app/mod.rs | 2 ++ src/app/widgets.rs | 35 +++++++++++++++++++++-------------- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e8fcb7..7a67565 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1177,6 +1177,7 @@ dependencies = [ "tower-http", "tui-input", "tui-logger", + "unicode-segmentation", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b4d2c00..0e9d429 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,4 @@ tokio = { version = "1", default-features = false, features = ["time", "macros", tower-http = { version = "0.6", features = ["limit"] } tui-input = "0.14.0" tui-logger = { version = "0.17", features = ["crossterm"] } +unicode-segmentation = "1.12.0" diff --git a/src/app/mod.rs b/src/app/mod.rs index 302dcf2..aa6d1e8 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -148,6 +148,7 @@ impl App { }, SendingScreen::Peers => match code { KeyCode::Tab => *sending_screen = SendingScreen::Files, + KeyCode::Char('t') => *sending_screen = SendingScreen::Text, KeyCode::Enter => self.send_content().await, KeyCode::Up => self.peer_state.select_previous(), KeyCode::Down => self.peer_state.select_next(), @@ -166,6 +167,7 @@ impl App { KeyCode::Enter => self.send_text().await, KeyCode::Esc => { self.text = None; + self.input.reset(); *sending_screen = SendingScreen::Files; } _ => { diff --git a/src/app/widgets.rs b/src/app/widgets.rs index 4057df0..c869362 100644 --- a/src/app/widgets.rs +++ b/src/app/widgets.rs @@ -195,14 +195,18 @@ impl Widget for &mut App { ); if s == SendingScreen::Text { - let rect = centered_rect(area, 90, 80); + let rect = centered_rect(area, Constraint::Percentage(80), Constraint::Max(10)); let text = if let Some(text) = self.text.as_ref() { text } else { "" }; - text_input(text, rect, buf); + text_popup(text, " Enter Text to Send ", rect, buf); + // TODO: add cursor, need to do that in the `draw` method + // because we need the frame to do it; add cursor position + // fields to `App` and mutate them in the text input + // function } } _ => { @@ -228,15 +232,18 @@ fn outer_frame(screen: &CurrentScreen, menu: &Line, area: Rect, buf: &mut Buffer .render(area, buf); } -fn text_input(text: &str, area: Rect, buf: &mut Buffer) { - let title = Line::from(" Input Text ".bold()); +fn text_popup(text: &str, title: &str, area: Rect, buf: &mut Buffer) { + let title = Line::from(title.bold()); let block = Block::bordered().title(title.centered()); - ratatui::widgets::Clear::default().render(area, buf); + ratatui::widgets::Clear.render(area, buf); - Paragraph::new(text) - .centered() - .block(block) - .render(area, buf); + block.render(area, buf); + + let (_, len) = unicode_segmentation::UnicodeSegmentation::graphemes(text, true).size_hint(); + let len = len.unwrap_or(text.len()) as u16; + let area = centered_rect(area, Constraint::Length(len), Constraint::Length(1)); + + Paragraph::new(text).centered().yellow().render(area, buf); } fn logger(area: Rect, buf: &mut Buffer) { @@ -385,10 +392,10 @@ impl Widget for NetworkInfoWidget { } // helpers -fn centered_rect(area: Rect, width_pct: u16, height_pct: u16) -> Rect { - let horizontal = Layout::horizontal([Constraint::Percentage(width_pct)]).flex(Flex::Center); - let vertical = Layout::vertical([Constraint::Percentage(height_pct)]).flex(Flex::Center); - let [area] = vertical.areas(area); - let [area] = horizontal.areas(area); +fn centered_rect(area: Rect, horizontal: Constraint, vertical: Constraint) -> Rect { + let [area] = Layout::horizontal([horizontal]) + .flex(Flex::Center) + .areas(area); + let [area] = Layout::vertical([vertical]).flex(Flex::Center).areas(area); area }