Signal-iOS/SignalServiceKit/src/Contacts/SignalAccount.m
2020-01-16 16:52:25 -03:00

241 lines
7.0 KiB
Objective-C

//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
//
#import "SignalAccount.h"
#import "Contact.h"
#import "ContactsManagerProtocol.h"
#import "NSData+Image.h"
#import "SSKEnvironment.h"
#import "SignalRecipient.h"
#import "UIImage+OWS.h"
#import <SignalCoreKit/Cryptography.h>
#import <SignalCoreKit/NSString+OWS.h>
#import <SignalServiceKit/SignalServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
NSUInteger const SignalAccountSchemaVersion = 1;
@interface SignalAccount ()
@property (nonatomic, readonly) NSUInteger accountSchemaVersion;
@end
#pragma mark -
@implementation SignalAccount
#pragma mark - Dependencies
- (id<ContactsManagerProtocol>)contactsManager
{
return SSKEnvironment.shared.contactsManager;
}
#pragma mark -
+ (BOOL)shouldBeIndexedForFTS
{
return YES;
}
- (instancetype)initWithSignalRecipient:(SignalRecipient *)signalRecipient
{
OWSAssertDebug(signalRecipient);
OWSAssertDebug(signalRecipient.address.isValid);
return [self initWithSignalServiceAddress:signalRecipient.address];
}
- (instancetype)initWithSignalServiceAddress:(SignalServiceAddress *)serviceAddress
{
if (self = [super init]) {
_recipientUUID = serviceAddress.uuidString;
_recipientPhoneNumber = serviceAddress.phoneNumber;
_accountSchemaVersion = SignalAccountSchemaVersion;
}
return self;
}
- (nullable instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (!self) {
return self;
}
// Migrating from an everyone has a phone number world to a
// world in which we have UUIDs
if (_accountSchemaVersion == 0) {
// Rename recipientId to recipientPhoneNumber
_recipientPhoneNumber = [coder decodeObjectForKey:@"recipientId"];
OWSAssert(_recipientPhoneNumber != nil);
}
_accountSchemaVersion = SignalAccountSchemaVersion;
return self;
}
- (instancetype)initWithContact:(nullable Contact *)contact
contactAvatarHash:(nullable NSData *)contactAvatarHash
contactAvatarJpegData:(nullable NSData *)contactAvatarJpegData
multipleAccountLabelText:(NSString *)multipleAccountLabelText
recipientPhoneNumber:(nullable NSString *)recipientPhoneNumber
recipientUUID:(nullable NSString *)recipientUUID
{
self = [super init];
if (!self) {
return self;
}
OWSAssertDebug(recipientPhoneNumber != nil || recipientUUID != nil);
OWSAssertDebug(recipientPhoneNumber != nil || SSKFeatureFlags.allowUUIDOnlyContacts);
_contact = contact;
_contactAvatarHash = contactAvatarHash;
_contactAvatarJpegData = contactAvatarJpegData;
_multipleAccountLabelText = multipleAccountLabelText;
_recipientPhoneNumber = recipientPhoneNumber;
_recipientUUID = recipientUUID;
_accountSchemaVersion = SignalAccountSchemaVersion;
return self;
}
// --- CODE GENERATION MARKER
// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run `sds_codegen.sh`.
// clang-format off
- (instancetype)initWithGrdbId:(int64_t)grdbId
uniqueId:(NSString *)uniqueId
contact:(nullable Contact *)contact
contactAvatarHash:(nullable NSData *)contactAvatarHash
contactAvatarJpegData:(nullable NSData *)contactAvatarJpegData
multipleAccountLabelText:(NSString *)multipleAccountLabelText
recipientPhoneNumber:(nullable NSString *)recipientPhoneNumber
recipientUUID:(nullable NSString *)recipientUUID
{
self = [super initWithGrdbId:grdbId
uniqueId:uniqueId];
if (!self) {
return self;
}
_contact = contact;
_contactAvatarHash = contactAvatarHash;
_contactAvatarJpegData = contactAvatarJpegData;
_multipleAccountLabelText = multipleAccountLabelText;
_recipientPhoneNumber = recipientPhoneNumber;
_recipientUUID = recipientUUID;
return self;
}
// clang-format on
// --- CODE GENERATION MARKER
- (nullable NSString *)contactFullName
{
return self.contact.fullName.filterStringForDisplay;
}
- (nullable NSString *)contactFirstName
{
return self.contact.firstName.filterStringForDisplay;
}
- (nullable NSString *)contactLastName
{
return self.contact.lastName.filterStringForDisplay;
}
- (NSString *)multipleAccountLabelText
{
NSString *_Nullable result = _multipleAccountLabelText.filterStringForDisplay;
return result != nil ? result : @"";
}
- (SignalServiceAddress *)recipientAddress
{
return [[SignalServiceAddress alloc] initWithUuidString:self.recipientUUID phoneNumber:self.recipientPhoneNumber];
}
- (BOOL)hasSameContent:(SignalAccount *)other
{
OWSAssertDebug(other != nil);
// NOTE: We don't want to compare contactAvatarJpegData.
// It can't change without contactAvatarHash changing
// as well.
return ([NSObject isNullableObject:self.recipientPhoneNumber equalTo:other.recipientPhoneNumber] &&
[NSObject isNullableObject:self.recipientUUID equalTo:other.recipientUUID] &&
[NSObject isNullableObject:self.contact equalTo:other.contact] &&
[NSObject isNullableObject:self.multipleAccountLabelText equalTo:other.multipleAccountLabelText] &&
[NSObject isNullableObject:self.contactAvatarHash equalTo:other.contactAvatarHash]);
}
- (void)tryToCacheContactAvatarData
{
OWSAssertDebug(self.contactAvatarHash == nil);
OWSAssertDebug(self.contactAvatarJpegData == nil);
if (self.contact == nil) {
OWSFailDebug(@"Missing contact.");
return;
}
if (self.contact.isFromContactSync) {
OWSLogVerbose(@"not caching data for synced contact");
return;
}
OWSAssertDebug(self.contact.cnContactId);
NSData *_Nullable contactAvatarData = [self.contactsManager avatarDataForCNContactId:self.contact.cnContactId];
if (contactAvatarData == nil) {
return;
}
self.contactAvatarHash = [Cryptography computeSHA256Digest:contactAvatarData];
OWSAssertDebug(self.contactAvatarHash != nil);
if (self.contactAvatarHash == nil) {
return;
}
self.contactAvatarJpegData = [UIImage validJpegDataFromAvatarData:contactAvatarData];
if (self.contactAvatarJpegData == nil) {
OWSFailDebug(@"Could not convert avatar to JPEG.");
return;
}
}
- (void)anyDidInsertWithTransaction:(SDSAnyWriteTransaction *)transaction
{
[super anyDidInsertWithTransaction:transaction];
[self.contactsManager.signalAccountReadCache didInsertOrUpdateSignalAccount:self transaction:transaction];
}
- (void)anyDidUpdateWithTransaction:(SDSAnyWriteTransaction *)transaction
{
[super anyDidUpdateWithTransaction:transaction];
[self.contactsManager.signalAccountReadCache didInsertOrUpdateSignalAccount:self transaction:transaction];
}
- (void)anyDidRemoveWithTransaction:(SDSAnyWriteTransaction *)transaction
{
[super anyDidRemoveWithTransaction:transaction];
[self.contactsManager.signalAccountReadCache didRemoveSignalAccount:self transaction:transaction];
}
@end
NS_ASSUME_NONNULL_END