notedeck

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

actionbar.rs (4838B)


      1 use crate::{
      2     column::Columns,
      3     notes_holder::{NotesHolder, NotesHolderStorage},
      4     profile::Profile,
      5     route::{Route, Router},
      6     thread::Thread,
      7 };
      8 
      9 use enostr::{NoteId, Pubkey, RelayPool};
     10 use nostrdb::{Ndb, Transaction};
     11 use notedeck::{note::root_note_id_from_selected_id, MuteFun, NoteCache, NoteRef};
     12 
     13 #[derive(Debug, Eq, PartialEq, Copy, Clone)]
     14 pub enum NoteAction {
     15     Reply(NoteId),
     16     Quote(NoteId),
     17     OpenThread(NoteId),
     18     OpenProfile(Pubkey),
     19 }
     20 
     21 pub struct NewNotes {
     22     pub id: [u8; 32],
     23     pub notes: Vec<NoteRef>,
     24 }
     25 
     26 pub enum NotesHolderResult {
     27     NewNotes(NewNotes),
     28 }
     29 
     30 /// open_thread is called when a note is selected and we need to navigate
     31 /// to a thread It is responsible for managing the subscription and
     32 /// making sure the thread is up to date. In a sense, it's a model for
     33 /// the thread view. We don't have a concept of model/view/controller etc
     34 /// in egui, but this is the closest thing to that.
     35 #[allow(clippy::too_many_arguments)]
     36 fn open_thread(
     37     ndb: &Ndb,
     38     txn: &Transaction,
     39     router: &mut Router<Route>,
     40     note_cache: &mut NoteCache,
     41     pool: &mut RelayPool,
     42     threads: &mut NotesHolderStorage<Thread>,
     43     selected_note: &[u8; 32],
     44     is_muted: &MuteFun,
     45 ) -> Option<NotesHolderResult> {
     46     router.route_to(Route::thread(NoteId::new(selected_note.to_owned())));
     47 
     48     let root_id = root_note_id_from_selected_id(ndb, note_cache, txn, selected_note);
     49     Thread::open(ndb, note_cache, txn, pool, threads, root_id, is_muted)
     50 }
     51 
     52 impl NoteAction {
     53     #[allow(clippy::too_many_arguments)]
     54     pub fn execute(
     55         self,
     56         ndb: &Ndb,
     57         router: &mut Router<Route>,
     58         threads: &mut NotesHolderStorage<Thread>,
     59         profiles: &mut NotesHolderStorage<Profile>,
     60         note_cache: &mut NoteCache,
     61         pool: &mut RelayPool,
     62         txn: &Transaction,
     63         is_muted: &MuteFun,
     64     ) -> Option<NotesHolderResult> {
     65         match self {
     66             NoteAction::Reply(note_id) => {
     67                 router.route_to(Route::reply(note_id));
     68                 None
     69             }
     70 
     71             NoteAction::OpenThread(note_id) => open_thread(
     72                 ndb,
     73                 txn,
     74                 router,
     75                 note_cache,
     76                 pool,
     77                 threads,
     78                 note_id.bytes(),
     79                 is_muted,
     80             ),
     81 
     82             NoteAction::OpenProfile(pubkey) => {
     83                 router.route_to(Route::profile(pubkey));
     84                 Profile::open(
     85                     ndb,
     86                     note_cache,
     87                     txn,
     88                     pool,
     89                     profiles,
     90                     pubkey.bytes(),
     91                     is_muted,
     92                 )
     93             }
     94 
     95             NoteAction::Quote(note_id) => {
     96                 router.route_to(Route::quote(note_id));
     97                 None
     98             }
     99         }
    100     }
    101 
    102     /// Execute the NoteAction and process the NotesHolderResult
    103     #[allow(clippy::too_many_arguments)]
    104     pub fn execute_and_process_result(
    105         self,
    106         ndb: &Ndb,
    107         columns: &mut Columns,
    108         col: usize,
    109         threads: &mut NotesHolderStorage<Thread>,
    110         profiles: &mut NotesHolderStorage<Profile>,
    111         note_cache: &mut NoteCache,
    112         pool: &mut RelayPool,
    113         txn: &Transaction,
    114         is_muted: &MuteFun,
    115     ) {
    116         let router = columns.column_mut(col).router_mut();
    117         if let Some(br) = self.execute(
    118             ndb, router, threads, profiles, note_cache, pool, txn, is_muted,
    119         ) {
    120             br.process(ndb, note_cache, txn, threads, is_muted);
    121         }
    122     }
    123 }
    124 
    125 impl NotesHolderResult {
    126     pub fn new_notes(notes: Vec<NoteRef>, id: [u8; 32]) -> Self {
    127         NotesHolderResult::NewNotes(NewNotes::new(notes, id))
    128     }
    129 
    130     pub fn process<N: NotesHolder>(
    131         &self,
    132         ndb: &Ndb,
    133         note_cache: &mut NoteCache,
    134         txn: &Transaction,
    135         storage: &mut NotesHolderStorage<N>,
    136         is_muted: &MuteFun,
    137     ) {
    138         match self {
    139             // update the thread for next render if we have new notes
    140             NotesHolderResult::NewNotes(new_notes) => {
    141                 let holder = storage
    142                     .notes_holder_mutated(ndb, note_cache, txn, &new_notes.id, is_muted)
    143                     .get_ptr();
    144                 new_notes.process(holder);
    145             }
    146         }
    147     }
    148 }
    149 
    150 impl NewNotes {
    151     pub fn new(notes: Vec<NoteRef>, id: [u8; 32]) -> Self {
    152         NewNotes { notes, id }
    153     }
    154 
    155     /// Simple helper for processing a NewThreadNotes result. It simply
    156     /// inserts/merges the notes into the thread cache
    157     pub fn process<N: NotesHolder>(&self, thread: &mut N) {
    158         // threads are chronological, ie reversed from reverse-chronological, the default.
    159         let reversed = true;
    160         thread.get_view().insert(&self.notes, reversed);
    161     }
    162 }