diff --git a/gossip-bin/src/ui/mod.rs b/gossip-bin/src/ui/mod.rs index 820146f4..e8545fa8 100644 --- a/gossip-bin/src/ui/mod.rs +++ b/gossip-bin/src/ui/mod.rs @@ -82,7 +82,7 @@ pub fn run() -> Result<(), Error> { centered: true, vsync: true, follow_system_theme: GLOBALS.storage.read_setting_follow_os_dark_mode(), - min_window_size: Some(egui::vec2(800.0,600.0)), + min_window_size: Some(egui::vec2(800.0, 600.0)), ..Default::default() }; @@ -1080,23 +1080,28 @@ impl eframe::App for GossipUi { egui::CentralPanel::default() .frame({ let frame = egui::Frame::central_panel(&self.theme.get_style()); - frame.inner_margin(egui::Margin { - left: 20.0, - right: 10.0, - top: 10.0, - bottom: 0.0, - }).fill({ - match self.page { - Page::PeopleList | Page::PeopleFollow | Page::PeopleMuted | Page::Person(_) => { - if self.theme.dark_mode { - ctx.style().visuals.panel_fill - } else { - self.theme.main_content_bgcolor() + frame + .inner_margin(egui::Margin { + left: 20.0, + right: 10.0, + top: 10.0, + bottom: 0.0, + }) + .fill({ + match self.page { + Page::PeopleList + | Page::PeopleFollow + | Page::PeopleMuted + | Page::Person(_) => { + if self.theme.dark_mode { + ctx.style().visuals.panel_fill + } else { + self.theme.main_content_bgcolor() + } } + _ => ctx.style().visuals.panel_fill, } - _ => {ctx.style().visuals.panel_fill} - } - }) + }) }) .show(ctx, |ui| { self.begin_ui(ui); @@ -1127,9 +1132,7 @@ impl eframe::App for GossipUi { impl GossipUi { fn begin_ui(&self, ui: &mut Ui) { // if a dialog is open, disable the rest of the UI - ui.set_enabled( - !relays::is_entry_dialog_active(self) && - self.person_qr.is_none()); + ui.set_enabled(!relays::is_entry_dialog_active(self) && self.person_qr.is_none()); } pub fn person_name(person: &Person) -> String { diff --git a/gossip-bin/src/ui/people/person.rs b/gossip-bin/src/ui/people/person.rs index 153c2deb..12b4ca59 100644 --- a/gossip-bin/src/ui/people/person.rs +++ b/gossip-bin/src/ui/people/person.rs @@ -1,19 +1,19 @@ use super::{GossipUi, Page}; use crate::ui::widgets; +use crate::ui::widgets::list_entry; use crate::ui::widgets::CopyButton; use crate::AVATAR_SIZE_F32; -use crate::ui::widgets::list_entry; use eframe::egui; use egui::{Context, Image, RichText, TextEdit, Ui, Vec2}; +use egui_winit::egui::vec2; use egui_winit::egui::InnerResponse; use egui_winit::egui::Response; use egui_winit::egui::Widget; -use egui_winit::egui::vec2; +use gossip_lib::comms::ToOverlordMessage; use gossip_lib::DmChannel; use gossip_lib::FeedKind; -use gossip_lib::PersonList; -use gossip_lib::comms::ToOverlordMessage; use gossip_lib::Person; +use gossip_lib::PersonList; use gossip_lib::GLOBALS; use nostr_types::{PublicKey, RelayUrl}; use serde_json::Value; @@ -40,12 +40,14 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra }; ui.add_space(10.0); - ui.horizontal(|ui|{ + ui.horizontal(|ui| { ui.add_space(10.0); let name = GossipUi::person_name(&person); - ui.label(RichText::new(name) - .size(22.0) - .color(app.theme.accent_color())); + ui.label( + RichText::new(name) + .size(22.0) + .color(app.theme.accent_color()), + ); }); app.vert_scroll_area() @@ -72,10 +74,9 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe let width = width.max(MIN_ITEM_WIDTH); let half_width = width / 2.0; - ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui|{ - ui.with_layout( - egui::Layout::top_down(egui::Align::TOP), - |ui|{ // left column + ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { + ui.with_layout(egui::Layout::top_down(egui::Align::TOP), |ui| { + // left column ui.set_min_width(width); ui.set_max_width(width); let person = person.clone(); @@ -87,14 +88,27 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe (egui::Layout::top_down(egui::Align::TOP), width) }; - ui.with_layout(layout,|ui|{ - profile_item_qr(ui, app, lwidth,"public key", gossip_lib::names::pubkey_short(&pubkey), "npub"); + ui.with_layout(layout, |ui| { + profile_item_qr( + ui, + app, + lwidth, + "public key", + gossip_lib::names::pubkey_short(&pubkey), + "npub", + ); profile_item(ui, app, lwidth, "NIP-05", person.nip05().unwrap_or("")); }); - ui.with_layout(layout, |ui|{ + ui.with_layout(layout, |ui| { profile_item(ui, app, lwidth, "name", person.name().unwrap_or("")); - profile_item(ui, app, lwidth, "display name", person.display_name().unwrap_or("")); + profile_item( + ui, + app, + lwidth, + "display name", + person.display_name().unwrap_or(""), + ); }); if !is_self { @@ -103,10 +117,12 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe ui.vertical(|ui| { item_label(ui, "Pet Name"); ui.add_space(ITEM_V_SPACE); - ui.horizontal(|ui|{ + ui.horizontal(|ui| { if app.editing_petname { let edit_color = app.theme.input_text_color(); - ui.add(TextEdit::singleline(&mut app.petname).text_color(edit_color)); + ui.add( + TextEdit::singleline(&mut app.petname).text_color(edit_color), + ); if ui.link("Save").clicked() { let mut person = person.clone(); if app.petname.trim().is_empty() { @@ -150,11 +166,13 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe app.notes.cache_invalidate_person(&person.pubkey); } } else { - if ui.link("Add") + if ui + .link("Add") .on_hover_cursor(egui::CursorIcon::PointingHand) - .clicked() { - app.editing_petname = true; - app.petname = "".to_owned(); + .clicked() + { + app.editing_petname = true; + app.petname = "".to_owned(); } } } @@ -170,7 +188,6 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe } if let Some(md) = &person.metadata { - // render some important fields first { const LUD06: &str = "lud06"; @@ -208,7 +225,7 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe } } - const SKIP: &[&str] = &[ "display_name", "lud06", "lud16", "website" ]; + const SKIP: &[&str] = &["display_name", "lud06", "lud16", "website"]; for (key, value) in &md.other { // skip the "important" fields that are already rendered @@ -238,7 +255,8 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe app.setting_active_person = false; let relays = GLOBALS.people.get_active_person_write_relays(); - let relays_str: String = relays.iter() + let relays_str: String = relays + .iter() .map(|f| f.0.host()) .collect::>() .join(", "); @@ -246,29 +264,28 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe profile_item(ui, app, width, "Relays", relays_str); // Option to manually add a relay for them - make_frame() - .show(ui, |ui| { - ui.vertical(|ui| { - item_label(ui, "Manual Relay"); - ui.add_space(ITEM_V_SPACE); - ui.horizontal(|ui| { - ui.add(text_edit_line!(app, app.add_relay).hint_text("wss://...")); - if ui.button("Add").clicked() { - if let Ok(url) = RelayUrl::try_from_str(&app.add_relay) { - let _ = GLOBALS - .to_overlord - .send(ToOverlordMessage::AddPubkeyRelay(pubkey, url)); - app.add_relay = "".to_owned(); - } else { - GLOBALS - .status_queue - .write() - .write("Invalid Relay Url".to_string()); - } + make_frame().show(ui, |ui| { + ui.vertical(|ui| { + item_label(ui, "Manual Relay"); + ui.add_space(ITEM_V_SPACE); + ui.horizontal(|ui| { + ui.add(text_edit_line!(app, app.add_relay).hint_text("wss://...")); + if ui.button("Add").clicked() { + if let Ok(url) = RelayUrl::try_from_str(&app.add_relay) { + let _ = GLOBALS + .to_overlord + .send(ToOverlordMessage::AddPubkeyRelay(pubkey, url)); + app.add_relay = "".to_owned(); + } else { + GLOBALS + .status_queue + .write() + .write("Invalid Relay Url".to_string()); } - }); + } }); }); + }); ui.add_space(10.0); } @@ -283,130 +300,208 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe // avatar column ui.allocate_ui_with_layout( - vec2( AVATAR_COL_WIDTH, f32::INFINITY), + vec2(AVATAR_COL_WIDTH, f32::INFINITY), egui::Layout::right_to_left(egui::Align::TOP).with_main_justify(true), - |ui|{ - ui.vertical(|ui|{ - - let avatar = if let Some(avatar) = app.try_get_avatar(ctx, &pubkey) { - avatar - } else { - app.placeholder_avatar.clone() - }; - - ui.vertical_centered_justified(|ui|{ - let followed = person.is_in_list(PersonList::Followed); - let muted = person.is_in_list(PersonList::Muted); - let on_list = person.is_in_list(PersonList::Custom(2)); // TODO: change to any list - let is_self = if let Some(pubkey) = GLOBALS.signer.public_key() { - pubkey == person.pubkey + |ui| { + ui.vertical(|ui| { + let avatar = if let Some(avatar) = app.try_get_avatar(ctx, &pubkey) { + avatar } else { - false + app.placeholder_avatar.clone() }; - let avatar_response = ui.add( - Image::new(&avatar) - .max_size(Vec2 { - x: AVATAR_SIZE_F32 * 3.0, - y: AVATAR_SIZE_F32 * 3.0, - }) - .maintain_aspect_ratio(true), - ); + ui.vertical_centered_justified(|ui| { + let followed = person.is_in_list(PersonList::Followed); + let muted = person.is_in_list(PersonList::Muted); + let on_list = person.is_in_list(PersonList::Custom(2)); // TODO: change to any list + let is_self = if let Some(pubkey) = GLOBALS.signer.public_key() { + pubkey == person.pubkey + } else { + false + }; - let status_color = match (followed, on_list, muted) { - (true, _, false) => app.theme.accent_color(), // followed - (false, true, false) => egui::Color32::GREEN, // on-list - (_, _, true) => app.theme.danger_color(), // muted - (false, false, false) => egui::Color32::TRANSPARENT, - }; - if status_color != egui::Color32::TRANSPARENT { - let center = avatar_response.rect.right_top() + vec2(-20.0,20.0); - ui.painter().circle( - center, - 10.0, - status_color, - egui::Stroke::new(2.0, ui.visuals().panel_fill)); - let rect = egui::Rect::from_center_size(center, vec2(10.0,10.0)); - ui.interact(rect, ui.auto_id_with("status-circle"), egui::Sense::hover()) + let avatar_response = ui.add( + Image::new(&avatar) + .max_size(Vec2 { + x: AVATAR_SIZE_F32 * 3.0, + y: AVATAR_SIZE_F32 * 3.0, + }) + .maintain_aspect_ratio(true), + ); + + let status_color = match (followed, on_list, muted) { + (true, _, false) => app.theme.accent_color(), // followed + (false, true, false) => egui::Color32::GREEN, // on-list + (_, _, true) => app.theme.danger_color(), // muted + (false, false, false) => egui::Color32::TRANSPARENT, + }; + if status_color != egui::Color32::TRANSPARENT { + let center = avatar_response.rect.right_top() + vec2(-20.0, 20.0); + ui.painter().circle( + center, + 10.0, + status_color, + egui::Stroke::new(2.0, ui.visuals().panel_fill), + ); + let rect = egui::Rect::from_center_size(center, vec2(10.0, 10.0)); + ui.interact( + rect, + ui.auto_id_with("status-circle"), + egui::Sense::hover(), + ) .on_hover_text({ let mut stat: Vec<&str> = Vec::new(); - if followed { stat.push("followed") } - if on_list { stat.push("priority") } - if muted { stat.push("muted") } + if followed { + stat.push("followed") + } + if on_list { + stat.push("priority") + } + if muted { + stat.push("muted") + } stat.join(", ") }); - } - - const MIN_SIZE: Vec2 = vec2(40.0, 22.0); - const BTN_SPACING: f32 = 15.0; - const BTN_ROUNDING: f32 = 4.0; - ui.add_space(40.0); - - ui.vertical_centered_justified(|ui|{ - app.theme.accent_button_1_style(ui.style_mut()); - - if ui.add(egui::Button::new("View posts").min_size(MIN_SIZE).rounding(BTN_ROUNDING)).clicked() { - app.set_page(Page::Feed(FeedKind::Person(person.pubkey))); } - ui.add_space(BTN_SPACING); + const MIN_SIZE: Vec2 = vec2(40.0, 22.0); + const BTN_SPACING: f32 = 15.0; + const BTN_ROUNDING: f32 = 4.0; + ui.add_space(40.0); + + ui.vertical_centered_justified(|ui| { + app.theme.accent_button_1_style(ui.style_mut()); + + if ui + .add( + egui::Button::new("View posts") + .min_size(MIN_SIZE) + .rounding(BTN_ROUNDING), + ) + .clicked() + { + app.set_page(Page::Feed(FeedKind::Person(person.pubkey))); + } + + ui.add_space(BTN_SPACING); + + if !is_self { + if ui + .add( + egui::Button::new("Send message") + .min_size(MIN_SIZE) + .rounding(BTN_ROUNDING), + ) + .clicked() + { + let channel = DmChannel::new(&[person.pubkey]); + app.set_page(Page::Feed(FeedKind::DmChat(channel))); + }; + } else { + if ui + .add( + egui::Button::new("Edit Profile") + .min_size(MIN_SIZE) + .rounding(BTN_ROUNDING), + ) + .clicked() + { + app.set_page(Page::YourMetadata); + } + } + }); if !is_self { - if ui.add(egui::Button::new("Send message").min_size(MIN_SIZE).rounding(BTN_ROUNDING)).clicked() { - let channel = DmChannel::new(&[person.pubkey]); - app.set_page(Page::Feed(FeedKind::DmChat(channel))); + ui.add_space(BTN_SPACING * 2.0); + app.theme.accent_button_2_style(ui.style_mut()); + + if !followed { + if ui + .add( + egui::Button::new("Follow") + .min_size(MIN_SIZE) + .rounding(BTN_ROUNDING), + ) + .clicked() + { + let _ = GLOBALS.people.follow(&person.pubkey, true, true); + } + } else { + app.theme.accent_button_danger_hover(ui.style_mut()); + if ui + .add( + egui::Button::new("Unfollow") + .min_size(MIN_SIZE) + .rounding(BTN_ROUNDING), + ) + .clicked() + { + let _ = GLOBALS.people.follow(&person.pubkey, false, true); + } + app.theme.accent_button_2_style(ui.style_mut()); + // restore style + } + ui.add_space(BTN_SPACING); + if !on_list { + if ui + .add( + egui::Button::new("Add to Priority") + .min_size(MIN_SIZE) + .rounding(BTN_ROUNDING), + ) + .clicked() + { + let _ = GLOBALS.storage.add_person_to_list( + &person.pubkey, + PersonList::Custom(2), + true, + None, + ); + }; + } else { + app.theme.accent_button_danger_hover(ui.style_mut()); + if ui + .add( + egui::Button::new("Remove from Priority") + .min_size(MIN_SIZE) + .rounding(BTN_ROUNDING), + ) + .clicked() + { + let _ = GLOBALS.storage.remove_person_from_list( + &person.pubkey, + PersonList::Custom(2), + None, + ); + }; + app.theme.accent_button_2_style(ui.style_mut()); + // restore style + } + ui.add_space(BTN_SPACING); + + let mute_label = if muted { + "Unmute" + } else { + app.theme.accent_button_danger_hover(ui.style_mut()); + "Mute" }; - } else { - if ui.add(egui::Button::new("Edit Profile").min_size(MIN_SIZE).rounding(BTN_ROUNDING)).clicked() { - app.set_page(Page::YourMetadata); + if ui + .add( + egui::Button::new(mute_label) + .min_size(MIN_SIZE) + .rounding(BTN_ROUNDING), + ) + .clicked() + { + let _ = GLOBALS.people.mute(&person.pubkey, !muted, true); + app.notes.cache_invalidate_person(&person.pubkey); } } }); - - if !is_self { - ui.add_space(BTN_SPACING*2.0); - app.theme.accent_button_2_style(ui.style_mut()); - - if !followed { - if ui.add(egui::Button::new("Follow").min_size(MIN_SIZE).rounding(BTN_ROUNDING)).clicked() { - let _ = GLOBALS.people.follow(&person.pubkey, true, true); - } - } else { - app.theme.accent_button_danger_hover(ui.style_mut()); - if ui.add(egui::Button::new("Unfollow").min_size(MIN_SIZE).rounding(BTN_ROUNDING)).clicked() { - let _ = GLOBALS.people.follow(&person.pubkey, false, true); - } - app.theme.accent_button_2_style(ui.style_mut()); // restore style - } - ui.add_space(BTN_SPACING); - if !on_list { - if ui.add(egui::Button::new("Add to Priority").min_size(MIN_SIZE).rounding(BTN_ROUNDING)).clicked() { - let _ = GLOBALS.storage.add_person_to_list(&person.pubkey, PersonList::Custom(2), true, None); - }; - } else { - app.theme.accent_button_danger_hover(ui.style_mut()); - if ui.add(egui::Button::new("Remove from Priority").min_size(MIN_SIZE).rounding(BTN_ROUNDING)).clicked() { - let _ = GLOBALS.storage.remove_person_from_list(&person.pubkey, PersonList::Custom(2), None); - }; - app.theme.accent_button_2_style(ui.style_mut()); // restore style - } - ui.add_space(BTN_SPACING); - - let mute_label = if muted { - "Unmute" - } else { - app.theme.accent_button_danger_hover(ui.style_mut()); - "Mute" - }; - if ui.add(egui::Button::new(mute_label).min_size(MIN_SIZE).rounding(BTN_ROUNDING)).clicked() { - let _ = GLOBALS.people.mute(&person.pubkey, !muted, true); - app.notes.cache_invalidate_person(&person.pubkey); - } - } }); - }); - ui.add_space(AVATAR_COL_SPACE); - }); + ui.add_space(AVATAR_COL_SPACE); + }, + ); }); // horizontal // Render a modal with QR based on selections made above @@ -414,38 +509,38 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe match app.person_qr { Some("npub") => { let ret = widgets::modal_popup(ui, DLG_SIZE, |ui| { - ui.vertical_centered(|ui|{ - ui.add_space(10.0); - ui.heading("Public Key (npub)"); - ui.add_space(10.0); - app.render_qr(ui, ctx, "person_qr", &npub); - ui.add_space(10.0); - ui.label(&npub); - ui.add_space(10.0); - if ui.link("Copy npub").clicked() { - ui.output_mut(|o| o.copied_text = npub.to_owned()); - } - }); + ui.vertical_centered(|ui| { + ui.add_space(10.0); + ui.heading("Public Key (npub)"); + ui.add_space(10.0); + app.render_qr(ui, ctx, "person_qr", &npub); + ui.add_space(10.0); + ui.label(&npub); + ui.add_space(10.0); + if ui.link("Copy npub").clicked() { + ui.output_mut(|o| o.copied_text = npub.to_owned()); + } }); + }); if ret.inner.clicked() { app.person_qr = None; } } Some("lud06") => { let ret = widgets::modal_popup(ui, DLG_SIZE, |ui| { - ui.vertical_centered(|ui|{ - ui.add_space(10.0); - ui.heading("Lightning Network Address (lud06)"); - ui.add_space(10.0); - app.render_qr(ui, ctx, "person_qr", &lud06); - ui.add_space(10.0); - ui.label(&lud06); - ui.add_space(10.0); - if ui.link("Copy lud06").clicked() { - ui.output_mut(|o| o.copied_text = lud06.to_owned()); - } - }); + ui.vertical_centered(|ui| { + ui.add_space(10.0); + ui.heading("Lightning Network Address (lud06)"); + ui.add_space(10.0); + app.render_qr(ui, ctx, "person_qr", &lud06); + ui.add_space(10.0); + ui.label(&lud06); + ui.add_space(10.0); + if ui.link("Copy lud06").clicked() { + ui.output_mut(|o| o.copied_text = lud06.to_owned()); + } }); + }); if ret.inner.clicked() { app.person_qr = None; } @@ -453,18 +548,18 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe Some("lud16") => { let ret = widgets::modal_popup(ui, DLG_SIZE, |ui| { ui.vertical_centered(|ui| { - ui.add_space(10.0); - ui.heading("Lightning Network Address (lud16)"); - ui.add_space(10.0); - app.render_qr(ui, ctx, "person_qr", &lud16); - ui.add_space(10.0); - ui.label(&lud16); - ui.add_space(10.0); - if ui.link("Copy lud16").clicked() { - ui.output_mut(|o| o.copied_text = lud16.to_owned()); - } - }); + ui.add_space(10.0); + ui.heading("Lightning Network Address (lud16)"); + ui.add_space(10.0); + app.render_qr(ui, ctx, "person_qr", &lud16); + ui.add_space(10.0); + ui.label(&lud16); + ui.add_space(10.0); + if ui.link("Copy lud16").clicked() { + ui.output_mut(|o| o.copied_text = lud16.to_owned()); + } }); + }); if ret.inner.clicked() { app.person_qr = None; } @@ -474,24 +569,39 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe } /// A profile item -fn profile_item(ui: &mut Ui, app: &mut GossipUi, width: f32, label: impl Into, content: impl Into) { +fn profile_item( + ui: &mut Ui, + app: &mut GossipUi, + width: f32, + label: impl Into, + content: impl Into, +) { let content: String = content.into(); let symbol = CopyButton::new().stroke(egui::Stroke::new(1.4, app.theme.accent_color())); let response = profile_item_frame(ui, width, label, &content, symbol).response; - if response - .clicked() { + if response.clicked() { ui.output_mut(|o| o.copied_text = content.to_owned()); } } /// A profile item with qr copy option -fn profile_item_qr(ui: &mut Ui, app: &mut GossipUi, width: f32, label: impl Into, display_content: impl Into, qr_content: &'static str) { - let symbol = egui::Label::new( egui::RichText::new("⚃").size(16.5).color(app.theme.accent_color()) ); +fn profile_item_qr( + ui: &mut Ui, + app: &mut GossipUi, + width: f32, + label: impl Into, + display_content: impl Into, + qr_content: &'static str, +) { + let symbol = egui::Label::new( + egui::RichText::new("⚃") + .size(16.5) + .color(app.theme.accent_color()), + ); let response = profile_item_frame(ui, width, label, display_content, symbol).response; - if response - .clicked() { + if response.clicked() { app.qr_codes.remove("person_qr"); app.person_qr = Some(qr_content); } @@ -520,51 +630,63 @@ fn item_label(ui: &mut Ui, label: impl Into) { ui.label(RichText::new(label.to_uppercase()).weak().small()); } -fn profile_item_frame(ui: &mut Ui, width: f32, label: impl Into, content: impl Into, symbol: impl Widget) -> InnerResponse { +fn profile_item_frame( + ui: &mut Ui, + width: f32, + label: impl Into, + content: impl Into, + symbol: impl Widget, +) -> InnerResponse { let content: String = content.into(); let label: String = label.into(); - let width = width - list_entry::TEXT_LEFT - list_entry::TEXT_RIGHT - ui.spacing().item_spacing.x; + let width = + width - list_entry::TEXT_LEFT - list_entry::TEXT_RIGHT - ui.spacing().item_spacing.x; let frame = make_frame(); let mut prepared = frame.begin(ui); let inner = { - let ui =&mut prepared.content_ui; - ui.horizontal(|ui|{ + let ui = &mut prepared.content_ui; + ui.horizontal(|ui| { ui.set_min_width(width); ui.set_max_width(width); - let response = ui.vertical(|ui|{ - item_label(ui, &label); - ui.add_space(ITEM_V_SPACE); - ui.horizontal_wrapped(|ui|{ - ui.label(content); - }); - }).response; + let response = ui + .vertical(|ui| { + item_label(ui, &label); + ui.add_space(ITEM_V_SPACE); + ui.horizontal_wrapped(|ui| { + ui.label(content); + }); + }) + .response; // ui.add_space(20.0); response - }).response + }) + .response }; - let frame_rect = (prepared.frame.inner_margin + prepared.frame.outer_margin).expand_rect(prepared.content_ui.min_rect()); + let frame_rect = (prepared.frame.inner_margin + prepared.frame.outer_margin) + .expand_rect(prepared.content_ui.min_rect()); - let response = ui.interact(frame_rect, ui.auto_id_with(&label), egui::Sense::click()) + let response = ui + .interact(frame_rect, ui.auto_id_with(&label), egui::Sense::click()) .on_hover_cursor(egui::CursorIcon::PointingHand); if response.hovered() { let sym_rect = egui::Rect::from_min_size( prepared.content_ui.min_rect().right_top() + vec2(-10.0, 0.0), - vec2(10.0, 10.0) + vec2(10.0, 10.0), ); // prepared.content_ui.allocate_ui_at_rect(sym_rect, |ui| { // ui.add_sized(sym_rect.size(), symbol) // }); - egui::Area::new(ui.auto_id_with(label+"_sym")) + egui::Area::new(ui.auto_id_with(label + "_sym")) .interactable(false) .movable(false) .order(egui::Order::Foreground) .fixed_pos(sym_rect.left_top()) - .show(prepared.content_ui.ctx(), |ui|{ + .show(prepared.content_ui.ctx(), |ui| { ui.add_sized(sym_rect.size(), symbol) }); if ui.visuals().dark_mode { diff --git a/gossip-bin/src/ui/relays/active.rs b/gossip-bin/src/ui/relays/active.rs index 41f31505..233a3d05 100644 --- a/gossip-bin/src/ui/relays/active.rs +++ b/gossip-bin/src/ui/relays/active.rs @@ -12,7 +12,7 @@ use nostr_types::RelayUrl; pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) { let is_editing = app.relays.edit.is_some(); - widgets::page_header(ui, Page::RelaysActivityMonitor.name(),|ui| { + widgets::page_header(ui, Page::RelaysActivityMonitor.name(), |ui| { ui.set_enabled(!is_editing); ui.add_space(20.0); super::configure_list_btn(app, ui); diff --git a/gossip-bin/src/ui/relays/coverage.rs b/gossip-bin/src/ui/relays/coverage.rs index 0c415812..2720c21f 100644 --- a/gossip-bin/src/ui/relays/coverage.rs +++ b/gossip-bin/src/ui/relays/coverage.rs @@ -121,32 +121,36 @@ fn find_relays_for_pubkey(pk: &PublicKey) -> Vec { } pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) { - widgets::page_header(ui, format!( - "Low Coverage Report (less than {} relays)", - app.settings.num_relays_per_person - ), |ui|{ - ui.add_space(20.0); - ui.spacing_mut().button_padding *= 2.0; - 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); - { - widgets::set_important_button_visuals(ui, app); - + widgets::page_header( + ui, + format!( + "Low Coverage Report (less than {} relays)", + app.settings.num_relays_per_person + ), + |ui| { + ui.add_space(20.0); + ui.spacing_mut().button_padding *= 2.0; if ui - .button(Page::RelaysActivityMonitor.name()) + .button("Pick Relays Again") .on_hover_cursor(egui::CursorIcon::PointingHand) .clicked() { - app.set_page(Page::RelaysActivityMonitor); + let _ = GLOBALS.to_overlord.send(ToOverlordMessage::PickRelays); } - } - }); + ui.add_space(10.0); + { + widgets::set_important_button_visuals(ui, app); + + if ui + .button(Page::RelaysActivityMonitor.name()) + .on_hover_cursor(egui::CursorIcon::PointingHand) + .clicked() + { + app.set_page(Page::RelaysActivityMonitor); + } + } + }, + ); ui.horizontal_wrapped(|ui| { ui.label("You can change how many relays per person to query here:"); if ui.link("Network Settings").clicked() { diff --git a/gossip-bin/src/ui/relays/known.rs b/gossip-bin/src/ui/relays/known.rs index 2fbb65bf..541cfd5e 100644 --- a/gossip-bin/src/ui/relays/known.rs +++ b/gossip-bin/src/ui/relays/known.rs @@ -8,7 +8,7 @@ use gossip_lib::GLOBALS; pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) { let is_editing = app.relays.edit.is_some(); - widgets::page_header(ui, Page::RelaysKnownNetwork.name(), |ui|{ + widgets::page_header(ui, Page::RelaysKnownNetwork.name(), |ui| { ui.set_enabled(!is_editing); ui.add_space(20.0); super::configure_list_btn(app, ui); diff --git a/gossip-bin/src/ui/relays/mine.rs b/gossip-bin/src/ui/relays/mine.rs index d051fd9f..87b5bb86 100644 --- a/gossip-bin/src/ui/relays/mine.rs +++ b/gossip-bin/src/ui/relays/mine.rs @@ -9,7 +9,7 @@ use gossip_lib::GLOBALS; pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) { let is_editing = app.relays.edit.is_some(); - widgets::page_header(ui, Page::RelaysMine.name(), |ui|{ + widgets::page_header(ui, Page::RelaysMine.name(), |ui| { ui.set_enabled(!is_editing); ui.add_space(20.0); super::configure_list_btn(app, ui); diff --git a/gossip-bin/src/ui/relays/mod.rs b/gossip-bin/src/ui/relays/mod.rs index f81d0692..62a0a7d4 100644 --- a/gossip-bin/src/ui/relays/mod.rs +++ b/gossip-bin/src/ui/relays/mod.rs @@ -339,8 +339,7 @@ fn entry_dialog_step1(ui: &mut Ui, app: &mut GossipUi) { // change frame color to error when url is invalid if !is_url_valid { - ui.visuals_mut().widgets.inactive.bg_stroke.color = - ui.visuals().error_fg_color; + ui.visuals_mut().widgets.inactive.bg_stroke.color = ui.visuals().error_fg_color; ui.visuals_mut().selection.stroke.color = ui.visuals().error_fg_color; } diff --git a/gossip-bin/src/ui/theme/default.rs b/gossip-bin/src/ui/theme/default.rs index 70d83c58..10834e9f 100644 --- a/gossip-bin/src/ui/theme/default.rs +++ b/gossip-bin/src/ui/theme/default.rs @@ -30,7 +30,7 @@ impl ThemeDef for DefaultTheme { } fn danger_color(_dark_mode: bool) -> Color32 { - Color32::from_rgb( 0xFF, 0x5E, 0x57 ) + Color32::from_rgb(0xFF, 0x5E, 0x57) } fn main_content_bgcolor(dark_mode: bool) -> Color32 { @@ -329,26 +329,30 @@ impl ThemeDef for DefaultTheme { let accent_color = Self::accent_color(dark_mode); if dark_mode { style.visuals.widgets.noninteractive.weak_bg_fill = accent_color; - style.visuals.widgets.noninteractive.fg_stroke = Stroke::new( 1.0, Color32::WHITE); + style.visuals.widgets.noninteractive.fg_stroke = Stroke::new(1.0, Color32::WHITE); style.visuals.widgets.inactive.weak_bg_fill = accent_color; style.visuals.widgets.inactive.fg_stroke = Stroke::new(1.0, Color32::WHITE); style.visuals.widgets.hovered.weak_bg_fill = Self::darken_color(accent_color, 0.2); style.visuals.widgets.hovered.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.hovered.bg_stroke = Stroke::new(1.0, Self::darken_color(accent_color, 0.2)); + style.visuals.widgets.hovered.bg_stroke = + Stroke::new(1.0, Self::darken_color(accent_color, 0.2)); style.visuals.widgets.active.weak_bg_fill = Self::darken_color(accent_color, 0.4); style.visuals.widgets.active.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.active.bg_stroke = Stroke::new(1.0, Self::darken_color(accent_color, 0.4)); + style.visuals.widgets.active.bg_stroke = + Stroke::new(1.0, Self::darken_color(accent_color, 0.4)); } else { style.visuals.widgets.noninteractive.weak_bg_fill = accent_color; - style.visuals.widgets.noninteractive.fg_stroke = Stroke::new( 1.0, Color32::WHITE); + style.visuals.widgets.noninteractive.fg_stroke = Stroke::new(1.0, Color32::WHITE); style.visuals.widgets.inactive.weak_bg_fill = accent_color; style.visuals.widgets.inactive.fg_stroke = Stroke::new(1.0, Color32::WHITE); style.visuals.widgets.hovered.weak_bg_fill = Self::darken_color(accent_color, 0.2); style.visuals.widgets.hovered.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.hovered.bg_stroke = Stroke::new(1.0, Self::darken_color(accent_color, 0.2)); + style.visuals.widgets.hovered.bg_stroke = + Stroke::new(1.0, Self::darken_color(accent_color, 0.2)); style.visuals.widgets.active.weak_bg_fill = Self::darken_color(accent_color, 0.4); style.visuals.widgets.active.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.active.bg_stroke = Stroke::new(1.0, Self::darken_color(accent_color, 0.4)); + style.visuals.widgets.active.bg_stroke = + Stroke::new(1.0, Self::darken_color(accent_color, 0.4)); } } @@ -356,40 +360,47 @@ impl ThemeDef for DefaultTheme { let accent_color = Self::accent_color(dark_mode); if dark_mode { style.visuals.widgets.noninteractive.weak_bg_fill = style.visuals.faint_bg_color; - style.visuals.widgets.noninteractive.fg_stroke = Stroke::new( 1.0, Color32::WHITE); + style.visuals.widgets.noninteractive.fg_stroke = Stroke::new(1.0, Color32::WHITE); style.visuals.widgets.noninteractive.bg_stroke = Stroke::new(1.0, Color32::WHITE); style.visuals.widgets.inactive.weak_bg_fill = style.visuals.faint_bg_color; style.visuals.widgets.inactive.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.inactive.bg_stroke = Stroke::new(1.0, Color32::from_white_alpha(40)); + style.visuals.widgets.inactive.bg_stroke = + Stroke::new(1.0, Color32::from_white_alpha(40)); style.visuals.widgets.hovered.weak_bg_fill = Self::darken_color(accent_color, 0.2); style.visuals.widgets.hovered.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.hovered.bg_stroke = Stroke::new(1.0, Self::darken_color(accent_color, 0.2)); + style.visuals.widgets.hovered.bg_stroke = + Stroke::new(1.0, Self::darken_color(accent_color, 0.2)); style.visuals.widgets.active.weak_bg_fill = Self::darken_color(accent_color, 0.4); style.visuals.widgets.active.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.active.bg_stroke = Stroke::new(1.0, Self::darken_color(accent_color, 0.4)); + style.visuals.widgets.active.bg_stroke = + Stroke::new(1.0, Self::darken_color(accent_color, 0.4)); } else { style.visuals.widgets.noninteractive.weak_bg_fill = Color32::WHITE; - style.visuals.widgets.noninteractive.fg_stroke = Stroke::new( 1.0, accent_color); + style.visuals.widgets.noninteractive.fg_stroke = Stroke::new(1.0, accent_color); style.visuals.widgets.noninteractive.bg_stroke = Stroke::new(1.0, accent_color); style.visuals.widgets.inactive.weak_bg_fill = Color32::WHITE; style.visuals.widgets.inactive.fg_stroke = Stroke::new(1.0, accent_color); style.visuals.widgets.inactive.bg_stroke = Stroke::new(1.0, accent_color); style.visuals.widgets.hovered.weak_bg_fill = Self::darken_color(accent_color, 0.2); style.visuals.widgets.hovered.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.hovered.bg_stroke = Stroke::new(1.0, Self::darken_color(accent_color, 0.2)); + style.visuals.widgets.hovered.bg_stroke = + Stroke::new(1.0, Self::darken_color(accent_color, 0.2)); style.visuals.widgets.active.weak_bg_fill = Self::darken_color(accent_color, 0.4); style.visuals.widgets.active.fg_stroke = Stroke::new(1.0, Color32::WHITE); - style.visuals.widgets.active.bg_stroke = Stroke::new(1.0, Self::darken_color(accent_color, 0.4)); + style.visuals.widgets.active.bg_stroke = + Stroke::new(1.0, Self::darken_color(accent_color, 0.4)); } } fn accent_button_danger_hover(style: &mut Style, dark_mode: bool) { style.visuals.widgets.hovered.weak_bg_fill = Self::danger_color(dark_mode); - style.visuals.widgets.hovered.fg_stroke = Stroke::new( 1.0, Color32::WHITE); - style.visuals.widgets.hovered.bg_stroke = Stroke::new(1.0, Self::darken_color(Self::danger_color(dark_mode), 0.2)); + style.visuals.widgets.hovered.fg_stroke = Stroke::new(1.0, Color32::WHITE); + style.visuals.widgets.hovered.bg_stroke = + Stroke::new(1.0, Self::darken_color(Self::danger_color(dark_mode), 0.2)); style.visuals.widgets.active.weak_bg_fill = Self::danger_color(dark_mode); - style.visuals.widgets.active.fg_stroke = Stroke::new( 1.0, Color32::WHITE); - style.visuals.widgets.active.bg_stroke = Stroke::new(1.0, Self::darken_color(Self::danger_color(dark_mode), 0.4)); + style.visuals.widgets.active.fg_stroke = Stroke::new(1.0, Color32::WHITE); + style.visuals.widgets.active.bg_stroke = + Stroke::new(1.0, Self::darken_color(Self::danger_color(dark_mode), 0.4)); } fn font_definitions() -> FontDefinitions { diff --git a/gossip-bin/src/ui/theme/mod.rs b/gossip-bin/src/ui/theme/mod.rs index 65b62b25..9edff043 100644 --- a/gossip-bin/src/ui/theme/mod.rs +++ b/gossip-bin/src/ui/theme/mod.rs @@ -400,8 +400,6 @@ pub trait ThemeDef: Send + Sync { /// 'danger' colored hover for accent-colored button styles fn accent_button_danger_hover(style: &mut Style, dark_mode: bool); - - fn font_definitions() -> FontDefinitions; fn text_styles() -> BTreeMap; fn highlight_text_format(highlight_type: HighlightType, dark_mode: bool) -> TextFormat; @@ -455,7 +453,6 @@ pub trait ThemeDef: Send + Sync { hsva.v = original_value * (1.0 - factor); // Linear interpolation hsva.into() } - } pub(super) fn font_definitions() -> FontDefinitions { diff --git a/gossip-bin/src/ui/widgets/copy_button.rs b/gossip-bin/src/ui/widgets/copy_button.rs index 31c10763..23dc0a6a 100644 --- a/gossip-bin/src/ui/widgets/copy_button.rs +++ b/gossip-bin/src/ui/widgets/copy_button.rs @@ -10,9 +10,7 @@ pub struct CopyButton { impl CopyButton { pub(crate) fn new() -> Self { - Self { - stroke: None - } + Self { stroke: None } } pub(crate) fn stroke(mut self, stroke: Stroke) -> Self { diff --git a/gossip-bin/src/ui/widgets/mod.rs b/gossip-bin/src/ui/widgets/mod.rs index 4fe06413..29c911b1 100644 --- a/gossip-bin/src/ui/widgets/mod.rs +++ b/gossip-bin/src/ui/widgets/mod.rs @@ -3,7 +3,9 @@ pub(crate) mod list_entry; pub use copy_button::{CopyButton, COPY_SYMBOL_SIZE}; mod nav_item; -use egui_winit::egui::{vec2, FontSelection, Rect, Response, Sense, TextEdit, Ui, WidgetText, self}; +use egui_winit::egui::{ + self, vec2, FontSelection, Rect, Response, Sense, TextEdit, Ui, WidgetText, +}; pub use nav_item::NavItem; mod relay_entry; @@ -27,15 +29,22 @@ pub const DROPDOWN_DISTANCE: f32 = 10.0; // ui.label(job.job); // } -pub fn page_header(ui: &mut Ui, title: impl Into, right_aligned_content: impl FnOnce(&mut Ui) -> R) { - ui.vertical(|ui|{ +pub fn page_header( + ui: &mut Ui, + title: impl Into, + right_aligned_content: impl FnOnce(&mut Ui) -> R, +) { + ui.vertical(|ui| { ui.add_space(10.0); ui.horizontal(|ui| { ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| { ui.add_space(2.0); ui.heading(title); }); - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), right_aligned_content); + ui.with_layout( + egui::Layout::right_to_left(egui::Align::Center), + right_aligned_content, + ); }); ui.add_space(10.0); }); diff --git a/gossip-bin/src/ui/widgets/modal_popup.rs b/gossip-bin/src/ui/widgets/modal_popup.rs index e64ff4a9..a5582807 100644 --- a/gossip-bin/src/ui/widgets/modal_popup.rs +++ b/gossip-bin/src/ui/widgets/modal_popup.rs @@ -1,12 +1,11 @@ -use egui_winit::egui::{Ui, InnerResponse, self}; -use eframe::epaint::{Color32}; - +use eframe::epaint::Color32; +use egui_winit::egui::{self, InnerResponse, Ui}; pub fn modal_popup( ui: &mut Ui, dlg_size: egui::Vec2, - content: impl FnOnce(&mut Ui)) -> InnerResponse { - + content: impl FnOnce(&mut Ui), +) -> InnerResponse { let content = |ui: &mut Ui| { ui.set_min_size(dlg_size); ui.set_max_size(dlg_size); @@ -19,7 +18,8 @@ pub fn modal_popup( let rect = egui::Rect::from_x_y_ranges(tr.x - 5.0..=tr.x + 5.0, tr.y + 5.0..=tr.y + 15.0); ui.allocate_ui_at_rect(rect, |ui| { ui.add_sized(rect.size(), super::NavItem::new("\u{274C}", false)) - }).inner + }) + .inner }; egui::Area::new("hide-background-area") @@ -40,24 +40,24 @@ pub fn modal_popup( }); let mut frame = egui::Frame::popup(ui.style()); - let area = egui::Area::new("modal-popup") - .movable(false) - .interactable(true) - .order(egui::Order::Foreground) - .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0]); - area.show_open_close_animation( - ui.ctx(), - &frame, - true, // TODO if we never pass false it won't show a close animation - ); - area.show(ui.ctx(), |ui| { - if ui.visuals().dark_mode { - frame.fill = ui.visuals().faint_bg_color; - } else { - frame.fill = Color32::WHITE; - } - frame.rounding = egui::Rounding::same(10.0); - frame.inner_margin = egui::Margin::symmetric(80.0, 40.0); - frame.show(ui, content).inner - }) + let area = egui::Area::new("modal-popup") + .movable(false) + .interactable(true) + .order(egui::Order::Foreground) + .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0]); + area.show_open_close_animation( + ui.ctx(), + &frame, + true, // TODO if we never pass false it won't show a close animation + ); + area.show(ui.ctx(), |ui| { + if ui.visuals().dark_mode { + frame.fill = ui.visuals().faint_bg_color; + } else { + frame.fill = Color32::WHITE; + } + frame.rounding = egui::Rounding::same(10.0); + frame.inner_margin = egui::Margin::symmetric(80.0, 40.0); + frame.show(ui, content).inner + }) }