notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

relay_view.rs (7060B)


      1 use crate::relay_pool_manager::{RelayPoolManager, RelayStatus};
      2 use egui::{Align, Button, Frame, Layout, Margin, Rgba, RichText, Rounding, Ui, Vec2};
      3 
      4 use crate::app_style::NotedeckTextStyle;
      5 
      6 pub struct RelayView<'a> {
      7     ctx: &'a egui::Context,
      8     manager: RelayPoolManager<'a>,
      9 }
     10 
     11 impl<'a> RelayView<'a> {
     12     pub fn new(ctx: &'a egui::Context, manager: RelayPoolManager<'a>) -> Self {
     13         RelayView { ctx, manager }
     14     }
     15 
     16     pub fn panel(&'a mut self) {
     17         let mut indices_to_remove: Option<Vec<usize>> = None;
     18 
     19         egui::CentralPanel::default().show(self.ctx, |ui| {
     20             ui.add_space(24.0);
     21 
     22             ui.horizontal(|ui| {
     23                 ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
     24                     ui.label(
     25                         RichText::new("Relays")
     26                             .text_style(NotedeckTextStyle::Heading2.text_style()),
     27                     );
     28                 });
     29 
     30                 ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
     31                     if ui.add(add_relay_button()).clicked() {
     32                         // TODO: navigate to 'add relay view'
     33                     };
     34                 });
     35             });
     36 
     37             ui.add_space(8.0);
     38 
     39             egui::ScrollArea::vertical()
     40                 .scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden)
     41                 .auto_shrink([false; 2])
     42                 .show(ui, |ui| {
     43                     indices_to_remove = self.show_relays(ui);
     44                 });
     45         });
     46 
     47         if let Some(indices) = indices_to_remove {
     48             self.manager.remove_relays(indices);
     49         }
     50     }
     51 
     52     /// Show the current relays, and returns the indices of relays the user requested to delete
     53     fn show_relays(&'a self, ui: &mut Ui) -> Option<Vec<usize>> {
     54         let mut indices_to_remove: Option<Vec<usize>> = None;
     55         for (index, relay_info) in self.manager.get_relay_infos().iter().enumerate() {
     56             ui.add_space(8.0);
     57             ui.vertical_centered_justified(|ui| {
     58                 relay_frame(ui).show(ui, |ui| {
     59                     ui.horizontal(|ui| {
     60                         ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
     61                             Frame::none()
     62                                 // 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.
     63                                 // TODO: remove this hack and actually center the url & status at the same time
     64                                 .inner_margin(Margin::symmetric(0.0, 4.0))
     65                                 .show(ui, |ui| {
     66                                     egui::ScrollArea::horizontal()
     67                                         .id_source(index)
     68                                         .max_width(
     69                                             ui.max_rect().width()
     70                                                 - get_right_side_width(relay_info.status),
     71                                         ) // 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
     72                                         .show(ui, |ui| {
     73                                             ui.label(
     74                                                 RichText::new(relay_info.relay_url)
     75                                                     .text_style(
     76                                                         NotedeckTextStyle::Monospace.text_style(),
     77                                                     )
     78                                                     .color(
     79                                                         ui.style()
     80                                                             .visuals
     81                                                             .noninteractive()
     82                                                             .fg_stroke
     83                                                             .color,
     84                                                     ),
     85                                             );
     86                                         });
     87                                 });
     88                         });
     89 
     90                         ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
     91                             if ui.add(delete_button(ui.visuals().dark_mode)).clicked() {
     92                                 indices_to_remove.get_or_insert_with(Vec::new).push(index);
     93                             };
     94 
     95                             show_connection_status(ui, relay_info.status);
     96                         });
     97                     });
     98                 });
     99             });
    100         }
    101 
    102         indices_to_remove
    103     }
    104 }
    105 
    106 fn get_right_side_width(status: &RelayStatus) -> f32 {
    107     match status {
    108         RelayStatus::Connected => 150.0,
    109         RelayStatus::Connecting => 160.0,
    110         RelayStatus::Disconnected => 175.0,
    111     }
    112 }
    113 
    114 fn add_relay_button() -> egui::Button<'static> {
    115     Button::new("+ Add relay").min_size(Vec2::new(0.0, 32.0))
    116 }
    117 
    118 fn delete_button(dark_mode: bool) -> egui::Button<'static> {
    119     let img_data = if dark_mode {
    120         egui::include_image!("../assets/icons/delete_icon_4x.png")
    121     } else {
    122         // TODO: use light delete icon
    123         egui::include_image!("../assets/icons/delete_icon_4x.png")
    124     };
    125 
    126     egui::Button::image(egui::Image::new(img_data).max_width(10.0)).frame(false)
    127 }
    128 
    129 fn relay_frame(ui: &mut Ui) -> Frame {
    130     Frame::none()
    131         .inner_margin(Margin::same(8.0))
    132         .rounding(ui.style().noninteractive().rounding)
    133         .stroke(ui.style().visuals.noninteractive().bg_stroke)
    134 }
    135 
    136 fn show_connection_status(ui: &mut Ui, status: &RelayStatus) {
    137     let fg_color = match status {
    138         RelayStatus::Connected => ui.visuals().selection.bg_fill,
    139         RelayStatus::Connecting => ui.visuals().warn_fg_color,
    140         RelayStatus::Disconnected => ui.visuals().error_fg_color,
    141     };
    142     let bg_color = egui::lerp(Rgba::from(fg_color)..=Rgba::BLACK, 0.8).into();
    143 
    144     let label_text = match status {
    145         RelayStatus::Connected => "Connected",
    146         RelayStatus::Connecting => "Connecting...",
    147         RelayStatus::Disconnected => "Not Connected",
    148     };
    149 
    150     let frame = Frame::none()
    151         .rounding(Rounding::same(100.0))
    152         .fill(bg_color)
    153         .inner_margin(Margin::symmetric(12.0, 4.0));
    154 
    155     frame.show(ui, |ui| {
    156         ui.label(RichText::new(label_text).color(fg_color));
    157         ui.add(get_connection_icon(status));
    158     });
    159 }
    160 
    161 fn get_connection_icon(status: &RelayStatus) -> egui::Image<'static> {
    162     let img_data = match status {
    163         RelayStatus::Connected => egui::include_image!("../assets/icons/connected_icon_4x.png"),
    164         RelayStatus::Connecting => egui::include_image!("../assets/icons/connecting_icon_4x.png"),
    165         RelayStatus::Disconnected => {
    166             egui::include_image!("../assets/icons/disconnected_icon_4x.png")
    167         }
    168     };
    169 
    170     egui::Image::new(img_data)
    171 }