follow/unfollow on person page (no immediate feedback because of ui caching person_view_* data)

This commit is contained in:
Mike Dilger 2023-01-01 05:15:21 +13:00
parent 12b0014485
commit 533dba7191
3 changed files with 55 additions and 9 deletions

View File

@ -601,7 +601,7 @@ impl Overlord {
.people .people
.write() .write()
.await .await
.follow(&(*pubkey).into()) .async_follow(&(*pubkey).into(), true)
.await?; .await?;
info!("Followed {}", &dns_id); info!("Followed {}", &dns_id);
@ -636,7 +636,12 @@ impl Overlord {
async fn follow_bech32(bech32: String, relay: String) -> Result<(), Error> { async fn follow_bech32(bech32: String, relay: String) -> Result<(), Error> {
let pk = PublicKey::try_from_bech32_string(&bech32)?; let pk = PublicKey::try_from_bech32_string(&bech32)?;
let pkhex: PublicKeyHex = pk.into(); let pkhex: PublicKeyHex = pk.into();
GLOBALS.people.write().await.follow(&pkhex).await?; GLOBALS
.people
.write()
.await
.async_follow(&pkhex, true)
.await?;
debug!("Followed {}", &pkhex); debug!("Followed {}", &pkhex);
@ -664,7 +669,12 @@ impl Overlord {
async fn follow_hexkey(hexkey: String, relay: String) -> Result<(), Error> { async fn follow_hexkey(hexkey: String, relay: String) -> Result<(), Error> {
let pk = PublicKey::try_from_hex_string(&hexkey)?; let pk = PublicKey::try_from_hex_string(&hexkey)?;
let pkhex: PublicKeyHex = pk.into(); let pkhex: PublicKeyHex = pk.into();
GLOBALS.people.write().await.follow(&pkhex).await?; GLOBALS
.people
.write()
.await
.async_follow(&pkhex, true)
.await?;
debug!("Followed {}", &pkhex); debug!("Followed {}", &pkhex);

View File

@ -9,6 +9,7 @@ use tokio::task;
pub struct People { pub struct People {
people: HashMap<PublicKeyHex, DbPerson>, people: HashMap<PublicKeyHex, DbPerson>,
deferred_load: HashSet<PublicKeyHex>, deferred_load: HashSet<PublicKeyHex>,
deferred_follow: HashMap<PublicKeyHex, bool>,
} }
impl People { impl People {
@ -16,6 +17,7 @@ impl People {
People { People {
people: HashMap::new(), people: HashMap::new(),
deferred_load: HashSet::new(), deferred_load: HashSet::new(),
deferred_follow: HashMap::new(),
} }
} }
@ -184,6 +186,7 @@ impl People {
} }
pub async fn sync(&mut self) -> Result<(), Error> { pub async fn sync(&mut self) -> Result<(), Error> {
// handle deferred load
for pubkeyhex in self.deferred_load.iter() { for pubkeyhex in self.deferred_load.iter() {
if !self.people.contains_key(pubkeyhex) { if !self.people.contains_key(pubkeyhex) {
if let Some(person) = Self::fetch_one(pubkeyhex).await? { if let Some(person) = Self::fetch_one(pubkeyhex).await? {
@ -192,6 +195,14 @@ impl People {
} }
} }
self.deferred_load.clear(); 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(()) Ok(())
} }
@ -210,23 +221,37 @@ impl People {
Ok(()) 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 // Follow in database
let sql = "INSERT INTO PERSON (pubkey, followed) values (?, 1) \ let sql = "INSERT INTO PERSON (pubkey, followed) values (?, ?) \
ON CONFLICT(pubkey) DO UPDATE SET followed=1"; ON CONFLICT(pubkey) DO UPDATE SET followed=?";
let pubkeyhex2 = pubkeyhex.to_owned(); let pubkeyhex2 = pubkeyhex.to_owned();
task::spawn_blocking(move || { task::spawn_blocking(move || {
let maybe_db = GLOBALS.db.blocking_lock(); let maybe_db = GLOBALS.db.blocking_lock();
let db = maybe_db.as_ref().unwrap(); let db = maybe_db.as_ref().unwrap();
let mut stmt = db.prepare(sql)?; let mut stmt = db.prepare(sql)?;
stmt.execute((&pubkeyhex2.0,))?; stmt.execute((&pubkeyhex2.0, &f, &f))?;
Ok::<(), Error>(()) Ok::<(), Error>(())
}) })
.await??; .await??;
// Make sure memory matches // Make sure memory matches
if let Some(dbperson) = self.people.get_mut(pubkeyhex) { if let Some(dbperson) = self.people.get_mut(pubkeyhex) {
dbperson.followed = 1; dbperson.followed = f;
} else { } else {
// load // load
if let Some(person) = Self::fetch_one(pubkeyhex).await? { if let Some(person) = Self::fetch_one(pubkeyhex).await? {

View File

@ -157,7 +157,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
{ {
ui.label("ERROR"); ui.label("ERROR");
} else { } 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 person = app.person_view_person.as_ref().unwrap();
let name = app.person_view_name.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); 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);
}
}
} }
} }
} }