Files
notedeck/src/profile.rs
William Casarin 01bedac710 Fix filter states when adding columns
This fixes various issues with filter states when adding columns. We now
maintain multiple states per relay so that we don't lose track of
anything.

Fixes: https://github.com/damus-io/notedeck/issues/431
Fixes: https://github.com/damus-io/notedeck/issues/359
Signed-off-by: William Casarin <jb55@jb55.com>
2024-11-14 15:25:08 -08:00

129 lines
3.2 KiB
Rust

use enostr::{Filter, Pubkey};
use nostrdb::{FilterBuilder, Ndb, ProfileRecord, Transaction};
use crate::{
filter::{self, FilterState},
multi_subscriber::MultiSubscriber,
note::NoteRef,
notecache::NoteCache,
notes_holder::NotesHolder,
timeline::{copy_notes_into_timeline, PubkeySource, Timeline, TimelineKind},
};
pub enum DisplayName<'a> {
One(&'a str),
Both {
username: &'a str,
display_name: &'a str,
},
}
impl<'a> DisplayName<'a> {
pub fn username(&self) -> &'a str {
match self {
Self::One(n) => n,
Self::Both { username, .. } => username,
}
}
}
fn is_empty(s: &str) -> bool {
s.chars().all(|c| c.is_whitespace())
}
pub fn get_profile_name<'a>(record: &'a ProfileRecord) -> Option<DisplayName<'a>> {
let profile = record.record().profile()?;
let display_name = profile.display_name().filter(|n| !is_empty(n));
let name = profile.name().filter(|n| !is_empty(n));
match (display_name, name) {
(None, None) => None,
(Some(disp), None) => Some(DisplayName::One(disp)),
(None, Some(username)) => Some(DisplayName::One(username)),
(Some(display_name), Some(username)) => Some(DisplayName::Both {
display_name,
username,
}),
}
}
pub struct Profile {
pub timeline: Timeline,
pub multi_subscriber: Option<MultiSubscriber>,
}
impl Profile {
pub fn new(
txn: &Transaction,
ndb: &Ndb,
note_cache: &mut NoteCache,
source: PubkeySource,
filters: Vec<Filter>,
notes: Vec<NoteRef>,
) -> Self {
let mut timeline =
Timeline::new(TimelineKind::profile(source), FilterState::ready(filters));
copy_notes_into_timeline(&mut timeline, txn, ndb, note_cache, notes);
Profile {
timeline,
multi_subscriber: None,
}
}
fn filters_raw(pk: &[u8; 32]) -> Vec<FilterBuilder> {
vec![Filter::new()
.authors([pk])
.kinds([1])
.limit(filter::default_limit())]
}
}
impl NotesHolder for Profile {
fn get_multi_subscriber(&mut self) -> Option<&mut MultiSubscriber> {
self.multi_subscriber.as_mut()
}
fn get_view(&mut self) -> &mut crate::timeline::TimelineTab {
self.timeline.current_view_mut()
}
fn filters(for_id: &[u8; 32]) -> Vec<enostr::Filter> {
Profile::filters_raw(for_id)
.into_iter()
.map(|mut f| f.build())
.collect()
}
fn filters_since(for_id: &[u8; 32], since: u64) -> Vec<enostr::Filter> {
Profile::filters_raw(for_id)
.into_iter()
.map(|f| f.since(since).build())
.collect()
}
fn new_notes_holder(
txn: &Transaction,
ndb: &Ndb,
note_cache: &mut NoteCache,
id: &[u8; 32],
filters: Vec<Filter>,
notes: Vec<NoteRef>,
) -> Self {
Profile::new(
txn,
ndb,
note_cache,
PubkeySource::Explicit(Pubkey::new(*id)),
filters,
notes,
)
}
fn set_multi_subscriber(&mut self, subscriber: MultiSubscriber) {
self.multi_subscriber = Some(subscriber);
}
}