From b579ea59152fa01637a63eae954fd98a578fe5c9 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 24 Aug 2017 17:08:02 -0400 Subject: [PATCH 1/3] Use profile name when building avatar if contact name is unavailable // FREEBIE --- Signal/src/AppDelegate.m | 1 + Signal/src/Models/OWSContactAvatarBuilder.m | 9 ++++- Signal/src/contact/OWSContactsManager.h | 13 +++++++ Signal/src/contact/OWSContactsManager.m | 38 +++++++++++++++++++-- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 39224f74c..a86d066eb 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -243,6 +243,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; [[TSStorageManager sharedManager] setupDatabaseWithSafeBlockingMigrations:^{ [VersionMigrations runSafeBlockingMigrations]; }]; + [[Environment getCurrent].contactsManager startObserving]; self.incomingMessageReadObserver = [[OWSIncomingMessageReadObserver alloc] initWithMessageSender:[Environment getCurrent].messageSender]; diff --git a/Signal/src/Models/OWSContactAvatarBuilder.m b/Signal/src/Models/OWSContactAvatarBuilder.m index b0177ce0d..2211ee870 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.m +++ b/Signal/src/Models/OWSContactAvatarBuilder.m @@ -48,7 +48,14 @@ NS_ASSUME_NONNULL_BEGIN diameter:(NSUInteger)diameter contactsManager:(OWSContactsManager *)contactsManager { - NSString *name = [contactsManager displayNameForPhoneIdentifier:signalId]; + // Name for avatar initialis. + NSString *_Nullable name = [contactsManager nameFromSystemContactsForRecipientId:signalId]; + if (name.length == 0) { + name = [contactsManager profileNameForRecipientId:signalId]; + } + if (name.length == 0) { + name = signalId; + } return [self initWithContactId:signalId name:name diameter:diameter contactsManager:contactsManager]; } diff --git a/Signal/src/contact/OWSContactsManager.h b/Signal/src/contact/OWSContactsManager.h index e3d4fa464..4cbc6fcc4 100644 --- a/Signal/src/contact/OWSContactsManager.h +++ b/Signal/src/contact/OWSContactsManager.h @@ -17,6 +17,12 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; */ @interface OWSContactsManager : NSObject +#pragma mark - Setup + +- (void)startObserving; + +#pragma mark - Accessors + @property (nonnull, readonly) NSCache *avatarCache; @property (atomic, readonly) NSArray *allContacts; @@ -54,7 +60,14 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; - (BOOL)hasNameInSystemContactsForRecipientId:(NSString *)recipientId; - (NSString *)displayNameForPhoneIdentifier:(nullable NSString *)identifier; - (NSString *)displayNameForSignalAccount:(SignalAccount *)signalAccount; + +// Generally we prefer the formattedProfileName over the raw profileName so as to +// distinguish a profile name apart from a name pulled from the system's contacts. +// This helps clarify when the remote person chooses a potentially confusing profile name. - (nullable NSString *)formattedProfileNameForRecipientId:(NSString *)recipientId; +- (nullable NSString *)profileNameForRecipientId:(NSString *)recipientId; +- (nullable NSString *)nameFromSystemContactsForRecipientId:(NSString *)recipientId; + - (nullable UIImage *)imageForPhoneIdentifier:(nullable NSString *)identifier; - (NSAttributedString *)formattedDisplayNameForSignalAccount:(SignalAccount *)signalAccount font:(UIFont *_Nonnull)font; - (NSAttributedString *)formattedFullNameForRecipientId:(NSString *)recipientId font:(UIFont *)font; diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index 735f7348a..acfc16157 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -136,6 +136,24 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account failure:failure]; } +- (void)startObserving +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(otherUsersProfileDidChange:) + name:kNSNotificationName_OtherUsersProfileDidChange + object:nil]; +} + +- (void)otherUsersProfileDidChange:(NSNotification *)notification +{ + OWSAssert([NSThread isMainThread]); + + NSString *recipientId = notification.userInfo[kNSNotificationKey_ProfileRecipientId]; + OWSAssert(recipientId.length > 0); + + [self clearAvatarCacheForRecipientId:recipientId]; +} + - (void)updateWithContacts:(NSArray *)contacts { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @@ -165,6 +183,11 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account }); } +- (void)clearAvatarCacheForRecipientId:(NSString *)recipientId +{ + [self.avatarCache removeObjectForKey:recipientId]; +} + - (void)updateSignalAccounts { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @@ -423,16 +446,25 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account return [NSString stringWithFormat:profileNameFormatString, profileName]; } +- (nullable NSString *)profileNameForRecipientId:(NSString *)recipientId +{ + return [self.profileManager profileNameForRecipientId:recipientId]; +} + +- (nullable NSString *)nameFromSystemContactsForRecipientId:(NSString *)recipientId +{ + return [self cachedDisplayNameForRecipientId:recipientId]; +} + - (NSString *_Nonnull)displayNameForPhoneIdentifier:(NSString *_Nullable)recipientId { if (!recipientId) { return self.unknownContactName; } - // Prefer a saved name from system contacts, if available - NSString *_Nullable displayName = [self cachedDisplayNameForRecipientId:recipientId]; + NSString *_Nullable displayName = [self nameFromSystemContactsForRecipientId:recipientId]; - // Else fall back to just using their recipientId + // Fall back to just using their recipientId if (displayName.length < 1) { displayName = recipientId; } From f6720f9afa7642b909f7fbe2ced7acd2baf2cb52 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 24 Aug 2017 18:47:11 -0400 Subject: [PATCH 2/3] properly clear all cached avatar images // FREEBIE --- Signal.xcodeproj/project.pbxproj | 16 +++++- Signal/src/Models/OWSContactAvatarBuilder.m | 8 +-- Signal/src/contact/OWSContactsManager.h | 3 +- Signal/src/contact/OWSContactsManager.m | 11 ++-- Signal/src/util/ImageCache.swift | 53 ++++++++++++++++++ Signal/test/util/ImageCacheTest.swift | 60 +++++++++++++++++++++ 6 files changed, 138 insertions(+), 13 deletions(-) create mode 100644 Signal/src/util/ImageCache.swift create mode 100644 Signal/test/util/ImageCacheTest.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index ce497d109..e288fa0b4 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -148,6 +148,9 @@ 454EBAB41F2BE14C00ACE0BB /* OWSAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D99C911F2937CC00D284D6 /* OWSAnalytics.swift */; }; 455A16DD1F1FEA0000F86704 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 455A16DB1F1FEA0000F86704 /* Metal.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 455A16DE1F1FEA0000F86704 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 455A16DC1F1FEA0000F86704 /* MetalKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 455AC69B1F4F79E500134004 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455AC69A1F4F79E500134004 /* ImageCache.swift */; }; + 455AC69C1F4F79E500134004 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455AC69A1F4F79E500134004 /* ImageCache.swift */; }; + 455AC69E1F4F8B0300134004 /* ImageCacheTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455AC69D1F4F8B0300134004 /* ImageCacheTest.swift */; }; 45638BDC1F3DD0D400128435 /* DebugUICalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45638BDB1F3DD0D400128435 /* DebugUICalling.swift */; }; 45638BDF1F3DDB2200128435 /* MessageSender+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45638BDE1F3DDB2200128435 /* MessageSender+Promise.swift */; }; 4563ADF11F22BD7100DEB8C7 /* OWS106EnsureProfileComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4563ADF01F22BD7100DEB8C7 /* OWS106EnsureProfileComplete.swift */; }; @@ -602,6 +605,8 @@ 454B35071D08EED80026D658 /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = translations/mk.lproj/Localizable.strings; sourceTree = ""; }; 455A16DB1F1FEA0000F86704 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 455A16DC1F1FEA0000F86704 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; + 455AC69A1F4F79E500134004 /* ImageCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; + 455AC69D1F4F8B0300134004 /* ImageCacheTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCacheTest.swift; sourceTree = ""; }; 45638BDB1F3DD0D400128435 /* DebugUICalling.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugUICalling.swift; sourceTree = ""; }; 45638BDE1F3DDB2200128435 /* MessageSender+Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MessageSender+Promise.swift"; sourceTree = ""; }; 4563ADF01F22BD7100DEB8C7 /* OWS106EnsureProfileComplete.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS106EnsureProfileComplete.swift; sourceTree = ""; }; @@ -1439,6 +1444,7 @@ 76EB04FB18170B33006006FC /* Util.h */, 45F170D51E315310003FC1F2 /* Weak.swift */, 45F170CB1E310E22003FC1F2 /* WeakTimer.swift */, + 455AC69A1F4F79E500134004 /* ImageCache.swift */, ); path = util; sourceTree = ""; @@ -1639,6 +1645,7 @@ B660F6B31C29868000687D6E /* UtilTest.h */, B660F6B41C29868000687D6E /* UtilTest.m */, 45666F571D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m */, + 455AC69D1F4F8B0300134004 /* ImageCacheTest.swift */, ); path = util; sourceTree = ""; @@ -2194,6 +2201,7 @@ 34E3EF0D1EFC235B007F6822 /* DebugUIDiskUsage.m in Sources */, 344F2F671E57A932000D9322 /* UIViewController+OWS.m in Sources */, B6DA6B071B8A2F9A00CA6F98 /* AppStoreRating.m in Sources */, + 455AC69B1F4F79E500134004 /* ImageCache.swift in Sources */, 451A13B11E13DED2000A50FD /* CallNotificationsAdapter.swift in Sources */, 3456710A1E8A9F5D006EE662 /* TSGenericAttachmentAdapter.m in Sources */, 450DF2091E0DD2C6003D14BE /* UserNotificationsAdaptee.swift in Sources */, @@ -2434,6 +2442,7 @@ B660F7771C29988E00687D6E /* UIImage+normalizeImage.m in Sources */, 954AEE6A1DF33E01002E5410 /* ContactsPickerTest.swift in Sources */, B660F77B1C29988E00687D6E /* Queue.m in Sources */, + 455AC69C1F4F79E500134004 /* ImageCache.swift in Sources */, 45666F581D9B2880008FE134 /* OWSScrubbingLogFormatterTest.m in Sources */, B660F77F1C29988E00687D6E /* DateUtil.m in Sources */, B660F7811C29988E00687D6E /* FunctionalUtil.m in Sources */, @@ -2462,6 +2471,7 @@ B660F6D21C29868000687D6E /* PushManagerTest.m in Sources */, 45C0DC1F1E69011F00E04C47 /* UIStoryboard+OWS.swift in Sources */, 4505C2C01E648EA300CEBF41 /* ExperienceUpgrade.swift in Sources */, + 455AC69E1F4F8B0300134004 /* ImageCacheTest.swift in Sources */, 450873C81D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2554,7 +2564,11 @@ "DEBUG=1", "$(inherited)", ); - "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "DEBUG=1 $(inherited) SSK_BUILDING_FOR_TESTS=1"; + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + "DEBUG=1", + "$(inherited)", + "SSK_BUILDING_FOR_TESTS=1", + ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; diff --git a/Signal/src/Models/OWSContactAvatarBuilder.m b/Signal/src/Models/OWSContactAvatarBuilder.m index 2211ee870..910b9aace 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.m +++ b/Signal/src/Models/OWSContactAvatarBuilder.m @@ -4,6 +4,7 @@ #import "OWSContactAvatarBuilder.h" #import "OWSContactsManager.h" +#import "Signal-Swift.h" #import "TSContactThread.h" #import "TSGroupThread.h" #import "TSThread.h" @@ -76,8 +77,8 @@ NS_ASSUME_NONNULL_BEGIN - (UIImage *)buildDefaultImage { - NSString *cacheKey = [NSString stringWithFormat:@"signalId:%@:diamater:%lu", self.signalId, (unsigned long)self.diameter]; - UIImage *cachedAvatar = [self.contactsManager.avatarCache objectForKey:cacheKey]; + UIImage *cachedAvatar = + [self.contactsManager.avatarCache imageForKey:self.signalId diameter:(CGFloat)self.diameter]; if (cachedAvatar) { return cachedAvatar; } @@ -115,7 +116,8 @@ NS_ASSUME_NONNULL_BEGIN textColor:[UIColor whiteColor] font:[UIFont ows_boldFontWithSize:fontSize] diameter:self.diameter] avatarImage]; - [self.contactsManager.avatarCache setObject:image forKey:cacheKey]; + + [self.contactsManager.avatarCache setImage:image forKey:self.signalId diameter:self.diameter]; return image; } diff --git a/Signal/src/contact/OWSContactsManager.h b/Signal/src/contact/OWSContactsManager.h index 4cbc6fcc4..8d8e09a7c 100644 --- a/Signal/src/contact/OWSContactsManager.h +++ b/Signal/src/contact/OWSContactsManager.h @@ -11,6 +11,7 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; @class UIFont; @class SignalAccount; +@class ImageCache; /** * Get latest Signal contacts, and be notified when they change. @@ -23,7 +24,7 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification; #pragma mark - Accessors -@property (nonnull, readonly) NSCache *avatarCache; +@property (nonnull, readonly) ImageCache *avatarCache; @property (atomic, readonly) NSArray *allContacts; diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index acfc16157..6c05bc0ce 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -50,7 +50,7 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account } // TODO: We need to configure the limits of this cache. - _avatarCache = [NSCache new]; + _avatarCache = [ImageCache new]; _allContacts = @[]; _signalAccountMap = @{}; _signalAccounts = @[]; @@ -151,7 +151,7 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account NSString *recipientId = notification.userInfo[kNSNotificationKey_ProfileRecipientId]; OWSAssert(recipientId.length > 0); - [self clearAvatarCacheForRecipientId:recipientId]; + [self.avatarCache removeAllImagesForKey:recipientId]; } - (void)updateWithContacts:(NSArray *)contacts @@ -172,7 +172,7 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account self.allContacts = contacts; self.allContactsMap = [allContactsMap copy]; - [self.avatarCache removeAllObjects]; + [self.avatarCache removeAllImages]; [self intersectContacts]; @@ -183,11 +183,6 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account }); } -- (void)clearAvatarCacheForRecipientId:(NSString *)recipientId -{ - [self.avatarCache removeObjectForKey:recipientId]; -} - - (void)updateSignalAccounts { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ diff --git a/Signal/src/util/ImageCache.swift b/Signal/src/util/ImageCache.swift new file mode 100644 index 000000000..005ee82bb --- /dev/null +++ b/Signal/src/util/ImageCache.swift @@ -0,0 +1,53 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +import Foundation +import UIKit + +class ImageCacheRecord: NSObject { + var variations: [CGFloat: UIImage] + init(variations: [CGFloat: UIImage]) { + self.variations = variations + } +} + +/** + * A two dimensional hash, allowing you to store variations under a single key. + * This is useful because we generate multiple diameters of an image, but when we + * want to clear out the images for a key we want to clear out *all* variations. + */ +@objc +class ImageCache: NSObject { + + let backingCache: NSCache + + override init() { + self.backingCache = NSCache() + } + + func image(forKey key: AnyObject, diameter: CGFloat) -> UIImage? { + guard let record = backingCache.object(forKey: key) else { + return nil + } + return record.variations[diameter] + } + + func setImage(_ image: UIImage, forKey key: AnyObject, diameter: CGFloat) { + if let existingRecord = backingCache.object(forKey: key) { + existingRecord.variations[diameter] = image + backingCache.setObject(existingRecord, forKey: key) + } else { + let newRecord = ImageCacheRecord(variations: [diameter: image]) + backingCache.setObject(newRecord, forKey: key) + } + } + + func removeAllImages() { + backingCache.removeAllObjects() + } + + func removeAllImages(forKey key: AnyObject) { + backingCache.removeObject(forKey: key) + } +} diff --git a/Signal/test/util/ImageCacheTest.swift b/Signal/test/util/ImageCacheTest.swift new file mode 100644 index 000000000..5837420ff --- /dev/null +++ b/Signal/test/util/ImageCacheTest.swift @@ -0,0 +1,60 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +import XCTest + +class ImageCacheTest: XCTestCase { + + var imageCache: ImageCache! + + let firstVariation = UIImage() + let secondVariation = UIImage() + let otherImage = UIImage() + + let cacheKey1 = "cache-key-1" as NSString + let cacheKey2 = "cache-key-2" as NSString + + override func setUp() { + super.setUp() + self.imageCache = ImageCache() + imageCache.setImage(firstVariation, forKey:cacheKey1, diameter:100) + imageCache.setImage(secondVariation, forKey:cacheKey1, diameter:200) + imageCache.setImage(otherImage, forKey:cacheKey2, diameter:100) + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testSetGet() { + XCTAssertEqual(firstVariation, imageCache.image(forKey:cacheKey1, diameter: 100)) + XCTAssertEqual(secondVariation, imageCache.image(forKey:cacheKey1, diameter: 200)) + XCTAssertNotEqual(secondVariation, imageCache.image(forKey:cacheKey1, diameter: 100)) + XCTAssertEqual(otherImage, imageCache.image(forKey:cacheKey2, diameter: 100)) + XCTAssertNil(imageCache.image(forKey:cacheKey2, diameter: 200)) + } + + func testRemoveAllForKey() { + // sanity check + XCTAssertEqual(firstVariation, imageCache.image(forKey:cacheKey1, diameter: 100)) + XCTAssertEqual(otherImage, imageCache.image(forKey:cacheKey2, diameter: 100)) + + imageCache.removeAllImages(forKey:cacheKey1) + + XCTAssertNil(imageCache.image(forKey:cacheKey1, diameter: 100)) + XCTAssertNil(imageCache.image(forKey:cacheKey1, diameter: 200)) + XCTAssertEqual(otherImage, imageCache.image(forKey:cacheKey2, diameter: 100)) + } + + func testRemoveAll() { + XCTAssertEqual(firstVariation, imageCache.image(forKey:cacheKey1, diameter: 100)) + + imageCache.removeAllImages() + + XCTAssertNil(imageCache.image(forKey:cacheKey1, diameter: 100)) + XCTAssertNil(imageCache.image(forKey:cacheKey1, diameter: 200)) + XCTAssertNil(imageCache.image(forKey:cacheKey2, diameter: 100)) + } +} From bde40a1f9cb71ce73121231c3dda94bdbc0d107b Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 25 Aug 2017 12:39:27 -0400 Subject: [PATCH 3/3] Ensure avatar upates right after profile change. // FREEBIE --- Signal.xcodeproj/project.pbxproj | 6 +---- Signal/src/Models/OWSContactAvatarBuilder.m | 2 +- Signal/src/Profiles/OWSProfileManager.h | 1 + Signal/src/Profiles/OWSProfileManager.m | 7 ++++++ .../src/ViewControllers/InboxTableViewCell.m | 23 ++++++++++++++--- Signal/src/contact/OWSContactsManager.m | 6 ++--- Signal/src/views/ContactTableViewCell.m | 25 ++++++++++++++++--- .../src/Messages/OWSMessageReceiver.m | 2 +- 8 files changed, 55 insertions(+), 17 deletions(-) diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index e288fa0b4..20f328642 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -2564,11 +2564,7 @@ "DEBUG=1", "$(inherited)", ); - "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( - "DEBUG=1", - "$(inherited)", - "SSK_BUILDING_FOR_TESTS=1", - ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "DEBUG=1 $(inherited) SSK_BUILDING_FOR_TESTS=1"; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; diff --git a/Signal/src/Models/OWSContactAvatarBuilder.m b/Signal/src/Models/OWSContactAvatarBuilder.m index 910b9aace..22d824573 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.m +++ b/Signal/src/Models/OWSContactAvatarBuilder.m @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN diameter:(NSUInteger)diameter contactsManager:(OWSContactsManager *)contactsManager { - // Name for avatar initialis. + // Name for avatar initials. NSString *_Nullable name = [contactsManager nameFromSystemContactsForRecipientId:signalId]; if (name.length == 0) { name = [contactsManager profileNameForRecipientId:signalId]; diff --git a/Signal/src/Profiles/OWSProfileManager.h b/Signal/src/Profiles/OWSProfileManager.h index 892755f63..4b8829dff 100644 --- a/Signal/src/Profiles/OWSProfileManager.h +++ b/Signal/src/Profiles/OWSProfileManager.h @@ -7,6 +7,7 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const kNSNotificationName_LocalProfileDidChange; +extern NSString *const kNSNotificationName_OtherUsersProfileWillChange; extern NSString *const kNSNotificationName_OtherUsersProfileDidChange; extern NSString *const kNSNotificationName_ProfileWhitelistDidChange; extern NSString *const kNSNotificationKey_ProfileRecipientId; diff --git a/Signal/src/Profiles/OWSProfileManager.m b/Signal/src/Profiles/OWSProfileManager.m index 009693179..bfde411ee 100644 --- a/Signal/src/Profiles/OWSProfileManager.m +++ b/Signal/src/Profiles/OWSProfileManager.m @@ -86,6 +86,7 @@ NS_ASSUME_NONNULL_BEGIN NSString *const kLocalProfileUniqueId = @"kLocalProfileUniqueId"; NSString *const kNSNotificationName_LocalProfileDidChange = @"kNSNotificationName_LocalProfileDidChange"; +NSString *const kNSNotificationName_OtherUsersProfileWillChange = @"kNSNotificationName_OtherUsersProfileWillChange"; NSString *const kNSNotificationName_OtherUsersProfileDidChange = @"kNSNotificationName_OtherUsersProfileDidChange"; NSString *const kNSNotificationName_ProfileWhitelistDidChange = @"kNSNotificationName_ProfileWhitelistDidChange"; NSString *const kNSNotificationKey_ProfileRecipientId = @"kNSNotificationKey_ProfileRecipientId"; @@ -239,6 +240,12 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; object:nil userInfo:nil]; } else { + [[NSNotificationCenter defaultCenter] + postNotificationName:kNSNotificationName_OtherUsersProfileWillChange + object:nil + userInfo:@{ + kNSNotificationKey_ProfileRecipientId : userProfile.recipientId, + }]; [[NSNotificationCenter defaultCenter] postNotificationName:kNSNotificationName_OtherUsersProfileDidChange object:nil diff --git a/Signal/src/ViewControllers/InboxTableViewCell.m b/Signal/src/ViewControllers/InboxTableViewCell.m index eb6698f44..e8cda13bc 100644 --- a/Signal/src/ViewControllers/InboxTableViewCell.m +++ b/Signal/src/ViewControllers/InboxTableViewCell.m @@ -212,10 +212,10 @@ const NSUInteger kAvatarViewDiameter = 52; name:kNSNotificationName_OtherUsersProfileDidChange object:nil]; [self updateNameLabel]; - + [self updateAvatarView]; + self.snippetLabel.attributedText = snippetText; self.timeLabel.attributedText = attributedDate; - self.avatarView.image = nil; self.separatorInset = UIEdgeInsetsMake(0, self.avatarSize * 1.5f, 0, 0); @@ -229,11 +229,27 @@ const NSUInteger kAvatarViewDiameter = 52; self.unreadBadge.hidden = YES; self.unreadLabel.hidden = YES; } +} + +- (void)updateAvatarView +{ + OWSContactsManager *contactsManager = self.contactsManager; + if (contactsManager == nil) { + OWSFail(@"%@ contactsManager should not be nil", self.logTag); + self.avatarView.image = nil; + return; + } + + TSThread *thread = self.thread; + if (thread == nil) { + OWSFail(@"%@ thread should not be nil", self.logTag); + self.avatarView.image = nil; + return; + } self.avatarView.image = [OWSAvatarBuilder buildImageForThread:thread diameter:kAvatarViewDiameter contactsManager:contactsManager]; } - #pragma mark - Date formatting - (NSAttributedString *)dateAttributedString:(NSDate *)date { @@ -286,6 +302,7 @@ const NSUInteger kAvatarViewDiameter = 52; } [self updateNameLabel]; + [self updateAvatarView]; } -(void)updateNameLabel diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index 6c05bc0ce..fa09b075e 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -139,12 +139,12 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account - (void)startObserving { [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(otherUsersProfileDidChange:) - name:kNSNotificationName_OtherUsersProfileDidChange + selector:@selector(otherUsersProfileWillChange:) + name:kNSNotificationName_OtherUsersProfileWillChange object:nil]; } -- (void)otherUsersProfileDidChange:(NSNotification *)notification +- (void)otherUsersProfileWillChange:(NSNotification *)notification { OWSAssert([NSThread isMainThread]); diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index a1caf7d88..18415739a 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -129,6 +129,7 @@ const NSUInteger kContactTableViewCellAvatarSize = 40; name:kNSNotificationName_OtherUsersProfileDidChange object:nil]; [self updateProfileName]; + [self updateAvatar]; if (self.accessoryMessage) { UILabel *blockedLabel = [[UILabel alloc] init]; @@ -141,10 +142,6 @@ const NSUInteger kContactTableViewCellAvatarSize = 40; self.accessoryView = blockedLabel; } - self.avatarView.image = [[[OWSContactAvatarBuilder alloc] initWithSignalId:recipientId - diameter:kContactTableViewCellAvatarSize - contactsManager:contactsManager] build]; - // Force layout, since imageView isn't being initally rendered on App Store optimized build. [self layoutSubviews]; } @@ -197,7 +194,26 @@ const NSUInteger kContactTableViewCellAvatarSize = 40; return [text copy]; } +- (void)updateAvatar +{ + OWSContactsManager *contactsManager = self.contactsManager; + if (contactsManager == nil) { + OWSFail(@"%@ contactsManager should not be nil", self.logTag); + self.avatarView.image = nil; + return; + } + + NSString *recipientId = self.recipientId; + if (recipientId.length == 0) { + OWSFail(@"%@ recipientId should not be nil", self.logTag); + self.avatarView.image = nil; + return; + } + self.avatarView.image = [[[OWSContactAvatarBuilder alloc] initWithSignalId:recipientId + diameter:kContactTableViewCellAvatarSize + contactsManager:contactsManager] build]; +} - (void)updateProfileName { OWSContactsManager *contactsManager = self.contactsManager; @@ -246,6 +262,7 @@ const NSUInteger kContactTableViewCellAvatarSize = 40; if (recipientId.length > 0 && [self.recipientId isEqualToString:recipientId]) { [self updateProfileName]; + [self updateAvatar]; } } diff --git a/SignalServiceKit/src/Messages/OWSMessageReceiver.m b/SignalServiceKit/src/Messages/OWSMessageReceiver.m index 91e979ae8..db975f76b 100644 --- a/SignalServiceKit/src/Messages/OWSMessageReceiver.m +++ b/SignalServiceKit/src/Messages/OWSMessageReceiver.m @@ -171,7 +171,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces { YapDatabaseView *existingView = [database registeredExtension:OWSMessageProcessingJobFinderExtensionName]; if (existingView) { - OWSFail(@"%@ was already initailized.", OWSMessageProcessingJobFinderExtensionName); + OWSFail(@"%@ was already initialized.", OWSMessageProcessingJobFinderExtensionName); // already initialized return; }