use crate::route::RouteServices; use crate::services::image_cache::ImageCache; use crate::services::ndb_wrapper::SubWrapper; use egui::{Color32, Image, Pos2, Response, Rounding, Sense, Ui, Vec2, Widget}; use nostrdb::NdbProfile; pub struct Avatar<'a> { image: Option>, sub: Option, size: Option, } impl<'a> Avatar<'a> { pub fn new(img: Image<'a>) -> Self { Self { image: Some(img), sub: None, size: None, } } pub fn new_optional(img: Option>) -> Self { Self { image: img, sub: None, size: None, } } pub fn from_profile(p: Option>, svc: &'a ImageCache) -> Self { let img = p .map_or(None, |f| f.picture().map(|f| svc.load(f))); Self { image: img, sub: None, size: None, } } pub fn pubkey(pk: &[u8; 32], svc: &'a RouteServices<'a>) -> Self { let (p, sub) = svc.ndb.fetch_profile(svc.tx, pk); Self { image: p.and_then(|p| p.picture().and_then(|p| Some(svc.img_cache.load(p)))), sub, size: None, } } pub fn size(mut self, size: f32) -> Self { self.size = Some(size); self } } impl<'a> Widget for Avatar<'a> { fn ui(self, ui: &mut Ui) -> Response { let size_v = self.size.unwrap_or(40.); let size = Vec2::new(size_v, size_v); match self.image { Some(img) => img.fit_to_exact_size(size).rounding(Rounding::same(size_v)).ui(ui), None => { let (response, painter) = ui.allocate_painter(size, Sense::click()); painter.circle_filled(Pos2::new(size_v / 2., size_v / 2.), size_v / 2., Color32::from_rgb(200, 200, 200)); response } } } }