route.rs (6729B)
1 use crate::{ 2 account_manager::AccountManager, 3 column::Columns, 4 draft::Drafts, 5 imgcache::ImageCache, 6 notecache::NoteCache, 7 notes_holder::NotesHolderStorage, 8 profile::Profile, 9 thread::Thread, 10 timeline::{TimelineId, TimelineKind}, 11 ui::{ 12 self, 13 note::{ 14 post::{PostAction, PostResponse}, 15 NoteOptions, QuoteRepostView, 16 }, 17 profile::ProfileView, 18 }, 19 unknowns::UnknownIds, 20 }; 21 22 use enostr::{NoteId, Pubkey, RelayPool}; 23 use nostrdb::{Ndb, Transaction}; 24 25 #[derive(Debug, Eq, PartialEq, Clone, Copy, serde::Serialize, serde::Deserialize)] 26 pub enum TimelineRoute { 27 Timeline(TimelineId), 28 Thread(NoteId), 29 Reply(NoteId), 30 Quote(NoteId), 31 } 32 33 pub enum AfterRouteExecution { 34 Post(PostResponse), 35 OpenProfile(Pubkey), 36 } 37 38 impl AfterRouteExecution { 39 pub fn post(post: PostResponse) -> Self { 40 AfterRouteExecution::Post(post) 41 } 42 } 43 44 #[allow(clippy::too_many_arguments)] 45 pub fn render_timeline_route( 46 ndb: &Ndb, 47 columns: &mut Columns, 48 pool: &mut RelayPool, 49 drafts: &mut Drafts, 50 img_cache: &mut ImageCache, 51 unknown_ids: &mut UnknownIds, 52 note_cache: &mut NoteCache, 53 threads: &mut NotesHolderStorage<Thread>, 54 accounts: &mut AccountManager, 55 route: TimelineRoute, 56 col: usize, 57 textmode: bool, 58 ui: &mut egui::Ui, 59 ) -> Option<AfterRouteExecution> { 60 match route { 61 TimelineRoute::Timeline(timeline_id) => { 62 let note_options = { 63 let is_universe = if let Some(timeline) = columns.find_timeline(timeline_id) { 64 timeline.kind == TimelineKind::Universe 65 } else { 66 false 67 }; 68 69 let mut options = NoteOptions::new(is_universe); 70 options.set_textmode(textmode); 71 options 72 }; 73 74 let timeline_response = ui::TimelineView::new( 75 timeline_id, 76 columns, 77 ndb, 78 note_cache, 79 img_cache, 80 note_options, 81 ) 82 .ui(ui); 83 84 if let Some(bar_action) = timeline_response.bar_action { 85 let txn = Transaction::new(ndb).expect("txn"); 86 let mut cur_column = columns.columns_mut(); 87 let router = cur_column[col].router_mut(); 88 89 bar_action.execute_and_process_result(ndb, router, threads, note_cache, pool, &txn); 90 } 91 92 timeline_response 93 .open_profile 94 .map(AfterRouteExecution::OpenProfile) 95 } 96 97 TimelineRoute::Thread(id) => { 98 let timeline_response = ui::ThreadView::new( 99 threads, 100 ndb, 101 note_cache, 102 unknown_ids, 103 img_cache, 104 id.bytes(), 105 textmode, 106 ) 107 .id_source(egui::Id::new(("threadscroll", col))) 108 .ui(ui); 109 if let Some(bar_action) = timeline_response.bar_action { 110 let txn = Transaction::new(ndb).expect("txn"); 111 let mut cur_column = columns.columns_mut(); 112 let router = cur_column[col].router_mut(); 113 bar_action.execute_and_process_result(ndb, router, threads, note_cache, pool, &txn); 114 } 115 116 timeline_response 117 .open_profile 118 .map(AfterRouteExecution::OpenProfile) 119 } 120 121 TimelineRoute::Reply(id) => { 122 let txn = if let Ok(txn) = Transaction::new(ndb) { 123 txn 124 } else { 125 ui.label("Reply to unknown note"); 126 return None; 127 }; 128 129 let note = if let Ok(note) = ndb.get_note_by_id(&txn, id.bytes()) { 130 note 131 } else { 132 ui.label("Reply to unknown note"); 133 return None; 134 }; 135 136 let id = egui::Id::new(("post", col, note.key().unwrap())); 137 let poster = accounts.selected_or_first_nsec()?; 138 let draft = drafts.reply_mut(note.id()); 139 140 let response = egui::ScrollArea::vertical().show(ui, |ui| { 141 ui::PostReplyView::new(ndb, poster, draft, note_cache, img_cache, ¬e) 142 .id_source(id) 143 .show(ui) 144 }); 145 146 if let Some(action) = &response.inner.action { 147 PostAction::execute(poster, action, pool, draft, |np, seckey| { 148 np.to_reply(seckey, ¬e) 149 }); 150 } 151 152 Some(AfterRouteExecution::post(response.inner)) 153 } 154 155 TimelineRoute::Quote(id) => { 156 let txn = Transaction::new(ndb).expect("txn"); 157 158 let note = if let Ok(note) = ndb.get_note_by_id(&txn, id.bytes()) { 159 note 160 } else { 161 ui.label("Quote of unknown note"); 162 return None; 163 }; 164 165 let id = egui::Id::new(("post", col, note.key().unwrap())); 166 167 let poster = accounts.selected_or_first_nsec()?; 168 let draft = drafts.quote_mut(note.id()); 169 170 let response = egui::ScrollArea::vertical().show(ui, |ui| { 171 QuoteRepostView::new(ndb, poster, note_cache, img_cache, draft, ¬e) 172 .id_source(id) 173 .show(ui) 174 }); 175 176 if let Some(action) = &response.inner.action { 177 PostAction::execute(poster, action, pool, draft, |np, seckey| { 178 np.to_quote(seckey, ¬e) 179 }); 180 } 181 Some(AfterRouteExecution::post(response.inner)) 182 } 183 } 184 } 185 186 #[allow(clippy::too_many_arguments)] 187 pub fn render_profile_route( 188 pubkey: &Pubkey, 189 ndb: &Ndb, 190 columns: &mut Columns, 191 profiles: &mut NotesHolderStorage<Profile>, 192 pool: &mut RelayPool, 193 img_cache: &mut ImageCache, 194 note_cache: &mut NoteCache, 195 threads: &mut NotesHolderStorage<Thread>, 196 col: usize, 197 ui: &mut egui::Ui, 198 ) -> Option<AfterRouteExecution> { 199 let timeline_response = ProfileView::new( 200 pubkey, 201 col, 202 profiles, 203 ndb, 204 note_cache, 205 img_cache, 206 NoteOptions::default(), 207 ) 208 .ui(ui); 209 if let Some(bar_action) = timeline_response.bar_action { 210 let txn = nostrdb::Transaction::new(ndb).expect("txn"); 211 let mut cur_column = columns.columns_mut(); 212 let router = cur_column[col].router_mut(); 213 214 bar_action.execute_and_process_result(ndb, router, threads, note_cache, pool, &txn); 215 } 216 217 timeline_response 218 .open_profile 219 .map(AfterRouteExecution::OpenProfile) 220 }