Skip to main content

csi_webclient/ui/
dashboard.rs

1use crate::state::DeviceState;
2
3/// Render the dashboard view for one device.
4pub fn render(ui: &mut egui::Ui, device: &DeviceState) {
5    ui.add(
6        egui::Label::new(format!("Dashboard — {}", device.id))
7            .wrap(),
8    );
9    ui.add_space(10.0);
10
11    ui.strong("Connection");
12    ui.add_space(4.0);
13    stat_row(ui, "Serial", format_tristate(device.serial_connected, "connected", "disconnected"));
14    if let Some(mac) = &device.mac {
15        stat_row(ui, "MAC", mac.clone());
16    }
17    stat_row(ui, "Port", device.port_path.clone().unwrap_or_else(|| "?".to_owned()));
18    if let Some(baud) = device.baud_rate {
19        stat_row(ui, "Baud", baud.to_string());
20    }
21    stat_row(
22        ui,
23        "Firmware",
24        format_tristate(device.firmware_verified, "verified", "unverified"),
25    );
26    stat_row(
27        ui,
28        "Collection",
29        format_tristate(device.collection_running, "running", "idle"),
30    );
31
32    if let Some(info) = &device.latest_info {
33        ui.add_space(10.0);
34        ui.strong("Firmware info");
35        ui.add_space(4.0);
36        stat_row(ui, "Name", info.name.clone().unwrap_or_default());
37        stat_row(ui, "Version", info.version.clone().unwrap_or_default());
38        stat_row(ui, "Chip", info.chip.clone().unwrap_or_default());
39        stat_row(
40            ui,
41            "Protocol",
42            info.protocol
43                .map(|v| v.to_string())
44                .unwrap_or_else(|| "?".to_owned()),
45        );
46        stat_row(ui, "Features", info.features.join(", "));
47    }
48
49    ui.add_space(10.0);
50    ui.strong("Session");
51    ui.add_space(4.0);
52    stat_row(
53        ui,
54        "Collection role",
55        device.forms.collection_mode.as_api_value().to_owned(),
56    );
57    stat_row(
58        ui,
59        "Output mode",
60        device.forms.output_mode.as_api_value().to_owned(),
61    );
62
63    ui.add_space(10.0);
64    ui.strong("Stream");
65    ui.add_space(4.0);
66    stat_row(
67        ui,
68        "WebSocket",
69        if device.ws_connected {
70            "connected".to_owned()
71        } else {
72            "disconnected".to_owned()
73        },
74    );
75    stat_row(ui, "Frames", device.frames_received.to_string());
76    stat_row(ui, "Bytes", device.bytes_received.to_string());
77}
78
79fn stat_row(ui: &mut egui::Ui, label: &str, value: String) {
80    ui.horizontal(|ui| {
81        ui.label(format!("{label}:"));
82        ui.add_space(8.0);
83        ui.add(egui::Label::new(value).wrap());
84    });
85    ui.add_space(2.0);
86}
87
88fn format_tristate(value: Option<bool>, true_label: &str, false_label: &str) -> String {
89    match value {
90        Some(true) => true_label.to_owned(),
91        Some(false) => false_label.to_owned(),
92        None => "?".to_owned(),
93    }
94}