mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-17 00:44:18 +01:00
Merge seen note perf improvements by kernel #1174
kernelkind (2):
fix(notif-indicator): more performant impl
refactor(NoteFreshness): remove now unnecessary `NoteFreshness`
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -258,7 +258,7 @@ impl TimelineCache {
|
||||
return;
|
||||
};
|
||||
|
||||
tl.current_view_mut().freshness.set_fresh();
|
||||
tl.seen_latest_notes = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ use crate::{
|
||||
|
||||
use notedeck::{
|
||||
contacts::hybrid_contacts_filter,
|
||||
debouncer::Debouncer,
|
||||
filter::{self, HybridFilter},
|
||||
tr, Accounts, CachedNote, ContactState, FilterError, FilterState, FilterStates, Localization,
|
||||
NoteCache, NoteRef, UnknownIds,
|
||||
@@ -17,12 +16,8 @@ use notedeck::{
|
||||
use egui_virtual_list::VirtualList;
|
||||
use enostr::{PoolRelay, Pubkey, RelayPool};
|
||||
use nostrdb::{Filter, Ndb, Note, NoteKey, Transaction};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashSet,
|
||||
time::{Duration, UNIX_EPOCH},
|
||||
};
|
||||
use std::{rc::Rc, time::SystemTime};
|
||||
use std::rc::Rc;
|
||||
use std::{cell::RefCell, collections::HashSet};
|
||||
|
||||
use tracing::{debug, error, info, warn};
|
||||
|
||||
@@ -111,7 +106,6 @@ pub struct TimelineTab {
|
||||
pub selection: i32,
|
||||
pub filter: ViewFilter,
|
||||
pub list: Rc<RefCell<VirtualList>>,
|
||||
pub freshness: NotesFreshness,
|
||||
}
|
||||
|
||||
impl TimelineTab {
|
||||
@@ -153,7 +147,6 @@ impl TimelineTab {
|
||||
selection,
|
||||
filter,
|
||||
list,
|
||||
freshness: NotesFreshness::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +236,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 +311,7 @@ impl Timeline {
|
||||
subscription,
|
||||
selected_view,
|
||||
enable_front_insert,
|
||||
seen_latest_notes: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +484,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)
|
||||
@@ -880,101 +875,3 @@ pub fn is_timeline_ready(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NotesFreshness {
|
||||
debouncer: Debouncer,
|
||||
state: NotesFreshnessState,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum NotesFreshnessState {
|
||||
Fresh {
|
||||
timestamp_viewed: u64,
|
||||
},
|
||||
Stale {
|
||||
have_unseen: bool,
|
||||
timestamp_last_viewed: u64,
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for NotesFreshness {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
debouncer: Debouncer::new(Duration::from_secs(2)),
|
||||
state: NotesFreshnessState::Stale {
|
||||
have_unseen: true,
|
||||
timestamp_last_viewed: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NotesFreshness {
|
||||
pub fn set_fresh(&mut self) {
|
||||
if !self.debouncer.should_act() {
|
||||
return;
|
||||
}
|
||||
self.state = NotesFreshnessState::Fresh {
|
||||
timestamp_viewed: timestamp_now(),
|
||||
};
|
||||
self.debouncer.bounce();
|
||||
}
|
||||
|
||||
pub fn update(&mut self, check_have_unseen: impl FnOnce(u64) -> bool) {
|
||||
if !self.debouncer.should_act() {
|
||||
return;
|
||||
}
|
||||
|
||||
match &self.state {
|
||||
NotesFreshnessState::Fresh { timestamp_viewed } => {
|
||||
let Ok(dur) = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH + Duration::from_secs(*timestamp_viewed))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
if dur > Duration::from_secs(2) {
|
||||
self.state = NotesFreshnessState::Stale {
|
||||
have_unseen: check_have_unseen(*timestamp_viewed),
|
||||
timestamp_last_viewed: *timestamp_viewed,
|
||||
};
|
||||
}
|
||||
}
|
||||
NotesFreshnessState::Stale {
|
||||
have_unseen,
|
||||
timestamp_last_viewed,
|
||||
} => {
|
||||
if *have_unseen {
|
||||
return;
|
||||
}
|
||||
|
||||
self.state = NotesFreshnessState::Stale {
|
||||
have_unseen: check_have_unseen(*timestamp_last_viewed),
|
||||
timestamp_last_viewed: *timestamp_last_viewed,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
self.debouncer.bounce();
|
||||
}
|
||||
|
||||
pub fn has_unseen(&self) -> bool {
|
||||
match &self.state {
|
||||
NotesFreshnessState::Fresh {
|
||||
timestamp_viewed: _,
|
||||
} => false,
|
||||
NotesFreshnessState::Stale {
|
||||
have_unseen,
|
||||
timestamp_last_viewed: _,
|
||||
} => *have_unseen,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn timestamp_now() -> u64 {
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap_or(Duration::ZERO)
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
@@ -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: ¬edeck::Accounts,
|
||||
active_col: usize,
|
||||
) -> bool {
|
||||
let Some(tl) = columns
|
||||
.timeline_cache
|
||||
.get_mut(&TimelineKind::Notifications(current_pk))
|
||||
else {
|
||||
let top = columns.columns(accounts).column(active_col).router().top();
|
||||
let current_pk = accounts.get_selected_account().keypair().pubkey;
|
||||
|
||||
if let Route::Timeline(TimelineKind::Notifications(notif_pk)) = top {
|
||||
if notif_pk == current_pk {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let notif_kind = TimelineKind::Notifications(*current_pk);
|
||||
let Some(tl) = columns.timeline_cache.get_mut(¬if_kind) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
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 {
|
||||
return false;
|
||||
};
|
||||
|
||||
!res.is_empty()
|
||||
});
|
||||
|
||||
freshness.has_unseen()
|
||||
!tl.seen_latest_notes
|
||||
}
|
||||
|
||||
/// When you click the toolbar button, these actions
|
||||
|
||||
Reference in New Issue
Block a user