120 lines
3.3 KiB
Rust
120 lines
3.3 KiB
Rust
use super::*;
|
|
|
|
pub(super) fn build(
|
|
p: &mut Painter,
|
|
state: &mut DeveloperToolsState,
|
|
records: &[Exchange],
|
|
viewport: Rect,
|
|
) {
|
|
let x = viewport.x;
|
|
let w = viewport.width;
|
|
let bottom = viewport.height - 22.0;
|
|
|
|
p.fill(Rect::new(x, 32.0, w, 30.0), BAR);
|
|
p.enabled_button(
|
|
Rect::new(x + 3.0, 32.0, 62.0, 29.0),
|
|
"Clear",
|
|
Action::ClearNetwork,
|
|
records.iter().any(|r| r.id > state.network_after),
|
|
);
|
|
let filter_area = Rect::new(x + 72.0, 35.0, (w - 85.0).max(100.0), 24.0);
|
|
p.ui.text_field(
|
|
filter_area,
|
|
Action::Focus(Focus::Filter),
|
|
state.focus == Some(Focus::Filter),
|
|
);
|
|
p.label(
|
|
filter_area.x + 7.0,
|
|
filter_area.y + 3.0,
|
|
&format!(
|
|
"Filter: {}{}",
|
|
state.filter,
|
|
if state.focus == Some(Focus::Filter) {
|
|
"│"
|
|
} else {
|
|
""
|
|
}
|
|
),
|
|
MUTED,
|
|
false,
|
|
);
|
|
|
|
p.label(
|
|
x + 10.0,
|
|
69.0,
|
|
"METHOD STATUS TIME PATH",
|
|
MUTED,
|
|
true,
|
|
);
|
|
let divider = 92.0 + (bottom - 92.0) * state.network_fraction;
|
|
let filter = state.filter.to_lowercase();
|
|
let visible = records
|
|
.iter()
|
|
.filter(|r| r.id > state.network_after)
|
|
.filter(|r| {
|
|
format!(
|
|
"{} {} {}",
|
|
r.method,
|
|
r.path,
|
|
r.status.map_or("pending".into(), |s| s.to_string())
|
|
)
|
|
.to_lowercase()
|
|
.contains(&filter)
|
|
})
|
|
.collect::<Vec<_>>();
|
|
let mut lines = Vec::new();
|
|
for r in &visible {
|
|
let mut l = Line::new(
|
|
format!(
|
|
"{:<7} {:<6} {:>5} ms {}",
|
|
r.method,
|
|
r.status.map_or("…".into(), |s| s.to_string()),
|
|
r.elapsed_ms,
|
|
r.path
|
|
),
|
|
if r.status.is_some_and(|s| s >= 400) {
|
|
ERROR
|
|
} else {
|
|
TEXT
|
|
},
|
|
);
|
|
l.selected = state.selected_request == Some(r.id);
|
|
l.action = Some(Action::Request(r.id));
|
|
lines.push(l);
|
|
}
|
|
if lines.is_empty() {
|
|
lines.push(Line::new(
|
|
"No matching requests. Listening to Tessera's local API.",
|
|
MUTED,
|
|
));
|
|
}
|
|
p.lines(
|
|
Rect::new(x + 1.0, 92.0, w - 2.0, divider - 92.0),
|
|
Region::Requests,
|
|
&lines,
|
|
state,
|
|
false,
|
|
);
|
|
p.split(Rect::new(x + 1.0, divider, w - 2.0, 1.0), Split::Network);
|
|
let selected = records
|
|
.iter()
|
|
.find(|r| Some(r.id) == state.selected_request);
|
|
let mut details = Vec::new();
|
|
if let Some(r) = selected {
|
|
request_details(&mut details, r);
|
|
} else {
|
|
multiline(
|
|
&mut details,
|
|
"Select a request to inspect headers and bodies.\n\nCapture scope: 127.0.0.1:4737 in this Tessera process.\n80 most recent requests; body previews up to 32 KiB.\nOnly Content-Type and Content-Length request headers are recorded.\nExternal browser / OS traffic is not captured.",
|
|
MUTED,
|
|
);
|
|
}
|
|
p.lines(
|
|
Rect::new(x + 1.0, divider + 5.0, w - 2.0, bottom - divider - 5.0),
|
|
Region::Details,
|
|
&details,
|
|
state,
|
|
false,
|
|
);
|
|
}
|