profiles: introduce DisplayNames

This is exactly the same as the DisplayName enum in Damus iOS. Due to
the various inconsistencies in `name` and `display_name` between
clients, we have to generalize DisplayName into two variants: one name
or two names.

If we have two names, we treat it in the standard way of display_name is
the real name, and `name` is the username.

If only one is set, then it is considered both the username and "real name".

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2024-04-21 15:55:47 -07:00
parent 2edba9942c
commit 893fd582dc
4 changed files with 59 additions and 22 deletions

View File

@@ -31,6 +31,7 @@ mod test_utils;
pub use app::Damus; pub use app::Damus;
pub use error::Error; pub use error::Error;
pub use profile::DisplayName;
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
use winit::platform::android::EventLoopBuilderExtAndroid; use winit::platform::android::EventLoopBuilderExtAndroid;

View File

@@ -1,17 +1,39 @@
use nostrdb::ProfileRecord; use nostrdb::ProfileRecord;
pub fn get_profile_name<'a>(record: &'a ProfileRecord) -> Option<&'a str> { pub enum DisplayName<'a> {
let profile = record.record().profile()?; One(&'a str),
let display_name = profile.display_name();
let name = profile.name();
if display_name.is_some() && display_name.unwrap() != "" { Both {
return display_name; username: &'a str,
} display_name: &'a str,
},
if name.is_some() && name.unwrap() != "" { }
return name;
} impl<'a> DisplayName<'a> {
pub fn username(&self) -> &'a str {
None match self {
Self::One(n) => n,
Self::Both { username, .. } => username,
}
}
}
fn is_empty(s: &str) -> bool {
s.chars().all(|c| c.is_whitespace())
}
pub fn get_profile_name<'a>(record: &'a ProfileRecord) -> Option<DisplayName<'a>> {
let profile = record.record().profile()?;
let display_name = profile.display_name().filter(|n| !is_empty(n));
let name = profile.name().filter(|n| !is_empty(n));
match (display_name, name) {
(None, None) => None,
(Some(disp), None) => Some(DisplayName::One(disp)),
(None, Some(username)) => Some(DisplayName::One(username)),
(Some(display_name), Some(username)) => Some(DisplayName::Both {
display_name,
username,
}),
}
} }

View File

@@ -129,19 +129,17 @@ fn render_note_contents(
let name: String = if let Some(name) = let name: String = if let Some(name) =
profile.as_ref().and_then(crate::profile::get_profile_name) profile.as_ref().and_then(crate::profile::get_profile_name)
{ {
format!("@{}", name) format!("@{}", name.username())
} else { } else {
"@nostrich".to_string() "??".to_string()
}; };
let resp = ui.colored_label(colors::PURPLE, &name); let resp = ui.colored_label(colors::PURPLE, &name);
if let Some(rec) = profile.as_ref() { if let Some(rec) = profile.as_ref() {
resp.on_hover_ui_at_pointer(|ui| { resp.on_hover_ui_at_pointer(|ui| {
egui::Frame::default().show(ui, |ui| { ui.set_max_width(300.0);
ui.set_max_width(300.0); ui.add(ui::ProfilePreview::new(rec));
ui.add(ui::ProfilePreview::new(rec));
});
}); });
} }
}); });

View File

@@ -1,5 +1,6 @@
use crate::app_style::NotedeckTextStyle; use crate::app_style::NotedeckTextStyle;
use crate::images; use crate::images;
use crate::DisplayName;
use egui::load::TexturePoll; use egui::load::TexturePoll;
use egui::{RichText, Sense}; use egui::{RichText, Sense};
use egui_extras::Size; use egui_extras::Size;
@@ -58,14 +59,29 @@ impl<'a> ProfilePreview<'a> {
} }
} }
fn body(ui: &mut egui::Ui, profile: &ProfileRecord<'_>) -> egui::Response { fn body(ui: &mut egui::Ui, profile: &ProfileRecord<'_>) {
let name = if let Some(name) = crate::profile::get_profile_name(profile) { let name = if let Some(name) = crate::profile::get_profile_name(profile) {
name name
} else { } else {
"nostrich" DisplayName::One("??")
}; };
ui.label(RichText::new(name).text_style(NotedeckTextStyle::Heading3.text_style())) match name {
DisplayName::One(n) => {
ui.label(RichText::new(n).text_style(NotedeckTextStyle::Heading3.text_style()));
}
DisplayName::Both {
display_name,
username,
} => {
ui.label(
RichText::new(display_name)
.text_style(NotedeckTextStyle::Heading3.text_style()),
);
ui.label(RichText::new(format!("@{}", username)));
}
}
} }
} }