From 742f8cf9020b2a271df09862d085363b7efa8ef4 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 31 Jul 2017 16:07:38 -0400 Subject: [PATCH] Avoid unnecessariy flashing avatars Make avatar building sync Tests on a iPhone5 with 1k threads, 3k contacts show no noticeable lag. Profiling shows ~4% of usage goes to contact avatar building, but once cached, even that goes towards zero. // FREEBIE --- Signal/src/Models/OWSAvatarBuilder.h | 4 ++-- Signal/src/Models/OWSAvatarBuilder.m | 2 +- Signal/src/Models/OWSContactAvatarBuilder.m | 2 +- Signal/src/Models/OWSGroupAvatarBuilder.m | 12 +++++++++--- .../src/ViewControllers/CallViewController.swift | 2 +- Signal/src/ViewControllers/InboxTableViewCell.m | 14 +++----------- .../OWSConversationSettingsTableViewController.m | 8 ++++---- Signal/src/views/ContactTableViewCell.m | 4 ++-- 8 files changed, 23 insertions(+), 25 deletions(-) diff --git a/Signal/src/Models/OWSAvatarBuilder.h b/Signal/src/Models/OWSAvatarBuilder.h index b669f0a7c..6ec98ef70 100644 --- a/Signal/src/Models/OWSAvatarBuilder.h +++ b/Signal/src/Models/OWSAvatarBuilder.h @@ -11,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSAvatarBuilder : NSObject + (UIImage *)buildImageForThread:(TSThread *)thread - contactsManager:(OWSContactsManager *)contactsManager - diameter:(NSUInteger)diameter; + diameter:(NSUInteger)diameter + contactsManager:(OWSContactsManager *)contactsManager NS_SWIFT_NAME(buildImage(thread:diameter:contactsManager:)); - (nullable UIImage *)buildSavedImage; - (UIImage *)buildDefaultImage; diff --git a/Signal/src/Models/OWSAvatarBuilder.m b/Signal/src/Models/OWSAvatarBuilder.m index f5ab65b6d..25026d4c1 100644 --- a/Signal/src/Models/OWSAvatarBuilder.m +++ b/Signal/src/Models/OWSAvatarBuilder.m @@ -13,8 +13,8 @@ NS_ASSUME_NONNULL_BEGIN @implementation OWSAvatarBuilder + (UIImage *)buildImageForThread:(TSThread *)thread - contactsManager:(OWSContactsManager *)contactsManager diameter:(NSUInteger)diameter + contactsManager:(OWSContactsManager *)contactsManager { OWSAvatarBuilder *avatarBuilder; if ([thread isKindOfClass:[TSContactThread class]]) { diff --git a/Signal/src/Models/OWSContactAvatarBuilder.m b/Signal/src/Models/OWSContactAvatarBuilder.m index 0d399e2e3..9031465b7 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.m +++ b/Signal/src/Models/OWSContactAvatarBuilder.m @@ -95,7 +95,7 @@ NS_ASSUME_NONNULL_BEGIN textColor:[UIColor whiteColor] font:[UIFont ows_boldFontWithSize:fontSize] diameter:self.diameter] avatarImage]; - [self.contactsManager.avatarCache setObject:image forKey:self.signalId]; + [self.contactsManager.avatarCache setObject:image forKey:cacheKey]; return image; } diff --git a/Signal/src/Models/OWSGroupAvatarBuilder.m b/Signal/src/Models/OWSGroupAvatarBuilder.m index aa10d9138..beb4f49fb 100644 --- a/Signal/src/Models/OWSGroupAvatarBuilder.m +++ b/Signal/src/Models/OWSGroupAvatarBuilder.m @@ -1,5 +1,6 @@ -// Created by Michael Kirk on 9/26/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "OWSGroupAvatarBuilder.h" #import "TSGroupThread.h" @@ -32,7 +33,12 @@ NS_ASSUME_NONNULL_BEGIN - (UIImage *)buildDefaultImage { - return [UIImage imageNamed:@"empty-group-avatar"]; + static UIImage *defaultGroupImage; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + defaultGroupImage = [UIImage imageNamed:@"empty-group-avatar"]; + }); + return defaultGroupImage; } @end diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 6662291e2..1f1adcd73 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -399,7 +399,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, } func updateAvatarImage() { - contactAvatarView.image = OWSAvatarBuilder.buildImage(for: thread, contactsManager: contactsManager, diameter:400) + contactAvatarView.image = OWSAvatarBuilder.buildImage(thread: thread, diameter: 400, contactsManager: contactsManager) } func createIncomingCallControls() { diff --git a/Signal/src/ViewControllers/InboxTableViewCell.m b/Signal/src/ViewControllers/InboxTableViewCell.m index cb65791a2..5f194feca 100644 --- a/Signal/src/ViewControllers/InboxTableViewCell.m +++ b/Signal/src/ViewControllers/InboxTableViewCell.m @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN #define DATE_LABEL_SIZE 13 #define SWIPE_ARCHIVE_OFFSET -50 -const NSUInteger kavatarViewDiameter = 52; +const NSUInteger kAvatarViewDiameter = 52; @interface InboxTableViewCell () @@ -227,16 +227,8 @@ const NSUInteger kavatarViewDiameter = 52; self.unreadLabel.hidden = YES; } - NSString *threadIdCopy = thread.uniqueId; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - UIImage *avatar = - [OWSAvatarBuilder buildImageForThread:thread contactsManager:contactsManager diameter:kavatarViewDiameter]; - dispatch_async(dispatch_get_main_queue(), ^{ - if ([_threadId isEqualToString:threadIdCopy]) { - self.avatarView.image = avatar; - } - }); - }); + self.avatarView.image = + [OWSAvatarBuilder buildImageForThread:thread diameter:kAvatarViewDiameter contactsManager:contactsManager]; } - (void)updateCellForUnreadMessage { diff --git a/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m b/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m index c3685bee1..ecdf65166 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m +++ b/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m @@ -575,11 +575,11 @@ NS_ASSUME_NONNULL_BEGIN [threadInfoView autoPinHeightToSuperviewWithMargin:16.f]; const NSUInteger kAvatarSize = 68; - UIImage *avatar = - [OWSAvatarBuilder buildImageForThread:self.thread contactsManager:self.contactsManager diameter:kAvatarSize]; - OWSAssert(avatar); + UIImage *avatarImage = + [OWSAvatarBuilder buildImageForThread:self.thread diameter:kAvatarSize contactsManager:self.contactsManager]; + OWSAssert(avatarImage); - AvatarImageView *avatarView = [[AvatarImageView alloc] initWithImage:avatar]; + AvatarImageView *avatarView = [[AvatarImageView alloc] initWithImage:avatarImage]; _avatarView = avatarView; [threadInfoView addSubview:avatarView]; [avatarView autoVCenterInSuperview]; diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index ba5a7389c..16e92da3e 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -139,8 +139,8 @@ const NSUInteger kContactTableViewCellAvatarSize = 40; self.nameLabel.attributedText = attributedText; self.avatarView.image = [OWSAvatarBuilder buildImageForThread:thread - contactsManager:contactsManager - diameter:kContactTableViewCellAvatarSize]; + diameter:kContactTableViewCellAvatarSize + contactsManager:contactsManager]; // Force layout, since imageView isn't being initally rendered on App Store optimized build. [self layoutSubviews];