mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-29 08:21:47 +00:00
relays/coverage.rs: - re-style coverage to spec
This commit is contained in:
parent
caec82c41c
commit
a35ca11794
@ -681,7 +681,6 @@ impl eframe::App for GossipUi {
|
||||
let (mut submenu, header_response) = self.get_openable_menu(ui, SubMenu::Relays, "Relays");
|
||||
submenu.show_body_indented(&header_response, ui, |ui| {
|
||||
self.add_menu_item_page(ui, Page::RelaysActivityMonitor, "Active Relays");
|
||||
self.add_menu_item_page(ui, Page::RelaysCoverage, "Coverage");
|
||||
self.add_menu_item_page(ui, Page::RelaysMine, "My Relays");
|
||||
self.add_menu_item_page(ui, Page::RelaysKnownNetwork, "Known Network");
|
||||
ui.vertical(|ui| {
|
||||
|
@ -1,65 +1,127 @@
|
||||
use egui_winit::egui::{Context, Ui, self, vec2, Response};
|
||||
use nostr_types::PublicKey;
|
||||
use egui_winit::egui::{Context, Ui, self, vec2, Response, RichText, Align, Id};
|
||||
use nostr_types::{PublicKey, RelayUrl};
|
||||
|
||||
use crate::{globals::GLOBALS, ui::{GossipUi, widgets, Page, SettingsTab}, comms::ToOverlordMessage};
|
||||
use crate::{globals::GLOBALS, ui::{GossipUi, widgets::{self, list_entry::{TEXT_TOP, TEXT_LEFT, self, draw_text_at, TEXT_RIGHT, allocate_text_at, draw_text_galley_at}}, Page, SettingsTab}, comms::ToOverlordMessage};
|
||||
|
||||
struct CoverageEntry<'a> {
|
||||
pk: &'a PublicKey,
|
||||
count: &'a usize,
|
||||
_count: &'a usize,
|
||||
relays: Vec<RelayUrl>,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl<'a> CoverageEntry<'a> {
|
||||
pub(super) fn new(pk: &'a PublicKey, count: &'a usize) -> Self {
|
||||
let name = GossipUi::display_name_from_pubkey_lookup(pk);
|
||||
pub(super) fn new(pk: &'a PublicKey, name: String, _count: &'a usize, relays: Vec<RelayUrl>) -> Self {
|
||||
Self {
|
||||
pk,
|
||||
count,
|
||||
_count,
|
||||
relays,
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn show(&self, ui: &mut Ui) -> Response {
|
||||
let (rect, _) = widgets::list_entry::allocate_space(ui, 45.0);
|
||||
fn make_id(&self, str: &str) -> Id {
|
||||
(self.pk.as_hex_string() + str).into()
|
||||
}
|
||||
|
||||
widgets::list_entry::paint_frame(ui, &rect);
|
||||
pub(super) fn show(&self, ui: &mut Ui, app: &mut GossipUi) -> Response {
|
||||
let available_width = ui.available_size_before_wrap().x;
|
||||
let (rect, response) = ui.allocate_exact_size(vec2(available_width, 80.0), egui::Sense::click());
|
||||
|
||||
let id = ui.auto_id_with(self.pk.as_hex_string());
|
||||
let pos = rect.min + vec2(widgets::list_entry::TEXT_LEFT, widgets::list_entry::TEXT_TOP);
|
||||
let (galley, response) = widgets::list_entry::allocate_text_at(
|
||||
let color = if response.hovered() {
|
||||
Some(ui.style().visuals.extreme_bg_color.linear_multiply(0.2))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
widgets::list_entry::paint_frame(ui, &rect, color);
|
||||
|
||||
// ---- title ----
|
||||
let pos = rect.min + vec2(TEXT_LEFT, TEXT_TOP);
|
||||
draw_text_at(
|
||||
ui,
|
||||
pos,
|
||||
self.name.clone().into(),
|
||||
egui::Align::LEFT,
|
||||
id);
|
||||
RichText::new(self.name.clone()).size(list_entry::TITLE_FONT_SIZE).into(),
|
||||
Align::LEFT,
|
||||
Some(app.settings.theme.accent_color()),
|
||||
None);
|
||||
|
||||
widgets::list_entry::draw_text_galley_at(
|
||||
// ---- pubkey ----
|
||||
// copy button
|
||||
{
|
||||
let pos = rect.right_top() + vec2(-TEXT_RIGHT, TEXT_TOP);
|
||||
let text = RichText::new(crate::ui::widgets::COPY_SYMBOL);
|
||||
let id = self.make_id("copy-pubkey");
|
||||
let (galley, response) = allocate_text_at(ui, pos, text.into(), Align::RIGHT, id);
|
||||
if response
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand)
|
||||
.clicked() {
|
||||
ui.output_mut(|o| {
|
||||
o.copied_text = self.pk.as_bech32_string();
|
||||
GLOBALS
|
||||
.status_queue
|
||||
.write()
|
||||
.write("copied to clipboard".to_owned());
|
||||
});
|
||||
}
|
||||
draw_text_galley_at(ui, pos, galley, None, None);
|
||||
}
|
||||
|
||||
// pubkey
|
||||
let pos = rect.right_top() + vec2(-TEXT_RIGHT - 20.0, TEXT_TOP);
|
||||
draw_text_at(
|
||||
ui,
|
||||
pos,
|
||||
galley,
|
||||
None,
|
||||
None);
|
||||
|
||||
widgets::list_entry::draw_text_at(
|
||||
ui,
|
||||
pos + vec2(response.rect.width(), 0.0),
|
||||
format!(": coverage short by {} relay(s)", self.count).into(),
|
||||
egui::Align::LEFT,
|
||||
self.pk.as_bech32_string().into(),
|
||||
Align::RIGHT,
|
||||
None,
|
||||
None);
|
||||
|
||||
let response = response
|
||||
.on_hover_text(format!("Go to profile of {}", self.name))
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
// ---- connected relays ----
|
||||
let pos = rect.min + vec2(TEXT_LEFT, TEXT_TOP + 30.0);
|
||||
let relays_string = self.relays.iter().map(|f| f.to_string()).collect::<Vec<String>>().join(", ");
|
||||
draw_text_at(
|
||||
ui,
|
||||
pos,
|
||||
relays_string.into(),
|
||||
Align::LEFT,
|
||||
None,
|
||||
None);
|
||||
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
fn find_relays_for_pubkey(pk: &PublicKey) -> Vec<RelayUrl> {
|
||||
GLOBALS.relay_picker.relay_assignments_iter()
|
||||
.filter(|f| f.pubkeys.contains(pk))
|
||||
.map(|f| f.relay_url.clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
|
||||
ui.add_space(10.0);
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.heading("Coverage Report");
|
||||
ui.heading(format!("Low Coverage Report (less than {} relays)", app.settings.num_relays_per_person));
|
||||
ui.add_space(10.0);
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Min), |ui| {
|
||||
ui.add_space(20.0);
|
||||
ui.spacing_mut().button_padding *= 2.0;
|
||||
{
|
||||
let visuals = ui.visuals_mut();
|
||||
visuals.widgets.inactive.weak_bg_fill = app.settings.theme.accent_color();
|
||||
visuals.widgets.inactive.fg_stroke.width = 1.0;
|
||||
visuals.widgets.inactive.fg_stroke.color = app.settings.theme.get_style().visuals.extreme_bg_color;
|
||||
visuals.widgets.hovered.weak_bg_fill = app.settings.theme.navigation_text_color();
|
||||
visuals.widgets.hovered.fg_stroke.color = app.settings.theme.accent_color();
|
||||
visuals.widgets.inactive.fg_stroke.color = app.settings.theme.get_style().visuals.extreme_bg_color;
|
||||
}
|
||||
if ui.button("Pick Relays Again")
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand)
|
||||
.clicked() {
|
||||
let _ = GLOBALS.to_overlord.send(ToOverlordMessage::PickRelays);
|
||||
}
|
||||
});
|
||||
});
|
||||
ui.add_space(10.0);
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
@ -69,8 +131,6 @@ pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Fr
|
||||
app.set_page(Page::Settings);
|
||||
}
|
||||
});
|
||||
ui.add_space(10.0);
|
||||
|
||||
if GLOBALS.relay_picker.pubkey_counts_iter().count() > 0 {
|
||||
ui.label(
|
||||
format!("The Relay-Picker has tried to connect to at least {} relays \
|
||||
@ -78,11 +138,6 @@ pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Fr
|
||||
You can manually ask the Relay-Picker to pick again, however most of the time it has already \
|
||||
tried its best.", app.settings.num_relays_per_person));
|
||||
|
||||
ui.add_space(10.0);
|
||||
if ui.link("Pick Again").clicked() {
|
||||
let _ = GLOBALS.to_overlord.send(ToOverlordMessage::PickRelays);
|
||||
}
|
||||
|
||||
ui.add_space(10.0);
|
||||
let id_source = ui.auto_id_with("relay-coverage-scroll");
|
||||
egui::ScrollArea::vertical()
|
||||
@ -91,12 +146,20 @@ pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Fr
|
||||
for elem in GLOBALS.relay_picker.pubkey_counts_iter() {
|
||||
let pk = elem.key();
|
||||
let count = elem.value();
|
||||
let name = GossipUi::display_name_from_pubkey_lookup(pk);
|
||||
let relays = find_relays_for_pubkey(pk);
|
||||
let hover_text = format!("Go to profile of {}", name);
|
||||
|
||||
let entry = CoverageEntry::new(pk, count);
|
||||
if entry.show(ui).clicked() {
|
||||
let entry = CoverageEntry::new(pk, name, count, relays);
|
||||
if entry.show(ui, app)
|
||||
.on_hover_text(hover_text)
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand)
|
||||
.clicked()
|
||||
{
|
||||
app.set_page(Page::Person(*pk));
|
||||
}
|
||||
}
|
||||
// uncomment below to mock with people entries for development
|
||||
// for pk in GLOBALS.people.get_followed_pubkeys() {
|
||||
// let entry = CoverageEntry::new(&pk, &0);
|
||||
// if entry.show(ui).clicked() {
|
||||
|
@ -17,6 +17,8 @@ pub(crate) const TEXT_LEFT: f32 = 20.0;
|
||||
pub(crate) const TEXT_RIGHT: f32 = 25.0;
|
||||
/// Start of text (excl. outer margin): top
|
||||
pub(crate) const TEXT_TOP: f32 = 15.0;
|
||||
/// Title font size
|
||||
pub(crate) const TITLE_FONT_SIZE: f32 = 16.5;
|
||||
/// Thickness of separator
|
||||
const HLINE_THICKNESS: f32 = 1.5;
|
||||
|
||||
@ -27,12 +29,12 @@ pub(crate) fn allocate_space(ui: &mut Ui, height: f32) -> (Rect, Response) {
|
||||
ui.allocate_exact_size(vec2(available_width, height), Sense::hover())
|
||||
}
|
||||
|
||||
pub(crate) fn paint_frame(ui: &mut Ui, rect: &Rect) {
|
||||
pub(crate) fn paint_frame(ui: &mut Ui, rect: &Rect, fill: Option<Color32>) {
|
||||
let frame_rect = Rect::from_min_max(
|
||||
rect.min + vec2(OUTER_MARGIN_LEFT, OUTER_MARGIN_TOP),
|
||||
rect.max - vec2(OUTER_MARGIN_RIGHT, OUTER_MARGIN_BOTTOM),
|
||||
);
|
||||
let fill = ui.style().visuals.extreme_bg_color;
|
||||
let fill = fill.unwrap_or(ui.style().visuals.extreme_bg_color);
|
||||
ui.painter().add(epaint::RectShape {
|
||||
rect: frame_rect,
|
||||
rounding: Rounding::same(5.0),
|
||||
|
@ -21,6 +21,9 @@ pub use relay_entry::{RelayEntry, RelayEntryView};
|
||||
// ui.label(job.job);
|
||||
// }
|
||||
|
||||
/// Copy symbol for copy button
|
||||
pub(crate) const COPY_SYMBOL: &str = "\u{1F4CB}";
|
||||
|
||||
pub fn break_anywhere_hyperlink_to(ui: &mut Ui, text: impl Into<WidgetText>, url: impl ToString) {
|
||||
let mut job = text.into().into_text_job(
|
||||
ui.style(),
|
||||
|
@ -43,8 +43,6 @@ const USAGE_LINE_X_END: f32 = -10.0;
|
||||
const USAGE_LINE_THICKNESS: f32 = 1.0;
|
||||
/// Spacing between nip11 text rows
|
||||
const NIP11_Y_SPACING: f32 = 20.0;
|
||||
/// Copy symbol for nip11 items copy button
|
||||
const COPY_SYMBOL: &str = "\u{2398}";
|
||||
/// Status symbol for status color indicator
|
||||
const STATUS_SYMBOL: &str = "\u{25CF}";
|
||||
/// Space reserved for status symbol before title
|
||||
@ -223,7 +221,7 @@ impl RelayEntry {
|
||||
if self.relay.url.0.len() > TITLE_MAX_LEN {
|
||||
title.push('\u{2026}'); // append ellipsis
|
||||
}
|
||||
let text = RichText::new(title).size(16.5);
|
||||
let text = RichText::new(title).size(list_entry::TITLE_FONT_SIZE);
|
||||
let pos = rect.min + vec2(TEXT_LEFT + STATUS_SYMBOL_SPACE, TEXT_TOP);
|
||||
let rect = draw_text_at(ui, pos, text.into(), Align::LEFT, Some(self.accent), None);
|
||||
ui.interact(rect, ui.next_auto_id(), Sense::hover())
|
||||
@ -601,7 +599,7 @@ impl RelayEntry {
|
||||
let rect = draw_text_at(ui, pos, contact.into(), align, None, None);
|
||||
let id = self.make_id("copy_nip11_contact");
|
||||
let pos = pos + vec2(rect.width() + ui.spacing().item_spacing.x, 0.0);
|
||||
let text = RichText::new(COPY_SYMBOL);
|
||||
let text = RichText::new(crate::ui::widgets::COPY_SYMBOL);
|
||||
let (galley, response) = allocate_text_at(ui, pos, text.into(), align, id);
|
||||
if response.clicked() {
|
||||
ui.output_mut(|o| {
|
||||
@ -634,7 +632,7 @@ impl RelayEntry {
|
||||
let rect = draw_text_at(ui, pos, npub.clone().into(), align, None, None);
|
||||
let id = self.make_id("copy_nip11_npub");
|
||||
let pos = pos + vec2(rect.width() + ui.spacing().item_spacing.x, 0.0);
|
||||
let text = RichText::new(COPY_SYMBOL);
|
||||
let text = RichText::new(crate::ui::widgets::COPY_SYMBOL);
|
||||
let (galley, response) = allocate_text_at(ui, pos, text.into(), align, id);
|
||||
if response.clicked() {
|
||||
ui.output_mut(|o| {
|
||||
@ -1035,7 +1033,7 @@ impl RelayEntry {
|
||||
|
||||
// all the heavy lifting is only done if it's actually visible
|
||||
if ui.is_rect_visible(rect) {
|
||||
list_entry::paint_frame(ui, &rect);
|
||||
list_entry::paint_frame(ui, &rect, None);
|
||||
self.paint_title(ui, &rect);
|
||||
response |= self.paint_edit_btn(ui, &rect);
|
||||
if self.relay.usage_bits != 0 {
|
||||
@ -1052,7 +1050,7 @@ impl RelayEntry {
|
||||
|
||||
// all the heavy lifting is only done if it's actually visible
|
||||
if ui.is_rect_visible(rect) {
|
||||
list_entry::paint_frame(ui, &rect);
|
||||
list_entry::paint_frame(ui, &rect, None);
|
||||
self.paint_title(ui, &rect);
|
||||
response |= self.paint_edit_btn(ui, &rect);
|
||||
self.paint_stats(ui, &rect);
|
||||
@ -1070,7 +1068,7 @@ impl RelayEntry {
|
||||
|
||||
// all the heavy lifting is only done if it's actually visible
|
||||
if ui.is_rect_visible(rect) {
|
||||
list_entry::paint_frame(ui, &rect);
|
||||
list_entry::paint_frame(ui, &rect, None);
|
||||
self.paint_title(ui, &rect);
|
||||
self.paint_stats(ui, &rect);
|
||||
paint_hline(ui, &rect, HLINE_1_Y_OFFSET);
|
||||
|
Loading…
Reference in New Issue
Block a user