commit 2b20f7397481aa0838c6b7586f3cc00a873b065a
parent d4ccf7435f1d25e0f8a1252461d4c83230f21d71
Author: William Casarin <jb55@jb55.com>
Date: Fri, 12 Apr 2024 18:53:32 -0700
initial inline note previews
still needs a border and options to remove actionbar
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
2 files changed, 83 insertions(+), 41 deletions(-)
diff --git a/src/ui/note/contents.rs b/src/ui/note/contents.rs
@@ -1,5 +1,5 @@
-use crate::{colors, Damus};
-use egui::{Hyperlink, Image, RichText};
+use crate::{colors, ui, Damus};
+use egui::{Color32, Hyperlink, Image, RichText};
use nostrdb::{BlockType, Mention, Note, NoteKey, Transaction};
use tracing::warn;
@@ -32,6 +32,31 @@ impl egui::Widget for NoteContents<'_> {
}
}
+fn render_note_preview(
+ ui: &mut egui::Ui,
+ app: &mut Damus,
+ txn: &Transaction,
+ id: &[u8; 32],
+ _id_str: &str,
+) -> egui::Response {
+ let note = if let Ok(note) = app.ndb.get_note_by_id(txn, id) {
+ note
+ } else {
+ return ui.colored_label(Color32::RED, "TODO: COULD NOT LOAD");
+ /*
+ return ui
+ .horizontal(|ui| {
+ ui.spacing_mut().item_spacing.x = 0.0;
+ ui.colored_label(colors::PURPLE, "@");
+ ui.colored_label(colors::PURPLE, &id_str[4..16]);
+ })
+ .response;
+ */
+ };
+
+ ui.add(ui::Note::new(app, ¬e).actionbar(false))
+}
+
fn render_note_contents(
ui: &mut egui::Ui,
damus: &mut Damus,
@@ -43,6 +68,7 @@ fn render_note_contents(
puffin::profile_function!();
let images: Vec<String> = vec![];
+ let mut inline_note: Option<(&[u8; 32], &str)> = None;
let resp = ui.horizontal_wrapped(|ui| {
let blocks = if let Ok(blocks) = damus.ndb.get_blocks_by_key(txn, note_key) {
@@ -57,29 +83,40 @@ fn render_note_contents(
for block in blocks.iter(note) {
match block.blocktype() {
- BlockType::MentionBech32 => {
- ui.colored_label(colors::PURPLE, "@");
- match block.as_mention().unwrap() {
- Mention::Pubkey(npub) => {
- let profile = damus.ndb.get_profile_by_pubkey(txn, npub.pubkey()).ok();
- if let Some(name) = profile
- .as_ref()
- .and_then(|p| crate::profile::get_profile_name(p))
- {
- ui.colored_label(colors::PURPLE, name);
- } else {
- ui.colored_label(colors::PURPLE, "nostrich");
- }
- }
- _ => {
- ui.colored_label(colors::PURPLE, block.as_str());
+ BlockType::MentionBech32 => match block.as_mention().unwrap() {
+ Mention::Pubkey(npub) => {
+ ui.colored_label(colors::PURPLE, "@");
+ let profile = damus.ndb.get_profile_by_pubkey(txn, npub.pubkey()).ok();
+ if let Some(name) = profile
+ .as_ref()
+ .and_then(|p| crate::profile::get_profile_name(p))
+ {
+ ui.colored_label(colors::PURPLE, name);
+ } else {
+ ui.colored_label(colors::PURPLE, "nostrich");
}
}
- }
+
+ Mention::Note(note) => {
+ inline_note = Some((note.id(), block.as_str()));
+ }
+
+ Mention::Event(note) => {
+ inline_note = Some((note.id(), block.as_str()));
+ }
+
+ _ => {
+ ui.colored_label(colors::PURPLE, "@");
+ ui.colored_label(colors::PURPLE, &block.as_str()[4..16]);
+ }
+ },
BlockType::Hashtag => {
- ui.colored_label(colors::PURPLE, "#");
- ui.colored_label(colors::PURPLE, block.as_str());
+ ui.horizontal(|ui| {
+ ui.spacing_mut().item_spacing.x = 0.0;
+ ui.colored_label(colors::PURPLE, "#");
+ ui.colored_label(colors::PURPLE, block.as_str());
+ });
}
BlockType::Url => {
@@ -107,6 +144,10 @@ fn render_note_contents(
}
});
+ if let Some((id, block_str)) = inline_note {
+ render_note_preview(ui, damus, txn, id, block_str);
+ }
+
for image in images {
let img_resp = ui.add(Image::new(image.clone()));
img_resp.context_menu(|ui| {
diff --git a/src/ui/note/mod.rs b/src/ui/note/mod.rs
@@ -3,18 +3,11 @@ pub use contents::NoteContents;
use crate::{ui, Damus};
use egui::{Color32, Label, RichText, Sense, TextureHandle, Vec2};
-use nostrdb::NoteKey;
pub struct Note<'a> {
app: &'a mut Damus,
note: &'a nostrdb::Note<'a>,
- timeline: usize,
-}
-
-#[derive(Hash, Clone, Copy)]
-struct NoteTimelineKey {
- timeline: usize,
- note_key: NoteKey,
+ actionbar: bool,
}
impl<'a> egui::Widget for Note<'a> {
@@ -28,14 +21,20 @@ impl<'a> egui::Widget for Note<'a> {
}
impl<'a> Note<'a> {
- pub fn new(app: &'a mut Damus, note: &'a nostrdb::Note<'a>, timeline: usize) -> Self {
+ pub fn new(app: &'a mut Damus, note: &'a nostrdb::Note<'a>) -> Self {
+ let actionbar = true;
Note {
app,
note,
- timeline,
+ actionbar,
}
}
+ pub fn actionbar(mut self, enable: bool) -> Self {
+ self.actionbar = enable;
+ self
+ }
+
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");
@@ -76,20 +75,20 @@ impl<'a> Note<'a> {
puffin::profile_function!();
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 });
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| {
+ crate::ui::padding(6.0, ui, |ui| {
match profile
.as_ref()
.ok()
@@ -117,19 +116,21 @@ impl<'a> Note<'a> {
ui.add(NoteContents::new(self.app, txn, self.note, note_key));
- render_note_actionbar(ui);
+ if self.actionbar {
+ 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());
- }
+ //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
}