notedeck

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

actionbar.rs (4013B)


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