introduce HybridFilter
This introduces a new filter construct called HybridFilter. This allows filters to have different remote filter than local ones. For example, adding kind0 to the remote for keeping profiles up to date on your timeline, but only subscribing to kind1 locally. Only home/contact filters use this feature for now. Fixes: https://github.com/damus-io/notedeck/issues/995 Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
24
crates/notedeck/src/contacts.rs
Normal file
24
crates/notedeck/src/contacts.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::{
|
||||
filter::{self, HybridFilter},
|
||||
Error,
|
||||
};
|
||||
use nostrdb::{Filter, Note};
|
||||
|
||||
pub fn contacts_filter(pk: &[u8; 32]) -> Filter {
|
||||
Filter::new().authors([pk]).kinds([3]).limit(1).build()
|
||||
}
|
||||
|
||||
/// Contact filters have an additional kind0 in the remote filter so it can fetch profiles as well
|
||||
/// we don't need this in the local filter since we only care about the kind1 results
|
||||
pub fn hybrid_contacts_filter(
|
||||
note: &Note,
|
||||
add_pk: Option<&[u8; 32]>,
|
||||
with_hashtags: bool,
|
||||
) -> Result<HybridFilter, Error> {
|
||||
let local = filter::filter_from_tags(¬e, add_pk, with_hashtags)?
|
||||
.into_filter([1], filter::default_limit());
|
||||
let remote = filter::filter_from_tags(¬e, add_pk, with_hashtags)?
|
||||
.into_filter([1, 0], filter::default_remote_limit());
|
||||
|
||||
Ok(HybridFilter::split(local, remote))
|
||||
}
|
||||
@@ -55,7 +55,7 @@ impl FilterStates {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_any_ready(&self) -> Option<&Vec<Filter>> {
|
||||
pub fn get_any_ready(&self) -> Option<&HybridFilter> {
|
||||
if let FilterState::Ready(fs) = &self.initial_state {
|
||||
Some(fs)
|
||||
} else {
|
||||
@@ -95,7 +95,7 @@ pub enum FilterState {
|
||||
NeedsRemote,
|
||||
FetchingRemote(FetchingRemoteType),
|
||||
GotRemote(GotRemoteType),
|
||||
Ready(Vec<Filter>),
|
||||
Ready(HybridFilter),
|
||||
Broken(FilterError),
|
||||
}
|
||||
|
||||
@@ -132,6 +132,17 @@ impl FilterState {
|
||||
|
||||
/// The filter is ready
|
||||
pub fn ready(filter: Vec<Filter>) -> Self {
|
||||
Self::Ready(HybridFilter::unsplit(filter))
|
||||
}
|
||||
|
||||
/// The filter is ready, but we have a different local filter from
|
||||
/// our remote one
|
||||
pub fn ready_split(local: Vec<Filter>, remote: Vec<Filter>) -> Self {
|
||||
Self::Ready(HybridFilter::split(local, remote))
|
||||
}
|
||||
|
||||
/// Our hybrid filter is ready (either split or unsplit)
|
||||
pub fn ready_hybrid(filter: HybridFilter) -> Self {
|
||||
Self::Ready(filter)
|
||||
}
|
||||
|
||||
@@ -195,6 +206,49 @@ pub struct FilteredTags {
|
||||
pub hashtags: Option<FilterBuilder>,
|
||||
}
|
||||
|
||||
/// The local and remote filter are related but slightly different
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SplitFilter {
|
||||
pub local: Vec<Filter>,
|
||||
pub remote: Vec<Filter>,
|
||||
}
|
||||
|
||||
/// Either a [`SplitFilter`] or a regular unsplit filter,. Split filters
|
||||
/// have different remote and local filters but are tracked together.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum HybridFilter {
|
||||
Split(SplitFilter),
|
||||
Unsplit(Vec<Filter>),
|
||||
}
|
||||
|
||||
impl HybridFilter {
|
||||
pub fn unsplit(filter: Vec<Filter>) -> Self {
|
||||
HybridFilter::Unsplit(filter)
|
||||
}
|
||||
|
||||
pub fn split(local: Vec<Filter>, remote: Vec<Filter>) -> Self {
|
||||
HybridFilter::Split(SplitFilter { local, remote })
|
||||
}
|
||||
|
||||
pub fn local(&self) -> &[Filter] {
|
||||
match self {
|
||||
Self::Split(split) => &split.local,
|
||||
|
||||
// local as the same as remote in unsplit
|
||||
Self::Unsplit(local) => &local,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remote(&self) -> &[Filter] {
|
||||
match self {
|
||||
Self::Split(split) => &split.remote,
|
||||
|
||||
// local as the same as remote in unsplit
|
||||
Self::Unsplit(remote) => remote,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FilteredTags {
|
||||
pub fn into_follow_filter(self) -> Vec<Filter> {
|
||||
self.into_filter([1], default_limit())
|
||||
|
||||
@@ -2,6 +2,7 @@ pub mod abbrev;
|
||||
mod account;
|
||||
mod app;
|
||||
mod args;
|
||||
pub mod contacts;
|
||||
mod context;
|
||||
pub mod debouncer;
|
||||
mod error;
|
||||
|
||||
Reference in New Issue
Block a user