notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 0344ea866f0ffccbfff1b870667a8a524a019540
parent 34c51536188005eca3c8d55408e07a007b517f9d
Author: kernelkind <kernelkind@gmail.com>
Date:   Sun, 19 Oct 2025 19:45:49 -0400

fix(notif-indicator): more performant impl

the previous unseen notification indicator only ran once a few
seconds, but when it did it often took > 5ms because of ndb::query,
which is unacceptable.

This commit removes the ndb::query entirely and relies on the
ndb::poll_for_notes which is already being used every time there is
a new event from a relay

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/notedeck_columns/src/app.rs | 6+-----
Mcrates/notedeck_columns/src/timeline/cache.rs | 2+-
Mcrates/notedeck_columns/src/timeline/mod.rs | 4+++-
Mcrates/notedeck_columns/src/toolbar.rs | 45+++++++++++++--------------------------------
4 files changed, 18 insertions(+), 39 deletions(-)

diff --git a/crates/notedeck_columns/src/app.rs b/crates/notedeck_columns/src/app.rs @@ -698,11 +698,7 @@ fn render_damus_mobile( break 'brk; } - let unseen_notif = unseen_notification( - app, - app_ctx.ndb, - app_ctx.accounts.get_selected_account().key.pubkey, - ); + let unseen_notif = unseen_notification(app, app_ctx.accounts, active_col); if skb_rect.is_none() { let resp = toolbar(ui, unseen_notif); diff --git a/crates/notedeck_columns/src/timeline/cache.rs b/crates/notedeck_columns/src/timeline/cache.rs @@ -258,7 +258,7 @@ impl TimelineCache { return; }; - tl.current_view_mut().freshness.set_fresh(); + tl.seen_latest_notes = true; } } diff --git a/crates/notedeck_columns/src/timeline/mod.rs b/crates/notedeck_columns/src/timeline/mod.rs @@ -243,6 +243,7 @@ pub struct Timeline { pub filter: FilterStates, pub views: Vec<TimelineTab>, pub selected_view: usize, + pub seen_latest_notes: bool, pub subscription: TimelineSub, pub enable_front_insert: bool, @@ -317,6 +318,7 @@ impl Timeline { subscription, selected_view, enable_front_insert, + seen_latest_notes: false, } } @@ -489,7 +491,7 @@ impl Timeline { if new_note_ids.is_empty() { return Ok(()); } else { - debug!("{} new notes! {:?}", new_note_ids.len(), new_note_ids); + self.seen_latest_notes = false; } self.insert(&new_note_ids, ndb, txn, unknown_ids, note_cache, reversed) diff --git a/crates/notedeck_columns/src/toolbar.rs b/crates/notedeck_columns/src/toolbar.rs @@ -1,4 +1,3 @@ -use nostrdb::Transaction; use notedeck::AppContext; use crate::{ @@ -10,42 +9,24 @@ use crate::{ #[profiling::function] pub fn unseen_notification( columns: &mut Damus, - ndb: &nostrdb::Ndb, - current_pk: notedeck::enostr::Pubkey, + accounts: &notedeck::Accounts, + active_col: usize, ) -> bool { - let Some(tl) = columns - .timeline_cache - .get_mut(&TimelineKind::Notifications(current_pk)) - else { - return false; - }; + let top = columns.columns(accounts).column(active_col).router().top(); + let current_pk = accounts.get_selected_account().keypair().pubkey; - let freshness = &mut tl.current_view_mut().freshness; - freshness.update(|timestamp_last_viewed| { - profiling::scope!("NotesFreshness::update closure"); - let filter = { - profiling::scope!("NotesFreshness::update filter instantiation"); - enostr::Filter::new_with_capacity(1) - .pubkeys([current_pk.bytes()]) - .kinds(crate::timeline::kind::notification_kinds()) - .limit(1) - .since(timestamp_last_viewed) - .build() - }; - let txn = Transaction::new(ndb).expect("txn"); - - let Some(res) = { - profiling::scope!("NoteFreshness::update Ndb::query"); - ndb.query(&txn, &[filter], 1) - } - .ok() else { + if let Route::Timeline(TimelineKind::Notifications(notif_pk)) = top { + if notif_pk == current_pk { return false; - }; + } + } - !res.is_empty() - }); + let notif_kind = TimelineKind::Notifications(*current_pk); + let Some(tl) = columns.timeline_cache.get_mut(&notif_kind) else { + return false; + }; - freshness.has_unseen() + !tl.seen_latest_notes } /// When you click the toolbar button, these actions