mod.rs (5218B)
1 mod action; 2 mod context; 3 4 pub use action::{MediaAction, NoteAction, ScrollInfo, ZapAction, ZapTargetAmount}; 5 pub use context::{BroadcastContext, ContextSelection, NoteContextSelection}; 6 7 use crate::Accounts; 8 use crate::GlobalWallet; 9 use crate::JobPool; 10 use crate::Localization; 11 use crate::UnknownIds; 12 use crate::{notecache::NoteCache, zaps::Zaps, Images}; 13 use enostr::{NoteId, RelayPool}; 14 use nostrdb::{Ndb, Note, NoteKey, QueryResult, Transaction}; 15 use std::borrow::Borrow; 16 use std::cmp::Ordering; 17 use std::fmt; 18 19 /// Aggregates dependencies to reduce the number of parameters 20 /// passed to inner UI elements, minimizing prop drilling. 21 pub struct NoteContext<'d> { 22 pub ndb: &'d Ndb, 23 pub accounts: &'d Accounts, 24 pub global_wallet: &'d GlobalWallet, 25 pub i18n: &'d mut Localization, 26 pub img_cache: &'d mut Images, 27 pub note_cache: &'d mut NoteCache, 28 pub zaps: &'d mut Zaps, 29 pub pool: &'d mut RelayPool, 30 pub job_pool: &'d mut JobPool, 31 pub unknown_ids: &'d mut UnknownIds, 32 pub clipboard: &'d mut egui_winit::clipboard::Clipboard, 33 } 34 35 #[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] 36 pub struct NoteRef { 37 pub key: NoteKey, 38 pub created_at: u64, 39 } 40 41 #[derive(Clone, Copy, Eq, PartialEq, Hash)] 42 pub struct RootNoteIdBuf([u8; 32]); 43 44 impl fmt::Debug for RootNoteIdBuf { 45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 46 write!(f, "RootNoteIdBuf({})", self.hex()) 47 } 48 } 49 50 #[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)] 51 pub struct RootNoteId<'a>(&'a [u8; 32]); 52 53 impl RootNoteIdBuf { 54 pub fn to_note_id(self) -> NoteId { 55 NoteId::new(self.0) 56 } 57 58 pub fn bytes(&self) -> &[u8; 32] { 59 &self.0 60 } 61 62 pub fn new( 63 ndb: &Ndb, 64 note_cache: &mut NoteCache, 65 txn: &Transaction, 66 id: &[u8; 32], 67 ) -> Result<RootNoteIdBuf, RootIdError> { 68 root_note_id_from_selected_id(ndb, note_cache, txn, id).map(|rnid| Self(*rnid.bytes())) 69 } 70 71 pub fn hex(&self) -> String { 72 hex::encode(self.bytes()) 73 } 74 75 pub fn new_unsafe(id: [u8; 32]) -> Self { 76 Self(id) 77 } 78 79 pub fn borrow(&self) -> RootNoteId<'_> { 80 RootNoteId(self.bytes()) 81 } 82 } 83 84 impl<'a> RootNoteId<'a> { 85 pub fn to_note_id(self) -> NoteId { 86 NoteId::new(*self.0) 87 } 88 89 pub fn bytes(&self) -> &[u8; 32] { 90 self.0 91 } 92 93 pub fn hex(&self) -> String { 94 hex::encode(self.bytes()) 95 } 96 97 pub fn to_owned(&self) -> RootNoteIdBuf { 98 RootNoteIdBuf::new_unsafe(*self.bytes()) 99 } 100 101 pub fn new( 102 ndb: &Ndb, 103 note_cache: &mut NoteCache, 104 txn: &'a Transaction, 105 id: &'a [u8; 32], 106 ) -> Result<RootNoteId<'a>, RootIdError> { 107 root_note_id_from_selected_id(ndb, note_cache, txn, id) 108 } 109 110 pub fn new_unsafe(id: &'a [u8; 32]) -> Self { 111 Self(id) 112 } 113 } 114 115 impl Borrow<[u8; 32]> for RootNoteIdBuf { 116 fn borrow(&self) -> &[u8; 32] { 117 &self.0 118 } 119 } 120 121 impl Borrow<[u8; 32]> for RootNoteId<'_> { 122 fn borrow(&self) -> &[u8; 32] { 123 self.0 124 } 125 } 126 127 impl NoteRef { 128 pub fn new(key: NoteKey, created_at: u64) -> Self { 129 NoteRef { key, created_at } 130 } 131 132 pub fn from_note(note: &Note<'_>) -> Self { 133 let created_at = note.created_at(); 134 let key = note.key().expect("todo: implement NoteBuf"); 135 NoteRef::new(key, created_at) 136 } 137 138 pub fn from_query_result(qr: QueryResult<'_>) -> Self { 139 NoteRef { 140 key: qr.note_key, 141 created_at: qr.note.created_at(), 142 } 143 } 144 } 145 146 impl Ord for NoteRef { 147 fn cmp(&self, other: &Self) -> Ordering { 148 match self.created_at.cmp(&other.created_at) { 149 Ordering::Equal => self.key.cmp(&other.key), 150 Ordering::Less => Ordering::Greater, 151 Ordering::Greater => Ordering::Less, 152 } 153 } 154 } 155 156 impl PartialOrd for NoteRef { 157 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 158 Some(self.cmp(other)) 159 } 160 } 161 162 #[derive(Debug, Copy, Clone)] 163 pub enum RootIdError { 164 NoteNotFound, 165 NoRootId, 166 } 167 168 pub fn root_note_id_from_selected_id<'txn, 'a>( 169 ndb: &Ndb, 170 note_cache: &mut NoteCache, 171 txn: &'txn Transaction, 172 selected_note_id: &'a [u8; 32], 173 ) -> Result<RootNoteId<'txn>, RootIdError> 174 where 175 'a: 'txn, 176 { 177 let selected_note_key = if let Ok(key) = ndb.get_notekey_by_id(txn, selected_note_id) { 178 key 179 } else { 180 return Err(RootIdError::NoteNotFound); 181 }; 182 183 let note = if let Ok(note) = ndb.get_note_by_key(txn, selected_note_key) { 184 note 185 } else { 186 return Err(RootIdError::NoteNotFound); 187 }; 188 189 note_cache 190 .cached_note_or_insert(selected_note_key, ¬e) 191 .reply 192 .borrow(note.tags()) 193 .root() 194 .map_or_else( 195 || Ok(RootNoteId::new_unsafe(selected_note_id)), 196 |rnid| Ok(RootNoteId::new_unsafe(rnid.id)), 197 ) 198 } 199 200 pub fn event_tag<'a>(ev: &nostrdb::Note<'a>, name: &str) -> Option<&'a str> { 201 ev.tags().iter().find_map(|tag| { 202 if tag.count() < 2 { 203 return None; 204 } 205 206 let cur_name = tag.get_str(0)?; 207 208 if cur_name != name { 209 return None; 210 } 211 212 tag.get_str(1) 213 }) 214 }