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