note: refactor to use action composition & reduce nesting
Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
@@ -14,6 +14,7 @@ pub use contents::{render_note_contents, render_note_preview, NoteContents};
|
|||||||
pub use context::NoteContextButton;
|
pub use context::NoteContextButton;
|
||||||
use notedeck::note::MediaAction;
|
use notedeck::note::MediaAction;
|
||||||
use notedeck::note::ZapTargetAmount;
|
use notedeck::note::ZapTargetAmount;
|
||||||
|
use notedeck::Images;
|
||||||
pub use options::NoteOptions;
|
pub use options::NoteOptions;
|
||||||
pub use reply_description::reply_desc;
|
pub use reply_description::reply_desc;
|
||||||
|
|
||||||
@@ -234,8 +235,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
note_key: NoteKey,
|
note_key: NoteKey,
|
||||||
profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>,
|
profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>,
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
) -> (egui::Response, Option<MediaAction>) {
|
) -> PfpResponse {
|
||||||
let mut action = None;
|
|
||||||
if !self.options().has_wide() {
|
if !self.options().has_wide() {
|
||||||
ui.spacing_mut().item_spacing.x = 16.0;
|
ui.spacing_mut().item_spacing.x = 16.0;
|
||||||
} else {
|
} else {
|
||||||
@@ -244,107 +244,77 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
|
|
||||||
let pfp_size = self.options().pfp_size();
|
let pfp_size = self.options().pfp_size();
|
||||||
|
|
||||||
let sense = Sense::click();
|
match profile
|
||||||
let resp = 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) => {
|
Some(pic) => show_actual_pfp(
|
||||||
let anim_speed = 0.05;
|
ui,
|
||||||
let profile_key = profile.as_ref().unwrap().record().note_key();
|
self.note_context.img_cache,
|
||||||
let note_key = note_key.as_u64();
|
pic,
|
||||||
|
pfp_size,
|
||||||
|
note_key,
|
||||||
|
profile,
|
||||||
|
),
|
||||||
|
|
||||||
let (rect, size, resp) = crate::anim::hover_expand(
|
None => show_fallback_pfp(ui, self.note_context.img_cache, pfp_size),
|
||||||
ui,
|
}
|
||||||
egui::Id::new((profile_key, note_key)),
|
}
|
||||||
pfp_size as f32,
|
|
||||||
NoteView::expand_size() as f32,
|
|
||||||
anim_speed,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut pfp = ProfilePic::new(self.note_context.img_cache, pic).size(size);
|
fn show_repost(
|
||||||
let pfp_resp = ui.put(rect, &mut pfp);
|
&mut self,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
txn: &Transaction,
|
||||||
|
note_to_repost: Note<'_>,
|
||||||
|
) -> NoteResponse {
|
||||||
|
let profile = self
|
||||||
|
.note_context
|
||||||
|
.ndb
|
||||||
|
.get_profile_by_pubkey(txn, self.note.pubkey());
|
||||||
|
|
||||||
action = action.or(pfp.action);
|
let style = NotedeckTextStyle::Small;
|
||||||
|
ui.horizontal(|ui| {
|
||||||
if resp.hovered() || resp.clicked() {
|
ui.vertical(|ui| {
|
||||||
crate::show_pointer(ui);
|
ui.add_space(2.0);
|
||||||
}
|
ui.add_sized([20.0, 20.0], repost_icon(ui.visuals().dark_mode));
|
||||||
|
});
|
||||||
pfp_resp.on_hover_ui_at_pointer(|ui| {
|
ui.add_space(6.0);
|
||||||
|
let resp = ui.add(one_line_display_name_widget(
|
||||||
|
ui.visuals(),
|
||||||
|
get_display_name(profile.as_ref().ok()),
|
||||||
|
style,
|
||||||
|
));
|
||||||
|
if let Ok(rec) = &profile {
|
||||||
|
resp.on_hover_ui_at_pointer(|ui| {
|
||||||
ui.set_max_width(300.0);
|
ui.set_max_width(300.0);
|
||||||
ui.add(ProfilePreview::new(
|
ui.add(ProfilePreview::new(rec, self.note_context.img_cache));
|
||||||
profile.as_ref().unwrap(),
|
|
||||||
self.note_context.img_cache,
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
resp
|
|
||||||
}
|
}
|
||||||
|
let color = ui.style().visuals.noninteractive().fg_stroke.color;
|
||||||
None => {
|
ui.add_space(4.0);
|
||||||
// This has to match the expand size from the above case to
|
ui.label(
|
||||||
// prevent bounciness
|
RichText::new("Reposted")
|
||||||
let size = (pfp_size + NoteView::expand_size()) as f32;
|
.color(color)
|
||||||
let (rect, _response) = ui.allocate_exact_size(egui::vec2(size, size), sense);
|
.text_style(style.text_style()),
|
||||||
|
);
|
||||||
let mut pfp =
|
});
|
||||||
ProfilePic::new(self.note_context.img_cache, notedeck::profile::no_pfp_url())
|
NoteView::new(
|
||||||
.size(pfp_size as f32);
|
self.note_context,
|
||||||
let resp = ui.put(rect, &mut pfp).interact(sense);
|
self.zapping_acc,
|
||||||
action = action.or(pfp.action);
|
¬e_to_repost,
|
||||||
|
self.flags,
|
||||||
resp
|
self.jobs,
|
||||||
}
|
)
|
||||||
};
|
.show(ui)
|
||||||
(resp, action)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_impl(&mut self, ui: &mut egui::Ui) -> NoteResponse {
|
pub fn show_impl(&mut self, ui: &mut egui::Ui) -> NoteResponse {
|
||||||
let txn = self.note.txn().expect("txn");
|
let txn = self.note.txn().expect("txn");
|
||||||
if let Some(note_to_repost) = get_reposted_note(self.note_context.ndb, txn, self.note) {
|
if let Some(note_to_repost) = get_reposted_note(self.note_context.ndb, txn, self.note) {
|
||||||
let profile = self
|
self.show_repost(ui, txn, note_to_repost)
|
||||||
.note_context
|
|
||||||
.ndb
|
|
||||||
.get_profile_by_pubkey(txn, self.note.pubkey());
|
|
||||||
|
|
||||||
let style = NotedeckTextStyle::Small;
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.vertical(|ui| {
|
|
||||||
ui.add_space(2.0);
|
|
||||||
ui.add_sized([20.0, 20.0], repost_icon(ui.visuals().dark_mode));
|
|
||||||
});
|
|
||||||
ui.add_space(6.0);
|
|
||||||
let resp = ui.add(one_line_display_name_widget(
|
|
||||||
ui.visuals(),
|
|
||||||
get_display_name(profile.as_ref().ok()),
|
|
||||||
style,
|
|
||||||
));
|
|
||||||
if let Ok(rec) = &profile {
|
|
||||||
resp.on_hover_ui_at_pointer(|ui| {
|
|
||||||
ui.set_max_width(300.0);
|
|
||||||
ui.add(ProfilePreview::new(rec, self.note_context.img_cache));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let color = ui.style().visuals.noninteractive().fg_stroke.color;
|
|
||||||
ui.add_space(4.0);
|
|
||||||
ui.label(
|
|
||||||
RichText::new("Reposted")
|
|
||||||
.color(color)
|
|
||||||
.text_style(style.text_style()),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
NoteView::new(
|
|
||||||
self.note_context,
|
|
||||||
self.zapping_acc,
|
|
||||||
¬e_to_repost,
|
|
||||||
self.flags,
|
|
||||||
self.jobs,
|
|
||||||
)
|
|
||||||
.show(ui)
|
|
||||||
} else {
|
} else {
|
||||||
self.show_standard(ui)
|
self.show_standard(ui)
|
||||||
}
|
}
|
||||||
@@ -395,19 +365,16 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
note_key: NoteKey,
|
note_key: NoteKey,
|
||||||
profile: &Result<ProfileRecord, nostrdb::Error>,
|
profile: &Result<ProfileRecord, nostrdb::Error>,
|
||||||
) -> egui::InnerResponse<Option<NoteAction>> {
|
) -> egui::InnerResponse<Option<NoteAction>> {
|
||||||
let mut note_action: Option<NoteAction> = None;
|
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
|
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
|
||||||
|
let mut note_action: Option<NoteAction> = None;
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let (pfp_resp, action) = self.pfp(note_key, profile, ui);
|
note_action = self
|
||||||
if pfp_resp.clicked() {
|
.pfp(note_key, profile, ui)
|
||||||
note_action = Some(NoteAction::Profile(Pubkey::new(*self.note.pubkey())));
|
.into_action(self.note.pubkey())
|
||||||
} else if let Some(action) = action {
|
.or(note_action.take());
|
||||||
note_action = Some(NoteAction::Media(action));
|
|
||||||
};
|
|
||||||
|
|
||||||
let size = ui.available_size();
|
let size = ui.available_size();
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| 's: {
|
||||||
ui.add_sized(
|
ui.add_sized(
|
||||||
[size.x, self.options().pfp_size() as f32],
|
[size.x, self.options().pfp_size() as f32],
|
||||||
|ui: &mut egui::Ui| {
|
|ui: &mut egui::Ui| {
|
||||||
@@ -430,25 +397,22 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
.reply
|
.reply
|
||||||
.borrow(self.note.tags());
|
.borrow(self.note.tags());
|
||||||
|
|
||||||
if note_reply.reply().is_some() {
|
if note_reply.reply().is_none() {
|
||||||
let action = ui
|
break 's;
|
||||||
.horizontal(|ui| {
|
|
||||||
reply_desc(
|
|
||||||
ui,
|
|
||||||
self.zapping_acc,
|
|
||||||
txn,
|
|
||||||
¬e_reply,
|
|
||||||
self.note_context,
|
|
||||||
self.flags,
|
|
||||||
self.jobs,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.inner;
|
|
||||||
|
|
||||||
if action.is_some() {
|
|
||||||
note_action = action;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
note_action = reply_desc(
|
||||||
|
ui,
|
||||||
|
self.zapping_acc,
|
||||||
|
txn,
|
||||||
|
¬e_reply,
|
||||||
|
self.note_context,
|
||||||
|
self.flags,
|
||||||
|
self.jobs,
|
||||||
|
)
|
||||||
|
.or(note_action.take());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -463,12 +427,10 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
|
|
||||||
ui.add(&mut contents);
|
ui.add(&mut contents);
|
||||||
|
|
||||||
if let Some(action) = contents.action {
|
note_action = contents.action.or(note_action);
|
||||||
note_action = Some(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.options().has_actionbar() {
|
if self.options().has_actionbar() {
|
||||||
if let Some(action) = render_note_actionbar(
|
note_action = render_note_actionbar(
|
||||||
ui,
|
ui,
|
||||||
self.zapping_acc.as_ref().map(|c| Zapper {
|
self.zapping_acc.as_ref().map(|c| Zapper {
|
||||||
zaps: self.note_context.zaps,
|
zaps: self.note_context.zaps,
|
||||||
@@ -479,9 +441,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
note_key,
|
note_key,
|
||||||
)
|
)
|
||||||
.inner
|
.inner
|
||||||
{
|
.or(note_action)
|
||||||
note_action = Some(action);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
note_action
|
note_action
|
||||||
@@ -495,19 +455,15 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
note_key: NoteKey,
|
note_key: NoteKey,
|
||||||
profile: &Result<ProfileRecord, nostrdb::Error>,
|
profile: &Result<ProfileRecord, nostrdb::Error>,
|
||||||
) -> egui::InnerResponse<Option<NoteAction>> {
|
) -> egui::InnerResponse<Option<NoteAction>> {
|
||||||
let mut note_action: Option<NoteAction> = None;
|
|
||||||
// main design
|
// main design
|
||||||
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 (pfp_resp, action) = self.pfp(note_key, profile, ui);
|
let mut note_action: Option<NoteAction> = self
|
||||||
if pfp_resp.clicked() {
|
.pfp(note_key, profile, ui)
|
||||||
note_action = Some(NoteAction::Profile(Pubkey::new(*self.note.pubkey())));
|
.into_action(self.note.pubkey());
|
||||||
} else if let Some(action) = action {
|
|
||||||
note_action = Some(NoteAction::Media(action));
|
|
||||||
};
|
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
|
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
|
||||||
NoteView::note_header(ui, self.note_context.note_cache, self.note, profile);
|
NoteView::note_header(ui, self.note_context.note_cache, self.note, profile);
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| 's: {
|
||||||
ui.spacing_mut().item_spacing.x = 2.0;
|
ui.spacing_mut().item_spacing.x = 2.0;
|
||||||
|
|
||||||
let note_reply = self
|
let note_reply = self
|
||||||
@@ -517,21 +473,20 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
.reply
|
.reply
|
||||||
.borrow(self.note.tags());
|
.borrow(self.note.tags());
|
||||||
|
|
||||||
if note_reply.reply().is_some() {
|
if note_reply.reply().is_none() {
|
||||||
let action = reply_desc(
|
break 's;
|
||||||
ui,
|
|
||||||
self.zapping_acc,
|
|
||||||
txn,
|
|
||||||
¬e_reply,
|
|
||||||
self.note_context,
|
|
||||||
self.flags,
|
|
||||||
self.jobs,
|
|
||||||
);
|
|
||||||
|
|
||||||
if action.is_some() {
|
|
||||||
note_action = action;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
note_action = reply_desc(
|
||||||
|
ui,
|
||||||
|
self.zapping_acc,
|
||||||
|
txn,
|
||||||
|
¬e_reply,
|
||||||
|
self.note_context,
|
||||||
|
self.flags,
|
||||||
|
self.jobs,
|
||||||
|
)
|
||||||
|
.or(note_action.take());
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut contents = NoteContents::new(
|
let mut contents = NoteContents::new(
|
||||||
@@ -544,12 +499,10 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
);
|
);
|
||||||
ui.add(&mut contents);
|
ui.add(&mut contents);
|
||||||
|
|
||||||
if let Some(action) = contents.action {
|
note_action = contents.action.or(note_action);
|
||||||
note_action = Some(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.options().has_actionbar() {
|
if self.options().has_actionbar() {
|
||||||
if let Some(action) = render_note_actionbar(
|
note_action = render_note_actionbar(
|
||||||
ui,
|
ui,
|
||||||
self.zapping_acc.as_ref().map(|c| Zapper {
|
self.zapping_acc.as_ref().map(|c| Zapper {
|
||||||
zaps: self.note_context.zaps,
|
zaps: self.note_context.zaps,
|
||||||
@@ -560,11 +513,8 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
note_key,
|
note_key,
|
||||||
)
|
)
|
||||||
.inner
|
.inner
|
||||||
{
|
.or(note_action)
|
||||||
note_action = Some(action);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
note_action
|
note_action
|
||||||
})
|
})
|
||||||
.inner
|
.inner
|
||||||
@@ -607,19 +557,20 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let note_action =
|
note_action = note_hitbox_clicked(ui, hitbox_id, &response.response.rect, maybe_hitbox)
|
||||||
if note_hitbox_clicked(ui, hitbox_id, &response.response.rect, maybe_hitbox) {
|
.then_some(NoteAction::Note(NoteId::new(*self.note.id())))
|
||||||
Some(NoteAction::Note(NoteId::new(*self.note.id())))
|
.or(note_action);
|
||||||
} else {
|
|
||||||
note_action
|
|
||||||
};
|
|
||||||
|
|
||||||
NoteResponse::new(response.response).with_action(note_action)
|
NoteResponse::new(response.response).with_action(note_action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_reposted_note<'a>(ndb: &Ndb, txn: &'a Transaction, note: &Note) -> Option<Note<'a>> {
|
fn get_reposted_note<'a>(ndb: &Ndb, txn: &'a Transaction, note: &Note) -> Option<Note<'a>> {
|
||||||
let new_note_id: &[u8; 32] = if note.kind() == 6 {
|
if note.kind() != 6 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_note_id: &[u8; 32] = {
|
||||||
let mut res = None;
|
let mut res = None;
|
||||||
for tag in note.tags().iter() {
|
for tag in note.tags().iter() {
|
||||||
if tag.count() == 0 {
|
if tag.count() == 0 {
|
||||||
@@ -634,14 +585,82 @@ fn get_reposted_note<'a>(ndb: &Ndb, txn: &'a Transaction, note: &Note) -> Option
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
res?
|
res?
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let note = ndb.get_note_by_id(txn, new_note_id).ok();
|
let note = ndb.get_note_by_id(txn, new_note_id).ok();
|
||||||
note.filter(|note| note.kind() == 1)
|
note.filter(|note| note.kind() == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PfpResponse {
|
||||||
|
action: Option<MediaAction>,
|
||||||
|
response: egui::Response,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PfpResponse {
|
||||||
|
fn into_action(self, note_pk: &[u8; 32]) -> Option<NoteAction> {
|
||||||
|
if self.response.clicked() {
|
||||||
|
return Some(NoteAction::Profile(Pubkey::new(*note_pk)));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action.map(NoteAction::Media)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_actual_pfp(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
images: &mut Images,
|
||||||
|
pic: &str,
|
||||||
|
pfp_size: i8,
|
||||||
|
note_key: NoteKey,
|
||||||
|
profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>,
|
||||||
|
) -> PfpResponse {
|
||||||
|
let anim_speed = 0.05;
|
||||||
|
let profile_key = profile.as_ref().unwrap().record().note_key();
|
||||||
|
let note_key = note_key.as_u64();
|
||||||
|
|
||||||
|
let (rect, size, resp) = crate::anim::hover_expand(
|
||||||
|
ui,
|
||||||
|
egui::Id::new((profile_key, note_key)),
|
||||||
|
pfp_size as f32,
|
||||||
|
NoteView::expand_size() as f32,
|
||||||
|
anim_speed,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut pfp = ProfilePic::new(images, pic).size(size);
|
||||||
|
let pfp_resp = ui.put(rect, &mut pfp);
|
||||||
|
let action = pfp.action;
|
||||||
|
|
||||||
|
if resp.hovered() || resp.clicked() {
|
||||||
|
crate::show_pointer(ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
pfp_resp.on_hover_ui_at_pointer(|ui| {
|
||||||
|
ui.set_max_width(300.0);
|
||||||
|
ui.add(ProfilePreview::new(profile.as_ref().unwrap(), images));
|
||||||
|
});
|
||||||
|
|
||||||
|
PfpResponse {
|
||||||
|
response: resp,
|
||||||
|
action,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_fallback_pfp(ui: &mut egui::Ui, images: &mut Images, pfp_size: i8) -> PfpResponse {
|
||||||
|
let sense = Sense::click();
|
||||||
|
// This has to match the expand size from the above case to
|
||||||
|
// prevent bounciness
|
||||||
|
let size = (pfp_size + NoteView::expand_size()) as f32;
|
||||||
|
let (rect, _response) = ui.allocate_exact_size(egui::vec2(size, size), sense);
|
||||||
|
|
||||||
|
let mut pfp = ProfilePic::new(images, notedeck::profile::no_pfp_url()).size(pfp_size as f32);
|
||||||
|
let response = ui.put(rect, &mut pfp).interact(sense);
|
||||||
|
|
||||||
|
PfpResponse {
|
||||||
|
action: pfp.action,
|
||||||
|
response,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn note_hitbox_id(
|
fn note_hitbox_id(
|
||||||
note_key: NoteKey,
|
note_key: NoteKey,
|
||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
|
|||||||
Reference in New Issue
Block a user