add threads impl

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-06-16 17:38:01 -04:00
parent 3c31e1a651
commit cdcca0ba35
3 changed files with 636 additions and 2 deletions

View File

@@ -2,10 +2,15 @@ use crate::{
column::Columns,
nav::{RouterAction, RouterType},
route::Route,
timeline::{ThreadSelection, TimelineCache, TimelineKind},
timeline::{
thread::{
selected_has_at_least_n_replies, InsertionResponse, NoteSeenFlags, ThreadNode, Threads,
},
ThreadSelection, TimelineCache, TimelineKind,
},
};
use enostr::{Pubkey, RelayPool};
use enostr::{NoteId, Pubkey, RelayPool};
use nostrdb::{Ndb, NoteKey, Transaction};
use notedeck::{
get_wallet_for_mut, note::ZapTargetAmount, Accounts, GlobalWallet, Images, NoteAction,
@@ -252,3 +257,103 @@ impl NewNotes {
}
}
}
pub struct NewThreadNotes {
pub selected_note_id: NoteId,
pub notes: Vec<NoteKey>,
}
impl NewThreadNotes {
pub fn process(
&self,
threads: &mut Threads,
ndb: &Ndb,
txn: &Transaction,
unknown_ids: &mut UnknownIds,
note_cache: &mut NoteCache,
) {
let Some(node) = threads.threads.get_mut(&self.selected_note_id.bytes()) else {
tracing::error!("Could not find thread node for {:?}", self.selected_note_id);
return;
};
process_thread_notes(
&self.notes,
node,
&mut threads.seen_flags,
ndb,
txn,
unknown_ids,
note_cache,
);
}
}
pub fn process_thread_notes(
notes: &Vec<NoteKey>,
thread: &mut ThreadNode,
seen_flags: &mut NoteSeenFlags,
ndb: &Ndb,
txn: &Transaction,
unknown_ids: &mut UnknownIds,
note_cache: &mut NoteCache,
) {
if notes.is_empty() {
return;
}
let mut has_spliced_resp = false;
let mut num_new_notes = 0;
for key in notes {
let note = if let Ok(note) = ndb.get_note_by_key(txn, *key) {
note
} else {
tracing::error!("hit race condition in poll_notes_into_view: https://github.com/damus-io/nostrdb/issues/35 note {:?} was not added to timeline", key);
continue;
};
// Ensure that unknown ids are captured when inserting notes
UnknownIds::update_from_note(txn, ndb, unknown_ids, note_cache, &note);
let created_at = note.created_at();
let note_ref = notedeck::NoteRef {
key: *key,
created_at,
};
if thread.replies.contains(&note_ref) {
continue;
}
let insertion_resp = thread.replies.insert(note_ref);
if let InsertionResponse::Merged(crate::timeline::MergeKind::Spliced) = insertion_resp {
has_spliced_resp = true;
}
if matches!(insertion_resp, InsertionResponse::Merged(_)) {
num_new_notes += 1;
}
if !seen_flags.contains(note.id()) {
let cached_note = note_cache.cached_note_or_insert_mut(*key, &note);
let note_reply = cached_note.reply.borrow(note.tags());
let has_reply = if let Some(root) = note_reply.root() {
selected_has_at_least_n_replies(ndb, txn, Some(note.id()), root.id, 1)
} else {
selected_has_at_least_n_replies(ndb, txn, None, note.id(), 1)
};
seen_flags.mark_replies(note.id(), has_reply);
}
}
if has_spliced_resp {
tracing::debug!(
"spliced when inserting {} new notes, resetting virtual list",
num_new_notes
);
thread.list.reset();
}
}