commit a517bc69bc98af57800c978b253be7af4d5fa41c parent e2d79af632291ed703c97722b6285ea8239c6936 Author: William Casarin <jb55@jb55.com> Date: Wed, 16 Jul 2025 08:50:42 -0700 Merge is_following fixes from kernel kernelkind (4): add `Accounts` to `NoteContext` remove `MuteFun` prop make `Contacts::is_following` use bytes instead of `Pubkey` migrate to check following through `Contacts::is_following` Diffstat:
16 files changed, 84 insertions(+), 268 deletions(-)
diff --git a/crates/notedeck/src/account/contacts.rs b/crates/notedeck/src/account/contacts.rs @@ -49,14 +49,14 @@ impl Contacts { update_state(&mut self.state, &res.note, res.note_key); } - pub fn is_following(&self, other: &Pubkey) -> IsFollowing { + pub fn is_following(&self, other_pubkey: &[u8; 32]) -> IsFollowing { match &self.state { ContactState::Unreceived => IsFollowing::Unknown, ContactState::Received { contacts, note_key: _, } => { - if contacts.contains(other) { + if contacts.contains(other_pubkey) { IsFollowing::Yes } else { IsFollowing::No diff --git a/crates/notedeck/src/note/mod.rs b/crates/notedeck/src/note/mod.rs @@ -4,6 +4,7 @@ mod context; pub use action::{MediaAction, NoteAction, ScrollInfo, ZapAction, ZapTargetAmount}; pub use context::{BroadcastContext, ContextSelection, NoteContextSelection}; +use crate::Accounts; use crate::JobPool; use crate::UnknownIds; use crate::{notecache::NoteCache, zaps::Zaps, Images}; @@ -17,6 +18,7 @@ use std::fmt; /// passed to inner UI elements, minimizing prop drilling. pub struct NoteContext<'d> { pub ndb: &'d Ndb, + pub accounts: &'d Accounts, pub img_cache: &'d mut Images, pub note_cache: &'d mut NoteCache, pub zaps: &'d mut Zaps, diff --git a/crates/notedeck/src/user_account.rs b/crates/notedeck/src/user_account.rs @@ -1,4 +1,4 @@ -use enostr::{Keypair, KeypairUnowned, Pubkey}; +use enostr::{Keypair, KeypairUnowned}; use tokenator::{ParseError, TokenParser, TokenSerializable}; use crate::{ @@ -33,8 +33,8 @@ impl UserAccount { self } - pub fn is_following(&self, pk: &Pubkey) -> IsFollowing { - self.data.contacts.is_following(pk) + pub fn is_following(&self, other_pubkey: &[u8; 32]) -> IsFollowing { + self.data.contacts.is_following(other_pubkey) } } diff --git a/crates/notedeck_columns/src/nav.rs b/crates/notedeck_columns/src/nav.rs @@ -485,8 +485,10 @@ fn render_nav_body( col: usize, inner_rect: egui::Rect, ) -> Option<RenderNavAction> { + let current_account_has_wallet = get_current_wallet(ctx.accounts, ctx.global_wallet).is_some(); let mut note_context = NoteContext { ndb: ctx.ndb, + accounts: ctx.accounts, img_cache: ctx.img_cache, note_cache: ctx.note_cache, zaps: ctx.zaps, @@ -494,7 +496,7 @@ fn render_nav_body( job_pool: ctx.job_pool, unknown_ids: ctx.unknown_ids, clipboard: ctx.clipboard, - current_account_has_wallet: get_current_wallet(ctx.accounts, ctx.global_wallet).is_some(), + current_account_has_wallet, }; match top { Route::Timeline(kind) => { @@ -507,7 +509,6 @@ fn render_nav_body( let nav_action = render_timeline_route( &mut app.timeline_cache, - ctx.accounts, kind, col, app.note_options, @@ -527,7 +528,6 @@ fn render_nav_body( } Route::Thread(selection) => render_thread_route( &mut app.threads, - ctx.accounts, selection, col, app.note_options, @@ -676,11 +676,9 @@ fn render_nav_body( SearchView::new( &txn, - &ctx.accounts.mutefun(), app.note_options, search_buffer, &mut note_context, - &(&ctx.accounts.get_selected_account().key).into(), &mut app.jobs, ) .show(ui) diff --git a/crates/notedeck_columns/src/timeline/route.rs b/crates/notedeck_columns/src/timeline/route.rs @@ -6,13 +6,12 @@ use crate::{ }; use enostr::Pubkey; -use notedeck::{Accounts, MuteFun, NoteContext}; +use notedeck::NoteContext; use notedeck_ui::{jobs::JobsCache, NoteOptions}; #[allow(clippy::too_many_arguments)] pub fn render_timeline_route( timeline_cache: &mut TimelineCache, - accounts: &mut Accounts, kind: &TimelineKind, col: usize, note_options: NoteOptions, @@ -30,18 +29,10 @@ pub fn render_timeline_route( | TimelineKind::Universe | TimelineKind::Hashtag(_) | TimelineKind::Generic(_) => { - let note_action = ui::TimelineView::new( - kind, - timeline_cache, - &accounts.mutefun(), - note_context, - note_options, - &(&accounts.get_selected_account().key).into(), - jobs, - col, - ) - .scroll_to_top(scroll_to_top) - .ui(ui); + let note_action = + ui::TimelineView::new(kind, timeline_cache, note_context, note_options, jobs, col) + .scroll_to_top(scroll_to_top) + .ui(ui); note_action.map(RenderNavAction::NoteAction) } @@ -50,11 +41,9 @@ pub fn render_timeline_route( if depth > 1 { render_profile_route( pubkey, - accounts, timeline_cache, col, ui, - &accounts.mutefun(), note_options, note_context, jobs, @@ -64,10 +53,8 @@ pub fn render_timeline_route( let note_action = ui::TimelineView::new( kind, timeline_cache, - &accounts.mutefun(), note_context, note_options, - &(&accounts.get_selected_account().key).into(), jobs, col, ) @@ -83,7 +70,6 @@ pub fn render_timeline_route( #[allow(clippy::too_many_arguments)] pub fn render_thread_route( threads: &mut Threads, - accounts: &mut Accounts, selection: &ThreadSelection, col: usize, mut note_options: NoteOptions, @@ -99,9 +85,7 @@ pub fn render_thread_route( threads, selection.selected_or_root(), note_options, - &accounts.mutefun(), note_context, - &(&accounts.get_selected_account().key).into(), jobs, ) .id_source(col) @@ -112,22 +96,18 @@ pub fn render_thread_route( #[allow(clippy::too_many_arguments)] pub fn render_profile_route( pubkey: &Pubkey, - accounts: &Accounts, timeline_cache: &mut TimelineCache, col: usize, ui: &mut egui::Ui, - is_muted: &MuteFun, note_options: NoteOptions, note_context: &mut NoteContext, jobs: &mut JobsCache, ) -> Option<RenderNavAction> { let profile_view = ProfileView::new( pubkey, - accounts, col, timeline_cache, note_options, - is_muted, note_context, jobs, ) @@ -135,7 +115,8 @@ pub fn render_profile_route( if let Some(action) = profile_view { match action { - ui::profile::ProfileViewAction::EditProfile => accounts + ui::profile::ProfileViewAction::EditProfile => note_context + .accounts .get_full(pubkey) .map(|kp| RenderNavAction::ProfileAction(ProfileAction::Edit(kp.to_full()))), ui::profile::ProfileViewAction::Note(note_action) => { diff --git a/crates/notedeck_columns/src/ui/note/post.rs b/crates/notedeck_columns/src/ui/note/post.rs @@ -12,7 +12,7 @@ use egui::{ widgets::text_edit::TextEdit, Frame, Layout, Margin, Pos2, ScrollArea, Sense, TextBuffer, }; -use enostr::{FilledKeypair, FullKeypair, KeypairUnowned, NoteId, Pubkey, RelayPool}; +use enostr::{FilledKeypair, FullKeypair, NoteId, Pubkey, RelayPool}; use nostrdb::{Ndb, Transaction}; use notedeck_ui::{ app_images, @@ -352,15 +352,9 @@ impl<'a, 'd> PostView<'a, 'd> { 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, - zapping_acc.as_ref(), txn, id.bytes(), nostrdb::NoteKey::new(0), @@ -793,6 +787,7 @@ mod preview { let txn = Transaction::new(app.ndb).expect("txn"); let mut note_context = NoteContext { ndb: app.ndb, + accounts: app.accounts, img_cache: app.img_cache, note_cache: app.note_cache, zaps: app.zaps, 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, KeypairUnowned, NoteId}; +use enostr::{FilledKeypair, NoteId}; use notedeck::NoteContext; use notedeck_ui::jobs::JobsCache; use notedeck_ui::{NoteOptions, NoteView, ProfilePic}; @@ -67,27 +67,16 @@ 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, - zapping_acc.as_ref(), - self.note, - self.note_options, - self.jobs, - ) - .truncate(false) - .selectable_text(true) - .actionbar(false) - .medium_pfp(true) - .options_button(true) - .show(ui) + NoteView::new(self.note_context, self.note, self.note_options, self.jobs) + .truncate(false) + .selectable_text(true) + .actionbar(false) + .medium_pfp(true) + .options_button(true) + .show(ui) }) .inner; diff --git a/crates/notedeck_columns/src/ui/profile/mod.rs b/crates/notedeck_columns/src/ui/profile/mod.rs @@ -12,8 +12,8 @@ use crate::{ ui::timeline::{tabs_ui, TimelineTabView}, }; use notedeck::{ - name::get_display_name, profile::get_profile_url, Accounts, IsFollowing, MuteFun, NoteAction, - NoteContext, NotedeckTextStyle, + name::get_display_name, profile::get_profile_url, IsFollowing, NoteAction, NoteContext, + NotedeckTextStyle, }; use notedeck_ui::{ app_images, @@ -24,11 +24,9 @@ use notedeck_ui::{ pub struct ProfileView<'a, 'd> { pubkey: &'a Pubkey, - accounts: &'a Accounts, col_id: usize, timeline_cache: &'a mut TimelineCache, note_options: NoteOptions, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, jobs: &'a mut JobsCache, } @@ -44,21 +42,17 @@ impl<'a, 'd> ProfileView<'a, 'd> { #[allow(clippy::too_many_arguments)] pub fn new( pubkey: &'a Pubkey, - accounts: &'a Accounts, col_id: usize, timeline_cache: &'a mut TimelineCache, note_options: NoteOptions, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, jobs: &'a mut JobsCache, ) -> Self { ProfileView { pubkey, - accounts, col_id, timeline_cache, note_options, - is_muted, note_context, jobs, } @@ -116,9 +110,7 @@ impl<'a, 'd> ProfileView<'a, 'd> { reversed, self.note_options, &txn, - self.is_muted, self.note_context, - &(&self.accounts.get_selected_account().key).into(), self.jobs, ) .show(ui) @@ -179,14 +171,14 @@ impl<'a, 'd> ProfileView<'a, 'd> { ui.add_space(24.0); let target_key = self.pubkey; - let selected = self.accounts.get_selected_account(); + let selected = self.note_context.accounts.get_selected_account(); let profile_type = if selected.key.secret_key.is_none() { ProfileType::ReadOnly } else if &selected.key.pubkey == self.pubkey { ProfileType::MyProfile } else { - ProfileType::Followable(selected.is_following(target_key)) + ProfileType::Followable(selected.is_following(target_key.bytes())) }; match profile_type { diff --git a/crates/notedeck_columns/src/ui/search/mod.rs b/crates/notedeck_columns/src/ui/search/mod.rs @@ -1,11 +1,11 @@ use egui::{vec2, Align, Color32, CornerRadius, RichText, Stroke, TextEdit}; -use enostr::{KeypairUnowned, NoteId, Pubkey}; +use enostr::{NoteId, Pubkey}; use state::TypingType; use crate::{timeline::TimelineTab, ui::timeline::TimelineTabView}; use egui_winit::clipboard::Clipboard; use nostrdb::{Filter, Ndb, Transaction}; -use notedeck::{MuteFun, NoteAction, NoteContext, NoteRef}; +use notedeck::{NoteAction, NoteContext, NoteRef}; use notedeck_ui::{ context_menu::{input_context, PasteBehavior}, icons::search_icon, @@ -25,29 +25,23 @@ pub struct SearchView<'a, 'd> { query: &'a mut SearchQueryState, note_options: NoteOptions, txn: &'a Transaction, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, - cur_acc: &'a KeypairUnowned<'a>, jobs: &'a mut JobsCache, } impl<'a, 'd> SearchView<'a, 'd> { pub fn new( txn: &'a Transaction, - is_muted: &'a MuteFun, note_options: NoteOptions, query: &'a mut SearchQueryState, note_context: &'a mut NoteContext<'d>, - cur_acc: &'a KeypairUnowned<'a>, jobs: &'a mut JobsCache, ) -> Self { Self { txn, - is_muted, query, note_options, note_context, - cur_acc, jobs, } } @@ -155,9 +149,7 @@ impl<'a, 'd> SearchView<'a, 'd> { reversed, self.note_options, self.txn, - self.is_muted, self.note_context, - self.cur_acc, self.jobs, ) .show(ui) diff --git a/crates/notedeck_columns/src/ui/thread.rs b/crates/notedeck_columns/src/ui/thread.rs @@ -1,9 +1,8 @@ use egui::InnerResponse; use egui_virtual_list::VirtualList; -use enostr::KeypairUnowned; use nostrdb::{Note, Transaction}; use notedeck::note::root_note_id_from_selected_id; -use notedeck::{MuteFun, NoteAction, NoteContext}; +use notedeck::{NoteAction, NoteContext}; use notedeck_ui::jobs::JobsCache; use notedeck_ui::note::NoteResponse; use notedeck_ui::{NoteOptions, NoteView}; @@ -16,9 +15,7 @@ pub struct ThreadView<'a, 'd> { note_options: NoteOptions, col: usize, id_source: egui::Id, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, - cur_acc: &'a KeypairUnowned<'a>, jobs: &'a mut JobsCache, } @@ -28,9 +25,7 @@ impl<'a, 'd> ThreadView<'a, 'd> { threads: &'a mut Threads, selected_note_id: &'a [u8; 32], note_options: NoteOptions, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, - cur_acc: &'a KeypairUnowned<'a>, jobs: &'a mut JobsCache, ) -> Self { let id_source = egui::Id::new("threadscroll_threadview"); @@ -39,9 +34,7 @@ impl<'a, 'd> ThreadView<'a, 'd> { selected_note_id, note_options, id_source, - is_muted, note_context, - cur_acc, jobs, col: 0, } @@ -134,21 +127,14 @@ impl<'a, 'd> ThreadView<'a, 'd> { ui.colored_label(ui.visuals().error_fg_color, "LOADING NOTES"); } - let zapping_acc = self - .note_context - .current_account_has_wallet - .then_some(self.cur_acc); - show_notes( ui, list, ¬es, self.note_context, - zapping_acc, self.note_options, self.jobs, txn, - self.is_muted, ) } } @@ -159,11 +145,9 @@ fn show_notes( list: &mut VirtualList, thread_notes: &ThreadNotes, note_context: &mut NoteContext<'_>, - zapping_acc: Option<&KeypairUnowned<'_>>, flags: NoteOptions, jobs: &mut JobsCache, txn: &Transaction, - is_muted: &MuteFun, ) -> Option<NoteAction> { let mut action = None; @@ -173,6 +157,8 @@ fn show_notes( let selected_note_index = thread_notes.selected_index; let notes = &thread_notes.notes; + let is_muted = note_context.accounts.mutefun(); + list.ui_custom_layout(ui, notes.len(), |ui, cur_index| { let note = ¬es[cur_index]; @@ -190,7 +176,7 @@ fn show_notes( return 1; } - let resp = note.show(note_context, zapping_acc, flags, jobs, ui); + let resp = note.show(note_context, flags, jobs, ui); action = if cur_index == selected_note_index { resp.action.and_then(strip_note_action) @@ -313,21 +299,14 @@ impl<'a> ThreadNote<'a> { fn show( &self, note_context: &'a mut NoteContext<'_>, - zapping_acc: Option<&'a KeypairUnowned<'a>>, flags: NoteOptions, jobs: &'a mut JobsCache, ui: &mut egui::Ui, ) -> NoteResponse { let inner = notedeck_ui::padding(8.0, ui, |ui| { - NoteView::new( - note_context, - zapping_acc, - &self.note, - self.options(flags), - jobs, - ) - .unread_indicator(self.unread_and_have_replies) - .show(ui) + NoteView::new(note_context, &self.note, self.options(flags), jobs) + .unread_indicator(self.unread_and_have_replies) + .show(ui) }); match self.note_type { diff --git a/crates/notedeck_columns/src/ui/timeline.rs b/crates/notedeck_columns/src/ui/timeline.rs @@ -1,7 +1,6 @@ use egui::containers::scroll_area::ScrollBarVisibility; use egui::{vec2, Direction, Layout, Pos2, Stroke}; use egui_tabs::TabColor; -use enostr::KeypairUnowned; use nostrdb::Transaction; use notedeck::ui::is_narrow; use notedeck_ui::jobs::JobsCache; @@ -9,7 +8,7 @@ use std::f32::consts::PI; use tracing::{error, warn}; use crate::timeline::{TimelineCache, TimelineKind, TimelineTab, ViewFilter}; -use notedeck::{note::root_note_id_from_selected_id, MuteFun, NoteAction, NoteContext, ScrollInfo}; +use notedeck::{note::root_note_id_from_selected_id, NoteAction, NoteContext, ScrollInfo}; use notedeck_ui::{ anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE}, show_pointer, NoteOptions, NoteView, @@ -20,9 +19,7 @@ pub struct TimelineView<'a, 'd> { timeline_cache: &'a mut TimelineCache, note_options: NoteOptions, reverse: bool, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, - cur_acc: &'a KeypairUnowned<'a>, jobs: &'a mut JobsCache, col: usize, scroll_to_top: bool, @@ -33,10 +30,8 @@ impl<'a, 'd> TimelineView<'a, 'd> { pub fn new( timeline_id: &'a TimelineKind, timeline_cache: &'a mut TimelineCache, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, note_options: NoteOptions, - cur_acc: &'a KeypairUnowned<'a>, jobs: &'a mut JobsCache, col: usize, ) -> Self { @@ -47,9 +42,7 @@ impl<'a, 'd> TimelineView<'a, 'd> { timeline_cache, note_options, reverse, - is_muted, note_context, - cur_acc, jobs, col, scroll_to_top, @@ -63,9 +56,7 @@ impl<'a, 'd> TimelineView<'a, 'd> { self.timeline_cache, self.reverse, self.note_options, - self.is_muted, self.note_context, - self.cur_acc, self.jobs, self.col, self.scroll_to_top, @@ -90,9 +81,7 @@ fn timeline_ui( timeline_cache: &mut TimelineCache, reversed: bool, note_options: NoteOptions, - is_muted: &MuteFun, note_context: &mut NoteContext, - cur_acc: &KeypairUnowned, jobs: &mut JobsCache, col: usize, scroll_to_top: bool, @@ -187,9 +176,7 @@ fn timeline_ui( reversed, note_options, &txn, - is_muted, note_context, - cur_acc, jobs, ) .show(ui) @@ -372,9 +359,7 @@ pub struct TimelineTabView<'a, 'd> { reversed: bool, note_options: NoteOptions, txn: &'a Transaction, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, - cur_acc: &'a KeypairUnowned<'a>, jobs: &'a mut JobsCache, } @@ -385,9 +370,7 @@ impl<'a, 'd> TimelineTabView<'a, 'd> { reversed: bool, note_options: NoteOptions, txn: &'a Transaction, - is_muted: &'a MuteFun, note_context: &'a mut NoteContext<'d>, - cur_acc: &'a KeypairUnowned<'a>, jobs: &'a mut JobsCache, ) -> Self { Self { @@ -395,9 +378,7 @@ impl<'a, 'd> TimelineTabView<'a, 'd> { reversed, note_options, txn, - is_muted, note_context, - cur_acc, jobs, } } @@ -406,7 +387,7 @@ impl<'a, 'd> TimelineTabView<'a, 'd> { let mut action: Option<NoteAction> = None; let len = self.tab.notes.len(); - let is_muted = self.is_muted; + let is_muted = self.note_context.accounts.mutefun(); self.tab .list @@ -444,21 +425,10 @@ impl<'a, 'd> TimelineTabView<'a, 'd> { }; if !muted { - let zapping_acc = if self.note_context.current_account_has_wallet { - Some(self.cur_acc) - } else { - None - }; - notedeck_ui::padding(8.0, ui, |ui| { - let resp = NoteView::new( - self.note_context, - zapping_acc, - ¬e, - self.note_options, - self.jobs, - ) - .show(ui); + let resp = + NoteView::new(self.note_context, ¬e, self.note_options, self.jobs) + .show(ui); if let Some(note_action) = resp.action { action = Some(note_action) diff --git a/crates/notedeck_dave/src/ui/dave.rs b/crates/notedeck_dave/src/ui/dave.rs @@ -211,6 +211,7 @@ impl<'a> DaveUi<'a> { ) -> Option<NoteAction> { let mut note_context = NoteContext { ndb: ctx.ndb, + accounts: ctx.accounts, img_cache: ctx.img_cache, note_cache: ctx.note_cache, zaps: ctx.zaps, @@ -243,7 +244,6 @@ impl<'a> DaveUi<'a> { |ui| { notedeck_ui::NoteView::new( &mut note_context, - None, ¬e, NoteOptions::default(), jobs, diff --git a/crates/notedeck_ui/src/contacts.rs b/crates/notedeck_ui/src/contacts.rs @@ -1,58 +1,5 @@ -use nostrdb::{Filter, Ndb, Note, Transaction}; - -fn pk1_is_following_pk2( - ndb: &Ndb, - txn: &Transaction, - pk1: &[u8; 32], - pk2: &[u8; 32], -) -> Option<bool> { - let note = get_contacts_note(ndb, txn, pk1)?; - - Some(note_follows(note, pk2)) -} - -pub fn trust_media_from_pk2( - ndb: &Ndb, - txn: &Transaction, - pk1: Option<&[u8; 32]>, - pk2: &[u8; 32], -) -> bool { - pk1.map(|pk| pk == pk2 || pk1_is_following_pk2(ndb, txn, pk, pk2).unwrap_or(false)) - .unwrap_or(false) -} - -fn get_contacts_note<'a>(ndb: &'a Ndb, txn: &'a Transaction, user: &[u8; 32]) -> Option<Note<'a>> { - Some( - ndb.query(txn, &[contacts_filter(user)], 1) - .ok()? - .first()? - .note - .clone(), - ) -} +use nostrdb::Filter; pub fn contacts_filter(pk: &[u8; 32]) -> Filter { Filter::new().authors([pk]).kinds([3]).limit(1).build() } - -fn note_follows(contacts_note: Note<'_>, pk: &[u8; 32]) -> bool { - for tag in contacts_note.tags() { - if tag.count() < 2 { - continue; - } - - let Some("p") = tag.get_str(0) else { - continue; - }; - - let Some(author) = tag.get_id(1) else { - continue; - }; - - if pk == author { - return true; - } - } - - false -} diff --git a/crates/notedeck_ui/src/note/contents.rs b/crates/notedeck_ui/src/note/contents.rs @@ -2,23 +2,20 @@ use std::cell::OnceCell; use crate::{ blur::imeta_blurhashes, - contacts::trust_media_from_pk2, jobs::JobsCache, note::{NoteAction, NoteOptions, NoteResponse, NoteView}, }; use egui::{Color32, Hyperlink, RichText}; -use enostr::KeypairUnowned; use nostrdb::{BlockType, Mention, Note, NoteKey, Transaction}; use tracing::warn; -use notedeck::NoteContext; +use notedeck::{IsFollowing, NoteContext}; use super::media::{find_renderable_media, image_carousel, RenderableMedia}; pub struct NoteContents<'a, 'd> { note_context: &'a mut NoteContext<'d>, - cur_acc: Option<&'a KeypairUnowned<'a>>, txn: &'a Transaction, note: &'a Note<'a>, options: NoteOptions, @@ -30,7 +27,6 @@ impl<'a, 'd> NoteContents<'a, 'd> { #[allow(clippy::too_many_arguments)] pub fn new( note_context: &'a mut NoteContext<'d>, - cur_acc: Option<&'a KeypairUnowned<'a>>, txn: &'a Transaction, note: &'a Note, options: NoteOptions, @@ -38,7 +34,6 @@ impl<'a, 'd> NoteContents<'a, 'd> { ) -> Self { NoteContents { note_context, - cur_acc, txn, note, options, @@ -53,7 +48,6 @@ impl egui::Widget for &mut NoteContents<'_, '_> { let result = render_note_contents( ui, self.note_context, - self.cur_acc, self.txn, self.note, self.options, @@ -71,7 +65,6 @@ impl egui::Widget for &mut NoteContents<'_, '_> { pub fn render_note_preview( ui: &mut egui::Ui, note_context: &mut NoteContext, - cur_acc: Option<&KeypairUnowned>, txn: &Transaction, id: &[u8; 32], parent: NoteKey, @@ -105,7 +98,7 @@ pub fn render_note_preview( */ }; - NoteView::new(note_context, cur_acc, ¬e, note_options, jobs) + NoteView::new(note_context, ¬e, note_options, jobs) .preview_style() .parent(parent) .show(ui) @@ -116,7 +109,6 @@ pub fn render_note_preview( pub fn render_note_contents( ui: &mut egui::Ui, note_context: &mut NoteContext, - cur_acc: Option<&KeypairUnowned>, txn: &Transaction, note: &Note, options: NoteOptions, @@ -275,7 +267,7 @@ pub fn render_note_contents( }); let preview_note_action = inline_note.and_then(|(id, _)| { - render_note_preview(ui, note_context, cur_acc, txn, id, note_key, options, jobs) + render_note_preview(ui, note_context, txn, id, note_key, options, jobs) .action .map(|a| match a { NoteAction::Note { note_id, .. } => NoteAction::Note { @@ -291,12 +283,11 @@ pub fn render_note_contents( ui.add_space(2.0); let carousel_id = egui::Id::new(("carousel", note.key().expect("expected tx note"))); - let trusted_media = trust_media_from_pk2( - note_context.ndb, - txn, - cur_acc.as_ref().map(|k| k.pubkey.bytes()), - note.pubkey(), - ); + let trusted_media = note_context + .accounts + .get_selected_account() + .is_following(note.pubkey()) + == IsFollowing::Yes; media_action = image_carousel( ui, diff --git a/crates/notedeck_ui/src/note/mod.rs b/crates/notedeck_ui/src/note/mod.rs @@ -33,7 +33,6 @@ use notedeck::{ pub struct NoteView<'a, 'd> { note_context: &'a mut NoteContext<'d>, - zapping_acc: Option<&'a KeypairUnowned<'a>>, parent: Option<NoteKey>, note: &'a nostrdb::Note<'a>, framed: bool, @@ -85,7 +84,6 @@ impl egui::Widget for &mut NoteView<'_, '_> { impl<'a, 'd> NoteView<'a, 'd> { pub fn new( note_context: &'a mut NoteContext<'d>, - zapping_acc: Option<&'a KeypairUnowned<'a>>, note: &'a nostrdb::Note<'a>, mut flags: NoteOptions, jobs: &'a mut JobsCache, @@ -98,7 +96,6 @@ impl<'a, 'd> NoteView<'a, 'd> { Self { note_context, - zapping_acc, parent, note, flags, @@ -231,7 +228,6 @@ impl<'a, 'd> NoteView<'a, 'd> { ui.add(&mut NoteContents::new( self.note_context, - self.zapping_acc, txn, self.note, self.flags, @@ -317,14 +313,7 @@ impl<'a, 'd> NoteView<'a, 'd> { .text_style(style.text_style()), ); }); - NoteView::new( - self.note_context, - self.zapping_acc, - ¬e_to_repost, - self.flags, - self.jobs, - ) - .show(ui) + NoteView::new(self.note_context, ¬e_to_repost, self.flags, self.jobs).show(ui) } pub fn show_impl(&mut self, ui: &mut egui::Ui) -> NoteResponse { @@ -440,7 +429,6 @@ impl<'a, 'd> NoteView<'a, 'd> { ui.horizontal(|ui| { note_action = reply_desc( ui, - self.zapping_acc, txn, ¬e_reply, self.note_context, @@ -455,32 +443,27 @@ impl<'a, 'd> NoteView<'a, 'd> { }) .inner; - let mut contents = NoteContents::new( - self.note_context, - self.zapping_acc, - txn, - self.note, - self.flags, - self.jobs, - ); + let mut contents = + NoteContents::new(self.note_context, txn, self.note, self.flags, self.jobs); ui.add(&mut contents); note_action = contents.action.or(note_action); if self.options().contains(NoteOptions::ActionBar) { - note_action = render_note_actionbar( - ui, - self.zapping_acc.as_ref().map(|c| Zapper { + let zapper = { + let cur_acc = self.note_context.accounts.get_selected_account(); + let has_wallet = cur_acc.wallet.is_some(); + + has_wallet.then_some(Zapper { zaps: self.note_context.zaps, - cur_acc: c, - }), - self.note.id(), - self.note.pubkey(), - note_key, - ) - .inner - .or(note_action); + cur_acc: cur_acc.keypair(), + }) + }; + note_action = + render_note_actionbar(ui, zapper, self.note.id(), self.note.pubkey(), note_key) + .inner + .or(note_action); } NoteUiResponse { @@ -527,7 +510,6 @@ impl<'a, 'd> NoteView<'a, 'd> { note_action = reply_desc( ui, - self.zapping_acc, txn, ¬e_reply, self.note_context, @@ -537,25 +519,25 @@ impl<'a, 'd> NoteView<'a, 'd> { .or(note_action.take()); }); - let mut contents = NoteContents::new( - self.note_context, - self.zapping_acc, - txn, - self.note, - self.flags, - self.jobs, - ); + let mut contents = + NoteContents::new(self.note_context, txn, self.note, self.flags, self.jobs); ui.add(&mut contents); note_action = contents.action.or(note_action); + let zapper = { + let cur_acc = self.note_context.accounts.get_selected_account(); + let has_wallet = cur_acc.wallet.is_some(); + + has_wallet.then_some(Zapper { + zaps: self.note_context.zaps, + cur_acc: cur_acc.keypair(), + }) + }; if self.options().contains(NoteOptions::ActionBar) { note_action = render_note_actionbar( ui, - self.zapping_acc.as_ref().map(|c| Zapper { - zaps: self.note_context.zaps, - cur_acc: c, - }), + zapper, self.note.id(), self.note.pubkey(), note_key, @@ -774,7 +756,7 @@ fn note_hitbox_clicked( struct Zapper<'a> { zaps: &'a Zaps, - cur_acc: &'a KeypairUnowned<'a>, + cur_acc: KeypairUnowned<'a>, } #[profiling::function] diff --git a/crates/notedeck_ui/src/note/reply_description.rs b/crates/notedeck_ui/src/note/reply_description.rs @@ -3,14 +3,12 @@ use nostrdb::{Note, NoteReply, Transaction}; use super::NoteOptions; use crate::{jobs::JobsCache, note::NoteView, Mention}; -use enostr::KeypairUnowned; use notedeck::{NoteAction, NoteContext}; #[must_use = "Please handle the resulting note action"] #[profiling::function] pub fn reply_desc( ui: &mut egui::Ui, - cur_acc: Option<&KeypairUnowned>, txn: &Transaction, note_reply: &NoteReply, note_context: &mut NoteContext, @@ -43,7 +41,7 @@ pub fn reply_desc( if r.hovered() { r.on_hover_ui_at_pointer(|ui| { ui.set_max_width(400.0); - NoteView::new(note_context, cur_acc, note, note_options, jobs) + NoteView::new(note_context, note, note_options, jobs) .actionbar(false) .wide(true) .show(ui);