|
|
|
@ -125,6 +125,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
@property (nonatomic, nullable) NSString *nameSuffix;
|
|
|
|
|
@property (nonatomic, nullable) NSString *namePrefix;
|
|
|
|
|
@property (nonatomic, nullable) NSString *middleName;
|
|
|
|
|
@property (nonatomic, nullable) NSString *organizationName;
|
|
|
|
|
@property (nonatomic, nullable) NSString *displayName;
|
|
|
|
|
|
|
|
|
|
@property (nonatomic, nullable) NSArray<OWSContactPhoneNumber *> *phoneNumbers;
|
|
|
|
|
@property (nonatomic, nullable) NSArray<OWSContactEmail *> *emails;
|
|
|
|
@ -139,183 +141,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
|
|
|
|
|
@implementation OWSContact
|
|
|
|
|
|
|
|
|
|
+ (OWSContact *_Nullable)contactForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage
|
|
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
|
|
|
|
{
|
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
|
|
|
|
|
|
if (dataMessage.contact.count < 1) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
OWSAssert(dataMessage.contact.count == 1);
|
|
|
|
|
OWSSignalServiceProtosDataMessageContact *contactProto = dataMessage.contact.firstObject;
|
|
|
|
|
|
|
|
|
|
OWSContact *contact = [OWSContact new];
|
|
|
|
|
if (contactProto.hasName) {
|
|
|
|
|
OWSSignalServiceProtosDataMessageContactName *nameProto = contactProto.name;
|
|
|
|
|
|
|
|
|
|
if (nameProto.hasGivenName) {
|
|
|
|
|
contact.givenName = nameProto.givenName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasFamilyName) {
|
|
|
|
|
contact.familyName = nameProto.familyName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasPrefix) {
|
|
|
|
|
contact.namePrefix = nameProto.prefix.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasSuffix) {
|
|
|
|
|
contact.nameSuffix = nameProto.suffix.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasMiddleName) {
|
|
|
|
|
contact.middleName = nameProto.middleName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSMutableArray<OWSContactPhoneNumber *> *phoneNumbers = [NSMutableArray new];
|
|
|
|
|
for (OWSSignalServiceProtosDataMessageContactPhone *phoneNumberProto in contactProto.number) {
|
|
|
|
|
OWSContactPhoneNumber *_Nullable phoneNumber = [self phoneNumberForProto:phoneNumberProto];
|
|
|
|
|
if (phoneNumber) {
|
|
|
|
|
[phoneNumbers addObject:phoneNumber];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
contact.phoneNumbers = [phoneNumbers copy];
|
|
|
|
|
|
|
|
|
|
NSMutableArray<OWSContactEmail *> *emails = [NSMutableArray new];
|
|
|
|
|
for (OWSSignalServiceProtosDataMessageContactEmail *emailProto in contactProto.email) {
|
|
|
|
|
OWSContactEmail *_Nullable email = [self emailForProto:emailProto];
|
|
|
|
|
if (email) {
|
|
|
|
|
[emails addObject:email];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
contact.emails = [emails copy];
|
|
|
|
|
|
|
|
|
|
NSMutableArray<OWSContactAddress *> *addresses = [NSMutableArray new];
|
|
|
|
|
for (OWSSignalServiceProtosDataMessageContactPostalAddress *addressProto in contactProto.address) {
|
|
|
|
|
OWSContactAddress *_Nullable address = [self addressForProto:addressProto];
|
|
|
|
|
if (address) {
|
|
|
|
|
[addresses addObject:address];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
contact.addresses = [addresses copy];
|
|
|
|
|
|
|
|
|
|
// TODO: Avatar
|
|
|
|
|
|
|
|
|
|
return contact;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (nullable OWSContactPhoneNumber *)phoneNumberForProto:
|
|
|
|
|
(OWSSignalServiceProtosDataMessageContactPhone *)phoneNumberProto
|
|
|
|
|
{
|
|
|
|
|
OWSContactPhoneNumber *result = [OWSContactPhoneNumber new];
|
|
|
|
|
result.phoneType = OWSContactPhoneType_Custom;
|
|
|
|
|
if (phoneNumberProto.hasType) {
|
|
|
|
|
switch (phoneNumberProto.type) {
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPhoneTypeHome:
|
|
|
|
|
result.phoneType = OWSContactPhoneType_Home;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPhoneTypeMobile:
|
|
|
|
|
result.phoneType = OWSContactPhoneType_Mobile;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPhoneTypeWork:
|
|
|
|
|
result.phoneType = OWSContactPhoneType_Work;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (phoneNumberProto.hasLabel) {
|
|
|
|
|
result.label = phoneNumberProto.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (phoneNumberProto.hasValue) {
|
|
|
|
|
result.phoneNumber = phoneNumberProto.value.ows_stripped;
|
|
|
|
|
} else {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
if (!result.isValid) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (nullable OWSContactEmail *)emailForProto:(OWSSignalServiceProtosDataMessageContactEmail *)emailProto
|
|
|
|
|
{
|
|
|
|
|
OWSContactEmail *result = [OWSContactEmail new];
|
|
|
|
|
result.emailType = OWSContactEmailType_Custom;
|
|
|
|
|
if (emailProto.hasType) {
|
|
|
|
|
switch (emailProto.type) {
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactEmailTypeHome:
|
|
|
|
|
result.emailType = OWSContactEmailType_Home;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactEmailTypeMobile:
|
|
|
|
|
result.emailType = OWSContactEmailType_Mobile;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactEmailTypeWork:
|
|
|
|
|
result.emailType = OWSContactEmailType_Work;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (emailProto.hasLabel) {
|
|
|
|
|
result.label = emailProto.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (emailProto.hasValue) {
|
|
|
|
|
result.email = emailProto.value.ows_stripped;
|
|
|
|
|
} else {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
if (!result.isValid) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (nullable OWSContactAddress *)addressForProto:(OWSSignalServiceProtosDataMessageContactPostalAddress *)addressProto
|
|
|
|
|
{
|
|
|
|
|
OWSContactAddress *result = [OWSContactAddress new];
|
|
|
|
|
result.addressType = OWSContactAddressType_Custom;
|
|
|
|
|
if (addressProto.hasType) {
|
|
|
|
|
switch (addressProto.type) {
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPostalAddressTypeHome:
|
|
|
|
|
result.addressType = OWSContactAddressType_Home;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPostalAddressTypeWork:
|
|
|
|
|
result.addressType = OWSContactAddressType_Work;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasLabel) {
|
|
|
|
|
result.label = addressProto.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasStreet) {
|
|
|
|
|
result.street = addressProto.street.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasPobox) {
|
|
|
|
|
result.pobox = addressProto.pobox.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasNeighborhood) {
|
|
|
|
|
result.neighborhood = addressProto.neighborhood.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasCity) {
|
|
|
|
|
result.city = addressProto.city.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasRegion) {
|
|
|
|
|
result.region = addressProto.region.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasPostcode) {
|
|
|
|
|
result.postcode = addressProto.postcode.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasCountry) {
|
|
|
|
|
result.country = addressProto.country.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (!result.isValid) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL)isValid
|
|
|
|
|
{
|
|
|
|
|
if (self.givenName.ows_stripped.length < 1 && self.familyName.ows_stripped.length) {
|
|
|
|
@ -403,9 +228,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
contact.familyName = systemContact.familyName.ows_stripped;
|
|
|
|
|
contact.namePrefix = systemContact.namePrefix.ows_stripped;
|
|
|
|
|
contact.nameSuffix = systemContact.nameSuffix.ows_stripped;
|
|
|
|
|
// TODO: Display name.
|
|
|
|
|
// contact.displayName = [CNContactFormatter stringFromContact:contact
|
|
|
|
|
// style:CNContactFormatterStyleFullName]; contact.organizationName = contact.organizationName.ows_stripped;
|
|
|
|
|
// TODO: Verify.
|
|
|
|
|
contact.displayName = [CNContactFormatter stringFromContact:systemContact style:CNContactFormatterStyleFullName];
|
|
|
|
|
contact.organizationName = systemContact.organizationName.ows_stripped;
|
|
|
|
|
|
|
|
|
|
NSMutableArray<OWSContactPhoneNumber *> *phoneNumbers = [NSMutableArray new];
|
|
|
|
|
for (CNLabeledValue<CNPhoneNumber *> *phoneNumberField in systemContact.phoneNumbers) {
|
|
|
|
@ -502,9 +327,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
systemContact.familyName = contact.familyName;
|
|
|
|
|
systemContact.namePrefix = contact.namePrefix;
|
|
|
|
|
systemContact.nameSuffix = contact.nameSuffix;
|
|
|
|
|
// TODO: Display name.
|
|
|
|
|
// contact.displayName = [CNContactFormatter stringFromContact:contact
|
|
|
|
|
// style:CNContactFormatterStyleFullName]; contact.organizationName = contact.organizationName.ows_stripped;
|
|
|
|
|
// We don't need to set display name, it's implicit for system contacts.
|
|
|
|
|
systemContact.organizationName = contact.organizationName;
|
|
|
|
|
|
|
|
|
|
NSMutableArray<CNLabeledValue<CNPhoneNumber *> *> *systemPhoneNumbers = [NSMutableArray new];
|
|
|
|
|
for (OWSContactPhoneNumber *phoneNumber in contact.phoneNumbers) {
|
|
|
|
@ -632,6 +456,324 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
return [self vCardDataForSystemContact:systemContact];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark - Proto Serialization
|
|
|
|
|
|
|
|
|
|
+ (nullable OWSSignalServiceProtosDataMessageContact *)protoForContact:(OWSContact *)contact
|
|
|
|
|
{
|
|
|
|
|
OWSAssert(contact);
|
|
|
|
|
|
|
|
|
|
if (!contact.isValid) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ contact share is invalid.", self.logTag);
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OWSSignalServiceProtosDataMessageContactBuilder *contactBuilder =
|
|
|
|
|
[OWSSignalServiceProtosDataMessageContactBuilder new];
|
|
|
|
|
|
|
|
|
|
// TODO: Should we normalize/validate values here?
|
|
|
|
|
OWSSignalServiceProtosDataMessageContactNameBuilder *nameBuilder =
|
|
|
|
|
[OWSSignalServiceProtosDataMessageContactNameBuilder new];
|
|
|
|
|
if (contact.givenName.ows_stripped.length > 0) {
|
|
|
|
|
nameBuilder.givenName = contact.givenName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (contact.familyName.ows_stripped.length > 0) {
|
|
|
|
|
nameBuilder.familyName = contact.familyName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (contact.middleName.ows_stripped.length > 0) {
|
|
|
|
|
nameBuilder.middleName = contact.middleName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (contact.namePrefix.ows_stripped.length > 0) {
|
|
|
|
|
nameBuilder.prefix = contact.namePrefix.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (contact.nameSuffix.ows_stripped.length > 0) {
|
|
|
|
|
nameBuilder.suffix = contact.nameSuffix.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
[contactBuilder setNameBuilder:nameBuilder];
|
|
|
|
|
|
|
|
|
|
for (OWSContactPhoneNumber *phoneNumber in contact.phoneNumbers) {
|
|
|
|
|
if (!phoneNumber.isValid) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ phone number is invalid.", self.logTag);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
OWSSignalServiceProtosDataMessageContactPhoneBuilder *phoneBuilder =
|
|
|
|
|
[OWSSignalServiceProtosDataMessageContactPhoneBuilder new];
|
|
|
|
|
phoneBuilder.value = phoneNumber.phoneNumber;
|
|
|
|
|
if (phoneBuilder.label.ows_stripped.length > 0) {
|
|
|
|
|
phoneBuilder.label = phoneBuilder.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
switch (phoneNumber.phoneType) {
|
|
|
|
|
case OWSContactPhoneType_Home:
|
|
|
|
|
phoneBuilder.type = OWSSignalServiceProtosDataMessageContactPhoneTypeHome;
|
|
|
|
|
break;
|
|
|
|
|
case OWSContactPhoneType_Mobile:
|
|
|
|
|
phoneBuilder.type = OWSSignalServiceProtosDataMessageContactPhoneTypeMobile;
|
|
|
|
|
break;
|
|
|
|
|
case OWSContactPhoneType_Work:
|
|
|
|
|
phoneBuilder.type = OWSSignalServiceProtosDataMessageContactPhoneTypeWork;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
phoneBuilder.type = OWSSignalServiceProtosDataMessageContactPhoneTypeCustom;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
[contactBuilder addNumber:phoneBuilder.build];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (OWSContactEmail *email in contact.emails) {
|
|
|
|
|
if (!email.isValid) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ email is invalid.", self.logTag);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
OWSSignalServiceProtosDataMessageContactEmailBuilder *emailBuilder =
|
|
|
|
|
[OWSSignalServiceProtosDataMessageContactEmailBuilder new];
|
|
|
|
|
emailBuilder.value = email.email;
|
|
|
|
|
if (emailBuilder.label.ows_stripped.length > 0) {
|
|
|
|
|
emailBuilder.label = emailBuilder.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
switch (email.emailType) {
|
|
|
|
|
case OWSContactEmailType_Home:
|
|
|
|
|
emailBuilder.type = OWSSignalServiceProtosDataMessageContactEmailTypeHome;
|
|
|
|
|
break;
|
|
|
|
|
case OWSContactEmailType_Mobile:
|
|
|
|
|
emailBuilder.type = OWSSignalServiceProtosDataMessageContactEmailTypeMobile;
|
|
|
|
|
break;
|
|
|
|
|
case OWSContactEmailType_Work:
|
|
|
|
|
emailBuilder.type = OWSSignalServiceProtosDataMessageContactEmailTypeWork;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
emailBuilder.type = OWSSignalServiceProtosDataMessageContactEmailTypeCustom;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
[contactBuilder addEmail:emailBuilder.build];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (OWSContactAddress *address in contact.addresses) {
|
|
|
|
|
if (!address.isValid) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ address is invalid.", self.logTag);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
OWSSignalServiceProtosDataMessageContactPostalAddressBuilder *addressBuilder =
|
|
|
|
|
[OWSSignalServiceProtosDataMessageContactPostalAddressBuilder new];
|
|
|
|
|
if (addressBuilder.label.ows_stripped.length > 0) {
|
|
|
|
|
addressBuilder.label = addressBuilder.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressBuilder.street.ows_stripped.length > 0) {
|
|
|
|
|
addressBuilder.street = addressBuilder.street.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressBuilder.pobox.ows_stripped.length > 0) {
|
|
|
|
|
addressBuilder.pobox = addressBuilder.pobox.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressBuilder.neighborhood.ows_stripped.length > 0) {
|
|
|
|
|
addressBuilder.neighborhood = addressBuilder.neighborhood.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressBuilder.city.ows_stripped.length > 0) {
|
|
|
|
|
addressBuilder.city = addressBuilder.city.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressBuilder.region.ows_stripped.length > 0) {
|
|
|
|
|
addressBuilder.region = addressBuilder.region.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressBuilder.postcode.ows_stripped.length > 0) {
|
|
|
|
|
addressBuilder.postcode = addressBuilder.postcode.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressBuilder.country.ows_stripped.length > 0) {
|
|
|
|
|
addressBuilder.country = addressBuilder.country.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
[contactBuilder addAddress:addressBuilder.build];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: avatar
|
|
|
|
|
|
|
|
|
|
OWSSignalServiceProtosDataMessageContact *contactProto = [contactBuilder build];
|
|
|
|
|
if (contactProto.number.count < 1 && contactProto.email.count < 1 && contactProto.address.count < 1) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ contact has neither phone, email or address.", self.logTag);
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
return contactProto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (OWSContact *_Nullable)contactForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage
|
|
|
|
|
{
|
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
|
|
|
|
|
|
if (dataMessage.contact.count < 1) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
OWSAssert(dataMessage.contact.count == 1);
|
|
|
|
|
OWSSignalServiceProtosDataMessageContact *contactProto = dataMessage.contact.firstObject;
|
|
|
|
|
|
|
|
|
|
OWSContact *contact = [OWSContact new];
|
|
|
|
|
|
|
|
|
|
if (contactProto.hasOrganization) {
|
|
|
|
|
contact.organizationName = contactProto.organization.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (contactProto.hasName) {
|
|
|
|
|
OWSSignalServiceProtosDataMessageContactName *nameProto = contactProto.name;
|
|
|
|
|
|
|
|
|
|
if (nameProto.hasGivenName) {
|
|
|
|
|
contact.givenName = nameProto.givenName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasFamilyName) {
|
|
|
|
|
contact.familyName = nameProto.familyName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasPrefix) {
|
|
|
|
|
contact.namePrefix = nameProto.prefix.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasSuffix) {
|
|
|
|
|
contact.nameSuffix = nameProto.suffix.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasMiddleName) {
|
|
|
|
|
contact.middleName = nameProto.middleName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (nameProto.hasDisplayName) {
|
|
|
|
|
contact.displayName = nameProto.displayName.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSMutableArray<OWSContactPhoneNumber *> *phoneNumbers = [NSMutableArray new];
|
|
|
|
|
for (OWSSignalServiceProtosDataMessageContactPhone *phoneNumberProto in contactProto.number) {
|
|
|
|
|
OWSContactPhoneNumber *_Nullable phoneNumber = [self phoneNumberForProto:phoneNumberProto];
|
|
|
|
|
if (phoneNumber) {
|
|
|
|
|
[phoneNumbers addObject:phoneNumber];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
contact.phoneNumbers = [phoneNumbers copy];
|
|
|
|
|
|
|
|
|
|
NSMutableArray<OWSContactEmail *> *emails = [NSMutableArray new];
|
|
|
|
|
for (OWSSignalServiceProtosDataMessageContactEmail *emailProto in contactProto.email) {
|
|
|
|
|
OWSContactEmail *_Nullable email = [self emailForProto:emailProto];
|
|
|
|
|
if (email) {
|
|
|
|
|
[emails addObject:email];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
contact.emails = [emails copy];
|
|
|
|
|
|
|
|
|
|
NSMutableArray<OWSContactAddress *> *addresses = [NSMutableArray new];
|
|
|
|
|
for (OWSSignalServiceProtosDataMessageContactPostalAddress *addressProto in contactProto.address) {
|
|
|
|
|
OWSContactAddress *_Nullable address = [self addressForProto:addressProto];
|
|
|
|
|
if (address) {
|
|
|
|
|
[addresses addObject:address];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
contact.addresses = [addresses copy];
|
|
|
|
|
|
|
|
|
|
// TODO: Avatar
|
|
|
|
|
|
|
|
|
|
return contact;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (nullable OWSContactPhoneNumber *)phoneNumberForProto:
|
|
|
|
|
(OWSSignalServiceProtosDataMessageContactPhone *)phoneNumberProto
|
|
|
|
|
{
|
|
|
|
|
OWSContactPhoneNumber *result = [OWSContactPhoneNumber new];
|
|
|
|
|
result.phoneType = OWSContactPhoneType_Custom;
|
|
|
|
|
if (phoneNumberProto.hasType) {
|
|
|
|
|
switch (phoneNumberProto.type) {
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPhoneTypeHome:
|
|
|
|
|
result.phoneType = OWSContactPhoneType_Home;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPhoneTypeMobile:
|
|
|
|
|
result.phoneType = OWSContactPhoneType_Mobile;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPhoneTypeWork:
|
|
|
|
|
result.phoneType = OWSContactPhoneType_Work;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (phoneNumberProto.hasLabel) {
|
|
|
|
|
result.label = phoneNumberProto.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (phoneNumberProto.hasValue) {
|
|
|
|
|
result.phoneNumber = phoneNumberProto.value.ows_stripped;
|
|
|
|
|
} else {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
if (!result.isValid) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (nullable OWSContactEmail *)emailForProto:(OWSSignalServiceProtosDataMessageContactEmail *)emailProto
|
|
|
|
|
{
|
|
|
|
|
OWSContactEmail *result = [OWSContactEmail new];
|
|
|
|
|
result.emailType = OWSContactEmailType_Custom;
|
|
|
|
|
if (emailProto.hasType) {
|
|
|
|
|
switch (emailProto.type) {
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactEmailTypeHome:
|
|
|
|
|
result.emailType = OWSContactEmailType_Home;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactEmailTypeMobile:
|
|
|
|
|
result.emailType = OWSContactEmailType_Mobile;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactEmailTypeWork:
|
|
|
|
|
result.emailType = OWSContactEmailType_Work;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (emailProto.hasLabel) {
|
|
|
|
|
result.label = emailProto.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (emailProto.hasValue) {
|
|
|
|
|
result.email = emailProto.value.ows_stripped;
|
|
|
|
|
} else {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
if (!result.isValid) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (nullable OWSContactAddress *)addressForProto:(OWSSignalServiceProtosDataMessageContactPostalAddress *)addressProto
|
|
|
|
|
{
|
|
|
|
|
OWSContactAddress *result = [OWSContactAddress new];
|
|
|
|
|
result.addressType = OWSContactAddressType_Custom;
|
|
|
|
|
if (addressProto.hasType) {
|
|
|
|
|
switch (addressProto.type) {
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPostalAddressTypeHome:
|
|
|
|
|
result.addressType = OWSContactAddressType_Home;
|
|
|
|
|
break;
|
|
|
|
|
case OWSSignalServiceProtosDataMessageContactPostalAddressTypeWork:
|
|
|
|
|
result.addressType = OWSContactAddressType_Work;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasLabel) {
|
|
|
|
|
result.label = addressProto.label.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasStreet) {
|
|
|
|
|
result.street = addressProto.street.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasPobox) {
|
|
|
|
|
result.pobox = addressProto.pobox.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasNeighborhood) {
|
|
|
|
|
result.neighborhood = addressProto.neighborhood.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasCity) {
|
|
|
|
|
result.city = addressProto.city.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasRegion) {
|
|
|
|
|
result.region = addressProto.region.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasPostcode) {
|
|
|
|
|
result.postcode = addressProto.postcode.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (addressProto.hasCountry) {
|
|
|
|
|
result.country = addressProto.country.ows_stripped;
|
|
|
|
|
}
|
|
|
|
|
if (!result.isValid) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_END
|
|
|
|
|