commit 2edba9942ca1de00ca0945b613f38a841afb0f49
parent 2f6f92e62c9e51e027b1f4d681cb20e8c92383ea
Author: William Casarin <jb55@jb55.com>
Date: Sun, 21 Apr 2024 15:00:25 -0700
ui: add banners to profile previews
profile previews still need lots of work, but this was a challenge to
get an aspectRatio: fill mechanism for images which the banner takes
advantage of.
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
2 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/src/ui/note/contents.rs b/src/ui/note/contents.rs
@@ -139,6 +139,7 @@ fn render_note_contents(
if let Some(rec) = profile.as_ref() {
resp.on_hover_ui_at_pointer(|ui| {
egui::Frame::default().show(ui, |ui| {
+ ui.set_max_width(300.0);
ui.add(ui::ProfilePreview::new(rec));
});
});
diff --git a/src/ui/profile/preview.rs b/src/ui/profile/preview.rs
@@ -1,25 +1,82 @@
+use crate::app_style::NotedeckTextStyle;
+use crate::images;
+use egui::load::TexturePoll;
+use egui::{RichText, Sense};
+use egui_extras::Size;
use nostrdb::ProfileRecord;
pub struct ProfilePreview<'a> {
profile: &'a ProfileRecord<'a>,
+ banner_height: Size,
}
impl<'a> ProfilePreview<'a> {
pub fn new(profile: &'a ProfileRecord<'a>) -> Self {
- ProfilePreview { profile }
+ let banner_height = Size::exact(80.0);
+ ProfilePreview {
+ profile,
+ banner_height,
+ }
+ }
+
+ pub fn banner_height(&mut self, size: Size) {
+ self.banner_height = size;
+ }
+
+ fn banner_texture(
+ ui: &mut egui::Ui,
+ profile: &ProfileRecord<'_>,
+ ) -> Option<egui::load::SizedTexture> {
+ // TODO: cache banner
+ let banner = profile.record().profile().and_then(|p| p.banner());
+
+ if let Some(banner) = banner {
+ let texture_load_res =
+ egui::Image::new(banner).load_for_size(ui.ctx(), ui.available_size());
+ if let Ok(texture_poll) = texture_load_res {
+ match texture_poll {
+ TexturePoll::Pending { .. } => {}
+ TexturePoll::Ready { texture, .. } => return Some(texture),
+ }
+ }
+ }
+
+ None
+ }
+
+ fn banner(ui: &mut egui::Ui, profile: &ProfileRecord<'_>) -> egui::Response {
+ if let Some(texture) = Self::banner_texture(ui, profile) {
+ images::aspect_fill(
+ ui,
+ Sense::hover(),
+ texture.id,
+ texture.size.x / texture.size.y,
+ )
+ } else {
+ // TODO: default banner texture
+ ui.label("")
+ }
+ }
+
+ fn body(ui: &mut egui::Ui, profile: &ProfileRecord<'_>) -> egui::Response {
+ let name = if let Some(name) = crate::profile::get_profile_name(profile) {
+ name
+ } else {
+ "nostrich"
+ };
+
+ ui.label(RichText::new(name).text_style(NotedeckTextStyle::Heading3.text_style()))
}
}
impl<'a> egui::Widget for ProfilePreview<'a> {
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
- ui.horizontal(|ui| {
- ui.label("Profile");
- let name = if let Some(name) = crate::profile::get_profile_name(self.profile) {
- name
- } else {
- "nostrich"
- };
- ui.label(name);
+ ui.vertical(|ui| {
+ ui.add_sized([ui.available_size().x, 80.0], |ui: &mut egui::Ui| {
+ ProfilePreview::banner(ui, self.profile)
+ });
+
+ ProfilePreview::body(ui, self.profile);
})
.response
}