Merge branch 'feat/tui-rework'
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 32s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 31s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 10s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m14s
Rust CI / cargo doc (push) Successful in 27s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 28s
Supply chain / cargo-deny bans licenses sources (push) Successful in 8s
Supply chain / cargo-deny advisories (push) Successful in 9s
Supply chain / actionlint (push) Successful in 3s
Netem Interop / netem interop (push) Successful in 1m7s

This commit is contained in:
Nils Andreas Svee committed 2026-10-05 19:40:44 +07:00
commit 1f7df1ebc9
3 files changed
+669 -858

No files matched your search

+14 -54
View File
@@ -17,11 +17,15 @@ use crate::{
},
},
};
use crossterm::event::{self, Event, KeyCode, KeyEventKind, KeyModifiers};
use crossterm::{
event::{self, Event, KeyCode, KeyEventKind, KeyModifiers},
terminal,
};
use irtt_client::managed::{
BlockingManagedClient, ManagedEndReason, ManagedEvent, ManagedEventSubscription,
ManagedEventTryRecvError, TargetInstance,
};
use ratatui::layout::Rect;
const RENDER_INTERVAL: Duration = Duration::from_millis(250);
const TUI_WAIT_SLICE: Duration = Duration::from_millis(20);
@@ -218,8 +222,13 @@ fn handle_input(state: &mut TuiState, shutdown_requested: &AtomicBool) -> io::Re
if !event::poll(Duration::ZERO)? {
break;
}
let Event::Key(key) = event::read()? else {
let key = match event::read()? {
Event::Key(key) => key,
Event::Resize(_, _) => {
force_render = true;
continue;
}
_ => continue,
};
if key.kind == KeyEventKind::Release {
continue;
@@ -234,59 +243,10 @@ fn handle_input(state: &mut TuiState, shutdown_requested: &AtomicBool) -> io::Re
force_render = true;
break;
}
KeyCode::Char('r') => {
state.clear_visible_history();
force_render = true;
_ => {
let (width, height) = terminal::size()?;
force_render |= state.handle_key(key.code, Rect::new(0, 0, width, height));
}
KeyCode::Char('p') => {
state.toggle_pause();
force_render = true;
}
KeyCode::Char('g') => {
state.toggle_view();
force_render = true;
}
KeyCode::Char('m') => {
state.cycle_graph_metric();
force_render = true;
}
KeyCode::Left => {
state.pan_graph_left();
force_render = true;
}
KeyCode::Right => {
state.pan_graph_right();
force_render = true;
}
KeyCode::PageUp => {
state.pan_graph_page_left();
force_render = true;
}
KeyCode::PageDown => {
state.pan_graph_page_right();
force_render = true;
}
KeyCode::Home => {
state.jump_graph_oldest();
force_render = true;
}
KeyCode::End => {
state.jump_graph_live();
force_render = true;
}
KeyCode::Char('+') | KeyCode::Char('=') => {
state.zoom_graph_in();
force_render = true;
}
KeyCode::Char('-') => {
state.zoom_graph_out();
force_render = true;
}
KeyCode::Char('0') => {
state.reset_graph_window();
force_render = true;
}
_ => {}
}
}
Ok(force_render)
File diff suppressed because it is too large. Load diff
+55 -11
View File
@@ -31,21 +31,65 @@ a finite run:
irtt-tui <server> --duration 30s
```
## DASHBOARD
One dashboard is used for every target count and terminal size. It shows:
- Run status, elapsed time, and finite duration or continuous mode.
- The selected target's label and remote address, plus latest signed
client-to-server and server-to-client delays (`-` means unavailable).
- Target rows with latest effective RTT, cumulative loss percentage, jitter
(standard deviation of round-trip IPDV), and age of the last primary reply.
- A graph overlaying all targets, with matching target colors and a visible
live/history indicator and window size.
An active session with no primary replies shows `waiting`. Reply age makes a
stale RTT distinguishable from a fresh measurement. Loss follows the shared
statistics collector: outstanding sends can temporarily contribute to the
cumulative loss estimate. Jitter is `-` until an IPDV pair is available.
`Tab` / `Shift-Tab` selects a target, bringing its row into view when necessary.
Up to six target rows are shown; smaller terminals show fewer. Selecting a target
changes the identification, one-way summary and details; the graph continues to
compare every target.
`d` opens a details sheet in the graph's space. It contains the selected target's
session and negotiation, packet counters, progress, latest timing sample, full
timing statistics, warnings, and recent events from all targets. Scroll it with
the arrows or page keys. Long lines and timing columns can be read with horizontal
scrolling, including full labels and remote addresses that do not fit in the
header. `d` or `Esc` returns to the graph, preserving its metric and viewport.
The former large/compact Dashboard screens have been replaced by this sheet;
`g` remains an alias for `d`.
The minimum terminal size is 56 columns by 18 rows. Below that size the UI asks
for a resize and continues acquiring measurements. Resize and important status
redraws still work while the display is paused.
## CONTROLS
| Key | Action |
| --- | --- |
| `q`, `Ctrl-C` | Quit |
| `p` | Toggle display pause (probing continues; only redraws stop) |
| `g` | Toggle Graph / Dashboard view |
| `m` | Cycle graph metric |
| `r` | Clear visible graph history |
| `←` / `→` | Pan graph |
| `PageUp` / `PageDown` | Page-pan graph |
| `Home` / `End` | Jump to oldest / jump to live |
| `+` / `=` | Zoom graph in |
| `-` | Zoom graph out |
| `0` | Reset graph window and zoom |
| `p` | Toggle display pause (probing and acquisition continue) |
| `Tab` / `Shift-Tab` | Select next / previous target |
| `d`, `g` | Toggle target details |
| `Esc` | Close target details |
| `r` | Clear graph history for all targets; keep latest samples and statistics |
| `m` | Cycle graph metric (graph visible) |
| `←` / `→` | Pan graph; scroll columns in details |
| `↑` / `↓` | Scroll details |
| `PageUp` / `PageDown` | Page-pan graph; page-scroll details |
| `Home` / `End` | Oldest / live graph; top / bottom of details |
| `+` / `=` | Zoom graph in (graph visible) |
| `-` | Zoom graph out (graph visible) |
| `0` | Reset graph window and zoom, keeping live/history position (graph visible) |
The six graph metrics are effective RTT, raw RTT, adjusted RTT,
client-to-server delay, server-to-client delay, and server processing time.
Signed effective/adjusted RTT and one-way values are preserved. Graph windows
range from 5 seconds to one hour and default to one minute. The footer shows
controls appropriate to the currently open graph or details sheet.
## RETAINED HISTORY
@@ -55,7 +99,7 @@ retention described in `irtt-client(1)`:
- Up to 100,000 graph samples per target.
- Up to 80 recent status/log messages.
`r` clears the currently visible graph history and returns the viewport to
`r` clears graph history for all targets and returns the viewport to
live; it does not change the 100,000-sample cap itself. These are
presentation bounds on top of the client's own statistics retention (see
`irtt-client(1)` MEASUREMENTS AND MEMORY) — a long continuous TUI session's