mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-20 03:57:03 +00:00
Major rework away from PublicKeyHex towards using PublicKey instead. NOTES:
We plan to switch to a different secp256k1 library soon, at which point this PublicKey will become interoperable again, e.g. in gossip-relay-picker
This commit is contained in:
parent
f5538f4476
commit
6b43ae7558
18
src/comms.rs
18
src/comms.rs
@ -1,5 +1,5 @@
|
||||
use nostr_types::{
|
||||
Event, Id, IdHex, Metadata, MilliSatoshi, PublicKey, PublicKeyHex, RelayUrl, Tag, UncheckedUrl,
|
||||
Event, Id, IdHex, Metadata, MilliSatoshi, PublicKey, RelayUrl, Tag, UncheckedUrl,
|
||||
};
|
||||
|
||||
/// This is a message sent to the Overlord
|
||||
@ -38,14 +38,14 @@ pub enum ToOverlordMessage {
|
||||
RankRelay(RelayUrl, u8),
|
||||
SaveSettings,
|
||||
Search(String),
|
||||
SetActivePerson(PublicKeyHex),
|
||||
SetActivePerson(PublicKey),
|
||||
AdjustRelayUsageBit(RelayUrl, u64, bool),
|
||||
SetThreadFeed(Id, Id, Vec<RelayUrl>, Option<PublicKeyHex>),
|
||||
SetThreadFeed(Id, Id, Vec<RelayUrl>, Option<PublicKey>),
|
||||
Shutdown,
|
||||
UnlockKey(String),
|
||||
UpdateFollowing(bool),
|
||||
UpdateMetadata(PublicKeyHex),
|
||||
UpdateMetadataInBulk(Vec<PublicKeyHex>),
|
||||
UpdateMetadata(PublicKey),
|
||||
UpdateMetadataInBulk(Vec<PublicKey>),
|
||||
VisibleNotesChanged(Vec<Id>),
|
||||
ZapStart(Id, PublicKey, UncheckedUrl),
|
||||
Zap(Id, PublicKey, MilliSatoshi, String),
|
||||
@ -77,12 +77,12 @@ pub enum ToMinionPayloadDetail {
|
||||
Shutdown,
|
||||
SubscribeAugments(Vec<IdHex>),
|
||||
SubscribeConfig,
|
||||
SubscribeDiscover(Vec<PublicKeyHex>),
|
||||
SubscribeGeneralFeed(Vec<PublicKeyHex>),
|
||||
SubscribeDiscover(Vec<PublicKey>),
|
||||
SubscribeGeneralFeed(Vec<PublicKey>),
|
||||
SubscribeMentions,
|
||||
SubscribePersonFeed(PublicKeyHex),
|
||||
SubscribePersonFeed(PublicKey),
|
||||
SubscribeThreadFeed(IdHex, Vec<IdHex>),
|
||||
TempSubscribeMetadata(Vec<PublicKeyHex>),
|
||||
TempSubscribeMetadata(Vec<PublicKey>),
|
||||
UnsubscribePersonFeed,
|
||||
UnsubscribeThreadFeed,
|
||||
}
|
||||
|
25
src/feed.rs
25
src/feed.rs
@ -1,7 +1,7 @@
|
||||
use crate::comms::{ToMinionMessage, ToMinionPayload, ToMinionPayloadDetail, ToOverlordMessage};
|
||||
use crate::error::Error;
|
||||
use crate::globals::GLOBALS;
|
||||
use nostr_types::{EventDelegation, EventKind, Id, PublicKey, PublicKeyHex, RelayUrl, Unixtime};
|
||||
use nostr_types::{EventDelegation, EventKind, Id, PublicKey, RelayUrl, Unixtime};
|
||||
use parking_lot::RwLock;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@ -15,9 +15,9 @@ pub enum FeedKind {
|
||||
Thread {
|
||||
id: Id,
|
||||
referenced_by: Id,
|
||||
author: Option<PublicKeyHex>,
|
||||
author: Option<PublicKey>,
|
||||
},
|
||||
Person(PublicKeyHex),
|
||||
Person(PublicKey),
|
||||
}
|
||||
|
||||
pub struct Feed {
|
||||
@ -106,12 +106,12 @@ impl Feed {
|
||||
id: Id,
|
||||
referenced_by: Id,
|
||||
relays: Vec<RelayUrl>,
|
||||
author: Option<PublicKeyHex>,
|
||||
author: Option<PublicKey>,
|
||||
) {
|
||||
*self.current_feed_kind.write() = FeedKind::Thread {
|
||||
id,
|
||||
referenced_by,
|
||||
author: author.clone(),
|
||||
author,
|
||||
};
|
||||
|
||||
// Parent starts with the post itself
|
||||
@ -136,8 +136,8 @@ impl Feed {
|
||||
));
|
||||
}
|
||||
|
||||
pub fn set_feed_to_person(&self, pubkey: PublicKeyHex) {
|
||||
*self.current_feed_kind.write() = FeedKind::Person(pubkey.clone());
|
||||
pub fn set_feed_to_person(&self, pubkey: PublicKey) {
|
||||
*self.current_feed_kind.write() = FeedKind::Person(pubkey);
|
||||
*self.thread_parent.write() = None;
|
||||
|
||||
// Recompute as they switch
|
||||
@ -243,12 +243,7 @@ impl Feed {
|
||||
let current_feed_kind = self.current_feed_kind.read().to_owned();
|
||||
match current_feed_kind {
|
||||
FeedKind::Followed(with_replies) => {
|
||||
let mut followed_pubkeys: Vec<PublicKey> = GLOBALS
|
||||
.people
|
||||
.get_followed_pubkeys()
|
||||
.iter()
|
||||
.map(|pk| PublicKey::try_from_hex_string(pk).unwrap())
|
||||
.collect();
|
||||
let mut followed_pubkeys: Vec<PublicKey> = GLOBALS.people.get_followed_pubkeys();
|
||||
|
||||
if let Some(pubkey) = GLOBALS.signer.public_key() {
|
||||
followed_pubkeys.push(pubkey); // add the user
|
||||
@ -371,11 +366,11 @@ impl Feed {
|
||||
if dismissed.contains(&e.id) {
|
||||
return false;
|
||||
} // not dismissed
|
||||
if e.pubkey.as_hex_string() == person_pubkey.as_str() {
|
||||
if e.pubkey == person_pubkey {
|
||||
true
|
||||
} else {
|
||||
if let EventDelegation::DelegatedBy(pk) = e.delegation() {
|
||||
pk.as_hex_string() == person_pubkey.as_str()
|
||||
pk == person_pubkey
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use crate::delegation::Delegation;
|
||||
use crate::feed::Feed;
|
||||
use crate::fetcher::Fetcher;
|
||||
use crate::media::Media;
|
||||
use crate::people::{Person, People};
|
||||
use crate::people::{People, Person};
|
||||
use crate::relay_picker_hooks::Hooks;
|
||||
use crate::settings::Settings;
|
||||
use crate::signer::Signer;
|
||||
@ -12,9 +12,7 @@ use crate::status::StatusQueue;
|
||||
use crate::storage::Storage;
|
||||
use dashmap::DashMap;
|
||||
use gossip_relay_picker::RelayPicker;
|
||||
use nostr_types::{
|
||||
Event, Id, PayRequestData, Profile, PublicKey, PublicKeyHex, RelayUrl, UncheckedUrl,
|
||||
};
|
||||
use nostr_types::{Event, Id, PayRequestData, Profile, PublicKey, RelayUrl, UncheckedUrl};
|
||||
use parking_lot::RwLock as PRwLock;
|
||||
use regex::Regex;
|
||||
use rusqlite::Connection;
|
||||
@ -83,7 +81,7 @@ pub struct Globals {
|
||||
/// Failed Avatars
|
||||
/// If in this map, the avatar failed to load or process and is unrecoverable
|
||||
/// (but we will take them out and try again if new metadata flows in)
|
||||
pub failed_avatars: RwLock<HashSet<PublicKeyHex>>,
|
||||
pub failed_avatars: RwLock<HashSet<PublicKey>>,
|
||||
|
||||
pub pixels_per_point_times_100: AtomicU32,
|
||||
|
||||
@ -108,7 +106,7 @@ pub struct Globals {
|
||||
|
||||
/// UI note cache invalidation per person
|
||||
// when we update a Person, the UI must recompute all notes by them
|
||||
pub ui_people_to_invalidate: PRwLock<Vec<PublicKeyHex>>,
|
||||
pub ui_people_to_invalidate: PRwLock<Vec<PublicKey>>,
|
||||
|
||||
/// Current zap data, for UI
|
||||
pub current_zap: PRwLock<ZapState>,
|
||||
|
40
src/nip05.rs
40
src/nip05.rs
@ -2,7 +2,7 @@ use crate::db::PersonRelay;
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::globals::GLOBALS;
|
||||
use crate::people::Person;
|
||||
use nostr_types::{Metadata, Nip05, PublicKeyHex, RelayUrl, Unixtime};
|
||||
use nostr_types::{Metadata, Nip05, PublicKey, RelayUrl, Unixtime};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
// This updates the people map and the database with the result
|
||||
@ -50,13 +50,26 @@ pub async fn validate_nip05(person: Person) -> Result<(), Error> {
|
||||
let mut valid = false;
|
||||
match nip05file.names.get(&user) {
|
||||
Some(pk) => {
|
||||
if *pk == person.pubkey {
|
||||
// Validated
|
||||
if let Ok(pubkey) = PublicKey::try_from_hex_string(pk) {
|
||||
if pubkey == person.pubkey {
|
||||
// Validated
|
||||
GLOBALS
|
||||
.people
|
||||
.upsert_nip05_validity(
|
||||
&person.pubkey,
|
||||
Some(nip05.clone()),
|
||||
true,
|
||||
now.0 as u64,
|
||||
)
|
||||
.await?;
|
||||
valid = true;
|
||||
}
|
||||
} else {
|
||||
// Failed
|
||||
GLOBALS
|
||||
.people
|
||||
.upsert_nip05_validity(&person.pubkey, Some(nip05.clone()), true, now.0 as u64)
|
||||
.upsert_nip05_validity(&person.pubkey, Some(nip05.clone()), false, now.0 as u64)
|
||||
.await?;
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
@ -69,10 +82,7 @@ pub async fn validate_nip05(person: Person) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
// UI cache invalidation (so notes of the person get rerendered)
|
||||
GLOBALS
|
||||
.ui_people_to_invalidate
|
||||
.write()
|
||||
.push(person.pubkey.clone());
|
||||
GLOBALS.ui_people_to_invalidate.write().push(person.pubkey);
|
||||
|
||||
if valid {
|
||||
update_relays(nip05, nip05file, &person.pubkey).await?;
|
||||
@ -90,7 +100,7 @@ pub async fn get_and_follow_nip05(nip05: String) -> Result<(), Error> {
|
||||
|
||||
// Get their pubkey
|
||||
let pubkey = match nip05file.names.get(&user) {
|
||||
Some(pk) => pk.to_owned(),
|
||||
Some(pk) => PublicKey::try_from_hex_string(pk)?,
|
||||
None => return Err((ErrorKind::Nip05KeyNotFound, file!(), line!()).into()),
|
||||
};
|
||||
|
||||
@ -115,13 +125,9 @@ pub async fn get_and_follow_nip05(nip05: String) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_relays(
|
||||
nip05: String,
|
||||
nip05file: Nip05,
|
||||
pubkey: &PublicKeyHex,
|
||||
) -> Result<(), Error> {
|
||||
async fn update_relays(nip05: String, nip05file: Nip05, pubkey: &PublicKey) -> Result<(), Error> {
|
||||
// Set their relays
|
||||
let relays = match nip05file.relays.get(pubkey) {
|
||||
let relays = match nip05file.relays.get(&(*pubkey).into()) {
|
||||
Some(relays) => relays,
|
||||
None => return Ok(()),
|
||||
};
|
||||
@ -132,7 +138,7 @@ async fn update_relays(
|
||||
|
||||
// Save person_relay
|
||||
PersonRelay::upsert_last_suggested_nip05(
|
||||
pubkey.to_owned(),
|
||||
(*pubkey).into(),
|
||||
relay_url,
|
||||
Unixtime::now().unwrap().0 as u64,
|
||||
)
|
||||
|
@ -15,8 +15,8 @@ use http::uri::{Parts, Scheme};
|
||||
use http::Uri;
|
||||
use mime::Mime;
|
||||
use nostr_types::{
|
||||
ClientMessage, EventKind, Filter, Id, IdHex, IdHexPrefix, PublicKeyHex, PublicKeyHexPrefix,
|
||||
RelayInformationDocument, RelayUrl, Unixtime,
|
||||
ClientMessage, EventKind, Filter, Id, IdHex, IdHexPrefix, PublicKey, PublicKeyHex,
|
||||
PublicKeyHexPrefix, RelayInformationDocument, RelayUrl, Unixtime,
|
||||
};
|
||||
use reqwest::Response;
|
||||
use std::borrow::Cow;
|
||||
@ -347,16 +347,15 @@ impl Minion {
|
||||
ToMinionPayloadDetail::SubscribeDiscover(pubkeys) => {
|
||||
self.subscribe_discover(message.job_id, pubkeys).await?;
|
||||
}
|
||||
ToMinionPayloadDetail::SubscribePersonFeed(pubkeyhex) => {
|
||||
self.subscribe_person_feed(message.job_id, pubkeyhex)
|
||||
.await?;
|
||||
ToMinionPayloadDetail::SubscribePersonFeed(pubkey) => {
|
||||
self.subscribe_person_feed(message.job_id, pubkey).await?;
|
||||
}
|
||||
ToMinionPayloadDetail::SubscribeThreadFeed(main, parents) => {
|
||||
self.subscribe_thread_feed(message.job_id, main, parents)
|
||||
.await?;
|
||||
}
|
||||
ToMinionPayloadDetail::TempSubscribeMetadata(pubkeyhexs) => {
|
||||
self.temp_subscribe_metadata(message.job_id, pubkeyhexs)
|
||||
ToMinionPayloadDetail::TempSubscribeMetadata(pubkeys) => {
|
||||
self.temp_subscribe_metadata(message.job_id, pubkeys)
|
||||
.await?;
|
||||
}
|
||||
ToMinionPayloadDetail::UnsubscribePersonFeed => {
|
||||
@ -406,7 +405,7 @@ impl Minion {
|
||||
async fn subscribe_general_feed(
|
||||
&mut self,
|
||||
job_id: u64,
|
||||
followed_pubkeys: Vec<PublicKeyHex>,
|
||||
followed_pubkeys: Vec<PublicKey>,
|
||||
) -> Result<(), Error> {
|
||||
let mut filters: Vec<Filter> = Vec::new();
|
||||
let (overlap, feed_chunk) = {
|
||||
@ -472,7 +471,7 @@ impl Minion {
|
||||
if !followed_pubkeys.is_empty() {
|
||||
let pkp: Vec<PublicKeyHexPrefix> = followed_pubkeys
|
||||
.iter()
|
||||
.map(|pk| pk.prefix(16)) // quarter-size
|
||||
.map(|pk| Into::<PublicKeyHex>::into(*pk).prefix(16)) // quarter-size
|
||||
.collect();
|
||||
|
||||
// feed related by people followed
|
||||
@ -493,7 +492,7 @@ impl Minion {
|
||||
.people
|
||||
.get_followed_pubkeys_needing_relay_lists(&followed_pubkeys)
|
||||
.drain(..)
|
||||
.map(|pk| pk.prefix(16)) // quarter-size
|
||||
.map(|pk| Into::<PublicKeyHex>::into(pk).prefix(16)) // quarter-size
|
||||
.collect();
|
||||
|
||||
if !keys_needing_relay_lists.is_empty() {
|
||||
@ -634,10 +633,13 @@ impl Minion {
|
||||
async fn subscribe_discover(
|
||||
&mut self,
|
||||
job_id: u64,
|
||||
pubkeys: Vec<PublicKeyHex>,
|
||||
pubkeys: Vec<PublicKey>,
|
||||
) -> Result<(), Error> {
|
||||
if !pubkeys.is_empty() {
|
||||
let pkp: Vec<PublicKeyHexPrefix> = pubkeys.iter().map(|pk| pk.prefix(16)).collect(); // quarter-size prefix
|
||||
let pkp: Vec<PublicKeyHexPrefix> = pubkeys
|
||||
.iter()
|
||||
.map(|pk| Into::<PublicKeyHex>::into(*pk).prefix(16))
|
||||
.collect(); // quarter-size prefix
|
||||
|
||||
let filters: Vec<Filter> = vec![Filter {
|
||||
authors: pkp,
|
||||
@ -653,11 +655,7 @@ impl Minion {
|
||||
}
|
||||
|
||||
// Subscribe to the posts a person generates on the relays they write to
|
||||
async fn subscribe_person_feed(
|
||||
&mut self,
|
||||
job_id: u64,
|
||||
pubkey: PublicKeyHex,
|
||||
) -> Result<(), Error> {
|
||||
async fn subscribe_person_feed(&mut self, job_id: u64, pubkey: PublicKey) -> Result<(), Error> {
|
||||
// NOTE we do not unsubscribe to the general feed
|
||||
|
||||
// Allow all feed related event kinds
|
||||
@ -667,7 +665,7 @@ impl Minion {
|
||||
.retain(|f| *f != EventKind::EncryptedDirectMessage && *f != EventKind::Reaction);
|
||||
|
||||
let filters: Vec<Filter> = vec![Filter {
|
||||
authors: vec![pubkey.clone().into()],
|
||||
authors: vec![Into::<PublicKeyHex>::into(pubkey).prefix(16)],
|
||||
kinds: event_kinds,
|
||||
// No since, just a limit on quantity of posts
|
||||
limit: Some(25),
|
||||
@ -922,12 +920,12 @@ impl Minion {
|
||||
async fn temp_subscribe_metadata(
|
||||
&mut self,
|
||||
job_id: u64,
|
||||
mut pubkeyhexs: Vec<PublicKeyHex>,
|
||||
mut pubkeys: Vec<PublicKey>,
|
||||
) -> Result<(), Error> {
|
||||
let pkhp: Vec<PublicKeyHexPrefix> = pubkeyhexs
|
||||
let pkhp: Vec<PublicKeyHexPrefix> = pubkeys
|
||||
.drain(..)
|
||||
.map(
|
||||
|pk| pk.prefix(16), // quarter-size
|
||||
|pk| Into::<PublicKeyHex>::into(pk).prefix(16), // quarter-size
|
||||
)
|
||||
.collect();
|
||||
|
||||
|
@ -3,7 +3,7 @@ mod minion;
|
||||
use crate::comms::{
|
||||
RelayJob, ToMinionMessage, ToMinionPayload, ToMinionPayloadDetail, ToOverlordMessage,
|
||||
};
|
||||
use crate::db::{PersonRelay, DbRelay};
|
||||
use crate::db::{DbRelay, PersonRelay};
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::globals::{ZapState, GLOBALS};
|
||||
use crate::people::People;
|
||||
@ -15,9 +15,8 @@ use gossip_relay_picker::{Direction, RelayAssignment};
|
||||
use http::StatusCode;
|
||||
use minion::Minion;
|
||||
use nostr_types::{
|
||||
EncryptedPrivateKey, EventKind, Id, IdHex, Metadata, MilliSatoshi, NostrBech32,
|
||||
PayRequestData, PreEvent, PrivateKey, Profile, PublicKey, PublicKeyHex, RelayUrl, Tag,
|
||||
UncheckedUrl, Unixtime,
|
||||
EncryptedPrivateKey, EventKind, Id, IdHex, Metadata, MilliSatoshi, NostrBech32, PayRequestData,
|
||||
PreEvent, PrivateKey, Profile, PublicKey, PublicKeyHex, RelayUrl, Tag, UncheckedUrl, Unixtime,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::Ordering;
|
||||
@ -715,7 +714,7 @@ impl Overlord {
|
||||
}
|
||||
ToOverlordMessage::UpdateMetadata(pubkey) => {
|
||||
let best_relays =
|
||||
PersonRelay::get_best_relays(pubkey.clone(), Direction::Write).await?;
|
||||
PersonRelay::get_best_relays(pubkey.into(), Direction::Write).await?;
|
||||
let num_relays_per_person = GLOBALS.settings.read().num_relays_per_person;
|
||||
|
||||
// we do 1 more than num_relays_per_person, which is really for main posts,
|
||||
@ -730,9 +729,7 @@ impl Overlord {
|
||||
reason: "tmp-metadata",
|
||||
payload: ToMinionPayload {
|
||||
job_id: rand::random::<u64>(),
|
||||
detail: ToMinionPayloadDetail::TempSubscribeMetadata(vec![
|
||||
pubkey.clone()
|
||||
]),
|
||||
detail: ToMinionPayloadDetail::TempSubscribeMetadata(vec![pubkey]),
|
||||
},
|
||||
persistent: false,
|
||||
}],
|
||||
@ -746,16 +743,16 @@ impl Overlord {
|
||||
}
|
||||
ToOverlordMessage::UpdateMetadataInBulk(mut pubkeys) => {
|
||||
let num_relays_per_person = GLOBALS.settings.read().num_relays_per_person;
|
||||
let mut map: HashMap<RelayUrl, Vec<PublicKeyHex>> = HashMap::new();
|
||||
let mut map: HashMap<RelayUrl, Vec<PublicKey>> = HashMap::new();
|
||||
for pubkey in pubkeys.drain(..) {
|
||||
let best_relays =
|
||||
PersonRelay::get_best_relays(pubkey.clone(), Direction::Write).await?;
|
||||
PersonRelay::get_best_relays(pubkey.into(), Direction::Write).await?;
|
||||
for (relay_url, _score) in
|
||||
best_relays.iter().take(num_relays_per_person as usize + 1)
|
||||
{
|
||||
map.entry(relay_url.to_owned())
|
||||
.and_modify(|entry| entry.push(pubkey.clone()))
|
||||
.or_insert_with(|| vec![pubkey.clone()]);
|
||||
.and_modify(|entry| entry.push(pubkey))
|
||||
.or_insert_with(|| vec![pubkey]);
|
||||
}
|
||||
}
|
||||
for (relay_url, pubkeys) in map.drain() {
|
||||
@ -826,14 +823,13 @@ impl Overlord {
|
||||
pubkeystr: String,
|
||||
relay: RelayUrl,
|
||||
) -> Result<(), Error> {
|
||||
let pk = match PublicKey::try_from_bech32_string(&pubkeystr) {
|
||||
let pubkey = match PublicKey::try_from_bech32_string(&pubkeystr) {
|
||||
Ok(pk) => pk,
|
||||
Err(_) => PublicKey::try_from_hex_string(&pubkeystr)?,
|
||||
};
|
||||
let pkhex: PublicKeyHex = pk.into();
|
||||
GLOBALS.people.async_follow(&pkhex, true).await?;
|
||||
GLOBALS.people.async_follow(&pubkey, true).await?;
|
||||
|
||||
tracing::debug!("Followed {}", &pkhex);
|
||||
tracing::debug!("Followed {}", &pubkey.as_hex_string());
|
||||
|
||||
// Save relay
|
||||
let db_relay = DbRelay::new(relay.clone());
|
||||
@ -843,7 +839,7 @@ impl Overlord {
|
||||
|
||||
// Save person_relay
|
||||
PersonRelay::insert(PersonRelay {
|
||||
person: pkhex.to_string(),
|
||||
person: pubkey.as_hex_string(),
|
||||
relay,
|
||||
last_fetched: None,
|
||||
last_suggested_kind3: Some(now), // consider it our claim in our contact list
|
||||
@ -860,7 +856,7 @@ impl Overlord {
|
||||
// Pick relays to start tracking them now
|
||||
self.pick_relays().await;
|
||||
|
||||
tracing::info!("Setup 1 relay for {}", &pkhex);
|
||||
tracing::info!("Setup 1 relay for {}", &pubkey.as_hex_string());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1347,23 +1343,23 @@ impl Overlord {
|
||||
|
||||
// add own pubkey as well
|
||||
if let Some(pubkey) = GLOBALS.signer.public_key() {
|
||||
pubkeys.push(pubkey.into())
|
||||
pubkeys.push(pubkey)
|
||||
}
|
||||
|
||||
let num_relays_per_person = GLOBALS.settings.read().num_relays_per_person;
|
||||
|
||||
let mut map: HashMap<RelayUrl, Vec<PublicKeyHex>> = HashMap::new();
|
||||
let mut map: HashMap<RelayUrl, Vec<PublicKey>> = HashMap::new();
|
||||
|
||||
// Sort the people into the relays we will find their metadata at
|
||||
for pubkey in &pubkeys {
|
||||
for relayscore in PersonRelay::get_best_relays(pubkey.to_owned(), Direction::Write)
|
||||
for relayscore in PersonRelay::get_best_relays((*pubkey).into(), Direction::Write)
|
||||
.await?
|
||||
.drain(..)
|
||||
.take(num_relays_per_person as usize)
|
||||
{
|
||||
map.entry(relayscore.0)
|
||||
.and_modify(|e| e.push(pubkey.to_owned()))
|
||||
.or_insert_with(|| vec![pubkey.to_owned()]);
|
||||
.and_modify(|e| e.push(*pubkey))
|
||||
.or_insert_with(|| vec![*pubkey]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1503,7 +1499,7 @@ impl Overlord {
|
||||
id: Id,
|
||||
referenced_by: Id,
|
||||
mut relays: Vec<RelayUrl>,
|
||||
author: Option<PublicKeyHex>,
|
||||
author: Option<PublicKey>,
|
||||
) -> Result<(), Error> {
|
||||
// We are responsible for loading all the ancestors and all the replies, and
|
||||
// process.rs is responsible for building the relationships.
|
||||
@ -1522,19 +1518,25 @@ impl Overlord {
|
||||
|
||||
// Include the relays where the referenced_by event was seen
|
||||
relays.extend(
|
||||
GLOBALS.storage.get_event_seen_on_relay(referenced_by)?
|
||||
GLOBALS
|
||||
.storage
|
||||
.get_event_seen_on_relay(referenced_by)?
|
||||
.drain(..)
|
||||
.map(|(url, _time)| url));
|
||||
.map(|(url, _time)| url),
|
||||
);
|
||||
relays.extend(
|
||||
GLOBALS.storage.get_event_seen_on_relay(id)?
|
||||
GLOBALS
|
||||
.storage
|
||||
.get_event_seen_on_relay(id)?
|
||||
.drain(..)
|
||||
.map(|(url, _time)| url));
|
||||
.map(|(url, _time)| url),
|
||||
);
|
||||
|
||||
// If we have less than 2 relays, include the write relays of the author
|
||||
if relays.len() < 2 {
|
||||
if let Some(pkh) = author {
|
||||
if let Some(pk) = author {
|
||||
let author_relays: Vec<RelayUrl> =
|
||||
PersonRelay::get_best_relays(pkh, Direction::Write)
|
||||
PersonRelay::get_best_relays(pk.into(), Direction::Write)
|
||||
.await?
|
||||
.drain(..)
|
||||
.map(|pair| pair.0)
|
||||
@ -1626,8 +1628,7 @@ impl Overlord {
|
||||
}
|
||||
|
||||
async fn follow_nprofile(&mut self, nprofile: Profile) -> Result<(), Error> {
|
||||
let pubkey = nprofile.pubkey.into();
|
||||
GLOBALS.people.async_follow(&pubkey, true).await?;
|
||||
GLOBALS.people.async_follow(&nprofile.pubkey, true).await?;
|
||||
|
||||
// Set their relays
|
||||
for relay in nprofile.relays.iter() {
|
||||
@ -1638,7 +1639,7 @@ impl Overlord {
|
||||
|
||||
// Save person_relay
|
||||
PersonRelay::upsert_last_suggested_nip05(
|
||||
pubkey.to_owned(),
|
||||
nprofile.pubkey.into(),
|
||||
relay_url,
|
||||
Unixtime::now().unwrap().0 as u64,
|
||||
)
|
||||
@ -1756,7 +1757,7 @@ impl Overlord {
|
||||
}
|
||||
};
|
||||
|
||||
let mut pubkeys: Vec<PublicKeyHex> = Vec::new();
|
||||
let mut pubkeys: Vec<PublicKey> = Vec::new();
|
||||
|
||||
let now = Unixtime::now().unwrap();
|
||||
|
||||
@ -1768,33 +1769,34 @@ impl Overlord {
|
||||
..
|
||||
} = tag
|
||||
{
|
||||
// Make sure we have that person
|
||||
GLOBALS
|
||||
.people
|
||||
.create_all_if_missing(&[pubkey.to_owned()])
|
||||
.await?;
|
||||
if let Ok(pubkey) = PublicKey::try_from_hex_string(pubkey) {
|
||||
// Make sure we have that person
|
||||
GLOBALS
|
||||
.people
|
||||
.create_all_if_missing(&[pubkey.to_owned()])
|
||||
.await?;
|
||||
|
||||
// Save the pubkey for actual following them (outside of the loop in a batch)
|
||||
pubkeys.push(pubkey.to_owned());
|
||||
// Save the pubkey for actual following them (outside of the loop in a batch)
|
||||
pubkeys.push(pubkey.to_owned());
|
||||
|
||||
// If there is a URL
|
||||
if let Some(url) = recommended_relay_url
|
||||
.as_ref()
|
||||
.and_then(|rru| RelayUrl::try_from_unchecked_url(rru).ok())
|
||||
{
|
||||
// Save relay if missing
|
||||
GLOBALS.storage.write_relay_if_missing(&url)?;
|
||||
// If there is a URL
|
||||
if let Some(url) = recommended_relay_url
|
||||
.as_ref()
|
||||
.and_then(|rru| RelayUrl::try_from_unchecked_url(rru).ok())
|
||||
{
|
||||
// Save relay if missing
|
||||
GLOBALS.storage.write_relay_if_missing(&url)?;
|
||||
|
||||
// create or update person_relay last_suggested_kind3
|
||||
PersonRelay::upsert_last_suggested_kind3(
|
||||
pubkey.to_string(),
|
||||
url,
|
||||
now.0 as u64,
|
||||
)
|
||||
.await?;
|
||||
// create or update person_relay last_suggested_kind3
|
||||
PersonRelay::upsert_last_suggested_kind3(
|
||||
pubkey.as_hex_string(),
|
||||
url,
|
||||
now.0 as u64,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
// TBD: do something with the petname
|
||||
}
|
||||
|
||||
// TBD: do something with the petname
|
||||
}
|
||||
}
|
||||
|
||||
|
280
src/people.rs
280
src/people.rs
@ -20,7 +20,7 @@ use tokio::task;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Person {
|
||||
pub pubkey: PublicKeyHex,
|
||||
pub pubkey: PublicKey,
|
||||
pub petname: Option<String>,
|
||||
pub followed: u8,
|
||||
pub followed_last_updated: i64,
|
||||
@ -36,7 +36,7 @@ pub struct Person {
|
||||
}
|
||||
|
||||
impl Person {
|
||||
pub fn new(pubkey: PublicKeyHex) -> Person {
|
||||
pub fn new(pubkey: PublicKey) -> Person {
|
||||
Person {
|
||||
pubkey,
|
||||
petname: None,
|
||||
@ -103,30 +103,30 @@ impl Person {
|
||||
}
|
||||
|
||||
pub struct People {
|
||||
people: DashMap<PublicKeyHex, Person>,
|
||||
people: DashMap<PublicKey, Person>,
|
||||
|
||||
// active person's relays (pull from db as needed)
|
||||
active_person: RwLock<Option<PublicKeyHex>>,
|
||||
active_person: RwLock<Option<PublicKey>>,
|
||||
active_persons_write_relays: RwLock<Vec<(RelayUrl, u64)>>,
|
||||
|
||||
// We fetch (with Fetcher), process, and temporarily hold avatars
|
||||
// until the UI next asks for them, at which point we remove them
|
||||
// and hand them over. This way we can do the work that takes
|
||||
// longer and the UI can do as little work as possible.
|
||||
avatars_temp: DashMap<PublicKeyHex, ColorImage>,
|
||||
avatars_pending_processing: DashSet<PublicKeyHex>,
|
||||
avatars_temp: DashMap<PublicKey, ColorImage>,
|
||||
avatars_pending_processing: DashSet<PublicKey>,
|
||||
|
||||
// When we manually ask for updating metadata, we want to recheck
|
||||
// the person's NIP-05 when that metadata come in. We remember this here.
|
||||
recheck_nip05: DashSet<PublicKeyHex>,
|
||||
recheck_nip05: DashSet<PublicKey>,
|
||||
|
||||
// People that need metadata, which the UI has asked for. These people
|
||||
// might simply not be loaded from the database yet.
|
||||
need_metadata: DashSet<PublicKeyHex>,
|
||||
need_metadata: DashSet<PublicKey>,
|
||||
|
||||
// People who we already tried to get their metadata. We only try once
|
||||
// per gossip run (this set only grows)
|
||||
tried_metadata: DashSet<PublicKeyHex>,
|
||||
tried_metadata: DashSet<PublicKey>,
|
||||
|
||||
// Date of the last self-owned contact list we have an event for
|
||||
pub last_contact_list_asof: AtomicI64,
|
||||
@ -173,25 +173,25 @@ impl People {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get_followed_pubkeys(&self) -> Vec<PublicKeyHex> {
|
||||
let mut output: Vec<PublicKeyHex> = Vec::new();
|
||||
pub fn get_followed_pubkeys(&self) -> Vec<PublicKey> {
|
||||
let mut output: Vec<PublicKey> = Vec::new();
|
||||
for person in self
|
||||
.people
|
||||
.iter()
|
||||
.filter_map(|p| if p.followed == 1 { Some(p) } else { None })
|
||||
{
|
||||
output.push(person.pubkey.clone());
|
||||
output.push(person.pubkey);
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
pub fn get_followed_pubkeys_needing_relay_lists(
|
||||
&self,
|
||||
among_these: &[PublicKeyHex],
|
||||
) -> Vec<PublicKeyHex> {
|
||||
among_these: &[PublicKey],
|
||||
) -> Vec<PublicKey> {
|
||||
// FIXME make this a setting (8 hours)
|
||||
let one_day_ago = Unixtime::now().unwrap().0 - (60 * 60 * 8);
|
||||
let mut output: Vec<PublicKeyHex> = Vec::new();
|
||||
let mut output: Vec<PublicKey> = Vec::new();
|
||||
for person in self.people.iter().filter_map(|p| {
|
||||
if p.followed == 1
|
||||
&& p.relay_list_last_received < one_day_ago
|
||||
@ -202,22 +202,22 @@ impl People {
|
||||
None
|
||||
}
|
||||
}) {
|
||||
output.push(person.pubkey.clone());
|
||||
output.push(person.pubkey);
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
pub fn create_if_missing_sync(&self, pubkey: PublicKeyHex) {
|
||||
task::spawn(async {
|
||||
pub fn create_if_missing_sync(&self, pubkey: PublicKey) {
|
||||
task::spawn(async move {
|
||||
if let Err(e) = GLOBALS.people.create_all_if_missing(&[pubkey]).await {
|
||||
tracing::error!("{}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub async fn create_all_if_missing(&self, pubkeys: &[PublicKeyHex]) -> Result<(), Error> {
|
||||
pub async fn create_all_if_missing(&self, pubkeys: &[PublicKey]) -> Result<(), Error> {
|
||||
// Collect the public keys that we don't have already (by checking in memory).
|
||||
let pubkeys: Vec<&PublicKeyHex> = pubkeys
|
||||
let pubkeys: Vec<&PublicKey> = pubkeys
|
||||
.iter()
|
||||
.filter(|pk| !self.people.contains_key(pk))
|
||||
.collect();
|
||||
@ -231,7 +231,7 @@ impl People {
|
||||
sql.push_str(&"(?),".repeat(pubkeys.len()));
|
||||
sql.pop(); // remove trailing comma
|
||||
|
||||
let pubkey_strings: Vec<String> = pubkeys.iter().map(|p| p.to_string()).collect();
|
||||
let pubkey_strings: Vec<String> = pubkeys.iter().map(|p| p.as_hex_string()).collect();
|
||||
|
||||
task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
@ -249,9 +249,7 @@ impl People {
|
||||
// Now load them from the database (some of them may have had records already)
|
||||
let mut loaded_people = Self::fetch_many(&pubkeys).await?;
|
||||
for loaded_person in loaded_people.drain(..) {
|
||||
let _ = self
|
||||
.people
|
||||
.insert(loaded_person.pubkey.clone(), loaded_person);
|
||||
let _ = self.people.insert(loaded_person.pubkey, loaded_person);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -259,23 +257,23 @@ impl People {
|
||||
|
||||
// If this person doesn't have metadata, and we are automatically fetching
|
||||
// metadata, then add this person to the list of people that need metadata.
|
||||
pub fn person_of_interest(&self, pubkeyhex: PublicKeyHex) {
|
||||
pub fn person_of_interest(&self, pubkey: PublicKey) {
|
||||
// Don't get metadata if disabled
|
||||
if !GLOBALS.settings.read().automatically_fetch_metadata {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't try over and over. We try just once per gossip run.
|
||||
if self.tried_metadata.contains(&pubkeyhex) {
|
||||
if self.tried_metadata.contains(&pubkey) {
|
||||
return;
|
||||
}
|
||||
|
||||
match self.people.get(&pubkeyhex) {
|
||||
match self.people.get(&pubkey) {
|
||||
Some(person) => {
|
||||
// If we haven't loaded the person from the database yet
|
||||
if !person.loaded {
|
||||
// Trigger a future load
|
||||
self.create_if_missing_sync(pubkeyhex.clone());
|
||||
self.create_if_missing_sync(pubkey);
|
||||
|
||||
// Don't load metadata now, we may have it on disk and get
|
||||
// it from the future load.
|
||||
@ -296,13 +294,13 @@ impl People {
|
||||
|
||||
// Record that we need it.
|
||||
// the periodic task will take care of it.
|
||||
if !self.need_metadata.contains(&pubkeyhex) {
|
||||
self.need_metadata.insert(pubkeyhex.clone());
|
||||
if !self.need_metadata.contains(&pubkey) {
|
||||
self.need_metadata.insert(pubkey);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// Trigger a future create and load
|
||||
self.create_if_missing_sync(pubkeyhex.clone());
|
||||
self.create_if_missing_sync(pubkey);
|
||||
|
||||
// Don't load metadata now, we may have it on disk and get
|
||||
// it from the future load.
|
||||
@ -313,10 +311,10 @@ impl People {
|
||||
// This is run periodically. It checks the database first, only then does it
|
||||
// ask the overlord to update the metadata from the relays.
|
||||
async fn maybe_fetch_metadata(&self) {
|
||||
let mut verified_need: Vec<PublicKeyHex> = Vec::new();
|
||||
let mut verified_need: Vec<PublicKey> = Vec::new();
|
||||
|
||||
// Take from self.need_metadata;
|
||||
let mut need_metadata: Vec<PublicKeyHex> = self
|
||||
let mut need_metadata: Vec<PublicKey> = self
|
||||
.need_metadata
|
||||
.iter()
|
||||
.map(|refmulti| refmulti.key().to_owned())
|
||||
@ -330,8 +328,8 @@ impl People {
|
||||
for pubkey in need_metadata.drain(..) {
|
||||
if let Some(person) = self.people.get(&pubkey) {
|
||||
if person.loaded {
|
||||
tracing::debug!("Seeking metadata for {}", &pubkey);
|
||||
verified_need.push(pubkey.clone());
|
||||
tracing::debug!("Seeking metadata for {}", pubkey.as_hex_string());
|
||||
verified_need.push(pubkey);
|
||||
self.tried_metadata.insert(pubkey);
|
||||
}
|
||||
}
|
||||
@ -342,30 +340,30 @@ impl People {
|
||||
.send(ToOverlordMessage::UpdateMetadataInBulk(verified_need));
|
||||
}
|
||||
|
||||
pub fn recheck_nip05_on_update_metadata(&self, pubkeyhex: &PublicKeyHex) {
|
||||
self.recheck_nip05.insert(pubkeyhex.to_owned());
|
||||
pub fn recheck_nip05_on_update_metadata(&self, pubkey: &PublicKey) {
|
||||
self.recheck_nip05.insert(pubkey.to_owned());
|
||||
}
|
||||
|
||||
pub async fn update_metadata(
|
||||
&self,
|
||||
pubkeyhex: &PublicKeyHex,
|
||||
pubkey: &PublicKey,
|
||||
metadata: Metadata,
|
||||
asof: Unixtime,
|
||||
) -> Result<(), Error> {
|
||||
// Sync in from database first
|
||||
self.create_all_if_missing(&[pubkeyhex.to_owned()]).await?;
|
||||
self.create_all_if_missing(&[*pubkey]).await?;
|
||||
|
||||
let now = Unixtime::now().unwrap();
|
||||
|
||||
// Update metadata_last_received, even if we don't update the metadata
|
||||
{
|
||||
// Update in memory
|
||||
if let Some(mut person) = self.people.get_mut(pubkeyhex) {
|
||||
if let Some(mut person) = self.people.get_mut(pubkey) {
|
||||
person.metadata_last_received = now.0;
|
||||
}
|
||||
|
||||
// Update in database
|
||||
let pkh = pubkeyhex.as_str().to_owned();
|
||||
let pkh: String = pubkey.as_hex_string();
|
||||
task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
let mut stmt =
|
||||
@ -377,10 +375,10 @@ impl People {
|
||||
}
|
||||
|
||||
// Copy the person
|
||||
let mut person = self.people.get(pubkeyhex).unwrap().to_owned();
|
||||
let mut person = self.people.get(pubkey).unwrap().to_owned();
|
||||
|
||||
// Remove from the list of people that need metadata
|
||||
self.need_metadata.remove(pubkeyhex);
|
||||
self.need_metadata.remove(pubkey);
|
||||
|
||||
// Determine whether it is fresh
|
||||
let fresh = match person.metadata_created_at {
|
||||
@ -397,7 +395,7 @@ impl People {
|
||||
|
||||
// Update person in the map, and the local variable
|
||||
person = {
|
||||
let mut person_mut = self.people.get_mut(pubkeyhex).unwrap();
|
||||
let mut person_mut = self.people.get_mut(pubkey).unwrap();
|
||||
person_mut.metadata = Some(metadata);
|
||||
person_mut.metadata_created_at = Some(asof.0);
|
||||
if nip05_changed {
|
||||
@ -408,7 +406,7 @@ impl People {
|
||||
};
|
||||
|
||||
// Update the database
|
||||
let pubkeyhex2 = pubkeyhex.to_owned();
|
||||
let pubkeyhex2: PublicKeyHex = (*pubkey).into();
|
||||
let person_inner = person.clone();
|
||||
task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
@ -434,14 +432,11 @@ impl People {
|
||||
.await??;
|
||||
|
||||
// UI cache invalidation (so notes of the person get rerendered)
|
||||
GLOBALS
|
||||
.ui_people_to_invalidate
|
||||
.write()
|
||||
.push(pubkeyhex.to_owned());
|
||||
GLOBALS.ui_people_to_invalidate.write().push(*pubkey);
|
||||
}
|
||||
|
||||
// Remove from failed avatars list so the UI will try to fetch the avatar again if missing
|
||||
GLOBALS.failed_avatars.write().await.remove(pubkeyhex);
|
||||
GLOBALS.failed_avatars.write().await.remove(pubkey);
|
||||
|
||||
// Only if they have a nip05 dns id set
|
||||
if matches!(
|
||||
@ -454,8 +449,8 @@ impl People {
|
||||
// Recheck nip05 every day if invalid, and every two weeks if valid
|
||||
|
||||
let recheck = {
|
||||
if self.recheck_nip05.contains(pubkeyhex) {
|
||||
self.recheck_nip05.remove(pubkeyhex);
|
||||
if self.recheck_nip05.contains(pubkey) {
|
||||
self.recheck_nip05.remove(pubkey);
|
||||
true
|
||||
} else if let Some(last) = person.nip05_last_checked {
|
||||
// FIXME make these settings
|
||||
@ -471,8 +466,7 @@ impl People {
|
||||
};
|
||||
|
||||
if recheck {
|
||||
self.update_nip05_last_checked(person.pubkey.clone())
|
||||
.await?;
|
||||
self.update_nip05_last_checked(person.pubkey).await?;
|
||||
task::spawn(async move {
|
||||
if let Err(e) = crate::nip05::validate_nip05(person).await {
|
||||
tracing::error!("{}", e);
|
||||
@ -521,7 +515,7 @@ impl People {
|
||||
};
|
||||
let pk: String = row.get(0)?;
|
||||
output.push(Person {
|
||||
pubkey: PublicKeyHex::try_from_string(pk)?,
|
||||
pubkey: PublicKey::try_from_hex_string(&pk)?,
|
||||
petname: row.get(1)?,
|
||||
followed: row.get(2)?,
|
||||
followed_last_updated: row.get(3)?,
|
||||
@ -541,25 +535,25 @@ impl People {
|
||||
.await?;
|
||||
|
||||
for person in output? {
|
||||
self.people.insert(person.pubkey.clone(), person);
|
||||
self.people.insert(person.pubkey, person);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Get from our memory map. If missing, eventually load from the database
|
||||
pub fn get(&self, pubkeyhex: &PublicKeyHex) -> Option<Person> {
|
||||
if self.people.contains_key(pubkeyhex) {
|
||||
self.people.get(pubkeyhex).map(|o| o.value().to_owned())
|
||||
pub fn get(&self, pubkey: &PublicKey) -> Option<Person> {
|
||||
if self.people.contains_key(pubkey) {
|
||||
self.people.get(pubkey).map(|o| o.value().to_owned())
|
||||
} else {
|
||||
// We can't get it now, but we can setup a task to do it soon
|
||||
let pubkeyhex = pubkeyhex.to_owned();
|
||||
let pubkey = pubkey.to_owned();
|
||||
tokio::spawn(async move {
|
||||
#[allow(clippy::map_entry)]
|
||||
if !GLOBALS.people.people.contains_key(&pubkeyhex) {
|
||||
match People::fetch_one(&pubkeyhex).await {
|
||||
if !GLOBALS.people.people.contains_key(&pubkey) {
|
||||
match People::fetch_one(&pubkey).await {
|
||||
Ok(Some(person)) => {
|
||||
let _ = GLOBALS.people.people.insert(pubkeyhex, person);
|
||||
let _ = GLOBALS.people.people.insert(pubkey, person);
|
||||
}
|
||||
Err(e) => tracing::error!("{}", e),
|
||||
_ => {}
|
||||
@ -578,7 +572,7 @@ impl People {
|
||||
.map(|s| s.to_lowercase())
|
||||
.cmp(&b.display_name().map(|s| s.to_lowercase()));
|
||||
if c == std::cmp::Ordering::Equal {
|
||||
a.pubkey.cmp(&b.pubkey)
|
||||
a.pubkey.as_hex_string().cmp(&b.pubkey.as_hex_string())
|
||||
} else {
|
||||
c
|
||||
}
|
||||
@ -586,19 +580,19 @@ impl People {
|
||||
v
|
||||
}
|
||||
|
||||
pub fn get_avatar(&self, pubkeyhex: &PublicKeyHex) -> Option<ColorImage> {
|
||||
pub fn get_avatar(&self, pubkey: &PublicKey) -> Option<ColorImage> {
|
||||
// If we have it, hand it over (we won't need a copy anymore)
|
||||
if let Some(th) = self.avatars_temp.remove(pubkeyhex) {
|
||||
if let Some(th) = self.avatars_temp.remove(pubkey) {
|
||||
return Some(th.1);
|
||||
}
|
||||
|
||||
// If it failed before, error out now
|
||||
if GLOBALS.failed_avatars.blocking_read().contains(pubkeyhex) {
|
||||
if GLOBALS.failed_avatars.blocking_read().contains(pubkey) {
|
||||
return None; // cannot recover.
|
||||
}
|
||||
|
||||
// If it is pending processing, respond now
|
||||
if self.avatars_pending_processing.contains(pubkeyhex) {
|
||||
if self.avatars_pending_processing.contains(pubkey) {
|
||||
return None; // will recover after processing completes
|
||||
}
|
||||
|
||||
@ -608,7 +602,7 @@ impl People {
|
||||
}
|
||||
|
||||
// Get the person this is about
|
||||
let person = match self.people.get(pubkeyhex) {
|
||||
let person = match self.people.get(pubkey) {
|
||||
Some(person) => person,
|
||||
None => {
|
||||
return None; // can recover once the person is loaded
|
||||
@ -618,10 +612,7 @@ impl People {
|
||||
// Fail permanently if they don't have a picture url
|
||||
if person.picture().is_none() {
|
||||
// this cannot recover without new metadata
|
||||
GLOBALS
|
||||
.failed_avatars
|
||||
.blocking_write()
|
||||
.insert(pubkeyhex.to_owned());
|
||||
GLOBALS.failed_avatars.blocking_write().insert(*pubkey);
|
||||
|
||||
return None;
|
||||
}
|
||||
@ -632,10 +623,7 @@ impl People {
|
||||
Ok(url) => url,
|
||||
Err(_) => {
|
||||
// this cannot recover without new metadata
|
||||
GLOBALS
|
||||
.failed_avatars
|
||||
.blocking_write()
|
||||
.insert(pubkeyhex.to_owned());
|
||||
GLOBALS.failed_avatars.blocking_write().insert(*pubkey);
|
||||
|
||||
return None;
|
||||
}
|
||||
@ -649,7 +637,7 @@ impl People {
|
||||
Ok(None) => None,
|
||||
Ok(Some(bytes)) => {
|
||||
// Finish this later (spawn)
|
||||
let apubkeyhex = pubkeyhex.to_owned();
|
||||
let apubkey = *pubkey;
|
||||
tokio::spawn(async move {
|
||||
let size = AVATAR_SIZE * 3 // 3x feed size, 1x people page size
|
||||
* GLOBALS
|
||||
@ -691,7 +679,7 @@ impl People {
|
||||
if GLOBALS.settings.read().theme.round_image() {
|
||||
round_image(&mut color_image);
|
||||
}
|
||||
GLOBALS.people.avatars_temp.insert(apubkeyhex, color_image);
|
||||
GLOBALS.people.avatars_temp.insert(apubkey, color_image);
|
||||
} else if let Ok(mut color_image) = egui_extras::image::load_svg_bytes_with_size(
|
||||
&bytes,
|
||||
FitTo::Size(size, size),
|
||||
@ -699,26 +687,19 @@ impl People {
|
||||
if GLOBALS.settings.read().theme.round_image() {
|
||||
round_image(&mut color_image);
|
||||
}
|
||||
GLOBALS.people.avatars_temp.insert(apubkeyhex, color_image);
|
||||
GLOBALS.people.avatars_temp.insert(apubkey, color_image);
|
||||
} else {
|
||||
// this cannot recover without new metadata
|
||||
GLOBALS
|
||||
.failed_avatars
|
||||
.write()
|
||||
.await
|
||||
.insert(apubkeyhex.to_owned());
|
||||
GLOBALS.failed_avatars.write().await.insert(apubkey);
|
||||
};
|
||||
});
|
||||
self.avatars_pending_processing.insert(pubkeyhex.to_owned());
|
||||
self.avatars_pending_processing.insert(pubkey.to_owned());
|
||||
None
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("{}", e);
|
||||
// this cannot recover without new metadata
|
||||
GLOBALS
|
||||
.failed_avatars
|
||||
.blocking_write()
|
||||
.insert(pubkeyhex.to_owned());
|
||||
GLOBALS.failed_avatars.blocking_write().insert(*pubkey);
|
||||
None
|
||||
}
|
||||
}
|
||||
@ -735,7 +716,7 @@ impl People {
|
||||
let search = String::from(text).to_lowercase();
|
||||
|
||||
// grab all results then sort by score
|
||||
let mut results: Vec<(u16, String, PublicKeyHex)> = self
|
||||
let mut results: Vec<(u16, String, PublicKey)> = self
|
||||
.people
|
||||
.iter()
|
||||
.filter_map(|person| {
|
||||
@ -773,13 +754,13 @@ impl People {
|
||||
// if there is not a name, fallback to showing the initial chars of the pubkey,
|
||||
// but this is probably unnecessary and will never happen
|
||||
if result_name.is_empty() {
|
||||
result_name = person.pubkey.to_string();
|
||||
result_name = person.pubkey.as_hex_string();
|
||||
}
|
||||
|
||||
// bigger names have a higher match chance, but they should be scored lower
|
||||
score -= result_name.len() as u16;
|
||||
|
||||
return Some((score, result_name, person.pubkey.clone()));
|
||||
return Some((score, result_name, person.pubkey));
|
||||
}
|
||||
|
||||
None
|
||||
@ -794,12 +775,7 @@ impl People {
|
||||
};
|
||||
results[0..max]
|
||||
.iter()
|
||||
.map(|r| {
|
||||
(
|
||||
r.1.to_owned(),
|
||||
PublicKey::try_from_hex_string(&r.2).unwrap(),
|
||||
)
|
||||
})
|
||||
.map(|r| (r.1.to_owned(), r.2.to_owned()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -823,10 +799,10 @@ impl People {
|
||||
let pubkeys = self.get_followed_pubkeys();
|
||||
for pubkey in &pubkeys {
|
||||
// Get their best relay
|
||||
let relays = PersonRelay::get_best_relays(pubkey.clone(), Direction::Write).await?;
|
||||
let relays = PersonRelay::get_best_relays((*pubkey).into(), Direction::Write).await?;
|
||||
let maybeurl = relays.get(0);
|
||||
p_tags.push(Tag::Pubkey {
|
||||
pubkey: pubkey.clone(),
|
||||
pubkey: (*pubkey).into(),
|
||||
recommended_relay_url: maybeurl.map(|(u, _)| u.to_unchecked_url()),
|
||||
petname: None,
|
||||
trailing: Vec::new(),
|
||||
@ -862,19 +838,19 @@ impl People {
|
||||
GLOBALS.signer.sign_preevent(pre_event, None, None)
|
||||
}
|
||||
|
||||
pub fn follow(&self, pubkeyhex: &PublicKeyHex, follow: bool) {
|
||||
pub fn follow(&self, pubkey: &PublicKey, follow: bool) {
|
||||
// We can't do it now, but we spawn a task to do it soon
|
||||
let pubkeyhex = pubkeyhex.to_owned();
|
||||
let pubkey = pubkey.to_owned();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = GLOBALS.people.async_follow(&pubkeyhex, follow).await {
|
||||
if let Err(e) = GLOBALS.people.async_follow(&pubkey, follow).await {
|
||||
tracing::error!("{}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub async fn async_follow(&self, pubkeyhex: &PublicKeyHex, follow: bool) -> Result<(), Error> {
|
||||
pub async fn async_follow(&self, pubkey: &PublicKey, follow: bool) -> Result<(), Error> {
|
||||
// Skip if they are already followed (or already not followed)
|
||||
let already_followed = self.get_followed_pubkeys().contains(pubkeyhex);
|
||||
let already_followed = self.get_followed_pubkeys().contains(pubkey);
|
||||
if follow == already_followed {
|
||||
return Ok(());
|
||||
}
|
||||
@ -884,22 +860,22 @@ impl People {
|
||||
// Follow in database
|
||||
let sql = "INSERT INTO PERSON (pubkey, followed) values (?, ?) \
|
||||
ON CONFLICT(pubkey) DO UPDATE SET followed=?";
|
||||
let pubkeyhex2 = pubkeyhex.to_owned();
|
||||
let pubkeyhexstr = pubkey.as_hex_string();
|
||||
task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
let mut stmt = db.prepare(sql)?;
|
||||
stmt.execute((pubkeyhex2.as_str(), &follow, &follow))?;
|
||||
stmt.execute((pubkeyhexstr, &follow, &follow))?;
|
||||
Ok::<(), Error>(())
|
||||
})
|
||||
.await??;
|
||||
|
||||
// Make sure memory matches
|
||||
if let Some(mut dbperson) = self.people.get_mut(pubkeyhex) {
|
||||
if let Some(mut dbperson) = self.people.get_mut(pubkey) {
|
||||
dbperson.followed = follow;
|
||||
} else {
|
||||
// load
|
||||
if let Some(person) = Self::fetch_one(pubkeyhex).await? {
|
||||
self.people.insert(pubkeyhex.to_owned(), person);
|
||||
if let Some(person) = Self::fetch_one(pubkey).await? {
|
||||
self.people.insert(pubkey.to_owned(), person);
|
||||
}
|
||||
}
|
||||
|
||||
@ -907,13 +883,13 @@ impl People {
|
||||
GLOBALS
|
||||
.ui_people_to_invalidate
|
||||
.write()
|
||||
.push(pubkeyhex.to_owned());
|
||||
.push(pubkey.to_owned());
|
||||
|
||||
if follow > 0 {
|
||||
// Add the person to the relay_picker for picking
|
||||
GLOBALS.relay_picker.add_someone(pubkeyhex.to_owned())?;
|
||||
GLOBALS.relay_picker.add_someone(pubkey.to_owned())?;
|
||||
} else {
|
||||
GLOBALS.relay_picker.remove_someone(pubkeyhex.to_owned());
|
||||
GLOBALS.relay_picker.remove_someone(pubkey.to_owned());
|
||||
}
|
||||
|
||||
// Update last_contact_list_edit
|
||||
@ -923,7 +899,7 @@ impl People {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn follow_all(&self, pubkeys: &[PublicKeyHex], merge: bool) -> Result<(), Error> {
|
||||
pub async fn follow_all(&self, pubkeys: &[PublicKey], merge: bool) -> Result<(), Error> {
|
||||
// If merging, and we already follow all these keys,
|
||||
// then just bail out
|
||||
if merge {
|
||||
@ -956,7 +932,8 @@ impl People {
|
||||
repeat_vars(pubkeys.len())
|
||||
);
|
||||
|
||||
let pubkey_strings: Vec<String> = pubkeys.iter().map(|p| p.to_string()).collect();
|
||||
let pubkey_strings: Vec<String> = pubkeys.iter().map(|p| p.as_hex_string()).collect();
|
||||
let pubkey_strings2 = pubkey_strings.clone();
|
||||
|
||||
let now = Unixtime::now().unwrap();
|
||||
|
||||
@ -982,14 +959,12 @@ impl People {
|
||||
repeat_vars(pubkeys.len())
|
||||
);
|
||||
|
||||
let pubkey_strings: Vec<String> = pubkeys.iter().map(|p| p.to_string()).collect();
|
||||
|
||||
task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
let mut stmt = db.prepare(&sql)?;
|
||||
stmt.raw_bind_parameter(1, now.0)?;
|
||||
let mut pos = 2;
|
||||
for pk in pubkey_strings.iter() {
|
||||
for pk in pubkey_strings2.iter() {
|
||||
stmt.raw_bind_parameter(pos, pk)?;
|
||||
pos += 1;
|
||||
}
|
||||
@ -1001,9 +976,9 @@ impl People {
|
||||
|
||||
// Make sure memory matches
|
||||
for mut elem in self.people.iter_mut() {
|
||||
let pkh = elem.key().clone();
|
||||
let pk = *elem.key();
|
||||
let person = elem.value_mut();
|
||||
if pubkeys.contains(&pkh) {
|
||||
if pubkeys.contains(&pk) {
|
||||
person.followed = 1;
|
||||
} else if !merge {
|
||||
person.followed = 0;
|
||||
@ -1038,38 +1013,37 @@ impl People {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mute(&self, pubkeyhex: &PublicKeyHex, mute: bool) {
|
||||
pub fn mute(&self, pubkey: PublicKey, mute: bool) {
|
||||
// We can't do it now, but we spawn a task to do it soon
|
||||
let pubkeyhex = pubkeyhex.to_owned();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = GLOBALS.people.async_mute(&pubkeyhex, mute).await {
|
||||
if let Err(e) = GLOBALS.people.async_mute(&pubkey, mute).await {
|
||||
tracing::error!("{}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub async fn async_mute(&self, pubkeyhex: &PublicKeyHex, mute: bool) -> Result<(), Error> {
|
||||
pub async fn async_mute(&self, pubkey: &PublicKey, mute: bool) -> Result<(), Error> {
|
||||
let mute: u8 = u8::from(mute);
|
||||
|
||||
// Mute in database
|
||||
let sql = "INSERT INTO PERSON (pubkey, muted) values (?, ?) \
|
||||
ON CONFLICT(pubkey) DO UPDATE SET muted=?";
|
||||
let pubkeyhex2 = pubkeyhex.to_owned();
|
||||
let pubkeyhexstr = pubkey.as_hex_string();
|
||||
task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
let mut stmt = db.prepare(sql)?;
|
||||
stmt.execute((pubkeyhex2.as_str(), &mute, &mute))?;
|
||||
stmt.execute((pubkeyhexstr, &mute, &mute))?;
|
||||
Ok::<(), Error>(())
|
||||
})
|
||||
.await??;
|
||||
|
||||
// Make sure memory matches
|
||||
if let Some(mut dbperson) = self.people.get_mut(pubkeyhex) {
|
||||
if let Some(mut dbperson) = self.people.get_mut(pubkey) {
|
||||
dbperson.muted = mute;
|
||||
} else {
|
||||
// load
|
||||
if let Some(person) = Self::fetch_one(pubkeyhex).await? {
|
||||
self.people.insert(pubkeyhex.to_owned(), person);
|
||||
if let Some(person) = Self::fetch_one(pubkey).await? {
|
||||
self.people.insert(pubkey.to_owned(), person);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1077,7 +1051,7 @@ impl People {
|
||||
GLOBALS
|
||||
.ui_people_to_invalidate
|
||||
.write()
|
||||
.push(pubkeyhex.to_owned());
|
||||
.push(pubkey.to_owned());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1085,14 +1059,14 @@ impl People {
|
||||
// Returns true if the date passed in is newer than what we already had
|
||||
pub async fn update_relay_list_stamps(
|
||||
&self,
|
||||
pubkeyhex: PublicKeyHex,
|
||||
pubkey: PublicKey,
|
||||
mut created_at: i64,
|
||||
) -> Result<bool, Error> {
|
||||
let now = Unixtime::now().unwrap().0;
|
||||
|
||||
let mut retval = false;
|
||||
|
||||
if let Some(mut person) = self.people.get_mut(&pubkeyhex) {
|
||||
if let Some(mut person) = self.people.get_mut(&pubkey) {
|
||||
person.relay_list_last_received = now;
|
||||
|
||||
if let Some(old_at) = person.relay_list_created_at {
|
||||
@ -1116,7 +1090,7 @@ impl People {
|
||||
"UPDATE person SET relay_list_last_received=?, \
|
||||
relay_list_created_at=? WHERE pubkey=?",
|
||||
)?;
|
||||
stmt.execute((&now, &created_at, pubkeyhex.as_str()))?;
|
||||
stmt.execute((&now, &created_at, pubkey.as_hex_string()))?;
|
||||
Ok::<(), Error>(())
|
||||
})
|
||||
.await??;
|
||||
@ -1124,17 +1098,17 @@ impl People {
|
||||
Ok(retval)
|
||||
}
|
||||
|
||||
pub async fn update_nip05_last_checked(&self, pubkeyhex: PublicKeyHex) -> Result<(), Error> {
|
||||
pub async fn update_nip05_last_checked(&self, pubkey: PublicKey) -> Result<(), Error> {
|
||||
let now = Unixtime::now().unwrap().0;
|
||||
|
||||
if let Some(mut person) = self.people.get_mut(&pubkeyhex) {
|
||||
if let Some(mut person) = self.people.get_mut(&pubkey) {
|
||||
person.nip05_last_checked = Some(now as u64);
|
||||
}
|
||||
|
||||
task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
let mut stmt = db.prepare("UPDATE person SET nip05_last_checked=? WHERE pubkey=?")?;
|
||||
stmt.execute((&now, pubkeyhex.as_str()))?;
|
||||
stmt.execute((&now, pubkey.as_hex_string()))?;
|
||||
Ok(())
|
||||
})
|
||||
.await?
|
||||
@ -1142,13 +1116,13 @@ impl People {
|
||||
|
||||
pub async fn upsert_nip05_validity(
|
||||
&self,
|
||||
pubkeyhex: &PublicKeyHex,
|
||||
pubkey: &PublicKey,
|
||||
nip05: Option<String>,
|
||||
nip05_valid: bool,
|
||||
nip05_last_checked: u64,
|
||||
) -> Result<(), Error> {
|
||||
// Update memory
|
||||
if let Some(mut dbperson) = self.people.get_mut(pubkeyhex) {
|
||||
if let Some(mut dbperson) = self.people.get_mut(pubkey) {
|
||||
if let Some(metadata) = &mut dbperson.metadata {
|
||||
metadata.nip05 = nip05.clone()
|
||||
} else {
|
||||
@ -1166,7 +1140,7 @@ impl People {
|
||||
ON CONFLICT(pubkey) DO \
|
||||
UPDATE SET metadata=json_patch(metadata, ?), nip05_valid=?, nip05_last_checked=?";
|
||||
|
||||
let pubkeyhex2 = pubkeyhex.to_owned();
|
||||
let pubkey2 = pubkey.to_owned();
|
||||
task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
let mut metadata = Metadata::new();
|
||||
@ -1177,7 +1151,7 @@ impl People {
|
||||
|
||||
let mut stmt = db.prepare(sql)?;
|
||||
stmt.execute((
|
||||
pubkeyhex2.as_str(),
|
||||
pubkey2.as_hex_string(),
|
||||
&metadata_json,
|
||||
&nip05_valid,
|
||||
&nip05_last_checked,
|
||||
@ -1193,7 +1167,7 @@ impl People {
|
||||
GLOBALS
|
||||
.ui_people_to_invalidate
|
||||
.write()
|
||||
.push(pubkeyhex.to_owned());
|
||||
.push(pubkey.to_owned());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1224,7 +1198,7 @@ impl People {
|
||||
};
|
||||
let pk: String = row.get(0)?;
|
||||
output.push(Person {
|
||||
pubkey: PublicKeyHex::try_from_string(pk)?,
|
||||
pubkey: PublicKey::try_from_hex_string(&pk)?,
|
||||
petname: row.get(1)?,
|
||||
followed: row.get(2)?,
|
||||
followed_last_updated: row.get(3)?,
|
||||
@ -1246,8 +1220,8 @@ impl People {
|
||||
output
|
||||
}
|
||||
|
||||
async fn fetch_one(pubkeyhex: &PublicKeyHex) -> Result<Option<Person>, Error> {
|
||||
let people = Self::fetch(Some(&format!("pubkey='{}'", pubkeyhex))).await?;
|
||||
async fn fetch_one(pubkey: &PublicKey) -> Result<Option<Person>, Error> {
|
||||
let people = Self::fetch(Some(&format!("pubkey='{}'", pubkey.as_hex_string()))).await?;
|
||||
|
||||
if people.is_empty() {
|
||||
Ok(None)
|
||||
@ -1256,7 +1230,7 @@ impl People {
|
||||
}
|
||||
}
|
||||
|
||||
async fn fetch_many(pubkeys: &[&PublicKeyHex]) -> Result<Vec<Person>, Error> {
|
||||
async fn fetch_many(pubkeys: &[&PublicKey]) -> Result<Vec<Person>, Error> {
|
||||
let sql = format!(
|
||||
"SELECT pubkey, petname, \
|
||||
followed, followed_last_updated, muted, \
|
||||
@ -1267,7 +1241,7 @@ impl People {
|
||||
repeat_vars(pubkeys.len())
|
||||
);
|
||||
|
||||
let pubkey_strings: Vec<String> = pubkeys.iter().map(|p| p.to_string()).collect();
|
||||
let pubkey_strings: Vec<String> = pubkeys.iter().map(|p| p.as_hex_string()).collect();
|
||||
|
||||
let output: Result<Vec<Person>, Error> = task::spawn_blocking(move || {
|
||||
let db = GLOBALS.db.blocking_lock();
|
||||
@ -1288,7 +1262,7 @@ impl People {
|
||||
};
|
||||
let pk: String = row.get(0)?;
|
||||
people.push(Person {
|
||||
pubkey: PublicKeyHex::try_from_string(pk)?,
|
||||
pubkey: PublicKey::try_from_hex_string(&pk)?,
|
||||
petname: row.get(1)?,
|
||||
followed: row.get(2)?,
|
||||
followed_last_updated: row.get(3)?,
|
||||
@ -1318,19 +1292,19 @@ impl People {
|
||||
}
|
||||
*/
|
||||
|
||||
pub async fn set_active_person(&self, pubkey: PublicKeyHex) -> Result<(), Error> {
|
||||
pub async fn set_active_person(&self, pubkey: PublicKey) -> Result<(), Error> {
|
||||
// Set the active person
|
||||
*self.active_person.write().await = Some(pubkey.clone());
|
||||
*self.active_person.write().await = Some(pubkey);
|
||||
|
||||
// Load their relays
|
||||
let best_relays = PersonRelay::get_best_relays(pubkey, Direction::Write).await?;
|
||||
let best_relays = PersonRelay::get_best_relays(pubkey.into(), Direction::Write).await?;
|
||||
*self.active_persons_write_relays.write().await = best_relays;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_active_person(&self) -> Option<PublicKeyHex> {
|
||||
self.active_person.blocking_read().clone()
|
||||
pub fn get_active_person(&self) -> Option<PublicKey> {
|
||||
*self.active_person.blocking_read()
|
||||
}
|
||||
|
||||
pub fn get_active_person_write_relays(&self) -> Vec<(RelayUrl, u64)> {
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::comms::ToOverlordMessage;
|
||||
use crate::db::{PersonRelay, DbRelay};
|
||||
use crate::db::{DbRelay, PersonRelay};
|
||||
use crate::error::Error;
|
||||
use crate::globals::GLOBALS;
|
||||
use nostr_types::{
|
||||
Event, EventKind, Metadata, NostrBech32, RelayUrl, SimpleRelayList, Tag, Unixtime,
|
||||
Event, EventKind, Metadata, NostrBech32, PublicKey, RelayUrl, SimpleRelayList, Tag, Unixtime,
|
||||
};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
@ -83,7 +83,7 @@ pub async fn process_new_event(
|
||||
// Create the person if missing in the database
|
||||
GLOBALS
|
||||
.people
|
||||
.create_all_if_missing(&[event.pubkey.into()])
|
||||
.create_all_if_missing(&[event.pubkey])
|
||||
.await?;
|
||||
|
||||
if let Some(ref url) = seen_on {
|
||||
@ -114,22 +114,21 @@ pub async fn process_new_event(
|
||||
recommended_relay_url: Some(should_be_url),
|
||||
..
|
||||
} => {
|
||||
if let Ok(url) = RelayUrl::try_from_unchecked_url(should_be_url) {
|
||||
GLOBALS.storage.write_relay_if_missing(&url)?;
|
||||
if let Ok(pubkey) = PublicKey::try_from_hex_string(pubkey) {
|
||||
if let Ok(url) = RelayUrl::try_from_unchecked_url(should_be_url) {
|
||||
GLOBALS.storage.write_relay_if_missing(&url)?;
|
||||
|
||||
// Add person if missing
|
||||
GLOBALS
|
||||
.people
|
||||
.create_all_if_missing(&[pubkey.clone()])
|
||||
// Add person if missing
|
||||
GLOBALS.people.create_all_if_missing(&[pubkey]).await?;
|
||||
|
||||
// upsert person_relay.last_suggested_bytag
|
||||
PersonRelay::upsert_last_suggested_bytag(
|
||||
pubkey.as_hex_string(),
|
||||
url,
|
||||
now.0 as u64,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// upsert person_relay.last_suggested_bytag
|
||||
PersonRelay::upsert_last_suggested_bytag(
|
||||
pubkey.to_string(),
|
||||
url,
|
||||
now.0 as u64,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -138,7 +137,7 @@ pub async fn process_new_event(
|
||||
}
|
||||
|
||||
// Save event relationships (whether from a relay or not)
|
||||
let invalid_ids = GLOBALS.storage.process_relationships_of_event(&event)?;
|
||||
let invalid_ids = GLOBALS.storage.process_relationships_of_event(event)?;
|
||||
|
||||
// Invalidate UI events indicated by those relationships
|
||||
GLOBALS.ui_notes_to_invalidate.write().extend(&invalid_ids);
|
||||
@ -157,7 +156,7 @@ pub async fn process_new_event(
|
||||
|
||||
GLOBALS
|
||||
.people
|
||||
.update_metadata(&event.pubkey.into(), metadata, event.created_at)
|
||||
.update_metadata(&event.pubkey, metadata, event.created_at)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@ -235,7 +234,7 @@ async fn process_relay_list(event: &Event) -> Result<(), Error> {
|
||||
// if this relay list happens to be newer)
|
||||
let newer = GLOBALS
|
||||
.people
|
||||
.update_relay_list_stamps(event.pubkey.into(), event.created_at.0)
|
||||
.update_relay_list_stamps(event.pubkey, event.created_at.0)
|
||||
.await?;
|
||||
|
||||
if !newer {
|
||||
@ -339,7 +338,7 @@ async fn process_somebody_elses_contact_list(event: &Event) -> Result<(), Error>
|
||||
// if this relay list happens to be newer)
|
||||
let newer = GLOBALS
|
||||
.people
|
||||
.update_relay_list_stamps(event.pubkey.into(), event.created_at.0)
|
||||
.update_relay_list_stamps(event.pubkey, event.created_at.0)
|
||||
.await?;
|
||||
|
||||
if !newer {
|
||||
|
@ -3,7 +3,7 @@ use crate::error::Error;
|
||||
use crate::globals::GLOBALS;
|
||||
use async_trait::async_trait;
|
||||
use gossip_relay_picker::{Direction, RelayPickerHooks};
|
||||
use nostr_types::{PublicKeyHex, RelayUrl};
|
||||
use nostr_types::{PublicKey, RelayUrl};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Hooks {}
|
||||
@ -23,10 +23,10 @@ impl RelayPickerHooks for Hooks {
|
||||
/// Returns all relays that this public key uses in the given Direction
|
||||
async fn get_relays_for_pubkey(
|
||||
&self,
|
||||
pubkey: PublicKeyHex,
|
||||
pubkey: PublicKey,
|
||||
direction: Direction,
|
||||
) -> Result<Vec<(RelayUrl, u64)>, Error> {
|
||||
PersonRelay::get_best_relays(pubkey, direction).await
|
||||
PersonRelay::get_best_relays(pubkey.into(), direction).await
|
||||
}
|
||||
|
||||
/// Is the relay currently connected?
|
||||
@ -46,7 +46,7 @@ impl RelayPickerHooks for Hooks {
|
||||
}
|
||||
|
||||
/// Returns the public keys of all the people followed
|
||||
fn get_followed_pubkeys(&self) -> Vec<PublicKeyHex> {
|
||||
fn get_followed_pubkeys(&self) -> Vec<PublicKey> {
|
||||
GLOBALS.people.get_followed_pubkeys()
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@ impl Storage {
|
||||
return Err(ErrorKind::General(format!(
|
||||
"Migration level {} unknown: This client is older than your data.",
|
||||
level
|
||||
)).into());
|
||||
))
|
||||
.into());
|
||||
}
|
||||
|
||||
while level < Self::MIGRATION_LEVEL {
|
||||
|
@ -831,7 +831,6 @@ impl Storage {
|
||||
|
||||
// This returns IDs that should be UI invalidated
|
||||
pub fn process_relationships_of_event(&self, event: &Event) -> Result<Vec<Id>, Error> {
|
||||
|
||||
let mut invalidate: Vec<Id> = Vec::new();
|
||||
|
||||
// replies to
|
||||
@ -841,11 +840,7 @@ impl Storage {
|
||||
|
||||
// reacts to
|
||||
if let Some((id, reaction, _maybe_url)) = event.reacts_to() {
|
||||
self.write_relationship(
|
||||
id,
|
||||
event.id,
|
||||
Relationship::Reaction(event.pubkey, reaction),
|
||||
)?;
|
||||
self.write_relationship(id, event.id, Relationship::Reaction(event.pubkey, reaction))?;
|
||||
|
||||
invalidate.push(id);
|
||||
}
|
||||
@ -857,11 +852,7 @@ impl Storage {
|
||||
for id in ids {
|
||||
// since it is a delete, we don't actually desire the event.
|
||||
|
||||
self.write_relationship(
|
||||
id,
|
||||
event.id,
|
||||
Relationship::Deletion(reason.clone()),
|
||||
)?;
|
||||
self.write_relationship(id, event.id, Relationship::Deletion(reason.clone()))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,13 +137,13 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
||||
render_a_feed(app, ctx, frame, ui, vec![parent], true, &id.as_hex_string());
|
||||
}
|
||||
}
|
||||
FeedKind::Person(pubkeyhex) => {
|
||||
FeedKind::Person(pubkey) => {
|
||||
ui.horizontal(|ui| {
|
||||
recompute_btn(app, ui);
|
||||
});
|
||||
|
||||
let feed = GLOBALS.feed.get_person_feed();
|
||||
render_a_feed(app, ctx, frame, ui, feed, false, pubkeyhex.as_str());
|
||||
render_a_feed(app, ctx, frame, ui, feed, false, &pubkey.as_hex_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ use eframe::{
|
||||
epaint::Vec2,
|
||||
};
|
||||
use egui::{RichText, Ui};
|
||||
use nostr_types::{ContentSegment, Id, IdHex, NostrBech32, PublicKeyHex, Span, Tag, Url};
|
||||
use nostr_types::{ContentSegment, Id, IdHex, NostrBech32, PublicKey, Span, Tag, Url};
|
||||
use std::{
|
||||
cell::{Ref, RefCell},
|
||||
rc::Rc,
|
||||
@ -95,10 +95,10 @@ pub(super) fn render_content(
|
||||
}
|
||||
}
|
||||
NostrBech32::Profile(prof) => {
|
||||
render_profile_link(app, ui, &prof.pubkey.into());
|
||||
render_profile_link(app, ui, &prof.pubkey);
|
||||
}
|
||||
NostrBech32::Pubkey(pk) => {
|
||||
render_profile_link(app, ui, &(*pk).into());
|
||||
NostrBech32::Pubkey(pubkey) => {
|
||||
render_profile_link(app, ui, pubkey);
|
||||
}
|
||||
NostrBech32::Relay(url) => {
|
||||
ui.label(RichText::new(&url.0).underline());
|
||||
@ -109,7 +109,10 @@ pub(super) fn render_content(
|
||||
if let Some(tag) = note.event.tags.get(*num) {
|
||||
match tag {
|
||||
Tag::Pubkey { pubkey, .. } => {
|
||||
render_profile_link(app, ui, pubkey);
|
||||
if let Ok(pubkey) = PublicKey::try_from_hex_string(pubkey.as_str())
|
||||
{
|
||||
render_profile_link(app, ui, &pubkey);
|
||||
}
|
||||
}
|
||||
Tag::Event { id, .. } => {
|
||||
let mut render_link = true;
|
||||
@ -192,8 +195,8 @@ pub(super) fn render_plain(ui: &mut Ui, note: &Ref<NoteData>, textspan: &Span, a
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn render_profile_link(app: &mut GossipUi, ui: &mut Ui, pubkey: &PublicKeyHex) {
|
||||
let nam = GossipUi::display_name_from_pubkeyhex_lookup(pubkey);
|
||||
pub(super) fn render_profile_link(app: &mut GossipUi, ui: &mut Ui, pubkey: &PublicKey) {
|
||||
let nam = GossipUi::display_name_from_pubkey_lookup(pubkey);
|
||||
let nam = format!("@{}", nam);
|
||||
if ui.link(&nam).clicked() {
|
||||
app.set_page(Page::Person(pubkey.to_owned()));
|
||||
|
@ -273,7 +273,7 @@ fn render_note_inner(
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
app.set_page(Page::Person(note.author.pubkey.clone()));
|
||||
app.set_page(Page::Person(note.author.pubkey));
|
||||
};
|
||||
|
||||
ui.add_space(avatar_margin_left);
|
||||
@ -293,7 +293,7 @@ fn render_note_inner(
|
||||
app.set_page(Page::Feed(FeedKind::Thread {
|
||||
id: irt,
|
||||
referenced_by: note.event.id,
|
||||
author: Some(note.event.pubkey.into()),
|
||||
author: Some(note.event.pubkey),
|
||||
}));
|
||||
};
|
||||
ui.reset_style();
|
||||
@ -343,7 +343,7 @@ fn render_note_inner(
|
||||
app.set_page(Page::Feed(FeedKind::Thread {
|
||||
id: note.event.id,
|
||||
referenced_by: note.event.id,
|
||||
author: Some(note.event.pubkey.into()),
|
||||
author: Some(note.event.pubkey),
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -431,7 +431,7 @@ fn render_note_inner(
|
||||
app.set_page(Page::Feed(FeedKind::Thread {
|
||||
id: note.event.id,
|
||||
referenced_by: note.event.id,
|
||||
author: Some(note.event.pubkey.into()),
|
||||
author: Some(note.event.pubkey),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{globals::GLOBALS, people::Person};
|
||||
use nostr_types::{
|
||||
ContentSegment, Event, EventDelegation, EventKind, Id, MilliSatoshi, NostrBech32, PublicKeyHex,
|
||||
ContentSegment, Event, EventDelegation, EventKind, Id, MilliSatoshi, NostrBech32, PublicKey,
|
||||
ShatteredContent, Tag,
|
||||
};
|
||||
|
||||
@ -154,10 +154,10 @@ impl NoteData {
|
||||
};
|
||||
|
||||
// If delegated, use the delegated person
|
||||
let author_pubkey: PublicKeyHex = if let EventDelegation::DelegatedBy(pubkey) = delegation {
|
||||
pubkey.into()
|
||||
let author_pubkey: PublicKey = if let EventDelegation::DelegatedBy(pubkey) = delegation {
|
||||
pubkey
|
||||
} else {
|
||||
event.pubkey.into()
|
||||
event.pubkey
|
||||
};
|
||||
|
||||
let author = match GLOBALS.people.get(&author_pubkey) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::notedata::NoteData;
|
||||
use crate::globals::GLOBALS;
|
||||
use nostr_types::{Id, PublicKeyHex};
|
||||
use nostr_types::{Id, PublicKey};
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
/// a 'note' is a processed event
|
||||
@ -29,7 +29,7 @@ impl Notes {
|
||||
}
|
||||
|
||||
/// Drop all NoteData for a given person
|
||||
pub(in crate::ui) fn cache_invalidate_person(&mut self, pubkey: &PublicKeyHex) {
|
||||
pub(in crate::ui) fn cache_invalidate_person(&mut self, pubkey: &PublicKey) {
|
||||
self.notes
|
||||
.retain(|_, note| note.borrow().author.pubkey != *pubkey);
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ fn real_posting_area(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
||||
NostrBech32::Profile(prof) => &prof.pubkey,
|
||||
_ => continue,
|
||||
};
|
||||
let rendered = if let Some(person) = GLOBALS.people.get(&pk.as_hex_string().into()) {
|
||||
let rendered = if let Some(person) = GLOBALS.people.get(pk) {
|
||||
match person.name() {
|
||||
Some(name) => name.to_owned(),
|
||||
None => format!("{}", bech32),
|
||||
|
@ -42,7 +42,7 @@ use egui::{
|
||||
#[cfg(feature = "video-ffmpeg")]
|
||||
use egui_video::{AudioDevice, Player};
|
||||
use egui_winit::egui::Response;
|
||||
use nostr_types::{Id, IdHex, Metadata, MilliSatoshi, PublicKey, PublicKeyHex, UncheckedUrl, Url};
|
||||
use nostr_types::{Id, IdHex, Metadata, MilliSatoshi, PublicKey, UncheckedUrl, Url};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
#[cfg(feature = "video-ffmpeg")]
|
||||
use std::rc::Rc;
|
||||
@ -98,7 +98,7 @@ enum Page {
|
||||
PeopleList,
|
||||
PeopleFollow,
|
||||
PeopleMuted,
|
||||
Person(PublicKeyHex),
|
||||
Person(PublicKey),
|
||||
YourKeys,
|
||||
YourMetadata,
|
||||
YourDelegation,
|
||||
@ -200,7 +200,7 @@ struct GossipUi {
|
||||
icon: TextureHandle,
|
||||
placeholder_avatar: TextureHandle,
|
||||
settings: Settings,
|
||||
avatars: HashMap<PublicKeyHex, TextureHandle>,
|
||||
avatars: HashMap<PublicKey, TextureHandle>,
|
||||
images: HashMap<Url, TextureHandle>,
|
||||
/// used when settings.show_media=false to explicitly show
|
||||
media_show_list: HashSet<Url>,
|
||||
@ -500,7 +500,7 @@ impl GossipUi {
|
||||
}) => {
|
||||
GLOBALS
|
||||
.feed
|
||||
.set_feed_to_thread(*id, *referenced_by, vec![], author.clone());
|
||||
.set_feed_to_thread(*id, *referenced_by, vec![], *author);
|
||||
}
|
||||
Page::Feed(FeedKind::Person(pubkey)) => {
|
||||
GLOBALS.feed.set_feed_to_person(pubkey.to_owned());
|
||||
@ -626,15 +626,14 @@ impl eframe::App for GossipUi {
|
||||
)));
|
||||
}
|
||||
if let Some(pubkey) = GLOBALS.signer.public_key() {
|
||||
let pubkeyhex: PublicKeyHex = pubkey.into();
|
||||
if self.add_selected_label(
|
||||
ui,
|
||||
matches!(&self.page, Page::Feed(FeedKind::Person(key)) if key.as_str() == pubkeyhex.as_str()),
|
||||
matches!(&self.page, Page::Feed(FeedKind::Person(key)) if *key == pubkey),
|
||||
"My Notes",
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
self.set_page(Page::Feed(FeedKind::Person(pubkeyhex)));
|
||||
self.set_page(Page::Feed(FeedKind::Person(pubkey)));
|
||||
}
|
||||
}
|
||||
if self.add_selected_label(
|
||||
@ -868,28 +867,15 @@ impl GossipUi {
|
||||
/// A short rendering of a `PublicKey`
|
||||
pub fn pubkey_short(pk: &PublicKey) -> String {
|
||||
let npub = pk.as_bech32_string();
|
||||
format!("{}…", &npub.get(0..20).unwrap_or("????????????????????"))
|
||||
}
|
||||
|
||||
/// A short rendering of a `PublicKeyHex`
|
||||
pub fn pubkeyhex_short(pubkeyhex: &PublicKeyHex) -> String {
|
||||
format!(
|
||||
"{}_{}...{}_{}",
|
||||
&pubkeyhex.as_str()[0..4],
|
||||
&pubkeyhex.as_str()[4..8],
|
||||
&pubkeyhex.as_str()[56..60],
|
||||
&pubkeyhex.as_str()[60..64],
|
||||
&npub.get(0..4).unwrap_or("????"),
|
||||
&npub.get(4..8).unwrap_or("????"),
|
||||
&npub.get(56..60).unwrap_or("????"),
|
||||
&npub.get(60..64).unwrap_or("????")
|
||||
)
|
||||
}
|
||||
|
||||
/// A short rendering of a `PublicKeyHex`, with attempt to convert to bech32
|
||||
pub fn pubkeyhex_convert_short(pubkeyhex: &PublicKeyHex) -> String {
|
||||
match PublicKey::try_from_hex_string(pubkeyhex) {
|
||||
Ok(pk) => Self::pubkey_short(&pk),
|
||||
Err(_) => GossipUi::pubkeyhex_short(pubkeyhex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hex_id_short(idhex: &IdHex) -> String {
|
||||
idhex.as_str()[0..8].to_string()
|
||||
}
|
||||
@ -898,22 +884,21 @@ impl GossipUi {
|
||||
pub fn display_name_from_dbperson(dbperson: &Person) -> String {
|
||||
match dbperson.display_name() {
|
||||
Some(name) => name.to_owned(),
|
||||
None => Self::pubkeyhex_convert_short(&dbperson.pubkey),
|
||||
None => Self::pubkey_short(&dbperson.pubkey),
|
||||
}
|
||||
}
|
||||
|
||||
/// A display name for a `PublicKeyHex`, via trying to lookup the person
|
||||
pub fn display_name_from_pubkeyhex_lookup(pkh: &PublicKeyHex) -> String {
|
||||
match GLOBALS.people.get(pkh) {
|
||||
pub fn display_name_from_pubkey_lookup(pubkey: &PublicKey) -> String {
|
||||
match GLOBALS.people.get(pubkey) {
|
||||
Some(dbperson) => Self::display_name_from_dbperson(&dbperson),
|
||||
None => Self::pubkeyhex_convert_short(pkh),
|
||||
None => Self::pubkey_short(pubkey),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_person_name_line(app: &mut GossipUi, ui: &mut Ui, person: &Person) {
|
||||
// Let the 'People' manager know that we are interested in displaying this person.
|
||||
// It will take all actions necessary to make the data eventually available.
|
||||
GLOBALS.people.person_of_interest(person.pubkey.clone());
|
||||
GLOBALS.people.person_of_interest(person.pubkey);
|
||||
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
let name = GossipUi::display_name_from_dbperson(person);
|
||||
@ -921,7 +906,7 @@ impl GossipUi {
|
||||
ui.menu_button(&name, |ui| {
|
||||
let mute_label = if person.muted == 1 { "Unmute" } else { "Mute" };
|
||||
if ui.button(mute_label).clicked() {
|
||||
GLOBALS.people.mute(&person.pubkey, person.muted == 0);
|
||||
GLOBALS.people.mute(person.pubkey, person.muted == 0);
|
||||
app.notes.cache_invalidate_person(&person.pubkey);
|
||||
}
|
||||
if person.followed == 0 && ui.button("Follow").clicked() {
|
||||
@ -932,10 +917,10 @@ impl GossipUi {
|
||||
if ui.button("Update Metadata").clicked() {
|
||||
let _ = GLOBALS
|
||||
.to_overlord
|
||||
.send(ToOverlordMessage::UpdateMetadata(person.pubkey.clone()));
|
||||
.send(ToOverlordMessage::UpdateMetadata(person.pubkey));
|
||||
}
|
||||
if ui.button("View Their Posts").clicked() {
|
||||
app.set_page(Page::Feed(FeedKind::Person(person.pubkey.clone())));
|
||||
app.set_page(Page::Feed(FeedKind::Person(person.pubkey)));
|
||||
}
|
||||
});
|
||||
|
||||
@ -966,28 +951,24 @@ impl GossipUi {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn try_get_avatar(
|
||||
&mut self,
|
||||
ctx: &Context,
|
||||
pubkeyhex: &PublicKeyHex,
|
||||
) -> Option<TextureHandle> {
|
||||
pub fn try_get_avatar(&mut self, ctx: &Context, pubkey: &PublicKey) -> Option<TextureHandle> {
|
||||
// Do not keep retrying if failed
|
||||
if GLOBALS.failed_avatars.blocking_read().contains(pubkeyhex) {
|
||||
if GLOBALS.failed_avatars.blocking_read().contains(pubkey) {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(th) = self.avatars.get(pubkeyhex) {
|
||||
if let Some(th) = self.avatars.get(pubkey) {
|
||||
return Some(th.to_owned());
|
||||
}
|
||||
|
||||
if let Some(color_image) = GLOBALS.people.get_avatar(pubkeyhex) {
|
||||
if let Some(color_image) = GLOBALS.people.get_avatar(pubkey) {
|
||||
let texture_handle = ctx.load_texture(
|
||||
pubkeyhex.to_string(),
|
||||
pubkey.as_hex_string(),
|
||||
color_image,
|
||||
TextureOptions::default(),
|
||||
);
|
||||
self.avatars
|
||||
.insert(pubkeyhex.to_owned(), texture_handle.clone());
|
||||
.insert(pubkey.to_owned(), texture_handle.clone());
|
||||
Some(texture_handle)
|
||||
} else {
|
||||
None
|
||||
|
@ -175,13 +175,11 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
.add(Image::new(&avatar, Vec2 { x: size, y: size }).sense(Sense::click()))
|
||||
.clicked()
|
||||
{
|
||||
app.set_page(Page::Person(person.pubkey.clone()));
|
||||
app.set_page(Page::Person(person.pubkey));
|
||||
};
|
||||
|
||||
ui.vertical(|ui| {
|
||||
ui.label(
|
||||
RichText::new(GossipUi::pubkeyhex_convert_short(&person.pubkey)).weak(),
|
||||
);
|
||||
ui.label(RichText::new(GossipUi::pubkey_short(&person.pubkey)).weak());
|
||||
GossipUi::render_person_name_line(app, ui, person);
|
||||
});
|
||||
});
|
||||
|
@ -44,17 +44,15 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
.add(Image::new(&avatar, Vec2 { x: size, y: size }).sense(Sense::click()))
|
||||
.clicked()
|
||||
{
|
||||
app.set_page(Page::Person(person.pubkey.clone()));
|
||||
app.set_page(Page::Person(person.pubkey));
|
||||
};
|
||||
|
||||
ui.vertical(|ui| {
|
||||
ui.label(
|
||||
RichText::new(GossipUi::pubkeyhex_convert_short(&person.pubkey)).weak(),
|
||||
);
|
||||
ui.label(RichText::new(GossipUi::pubkey_short(&person.pubkey)).weak());
|
||||
GossipUi::render_person_name_line(app, ui, person);
|
||||
|
||||
if ui.button("UNMUTE").clicked() {
|
||||
GLOBALS.people.mute(&person.pubkey, false);
|
||||
GLOBALS.people.mute(person.pubkey, false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -6,17 +6,17 @@ use crate::ui::widgets::CopyButton;
|
||||
use crate::AVATAR_SIZE_F32;
|
||||
use eframe::egui;
|
||||
use egui::{Context, Frame, RichText, ScrollArea, Ui, Vec2};
|
||||
use nostr_types::{PublicKey, PublicKeyHex};
|
||||
use nostr_types::PublicKey;
|
||||
use serde_json::Value;
|
||||
|
||||
pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
|
||||
let (pubkeyhex, person) = match &app.page {
|
||||
Page::Person(pubkeyhex) => {
|
||||
let person = match GLOBALS.people.get(pubkeyhex) {
|
||||
let (pubkey, person) = match &app.page {
|
||||
Page::Person(pubkey) => {
|
||||
let person = match GLOBALS.people.get(pubkey) {
|
||||
Some(p) => p,
|
||||
None => Person::new(pubkeyhex.to_owned()),
|
||||
None => Person::new(pubkey.to_owned()),
|
||||
};
|
||||
(pubkeyhex.to_owned(), person)
|
||||
(pubkey.to_owned(), person)
|
||||
}
|
||||
_ => {
|
||||
ui.label("ERROR");
|
||||
@ -33,22 +33,16 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
.max_width(f32::INFINITY)
|
||||
.auto_shrink([false, false])
|
||||
.show(ui, |ui| {
|
||||
content(app, ctx, ui, pubkeyhex, person);
|
||||
content(app, ctx, ui, pubkey, person);
|
||||
});
|
||||
}
|
||||
|
||||
fn content(
|
||||
app: &mut GossipUi,
|
||||
ctx: &Context,
|
||||
ui: &mut Ui,
|
||||
pubkeyhex: PublicKeyHex,
|
||||
person: Person,
|
||||
) {
|
||||
fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, person: Person) {
|
||||
ui.add_space(24.0);
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
// Avatar first
|
||||
let avatar = if let Some(avatar) = app.try_get_avatar(ctx, &pubkeyhex) {
|
||||
let avatar = if let Some(avatar) = app.try_get_avatar(ctx, &pubkey) {
|
||||
avatar
|
||||
} else {
|
||||
app.placeholder_avatar.clone()
|
||||
@ -63,32 +57,29 @@ fn content(
|
||||
ui.vertical(|ui| {
|
||||
let name = GossipUi::display_name_from_dbperson(&person);
|
||||
ui.heading(name);
|
||||
ui.label(RichText::new(GossipUi::pubkeyhex_convert_short(&pubkeyhex)).weak());
|
||||
ui.label(RichText::new(GossipUi::pubkey_short(&pubkey)).weak());
|
||||
GossipUi::render_person_name_line(app, ui, &person);
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(12.0);
|
||||
|
||||
let mut npub = "Unable to get npub".to_owned();
|
||||
if let Ok(pk) = PublicKey::try_from_hex_string(&pubkeyhex) {
|
||||
npub = pk.as_bech32_string();
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.label(RichText::new("Public Key: ").strong());
|
||||
ui.label(&npub);
|
||||
if ui
|
||||
.add(CopyButton {})
|
||||
.on_hover_text("Copy Public Key")
|
||||
.clicked()
|
||||
{
|
||||
ui.output_mut(|o| o.copied_text = npub.to_owned());
|
||||
}
|
||||
if ui.button("⚃").on_hover_text("Show as QR code").clicked() {
|
||||
app.qr_codes.remove("person_qr");
|
||||
app.person_qr = Some("npub");
|
||||
}
|
||||
});
|
||||
}
|
||||
let npub = pubkey.as_bech32_string();
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.label(RichText::new("Public Key: ").strong());
|
||||
ui.label(&npub);
|
||||
if ui
|
||||
.add(CopyButton {})
|
||||
.on_hover_text("Copy Public Key")
|
||||
.clicked()
|
||||
{
|
||||
ui.output_mut(|o| o.copied_text = npub.to_owned());
|
||||
}
|
||||
if ui.button("⚃").on_hover_text("Show as QR code").clicked() {
|
||||
app.qr_codes.remove("person_qr");
|
||||
app.person_qr = Some("npub");
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(name) = person.name() {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
@ -198,8 +189,9 @@ fn content(
|
||||
}
|
||||
|
||||
let mut need_to_set_active_person = true;
|
||||
|
||||
if let Some(ap) = GLOBALS.people.get_active_person() {
|
||||
if ap == pubkeyhex {
|
||||
if ap == pubkey {
|
||||
need_to_set_active_person = false;
|
||||
app.setting_active_person = false;
|
||||
|
||||
@ -217,6 +209,6 @@ fn content(
|
||||
app.setting_active_person = true;
|
||||
let _ = GLOBALS
|
||||
.to_overlord
|
||||
.send(ToOverlordMessage::SetActivePerson(pubkeyhex.clone()));
|
||||
.send(ToOverlordMessage::SetActivePerson(pubkey));
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
||||
for elem in GLOBALS.relay_picker.pubkey_counts_iter() {
|
||||
let pk = elem.key();
|
||||
let count = elem.value();
|
||||
let name = GossipUi::display_name_from_pubkeyhex_lookup(pk);
|
||||
let name = GossipUi::display_name_from_pubkey_lookup(pk);
|
||||
ui.label(format!("{}: coverage short by {} relay(s)", name, count));
|
||||
}
|
||||
} else {
|
||||
|
@ -77,14 +77,11 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut Frame, ui:
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
app.set_page(Page::Person(person.pubkey.clone()));
|
||||
app.set_page(Page::Person(person.pubkey));
|
||||
};
|
||||
|
||||
ui.vertical(|ui| {
|
||||
ui.label(
|
||||
RichText::new(GossipUi::pubkeyhex_convert_short(&person.pubkey))
|
||||
.weak(),
|
||||
);
|
||||
ui.label(RichText::new(GossipUi::pubkey_short(&person.pubkey)).weak());
|
||||
GossipUi::render_person_name_line(app, ui, person);
|
||||
});
|
||||
});
|
||||
@ -104,8 +101,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut Frame, ui:
|
||||
.weak(),
|
||||
);
|
||||
|
||||
let pubkeyhex = event.pubkey.into();
|
||||
if let Some(person) = GLOBALS.people.get(&pubkeyhex) {
|
||||
if let Some(person) = GLOBALS.people.get(&event.pubkey) {
|
||||
GossipUi::render_person_name_line(app, ui, &person);
|
||||
} else {
|
||||
ui.label(event.pubkey.as_bech32_string());
|
||||
@ -122,7 +118,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut Frame, ui:
|
||||
app.set_page(Page::Feed(FeedKind::Thread {
|
||||
id: event.id,
|
||||
referenced_by: event.id,
|
||||
author: Some(event.pubkey.into()),
|
||||
author: Some(event.pubkey),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,11 @@ pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Fr
|
||||
}
|
||||
};
|
||||
|
||||
let you = match GLOBALS.people.get(&public_key.into()) {
|
||||
let you = match GLOBALS.people.get(&public_key) {
|
||||
Some(dbp) => dbp,
|
||||
None => {
|
||||
ui.label("I cannot find you.");
|
||||
GLOBALS.people.create_if_missing_sync(public_key.into());
|
||||
GLOBALS.people.create_if_missing_sync(public_key);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user