preview.rs (5658B)
1 use crate::ui::ProfilePic; 2 use crate::NostrName; 3 use egui::{Frame, Label, RichText, Widget}; 4 use egui_extras::Size; 5 use nostrdb::ProfileRecord; 6 7 use notedeck::{Images, NotedeckTextStyle, UserAccount}; 8 9 use super::{about_section_widget, banner, display_name_widget, get_display_name, get_profile_url}; 10 11 pub struct ProfilePreview<'a, 'cache> { 12 profile: &'a ProfileRecord<'a>, 13 cache: &'cache mut Images, 14 banner_height: Size, 15 } 16 17 impl<'a, 'cache> ProfilePreview<'a, 'cache> { 18 pub fn new(profile: &'a ProfileRecord<'a>, cache: &'cache mut Images) -> Self { 19 let banner_height = Size::exact(80.0); 20 ProfilePreview { 21 profile, 22 cache, 23 banner_height, 24 } 25 } 26 27 pub fn banner_height(&mut self, size: Size) { 28 self.banner_height = size; 29 } 30 31 fn body(self, ui: &mut egui::Ui) { 32 let padding = 12.0; 33 crate::ui::padding(padding, ui, |ui| { 34 let mut pfp_rect = ui.available_rect_before_wrap(); 35 let size = 80.0; 36 pfp_rect.set_width(size); 37 pfp_rect.set_height(size); 38 let pfp_rect = pfp_rect.translate(egui::vec2(0.0, -(padding + 2.0 + (size / 2.0)))); 39 40 ui.put( 41 pfp_rect, 42 ProfilePic::new(self.cache, get_profile_url(Some(self.profile))) 43 .size(size) 44 .border(ProfilePic::border_stroke(ui)), 45 ); 46 ui.add(display_name_widget( 47 get_display_name(Some(self.profile)), 48 false, 49 )); 50 ui.add(about_section_widget(self.profile)); 51 }); 52 } 53 } 54 55 impl egui::Widget for ProfilePreview<'_, '_> { 56 fn ui(self, ui: &mut egui::Ui) -> egui::Response { 57 ui.vertical(|ui| { 58 banner( 59 ui, 60 self.profile.record().profile().and_then(|p| p.banner()), 61 80.0, 62 ); 63 64 self.body(ui); 65 }) 66 .response 67 } 68 } 69 70 pub struct SimpleProfilePreview<'a, 'cache> { 71 profile: Option<&'a ProfileRecord<'a>>, 72 cache: &'cache mut Images, 73 is_nsec: bool, 74 } 75 76 impl<'a, 'cache> SimpleProfilePreview<'a, 'cache> { 77 pub fn new( 78 profile: Option<&'a ProfileRecord<'a>>, 79 cache: &'cache mut Images, 80 is_nsec: bool, 81 ) -> Self { 82 SimpleProfilePreview { 83 profile, 84 cache, 85 is_nsec, 86 } 87 } 88 } 89 90 impl egui::Widget for SimpleProfilePreview<'_, '_> { 91 fn ui(self, ui: &mut egui::Ui) -> egui::Response { 92 Frame::none() 93 .show(ui, |ui| { 94 ui.add(ProfilePic::new(self.cache, get_profile_url(self.profile)).size(48.0)); 95 ui.vertical(|ui| { 96 ui.add(display_name_widget(get_display_name(self.profile), true)); 97 if !self.is_nsec { 98 ui.add( 99 Label::new( 100 RichText::new("Read only") 101 .size(notedeck::fonts::get_font_size( 102 ui.ctx(), 103 &NotedeckTextStyle::Tiny, 104 )) 105 .color(ui.visuals().warn_fg_color), 106 ) 107 .selectable(false), 108 ); 109 } 110 }); 111 }) 112 .response 113 } 114 } 115 116 mod previews { 117 use super::*; 118 use crate::test_data::test_profile_record; 119 use crate::ui::{Preview, PreviewConfig}; 120 use notedeck::{App, AppContext}; 121 122 pub struct ProfilePreviewPreview<'a> { 123 profile: ProfileRecord<'a>, 124 } 125 126 impl ProfilePreviewPreview<'_> { 127 pub fn new() -> Self { 128 let profile = test_profile_record(); 129 ProfilePreviewPreview { profile } 130 } 131 } 132 133 impl Default for ProfilePreviewPreview<'_> { 134 fn default() -> Self { 135 ProfilePreviewPreview::new() 136 } 137 } 138 139 impl App for ProfilePreviewPreview<'_> { 140 fn update(&mut self, app: &mut AppContext<'_>, ui: &mut egui::Ui) { 141 ProfilePreview::new(&self.profile, app.img_cache).ui(ui); 142 } 143 } 144 145 impl<'a> Preview for ProfilePreview<'a, '_> { 146 /// A preview of the profile preview :D 147 type Prev = ProfilePreviewPreview<'a>; 148 149 fn preview(_cfg: PreviewConfig) -> Self::Prev { 150 ProfilePreviewPreview::new() 151 } 152 } 153 } 154 155 pub fn get_profile_url_owned(profile: Option<ProfileRecord<'_>>) -> &str { 156 if let Some(url) = profile.and_then(|pr| pr.record().profile().and_then(|p| p.picture())) { 157 url 158 } else { 159 ProfilePic::no_pfp_url() 160 } 161 } 162 163 pub fn get_account_url<'a>( 164 txn: &'a nostrdb::Transaction, 165 ndb: &nostrdb::Ndb, 166 account: Option<&UserAccount>, 167 ) -> &'a str { 168 if let Some(selected_account) = account { 169 if let Ok(profile) = ndb.get_profile_by_pubkey(txn, selected_account.pubkey.bytes()) { 170 get_profile_url_owned(Some(profile)) 171 } else { 172 get_profile_url_owned(None) 173 } 174 } else { 175 get_profile_url(None) 176 } 177 } 178 179 pub fn one_line_display_name_widget<'a>( 180 visuals: &egui::Visuals, 181 display_name: NostrName<'a>, 182 style: NotedeckTextStyle, 183 ) -> impl egui::Widget + 'a { 184 let text_style = style.text_style(); 185 let color = visuals.noninteractive().fg_stroke.color; 186 187 move |ui: &mut egui::Ui| -> egui::Response { 188 ui.label( 189 RichText::new(display_name.name()) 190 .text_style(text_style) 191 .color(color), 192 ) 193 } 194 }