feat: Implement minimum TUI size (#425)

* Implement minimum size

* Update tui/src/state.rs

Co-authored-by: Adam Perkowski <adas1per@protonmail.com>

---------

Co-authored-by: Chris Titus <contact@christitus.com>
Co-authored-by: Adam Perkowski <adas1per@protonmail.com>
This commit is contained in:
JEEVITHA KANNAN K S 2024-09-19 00:19:33 +05:30 committed by GitHub
parent 54786a719e
commit fde25afcbd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -33,6 +33,7 @@ pub struct AppState {
/// widget /// widget
selection: ListState, selection: ListState,
filter: Filter, filter: Filter,
drawable: bool,
} }
pub enum Focus { pub enum Focus {
@ -60,11 +61,55 @@ impl AppState {
visit_stack: vec![root_id], visit_stack: vec![root_id],
selection: ListState::default().with_selected(Some(0)), selection: ListState::default().with_selected(Some(0)),
filter: Filter::new(), filter: Filter::new(),
drawable: false,
}; };
state.update_items(); state.update_items();
state state
} }
pub fn draw(&mut self, frame: &mut Frame) { pub fn draw(&mut self, frame: &mut Frame) {
let terminal_size = frame.area();
let min_width = 77; // Minimum width threshold
let min_height = 19; // Minimum height threshold
if terminal_size.width < min_width || terminal_size.height < min_height {
let size_warning_message = format!(
"Terminal size too small:\nWidth = {} Height = {}\n\nMinimum size:\nWidth = {} Height = {}",
terminal_size.width,
terminal_size.height,
min_width,
min_height,
);
let warning_paragraph = Paragraph::new(size_warning_message.clone())
.alignment(Alignment::Center)
.style(Style::default().fg(ratatui::style::Color::Red).bold())
.wrap(ratatui::widgets::Wrap { trim: true });
// Get the maximum width and height of text lines
let text_lines: Vec<String> = size_warning_message
.lines()
.map(|line| line.to_string())
.collect();
let max_line_length = text_lines.iter().map(|line| line.len()).max().unwrap_or(0);
let num_lines = text_lines.len();
// Calculate the centered area
let centered_area = ratatui::layout::Rect {
x: terminal_size.x + (terminal_size.width - max_line_length as u16) / 2,
y: terminal_size.y + (terminal_size.height - num_lines as u16) / 2,
width: max_line_length as u16,
height: num_lines as u16,
};
frame.render_widget(warning_paragraph, centered_area);
self.drawable = false;
} else {
self.drawable = true;
}
if !self.drawable {
return;
}
let label_block = let label_block =
Block::default() Block::default()
.borders(Borders::all()) .borders(Borders::all())
@ -187,6 +232,21 @@ impl AppState {
} }
pub fn handle_key(&mut self, key: &KeyEvent) -> bool { pub fn handle_key(&mut self, key: &KeyEvent) -> bool {
// This should be defined first to allow closing
// the application even when not drawable ( If terminal is small )
if matches!(self.focus, Focus::TabList | Focus::List) {
if key.code == KeyCode::Char('q')
|| key.code == KeyCode::Char('c') && key.modifiers.contains(KeyModifiers::CONTROL)
{
return false;
}
}
// If UI is not drawable returning true will mark as the key handled
if !self.drawable {
return true;
}
match &mut self.focus { match &mut self.focus {
Focus::FloatingWindow(command) => { Focus::FloatingWindow(command) => {
if command.handle_key_event(key) { if command.handle_key_event(key) {