diff --git a/crates/notedeck_columns/src/ui/relay_debug.rs b/crates/notedeck_columns/src/ui/relay_debug.rs new file mode 100644 index 00000000..22ec6a5c --- /dev/null +++ b/crates/notedeck_columns/src/ui/relay_debug.rs @@ -0,0 +1,164 @@ +use egui::ScrollArea; +use enostr::{RelayLogEvent, SubsDebug}; + +pub struct RelayDebugView<'a> { + debug: &'a mut SubsDebug, +} + +impl<'a> RelayDebugView<'a> { + pub fn new(debug: &'a mut SubsDebug) -> Self { + Self { debug } + } +} + +impl<'a> RelayDebugView<'a> { + pub fn ui(&mut self, ui: &mut egui::Ui) { + ScrollArea::vertical() + .id_salt(ui.id().with("relays_debug")) + .max_height(ui.max_rect().height() / 2.0) + .show(ui, |ui| { + ui.label("Active Relays:"); + for (relay_str, data) in self.debug.get_data() { + egui::CollapsingHeader::new(format!( + "{} {} {}", + relay_str, + format_total(&data.count), + format_sec(&data.count) + )) + .default_open(true) + .show(ui, |ui| { + ui.horizontal_wrapped(|ui| { + for (i, sub_data) in data.sub_data.values().enumerate() { + ui.label(format!( + "Filter {} ({})", + i + 1, + format_sec(&sub_data.count) + )) + .on_hover_cursor(egui::CursorIcon::Help) + .on_hover_text(sub_data.filter.to_string()); + } + }) + }); + } + }); + + ui.separator(); + egui::ComboBox::from_label("Show events from relay") + .selected_text( + self.debug + .relay_events_selection + .as_ref() + .map_or(String::new(), |s| s.clone()), + ) + .show_ui(ui, |ui| { + let mut make_selection = None; + for relay in self.debug.get_data().keys() { + if ui + .selectable_label( + if let Some(s) = &self.debug.relay_events_selection { + *s == *relay + } else { + false + }, + relay, + ) + .clicked() + { + make_selection = Some(relay.clone()); + } + } + if make_selection.is_some() { + self.debug.relay_events_selection = make_selection + } + }); + let show_relay_evs = + |ui: &mut egui::Ui, relay: Option, events: Vec| { + for ev in events { + ui.horizontal_wrapped(|ui| { + if let Some(r) = &relay { + ui.label("relay").on_hover_text(r.clone()); + } + match ev { + RelayLogEvent::Send(client_message) => { + ui.label("SEND: "); + let msg = &match client_message { + enostr::ClientMessage::Event { .. } => "Event", + enostr::ClientMessage::Req { .. } => "Req", + enostr::ClientMessage::Close { .. } => "Close", + enostr::ClientMessage::Raw(_) => "Raw", + }; + + if let Ok(json) = client_message.to_json() { + ui.label(*msg).on_hover_text(json) + } else { + ui.label(*msg) + } + } + RelayLogEvent::Recieve(e) => { + ui.label("RECIEVE: "); + match e { + enostr::OwnedRelayEvent::Opened => ui.label("Opened"), + enostr::OwnedRelayEvent::Closed => ui.label("Closed"), + enostr::OwnedRelayEvent::Other(s) => { + ui.label("Other").on_hover_text(s) + } + enostr::OwnedRelayEvent::Error(s) => { + ui.label("Error").on_hover_text(s) + } + enostr::OwnedRelayEvent::Message(s) => { + ui.label("Message").on_hover_text(s) + } + } + } + } + }); + } + }; + + ScrollArea::vertical() + .id_salt(ui.id().with("events")) + .show(ui, |ui| { + if let Some(relay) = &self.debug.relay_events_selection { + if let Some(data) = self.debug.get_data().get(relay) { + show_relay_evs(ui, None, data.events.clone()); + } + } else { + for (relay, data) in self.debug.get_data() { + show_relay_evs(ui, Some(relay.clone()), data.events.clone()); + } + } + }); + + self.debug.try_increment_stats(); + } +} + +fn format_sec(c: &enostr::TransferStats) -> String { + format!( + "⬇{} ⬆️{}", + byte_to_string(c.down_sec_prior), + byte_to_string(c.up_sec_prior) + ) +} + +fn format_total(c: &enostr::TransferStats) -> String { + format!( + "total: ⬇{} ⬆️{}", + byte_to_string(c.down_total), + byte_to_string(c.up_total) + ) +} + +const MB: usize = 1_048_576; +const KB: usize = 1024; +fn byte_to_string(b: usize) -> String { + if b >= MB { + let mbs = b as f32 / MB as f32; + format!("{:.2} MB", mbs) + } else if b >= KB { + let kbs = b as f32 / KB as f32; + format!("{:.2} KB", kbs) + } else { + format!("{} B", b) + } +}