JMAP for Contacts implementation (closes #1576)

This commit is contained in:
mdecimus
2025-10-03 11:55:04 +02:00
parent 3da4619d43
commit d000b5975a
15 changed files with 669 additions and 159 deletions

View File

@@ -5,7 +5,7 @@
*/
use super::{AddressBook, ArchivedAddressBook, ArchivedContactCard, ContactCard};
use calcard::vcard::VCardProperty;
use calcard::vcard::{ArchivedVCardProperty, VCardProperty};
use common::storage::index::{
IndexItem, IndexValue, IndexableAndSerializableObject, IndexableObject,
};
@@ -83,6 +83,24 @@ impl IndexableObject for ContactCard {
field: ContactField::Uid.into(),
value: self.card.uid().into(),
},
IndexValue::Index {
field: ContactField::Created.into(),
value: self.created.into(),
},
IndexValue::Index {
field: ContactField::Updated.into(),
value: self.modified.into(),
},
IndexValue::IndexList {
field: ContactField::Text.into(),
value: self
.text()
.map(str::to_lowercase)
.map(Into::into)
.collect::<HashSet<IndexItem>>()
.into_iter()
.collect(),
},
IndexValue::IndexList {
field: ContactField::Email.into(),
value: self
@@ -114,6 +132,24 @@ impl IndexableObject for &ArchivedContactCard {
field: ContactField::Uid.into(),
value: self.card.uid().into(),
},
IndexValue::Index {
field: ContactField::Created.into(),
value: self.created.to_native().into(),
},
IndexValue::Index {
field: ContactField::Updated.into(),
value: self.modified.to_native().into(),
},
IndexValue::IndexList {
field: ContactField::Text.into(),
value: self
.text()
.map(str::to_lowercase)
.map(Into::into)
.collect::<HashSet<IndexItem>>()
.into_iter()
.collect(),
},
IndexValue::IndexList {
field: ContactField::Email.into(),
value: self
@@ -145,6 +181,26 @@ impl IndexableAndSerializableObject for ContactCard {
}
impl ContactCard {
pub fn text(&self) -> impl Iterator<Item = &str> {
self.card
.entries
.iter()
.filter(|e| {
matches!(
e.name,
VCardProperty::Adr
| VCardProperty::N
| VCardProperty::Fn
| VCardProperty::Title
| VCardProperty::Org
| VCardProperty::Note
| VCardProperty::Nickname
)
})
.flat_map(|e| e.values.iter().filter_map(|v| v.as_text()))
.flat_map(str::split_whitespace)
}
pub fn emails(&self) -> impl Iterator<Item = String> {
self.card.properties(&VCardProperty::Email).flat_map(|e| {
e.values
@@ -155,6 +211,26 @@ impl ContactCard {
}
impl ArchivedContactCard {
pub fn text(&self) -> impl Iterator<Item = &str> {
self.card
.entries
.iter()
.filter(|e| {
matches!(
e.name,
ArchivedVCardProperty::Adr
| ArchivedVCardProperty::N
| ArchivedVCardProperty::Fn
| ArchivedVCardProperty::Title
| ArchivedVCardProperty::Org
| ArchivedVCardProperty::Note
| ArchivedVCardProperty::Nickname
)
})
.flat_map(|e| e.values.iter().filter_map(|v| v.as_text()))
.flat_map(str::split_whitespace)
}
pub fn emails(&self) -> impl Iterator<Item = String> {
self.card.properties(&VCardProperty::Email).flat_map(|e| {
e.values