Add note wide mode for reposts

This adds a 'wide' note design for note previews. This is a mode
where the note contents does not have padding at the start. This makes
notes previews a bit nicer.

Screenshot: https://cdn.jb55.com/s/84271f386d564c34.png
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin 2024-07-10 09:53:51 -07:00
parent 61bc9d9919
commit af8d7d222c
3 changed files with 114 additions and 47 deletions

View File

@ -92,6 +92,7 @@ fn render_note_preview(
ui::NoteView::new(app, &note) ui::NoteView::new(app, &note)
.actionbar(false) .actionbar(false)
.small_pfp(true) .small_pfp(true)
.wide(true)
.note_previews(false) .note_previews(false)
.show(ui); .show(ui);
}) })

View File

@ -10,7 +10,7 @@ pub use reply::PostReplyView;
use crate::{colors, notecache::CachedNote, ui, ui::View, Damus}; use crate::{colors, notecache::CachedNote, ui, ui::View, Damus};
use egui::{Label, RichText, Sense}; use egui::{Label, RichText, Sense};
use nostrdb::{NoteKey, Transaction}; use nostrdb::{Note, NoteKey, NoteReply, Transaction};
pub struct NoteView<'a> { pub struct NoteView<'a> {
app: &'a mut Damus, app: &'a mut Damus,
@ -29,35 +29,22 @@ impl<'a> View for NoteView<'a> {
} }
} }
fn reply_desc( fn reply_desc(ui: &mut egui::Ui, txn: &Transaction, note_reply: &NoteReply, app: &mut Damus) {
ui: &mut egui::Ui,
txn: &Transaction,
app: &mut Damus,
note_key: NoteKey,
note: &nostrdb::Note<'_>,
) {
#[cfg(feature = "profiling")] #[cfg(feature = "profiling")]
puffin::profile_function!(); puffin::profile_function!();
let note_reply = app
.note_cache_mut()
.cached_note_or_insert_mut(note_key, note)
.reply
.borrow(note.tags());
let reply = if let Some(reply) = note_reply.reply() {
reply
} else {
// not a reply, nothing to do here
return;
};
ui.add(Label::new( ui.add(Label::new(
RichText::new("replying to") RichText::new("replying to")
.size(10.0) .size(10.0)
.color(colors::GRAY_SECONDARY), .color(colors::GRAY_SECONDARY),
)); ));
let reply = if let Some(reply) = note_reply.reply() {
reply
} else {
return;
};
let reply_note = if let Ok(reply_note) = app.ndb.get_note_by_id(txn, reply.id) { let reply_note = if let Ok(reply_note) = app.ndb.get_note_by_id(txn, reply.id) {
reply_note reply_note
} else { } else {
@ -140,6 +127,11 @@ impl<'a> NoteView<'a> {
self self
} }
pub fn wide(mut self, enable: bool) -> Self {
self.options_mut().set_wide(enable);
self
}
pub fn options(&self) -> NoteOptions { pub fn options(&self) -> NoteOptions {
self.flags self.flags
} }
@ -196,15 +188,13 @@ impl<'a> NoteView<'a> {
profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>, profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>,
ui: &mut egui::Ui, ui: &mut egui::Ui,
) { ) {
ui.spacing_mut().item_spacing.x = 16.0; if !self.options().has_wide() {
ui.spacing_mut().item_spacing.x = 16.0;
let pfp_size = if self.options().has_small_pfp() {
ui::ProfilePic::small_size()
} else if self.options().has_medium_pfp() {
ui::ProfilePic::medium_size()
} else { } else {
ui::ProfilePic::default_size() ui.spacing_mut().item_spacing.x = 4.0;
}; }
let pfp_size = self.options().pfp_size();
match profile match profile
.as_ref() .as_ref()
@ -262,6 +252,26 @@ impl<'a> NoteView<'a> {
} }
} }
fn note_header(
ui: &mut egui::Ui,
app: &mut Damus,
note: &Note,
profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>,
) -> egui::Response {
let note_key = note.key().unwrap();
ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 2.0;
ui.add(ui::Username::new(profile.as_ref().ok(), note.pubkey()).abbreviated(20));
let cached_note = app
.note_cache_mut()
.cached_note_or_insert_mut(note_key, note);
render_reltime(ui, cached_note, true);
})
.response
}
fn show_standard(&mut self, ui: &mut egui::Ui) -> NoteResponse { fn show_standard(&mut self, ui: &mut egui::Ui) -> NoteResponse {
#[cfg(feature = "profiling")] #[cfg(feature = "profiling")]
puffin::profile_function!(); puffin::profile_function!();
@ -270,34 +280,69 @@ impl<'a> NoteView<'a> {
let mut note_action: Option<BarAction> = None; let mut note_action: Option<BarAction> = None;
let profile = self.app.ndb.get_profile_by_pubkey(txn, self.note.pubkey()); let profile = self.app.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
if self.options().has_wide() { // wide design
ui.horizontal_centered(|ui| { let response = if self.options().has_wide() {
ui.horizontal(|ui| {
self.pfp(note_key, &profile, ui); self.pfp(note_key, &profile, ui);
});
}
let response = ui let size = ui.available_size();
.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { ui.vertical(|ui| {
ui.add_sized([size.x, self.options().pfp_size()], |ui: &mut egui::Ui| {
ui.horizontal_centered(|ui| {
NoteView::note_header(ui, self.app, self.note, &profile);
})
.response
});
let note_reply = self
.app
.note_cache_mut()
.cached_note_or_insert_mut(note_key, self.note)
.reply
.borrow(self.note.tags());
if note_reply.reply().is_some() {
ui.horizontal(|ui| {
reply_desc(ui, txn, &note_reply, self.app);
});
}
});
});
let resp = ui.add(NoteContents::new(
self.app,
txn,
self.note,
note_key,
self.options(),
));
if self.options().has_actionbar() {
note_action = render_note_actionbar(ui, note_key).inner;
}
resp
} else {
// main design
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
self.pfp(note_key, &profile, ui); self.pfp(note_key, &profile, ui);
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| { ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
NoteView::note_header(ui, self.app, self.note, &profile);
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 2.0; ui.spacing_mut().item_spacing.x = 2.0;
ui.add(
ui::Username::new(profile.as_ref().ok(), self.note.pubkey())
.abbreviated(20),
);
let cached_note = self let note_reply = self
.app .app
.note_cache_mut() .note_cache_mut()
.cached_note_or_insert_mut(note_key, self.note); .cached_note_or_insert_mut(note_key, self.note)
render_reltime(ui, cached_note, true); .reply
}); .borrow(self.note.tags());
ui.horizontal(|ui| { if note_reply.reply().is_some() {
ui.spacing_mut().item_spacing.x = 2.0; reply_desc(ui, txn, &note_reply, self.app);
reply_desc(ui, txn, self.app, note_key, self.note); }
}); });
ui.add(NoteContents::new( ui.add(NoteContents::new(
@ -313,7 +358,8 @@ impl<'a> NoteView<'a> {
} }
}); });
}) })
.response; .response
};
NoteResponse { NoteResponse {
response, response,

View File

@ -1,3 +1,4 @@
use crate::ui::ProfilePic;
use bitflags::bitflags; use bitflags::bitflags;
bitflags! { bitflags! {
@ -34,11 +35,30 @@ impl NoteOptions {
(self & NoteOptions::medium_pfp) == NoteOptions::medium_pfp (self & NoteOptions::medium_pfp) == NoteOptions::medium_pfp
} }
pub fn pfp_size(&self) -> f32 {
if self.has_small_pfp() {
ProfilePic::small_size()
} else if self.has_medium_pfp() {
ProfilePic::medium_size()
} else {
ProfilePic::default_size()
}
}
#[inline] #[inline]
pub fn has_wide(self) -> bool { pub fn has_wide(self) -> bool {
(self & NoteOptions::wide) == NoteOptions::wide (self & NoteOptions::wide) == NoteOptions::wide
} }
#[inline]
pub fn set_wide(&mut self, enable: bool) {
if enable {
*self |= NoteOptions::wide;
} else {
*self &= !NoteOptions::wide;
}
}
#[inline] #[inline]
pub fn set_small_pfp(&mut self, enable: bool) { pub fn set_small_pfp(&mut self, enable: bool) {
if enable { if enable {