commit cb7dadee44cc3423bdef373ae0324c87ef504fc7
parent 74f63f49caceccaf2983026166675d3f0ec71fe4
Author: William Casarin <jb55@jb55.com>
Date: Tue, 4 Nov 2025 14:41:25 -0800
ui: note metadata stats
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
1 file changed, 75 insertions(+), 12 deletions(-)
diff --git a/crates/notedeck_ui/src/note/mod.rs b/crates/notedeck_ui/src/note/mod.rs
@@ -452,15 +452,30 @@ impl<'a, 'd> NoteView<'a, 'd> {
// question: WTF? question 2: WHY?
ui.allocate_space(egui::vec2(0.0, 0.0));
+ let counts = self
+ .note_context
+ .ndb
+ .get_note_metadata(txn, self.note.id())
+ .ok()
+ .and_then(|md| {
+ md.into_iter().find_map(|e| {
+ if let nostrdb::NoteMetadataEntryVariant::Counts(ce) = e {
+ Some(ce)
+ } else {
+ None
+ }
+ })
+ });
+
render_note_actionbar(
ui,
+ counts,
get_zapper(
self.note_context.accounts,
self.note_context.global_wallet,
self.note_context.zaps,
),
- self.note.id(),
- self.note.pubkey(),
+ self.note,
self.note_context.accounts.selected_account_pubkey(),
note_key,
self.note_context.i18n,
@@ -539,17 +554,32 @@ impl<'a, 'd> NoteView<'a, 'd> {
note_action = contents.action.or(note_action);
if self.options().contains(NoteOptions::ActionBar) {
+ let counts = self
+ .note_context
+ .ndb
+ .get_note_metadata(txn, self.note.id())
+ .ok()
+ .and_then(|md| {
+ md.into_iter().find_map(|e| {
+ if let nostrdb::NoteMetadataEntryVariant::Counts(ce) = e {
+ Some(ce)
+ } else {
+ None
+ }
+ })
+ });
+
note_action = ui
.horizontal_wrapped(|ui| {
render_note_actionbar(
ui,
+ counts,
get_zapper(
self.note_context.accounts,
self.note_context.global_wallet,
self.note_context.zaps,
),
- self.note.id(),
- self.note.pubkey(),
+ self.note,
self.note_context.accounts.selected_account_pubkey(),
note_key,
self.note_context.i18n,
@@ -862,48 +892,81 @@ fn is_root_note(note: &Note) -> bool {
#[profiling::function]
fn render_note_actionbar(
ui: &mut egui::Ui,
+ counts: Option<nostrdb::CountsEntry<'_>>,
zapper: Option<Zapper<'_>>,
- note_id: &[u8; 32],
- note_pubkey: &[u8; 32],
+ note: &Note,
current_user_pubkey: &Pubkey,
note_key: NoteKey,
i18n: &mut Localization,
) -> Option<NoteAction> {
let mut action = None;
+ let spacing = 24.0;
+ ui.spacing_mut().item_spacing.x = 2.0;
ui.set_min_height(26.0);
- ui.spacing_mut().item_spacing.x = 24.0;
let reply_resp =
reply_button(ui, i18n, note_key).on_hover_cursor(egui::CursorIcon::PointingHand);
+ if let Some(c) = &counts {
+ let count = if is_root_note(note) {
+ c.thread_replies()
+ } else {
+ c.direct_replies() as u32
+ };
+
+ if count > 0 {
+ ui.weak(format!("{}", count));
+ }
+ }
+
+ ui.add_space(spacing);
+
let filled = ui
.ctx()
- .data(|d| d.get_temp(reaction_sent_id(current_user_pubkey, note_id)))
+ .data(|d| d.get_temp(reaction_sent_id(current_user_pubkey, note.id())))
== Some(true);
let like_resp =
like_button(ui, i18n, note_key, filled).on_hover_cursor(egui::CursorIcon::PointingHand);
+ if let Some(c) = &counts {
+ let count = c.reactions();
+ if count > 0 {
+ ui.weak(format!("{}", count));
+ }
+ }
+
+ ui.add_space(spacing);
+
let quote_resp =
quote_repost_button(ui, i18n, note_key).on_hover_cursor(egui::CursorIcon::PointingHand);
+ if let Some(c) = &counts {
+ let count = c.quotes() + c.reposts();
+ if count > 0 {
+ ui.weak(format!("{}", count));
+ }
+ }
+
+ ui.add_space(spacing);
+
if reply_resp.clicked() {
- action = Some(NoteAction::Reply(NoteId::new(*note_id)));
+ action = Some(NoteAction::Reply(NoteId::new(*note.id())));
}
if like_resp.clicked() {
action = Some(NoteAction::React(ReactAction::new(
- NoteId::new(*note_id),
+ NoteId::new(*note.id()),
"🤙🏻",
)));
}
if quote_resp.clicked() {
- action = Some(NoteAction::Repost(NoteId::new(*note_id)));
+ action = Some(NoteAction::Repost(NoteId::new(*note.id())));
}
- action = zap_actionbar_button(ui, note_id, note_pubkey, zapper, i18n).or(action);
+ action = zap_actionbar_button(ui, note.id(), note.pubkey(), zapper, i18n).or(action);
action
}