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