diff --git a/mutiny-core/src/labels.rs b/mutiny-core/src/labels.rs index cb02e2224..54b81431f 100644 --- a/mutiny-core/src/labels.rs +++ b/mutiny-core/src/labels.rs @@ -7,6 +7,7 @@ use lnurl::lightning_address::LightningAddress; use lnurl::lnurl::LnUrl; use nostr::{key::XOnlyPublicKey, Metadata}; use serde::{Deserialize, Serialize}; +use serde_json::Value; use std::collections::HashMap; use std::str::FromStr; use uuid::Uuid; @@ -37,8 +38,6 @@ pub struct Contact { pub lnurl: Option, #[serde(skip_serializing_if = "Option::is_none")] pub image_url: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub archived: Option, pub last_used: u64, } @@ -140,8 +139,8 @@ pub trait LabelStorage { ) -> Result; /// Create a new contact and return the identifying label fn create_new_contact(&self, contact: Contact) -> Result; - /// Marks a contact as archived - fn archive_contact(&self, id: impl AsRef) -> Result<(), MutinyError>; + /// Deletes a contact and all labels associated with it + fn delete_contact(&self, id: impl AsRef) -> Result<(), MutinyError>; /// Edits an existing contact and replaces the existing contact fn edit_contact(&self, id: impl AsRef, contact: Contact) -> Result<(), MutinyError>; /// Gets all the existing tags (labels and contacts) @@ -287,10 +286,6 @@ impl LabelStorage for S { let mut contacts = HashMap::with_capacity(all.len()); for (key, contact) in all { let label = key.replace(CONTACT_PREFIX, ""); - // skip archived contacts - if contact.archived.unwrap_or(false) { - continue; - } contacts.insert(label, contact); } @@ -375,12 +370,32 @@ impl LabelStorage for S { Ok(id) } - fn archive_contact(&self, id: impl AsRef) -> Result<(), MutinyError> { - let contact = self.get_contact(&id)?; - if let Some(mut contact) = contact { - contact.archived = Some(true); - self.set_data(get_contact_key(&id), contact, None)?; + fn delete_contact(&self, id: impl AsRef) -> Result<(), MutinyError> { + // first remove from all labels + let mut inv_labels = self.get_invoice_labels()?; + for value in inv_labels.values_mut() { + value.retain(|s| *s != id.as_ref()); } + let mut addr_labels = self.get_address_labels()?; + for value in addr_labels.values_mut() { + value.retain(|s| *s != id.as_ref()); + } + let to_set: Vec<(String, Value)> = vec![ + ( + ADDRESS_LABELS_MAP_KEY.to_string(), + serde_json::to_value(addr_labels)?, + ), + ( + INVOICE_LABELS_MAP_KEY.to_string(), + serde_json::to_value(inv_labels)?, + ), + ]; + self.set(to_set)?; + + // then delete actual label + let contact_key = get_contact_key(&id); + let label_item_key = get_label_item_key(&id); + self.delete(&[contact_key, label_item_key])?; Ok(()) } @@ -466,8 +481,8 @@ impl LabelStorage for NodeManager { self.storage.create_new_contact(contact) } - fn archive_contact(&self, id: impl AsRef) -> Result<(), MutinyError> { - self.storage.archive_contact(id) + fn delete_contact(&self, id: impl AsRef) -> Result<(), MutinyError> { + self.storage.delete_contact(id) } fn edit_contact(&self, id: impl AsRef, contact: Contact) -> Result<(), MutinyError> { @@ -566,7 +581,6 @@ mod tests { npub: None, ln_address: None, lnurl: None, - archived: Some(false), image_url: None, last_used: 0, }, @@ -578,7 +592,6 @@ mod tests { npub: None, ln_address: None, lnurl: None, - archived: Some(false), image_url: None, last_used: 0, }, @@ -590,7 +603,6 @@ mod tests { npub: None, ln_address: None, lnurl: None, - archived: Some(false), image_url: None, last_used: 0, }, @@ -744,7 +756,6 @@ mod tests { npub: None, ln_address: None, lnurl: None, - archived: Some(false), image_url: None, last_used: 0, }; @@ -766,7 +777,6 @@ mod tests { npub: None, ln_address: None, lnurl: None, - archived: Some(false), image_url: None, last_used: 0, }; @@ -781,8 +791,8 @@ mod tests { } #[test] - fn test_archive_contact() { - let test_name = "test_archive_contact"; + fn test_delete_contact() { + let test_name = "test_delete_contact"; log!("{}", test_name); let storage = MemoryStorage::default(); @@ -792,21 +802,41 @@ mod tests { npub: None, ln_address: None, lnurl: None, - archived: Some(false), image_url: None, last_used: 0, }; let id = storage.create_new_contact(contact).unwrap(); + let contact = storage.get_contact(&id).unwrap(); + assert!(contact.is_some()); - let mut contact = storage.get_contact(&id).unwrap().unwrap(); - contact.archived = Some(true); - storage.archive_contact(&id).unwrap(); + // set labels for invoice and address + let invoice = Bolt11Invoice::from_str(INVOICE).unwrap(); + storage + .set_invoice_labels(invoice.clone(), vec![id.clone()]) + .unwrap(); + let address = Address::from_str(ADDRESS).unwrap(); + storage + .set_address_labels(address, vec![id.clone()]) + .unwrap(); - let result = storage.get_contact(&id).unwrap(); - assert_eq!(result.unwrap(), contact); + // delete contact + storage.delete_contact(&id).unwrap(); + // make sure it is deleted + let result = storage.get_contact(&id).unwrap(); + assert!(result.is_none()); let contacts = storage.get_contacts().unwrap(); assert!(contacts.get(&id).is_none()); + + // check invoice labels are empty + let inv_labels = storage.get_invoice_labels().unwrap(); + let labels = inv_labels.get(&invoice).cloned().unwrap_or_default(); + assert!(labels.is_empty()); + + // check address labels are empty + let addr_labels = storage.get_address_labels().unwrap(); + let labels = addr_labels.get(ADDRESS).cloned().unwrap_or_default(); + assert!(labels.is_empty()); } #[test] diff --git a/mutiny-core/src/lib.rs b/mutiny-core/src/lib.rs index 8b34562be..16349b339 100644 --- a/mutiny-core/src/lib.rs +++ b/mutiny-core/src/lib.rs @@ -1319,7 +1319,6 @@ impl MutinyWallet { ln_address: None, lnurl: None, image_url: Some("https://void.cat/d/CZPXhnwjqRhULSjPJ3sXTE.webp".to_string()), - archived: None, last_used: utils::now().as_secs(), }; self.storage.set_data(key, contact, None)?; @@ -2179,7 +2178,6 @@ mod tests { assert_eq!(contacts.len(), 1); let contact = contacts.first().unwrap(); assert_eq!(contact.npub, Some(ben)); - assert!(!contact.archived.unwrap_or(false)); assert!(contact.image_url.is_some()); assert!(contact.ln_address.is_some()); assert!(!contact.name.is_empty()); @@ -2202,7 +2200,6 @@ mod tests { assert_eq!(contacts.len(), 2); let contact = contacts.get(&id).unwrap(); assert_eq!(contact.npub, Some(tony)); - assert!(!contact.archived.unwrap_or(false)); assert!(contact.image_url.is_some()); assert!(contact.ln_address.is_some()); assert_ne!(contact.name, incorrect_name); diff --git a/mutiny-wasm/src/lib.rs b/mutiny-wasm/src/lib.rs index 9f2c513ae..73f9c5485 100644 --- a/mutiny-wasm/src/lib.rs +++ b/mutiny-wasm/src/lib.rs @@ -1178,7 +1178,6 @@ impl MutinyWallet { .transpose()?, lnurl: lnurl.map(|l| LnUrl::from_str(&l)).transpose()?, image_url, - archived: None, last_used: now().as_secs(), }; @@ -1204,14 +1203,13 @@ impl MutinyWallet { .transpose()?, lnurl: lnurl.map(|l| LnUrl::from_str(&l)).transpose()?, image_url, - archived: None, last_used: now().as_secs(), }; Ok(self.inner.node_manager.create_new_contact(contact)?) } - pub fn archive_contact(&self, id: String) -> Result<(), MutinyJsError> { - Ok(self.inner.node_manager.archive_contact(id)?) + pub fn delete_contact(&self, id: String) -> Result<(), MutinyJsError> { + Ok(self.inner.node_manager.delete_contact(id)?) } pub fn edit_contact( @@ -1231,7 +1229,6 @@ impl MutinyWallet { .transpose()?, lnurl: lnurl.map(|l| LnUrl::from_str(&l)).transpose()?, image_url, - archived: None, last_used: now().as_secs(), };