commit 54c0fdb563a2d9bd4e633b8249597a4895f44863
parent 86d2a9e2e78b4d20503c67cea8b6362ff4341f05
Author: kernelkind <kernelkind@gmail.com>
Date: Wed, 7 May 2025 14:36:56 -0400
don't show zap button if no wallet
Signed-off-by: kernelkind <kernelkind@gmail.com>
Diffstat:
10 files changed, 84 insertions(+), 58 deletions(-)
diff --git a/crates/enostr/src/keypair.rs b/crates/enostr/src/keypair.rs
@@ -84,8 +84,8 @@ impl<'a> FilledKeypair<'a> {
}
}
-impl<'a> From<FilledKeypair<'a>> for KeypairUnowned<'a> {
- fn from(value: FilledKeypair<'a>) -> Self {
+impl<'a> From<&'a FilledKeypair<'a>> for KeypairUnowned<'a> {
+ fn from(value: &'a FilledKeypair<'a>) -> Self {
Self {
pubkey: value.pubkey,
secret_key: Some(value.secret_key),
diff --git a/crates/notedeck/src/note/mod.rs b/crates/notedeck/src/note/mod.rs
@@ -21,6 +21,7 @@ pub struct NoteContext<'d> {
pub zaps: &'d mut Zaps,
pub pool: &'d mut RelayPool,
pub job_pool: &'d mut JobPool,
+ pub current_account_has_wallet: bool,
}
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
diff --git a/crates/notedeck_columns/src/nav.rs b/crates/notedeck_columns/src/nav.rs
@@ -27,7 +27,7 @@ use crate::{
use egui_nav::{Nav, NavAction, NavResponse, NavUiType};
use nostrdb::Transaction;
-use notedeck::{AccountsAction, AppContext, NoteAction, NoteContext};
+use notedeck::{get_current_wallet, AccountsAction, AppContext, NoteAction, NoteContext};
use notedeck_ui::View;
use tracing::error;
@@ -277,6 +277,7 @@ fn render_nav_body(
zaps: ctx.zaps,
pool: ctx.pool,
job_pool: ctx.job_pool,
+ current_account_has_wallet: get_current_wallet(ctx.accounts, ctx.global_wallet).is_some(),
};
match top {
Route::Timeline(kind) => render_timeline_route(
diff --git a/crates/notedeck_columns/src/ui/note/post.rs b/crates/notedeck_columns/src/ui/note/post.rs
@@ -11,7 +11,7 @@ use egui::{
widgets::text_edit::TextEdit,
Frame, Layout, Margin, Pos2, ScrollArea, Sense, TextBuffer,
};
-use enostr::{FilledKeypair, FullKeypair, NoteId, Pubkey, RelayPool};
+use enostr::{FilledKeypair, FullKeypair, KeypairUnowned, NoteId, Pubkey, RelayPool};
use nostrdb::{Ndb, Transaction};
use notedeck_ui::blur::PixelDimensions;
use notedeck_ui::images::{get_render_state, RenderState};
@@ -341,10 +341,16 @@ impl<'a, 'd> PostView<'a, 'd> {
.show(ui, |ui| {
ui.vertical(|ui| {
ui.set_max_width(avail_size.x * 0.8);
+
+ let zapping_acc = self
+ .note_context
+ .current_account_has_wallet
+ .then(|| KeypairUnowned::from(&self.poster));
+
render_note_preview(
ui,
self.note_context,
- &Some(self.poster.into()),
+ zapping_acc.as_ref(),
txn,
id.bytes(),
nostrdb::NoteKey::new(0),
@@ -778,6 +784,7 @@ mod preview {
zaps: app.zaps,
pool: app.pool,
job_pool: app.job_pool,
+ current_account_has_wallet: false,
};
PostView::new(
diff --git a/crates/notedeck_columns/src/ui/note/reply.rs b/crates/notedeck_columns/src/ui/note/reply.rs
@@ -4,7 +4,7 @@ use crate::ui::{
note::{PostAction, PostResponse, PostType},
};
-use enostr::{FilledKeypair, NoteId};
+use enostr::{FilledKeypair, KeypairUnowned, NoteId};
use notedeck::NoteContext;
use notedeck_ui::jobs::JobsCache;
use notedeck_ui::{NoteOptions, NoteView, ProfilePic};
@@ -67,12 +67,17 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
let note_offset: i8 =
pfp_offset - ProfilePic::medium_size() / 2 - NoteView::expand_size() / 2;
+ let zapping_acc = self
+ .note_context
+ .current_account_has_wallet
+ .then(|| KeypairUnowned::from(&self.poster));
+
let quoted_note = egui::Frame::NONE
.outer_margin(egui::Margin::same(note_offset))
.show(ui, |ui| {
NoteView::new(
self.note_context,
- &Some(self.poster.into()),
+ zapping_acc.as_ref(),
self.note,
self.note_options,
self.jobs,
diff --git a/crates/notedeck_columns/src/ui/timeline.rs b/crates/notedeck_columns/src/ui/timeline.rs
@@ -399,10 +399,15 @@ impl<'a, 'd> TimelineTabView<'a, 'd> {
};
if !muted {
+ let zapping_acc = self
+ .cur_acc
+ .as_ref()
+ .filter(|_| self.note_context.current_account_has_wallet);
+
notedeck_ui::padding(8.0, ui, |ui| {
let resp = NoteView::new(
self.note_context,
- self.cur_acc,
+ zapping_acc,
¬e,
self.note_options,
self.jobs,
diff --git a/crates/notedeck_dave/src/ui/dave.rs b/crates/notedeck_dave/src/ui/dave.rs
@@ -229,6 +229,7 @@ impl<'a> DaveUi<'a> {
zaps: ctx.zaps,
pool: ctx.pool,
job_pool: ctx.job_pool,
+ current_account_has_wallet: false,
};
let txn = Transaction::new(note_context.ndb).unwrap();
@@ -253,7 +254,7 @@ impl<'a> DaveUi<'a> {
|ui| {
notedeck_ui::NoteView::new(
&mut note_context,
- &None,
+ None,
¬e,
NoteOptions::default(),
jobs,
diff --git a/crates/notedeck_ui/src/note/contents.rs b/crates/notedeck_ui/src/note/contents.rs
@@ -18,7 +18,7 @@ use super::media::{find_renderable_media, image_carousel, RenderableMedia};
pub struct NoteContents<'a, 'd> {
note_context: &'a mut NoteContext<'d>,
- cur_acc: &'a Option<KeypairUnowned<'a>>,
+ cur_acc: Option<&'a KeypairUnowned<'a>>,
txn: &'a Transaction,
note: &'a Note<'a>,
options: NoteOptions,
@@ -30,7 +30,7 @@ impl<'a, 'd> NoteContents<'a, 'd> {
#[allow(clippy::too_many_arguments)]
pub fn new(
note_context: &'a mut NoteContext<'d>,
- cur_acc: &'a Option<KeypairUnowned<'a>>,
+ cur_acc: Option<&'a KeypairUnowned<'a>>,
txn: &'a Transaction,
note: &'a Note,
options: NoteOptions,
@@ -71,7 +71,7 @@ impl egui::Widget for &mut NoteContents<'_, '_> {
pub fn render_note_preview(
ui: &mut egui::Ui,
note_context: &mut NoteContext,
- cur_acc: &Option<KeypairUnowned>,
+ cur_acc: Option<&KeypairUnowned>,
txn: &Transaction,
id: &[u8; 32],
parent: NoteKey,
@@ -112,7 +112,7 @@ pub fn render_note_preview(
pub fn render_note_contents(
ui: &mut egui::Ui,
note_context: &mut NoteContext,
- cur_acc: &Option<KeypairUnowned>,
+ cur_acc: Option<&KeypairUnowned>,
txn: &Transaction,
note: &Note,
options: NoteOptions,
diff --git a/crates/notedeck_ui/src/note/mod.rs b/crates/notedeck_ui/src/note/mod.rs
@@ -30,7 +30,7 @@ use notedeck::{
pub struct NoteView<'a, 'd> {
note_context: &'a mut NoteContext<'d>,
- cur_acc: &'a Option<KeypairUnowned<'a>>,
+ zapping_acc: Option<&'a KeypairUnowned<'a>>,
parent: Option<NoteKey>,
note: &'a nostrdb::Note<'a>,
framed: bool,
@@ -74,7 +74,7 @@ impl egui::Widget for &mut NoteView<'_, '_> {
impl<'a, 'd> NoteView<'a, 'd> {
pub fn new(
note_context: &'a mut NoteContext<'d>,
- cur_acc: &'a Option<KeypairUnowned<'a>>,
+ zapping_acc: Option<&'a KeypairUnowned<'a>>,
note: &'a nostrdb::Note<'a>,
mut flags: NoteOptions,
jobs: &'a mut JobsCache,
@@ -87,7 +87,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
Self {
note_context,
- cur_acc,
+ zapping_acc,
parent,
note,
flags,
@@ -214,7 +214,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
ui.add(&mut NoteContents::new(
self.note_context,
- self.cur_acc,
+ self.zapping_acc,
txn,
self.note,
self.flags,
@@ -338,7 +338,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
});
NoteView::new(
self.note_context,
- self.cur_acc,
+ self.zapping_acc,
¬e_to_repost,
self.flags,
self.jobs,
@@ -441,7 +441,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
.horizontal(|ui| {
reply_desc(
ui,
- self.cur_acc,
+ self.zapping_acc,
txn,
¬e_reply,
self.note_context,
@@ -460,7 +460,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
let mut contents = NoteContents::new(
self.note_context,
- self.cur_acc,
+ self.zapping_acc,
txn,
self.note,
self.flags,
@@ -476,8 +476,10 @@ impl<'a, 'd> NoteView<'a, 'd> {
if self.options().has_actionbar() {
if let Some(action) = render_note_actionbar(
ui,
- self.note_context.zaps,
- self.cur_acc.as_ref(),
+ self.zapping_acc.as_ref().map(|c| Zapper {
+ zaps: self.note_context.zaps,
+ cur_acc: c,
+ }),
self.note.id(),
self.note.pubkey(),
note_key,
@@ -514,7 +516,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
if note_reply.reply().is_some() {
let action = reply_desc(
ui,
- self.cur_acc,
+ self.zapping_acc,
txn,
¬e_reply,
self.note_context,
@@ -530,7 +532,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
let mut contents = NoteContents::new(
self.note_context,
- self.cur_acc,
+ self.zapping_acc,
txn,
self.note,
self.flags,
@@ -545,8 +547,10 @@ impl<'a, 'd> NoteView<'a, 'd> {
if self.options().has_actionbar() {
if let Some(action) = render_note_actionbar(
ui,
- self.note_context.zaps,
- self.cur_acc.as_ref(),
+ self.zapping_acc.as_ref().map(|c| Zapper {
+ zaps: self.note_context.zaps,
+ cur_acc: c,
+ }),
self.note.id(),
self.note.pubkey(),
note_key,
@@ -657,11 +661,15 @@ fn note_hitbox_clicked(
}
}
+struct Zapper<'a> {
+ zaps: &'a Zaps,
+ cur_acc: &'a KeypairUnowned<'a>,
+}
+
#[profiling::function]
fn render_note_actionbar(
ui: &mut egui::Ui,
- zaps: &Zaps,
- cur_acc: Option<&KeypairUnowned>,
+ zapper: Option<Zapper>,
note_id: &[u8; 32],
note_pubkey: &[u8; 32],
note_key: NoteKey,
@@ -670,29 +678,7 @@ fn render_note_actionbar(
let reply_resp = reply_button(ui, note_key);
let quote_resp = quote_repost_button(ui, note_key);
- let zap_target = ZapTarget::Note(NoteZapTarget {
- note_id,
- zap_recipient: note_pubkey,
- });
-
- let zap_state = cur_acc.map_or_else(
- || Ok(AnyZapState::None),
- |kp| zaps.any_zap_state_for(kp.pubkey.bytes(), zap_target),
- );
- let zap_resp = cur_acc
- .filter(|k| k.secret_key.is_some())
- .map(|_| match &zap_state {
- Ok(any_zap_state) => ui.add(zap_button(any_zap_state.clone(), note_id)),
- Err(zapping_error) => {
- let (rect, _) =
- ui.allocate_at_least(egui::vec2(10.0, 10.0), egui::Sense::click());
- ui.add(x_button(rect))
- .on_hover_text(format!("{zapping_error}"))
- }
- });
-
let to_noteid = |id: &[u8; 32]| NoteId::new(*id);
-
if reply_resp.clicked() {
break 's Some(NoteAction::Reply(to_noteid(note_id)));
} else if reply_resp.hovered() {
@@ -705,17 +691,16 @@ fn render_note_actionbar(
crate::show_pointer(ui);
}
- let Some(zap_resp) = zap_resp else {
+ let Some(Zapper { zaps, cur_acc }) = zapper else {
break 's None;
};
- if zap_resp.hovered() {
- crate::show_pointer(ui);
- }
+ let zap_target = ZapTarget::Note(NoteZapTarget {
+ note_id,
+ zap_recipient: note_pubkey,
+ });
- if !zap_resp.clicked() {
- break 's None;
- }
+ let zap_state = zaps.any_zap_state_for(cur_acc.pubkey.bytes(), zap_target);
let target = NoteZapTargetOwned {
note_id: to_noteid(note_id),
@@ -726,6 +711,27 @@ fn render_note_actionbar(
break 's Some(NoteAction::Zap(ZapAction::ClearError(target)));
}
+ let zap_resp = {
+ cur_acc.secret_key.as_ref()?;
+
+ match zap_state {
+ Ok(any_zap_state) => ui.add(zap_button(any_zap_state, note_id)),
+ Err(err) => {
+ let (rect, _) =
+ ui.allocate_at_least(egui::vec2(10.0, 10.0), egui::Sense::click());
+ ui.add(x_button(rect)).on_hover_text(err.to_string())
+ }
+ }
+ };
+
+ if zap_resp.hovered() {
+ crate::show_pointer(ui);
+ }
+
+ if !zap_resp.clicked() {
+ break 's None;
+ }
+
Some(NoteAction::Zap(ZapAction::Send(ZapTargetAmount {
target,
specified_msats: None,
diff --git a/crates/notedeck_ui/src/note/reply_description.rs b/crates/notedeck_ui/src/note/reply_description.rs
@@ -10,7 +10,7 @@ use notedeck::{NoteAction, NoteContext};
#[profiling::function]
pub fn reply_desc(
ui: &mut egui::Ui,
- cur_acc: &Option<KeypairUnowned>,
+ cur_acc: Option<&KeypairUnowned>,
txn: &Transaction,
note_reply: &NoteReply,
note_context: &mut NoteContext,