From 810e212b4b255914cfa73e85b52ec23db281c0e3 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 29 Oct 2026 23:06:22 +0100 Subject: v3.1.0: warn on shrink, but let a live round finish --- src/bin/client/repl.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) (limited to 'src/bin') diff --git a/src/bin/client/repl.rs b/src/bin/client/repl.rs index 2cf121d..bf02c8d 100644 --- a/src/bin/client/repl.rs +++ b/src/bin/client/repl.rs @@ -17,7 +17,7 @@ use zagan_bet::client::core::{ClientCore, Effect, InteractiveCommand, Key}; use zagan_bet::client::database; use zagan_bet::client::ui::{ display_width, format_pong, host_lines, input_cursor_column, lines_to_move_up, - visual_line_count, + terminal_size_warning, visual_line_count, MIN_COLUMNS, MIN_ROWS, }; use zagan_bet::protocol::io_failure_message; use zagan_bet::roulette::{WHEEL, color as roulette_color}; @@ -36,6 +36,10 @@ pub struct ClientState { /// Text last drawn after the `> ` prompt, used to keep the command echo /// in the transcript before printing command output. prompt_text: String, + /// Last known terminal size, updated from resize events. + terminal_size: (u16, u16), + /// Size we already warned about, so a resize does not spam the transcript. + size_warned: Option<(u16, u16)>, } impl ClientState { @@ -60,6 +64,8 @@ impl ClientState { cleanup_done: Arc::new(Mutex::new(false)), game_lines: 0, prompt_text: String::new(), + terminal_size: crossterm::terminal::size().unwrap_or((MIN_COLUMNS, MIN_ROWS)), + size_warned: None, } } @@ -114,7 +120,15 @@ impl ClientState { } } } - Event::Resize(_, _) => self.apply_prompt(), + Event::Resize(columns, rows) => { + self.terminal_size = (columns, rows); + if self.core.is_in_game() { + let effects = self.core.refresh_board(); + self.apply_effects(effects); + } else { + self.apply_prompt(); + } + } _ => {} } } @@ -130,6 +144,10 @@ impl ClientState { } } + if !quit { + quit = self.warn_about_size(); + } + if quit { break; } @@ -292,7 +310,42 @@ impl ClientState { self.prompt_text.clear(); } + /// Warn once per size when the terminal is too small and no round is live. + /// Inside a game the warning is appended to the board instead, and during a + /// live round it is suppressed until the round settles. + fn warn_about_size(&mut self) -> bool { + let size = self.terminal_size; + let Some(message) = terminal_size_warning(size.0, size.1) else { + self.size_warned = None; + return false; + }; + if self.core.is_in_game() || self.size_warned == Some(size) { + return false; + } + self.size_warned = Some(size); + self.apply_effects(vec![Effect::Print(vec![message])]); + false + } + fn draw_region(&mut self, lines: &[String]) { + let warning = if self.core.is_live_game() { + None + } else { + terminal_size_warning(self.terminal_size.0, self.terminal_size.1) + }; + let owned; + let lines: &[String] = match warning { + Some(warning) => { + owned = { + let mut lines = lines.to_vec(); + lines.push(warning); + lines + }; + &owned + } + None => lines, + }; + if self.game_lines == 0 { self.commit_prompt_line(); } else { @@ -308,6 +361,8 @@ impl ClientState { .map(|line| { if line.starts_with("===") { line.as_str().bold().cyan().to_string() + } else if line.starts_with("WARNING:") { + line.as_str().bold().red().to_string() } else if roulette { if line.starts_with("Won ") { line.as_str().bold().green().to_string() -- cgit v1.2.3