mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-17 08:44:20 +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;
|
break 'brk;
|
||||||
}
|
}
|
||||||
|
|
||||||
let unseen_notif = unseen_notification(
|
let unseen_notif = unseen_notification(app, app_ctx.accounts, active_col);
|
||||||
app,
|
|
||||||
app_ctx.ndb,
|
|
||||||
app_ctx.accounts.get_selected_account().key.pubkey,
|
|
||||||
);
|
|
||||||
|
|
||||||
if skb_rect.is_none() {
|
if skb_rect.is_none() {
|
||||||
let resp = toolbar(ui, unseen_notif);
|
let resp = toolbar(ui, unseen_notif);
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ impl TimelineCache {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
tl.current_view_mut().freshness.set_fresh();
|
tl.seen_latest_notes = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use crate::{
|
|||||||
|
|
||||||
use notedeck::{
|
use notedeck::{
|
||||||
contacts::hybrid_contacts_filter,
|
contacts::hybrid_contacts_filter,
|
||||||
debouncer::Debouncer,
|
|
||||||
filter::{self, HybridFilter},
|
filter::{self, HybridFilter},
|
||||||
tr, Accounts, CachedNote, ContactState, FilterError, FilterState, FilterStates, Localization,
|
tr, Accounts, CachedNote, ContactState, FilterError, FilterState, FilterStates, Localization,
|
||||||
NoteCache, NoteRef, UnknownIds,
|
NoteCache, NoteRef, UnknownIds,
|
||||||
@@ -17,12 +16,8 @@ use notedeck::{
|
|||||||
use egui_virtual_list::VirtualList;
|
use egui_virtual_list::VirtualList;
|
||||||
use enostr::{PoolRelay, Pubkey, RelayPool};
|
use enostr::{PoolRelay, Pubkey, RelayPool};
|
||||||
use nostrdb::{Filter, Ndb, Note, NoteKey, Transaction};
|
use nostrdb::{Filter, Ndb, Note, NoteKey, Transaction};
|
||||||
use std::{
|
use std::rc::Rc;
|
||||||
cell::RefCell,
|
use std::{cell::RefCell, collections::HashSet};
|
||||||
collections::HashSet,
|
|
||||||
time::{Duration, UNIX_EPOCH},
|
|
||||||
};
|
|
||||||
use std::{rc::Rc, time::SystemTime};
|
|
||||||
|
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
@@ -111,7 +106,6 @@ pub struct TimelineTab {
|
|||||||
pub selection: i32,
|
pub selection: i32,
|
||||||
pub filter: ViewFilter,
|
pub filter: ViewFilter,
|
||||||
pub list: Rc<RefCell<VirtualList>>,
|
pub list: Rc<RefCell<VirtualList>>,
|
||||||
pub freshness: NotesFreshness,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimelineTab {
|
impl TimelineTab {
|
||||||
@@ -153,7 +147,6 @@ impl TimelineTab {
|
|||||||
selection,
|
selection,
|
||||||
filter,
|
filter,
|
||||||
list,
|
list,
|
||||||
freshness: NotesFreshness::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +236,7 @@ pub struct Timeline {
|
|||||||
pub filter: FilterStates,
|
pub filter: FilterStates,
|
||||||
pub views: Vec<TimelineTab>,
|
pub views: Vec<TimelineTab>,
|
||||||
pub selected_view: usize,
|
pub selected_view: usize,
|
||||||
|
pub seen_latest_notes: bool,
|
||||||
|
|
||||||
pub subscription: TimelineSub,
|
pub subscription: TimelineSub,
|
||||||
pub enable_front_insert: bool,
|
pub enable_front_insert: bool,
|
||||||
@@ -317,6 +311,7 @@ impl Timeline {
|
|||||||
subscription,
|
subscription,
|
||||||
selected_view,
|
selected_view,
|
||||||
enable_front_insert,
|
enable_front_insert,
|
||||||
|
seen_latest_notes: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +484,7 @@ impl Timeline {
|
|||||||
if new_note_ids.is_empty() {
|
if new_note_ids.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} 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)
|
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 notedeck::AppContext;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -10,42 +9,24 @@ use crate::{
|
|||||||
#[profiling::function]
|
#[profiling::function]
|
||||||
pub fn unseen_notification(
|
pub fn unseen_notification(
|
||||||
columns: &mut Damus,
|
columns: &mut Damus,
|
||||||
ndb: &nostrdb::Ndb,
|
accounts: ¬edeck::Accounts,
|
||||||
current_pk: notedeck::enostr::Pubkey,
|
active_col: usize,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let Some(tl) = columns
|
let top = columns.columns(accounts).column(active_col).router().top();
|
||||||
.timeline_cache
|
let current_pk = accounts.get_selected_account().keypair().pubkey;
|
||||||
.get_mut(&TimelineKind::Notifications(current_pk))
|
|
||||||
else {
|
if let Route::Timeline(TimelineKind::Notifications(notif_pk)) = top {
|
||||||
|
if notif_pk == current_pk {
|
||||||
return false;
|
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 {
|
}
|
||||||
|
|
||||||
|
let notif_kind = TimelineKind::Notifications(*current_pk);
|
||||||
|
let Some(tl) = columns.timeline_cache.get_mut(¬if_kind) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
!res.is_empty()
|
!tl.seen_latest_notes
|
||||||
});
|
|
||||||
|
|
||||||
freshness.has_unseen()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When you click the toolbar button, these actions
|
/// When you click the toolbar button, these actions
|
||||||
|
|||||||
Reference in New Issue
Block a user