Restore TUI key hints after updates
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user