profile.rs (3468B)
1 use enostr::{Filter, Pubkey}; 2 use nostrdb::{FilterBuilder, Ndb, ProfileRecord, Transaction}; 3 4 use notedeck::{filter::default_limit, FilterState, MuteFun, NoteCache, NoteRef}; 5 6 use crate::{ 7 multi_subscriber::MultiSubscriber, 8 notes_holder::NotesHolder, 9 timeline::{copy_notes_into_timeline, PubkeySource, Timeline, TimelineKind, TimelineTab}, 10 }; 11 12 pub enum DisplayName<'a> { 13 One(&'a str), 14 15 Both { 16 username: &'a str, 17 display_name: &'a str, 18 }, 19 } 20 21 impl<'a> DisplayName<'a> { 22 pub fn username(&self) -> &'a str { 23 match self { 24 Self::One(n) => n, 25 Self::Both { username, .. } => username, 26 } 27 } 28 } 29 30 fn is_empty(s: &str) -> bool { 31 s.chars().all(|c| c.is_whitespace()) 32 } 33 34 pub fn get_profile_name<'a>(record: &ProfileRecord<'a>) -> Option<DisplayName<'a>> { 35 let profile = record.record().profile()?; 36 let display_name = profile.display_name().filter(|n| !is_empty(n)); 37 let name = profile.name().filter(|n| !is_empty(n)); 38 39 match (display_name, name) { 40 (None, None) => None, 41 (Some(disp), None) => Some(DisplayName::One(disp)), 42 (None, Some(username)) => Some(DisplayName::One(username)), 43 (Some(display_name), Some(username)) => Some(DisplayName::Both { 44 display_name, 45 username, 46 }), 47 } 48 } 49 50 pub struct Profile { 51 pub timeline: Timeline, 52 pub multi_subscriber: Option<MultiSubscriber>, 53 } 54 55 impl Profile { 56 pub fn new( 57 txn: &Transaction, 58 ndb: &Ndb, 59 note_cache: &mut NoteCache, 60 source: PubkeySource, 61 filters: Vec<Filter>, 62 notes: Vec<NoteRef>, 63 is_muted: &MuteFun, 64 ) -> Self { 65 let mut timeline = Timeline::new( 66 TimelineKind::profile(source), 67 FilterState::ready(filters), 68 TimelineTab::full_tabs(), 69 ); 70 71 copy_notes_into_timeline(&mut timeline, txn, ndb, note_cache, notes, is_muted); 72 73 Profile { 74 timeline, 75 multi_subscriber: None, 76 } 77 } 78 79 fn filters_raw(pk: &[u8; 32]) -> Vec<FilterBuilder> { 80 vec![Filter::new() 81 .authors([pk]) 82 .kinds([1]) 83 .limit(default_limit())] 84 } 85 } 86 87 impl NotesHolder for Profile { 88 fn get_multi_subscriber(&mut self) -> Option<&mut MultiSubscriber> { 89 self.multi_subscriber.as_mut() 90 } 91 92 fn get_view(&mut self) -> &mut crate::timeline::TimelineTab { 93 self.timeline.current_view_mut() 94 } 95 96 fn filters(for_id: &[u8; 32]) -> Vec<enostr::Filter> { 97 Profile::filters_raw(for_id) 98 .into_iter() 99 .map(|mut f| f.build()) 100 .collect() 101 } 102 103 fn filters_since(for_id: &[u8; 32], since: u64) -> Vec<enostr::Filter> { 104 Profile::filters_raw(for_id) 105 .into_iter() 106 .map(|f| f.since(since).build()) 107 .collect() 108 } 109 110 fn new_notes_holder( 111 txn: &Transaction, 112 ndb: &Ndb, 113 note_cache: &mut NoteCache, 114 id: &[u8; 32], 115 filters: Vec<Filter>, 116 notes: Vec<NoteRef>, 117 is_muted: &MuteFun, 118 ) -> Self { 119 Profile::new( 120 txn, 121 ndb, 122 note_cache, 123 PubkeySource::Explicit(Pubkey::new(*id)), 124 filters, 125 notes, 126 is_muted, 127 ) 128 } 129 130 fn set_multi_subscriber(&mut self, subscriber: MultiSubscriber) { 131 self.multi_subscriber = Some(subscriber); 132 } 133 }