initial inline note previews

still needs a border and options to remove actionbar

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2024-04-12 18:53:32 -07:00
parent d4ccf7435f
commit 2b20f73974
2 changed files with 83 additions and 41 deletions

View File

@@ -1,5 +1,5 @@
use crate::{colors, Damus}; use crate::{colors, ui, Damus};
use egui::{Hyperlink, Image, RichText}; use egui::{Color32, Hyperlink, Image, RichText};
use nostrdb::{BlockType, Mention, Note, NoteKey, Transaction}; use nostrdb::{BlockType, Mention, Note, NoteKey, Transaction};
use tracing::warn; 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, &note).actionbar(false))
}
fn render_note_contents( fn render_note_contents(
ui: &mut egui::Ui, ui: &mut egui::Ui,
damus: &mut Damus, damus: &mut Damus,
@@ -43,6 +68,7 @@ fn render_note_contents(
puffin::profile_function!(); puffin::profile_function!();
let images: Vec<String> = vec![]; let images: Vec<String> = vec![];
let mut inline_note: Option<(&[u8; 32], &str)> = None;
let resp = ui.horizontal_wrapped(|ui| { let resp = ui.horizontal_wrapped(|ui| {
let blocks = if let Ok(blocks) = damus.ndb.get_blocks_by_key(txn, note_key) { 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) { for block in blocks.iter(note) {
match block.blocktype() { match block.blocktype() {
BlockType::MentionBech32 => { BlockType::MentionBech32 => match block.as_mention().unwrap() {
ui.colored_label(colors::PURPLE, "@"); Mention::Pubkey(npub) => {
match block.as_mention().unwrap() { ui.colored_label(colors::PURPLE, "@");
Mention::Pubkey(npub) => { let profile = damus.ndb.get_profile_by_pubkey(txn, npub.pubkey()).ok();
let profile = damus.ndb.get_profile_by_pubkey(txn, npub.pubkey()).ok(); if let Some(name) = profile
if let Some(name) = profile .as_ref()
.as_ref() .and_then(|p| crate::profile::get_profile_name(p))
.and_then(|p| crate::profile::get_profile_name(p)) {
{ ui.colored_label(colors::PURPLE, name);
ui.colored_label(colors::PURPLE, name); } else {
} else { ui.colored_label(colors::PURPLE, "nostrich");
ui.colored_label(colors::PURPLE, "nostrich");
}
}
_ => {
ui.colored_label(colors::PURPLE, block.as_str());
} }
} }
}
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 => { BlockType::Hashtag => {
ui.colored_label(colors::PURPLE, "#"); ui.horizontal(|ui| {
ui.colored_label(colors::PURPLE, block.as_str()); ui.spacing_mut().item_spacing.x = 0.0;
ui.colored_label(colors::PURPLE, "#");
ui.colored_label(colors::PURPLE, block.as_str());
});
} }
BlockType::Url => { 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 { for image in images {
let img_resp = ui.add(Image::new(image.clone())); let img_resp = ui.add(Image::new(image.clone()));
img_resp.context_menu(|ui| { img_resp.context_menu(|ui| {

View File

@@ -3,18 +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;
pub struct Note<'a> { pub struct Note<'a> {
app: &'a mut Damus, app: &'a mut Damus,
note: &'a nostrdb::Note<'a>, note: &'a nostrdb::Note<'a>,
timeline: usize, actionbar: bool,
}
#[derive(Hash, Clone, Copy)]
struct NoteTimelineKey {
timeline: usize,
note_key: NoteKey,
} }
impl<'a> egui::Widget for Note<'a> { impl<'a> egui::Widget for Note<'a> {
@@ -28,14 +21,20 @@ impl<'a> egui::Widget for Note<'a> {
} }
impl<'a> 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 { Note {
app, app,
note, 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 { fn textmode_ui(self, ui: &mut egui::Ui) -> egui::Response {
let note_key = self.note.key().expect("todo: implement non-db notes"); let note_key = self.note.key().expect("todo: implement non-db notes");
let txn = self.note.txn().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!(); puffin::profile_function!();
let note_key = self.note.key().expect("todo: support non-db notes"); let note_key = self.note.key().expect("todo: support non-db notes");
let txn = self.note.txn().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| { 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, self.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| { crate::ui::padding(6.0, ui, |ui| {
match profile match profile
.as_ref() .as_ref()
.ok() .ok()
@@ -117,19 +116,21 @@ impl<'a> Note<'a> {
ui.add(NoteContents::new(self.app, txn, self.note, note_key)); 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 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() { //if resp.hovered() ^ collapse_state.is_open() {
//info!("clicked {:?}, {}", self.note_key, collapse_state.is_open()); //info!("clicked {:?}, {}", self.note_key, collapse_state.is_open());
collapse_state.toggle(ui); //collapse_state.toggle(ui);
collapse_state.store(ui.ctx()); //collapse_state.store(ui.ctx());
} //}
}) })
.response .response
} }