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