From 533dba71917954d2d6df69c744d9cb65af563e1d Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Sun, 1 Jan 2023 05:15:21 +1300 Subject: [PATCH] follow/unfollow on person page (no immediate feedback because of ui caching person_view_* data) --- src/overlord/mod.rs | 16 +++++++++++++--- src/people/mod.rs | 35 ++++++++++++++++++++++++++++++----- src/ui/people.rs | 13 ++++++++++++- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/overlord/mod.rs b/src/overlord/mod.rs index eb0da1c2..a04c3a9e 100644 --- a/src/overlord/mod.rs +++ b/src/overlord/mod.rs @@ -601,7 +601,7 @@ impl Overlord { .people .write() .await - .follow(&(*pubkey).into()) + .async_follow(&(*pubkey).into(), true) .await?; info!("Followed {}", &dns_id); @@ -636,7 +636,12 @@ impl Overlord { async fn follow_bech32(bech32: String, relay: String) -> Result<(), Error> { let pk = PublicKey::try_from_bech32_string(&bech32)?; let pkhex: PublicKeyHex = pk.into(); - GLOBALS.people.write().await.follow(&pkhex).await?; + GLOBALS + .people + .write() + .await + .async_follow(&pkhex, true) + .await?; debug!("Followed {}", &pkhex); @@ -664,7 +669,12 @@ impl Overlord { async fn follow_hexkey(hexkey: String, relay: String) -> Result<(), Error> { let pk = PublicKey::try_from_hex_string(&hexkey)?; let pkhex: PublicKeyHex = pk.into(); - GLOBALS.people.write().await.follow(&pkhex).await?; + GLOBALS + .people + .write() + .await + .async_follow(&pkhex, true) + .await?; debug!("Followed {}", &pkhex); diff --git a/src/people/mod.rs b/src/people/mod.rs index 3b2c278f..e9e3d798 100644 --- a/src/people/mod.rs +++ b/src/people/mod.rs @@ -9,6 +9,7 @@ use tokio::task; pub struct People { people: HashMap, deferred_load: HashSet, + deferred_follow: HashMap, } impl People { @@ -16,6 +17,7 @@ impl People { People { people: HashMap::new(), deferred_load: HashSet::new(), + deferred_follow: HashMap::new(), } } @@ -184,6 +186,7 @@ impl People { } pub async fn sync(&mut self) -> Result<(), Error> { + // handle deferred load for pubkeyhex in self.deferred_load.iter() { if !self.people.contains_key(pubkeyhex) { if let Some(person) = Self::fetch_one(pubkeyhex).await? { @@ -192,6 +195,14 @@ impl People { } } self.deferred_load.clear(); + + // handle deferred follow + let df = self.deferred_follow.clone(); + for (pubkeyhex, follow) in df { + self.async_follow(&pubkeyhex, follow).await?; + } + self.deferred_follow.clear(); + Ok(()) } @@ -210,23 +221,37 @@ impl People { Ok(()) } - pub async fn follow(&mut self, pubkeyhex: &PublicKeyHex) -> Result<(), Error> { + pub fn follow(&mut self, pubkeyhex: &PublicKeyHex, follow: bool) { + self.deferred_follow + .entry(pubkeyhex.clone()) + .and_modify(|d| *d = follow) + .or_insert_with(|| follow); + let _ = GLOBALS.to_syncer.send("sync_people".to_owned()); + } + + pub async fn async_follow( + &mut self, + pubkeyhex: &PublicKeyHex, + follow: bool, + ) -> Result<(), Error> { + let f: u8 = u8::from(follow); + // Follow in database - let sql = "INSERT INTO PERSON (pubkey, followed) values (?, 1) \ - ON CONFLICT(pubkey) DO UPDATE SET followed=1"; + let sql = "INSERT INTO PERSON (pubkey, followed) values (?, ?) \ + ON CONFLICT(pubkey) DO UPDATE SET followed=?"; let pubkeyhex2 = pubkeyhex.to_owned(); task::spawn_blocking(move || { let maybe_db = GLOBALS.db.blocking_lock(); let db = maybe_db.as_ref().unwrap(); let mut stmt = db.prepare(sql)?; - stmt.execute((&pubkeyhex2.0,))?; + stmt.execute((&pubkeyhex2.0, &f, &f))?; Ok::<(), Error>(()) }) .await??; // Make sure memory matches if let Some(dbperson) = self.people.get_mut(pubkeyhex) { - dbperson.followed = 1; + dbperson.followed = f; } else { // load if let Some(person) = Self::fetch_one(pubkeyhex).await? { diff --git a/src/ui/people.rs b/src/ui/people.rs index 0f365c73..61023368 100644 --- a/src/ui/people.rs +++ b/src/ui/people.rs @@ -157,7 +157,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra { ui.label("ERROR"); } else { - //let pubkey = app.person_view_pubkey.as_ref().unwrap(); + let pubkeyhex = app.person_view_pubkey.as_ref().unwrap(); let person = app.person_view_person.as_ref().unwrap(); let name = app.person_view_name.as_ref().unwrap(); @@ -182,6 +182,17 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra } ui.add_space(12.0); + + #[allow(clippy::collapsible_else_if)] + if person.followed == 0 { + if ui.button("FOLLOW").clicked() { + GLOBALS.people.blocking_write().follow(pubkeyhex, true); + } + } else { + if ui.button("UNFOLLOW").clicked() { + GLOBALS.people.blocking_write().follow(pubkeyhex, false); + } + } } } }