threads: check for new notes locally when thread is re-opened
We have a NoteRef cache for threads in memory, which is just a list of NoteKeys and timestamps. When reopening a thread, query the local DB to see if there are any new notes that we might have missed because we weren't actively subscribed to them. Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
124
src/actionbar.rs
124
src/actionbar.rs
@@ -1,4 +1,9 @@
|
||||
use crate::{route::Route, thread::Thread, Damus};
|
||||
use crate::{
|
||||
note::NoteRef,
|
||||
route::Route,
|
||||
thread::{Thread, ThreadResult},
|
||||
Damus,
|
||||
};
|
||||
use enostr::NoteId;
|
||||
use nostrdb::Transaction;
|
||||
use tracing::{info, warn};
|
||||
@@ -9,6 +14,79 @@ pub enum BarAction {
|
||||
OpenThread,
|
||||
}
|
||||
|
||||
pub enum BarResult {
|
||||
NewThreadNotes(Vec<NoteRef>),
|
||||
}
|
||||
|
||||
/// open_thread is called when a note is selected and we need to navigate
|
||||
/// to a thread It is responsible for managing the subscription and
|
||||
/// making sure the thread is up to date. In a sense, it's a model for
|
||||
/// the thread view. We don't have a concept of model/view/controller etc
|
||||
/// in egui, but this is the closest thing to that.
|
||||
fn open_thread(
|
||||
app: &mut Damus,
|
||||
txn: &Transaction,
|
||||
timeline: usize,
|
||||
selected_note: &[u8; 32],
|
||||
) -> Option<BarResult> {
|
||||
{
|
||||
let timeline = &mut app.timelines[timeline];
|
||||
timeline
|
||||
.routes
|
||||
.push(Route::Thread(NoteId::new(selected_note.to_owned())));
|
||||
timeline.navigating = true;
|
||||
}
|
||||
|
||||
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) => {
|
||||
let notes = Thread::new_notes(&thread.view.notes, root_id, txn, &app.ndb);
|
||||
//
|
||||
// we can't insert and update the VirtualList now, because we
|
||||
// are already borrowing it mutably. Let's pass it as a
|
||||
// result instead
|
||||
//
|
||||
// thread.view.insert(¬es);
|
||||
(thread, Some(BarResult::NewThreadNotes(notes)))
|
||||
}
|
||||
|
||||
ThreadResult::Fresh(thread) => (thread, None),
|
||||
};
|
||||
|
||||
// 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();
|
||||
|
||||
match thread.subscription() {
|
||||
Some(_sub) => {
|
||||
thread.subscribers += 1;
|
||||
info!(
|
||||
"Locally subscribing to thread. {} total active subscriptions, {} on this thread",
|
||||
app.ndb.subscription_count(),
|
||||
thread.subscribers,
|
||||
);
|
||||
}
|
||||
None => warn!(
|
||||
"Error subscribing locally to selected note '{}''s thread",
|
||||
hex::encode(selected_note)
|
||||
),
|
||||
}
|
||||
} else {
|
||||
thread.subscribers += 1;
|
||||
info!(
|
||||
"Re-using existing thread subscription. {} total active subscriptions, {} on this thread",
|
||||
app.ndb.subscription_count(),
|
||||
thread.subscribers,
|
||||
)
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
impl BarAction {
|
||||
pub fn execute(
|
||||
self,
|
||||
@@ -16,7 +94,7 @@ impl BarAction {
|
||||
timeline: usize,
|
||||
replying_to: &[u8; 32],
|
||||
txn: &Transaction,
|
||||
) {
|
||||
) -> Option<BarResult> {
|
||||
match self {
|
||||
BarAction::Reply => {
|
||||
let timeline = &mut app.timelines[timeline];
|
||||
@@ -24,48 +102,10 @@ impl BarAction {
|
||||
.routes
|
||||
.push(Route::Reply(NoteId::new(replying_to.to_owned())));
|
||||
timeline.navigating = true;
|
||||
None
|
||||
}
|
||||
|
||||
BarAction::OpenThread => {
|
||||
{
|
||||
let timeline = &mut app.timelines[timeline];
|
||||
timeline
|
||||
.routes
|
||||
.push(Route::Thread(NoteId::new(replying_to.to_owned())));
|
||||
timeline.navigating = true;
|
||||
}
|
||||
|
||||
let root_id = crate::note::root_note_id_from_selected_id(app, txn, replying_to);
|
||||
let thread = app.threads.thread_mut(&app.ndb, txn, root_id);
|
||||
|
||||
// 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();
|
||||
|
||||
match thread.subscription() {
|
||||
Some(_sub) => {
|
||||
thread.subscribers += 1;
|
||||
info!(
|
||||
"Locally subscribing to thread. {} total active subscriptions, {} on this thread",
|
||||
app.ndb.subscription_count(),
|
||||
thread.subscribers,
|
||||
);
|
||||
}
|
||||
None => warn!(
|
||||
"Error subscribing locally to selected note '{}''s thread",
|
||||
hex::encode(replying_to)
|
||||
),
|
||||
}
|
||||
} else {
|
||||
thread.subscribers += 1;
|
||||
info!(
|
||||
"Re-using existing thread subscription. {} total active subscriptions, {} on this thread",
|
||||
app.ndb.subscription_count(),
|
||||
thread.subscribers,
|
||||
)
|
||||
}
|
||||
}
|
||||
BarAction::OpenThread => open_thread(app, txn, timeline, replying_to),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user