Restore TUI key hints after updates

This commit is contained in:
Georg Bauer
2026-08-03 22:24:30 +02:00
parent c7c44676fb
commit 1a43bf1ba8
2 changed files with 27 additions and 5 deletions

View File

@@ -12,6 +12,7 @@ use gotcha_gitea::{
use crate::editor::{Editor, EditorAction, EditorEvent};
const ALL_BRANCHES: &str = "All branches";
const UPDATE_STATUS_DURATION: Duration = Duration::from_secs(2);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Tab {
@@ -162,6 +163,7 @@ pub struct App {
pub editor: Option<Editor>,
pub confirm: Option<(String, ConfirmAction)>,
pub status: String,
status_deadline: Option<Instant>,
pub should_quit: bool,
pub last_input: Instant,
pub last_reload: Instant,
@@ -218,6 +220,7 @@ impl App {
editor: None,
confirm: None,
status: "Loading…".into(),
status_deadline: None,
should_quit: false,
last_input: Instant::now(),
last_reload: Instant::now(),
@@ -256,6 +259,7 @@ impl App {
pub async fn handle_key(&mut self, key: KeyEvent) {
self.last_input = Instant::now();
self.status_deadline = None;
if let Some(editor) = &mut self.editor {
match editor.handle_key(key) {
EditorEvent::Submit => self.submit_editor().await,
@@ -328,6 +332,7 @@ impl App {
pub async fn handle_mouse(&mut self, mouse: MouseEvent) {
self.last_input = Instant::now();
self.status_deadline = None;
if self.editor.is_some() || self.confirm.is_some() {
return;
}
@@ -396,6 +401,7 @@ impl App {
let page = self.screen.page;
let selected_key = self.screen.selected_item().map(|item| item.key.clone());
self.status = "Loading…".into();
self.status_deadline = None;
match self.load_screen(kind, page).await {
Ok(mut screen) => {
if let Some(key) = selected_key
@@ -405,12 +411,21 @@ impl App {
}
self.screen = screen;
self.status = format!("Updated {}", clock());
self.status_deadline = Some(Instant::now() + UPDATE_STATUS_DURATION);
}
Err(error) => self.status = error,
}
self.last_reload = Instant::now();
}
pub fn visible_status(&self) -> Option<&str> {
(!self.status.is_empty()
&& self
.status_deadline
.is_none_or(|deadline| Instant::now() < deadline))
.then_some(self.status.as_str())
}
async fn switch_tab(&mut self, tab: Tab) {
self.tab = tab;
self.history.clear();
@@ -1898,6 +1913,13 @@ mod tests {
#[tokio::test]
async fn auto_reload_waits_for_idle_overview_without_an_editor() {
let mut app = App::new(Config::default(), None).await.unwrap();
assert!(app.visible_status().unwrap().starts_with("Updated "));
app.status_deadline = Some(Instant::now() - Duration::from_secs(1));
assert_eq!(app.visible_status(), None);
app.status = "Network unavailable".into();
app.status_deadline = None;
assert_eq!(app.visible_status(), Some("Network unavailable"));
app.last_reload = Instant::now() - Duration::from_secs(6);
app.last_input = Instant::now() - Duration::from_secs(6);
assert!(app.should_auto_reload());

View File

@@ -187,15 +187,15 @@ fn draw_detail(frame: &mut Frame<'_>, app: &App, area: Rect) {
}
fn draw_footer(frame: &mut Frame<'_>, app: &App, area: Rect) {
let status = if app.status.is_empty() {
let status = if let Some(status) = app.visible_status() {
format!(
"Page {} · j/k move · Enter open · Backspace back · n/p pages · a/e/c/x/d actions · / filters · * favorite · r reload · q quit",
app.screen.page
"{} · Page {} · j/k move · Enter open · Backspace back · n/p pages · q quit",
status, app.screen.page
)
} else {
format!(
"{} · Page {} · j/k move · Enter open · Backspace back · n/p pages · q quit",
app.status, app.screen.page
"Page {} · j/k move · Enter open · Backspace back · n/p pages · a/e/c/x/d actions · / filters · * favorite · r reload · q quit",
app.screen.page
)
};
frame.render_widget(