relay.rs (7885B)
1 use crate::relay_pool_manager::{RelayPoolManager, RelayStatus}; 2 use crate::ui::{Preview, PreviewConfig, View}; 3 use egui::{Align, Button, Frame, Layout, Margin, Rgba, RichText, Rounding, Ui, Vec2}; 4 5 use crate::app_style::NotedeckTextStyle; 6 use enostr::RelayPool; 7 8 pub struct RelayView<'a> { 9 manager: RelayPoolManager<'a>, 10 } 11 12 impl View for RelayView<'_> { 13 fn ui(&mut self, ui: &mut egui::Ui) { 14 ui.add_space(24.0); 15 16 ui.horizontal(|ui| { 17 ui.with_layout(Layout::left_to_right(Align::Center), |ui| { 18 ui.label( 19 RichText::new("Relays").text_style(NotedeckTextStyle::Heading2.text_style()), 20 ); 21 }); 22 23 // TODO: implement manually adding relays 24 // ui.with_layout(Layout::right_to_left(Align::Center), |ui| { 25 // if ui.add(add_relay_button()).clicked() { 26 // // TODO: navigate to 'add relay view' 27 // }; 28 // }); 29 }); 30 31 ui.add_space(8.0); 32 33 egui::ScrollArea::vertical() 34 .scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden) 35 .auto_shrink([false; 2]) 36 .show(ui, |ui| { 37 if let Some(indices) = self.show_relays(ui) { 38 self.manager.remove_relays(indices); 39 } 40 }); 41 } 42 } 43 44 impl<'a> RelayView<'a> { 45 pub fn new(manager: RelayPoolManager<'a>) -> Self { 46 RelayView { manager } 47 } 48 49 pub fn panel(&mut self, ui: &mut egui::Ui) { 50 egui::CentralPanel::default().show(ui.ctx(), |ui| self.ui(ui)); 51 } 52 53 /// Show the current relays, and returns the indices of relays the user requested to delete 54 fn show_relays(&'a self, ui: &mut Ui) -> Option<Vec<usize>> { 55 let mut indices_to_remove: Option<Vec<usize>> = None; 56 for (index, relay_info) in self.manager.get_relay_infos().iter().enumerate() { 57 ui.add_space(8.0); 58 ui.vertical_centered_justified(|ui| { 59 relay_frame(ui).show(ui, |ui| { 60 ui.horizontal(|ui| { 61 ui.with_layout(Layout::left_to_right(Align::Center), |ui| { 62 Frame::none() 63 // This frame is needed to add margin because the label will be added to the outer frame first and centered vertically before the connection status is added so the vertical centering isn't accurate. 64 // TODO: remove this hack and actually center the url & status at the same time 65 .inner_margin(Margin::symmetric(0.0, 4.0)) 66 .show(ui, |ui| { 67 egui::ScrollArea::horizontal() 68 .id_salt(index) 69 .max_width( 70 ui.max_rect().width() 71 - get_right_side_width(relay_info.status), 72 ) // TODO: refactor to dynamically check the size of the 'right to left' portion and set the max width to be the screen width minus padding minus 'right to left' width 73 .show(ui, |ui| { 74 ui.label( 75 RichText::new(relay_info.relay_url) 76 .text_style( 77 NotedeckTextStyle::Monospace.text_style(), 78 ) 79 .color( 80 ui.style() 81 .visuals 82 .noninteractive() 83 .fg_stroke 84 .color, 85 ), 86 ); 87 }); 88 }); 89 }); 90 91 ui.with_layout(Layout::right_to_left(Align::Center), |ui| { 92 if ui.add(delete_button(ui.visuals().dark_mode)).clicked() { 93 indices_to_remove.get_or_insert_with(Vec::new).push(index); 94 }; 95 96 show_connection_status(ui, relay_info.status); 97 }); 98 }); 99 }); 100 }); 101 } 102 103 indices_to_remove 104 } 105 } 106 107 fn get_right_side_width(status: &RelayStatus) -> f32 { 108 match status { 109 RelayStatus::Connected => 150.0, 110 RelayStatus::Connecting => 160.0, 111 RelayStatus::Disconnected => 175.0, 112 } 113 } 114 115 #[allow(unused)] 116 fn add_relay_button() -> egui::Button<'static> { 117 Button::new("+ Add relay").min_size(Vec2::new(0.0, 32.0)) 118 } 119 120 fn delete_button(_dark_mode: bool) -> egui::Button<'static> { 121 /* 122 let img_data = if dark_mode { 123 egui::include_image!("../../assets/icons/delete_icon_4x.png") 124 } else { 125 // TODO: use light delete icon 126 egui::include_image!("../../assets/icons/delete_icon_4x.png") 127 }; 128 */ 129 let img_data = egui::include_image!("../../assets/icons/delete_icon_4x.png"); 130 131 egui::Button::image(egui::Image::new(img_data).max_width(10.0)).frame(false) 132 } 133 134 fn relay_frame(ui: &mut Ui) -> Frame { 135 Frame::none() 136 .inner_margin(Margin::same(8.0)) 137 .rounding(ui.style().noninteractive().rounding) 138 .stroke(ui.style().visuals.noninteractive().bg_stroke) 139 } 140 141 fn show_connection_status(ui: &mut Ui, status: &RelayStatus) { 142 let fg_color = match status { 143 RelayStatus::Connected => ui.visuals().selection.bg_fill, 144 RelayStatus::Connecting => ui.visuals().warn_fg_color, 145 RelayStatus::Disconnected => ui.visuals().error_fg_color, 146 }; 147 let bg_color = egui::lerp(Rgba::from(fg_color)..=Rgba::BLACK, 0.8).into(); 148 149 let label_text = match status { 150 RelayStatus::Connected => "Connected", 151 RelayStatus::Connecting => "Connecting...", 152 RelayStatus::Disconnected => "Not Connected", 153 }; 154 155 let frame = Frame::none() 156 .rounding(Rounding::same(100.0)) 157 .fill(bg_color) 158 .inner_margin(Margin::symmetric(12.0, 4.0)); 159 160 frame.show(ui, |ui| { 161 ui.label(RichText::new(label_text).color(fg_color)); 162 ui.add(get_connection_icon(status)); 163 }); 164 } 165 166 fn get_connection_icon(status: &RelayStatus) -> egui::Image<'static> { 167 let img_data = match status { 168 RelayStatus::Connected => egui::include_image!("../../assets/icons/connected_icon_4x.png"), 169 RelayStatus::Connecting => { 170 egui::include_image!("../../assets/icons/connecting_icon_4x.png") 171 } 172 RelayStatus::Disconnected => { 173 egui::include_image!("../../assets/icons/disconnected_icon_4x.png") 174 } 175 }; 176 177 egui::Image::new(img_data) 178 } 179 180 // PREVIEWS 181 182 mod preview { 183 use super::*; 184 use crate::test_data::sample_pool; 185 186 pub struct RelayViewPreview { 187 pool: RelayPool, 188 } 189 190 impl RelayViewPreview { 191 fn new() -> Self { 192 RelayViewPreview { 193 pool: sample_pool(), 194 } 195 } 196 } 197 198 impl View for RelayViewPreview { 199 fn ui(&mut self, ui: &mut egui::Ui) { 200 self.pool.try_recv(); 201 RelayView::new(RelayPoolManager::new(&mut self.pool)).ui(ui); 202 } 203 } 204 205 impl Preview for RelayView<'_> { 206 type Prev = RelayViewPreview; 207 208 fn preview(_cfg: PreviewConfig) -> Self::Prev { 209 RelayViewPreview::new() 210 } 211 } 212 }