chore: improve the activity check (#145)

* better check for activity

* .
This commit is contained in:
reya
2025-09-09 10:23:40 +07:00
committed by GitHub
parent d0f7a1abd3
commit fc99ef4dfe
3 changed files with 62 additions and 37 deletions

View File

@@ -636,12 +636,18 @@ impl ChatSpace {
/// Fetches metadata for a list of public keys /// Fetches metadata for a list of public keys
async fn fetch_metadata_for_pubkeys(public_keys: HashSet<PublicKey>) { async fn fetch_metadata_for_pubkeys(public_keys: HashSet<PublicKey>) {
if public_keys.is_empty() {
return;
}
let client = nostr_client(); let client = nostr_client();
let css = css(); let css = css();
let kinds = vec![Kind::Metadata, Kind::ContactList, Kind::RelayList]; let kinds = vec![Kind::Metadata, Kind::ContactList, Kind::RelayList];
let limit = public_keys.len() * kinds.len() + 20; // + 20 to ensure Coop has enough metadata let limit = public_keys.len() * kinds.len() + 20;
let filter = Filter::new().limit(limit).authors(public_keys).kinds(kinds);
// A filter to fetch metadata
let filter = Filter::new().authors(public_keys).kinds(kinds).limit(limit);
client client
.subscribe_to(BOOTSTRAP_RELAYS, filter, css.auto_close_opts) .subscribe_to(BOOTSTRAP_RELAYS, filter, css.auto_close_opts)

View File

@@ -1,6 +1,6 @@
use std::time::Duration; use std::time::Duration;
use common::display::{shorten_pubkey, ReadableProfile}; use common::display::{shorten_pubkey, ReadableProfile, ReadableTimestamp};
use common::nip05::nip05_verify; use common::nip05::nip05_verify;
use global::constants::BOOTSTRAP_RELAYS; use global::constants::BOOTSTRAP_RELAYS;
use global::nostr_client; use global::nostr_client;
@@ -30,7 +30,7 @@ pub struct Screening {
verified: bool, verified: bool,
followed: bool, followed: bool,
dm_relays: Option<bool>, dm_relays: Option<bool>,
active: Option<bool>, last_active: Option<Timestamp>,
mutual_contacts: Vec<Profile>, mutual_contacts: Vec<Profile>,
_tasks: SmallVec<[Task<()>; 4]>, _tasks: SmallVec<[Task<()>; 4]>,
} }
@@ -68,19 +68,15 @@ impl Screening {
let activity_check = cx.background_spawn(async move { let activity_check = cx.background_spawn(async move {
let client = nostr_client(); let client = nostr_client();
let mut activity = false; let filter = Filter::new().author(public_key).limit(1);
let mut activity: Option<Timestamp> = None;
let filter = Filter::new()
.author(public_key)
.since(Timestamp::now() - Duration::from_secs(172800))
.limit(1);
if let Ok(mut stream) = client if let Ok(mut stream) = client
.stream_events_from(BOOTSTRAP_RELAYS, filter, Duration::from_secs(2)) .stream_events_from(BOOTSTRAP_RELAYS, filter, Duration::from_secs(2))
.await .await
{ {
while stream.next().await.is_some() { while let Some(event) = stream.next().await {
activity = true activity = Some(event.created_at);
} }
} }
@@ -133,7 +129,7 @@ impl Screening {
let active = activity_check.await; let active = activity_check.await;
this.update(cx, |this, cx| { this.update(cx, |this, cx| {
this.active = Some(active); this.last_active = active;
cx.notify(); cx.notify();
}) })
.ok(); .ok();
@@ -173,7 +169,7 @@ impl Screening {
verified: false, verified: false,
followed: false, followed: false,
dm_relays: None, dm_relays: None,
active: None, last_active: None,
mutual_contacts: vec![], mutual_contacts: vec![],
_tasks: tasks, _tasks: tasks,
} }
@@ -261,6 +257,7 @@ impl Render for Screening {
let proxy = AppSettings::get_proxy_user_avatars(cx); let proxy = AppSettings::get_proxy_user_avatars(cx);
let shorten_pubkey = shorten_pubkey(self.profile.public_key(), 8); let shorten_pubkey = shorten_pubkey(self.profile.public_key(), 8);
let total_mutuals = self.mutual_contacts.len(); let total_mutuals = self.mutual_contacts.len();
let last_active = self.last_active.map(|_| true);
v_flex() v_flex()
.gap_4() .gap_4()
@@ -353,20 +350,36 @@ impl Render for Screening {
.items_start() .items_start()
.gap_2() .gap_2()
.text_sm() .text_sm()
.child(status_badge(self.active, cx)) .child(status_badge(last_active, cx))
.child( .child(
v_flex() v_flex()
.text_sm() .text_sm()
.child(
h_flex()
.gap_0p5()
.child(shared_t!("screening.active_label")) .child(shared_t!("screening.active_label"))
.child(
Button::new("active")
.icon(IconName::Info)
.xsmall()
.ghost()
.rounded(ButtonRounded::Full)
.tooltip(t!("screening.active_tooltip")),
),
)
.child( .child(
div() div()
.w_full()
.line_clamp(1) .line_clamp(1)
.text_color(cx.theme().text_muted) .text_color(cx.theme().text_muted)
.child({ .map(|this| {
if self.active == Some(true) { if let Some(date) = self.last_active {
shared_t!("screening.active") this.child(shared_t!(
"screening.active_at",
d = date.to_human_time()
))
} else { } else {
shared_t!("screening.no_active") this.child(shared_t!("screening.no_active"))
} }
}), }),
), ),
@@ -480,7 +493,11 @@ impl Render for Screening {
} }
fn status_badge(status: Option<bool>, cx: &App) -> Div { fn status_badge(status: Option<bool>, cx: &App) -> Div {
div().pt_1().flex_shrink_0().map(|this| { h_flex()
.size_6()
.justify_center()
.flex_shrink_0()
.map(|this| {
if let Some(status) = status { if let Some(status) = status {
this.child(Icon::new(IconName::CheckCircleFill).small().text_color({ this.child(Icon::new(IconName::CheckCircleFill).small().text_color({
if status { if status {
@@ -490,7 +507,7 @@ fn status_badge(status: Option<bool>, cx: &App) -> Div {
} }
})) }))
} else { } else {
this.child(Indicator::new().xsmall()) this.child(Indicator::new().small())
} }
}) })
} }

View File

@@ -220,11 +220,13 @@ screening:
not_contact: not_contact:
en: "This person is not one of your contacts." en: "This person is not one of your contacts."
active_label: active_label:
en: "Activity" en: "Activity on Public Relays"
active: active_tooltip:
en: "This person has activity in the last 2 days" en: "This may be inaccurate if the user only publishes to their private relays."
no_active: no_active:
en: "This person has no activity in the last 2 days" en: "This person hasn't had any activity."
active_at:
en: "Last active: %{d}."
mutual_label: mutual_label:
en: "Mutual contacts" en: "Mutual contacts"
mutual: mutual: