use std::time::Instant;
use ashlar_telemetry::{Telemetry, TurnGuard};
use egui::{Rect, RichText, Ui};
use crate::automation::{self, Details, Role};
pub struct FrameProbe;
impl FrameProbe {
pub fn logic(telemetry: &Telemetry, ctx: &egui::Context) -> TurnGuard {
let turn = telemetry.turn();
let (focused, active) = ctx.input(|i| (i.focused, !i.events.is_empty()));
telemetry.input(focused, active);
turn
}
pub fn ui<R>(telemetry: &Telemetry, counts: bool, pass: impl FnOnce() -> R) -> R {
let _turn = telemetry.turn();
let started = Instant::now();
let r = pass();
if counts {
telemetry.frame(started.elapsed());
}
r
}
}
#[derive(Clone, Copy, Debug)]
pub struct PrivacyText<'a> {
pub status: &'a str,
pub sent_heading: &'a str,
pub sent: &'a [&'a str],
pub never_sent: &'a str,
pub footer: &'a str,
}
pub fn privacy_section(ui: &mut Ui, id: &str, text: &PrivacyText<'_>) -> Vec<(String, Rect)> {
let mut out = Vec::new();
let mut line = |ui: &mut Ui, sub: String, s: &str, rich: RichText| {
let r = ui.add(egui::Label::new(rich).wrap());
automation::register_with(ui, &r, &sub, s, Role::Status, Details { value: Some(s), selected: None });
out.push((sub, r.rect));
};
line(ui, format!("{id}.status"), text.status, RichText::new(text.status));
ui.add_space(6.0);
ui.label(RichText::new(text.sent_heading).strong());
for (i, s) in text.sent.iter().enumerate() {
line(ui, format!("{id}.sent.{i}"), s, RichText::new(format!("• {s}")));
}
ui.add_space(6.0);
line(ui, format!("{id}.neverSent"), text.never_sent, RichText::new(text.never_sent));
if !text.footer.is_empty() {
ui.add_space(6.0);
let weak = RichText::new(text.footer).weak();
line(ui, format!("{id}.footer"), text.footer, weak);
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_section_shows_the_apps_words_with_ids() {
let ctx = egui::Context::default();
crate::automation::install(&ctx);
let text = PrivacyText {
status: "Reports go to t.example.com.",
sent_heading: "What is sent",
sent: &["Crashes", "Frame times"],
never_sent: "Never: files.",
footer: "Always on.",
};
let mut got = Vec::new();
let mut out = ctx.run_ui(egui::RawInput::default(), |ui| got = privacy_section(ui, "privacy", &text));
out.textures_delta.clear();
let ids: Vec<&str> = got.iter().map(|(i, _)| i.as_str()).collect();
assert_eq!(ids, ["privacy.status", "privacy.sent.0", "privacy.sent.1", "privacy.neverSent", "privacy.footer"]);
}
#[test]
fn the_probe_runs_with_a_disabled_client() {
let ctx = egui::Context::default();
let t = Telemetry::default();
let turn = FrameProbe::logic(&t, &ctx);
drop(turn);
assert_eq!(FrameProbe::ui(&t, true, || 3), 3);
}
}