route.rs (4852B)
1 use crate::{ 2 nav::RenderNavAction, 3 profile::ProfileAction, 4 timeline::{TimelineCache, TimelineKind}, 5 ui::{self, note::NoteOptions, profile::ProfileView}, 6 }; 7 8 use enostr::Pubkey; 9 use nostrdb::Ndb; 10 use notedeck::{Accounts, Images, MuteFun, NoteCache, UnknownIds}; 11 12 #[allow(clippy::too_many_arguments)] 13 pub fn render_timeline_route( 14 ndb: &Ndb, 15 img_cache: &mut Images, 16 unknown_ids: &mut UnknownIds, 17 note_cache: &mut NoteCache, 18 timeline_cache: &mut TimelineCache, 19 accounts: &mut Accounts, 20 kind: &TimelineKind, 21 col: usize, 22 mut note_options: NoteOptions, 23 depth: usize, 24 ui: &mut egui::Ui, 25 ) -> Option<RenderNavAction> { 26 if kind == &TimelineKind::Universe { 27 note_options.set_hide_media(true); 28 } 29 30 match kind { 31 TimelineKind::List(_) 32 | TimelineKind::Search(_) 33 | TimelineKind::Algo(_) 34 | TimelineKind::Notifications(_) 35 | TimelineKind::Universe 36 | TimelineKind::Hashtag(_) 37 | TimelineKind::Generic(_) => { 38 let note_action = ui::TimelineView::new( 39 kind, 40 timeline_cache, 41 ndb, 42 note_cache, 43 img_cache, 44 note_options, 45 &accounts.mutefun(), 46 ) 47 .ui(ui); 48 49 note_action.map(RenderNavAction::NoteAction) 50 } 51 52 TimelineKind::Profile(pubkey) => { 53 if depth > 1 { 54 render_profile_route( 55 pubkey, 56 accounts, 57 ndb, 58 timeline_cache, 59 img_cache, 60 note_cache, 61 unknown_ids, 62 col, 63 ui, 64 &accounts.mutefun(), 65 note_options, 66 ) 67 } else { 68 // we render profiles like timelines if they are at the root 69 let note_action = ui::TimelineView::new( 70 kind, 71 timeline_cache, 72 ndb, 73 note_cache, 74 img_cache, 75 note_options, 76 &accounts.mutefun(), 77 ) 78 .ui(ui); 79 80 note_action.map(RenderNavAction::NoteAction) 81 } 82 } 83 84 TimelineKind::Thread(id) => ui::ThreadView::new( 85 timeline_cache, 86 ndb, 87 note_cache, 88 unknown_ids, 89 img_cache, 90 id.selected_or_root(), 91 note_options, 92 &accounts.mutefun(), 93 ) 94 .id_source(egui::Id::new(("threadscroll", col))) 95 .ui(ui) 96 .map(Into::into), 97 } 98 } 99 100 #[allow(clippy::too_many_arguments)] 101 pub fn render_profile_route( 102 pubkey: &Pubkey, 103 accounts: &Accounts, 104 ndb: &Ndb, 105 timeline_cache: &mut TimelineCache, 106 img_cache: &mut Images, 107 note_cache: &mut NoteCache, 108 unknown_ids: &mut UnknownIds, 109 col: usize, 110 ui: &mut egui::Ui, 111 is_muted: &MuteFun, 112 note_options: NoteOptions, 113 ) -> Option<RenderNavAction> { 114 let action = ProfileView::new( 115 pubkey, 116 accounts, 117 col, 118 timeline_cache, 119 ndb, 120 note_cache, 121 img_cache, 122 unknown_ids, 123 is_muted, 124 note_options, 125 ) 126 .ui(ui); 127 128 if let Some(action) = action { 129 match action { 130 ui::profile::ProfileViewAction::EditProfile => accounts 131 .get_full(pubkey.bytes()) 132 .map(|kp| RenderNavAction::ProfileAction(ProfileAction::Edit(kp.to_full()))), 133 ui::profile::ProfileViewAction::Note(note_action) => { 134 Some(RenderNavAction::NoteAction(note_action)) 135 } 136 } 137 } else { 138 None 139 } 140 } 141 142 #[cfg(test)] 143 mod tests { 144 use enostr::NoteId; 145 use tokenator::{TokenParser, TokenWriter}; 146 147 use crate::timeline::{ThreadSelection, TimelineKind}; 148 use enostr::Pubkey; 149 use notedeck::RootNoteIdBuf; 150 151 #[test] 152 fn test_timeline_route_serialize() { 153 let note_id_hex = "1c54e5b0c386425f7e017d9e068ddef8962eb2ce1bb08ed27e24b93411c12e60"; 154 let note_id = NoteId::from_hex(note_id_hex).unwrap(); 155 let data_str = format!("thread:{}", note_id_hex); 156 let data = &data_str.split(":").collect::<Vec<&str>>(); 157 let mut token_writer = TokenWriter::default(); 158 let mut parser = TokenParser::new(&data); 159 let parsed = TimelineKind::parse(&mut parser, &Pubkey::new(*note_id.bytes())).unwrap(); 160 let expected = TimelineKind::Thread(ThreadSelection::from_root_id( 161 RootNoteIdBuf::new_unsafe(*note_id.bytes()), 162 )); 163 parsed.serialize_tokens(&mut token_writer); 164 assert_eq!(expected, parsed); 165 assert_eq!(token_writer.str(), data_str); 166 } 167 }