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 }