From dfc0ef8b35df6112cda389f216d33d74a3befd35 Mon Sep 17 00:00:00 2001 From: dragonfly1033 <=> Date: Sun, 10 Aug 2025 16:18:03 +0100 Subject: [PATCH] refactor(multiverse): Create generic `PopupInput` widget --- .../src/widgets/create_room/input.rs | 47 ---------- .../multiverse/src/widgets/create_room/mod.rs | 15 ++-- labs/multiverse/src/widgets/mod.rs | 1 + labs/multiverse/src/widgets/popup_input.rs | 85 +++++++++++++++++++ 4 files changed, 91 insertions(+), 57 deletions(-) delete mode 100644 labs/multiverse/src/widgets/create_room/input.rs create mode 100644 labs/multiverse/src/widgets/popup_input.rs diff --git a/labs/multiverse/src/widgets/create_room/input.rs b/labs/multiverse/src/widgets/create_room/input.rs deleted file mode 100644 index b23076ac3..000000000 --- a/labs/multiverse/src/widgets/create_room/input.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crossterm::event::KeyEvent; -use ratatui::{ - buffer::Buffer, - layout::Rect, - style::{Stylize, palette::tailwind}, - widgets::{Block, Borders, Widget}, -}; -use tui_textarea::TextArea; - -#[derive(Default)] -pub(crate) struct Input { - /// The text area that will keep track of what the user has input. - textarea: TextArea<'static>, -} - -impl Input { - /// Create a new empty [`Input`] widget. - pub fn new() -> Self { - let textarea = TextArea::default(); - Self { textarea } - } - - /// Receive a key press event and handle it. - pub fn handle_key_press(&mut self, key: KeyEvent) { - self.textarea.input(key); - } - - /// Get the currently input text. - pub fn get_input(&self) -> String { - self.textarea.lines().join("\n") - } -} - -impl Widget for &mut Input { - fn render(self, area: Rect, buf: &mut Buffer) { - // Set the placeholder text. - self.textarea.set_placeholder_text("(Enter new room name)"); - - // Let's first create a block to set the background color. - let input_block = - Block::new().borders(Borders::ALL).bg(tailwind::BLUE.c400).title("Create Room"); - - // Now we set the block and we render the textarea. - self.textarea.set_block(input_block); - self.textarea.render(area, buf); - } -} diff --git a/labs/multiverse/src/widgets/create_room/mod.rs b/labs/multiverse/src/widgets/create_room/mod.rs index 105f52c94..d0b1226c4 100644 --- a/labs/multiverse/src/widgets/create_room/mod.rs +++ b/labs/multiverse/src/widgets/create_room/mod.rs @@ -1,16 +1,16 @@ use crossterm::event::KeyEvent; -use ratatui::{layout::Flex, prelude::*}; -mod input; -use input::Input; +use ratatui::prelude::*; + +use crate::widgets::popup_input::PopupInput; #[derive(Default)] pub struct CreateRoomView { - input: Input, + input: PopupInput, } impl CreateRoomView { pub fn new() -> Self { - Self { input: Input::new() } + Self { input: PopupInput::new("Create Room", "(Enter name for new room)") } } pub fn get_text(&self) -> Option { @@ -25,11 +25,6 @@ impl CreateRoomView { impl Widget for &mut CreateRoomView { fn render(self, area: Rect, buf: &mut Buffer) { - let vertical = Layout::vertical([Constraint::Length(3)]).flex(Flex::Center); - let horizontal = Layout::horizontal([Constraint::Percentage(30)]).flex(Flex::Center); - let [area] = vertical.areas(area); - let [area] = horizontal.areas(area); - self.input.render(area, buf); } } diff --git a/labs/multiverse/src/widgets/mod.rs b/labs/multiverse/src/widgets/mod.rs index 38147dfcb..78bbfccb8 100644 --- a/labs/multiverse/src/widgets/mod.rs +++ b/labs/multiverse/src/widgets/mod.rs @@ -3,6 +3,7 @@ use ratatui::{prelude::*, widgets::WidgetRef}; pub mod create_room; pub mod help; +pub mod popup_input; pub mod recovery; pub mod room_list; pub mod room_view; diff --git a/labs/multiverse/src/widgets/popup_input.rs b/labs/multiverse/src/widgets/popup_input.rs new file mode 100644 index 000000000..e53280e16 --- /dev/null +++ b/labs/multiverse/src/widgets/popup_input.rs @@ -0,0 +1,85 @@ +use crossterm::event::KeyEvent; +use ratatui::{ + buffer::Buffer, + layout::{Constraint, Flex, Layout, Rect}, + style::{Stylize, palette::tailwind}, + widgets::{Block, Borders, Clear, Widget}, +}; +use tui_textarea::TextArea; + +#[derive(Default, Clone)] +pub(crate) struct PopupInput { + /// The text area that will keep track of what the user has input. + textarea: TextArea<'static>, + + /// Title of popup + title: String, + + /// Placeholder text of popup + placeholder_text: String, + + /// Width constraint text of popup + width_constraint: Constraint, + + /// Height constraint of popup + height_constraint: Constraint, +} + +impl PopupInput { + /// Create a new empty [`PopupInput`] widget. + pub fn new>(title: T, placeholder_text: T) -> Self { + let mut ret = Self { + textarea: TextArea::default(), + title: title.into(), + placeholder_text: placeholder_text.into(), + width_constraint: Constraint::Percentage(40), + height_constraint: Constraint::Length(3), + }; + + // Set the placeholder text. + ret.textarea.set_placeholder_text(ret.placeholder_text.clone()); + + // Let's first create a block to set the background color. + let input_block = + Block::new().borders(Borders::ALL).bg(tailwind::BLUE.c400).title(ret.title.clone()); + + // Now we set the block and we render the textarea. + ret.textarea.set_block(input_block); + + ret + } + + /// Width constraint text of popup + pub fn width_constraint(&mut self, value: Constraint) -> Self { + self.width_constraint = value; + self.clone() + } + + /// Height constraint of popup + pub fn height_constraint(&mut self, value: Constraint) -> Self { + self.height_constraint = value; + self.clone() + } + + /// Receive a key press event and handle it. + pub fn handle_key_press(&mut self, key: KeyEvent) { + self.textarea.input(key); + } + + /// Get the currently input text. + pub fn get_input(&self) -> String { + self.textarea.lines().join("\n") + } +} + +impl Widget for &mut PopupInput { + fn render(self, area: Rect, buf: &mut Buffer) { + let vertical = Layout::vertical([self.height_constraint]).flex(Flex::Center); + let horizontal = Layout::horizontal([self.width_constraint]).flex(Flex::Center); + let [area] = vertical.areas(area); + let [area] = horizontal.areas(area); + Clear.render(area, buf); + + self.textarea.render(area, buf); + } +}