notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

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, &note)
    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 }