notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

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 }