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