@@ -47,7 +47,7 @@ fn open_thread(
|
|||||||
router.route_to(Route::thread(NoteId::new(selected_note.to_owned())));
|
router.route_to(Route::thread(NoteId::new(selected_note.to_owned())));
|
||||||
|
|
||||||
let root_id = crate::note::root_note_id_from_selected_id(ndb, note_cache, txn, selected_note);
|
let root_id = crate::note::root_note_id_from_selected_id(ndb, note_cache, txn, selected_note);
|
||||||
Thread::open(ndb, txn, pool, threads, root_id)
|
Thread::open(ndb, note_cache, txn, pool, threads, root_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BarAction {
|
impl BarAction {
|
||||||
@@ -91,7 +91,7 @@ impl BarAction {
|
|||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
) {
|
) {
|
||||||
if let Some(br) = self.execute(ndb, router, threads, note_cache, pool, txn) {
|
if let Some(br) = self.execute(ndb, router, threads, note_cache, pool, txn) {
|
||||||
br.process(ndb, txn, threads);
|
br.process(ndb, note_cache, txn, threads);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,6 +104,7 @@ impl NotesHolderResult {
|
|||||||
pub fn process<N: NotesHolder>(
|
pub fn process<N: NotesHolder>(
|
||||||
&self,
|
&self,
|
||||||
ndb: &Ndb,
|
ndb: &Ndb,
|
||||||
|
note_cache: &mut NoteCache,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
storage: &mut NotesHolderStorage<N>,
|
storage: &mut NotesHolderStorage<N>,
|
||||||
) {
|
) {
|
||||||
@@ -111,7 +112,7 @@ impl NotesHolderResult {
|
|||||||
// update the thread for next render if we have new notes
|
// update the thread for next render if we have new notes
|
||||||
NotesHolderResult::NewNotes(new_notes) => {
|
NotesHolderResult::NewNotes(new_notes) => {
|
||||||
let holder = storage
|
let holder = storage
|
||||||
.notes_holder_mutated(ndb, txn, &new_notes.id)
|
.notes_holder_mutated(ndb, note_cache, txn, &new_notes.id)
|
||||||
.get_ptr();
|
.get_ptr();
|
||||||
new_notes.process(holder);
|
new_notes.process(holder);
|
||||||
}
|
}
|
||||||
|
|||||||
37
src/app.rs
37
src/app.rs
@@ -364,8 +364,24 @@ fn setup_initial_timeline(
|
|||||||
timeline.subscription, timeline.filter
|
timeline.subscription, timeline.filter
|
||||||
);
|
);
|
||||||
let lim = filters[0].limit().unwrap_or(crate::filter::default_limit()) as i32;
|
let lim = filters[0].limit().unwrap_or(crate::filter::default_limit()) as i32;
|
||||||
let results = ndb.query(&txn, filters, lim)?;
|
let notes = ndb
|
||||||
|
.query(&txn, filters, lim)?
|
||||||
|
.into_iter()
|
||||||
|
.map(NoteRef::from_query_result)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
copy_notes_into_timeline(timeline, &txn, ndb, note_cache, notes);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy_notes_into_timeline(
|
||||||
|
timeline: &mut Timeline,
|
||||||
|
txn: &Transaction,
|
||||||
|
ndb: &Ndb,
|
||||||
|
note_cache: &mut NoteCache,
|
||||||
|
notes: Vec<NoteRef>,
|
||||||
|
) {
|
||||||
let filters = {
|
let filters = {
|
||||||
let views = &timeline.views;
|
let views = &timeline.views;
|
||||||
let filters: Vec<fn(&CachedNote, &Note) -> bool> =
|
let filters: Vec<fn(&CachedNote, &Note) -> bool> =
|
||||||
@@ -373,21 +389,18 @@ fn setup_initial_timeline(
|
|||||||
filters
|
filters
|
||||||
};
|
};
|
||||||
|
|
||||||
for result in results {
|
for note_ref in notes {
|
||||||
for (view, filter) in filters.iter().enumerate() {
|
for (view, filter) in filters.iter().enumerate() {
|
||||||
if filter(
|
if let Ok(note) = ndb.get_note_by_key(txn, note_ref.key) {
|
||||||
note_cache.cached_note_or_insert_mut(result.note_key, &result.note),
|
if filter(
|
||||||
&result.note,
|
note_cache.cached_note_or_insert_mut(note_ref.key, ¬e),
|
||||||
) {
|
¬e,
|
||||||
timeline.views[view].notes.push(NoteRef {
|
) {
|
||||||
key: result.note_key,
|
timeline.views[view].notes.push(note_ref)
|
||||||
created_at: result.note.created_at(),
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_initial_nostrdb_subs(
|
fn setup_initial_nostrdb_subs(
|
||||||
|
|||||||
13
src/nav.rs
13
src/nav.rs
@@ -152,12 +152,13 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
|||||||
let txn = Transaction::new(&app.ndb).expect("txn");
|
let txn = Transaction::new(&app.ndb).expect("txn");
|
||||||
if let Some(res) = Profile::open(
|
if let Some(res) = Profile::open(
|
||||||
&app.ndb,
|
&app.ndb,
|
||||||
|
&mut app.note_cache,
|
||||||
&txn,
|
&txn,
|
||||||
&mut app.pool,
|
&mut app.pool,
|
||||||
&mut app.profiles,
|
&mut app.profiles,
|
||||||
pubkey.bytes(),
|
pubkey.bytes(),
|
||||||
) {
|
) {
|
||||||
res.process(&app.ndb, &txn, &mut app.profiles);
|
res.process(&app.ndb, &mut app.note_cache, &txn, &mut app.profiles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,13 +176,21 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
|||||||
id.bytes(),
|
id.bytes(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
Thread::unsubscribe_locally(&txn, &app.ndb, &mut app.threads, &mut app.pool, root_id);
|
Thread::unsubscribe_locally(
|
||||||
|
&txn,
|
||||||
|
&app.ndb,
|
||||||
|
&mut app.note_cache,
|
||||||
|
&mut app.threads,
|
||||||
|
&mut app.pool,
|
||||||
|
root_id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(Route::Profile(pubkey)) = r {
|
if let Some(Route::Profile(pubkey)) = r {
|
||||||
Profile::unsubscribe_locally(
|
Profile::unsubscribe_locally(
|
||||||
&txn,
|
&txn,
|
||||||
&app.ndb,
|
&app.ndb,
|
||||||
|
&mut app.note_cache,
|
||||||
&mut app.profiles,
|
&mut app.profiles,
|
||||||
&mut app.pool,
|
&mut app.pool,
|
||||||
pubkey.bytes(),
|
pubkey.bytes(),
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use enostr::{Filter, RelayPool};
|
use enostr::{Filter, RelayPool};
|
||||||
use nostrdb::{Ndb, Transaction};
|
use nostrdb::{Ndb, Transaction};
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
actionbar::NotesHolderResult, multi_subscriber::MultiSubscriber, note::NoteRef,
|
actionbar::NotesHolderResult, multi_subscriber::MultiSubscriber, note::NoteRef,
|
||||||
timeline::TimelineTab, Error, Result,
|
notecache::NoteCache, timeline::TimelineTab, Error, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct NotesHolderStorage<M: NotesHolder> {
|
pub struct NotesHolderStorage<M: NotesHolder> {
|
||||||
@@ -52,6 +52,7 @@ impl<M: NotesHolder> NotesHolderStorage<M> {
|
|||||||
pub fn notes_holder_mutated<'a>(
|
pub fn notes_holder_mutated<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
ndb: &Ndb,
|
ndb: &Ndb,
|
||||||
|
note_cache: &mut NoteCache,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
id: &[u8; 32],
|
id: &[u8; 32],
|
||||||
) -> Vitality<'a, M> {
|
) -> Vitality<'a, M> {
|
||||||
@@ -79,12 +80,12 @@ impl<M: NotesHolder> NotesHolderStorage<M> {
|
|||||||
if notes.is_empty() {
|
if notes.is_empty() {
|
||||||
warn!("thread query returned 0 notes? ")
|
warn!("thread query returned 0 notes? ")
|
||||||
} else {
|
} else {
|
||||||
debug!("found thread with {} notes", notes.len());
|
info!("found thread with {} notes", notes.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.id_to_object.insert(
|
self.id_to_object.insert(
|
||||||
id.to_owned(),
|
id.to_owned(),
|
||||||
M::new_notes_holder(id, M::filters(id), notes),
|
M::new_notes_holder(txn, ndb, note_cache, id, M::filters(id), notes),
|
||||||
);
|
);
|
||||||
Vitality::Fresh(self.id_to_object.get_mut(id).unwrap())
|
Vitality::Fresh(self.id_to_object.get_mut(id).unwrap())
|
||||||
}
|
}
|
||||||
@@ -96,7 +97,14 @@ pub trait NotesHolder {
|
|||||||
fn get_view(&mut self) -> &mut TimelineTab;
|
fn get_view(&mut self) -> &mut TimelineTab;
|
||||||
fn filters(for_id: &[u8; 32]) -> Vec<Filter>;
|
fn filters(for_id: &[u8; 32]) -> Vec<Filter>;
|
||||||
fn filters_since(for_id: &[u8; 32], since: u64) -> Vec<Filter>;
|
fn filters_since(for_id: &[u8; 32], since: u64) -> Vec<Filter>;
|
||||||
fn new_notes_holder(id: &[u8; 32], filters: Vec<Filter>, notes: Vec<NoteRef>) -> Self;
|
fn new_notes_holder(
|
||||||
|
txn: &Transaction,
|
||||||
|
ndb: &Ndb,
|
||||||
|
note_cache: &mut NoteCache,
|
||||||
|
id: &[u8; 32],
|
||||||
|
filters: Vec<Filter>,
|
||||||
|
notes: Vec<NoteRef>,
|
||||||
|
) -> Self;
|
||||||
|
|
||||||
#[must_use = "UnknownIds::update_from_note_refs should be used on this result"]
|
#[must_use = "UnknownIds::update_from_note_refs should be used on this result"]
|
||||||
fn poll_notes_into_view(&mut self, txn: &Transaction, ndb: &Ndb) -> Result<()> {
|
fn poll_notes_into_view(&mut self, txn: &Transaction, ndb: &Ndb) -> Result<()> {
|
||||||
@@ -138,12 +146,13 @@ pub trait NotesHolder {
|
|||||||
fn unsubscribe_locally<M: NotesHolder>(
|
fn unsubscribe_locally<M: NotesHolder>(
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
ndb: &Ndb,
|
ndb: &Ndb,
|
||||||
|
note_cache: &mut NoteCache,
|
||||||
notes_holder_storage: &mut NotesHolderStorage<M>,
|
notes_holder_storage: &mut NotesHolderStorage<M>,
|
||||||
pool: &mut RelayPool,
|
pool: &mut RelayPool,
|
||||||
id: &[u8; 32],
|
id: &[u8; 32],
|
||||||
) {
|
) {
|
||||||
let notes_holder = notes_holder_storage
|
let notes_holder = notes_holder_storage
|
||||||
.notes_holder_mutated(ndb, txn, id)
|
.notes_holder_mutated(ndb, note_cache, txn, id)
|
||||||
.get_ptr();
|
.get_ptr();
|
||||||
|
|
||||||
if let Some(multi_subscriber) = notes_holder.get_multi_subscriber() {
|
if let Some(multi_subscriber) = notes_holder.get_multi_subscriber() {
|
||||||
@@ -153,12 +162,13 @@ pub trait NotesHolder {
|
|||||||
|
|
||||||
fn open<M: NotesHolder>(
|
fn open<M: NotesHolder>(
|
||||||
ndb: &Ndb,
|
ndb: &Ndb,
|
||||||
|
note_cache: &mut NoteCache,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
pool: &mut RelayPool,
|
pool: &mut RelayPool,
|
||||||
storage: &mut NotesHolderStorage<M>,
|
storage: &mut NotesHolderStorage<M>,
|
||||||
id: &[u8; 32],
|
id: &[u8; 32],
|
||||||
) -> Option<NotesHolderResult> {
|
) -> Option<NotesHolderResult> {
|
||||||
let vitality = storage.notes_holder_mutated(ndb, txn, id);
|
let vitality = storage.notes_holder_mutated(ndb, note_cache, txn, id);
|
||||||
|
|
||||||
let (holder, result) = match vitality {
|
let (holder, result) = match vitality {
|
||||||
Vitality::Stale(holder) => {
|
Vitality::Stale(holder) => {
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
use enostr::{Filter, Pubkey};
|
use enostr::{Filter, Pubkey};
|
||||||
use nostrdb::{FilterBuilder, ProfileRecord};
|
use nostrdb::{FilterBuilder, Ndb, ProfileRecord, Transaction};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
filter::{self, FilterState},
|
app::copy_notes_into_timeline, filter::{self, FilterState}, multi_subscriber::MultiSubscriber, note::NoteRef, notecache::NoteCache, notes_holder::NotesHolder, timeline::{PubkeySource, Timeline, TimelineKind}
|
||||||
multi_subscriber::MultiSubscriber,
|
|
||||||
note::NoteRef,
|
|
||||||
notes_holder::NotesHolder,
|
|
||||||
timeline::{PubkeySource, Timeline, TimelineKind},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum DisplayName<'a> {
|
pub enum DisplayName<'a> {
|
||||||
@@ -53,10 +49,18 @@ pub struct Profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Profile {
|
impl Profile {
|
||||||
pub fn new(source: PubkeySource, filters: Vec<Filter>, notes: Vec<NoteRef>) -> Self {
|
pub fn new(
|
||||||
|
txn: &Transaction,
|
||||||
|
ndb: &Ndb,
|
||||||
|
note_cache: &mut NoteCache,
|
||||||
|
source: PubkeySource,
|
||||||
|
filters: Vec<Filter>,
|
||||||
|
notes: Vec<NoteRef>,
|
||||||
|
) -> Self {
|
||||||
let mut timeline =
|
let mut timeline =
|
||||||
Timeline::new(TimelineKind::profile(source), FilterState::ready(filters));
|
Timeline::new(TimelineKind::profile(source), FilterState::ready(filters));
|
||||||
timeline.current_view_mut().notes = notes;
|
|
||||||
|
copy_notes_into_timeline(&mut timeline, txn, ndb, note_cache, notes);
|
||||||
|
|
||||||
Profile {
|
Profile {
|
||||||
timeline,
|
timeline,
|
||||||
@@ -95,8 +99,22 @@ impl NotesHolder for Profile {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_notes_holder(id: &[u8; 32], filters: Vec<Filter>, notes: Vec<NoteRef>) -> Self {
|
fn new_notes_holder(
|
||||||
Profile::new(PubkeySource::Explicit(Pubkey::new(*id)), filters, notes)
|
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) {
|
fn set_multi_subscriber(&mut self, subscriber: MultiSubscriber) {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
multi_subscriber::MultiSubscriber,
|
multi_subscriber::MultiSubscriber,
|
||||||
note::NoteRef,
|
note::NoteRef,
|
||||||
|
notecache::NoteCache,
|
||||||
notes_holder::NotesHolder,
|
notes_holder::NotesHolder,
|
||||||
timeline::{TimelineTab, ViewFilter},
|
timeline::{TimelineTab, ViewFilter},
|
||||||
};
|
};
|
||||||
use nostrdb::{Filter, FilterBuilder};
|
use nostrdb::{Filter, FilterBuilder, Ndb, Transaction};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Thread {
|
pub struct Thread {
|
||||||
@@ -66,7 +67,14 @@ impl NotesHolder for Thread {
|
|||||||
Thread::filters(for_id)
|
Thread::filters(for_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_notes_holder(_: &[u8; 32], _: Vec<Filter>, notes: Vec<NoteRef>) -> Self {
|
fn new_notes_holder(
|
||||||
|
_: &Transaction,
|
||||||
|
_: &Ndb,
|
||||||
|
_: &mut NoteCache,
|
||||||
|
_: &[u8; 32],
|
||||||
|
_: Vec<Filter>,
|
||||||
|
notes: Vec<NoteRef>,
|
||||||
|
) -> Self {
|
||||||
Thread::new(notes)
|
Thread::new(notes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ impl<'a> ProfileView<'a> {
|
|||||||
}
|
}
|
||||||
let profile = self
|
let profile = self
|
||||||
.profiles
|
.profiles
|
||||||
.notes_holder_mutated(self.ndb, &txn, self.pubkey.bytes())
|
.notes_holder_mutated(self.ndb, self.note_cache, &txn, self.pubkey.bytes())
|
||||||
.get_ptr();
|
.get_ptr();
|
||||||
|
|
||||||
profile.timeline.selected_view = tabs_ui(ui);
|
profile.timeline.selected_view = tabs_ui(ui);
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ impl<'a> ThreadView<'a> {
|
|||||||
|
|
||||||
let thread = self
|
let thread = self
|
||||||
.threads
|
.threads
|
||||||
.notes_holder_mutated(self.ndb, &txn, root_id)
|
.notes_holder_mutated(self.ndb, self.note_cache, &txn, root_id)
|
||||||
.get_ptr();
|
.get_ptr();
|
||||||
|
|
||||||
// TODO(jb55): skip poll if ThreadResult is fresh?
|
// TODO(jb55): skip poll if ThreadResult is fresh?
|
||||||
|
|||||||
Reference in New Issue
Block a user