mirror of
https://github.com/aljazceru/notedeck.git
synced 2026-01-28 20:54:19 +01:00
remove duplicate filter types
only use nostrdb::Filter Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
@@ -6,7 +6,8 @@ use crate::{
|
||||
};
|
||||
use enostr::NoteId;
|
||||
use nostrdb::Transaction;
|
||||
use tracing::{info, warn};
|
||||
use tracing::{error, info};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||
pub enum BarAction {
|
||||
@@ -45,11 +46,11 @@ fn open_thread(
|
||||
let root_id = crate::note::root_note_id_from_selected_id(app, txn, selected_note);
|
||||
let thread_res = app.threads.thread_mut(&app.ndb, txn, root_id);
|
||||
|
||||
// The thread is stale, let's update it
|
||||
let (thread, result) = match thread_res {
|
||||
ThreadResult::Stale(thread) => {
|
||||
// The thread is stale, let's update it
|
||||
let notes = Thread::new_notes(&thread.view.notes, root_id, txn, &app.ndb);
|
||||
let br = if notes.is_empty() {
|
||||
let bar_result = if notes.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(BarResult::new_thread_notes(
|
||||
@@ -63,8 +64,9 @@ fn open_thread(
|
||||
// are already borrowing it mutably. Let's pass it as a
|
||||
// result instead
|
||||
//
|
||||
// thread.view.insert(¬es);
|
||||
(thread, br)
|
||||
// thread.view.insert(¬es); <-- no
|
||||
//
|
||||
(thread, bar_result)
|
||||
}
|
||||
|
||||
ThreadResult::Fresh(thread) => (thread, None),
|
||||
@@ -73,18 +75,27 @@ fn open_thread(
|
||||
// only start a subscription on nav and if we don't have
|
||||
// an active subscription for this thread.
|
||||
if thread.subscription().is_none() {
|
||||
*thread.subscription_mut() = app.ndb.subscribe(Thread::filters(root_id)).ok();
|
||||
let filters = Thread::filters(root_id);
|
||||
*thread.subscription_mut() = app.ndb.subscribe(filters.clone()).ok();
|
||||
|
||||
if thread.remote_subscription().is_some() {
|
||||
error!("Found active remote subscription when it was not expected");
|
||||
} else {
|
||||
let subid = Uuid::new_v4().to_string();
|
||||
*thread.remote_subscription_mut() = Some(subid.clone());
|
||||
app.pool.subscribe(subid, filters);
|
||||
}
|
||||
|
||||
match thread.subscription() {
|
||||
Some(_sub) => {
|
||||
thread.subscribers += 1;
|
||||
info!(
|
||||
"Locally subscribing to thread. {} total active subscriptions, {} on this thread",
|
||||
"Locally/remotely subscribing to thread. {} total active subscriptions, {} on this thread",
|
||||
app.ndb.subscription_count(),
|
||||
thread.subscribers,
|
||||
);
|
||||
}
|
||||
None => warn!(
|
||||
None => error!(
|
||||
"Error subscribing locally to selected note '{}''s thread",
|
||||
hex::encode(selected_note)
|
||||
),
|
||||
|
||||
72
src/app.rs
72
src/app.rs
@@ -17,15 +17,14 @@ use crate::ui::{self, AccountSelectionWidget, DesktopGlobalPopup};
|
||||
use crate::ui::{DesktopSidePanel, RelayView, View};
|
||||
use crate::Result;
|
||||
use egui_nav::{Nav, NavAction};
|
||||
use enostr::{Keypair, RelayPool, SecretKey};
|
||||
use enostr::{ClientMessage, Keypair, RelayEvent, RelayMessage, RelayPool, SecretKey};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use egui::{Context, Frame, Style};
|
||||
use egui_extras::{Size, StripBuilder};
|
||||
|
||||
use enostr::{ClientMessage, Filter, Pubkey, RelayEvent, RelayMessage};
|
||||
use nostrdb::{BlockType, Config, Mention, Ndb, Note, NoteKey, Transaction};
|
||||
use nostrdb::{BlockType, Config, Filter, Mention, Ndb, Note, NoteKey, Transaction};
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
@@ -102,23 +101,27 @@ fn send_initial_filters(damus: &mut Damus, relay_url: &str) {
|
||||
let relay = &mut relay.relay;
|
||||
if relay.url == relay_url {
|
||||
for timeline in &damus.timelines {
|
||||
let mut filter = timeline.filter.clone();
|
||||
for f in &mut filter {
|
||||
let filter = timeline.filter.clone();
|
||||
let new_filters = filter.into_iter().map(|f| {
|
||||
// limit the size of remote filters
|
||||
let default_limit = enostr::Filter::default_remote_limit();
|
||||
let lim = f.limit.unwrap_or(default_limit);
|
||||
let default_limit = crate::filter::default_remote_limit();
|
||||
let mut lim = f.limit().unwrap_or(default_limit);
|
||||
let mut filter = f;
|
||||
if lim > default_limit {
|
||||
f.limit = Some(default_limit);
|
||||
lim = default_limit;
|
||||
filter = filter.limit_mut(lim);
|
||||
}
|
||||
|
||||
let notes = timeline.notes(ViewFilter::NotesAndReplies);
|
||||
if crate::filter::should_since_optimize(f.limit, notes.len()) {
|
||||
crate::filter::since_optimize_filter(f, notes);
|
||||
if crate::filter::should_since_optimize(lim, notes.len()) {
|
||||
filter = crate::filter::since_optimize_filter(filter, notes);
|
||||
} else {
|
||||
warn!("Skipping since optimization for {:?}: number of local notes is less than limit, attempting to backfill.", f);
|
||||
warn!("Skipping since optimization for {:?}: number of local notes is less than limit, attempting to backfill.", filter);
|
||||
}
|
||||
}
|
||||
relay.subscribe(format!("initial{}", c), filter);
|
||||
|
||||
filter
|
||||
}).collect();
|
||||
relay.subscribe(format!("initial{}", c), new_filters);
|
||||
c += 1;
|
||||
}
|
||||
return;
|
||||
@@ -347,11 +350,7 @@ fn setup_profiling() {
|
||||
fn setup_initial_nostrdb_subs(damus: &mut Damus) -> Result<()> {
|
||||
let timelines = damus.timelines.len();
|
||||
for i in 0..timelines {
|
||||
let filters: Vec<nostrdb::Filter> = damus.timelines[i]
|
||||
.filter
|
||||
.iter()
|
||||
.map(crate::filter::convert_enostr_filter)
|
||||
.collect();
|
||||
let filters = damus.timelines[i].filter.clone();
|
||||
damus.timelines[i].subscription = Some(damus.ndb.subscribe(filters.clone())?);
|
||||
let txn = Transaction::new(&damus.ndb)?;
|
||||
debug!(
|
||||
@@ -363,8 +362,8 @@ fn setup_initial_nostrdb_subs(damus: &mut Damus) -> Result<()> {
|
||||
&txn,
|
||||
filters,
|
||||
damus.timelines[i].filter[0]
|
||||
.limit
|
||||
.unwrap_or(enostr::Filter::default_limit()) as i32,
|
||||
.limit()
|
||||
.unwrap_or(crate::filter::default_limit()) as i32,
|
||||
)?;
|
||||
|
||||
let filters = {
|
||||
@@ -465,22 +464,16 @@ fn get_unknown_ids_filter(ids: &[UnknownId<'_>]) -> Option<Vec<Filter>> {
|
||||
|
||||
let mut filters: Vec<Filter> = vec![];
|
||||
|
||||
let pks: Vec<Pubkey> = ids
|
||||
.iter()
|
||||
.flat_map(|id| id.is_pubkey().map(Pubkey::new))
|
||||
.collect();
|
||||
let pks: Vec<&[u8; 32]> = ids.iter().flat_map(|id| id.is_pubkey()).collect();
|
||||
if !pks.is_empty() {
|
||||
let pk_filter = Filter::new().authors(pks).kinds(vec![0]);
|
||||
let pk_filter = Filter::new().authors(pks).kinds([0]).build();
|
||||
|
||||
filters.push(pk_filter);
|
||||
}
|
||||
|
||||
let note_ids: Vec<enostr::NoteId> = ids
|
||||
.iter()
|
||||
.flat_map(|id| id.is_id().map(|id| enostr::NoteId::new(*id)))
|
||||
.collect();
|
||||
let note_ids: Vec<&[u8; 32]> = ids.iter().flat_map(|id| id.is_id()).collect();
|
||||
if !note_ids.is_empty() {
|
||||
filters.push(Filter::new().ids(note_ids));
|
||||
filters.push(Filter::new().ids(note_ids).build());
|
||||
}
|
||||
|
||||
Some(filters)
|
||||
@@ -589,8 +582,8 @@ fn parse_args(args: &[String]) -> Args {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Ok(filter) = serde_json::from_str(filter) {
|
||||
res.timelines.push(Timeline::new(filter));
|
||||
if let Ok(filter) = Filter::from_json(filter) {
|
||||
res.timelines.push(Timeline::new(vec![filter]));
|
||||
} else {
|
||||
error!("failed to parse filter '{}'", filter);
|
||||
}
|
||||
@@ -628,8 +621,11 @@ fn parse_args(args: &[String]) -> Args {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Ok(filter) = serde_json::from_slice(&data) {
|
||||
res.timelines.push(Timeline::new(filter));
|
||||
if let Some(filter) = std::str::from_utf8(&data)
|
||||
.ok()
|
||||
.and_then(|s| Filter::from_json(s).ok())
|
||||
{
|
||||
res.timelines.push(Timeline::new(vec![filter]));
|
||||
} else {
|
||||
error!("failed to parse filter in '{}'", filter_file);
|
||||
}
|
||||
@@ -639,8 +635,8 @@ fn parse_args(args: &[String]) -> Args {
|
||||
}
|
||||
|
||||
if res.timelines.is_empty() {
|
||||
let filter = serde_json::from_str(include_str!("../queries/timeline.json")).unwrap();
|
||||
res.timelines.push(Timeline::new(filter));
|
||||
let filter = Filter::from_json(include_str!("../queries/timeline.json")).unwrap();
|
||||
res.timelines.push(Timeline::new(vec![filter]));
|
||||
}
|
||||
|
||||
res
|
||||
@@ -749,8 +745,8 @@ impl Damus {
|
||||
|
||||
pub fn mock<P: AsRef<Path>>(data_path: P, is_mobile: bool) -> Self {
|
||||
let mut timelines: Vec<Timeline> = vec![];
|
||||
let filter = serde_json::from_str(include_str!("../queries/global.json")).unwrap();
|
||||
timelines.push(Timeline::new(filter));
|
||||
let filter = Filter::from_json(include_str!("../queries/global.json")).unwrap();
|
||||
timelines.push(Timeline::new(vec![filter]));
|
||||
|
||||
let imgcache_dir = data_path.as_ref().join(ImageCache::rel_datadir());
|
||||
let _ = std::fs::create_dir_all(imgcache_dir.clone());
|
||||
|
||||
@@ -1,72 +1,32 @@
|
||||
use crate::note::NoteRef;
|
||||
use nostrdb::Filter;
|
||||
|
||||
pub fn should_since_optimize(limit: Option<u16>, num_notes: usize) -> bool {
|
||||
let limit = limit.unwrap_or(enostr::Filter::default_limit()) as usize;
|
||||
|
||||
pub fn should_since_optimize(limit: u64, num_notes: usize) -> bool {
|
||||
// rough heuristic for bailing since optimization if we don't have enough notes
|
||||
limit <= num_notes
|
||||
limit as usize <= num_notes
|
||||
}
|
||||
|
||||
pub fn since_optimize_filter_with(filter: &mut enostr::Filter, notes: &[NoteRef], since_gap: u64) {
|
||||
pub fn since_optimize_filter_with(filter: Filter, notes: &[NoteRef], since_gap: u64) -> Filter {
|
||||
// Get the latest entry in the events
|
||||
if notes.is_empty() {
|
||||
return;
|
||||
return filter;
|
||||
}
|
||||
|
||||
// get the latest note
|
||||
let latest = notes[0];
|
||||
let since = latest.created_at - since_gap;
|
||||
|
||||
// update the filters
|
||||
filter.since = Some(since);
|
||||
filter.since_mut(since)
|
||||
}
|
||||
|
||||
pub fn since_optimize_filter(filter: &mut enostr::Filter, notes: &[NoteRef]) {
|
||||
since_optimize_filter_with(filter, notes, 60);
|
||||
pub fn since_optimize_filter(filter: Filter, notes: &[NoteRef]) -> Filter {
|
||||
since_optimize_filter_with(filter, notes, 60)
|
||||
}
|
||||
|
||||
pub fn convert_enostr_filter(filter: &enostr::Filter) -> nostrdb::Filter {
|
||||
let mut nfilter = nostrdb::Filter::new();
|
||||
|
||||
if let Some(ref ids) = filter.ids {
|
||||
nfilter = nfilter.ids(ids.iter().map(|a| *a.bytes()).collect());
|
||||
}
|
||||
|
||||
if let Some(ref authors) = filter.authors {
|
||||
let authors: Vec<[u8; 32]> = authors.iter().map(|a| *a.bytes()).collect();
|
||||
nfilter = nfilter.authors(authors);
|
||||
}
|
||||
|
||||
if let Some(ref kinds) = filter.kinds {
|
||||
nfilter = nfilter.kinds(kinds.clone());
|
||||
}
|
||||
|
||||
// #e
|
||||
if let Some(ref events) = filter.events {
|
||||
nfilter = nfilter.events(events.iter().map(|a| *a.bytes()).collect());
|
||||
}
|
||||
|
||||
// #p
|
||||
if let Some(ref pubkeys) = filter.pubkeys {
|
||||
nfilter = nfilter.pubkeys(pubkeys.iter().map(|a| *a.bytes()).collect());
|
||||
}
|
||||
|
||||
// #t
|
||||
if let Some(ref hashtags) = filter.hashtags {
|
||||
nfilter = nfilter.tags(hashtags.clone(), 't');
|
||||
}
|
||||
|
||||
if let Some(since) = filter.since {
|
||||
nfilter = nfilter.since(since);
|
||||
}
|
||||
|
||||
if let Some(until) = filter.until {
|
||||
nfilter = nfilter.until(until);
|
||||
}
|
||||
|
||||
if let Some(limit) = filter.limit {
|
||||
nfilter = nfilter.limit(limit.into());
|
||||
}
|
||||
|
||||
nfilter.build()
|
||||
pub fn default_limit() -> u64 {
|
||||
250
|
||||
}
|
||||
|
||||
pub fn default_remote_limit() -> u64 {
|
||||
150
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use tracing::{debug, warn};
|
||||
pub struct Thread {
|
||||
pub view: TimelineTab,
|
||||
sub: Option<Subscription>,
|
||||
remote_sub: Option<String>,
|
||||
pub subscribers: i32,
|
||||
}
|
||||
|
||||
@@ -28,11 +29,13 @@ impl Thread {
|
||||
let mut view = TimelineTab::new_with_capacity(ViewFilter::NotesAndReplies, cap);
|
||||
view.notes = notes;
|
||||
let sub: Option<Subscription> = None;
|
||||
let remote_sub: Option<String> = None;
|
||||
let subscribers: i32 = 0;
|
||||
|
||||
Thread {
|
||||
view,
|
||||
sub,
|
||||
remote_sub,
|
||||
subscribers,
|
||||
}
|
||||
}
|
||||
@@ -83,14 +86,22 @@ impl Thread {
|
||||
self.sub.as_ref()
|
||||
}
|
||||
|
||||
pub fn remote_subscription(&self) -> Option<&String> {
|
||||
self.remote_sub.as_ref()
|
||||
}
|
||||
|
||||
pub fn remote_subscription_mut(&mut self) -> &mut Option<String> {
|
||||
&mut self.remote_sub
|
||||
}
|
||||
|
||||
pub fn subscription_mut(&mut self) -> &mut Option<Subscription> {
|
||||
&mut self.sub
|
||||
}
|
||||
|
||||
fn filters_raw(root: &[u8; 32]) -> Vec<FilterBuilder> {
|
||||
vec![
|
||||
nostrdb::Filter::new().kinds(vec![1]).event(root),
|
||||
nostrdb::Filter::new().ids(vec![*root]).limit(1),
|
||||
nostrdb::Filter::new().kinds([1]).event(root),
|
||||
nostrdb::Filter::new().ids([root]).limit(1),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@ use crate::{Damus, Result};
|
||||
use crate::route::Route;
|
||||
|
||||
use egui_virtual_list::VirtualList;
|
||||
use enostr::Filter;
|
||||
use nostrdb::{Note, Subscription, Transaction};
|
||||
use nostrdb::{Filter, Note, Subscription, Transaction};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
Reference in New Issue
Block a user