refactor(multiverse): Create generic PopupInput widget

This commit is contained in:
dragonfly1033
2025-08-10 16:18:03 +01:00
committed by Andy Balaam
parent d2feeaac30
commit dfc0ef8b35
4 changed files with 91 additions and 57 deletions

View File

@@ -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);
}
}

View File

@@ -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<String> {
@@ -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);
}
}

View File

@@ -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;

View File

@@ -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<T: Into<String>>(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);
}
}