commit 5e45e4a2e572c0d273eaff313d54a6cffed45344
parent 4e7d168d223bd3b02363468b80c030dc02cc62dc
Author: William Casarin <jb55@jb55.com>
Date: Fri, 12 Apr 2024 16:46:31 -0700
ui: simplify note widget
pass just a note pointer to the note ui widget. We currently don't
support non-db notes but we can add support for that later.
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
M | src/app.rs | | | 19 | +++++++++++++++---- |
M | src/ui/note/mod.rs | | | 179 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
2 files changed, 100 insertions(+), 98 deletions(-)
diff --git a/src/app.rs b/src/app.rs
@@ -515,17 +515,28 @@ struct NoteTimelineKey {
note_key: NoteKey,
}
-fn render_notes(ui: &mut egui::Ui, damus: &mut Damus, timeline: usize) {
+fn render_notes(ui: &mut egui::Ui, damus: &mut Damus, timeline: usize) -> Result<()> {
#[cfg(feature = "profiling")]
puffin::profile_function!();
let num_notes = damus.timelines[timeline].notes.len();
+ let txn = Transaction::new(&damus.ndb)?;
for i in 0..num_notes {
- let note = ui::Note::new(damus, damus.timelines[timeline].notes[i].key, timeline);
- ui.add(note);
+ let note_key = damus.timelines[timeline].notes[i].key;
+ let note = if let Ok(note) = damus.ndb.get_note_by_key(&txn, note_key) {
+ note
+ } else {
+ warn!("failed to query note {:?}", note_key);
+ continue;
+ };
+
+ let note_ui = ui::Note::new(damus, ¬e, timeline);
+ ui.add(note_ui);
ui.add(egui::Separator::default().spacing(0.0));
}
+
+ Ok(())
}
fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
@@ -545,7 +556,7 @@ fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
*/
.show(ui, |ui| {
ui.spacing_mut().item_spacing.y = 0.0;
- render_notes(ui, app, timeline);
+ let _ = render_notes(ui, app, timeline);
});
}
diff --git a/src/ui/note/mod.rs b/src/ui/note/mod.rs
@@ -3,11 +3,11 @@ pub use contents::NoteContents;
use crate::{ui, Damus};
use egui::{Color32, Label, RichText, Sense, TextureHandle, Vec2};
-use nostrdb::{NoteKey, Transaction};
+use nostrdb::NoteKey;
pub struct Note<'a> {
app: &'a mut Damus,
- note_key: NoteKey,
+ note: &'a nostrdb::Note<'a>,
timeline: usize,
}
@@ -19,128 +19,119 @@ struct NoteTimelineKey {
impl<'a> egui::Widget for Note<'a> {
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
- let res = if self.app.textmode {
+ if self.app.textmode {
self.textmode_ui(ui)
} else {
self.standard_ui(ui)
- };
-
- if let Ok(resp) = res {
- resp
- } else {
- ui.label("Could not render note")
}
}
}
impl<'a> Note<'a> {
- pub fn new(app: &'a mut Damus, note_key: NoteKey, timeline: usize) -> Self {
+ pub fn new(app: &'a mut Damus, note: &'a nostrdb::Note<'a>, timeline: usize) -> Self {
Note {
app,
- note_key,
+ note,
timeline,
}
}
- fn textmode_ui(self, ui: &mut egui::Ui) -> Result<egui::Response, nostrdb::Error> {
- let txn = Transaction::new(&self.app.ndb)?;
- let note = self.app.ndb.get_note_by_key(&txn, self.note_key)?;
+ fn textmode_ui(self, ui: &mut egui::Ui) -> egui::Response {
+ let note_key = self.note.key().expect("todo: implement non-db notes");
+ let txn = self.note.txn().expect("todo: implement non-db notes");
- Ok(ui
- .with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
- let profile = self.app.ndb.get_profile_by_pubkey(&txn, note.pubkey());
+ ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
+ let profile = self.app.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
- ui.horizontal(|ui| {
- ui.spacing_mut().item_spacing.x = 2.0;
+ ui.horizontal(|ui| {
+ ui.spacing_mut().item_spacing.x = 2.0;
- let note_cache = self
- .app
- .get_note_cache_mut(self.note_key, note.created_at());
- let (_id, rect) = ui.allocate_space(egui::vec2(50.0, 20.0));
- ui.allocate_rect(rect, Sense::hover());
- ui.put(rect, |ui: &mut egui::Ui| {
- render_reltime(ui, note_cache, false).response
- });
- let (_id, rect) = ui.allocate_space(egui::vec2(150.0, 20.0));
- ui.allocate_rect(rect, Sense::hover());
- ui.put(rect, |ui: &mut egui::Ui| {
- ui.add(
- ui::Username::new(profile.as_ref().ok(), note.pubkey())
- .abbreviated(8)
- .pk_colored(true),
- )
- });
+ let note_cache = self
+ .app
+ .get_note_cache_mut(note_key, self.note.created_at());
- ui.add(NoteContents::new(self.app, &txn, ¬e, self.note_key));
+ let (_id, rect) = ui.allocate_space(egui::vec2(50.0, 20.0));
+ ui.allocate_rect(rect, Sense::hover());
+ ui.put(rect, |ui: &mut egui::Ui| {
+ render_reltime(ui, note_cache, false).response
});
- })
- .response)
+ let (_id, rect) = ui.allocate_space(egui::vec2(150.0, 20.0));
+ ui.allocate_rect(rect, Sense::hover());
+ ui.put(rect, |ui: &mut egui::Ui| {
+ ui.add(
+ ui::Username::new(profile.as_ref().ok(), self.note.pubkey())
+ .abbreviated(8)
+ .pk_colored(true),
+ )
+ });
+
+ ui.add(NoteContents::new(self.app, txn, self.note, note_key));
+ });
+ })
+ .response
}
- pub fn standard_ui(self, ui: &mut egui::Ui) -> Result<egui::Response, nostrdb::Error> {
+ pub fn standard_ui(self, ui: &mut egui::Ui) -> egui::Response {
#[cfg(feature = "profiling")]
puffin::profile_function!();
-
- let txn = Transaction::new(&self.app.ndb)?;
- let note = self.app.ndb.get_note_by_key(&txn, self.note_key)?;
- let note_key = self.note_key;
+ let note_key = self.note.key().expect("todo: support non-db notes");
+ let txn = self.note.txn().expect("todo: support non-db notes");
let timeline = self.timeline;
let id = egui::Id::new(NoteTimelineKey { note_key, timeline });
- Ok(ui
- .with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
- let profile = self.app.ndb.get_profile_by_pubkey(&txn, note.pubkey());
-
- let mut collapse_state =
- egui::collapsing_header::CollapsingState::load_with_default_open(
- ui.ctx(),
- id,
- false,
- );
-
- let inner_resp = crate::ui::padding(6.0, ui, |ui| {
- match profile
- .as_ref()
- .ok()
- .and_then(|p| p.record.profile()?.picture())
- {
- // these have different lifetimes and types,
- // so the calls must be separate
- Some(pic) => render_pfp(ui, self.app, pic),
- None => render_pfp(ui, self.app, no_pfp_url()),
- }
-
- ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
- 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 note_cache = self
- .app
- .get_note_cache_mut(self.note_key, note.created_at());
- render_reltime(ui, note_cache, true);
- });
-
- ui.add(NoteContents::new(self.app, &txn, ¬e, self.note_key));
-
- render_note_actionbar(ui);
-
- //let header_res = ui.horizontal(|ui| {});
+ ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
+ let profile = self.app.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
+
+ let mut collapse_state =
+ egui::collapsing_header::CollapsingState::load_with_default_open(
+ ui.ctx(),
+ id,
+ false,
+ );
+
+ let inner_resp = crate::ui::padding(6.0, ui, |ui| {
+ match profile
+ .as_ref()
+ .ok()
+ .and_then(|p| p.record.profile()?.picture())
+ {
+ // these have different lifetimes and types,
+ // so the calls must be separate
+ Some(pic) => render_pfp(ui, self.app, pic),
+ None => render_pfp(ui, self.app, no_pfp_url()),
+ }
+
+ ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
+ ui.horizontal(|ui| {
+ ui.spacing_mut().item_spacing.x = 2.0;
+ ui.add(
+ ui::Username::new(profile.as_ref().ok(), self.note.pubkey())
+ .abbreviated(20),
+ );
+
+ let note_cache = self
+ .app
+ .get_note_cache_mut(note_key, self.note.created_at());
+ render_reltime(ui, note_cache, true);
});
+
+ ui.add(NoteContents::new(self.app, txn, self.note, note_key));
+
+ render_note_actionbar(ui);
+
+ //let header_res = ui.horizontal(|ui| {});
});
+ });
- let resp = ui.interact(inner_resp.response.rect, id, Sense::hover());
+ let resp = ui.interact(inner_resp.response.rect, id, Sense::hover());
- if resp.hovered() ^ collapse_state.is_open() {
- //info!("clicked {:?}, {}", self.note_key, collapse_state.is_open());
- collapse_state.toggle(ui);
- collapse_state.store(ui.ctx());
- }
- })
- .response)
+ if resp.hovered() ^ collapse_state.is_open() {
+ //info!("clicked {:?}, {}", self.note_key, collapse_state.is_open());
+ collapse_state.toggle(ui);
+ collapse_state.store(ui.ctx());
+ }
+ })
+ .response
}
}