add refreshing/refreshsed indicator on tui status when refresh is requested
This commit is contained in:
parent
9139c36e09
commit
c11518d40f
1 changed files with 50 additions and 13 deletions
63
src/tui.zig
63
src/tui.zig
|
|
@ -484,6 +484,16 @@ pub const App = struct {
|
|||
status_msg: [256]u8 = undefined,
|
||||
status_len: usize = 0,
|
||||
|
||||
/// True between the refresh keypress and the deferred refresh
|
||||
/// work completing. While set, the status bar shows the
|
||||
/// in-progress indicator; the poll tick is armed so the
|
||||
/// (blocking) refresh runs one frame later, letting the
|
||||
/// indicator paint first (vxfw draws after the handler returns).
|
||||
refresh_pending: bool = false,
|
||||
/// Wall-clock seconds when the last manual refresh completed
|
||||
/// (0 = never). Drives the "refreshed Xs ago" status readout.
|
||||
last_refresh_s: i64 = 0,
|
||||
|
||||
// Input mode state
|
||||
mode: InputMode = .normal,
|
||||
// SAFETY: paired with `input_len`; only the prefix
|
||||
|
|
@ -536,7 +546,7 @@ pub const App = struct {
|
|||
// picked up automatically because dispatch targets the
|
||||
// active tab. 100ms cadence — fast enough to feel
|
||||
// responsive, slow enough to be invisible in CPU terms.
|
||||
defer if (!self.poll_tick_armed and self.dispatchBool("wantsPollTick", .{})) {
|
||||
defer if (!self.poll_tick_armed and (self.refresh_pending or self.dispatchBool("wantsPollTick", .{}))) {
|
||||
if (ctx.tick(100, self.widget())) {
|
||||
self.poll_tick_armed = true;
|
||||
} else |err| {
|
||||
|
|
@ -583,12 +593,21 @@ pub const App = struct {
|
|||
self.loadTabData();
|
||||
},
|
||||
.tick => {
|
||||
// Our scheduled poll timer fired. Mark it
|
||||
// un-armed (the defer above re-arms if the active
|
||||
// tab still wants polling) and request a redraw
|
||||
// so the draw pass runs the tab's tick hook.
|
||||
// Our scheduled timer fired. Mark it un-armed (the
|
||||
// defer above re-arms if there's more work).
|
||||
self.poll_tick_armed = false;
|
||||
if (self.dispatchBool("wantsPollTick", .{})) {
|
||||
if (self.refresh_pending) {
|
||||
// Phase 2 of refresh: the indicator painted last
|
||||
// frame; now run the (blocking) refresh.
|
||||
self.refresh_pending = false;
|
||||
self.refreshCurrentTab();
|
||||
// wall-clock required: timestamp the completed
|
||||
// refresh for the "refreshed Xs ago" readout.
|
||||
self.last_refresh_s = std.Io.Timestamp.now(self.io, .real).toSeconds();
|
||||
ctx.redraw = true;
|
||||
} else if (self.dispatchBool("wantsPollTick", .{})) {
|
||||
// Poll-driven redraw so the draw pass runs the
|
||||
// active tab's tick hook.
|
||||
ctx.redraw = true;
|
||||
}
|
||||
},
|
||||
|
|
@ -1004,7 +1023,11 @@ pub const App = struct {
|
|||
return ctx.consumeAndRedraw();
|
||||
},
|
||||
.refresh => {
|
||||
self.refreshCurrentTab();
|
||||
// Two-phase so the "Refreshing..." indicator paints
|
||||
// before the (blocking) refresh runs. Flag it and
|
||||
// redraw now; the armed poll tick runs the actual
|
||||
// refresh one frame later (see the `.tick` branch).
|
||||
self.refresh_pending = true;
|
||||
return ctx.consumeAndRedraw();
|
||||
},
|
||||
.prev_tab => {
|
||||
|
|
@ -1299,15 +1322,29 @@ pub const App = struct {
|
|||
};
|
||||
}
|
||||
|
||||
/// Returns the current status message. When no message has been
|
||||
/// set, builds a dynamic default hint composed from a small set
|
||||
/// of always-shown global keys plus the active tab's
|
||||
/// `status_hints`. Allocated in `arena` for the dynamic default;
|
||||
/// the user-set buffer is returned by reference.
|
||||
/// Returns the current status message. While a refresh is in
|
||||
/// flight, shows the in-progress indicator. Otherwise: a
|
||||
/// user-set message if present, else a dynamic default hint
|
||||
/// (global keys + the active tab's `status_hints`), prefixed
|
||||
/// with a "refreshed Xs ago" readout once a refresh has run.
|
||||
/// Allocated in `arena` for the dynamic forms; the user-set
|
||||
/// buffer is returned by reference.
|
||||
fn getStatus(self: *App, arena: std.mem.Allocator) []const u8 {
|
||||
if (self.refresh_pending) return "Refreshing...";
|
||||
if (self.status_len > 0) return self.status_msg[0..self.status_len];
|
||||
return self.buildDefaultStatusHint(arena) catch
|
||||
const hint = self.buildDefaultStatusHint(arena) catch
|
||||
"h/l tabs | j/k select | / symbol | ? help";
|
||||
if (self.last_refresh_s > 0) {
|
||||
// wall-clock required: per-frame "now" for the relative
|
||||
// "refreshed Xs ago" readout.
|
||||
const now_s = std.Io.Timestamp.now(self.io, .real).toSeconds();
|
||||
var ago_buf: [24]u8 = undefined;
|
||||
const ago = fmt.fmtTimeAgo(&ago_buf, self.last_refresh_s, now_s);
|
||||
if (ago.len > 0) {
|
||||
return std.fmt.allocPrint(arena, "refreshed {s} | {s}", .{ ago, hint }) catch hint;
|
||||
}
|
||||
}
|
||||
return hint;
|
||||
}
|
||||
|
||||
/// Build the dynamic default status hint: a small set of always-
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue