commit 8fd3e39af3fdd8343710650c83de61b2d54cc812
parent 647d15be216eda1a4808f2d54095451238cf310c
Author: William Casarin <jb55@jb55.com>
Date: Thu, 4 Dec 2025 01:25:39 -0800
Merge hide futures notes by elsat #1202
alltheseas (4):
Filter out future-dated notes
Run cargo fmt
Update time.rs
Diffstat:
4 files changed, 54 insertions(+), 11 deletions(-)
diff --git a/crates/notedeck/src/lib.rs b/crates/notedeck/src/lib.rs
@@ -83,8 +83,9 @@ pub use route::DrawerRouter;
pub use storage::{AccountStorage, DataPath, DataPathType, Directory};
pub use style::NotedeckTextStyle;
pub use theme::ColorTheme;
-pub use time::time_ago_since;
-pub use time::time_format;
+pub use time::{
+ is_future_timestamp, time_ago_since, time_format, unix_time_secs, MAX_FUTURE_NOTE_SKEW_SECS,
+};
pub use timecache::TimeCached;
pub use unknowns::{get_unknown_note_ids, NoteRefsUnkIdAction, SingleUnkIdAction, UnknownIds};
pub use urls::{supported_mime_hosted_at_url, SupportedMimeType, UrlMimes};
diff --git a/crates/notedeck/src/time.rs b/crates/notedeck/src/time.rs
@@ -10,6 +10,22 @@ const ONE_WEEK_IN_SECONDS: u64 = 604_800;
const ONE_MONTH_IN_SECONDS: u64 = 2_592_000; // 30 days
const ONE_YEAR_IN_SECONDS: u64 = 31_536_000; // 365 days
+/// Maximum tolerated skew for note timestamps in the future (2 minutes / 120 seconds).
+pub const MAX_FUTURE_NOTE_SKEW_SECS: u64 = 2 * ONE_MINUTE_IN_SECONDS;
+
+/// Returns the current UNIX timestamp in seconds.
+pub fn unix_time_secs() -> u64 {
+ SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .expect("Time went backwards")
+ .as_secs()
+}
+
+/// Whether `timestamp` is further in the future than the allowed skew.
+pub fn is_future_timestamp(timestamp: u64, now: u64) -> bool {
+ timestamp > now + MAX_FUTURE_NOTE_SKEW_SECS
+}
+
/// Calculate relative time between two timestamps, with two units only
/// when the scale is large enough (e.g., "1y 6m", "5d 4h"),
/// but not for hours/minutes/seconds.
@@ -95,10 +111,7 @@ pub fn time_format(_i18n: &mut Localization, timestamp: u64) -> String {
}
pub fn time_ago_since(i18n: &mut Localization, timestamp: u64) -> String {
- let now = SystemTime::now()
- .duration_since(UNIX_EPOCH)
- .expect("Time went backwards")
- .as_secs();
+ let now = unix_time_secs();
time_ago_between(i18n, timestamp, now)
}
@@ -354,4 +367,18 @@ mod tests {
result
);
}
+
+ #[test]
+ fn test_future_skew_helper() {
+ let now = 1_000_000u64;
+ assert!(!is_future_timestamp(now, now));
+ assert!(!is_future_timestamp(
+ now + MAX_FUTURE_NOTE_SKEW_SECS - 1,
+ now
+ ));
+ assert!(is_future_timestamp(
+ now + MAX_FUTURE_NOTE_SKEW_SECS + 1,
+ now
+ ));
+ }
}
diff --git a/crates/notedeck_columns/src/actionbar.rs b/crates/notedeck_columns/src/actionbar.rs
@@ -15,10 +15,10 @@ use egui_nav::Percent;
use enostr::{FilledKeypair, NoteId, Pubkey, RelayPool};
use nostrdb::{IngestMetadata, Ndb, NoteBuilder, NoteKey, Transaction};
use notedeck::{
- get_wallet_for,
+ get_wallet_for, is_future_timestamp,
note::{reaction_sent_id, ReactAction, ZapTargetAmount},
- Accounts, GlobalWallet, Images, MediaJobSender, NoteAction, NoteCache, NoteZapTargetOwned,
- UnknownIds, ZapAction, ZapTarget, ZappingError, Zaps,
+ unix_time_secs, Accounts, GlobalWallet, Images, MediaJobSender, NoteAction, NoteCache,
+ NoteZapTargetOwned, UnknownIds, ZapAction, ZapTarget, ZappingError, Zaps,
};
use notedeck_ui::media::MediaViewerFlags;
use tracing::error;
@@ -504,6 +504,7 @@ pub fn process_thread_notes(
return;
}
+ let now = unix_time_secs();
let mut has_spliced_resp = false;
let mut num_new_notes = 0;
for key in notes {
@@ -517,6 +518,10 @@ pub fn process_thread_notes(
continue;
};
+ if is_future_timestamp(note.created_at(), now) {
+ continue;
+ }
+
// Ensure that unknown ids are captured when inserting notes
UnknownIds::update_from_note(txn, ndb, unknown_ids, note_cache, ¬e);
diff --git a/crates/notedeck_columns/src/timeline/mod.rs b/crates/notedeck_columns/src/timeline/mod.rs
@@ -9,8 +9,8 @@ use crate::{
use notedeck::{
contacts::hybrid_contacts_filter,
filter::{self, HybridFilter},
- tr, Accounts, CachedNote, ContactState, FilterError, FilterState, FilterStates, Localization,
- NoteCache, NoteRef, UnknownIds,
+ is_future_timestamp, tr, unix_time_secs, Accounts, CachedNote, ContactState, FilterError,
+ FilterState, FilterStates, Localization, NoteCache, NoteRef, UnknownIds,
};
use egui_virtual_list::VirtualList;
@@ -368,8 +368,13 @@ impl Timeline {
filters
};
+ let now = unix_time_secs();
let mut unknown_pks = HashSet::new();
for note_ref in notes {
+ if is_future_timestamp(note_ref.created_at, now) {
+ continue;
+ }
+
for (view, filter) in filters.iter().enumerate() {
if let Ok(note) = ndb.get_note_by_key(txn, note_ref.key) {
if filter(
@@ -417,6 +422,7 @@ impl Timeline {
reversed: bool,
) -> Result<()> {
let mut payloads: Vec<NotePayload> = Vec::with_capacity(new_note_ids.len());
+ let now = unix_time_secs();
for key in new_note_ids {
let note = if let Ok(note) = ndb.get_note_by_key(txn, *key) {
@@ -429,6 +435,10 @@ impl Timeline {
continue;
};
+ if is_future_timestamp(note.created_at(), now) {
+ continue;
+ }
+
// Ensure that unknown ids are captured when inserting notes
// into the timeline
UnknownIds::update_from_note(txn, ndb, unknown_ids, note_cache, ¬e);