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>
This commit is contained in:
19
src/app.rs
19
src/app.rs
@@ -515,17 +515,28 @@ struct NoteTimelineKey {
|
|||||||
note_key: NoteKey,
|
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")]
|
#[cfg(feature = "profiling")]
|
||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
|
|
||||||
let num_notes = damus.timelines[timeline].notes.len();
|
let num_notes = damus.timelines[timeline].notes.len();
|
||||||
|
let txn = Transaction::new(&damus.ndb)?;
|
||||||
|
|
||||||
for i in 0..num_notes {
|
for i in 0..num_notes {
|
||||||
let note = ui::Note::new(damus, damus.timelines[timeline].notes[i].key, timeline);
|
let note_key = damus.timelines[timeline].notes[i].key;
|
||||||
ui.add(note);
|
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));
|
ui.add(egui::Separator::default().spacing(0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
|
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| {
|
.show(ui, |ui| {
|
||||||
ui.spacing_mut().item_spacing.y = 0.0;
|
ui.spacing_mut().item_spacing.y = 0.0;
|
||||||
render_notes(ui, app, timeline);
|
let _ = render_notes(ui, app, timeline);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ pub use contents::NoteContents;
|
|||||||
|
|
||||||
use crate::{ui, Damus};
|
use crate::{ui, Damus};
|
||||||
use egui::{Color32, Label, RichText, Sense, TextureHandle, Vec2};
|
use egui::{Color32, Label, RichText, Sense, TextureHandle, Vec2};
|
||||||
use nostrdb::{NoteKey, Transaction};
|
use nostrdb::NoteKey;
|
||||||
|
|
||||||
pub struct Note<'a> {
|
pub struct Note<'a> {
|
||||||
app: &'a mut Damus,
|
app: &'a mut Damus,
|
||||||
note_key: NoteKey,
|
note: &'a nostrdb::Note<'a>,
|
||||||
timeline: usize,
|
timeline: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,128 +19,119 @@ struct NoteTimelineKey {
|
|||||||
|
|
||||||
impl<'a> egui::Widget for Note<'a> {
|
impl<'a> egui::Widget for Note<'a> {
|
||||||
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
||||||
let res = if self.app.textmode {
|
if self.app.textmode {
|
||||||
self.textmode_ui(ui)
|
self.textmode_ui(ui)
|
||||||
} else {
|
} else {
|
||||||
self.standard_ui(ui)
|
self.standard_ui(ui)
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(resp) = res {
|
|
||||||
resp
|
|
||||||
} else {
|
|
||||||
ui.label("Could not render note")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Note<'a> {
|
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 {
|
Note {
|
||||||
app,
|
app,
|
||||||
note_key,
|
note,
|
||||||
timeline,
|
timeline,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn textmode_ui(self, ui: &mut egui::Ui) -> Result<egui::Response, nostrdb::Error> {
|
fn textmode_ui(self, ui: &mut egui::Ui) -> egui::Response {
|
||||||
let txn = Transaction::new(&self.app.ndb)?;
|
let note_key = self.note.key().expect("todo: implement non-db notes");
|
||||||
let note = self.app.ndb.get_note_by_key(&txn, self.note_key)?;
|
let txn = self.note.txn().expect("todo: implement non-db notes");
|
||||||
|
|
||||||
Ok(ui
|
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |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 profile = self.app.ndb.get_profile_by_pubkey(&txn, note.pubkey());
|
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.spacing_mut().item_spacing.x = 2.0;
|
ui.spacing_mut().item_spacing.x = 2.0;
|
||||||
|
|
||||||
let note_cache = self
|
let note_cache = self
|
||||||
.app
|
.app
|
||||||
.get_note_cache_mut(self.note_key, note.created_at());
|
.get_note_cache_mut(note_key, self.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),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
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
|
||||||
});
|
});
|
||||||
})
|
let (_id, rect) = ui.allocate_space(egui::vec2(150.0, 20.0));
|
||||||
.response)
|
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")]
|
#[cfg(feature = "profiling")]
|
||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
|
let note_key = self.note.key().expect("todo: support non-db notes");
|
||||||
let txn = Transaction::new(&self.app.ndb)?;
|
let txn = self.note.txn().expect("todo: support non-db notes");
|
||||||
let note = self.app.ndb.get_note_by_key(&txn, self.note_key)?;
|
|
||||||
let note_key = self.note_key;
|
|
||||||
let timeline = self.timeline;
|
let timeline = self.timeline;
|
||||||
let id = egui::Id::new(NoteTimelineKey { note_key, timeline });
|
let id = egui::Id::new(NoteTimelineKey { note_key, timeline });
|
||||||
|
|
||||||
Ok(ui
|
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |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 profile = self.app.ndb.get_profile_by_pubkey(&txn, note.pubkey());
|
|
||||||
|
|
||||||
let mut collapse_state =
|
let mut collapse_state =
|
||||||
egui::collapsing_header::CollapsingState::load_with_default_open(
|
egui::collapsing_header::CollapsingState::load_with_default_open(
|
||||||
ui.ctx(),
|
ui.ctx(),
|
||||||
id,
|
id,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let inner_resp = crate::ui::padding(6.0, ui, |ui| {
|
let inner_resp = crate::ui::padding(6.0, ui, |ui| {
|
||||||
match profile
|
match profile
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|p| p.record.profile()?.picture())
|
.and_then(|p| p.record.profile()?.picture())
|
||||||
{
|
{
|
||||||
// these have different lifetimes and types,
|
// these have different lifetimes and types,
|
||||||
// so the calls must be separate
|
// so the calls must be separate
|
||||||
Some(pic) => render_pfp(ui, self.app, pic),
|
Some(pic) => render_pfp(ui, self.app, pic),
|
||||||
None => render_pfp(ui, self.app, no_pfp_url()),
|
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| {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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)
|
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());
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user