diff --git a/local/recipes/system/redbear-power/source/src/app.rs b/local/recipes/system/redbear-power/source/src/app.rs index 224d8ebfc6..0cf8476581 100644 --- a/local/recipes/system/redbear-power/source/src/app.rs +++ b/local/recipes/system/redbear-power/source/src/app.rs @@ -831,7 +831,12 @@ impl App { self.pkg_thermal = PackageThermal::from_msr(pkg); // PROCHOT at the package level means the entire chip is // throttling. Surface that in the global header. - self.throttle = if pkg & THERM_STATUS_PROCHOT != 0 { + let prochot_now = pkg & THERM_STATUS_PROCHOT != 0; + let prochot_was = matches!(self.throttle, ThrottleMode::ForcedMin); + if prochot_now && !prochot_was { + self.flash_toast("PROCHOT triggered \u{2014} throttling active"); + } + self.throttle = if prochot_now { if matches!(self.throttle, ThrottleMode::Auto) { ThrottleMode::ForcedMin } else { diff --git a/local/recipes/system/redbear-power/source/src/main.rs b/local/recipes/system/redbear-power/source/src/main.rs index 945750be9d..5007a86cb5 100644 --- a/local/recipes/system/redbear-power/source/src/main.rs +++ b/local/recipes/system/redbear-power/source/src/main.rs @@ -78,7 +78,7 @@ use crate::render::{ GRAPH_HEIGHT, render_battery_panel, render_cpu_table, render_header, render_help, render_info_panel, render_keybar, render_motherboard_panel, render_network_panel, render_once, render_pid_detail, render_process_panel, render_prochot_alert, render_sensor_panel, - render_storage_panel, render_system_panel, render_tab_bar, snapshot, + render_storage_panel, render_system_panel, render_tab_bar, render_toast, snapshot, }; #[derive(Clone, Copy, Debug, PartialEq)] @@ -747,6 +747,9 @@ fn main() -> io::Result<()> { let area = Rect::new(0, full.y + full.height - 1, full.width, 1); f.render_widget(alert, area); } + if let Some(toast) = render_toast(&app) { + f.render_widget(toast, full); + } if show_help { let area = full.centered(Constraint::Percentage(70), Constraint::Percentage(80)); f.render_widget(Clear, area); diff --git a/local/recipes/system/redbear-power/source/src/render.rs b/local/recipes/system/redbear-power/source/src/render.rs index 357dee0349..0a8d5b9f47 100644 --- a/local/recipes/system/redbear-power/source/src/render.rs +++ b/local/recipes/system/redbear-power/source/src/render.rs @@ -145,6 +145,21 @@ pub fn render_prochot_alert(app: &App, frame: &Frame) -> Option(app: &'a App) -> Option> { + use crate::theme; + let msg = app.active_toast()?; + Some( + Paragraph::new(Line::from(vec![ + ratatui::text::Span::styled(" \u{25CF} ", theme::STATUS_OK), + ratatui::text::Span::styled(msg, theme::VALUE), + ])) + .style(theme::VALUE) + .block(Block::default().borders(Borders::ALL).title(" Notice ")) + .alignment(ratatui::layout::Alignment::Left), + ) +} + pub fn render_header<'a>(app: &'a App, focused: bool) -> Paragraph<'a> { let pkg_temp = app .cpus diff --git a/local/recipes/tui/tlc/source/src/filemanager/cmdline.rs b/local/recipes/tui/tlc/source/src/filemanager/cmdline.rs index 0860c397b9..8e34f15474 100644 --- a/local/recipes/tui/tlc/source/src/filemanager/cmdline.rs +++ b/local/recipes/tui/tlc/source/src/filemanager/cmdline.rs @@ -57,6 +57,10 @@ pub struct Cmdline { /// activated so completion resolves relative to the active /// panel's current directory. base_dir: Option, + /// Last-completion candidates, populated when the user presses + /// Tab and the prefix matches more than one entry. Used to + /// render the completion hint popup. + pub completions: Vec, } impl Default for Cmdline { @@ -77,6 +81,7 @@ impl Cmdline { message: None, width_pct: 1.0, base_dir: None, + completions: Vec::new(), } } @@ -104,6 +109,7 @@ impl Cmdline { pub fn complete(&mut self, base_dir: Option<&std::path::Path>) -> bool { let raw = self.input.value().to_string(); if raw.is_empty() { + self.completions.clear(); return false; } let (dir, prefix) = match base_dir { @@ -135,10 +141,14 @@ impl Cmdline { .filter_map(|e| e.file_name().into_string().ok()) .filter(|n| n.starts_with(&prefix)) .collect(); - if matches.is_empty() { +if matches.is_empty() { + self.completions.clear(); return false; } matches.sort(); + // Store all matches so the caller can render a hint + // popup with the candidate list. + self.completions = matches.clone(); let lcp: String = { let mut chars: Vec = matches[0].chars().collect(); 'outer: for (i, c) in chars.clone().into_iter().enumerate() { diff --git a/local/sources/userutils b/local/sources/userutils index 25ae058f11..395046ee3f 160000 --- a/local/sources/userutils +++ b/local/sources/userutils @@ -1 +1 @@ -Subproject commit 25ae058f11ffd8bf8c29abe41ccaedf6f13fe404 +Subproject commit 395046ee3f9a3aa4ac0e50012473c4a9fee2af5b