notedeck

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

commit 2d566cc637a4fd1f14cdc698e54bcba2f20a2387
parent 51c25b88cceff5f8f45fa69acae1693356db6c3b
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 19 Apr 2024 21:53:47 -0700

ui: move RelayView into ui module

Trying to keep all UI stuff in there

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Msrc/lib.rs | 1-
Dsrc/relay_view.rs | 205-------------------------------------------------------------------------------
Msrc/ui/mod.rs | 2++
Asrc/ui/relay.rs | 207+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 209 insertions(+), 206 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs @@ -18,7 +18,6 @@ pub mod login_manager; mod notecache; mod profile; pub mod relay_pool_manager; -pub mod relay_view; mod result; mod test_data; mod time; diff --git a/src/relay_view.rs b/src/relay_view.rs @@ -1,205 +0,0 @@ -use crate::relay_pool_manager::{RelayPoolManager, RelayStatus}; -use crate::ui::{Preview, View}; -use egui::{Align, Button, Frame, Layout, Margin, Rgba, RichText, Rounding, Ui, Vec2}; - -use crate::app_style::NotedeckTextStyle; -use enostr::RelayPool; - -pub struct RelayView<'a> { - manager: RelayPoolManager<'a>, -} - -impl<'a> View for RelayView<'a> { - fn ui(&mut self, ui: &mut egui::Ui) { - ui.add_space(24.0); - - ui.horizontal(|ui| { - ui.with_layout(Layout::left_to_right(Align::Center), |ui| { - ui.label( - RichText::new("Relays").text_style(NotedeckTextStyle::Heading2.text_style()), - ); - }); - - ui.with_layout(Layout::right_to_left(Align::Center), |ui| { - if ui.add(add_relay_button()).clicked() { - // TODO: navigate to 'add relay view' - }; - }); - }); - - ui.add_space(8.0); - - egui::ScrollArea::vertical() - .scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden) - .auto_shrink([false; 2]) - .show(ui, |ui| { - if let Some(indices) = self.show_relays(ui) { - self.manager.remove_relays(indices); - } - }); - } -} - -impl<'a> RelayView<'a> { - pub fn new(manager: RelayPoolManager<'a>) -> Self { - RelayView { manager } - } - - pub fn panel(&mut self, ui: &mut egui::Ui) { - egui::CentralPanel::default().show(ui.ctx(), |ui| self.ui(ui)); - } - - /// Show the current relays, and returns the indices of relays the user requested to delete - fn show_relays(&'a self, ui: &mut Ui) -> Option<Vec<usize>> { - let mut indices_to_remove: Option<Vec<usize>> = None; - for (index, relay_info) in self.manager.get_relay_infos().iter().enumerate() { - ui.add_space(8.0); - ui.vertical_centered_justified(|ui| { - relay_frame(ui).show(ui, |ui| { - ui.horizontal(|ui| { - ui.with_layout(Layout::left_to_right(Align::Center), |ui| { - Frame::none() - // 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. - // TODO: remove this hack and actually center the url & status at the same time - .inner_margin(Margin::symmetric(0.0, 4.0)) - .show(ui, |ui| { - egui::ScrollArea::horizontal() - .id_source(index) - .max_width( - ui.max_rect().width() - - get_right_side_width(relay_info.status), - ) // 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 - .show(ui, |ui| { - ui.label( - RichText::new(relay_info.relay_url) - .text_style( - NotedeckTextStyle::Monospace.text_style(), - ) - .color( - ui.style() - .visuals - .noninteractive() - .fg_stroke - .color, - ), - ); - }); - }); - }); - - ui.with_layout(Layout::right_to_left(Align::Center), |ui| { - if ui.add(delete_button(ui.visuals().dark_mode)).clicked() { - indices_to_remove.get_or_insert_with(Vec::new).push(index); - }; - - show_connection_status(ui, relay_info.status); - }); - }); - }); - }); - } - - indices_to_remove - } -} - -fn get_right_side_width(status: &RelayStatus) -> f32 { - match status { - RelayStatus::Connected => 150.0, - RelayStatus::Connecting => 160.0, - RelayStatus::Disconnected => 175.0, - } -} - -fn add_relay_button() -> egui::Button<'static> { - Button::new("+ Add relay").min_size(Vec2::new(0.0, 32.0)) -} - -fn delete_button(dark_mode: bool) -> egui::Button<'static> { - let img_data = if dark_mode { - egui::include_image!("../assets/icons/delete_icon_4x.png") - } else { - // TODO: use light delete icon - egui::include_image!("../assets/icons/delete_icon_4x.png") - }; - - egui::Button::image(egui::Image::new(img_data).max_width(10.0)).frame(false) -} - -fn relay_frame(ui: &mut Ui) -> Frame { - Frame::none() - .inner_margin(Margin::same(8.0)) - .rounding(ui.style().noninteractive().rounding) - .stroke(ui.style().visuals.noninteractive().bg_stroke) -} - -fn show_connection_status(ui: &mut Ui, status: &RelayStatus) { - let fg_color = match status { - RelayStatus::Connected => ui.visuals().selection.bg_fill, - RelayStatus::Connecting => ui.visuals().warn_fg_color, - RelayStatus::Disconnected => ui.visuals().error_fg_color, - }; - let bg_color = egui::lerp(Rgba::from(fg_color)..=Rgba::BLACK, 0.8).into(); - - let label_text = match status { - RelayStatus::Connected => "Connected", - RelayStatus::Connecting => "Connecting...", - RelayStatus::Disconnected => "Not Connected", - }; - - let frame = Frame::none() - .rounding(Rounding::same(100.0)) - .fill(bg_color) - .inner_margin(Margin::symmetric(12.0, 4.0)); - - frame.show(ui, |ui| { - ui.label(RichText::new(label_text).color(fg_color)); - ui.add(get_connection_icon(status)); - }); -} - -fn get_connection_icon(status: &RelayStatus) -> egui::Image<'static> { - let img_data = match status { - RelayStatus::Connected => egui::include_image!("../assets/icons/connected_icon_4x.png"), - RelayStatus::Connecting => egui::include_image!("../assets/icons/connecting_icon_4x.png"), - RelayStatus::Disconnected => { - egui::include_image!("../assets/icons/disconnected_icon_4x.png") - } - }; - - egui::Image::new(img_data) -} - -// PREVIEWS - -mod preview { - use super::*; - use crate::test_data::sample_pool; - - pub struct RelayViewPreview { - pool: RelayPool, - } - - impl RelayViewPreview { - fn new() -> Self { - RelayViewPreview { - pool: sample_pool(), - } - } - } - - impl View for RelayViewPreview { - fn ui(&mut self, ui: &mut egui::Ui) { - self.pool.try_recv(); - RelayView::new(RelayPoolManager::new(&mut self.pool)).ui(ui) - } - } - - impl<'a> Preview for RelayView<'a> { - type Prev = RelayViewPreview; - - fn preview() -> Self::Prev { - RelayViewPreview::new() - } - } -} diff --git a/src/ui/mod.rs b/src/ui/mod.rs @@ -1,9 +1,11 @@ pub mod note; pub mod preview; +pub mod relay; pub mod username; pub use note::Note; pub use preview::{Preview, PreviewApp}; +pub use relay::RelayView; pub use username::Username; use egui::Margin; diff --git a/src/ui/relay.rs b/src/ui/relay.rs @@ -0,0 +1,207 @@ +use crate::relay_pool_manager::{RelayPoolManager, RelayStatus}; +use crate::ui::{Preview, View}; +use egui::{Align, Button, Frame, Layout, Margin, Rgba, RichText, Rounding, Ui, Vec2}; + +use crate::app_style::NotedeckTextStyle; +use enostr::RelayPool; + +pub struct RelayView<'a> { + manager: RelayPoolManager<'a>, +} + +impl<'a> View for RelayView<'a> { + fn ui(&mut self, ui: &mut egui::Ui) { + ui.add_space(24.0); + + ui.horizontal(|ui| { + ui.with_layout(Layout::left_to_right(Align::Center), |ui| { + ui.label( + RichText::new("Relays").text_style(NotedeckTextStyle::Heading2.text_style()), + ); + }); + + ui.with_layout(Layout::right_to_left(Align::Center), |ui| { + if ui.add(add_relay_button()).clicked() { + // TODO: navigate to 'add relay view' + }; + }); + }); + + ui.add_space(8.0); + + egui::ScrollArea::vertical() + .scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden) + .auto_shrink([false; 2]) + .show(ui, |ui| { + if let Some(indices) = self.show_relays(ui) { + self.manager.remove_relays(indices); + } + }); + } +} + +impl<'a> RelayView<'a> { + pub fn new(manager: RelayPoolManager<'a>) -> Self { + RelayView { manager } + } + + pub fn panel(&mut self, ui: &mut egui::Ui) { + egui::CentralPanel::default().show(ui.ctx(), |ui| self.ui(ui)); + } + + /// Show the current relays, and returns the indices of relays the user requested to delete + fn show_relays(&'a self, ui: &mut Ui) -> Option<Vec<usize>> { + let mut indices_to_remove: Option<Vec<usize>> = None; + for (index, relay_info) in self.manager.get_relay_infos().iter().enumerate() { + ui.add_space(8.0); + ui.vertical_centered_justified(|ui| { + relay_frame(ui).show(ui, |ui| { + ui.horizontal(|ui| { + ui.with_layout(Layout::left_to_right(Align::Center), |ui| { + Frame::none() + // 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. + // TODO: remove this hack and actually center the url & status at the same time + .inner_margin(Margin::symmetric(0.0, 4.0)) + .show(ui, |ui| { + egui::ScrollArea::horizontal() + .id_source(index) + .max_width( + ui.max_rect().width() + - get_right_side_width(relay_info.status), + ) // 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 + .show(ui, |ui| { + ui.label( + RichText::new(relay_info.relay_url) + .text_style( + NotedeckTextStyle::Monospace.text_style(), + ) + .color( + ui.style() + .visuals + .noninteractive() + .fg_stroke + .color, + ), + ); + }); + }); + }); + + ui.with_layout(Layout::right_to_left(Align::Center), |ui| { + if ui.add(delete_button(ui.visuals().dark_mode)).clicked() { + indices_to_remove.get_or_insert_with(Vec::new).push(index); + }; + + show_connection_status(ui, relay_info.status); + }); + }); + }); + }); + } + + indices_to_remove + } +} + +fn get_right_side_width(status: &RelayStatus) -> f32 { + match status { + RelayStatus::Connected => 150.0, + RelayStatus::Connecting => 160.0, + RelayStatus::Disconnected => 175.0, + } +} + +fn add_relay_button() -> egui::Button<'static> { + Button::new("+ Add relay").min_size(Vec2::new(0.0, 32.0)) +} + +fn delete_button(dark_mode: bool) -> egui::Button<'static> { + let img_data = if dark_mode { + egui::include_image!("../../assets/icons/delete_icon_4x.png") + } else { + // TODO: use light delete icon + egui::include_image!("../../assets/icons/delete_icon_4x.png") + }; + + egui::Button::image(egui::Image::new(img_data).max_width(10.0)).frame(false) +} + +fn relay_frame(ui: &mut Ui) -> Frame { + Frame::none() + .inner_margin(Margin::same(8.0)) + .rounding(ui.style().noninteractive().rounding) + .stroke(ui.style().visuals.noninteractive().bg_stroke) +} + +fn show_connection_status(ui: &mut Ui, status: &RelayStatus) { + let fg_color = match status { + RelayStatus::Connected => ui.visuals().selection.bg_fill, + RelayStatus::Connecting => ui.visuals().warn_fg_color, + RelayStatus::Disconnected => ui.visuals().error_fg_color, + }; + let bg_color = egui::lerp(Rgba::from(fg_color)..=Rgba::BLACK, 0.8).into(); + + let label_text = match status { + RelayStatus::Connected => "Connected", + RelayStatus::Connecting => "Connecting...", + RelayStatus::Disconnected => "Not Connected", + }; + + let frame = Frame::none() + .rounding(Rounding::same(100.0)) + .fill(bg_color) + .inner_margin(Margin::symmetric(12.0, 4.0)); + + frame.show(ui, |ui| { + ui.label(RichText::new(label_text).color(fg_color)); + ui.add(get_connection_icon(status)); + }); +} + +fn get_connection_icon(status: &RelayStatus) -> egui::Image<'static> { + let img_data = match status { + RelayStatus::Connected => egui::include_image!("../../assets/icons/connected_icon_4x.png"), + RelayStatus::Connecting => { + egui::include_image!("../../assets/icons/connecting_icon_4x.png") + } + RelayStatus::Disconnected => { + egui::include_image!("../../assets/icons/disconnected_icon_4x.png") + } + }; + + egui::Image::new(img_data) +} + +// PREVIEWS + +mod preview { + use super::*; + use crate::test_data::sample_pool; + + pub struct RelayViewPreview { + pool: RelayPool, + } + + impl RelayViewPreview { + fn new() -> Self { + RelayViewPreview { + pool: sample_pool(), + } + } + } + + impl View for RelayViewPreview { + fn ui(&mut self, ui: &mut egui::Ui) { + self.pool.try_recv(); + RelayView::new(RelayPoolManager::new(&mut self.pool)).ui(ui) + } + } + + impl<'a> Preview for RelayView<'a> { + type Prev = RelayViewPreview; + + fn preview() -> Self::Prev { + RelayViewPreview::new() + } + } +}