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 }