use WebOfTrust registry for screening dialog mutuals

This commit is contained in:
2026-10-20 09:47:34 +07:00
parent 80f4bc387e
commit 66768e71a6
4 changed files with 678 additions and 35 deletions
+50 -21
View File
@@ -9,7 +9,7 @@ use gpui::{
};
use instant::Duration;
use nostr_sdk::prelude::*;
use person::{Directory, Person, shorten_pubkey};
use person::{Directory, Person, WebOfTrust, shorten_pubkey};
use smallvec::{SmallVec, smallvec};
use state::{BOOTSTRAP_RELAYS, NostrAddress, NostrRegistry, TIMEOUT};
use theme::{ActiveTheme, TextStyle, Typeset as _, button_radius};
@@ -33,14 +33,19 @@ pub struct Screening {
last_active: Option<Timestamp>,
/// All mutual contacts of the person being screened.
mutual_contacts: Vec<PublicKey>,
/// Whether the database fallback for mutual contacts has run.
mutuals_fallback: bool,
/// Person directory for the person and their mutual contacts
directory: Entity<Directory>,
tasks: SmallVec<[Task<()>; 3]>,
_subscriptions: SmallVec<[Subscription; 1]>,
_subscriptions: SmallVec<[Subscription; 2]>,
}
impl Screening {
pub fn new(public_key: PublicKey, window: &mut Window, cx: &mut Context<Self>) -> Self {
let wot = WebOfTrust::global(cx);
let directory = Directory::new(cx);
let mut subscriptions = smallvec![];
subscriptions.push(cx.on_release_in(window, move |this, window, cx| {
@@ -48,6 +53,14 @@ impl Screening {
window.close_all_dialogs(cx);
}));
subscriptions.push(cx.subscribe(&wot, |this, _wot, _event, cx| {
this.check_wot(cx);
}));
directory.update(cx, |directory, cx| {
directory.track([public_key], cx);
});
cx.defer_in(window, |this, _window, cx| {
this.check_contact(cx);
this.check_wot(cx);
@@ -55,15 +68,13 @@ impl Screening {
this.verify_identifier(cx);
});
let directory = Directory::new(cx);
directory.update(cx, |directory, cx| directory.track([public_key], cx));
Self {
public_key,
verified: false,
followed: false,
last_active: None,
mutual_contacts: vec![],
mutuals_fallback: false,
directory,
tasks: smallvec![],
_subscriptions: subscriptions,
@@ -110,7 +121,25 @@ impl Screening {
}));
}
/// Check mutual contacts through the web of trust,
/// falling back to the database while it loads
fn check_wot(&mut self, cx: &mut Context<Self>) {
let trusted = {
let wot = WebOfTrust::global(cx).read(cx);
(wot.is_ready() && !wot.is_disabled()).then(|| wot.mutuals(&self.public_key))
};
if let Some(contacts) = trusted {
self.mutual_contacts = contacts;
cx.notify();
return;
}
if self.mutuals_fallback {
return;
}
self.mutuals_fallback = true;
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let public_key = self.public_key;
@@ -119,33 +148,33 @@ impl Screening {
return;
};
let task: Task<Result<Vec<PublicKey>, Error>> = cx.background_spawn(async move {
// Check mutual contacts
let task: Task<Vec<PublicKey>> = cx.background_spawn(async move {
// Check mutual contacts among the locally stored contact lists
let filter = Filter::new().kind(Kind::ContactList).pubkey(public_key);
let mut mutual_contacts = vec![];
let mut contacts = vec![];
if let Ok(events) = client.database().query(filter).await {
for event in events.into_iter().filter(|ev| ev.pubkey != current_user) {
mutual_contacts.push(event.pubkey);
contacts.push(event.pubkey);
}
}
Ok(mutual_contacts)
contacts
});
self.tasks.push(cx.spawn(async move |this, cx| {
match task.await {
Ok(contacts) => {
this.update(cx, |this, cx| {
this.mutual_contacts = contacts;
cx.notify();
})
.ok();
let contacts = task.await;
this.update(cx, |this, cx| {
let wot = WebOfTrust::global(cx).read(cx);
// The web of trust wins once its load has finished
if wot.is_ready() && !wot.is_disabled() {
return;
}
Err(e) => {
log::error!("Failed to fetch mutual contacts: {}", e);
}
};
this.mutual_contacts = contacts;
cx.notify();
})
.ok();
}));
}