Add resize handling and non-blocking input loop

Use `recv_timeout` to prevent UI blocking, forward terminal resize
events,
adjust keybinding width calculation, and replace percentage layout with
fill/length for the main menu.
This commit is contained in:
2026-03-12 16:23:54 +01:00
parent 71b9d44a77
commit c3886ca0cf
3 changed files with 19 additions and 8 deletions
+17 -5
View File
@@ -12,11 +12,13 @@ use ratatui::{
}; };
use std::{ use std::{
io::Result, io::Result,
sync::mpsc::{self, Receiver}, sync::mpsc::{self, Receiver, RecvTimeoutError},
time::Duration,
}; };
pub enum Event { pub enum Event {
Input(KeyEvent), Input(KeyEvent),
Resize(u16, u16),
} }
pub struct App { pub struct App {
@@ -80,12 +82,16 @@ impl App {
while !self.exit { while !self.exit {
terminal.draw(|frame: &mut Frame<'_>| self.draw(frame))?; terminal.draw(|frame: &mut Frame<'_>| self.draw(frame))?;
let event: Event = match rx.recv() { let event = match rx.recv_timeout(Duration::from_millis(100)) {
Ok(ev) => ev, Ok(ev) => ev,
Err(RecvTimeoutError::Timeout) => {
continue;
}
Err(_) => break, Err(_) => break,
}; };
match event { match event {
Event::Input(key_event) => self.handle_key_event(key_event)?, Event::Input(key_event) => self.handle_key_event(key_event)?,
Event::Resize(_, _) => {}
} }
} }
@@ -117,13 +123,19 @@ impl App {
pub fn handle_input_events(tx: mpsc::Sender<Event>) { pub fn handle_input_events(tx: mpsc::Sender<Event>) {
loop { loop {
match event::read() { match event::read() {
Ok(ev) => { Ok(ev) => match ev {
if let event::Event::Key(key_event) = ev { event::Event::Key(key_event) => {
if tx.send(Event::Input(key_event)).is_err() { if tx.send(Event::Input(key_event)).is_err() {
break; break;
} }
} }
} event::Event::Resize(cols, rows) => {
if tx.send(Event::Resize(cols, rows)).is_err() {
break;
}
}
_ => {}
},
Err(_) => { Err(_) => {
continue; continue;
} }
+1 -1
View File
@@ -30,7 +30,7 @@ impl Widget for KeybindingsWidget {
block.render(area, buf); block.render(area, buf);
let base: u16 = if count == 0 { 0 } else { 10 }; let base: u16 = if count == 0 { 0 } else { 100u16 / count };
let constraints: Vec<Constraint> = vec![Constraint::Percentage(base); count as usize]; let constraints: Vec<Constraint> = vec![Constraint::Percentage(base); count as usize];
+1 -2
View File
@@ -27,8 +27,7 @@ fn view_options() -> Vec<(usize, String)> {
} }
pub fn main_menu_widget(app: &App, area: Rect, buf: &mut Buffer) { pub fn main_menu_widget(app: &App, area: Rect, buf: &mut Buffer) {
let vertical_layout: Layout = let vertical_layout: Layout = Layout::vertical([Constraint::Fill(1), Constraint::Length(4)]);
Layout::vertical([Constraint::Percentage(92), Constraint::Percentage(8)]);
let [main_menu_area, keybindings_area] = vertical_layout.areas(area); let [main_menu_area, keybindings_area] = vertical_layout.areas(area);