From 0f0216051f860ec67e7e63ba863207296d926bb1 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Tue, 20 Oct 2026 10:58:32 +0700 Subject: [PATCH] add web of trust score to profile dialog --- crates/person/src/wot.rs | 5 +++++ crates/workspace/src/dialogs/profile.rs | 17 ++++++++++++++++- crates/workspace/src/dialogs/screening.rs | 6 +++--- docs/web-of-trust.md | 6 ++++-- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/crates/person/src/wot.rs b/crates/person/src/wot.rs index ccd363c7..58ff5f96 100644 --- a/crates/person/src/wot.rs +++ b/crates/person/src/wot.rs @@ -455,6 +455,11 @@ impl WebOfTrust { self.ready } + /// Whether the graph is loaded and score queries are meaningful + pub fn is_loaded(&self) -> bool { + self.ready && !self.disabled + } + /// Whether scoring is disabled due to an oversized follow set pub fn is_disabled(&self) -> bool { self.disabled diff --git a/crates/workspace/src/dialogs/profile.rs b/crates/workspace/src/dialogs/profile.rs index fc8313ec..fceedd78 100644 --- a/crates/workspace/src/dialogs/profile.rs +++ b/crates/workspace/src/dialogs/profile.rs @@ -9,7 +9,7 @@ use gpui::{ }; use instant::Duration; use nostr_sdk::prelude::*; -use person::{Directory, Person, PersonRegistry, shorten_pubkey}; +use person::{Directory, Person, PersonRegistry, WebOfTrust, shorten_pubkey}; use settings::AppSettings; use state::{NostrRegistry, upload}; use theme::{ActiveTheme, TextStyle, Typeset as _, button_radius}; @@ -459,9 +459,24 @@ impl Render for ProfileDialog { .filter(|website| !website.trim().is_empty()) .map(SharedString::from); + let score = { + let wot = WebOfTrust::global(cx).read(cx); + wot.is_loaded().then(|| wot.score(&self.public_key)) + } + .map(|score| { + SharedString::from(format!( + "{} mutual {}", + score, + if score == 1 { "contact" } else { "contacts" } + )) + }); + this.child(field("Name", name, "Unknown", cx)) .child(field("About", about, "No bio", cx)) .child(field("Website", website, "No website", cx)) + .when(!self.is_current_user, |this| { + this.child(field("Web of Trust", score, "Not loaded yet", cx)) + }) }) .child( h_flex() diff --git a/crates/workspace/src/dialogs/screening.rs b/crates/workspace/src/dialogs/screening.rs index 96fb46a5..819b453b 100644 --- a/crates/workspace/src/dialogs/screening.rs +++ b/crates/workspace/src/dialogs/screening.rs @@ -126,7 +126,7 @@ impl Screening { fn check_wot(&mut self, cx: &mut Context) { let trusted = { let wot = WebOfTrust::global(cx).read(cx); - (wot.is_ready() && !wot.is_disabled()).then(|| wot.mutuals(&self.public_key)) + wot.is_loaded().then(|| wot.mutuals(&self.public_key)) }; if let Some(contacts) = trusted { @@ -166,11 +166,11 @@ impl Screening { 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() { + if WebOfTrust::global(cx).read(cx).is_loaded() { return; } + this.mutual_contacts = contacts; cx.notify(); }) diff --git a/docs/web-of-trust.md b/docs/web-of-trust.md index ad752e5f..02123865 100644 --- a/docs/web-of-trust.md +++ b/docs/web-of-trust.md @@ -150,8 +150,10 @@ Status: **partially implemented**. Request rooms whose members are all outside the web of trust show a `SPAM` badge in the sidebar (`Room::is_spam` + `WebOfTrust::is_outside`, rendered in `crates/workspace/src/sidebar/rows.rs`; the sidebar subscribes to `WoTEvent` so -badges update when the graph loads). The mutual-count caption below is still -open and will follow a different flow. +badges update when the graph loads). The profile dialog shows the score as a +"Web of Trust" field (`crates/workspace/src/dialogs/profile.rs`, other users +only). The mutual-count caption below is still open and will follow a +different flow. Where request rooms are rendered, show the mutual count for the sender: