From b11f8affa7eedb6995cef627e8ebd4d163097427 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Sat, 13 May 2017 17:36:12 -0400 Subject: [PATCH 1/6] Use AvatarImageView Conistently apply avatar style * contact picker * conversation settings * home view // FREEBIE --- .../src/ViewControllers/InboxTableViewCell.h | 4 +- .../src/ViewControllers/InboxTableViewCell.m | 1 - .../ViewControllers/InboxTableViewCell.xib | 11 +++--- ...SConversationSettingsTableViewController.m | 6 +-- Signal/src/views/AvatarImageView.swift | 39 +++++++++++++++++-- Signal/src/views/ContactTableViewCell.m | 16 +------- 6 files changed, 45 insertions(+), 32 deletions(-) diff --git a/Signal/src/ViewControllers/InboxTableViewCell.h b/Signal/src/ViewControllers/InboxTableViewCell.h index 2e57a8767..7a1f5737c 100644 --- a/Signal/src/ViewControllers/InboxTableViewCell.h +++ b/Signal/src/ViewControllers/InboxTableViewCell.h @@ -2,13 +2,13 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import #import "TSThread.h" NS_ASSUME_NONNULL_BEGIN @class Contact; @class OWSContactsManager; +@class AvatarImageView; typedef enum : NSUInteger { kArchiveState = 0, kInboxState = 1 } CellState; @@ -16,7 +16,7 @@ typedef enum : NSUInteger { kArchiveState = 0, kInboxState = 1 } CellState; @property (nonatomic) IBOutlet UILabel *nameLabel; @property (nonatomic) IBOutlet UILabel *snippetLabel; -@property (nonatomic) IBOutlet UIImageView *contactPictureView; +@property (nonatomic) IBOutlet AvatarImageView *contactPictureView; @property (nonatomic) IBOutlet UILabel *timeLabel; @property (nonatomic) IBOutlet UIView *contentContainerView; @property (nonatomic) IBOutlet UIView *messageCounter; diff --git a/Signal/src/ViewControllers/InboxTableViewCell.m b/Signal/src/ViewControllers/InboxTableViewCell.m index fb7afd9fd..f2a29c088 100644 --- a/Signal/src/ViewControllers/InboxTableViewCell.m +++ b/Signal/src/ViewControllers/InboxTableViewCell.m @@ -120,7 +120,6 @@ NS_ASSUME_NONNULL_BEGIN self.snippetLabel.attributedText = snippetText; self.timeLabel.attributedText = attributedDate; self.contactPictureView.image = nil; - [UIUtil applyRoundedBorderToImageView:_contactPictureView]; self.separatorInset = UIEdgeInsetsMake(0, _contactPictureView.frame.size.width * 1.5f, 0, 0); diff --git a/Signal/src/ViewControllers/InboxTableViewCell.xib b/Signal/src/ViewControllers/InboxTableViewCell.xib index 882ca800e..e4c55c963 100644 --- a/Signal/src/ViewControllers/InboxTableViewCell.xib +++ b/Signal/src/ViewControllers/InboxTableViewCell.xib @@ -1,11 +1,10 @@ - - + + - - + @@ -16,13 +15,13 @@ - + - + diff --git a/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m b/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m index 371c080c0..12825fdb1 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m +++ b/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m @@ -539,12 +539,8 @@ NS_ASSUME_NONNULL_BEGIN UIImage *avatar = [OWSAvatarBuilder buildImageForThread:self.thread contactsManager:self.contactsManager]; OWSAssert(avatar); const CGFloat kAvatarSize = 68.f; - UIImageView *avatarView = [[UIImageView alloc] initWithImage:avatar]; + AvatarImageView *avatarView = [[AvatarImageView alloc] initWithImage:avatar]; _avatarView = avatarView; - avatarView.layer.borderColor = UIColor.clearColor.CGColor; - avatarView.layer.masksToBounds = YES; - avatarView.layer.cornerRadius = kAvatarSize / 2.0f; - avatarView.contentMode = UIViewContentModeScaleAspectFill; [threadInfoView addSubview:avatarView]; [avatarView autoVCenterInSuperview]; [avatarView autoPinEdgeToSuperviewEdge:ALEdgeLeft]; diff --git a/Signal/src/views/AvatarImageView.swift b/Signal/src/views/AvatarImageView.swift index 0687e7b06..9f442019c 100644 --- a/Signal/src/views/AvatarImageView.swift +++ b/Signal/src/views/AvatarImageView.swift @@ -1,14 +1,45 @@ -// Created by Michael Kirk on 12/11/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// import UIKit @IBDesignable class AvatarImageView: UIImageView { - override func layoutSubviews() { + init() { + super.init(frame: CGRect.zero) + self.configureView() + } + + override init(frame: CGRect) { + super.init(frame: frame) + self.configureView() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.configureView() + } + + override init(image: UIImage?) { + super.init(image: image) + self.configureView() + } + + func configureView() { + self.layer.minificationFilter = kCAFilterTrilinear + self.layer.magnificationFilter = kCAFilterTrilinear + self.layer.borderWidth = 0.5 self.layer.masksToBounds = true - self.layer.cornerRadius = self.frame.size.width / 2 + if self.image == nil { + self.image = #imageLiteral(resourceName: "empty-group-avatar") + } + self.contentMode = .scaleToFill } + override func layoutSubviews() { + self.layer.borderColor = UIColor.black.cgColor.copy(alpha: 0.15) + self.layer.cornerRadius = self.frame.size.width / 2 + } } diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index 1a3d17ca8..d0b20eac9 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -6,6 +6,7 @@ #import "Environment.h" #import "OWSContactAvatarBuilder.h" #import "OWSContactsManager.h" +#import "Signal-Swift.h" #import "UIFont+OWS.h" #import "UIUtil.h" #import "UIView+OWS.h" @@ -52,14 +53,7 @@ NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseI - (void)configureProgrammatically { const CGFloat kAvatarSize = 40.f; - _avatarView = [UIImageView new]; - _avatarView.image = [UIImage imageNamed:@"empty-group-avatar"]; - _avatarView.contentMode = UIViewContentModeScaleToFill; - // applyRoundedBorderToImageView requires the avatar to have - // the correct size. - _avatarView.frame = CGRectMake(0, 0, kAvatarSize, kAvatarSize); - _avatarView.layer.minificationFilter = kCAFilterTrilinear; - _avatarView.layer.magnificationFilter = kCAFilterTrilinear; + _avatarView = [AvatarImageView new]; [self.contentView addSubview:_avatarView]; _nameLabel = [UILabel new]; @@ -147,12 +141,6 @@ NSString *const kContactsTable_CellReuseIdentifier = @"kContactsTable_CellReuseI [self layoutSubviews]; } -- (void)layoutSubviews -{ - [super layoutSubviews]; - [UIUtil applyRoundedBorderToImageView:self.avatarView]; -} - - (void)prepareForReuse { self.accessoryMessage = nil; From 19d74d91e039bd346bc569b60d67e96ab860c974 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Sat, 13 May 2017 19:37:50 -0400 Subject: [PATCH 2/6] Build higher res avatar for call screen Initials avatar looks blurry on call screen // FREEBIE --- Signal/src/Models/OWSAvatarBuilder.h | 6 ++-- Signal/src/Models/OWSAvatarBuilder.m | 14 +++++--- Signal/src/Models/OWSContactAvatarBuilder.h | 14 ++++++-- Signal/src/Models/OWSContactAvatarBuilder.m | 33 +++++++++++++------ .../ViewControllers/CallViewController.swift | 2 +- 5 files changed, 50 insertions(+), 19 deletions(-) diff --git a/Signal/src/Models/OWSAvatarBuilder.h b/Signal/src/Models/OWSAvatarBuilder.h index 9138007d2..8c51ff898 100644 --- a/Signal/src/Models/OWSAvatarBuilder.h +++ b/Signal/src/Models/OWSAvatarBuilder.h @@ -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. +// NS_ASSUME_NONNULL_BEGIN @@ -10,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSAvatarBuilder : NSObject + (UIImage *)buildImageForThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager; ++ (UIImage *)buildImageForThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager diameter:(CGFloat)diameter; - (nullable UIImage *)buildSavedImage; - (UIImage *)buildDefaultImage; diff --git a/Signal/src/Models/OWSAvatarBuilder.m b/Signal/src/Models/OWSAvatarBuilder.m index fe22c9429..e125622a9 100644 --- a/Signal/src/Models/OWSAvatarBuilder.m +++ b/Signal/src/Models/OWSAvatarBuilder.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 "OWSAvatarBuilder.h" #import "OWSContactAvatarBuilder.h" @@ -12,11 +13,16 @@ NS_ASSUME_NONNULL_BEGIN @implementation OWSAvatarBuilder + (UIImage *)buildImageForThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager +{ + const CGFloat kDefaultAvatarDiameter = 100; + return [self buildImageForThread:thread contactsManager:contactsManager diameter:kDefaultAvatarDiameter]; +} + ++ (UIImage *)buildImageForThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager diameter:(CGFloat)diameter { OWSAvatarBuilder *avatarBuilder; if ([thread isKindOfClass:[TSContactThread class]]) { - avatarBuilder = - [[OWSContactAvatarBuilder alloc] initWithThread:(TSContactThread *)thread contactsManager:contactsManager]; + avatarBuilder = [[OWSContactAvatarBuilder alloc] initWithThread:(TSContactThread *)thread contactsManager:contactsManager diameter:diameter]; } else if ([thread isKindOfClass:[TSGroupThread class]]) { avatarBuilder = [[OWSGroupAvatarBuilder alloc] initWithThread:(TSGroupThread *)thread]; } else { diff --git a/Signal/src/Models/OWSContactAvatarBuilder.h b/Signal/src/Models/OWSContactAvatarBuilder.h index 6fceb151a..3a655459c 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.h +++ b/Signal/src/Models/OWSContactAvatarBuilder.h @@ -1,5 +1,6 @@ -// Created by Michael Kirk on 9/22/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "OWSAvatarBuilder.h" @@ -14,6 +15,15 @@ NS_ASSUME_NONNULL_BEGIN name:(NSString *)name contactsManager:(OWSContactsManager *)contactsManager; +- (instancetype)initWithContactId:(NSString *)contactId + name:(NSString *)name + contactsManager:(OWSContactsManager *)contactsManager + diameter:(NSUInteger)diameter; + +- (instancetype)initWithThread:(TSContactThread *)thread + contactsManager:(OWSContactsManager *)contactsManager + diameter:(NSUInteger)diameter; + - (instancetype)initWithThread:(TSContactThread *)thread contactsManager:(OWSContactsManager *)contactsManager; @end diff --git a/Signal/src/Models/OWSContactAvatarBuilder.m b/Signal/src/Models/OWSContactAvatarBuilder.m index 35b232f6e..7faf973a5 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.m +++ b/Signal/src/Models/OWSContactAvatarBuilder.m @@ -1,5 +1,6 @@ -// Created by Michael Kirk on 9/22/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "OWSContactAvatarBuilder.h" #import "OWSContactsManager.h" @@ -17,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) OWSContactsManager *contactsManager; @property (nonatomic, readonly) NSString *signalId; @property (nonatomic, readonly) NSString *contactName; +@property (nonatomic, readonly) NSUInteger diameter; @end @@ -25,23 +27,32 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithContactId:(NSString *)contactId name:(NSString *)name contactsManager:(OWSContactsManager *)contactsManager +{ + const CGFloat kDefaultAvatarDiamater = 100; + return [self initWithContactId:contactId name:name contactsManager:contactsManager diameter:kDefaultAvatarDiamater]; +} + +- (instancetype)initWithContactId:(NSString *)contactId + name:(NSString *)name + contactsManager:(OWSContactsManager *)contactsManager + diameter:(NSUInteger)diameter { self = [super init]; if (!self) { return self; } - + _signalId = contactId; _contactName = name; _contactsManager = contactsManager; - + _diameter = diameter; + return self; } - -- (instancetype)initWithThread:(TSContactThread *)thread contactsManager:(OWSContactsManager *)contactsManager +- (instancetype)initWithThread:(TSContactThread *)thread contactsManager:(OWSContactsManager *)contactsManager diameter:(CGFloat)diameter { - return [self initWithContactId:thread.contactIdentifier name:thread.name contactsManager:contactsManager]; + return [self initWithContactId:thread.contactIdentifier name:thread.name contactsManager:contactsManager diameter:diameter]; } - (nullable UIImage *)buildSavedImage @@ -51,7 +62,8 @@ NS_ASSUME_NONNULL_BEGIN - (UIImage *)buildDefaultImage { - UIImage *cachedAvatar = [self.contactsManager.avatarCache objectForKey:self.signalId]; + NSString *cacheKey = [NSString stringWithFormat:@"signalId:%@:diamater:%lu", self.signalId, (unsigned long)self.diameter]; + UIImage *cachedAvatar = [self.contactsManager.avatarCache objectForKey:cacheKey]; if (cachedAvatar) { return cachedAvatar; } @@ -82,12 +94,13 @@ NS_ASSUME_NONNULL_BEGIN [initials appendString:@"#"]; } + CGFloat fontSize = (CGFloat)self.diameter / 2.8; UIColor *backgroundColor = [UIColor backgroundColorForContact:self.signalId]; UIImage *image = [[JSQMessagesAvatarImageFactory avatarImageWithUserInitials:initials backgroundColor:backgroundColor textColor:[UIColor whiteColor] - font:[UIFont ows_boldFontWithSize:36.0] - diameter:100] avatarImage]; + font:[UIFont ows_boldFontWithSize:fontSize] + diameter:self.diameter] avatarImage]; [self.contactsManager.avatarCache setObject:image forKey:self.signalId]; return image; } diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index f75f5be0a..51d489501 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -147,7 +147,7 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R createViews() contactNameLabel.text = contactsManager.displayName(forPhoneIdentifier: thread.contactIdentifier()) - contactAvatarView.image = OWSAvatarBuilder.buildImage(for: thread, contactsManager: contactsManager) + contactAvatarView.image = OWSAvatarBuilder.buildImage(for: thread, contactsManager: contactsManager, diameter:400) assert(call != nil) // Subscribe for future call updates From 52aa8a37445401a11a795dad25a36e3841a1e02f Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Sat, 27 May 2017 08:56:08 -0700 Subject: [PATCH 3/6] require explicit avatar diameter This will help us get crisper text in our generated avatars. // FREEBIE --- Signal/src/Models/OWSAvatarBuilder.h | 5 +++-- Signal/src/Models/OWSAvatarBuilder.m | 10 +++------- Signal/src/Models/OWSContactAvatarBuilder.h | 6 ------ Signal/src/Models/OWSContactAvatarBuilder.m | 12 +++--------- Signal/src/ViewControllers/InboxTableViewCell.m | 6 +++++- .../src/ViewControllers/InboxTableViewCell.xib | 8 +++++--- ...OWSConversationSettingsTableViewController.m | 6 ++++-- Signal/src/views/ContactCell.swift | 4 +++- Signal/src/views/ContactTableViewCell.m | 17 ++++++++++------- 9 files changed, 36 insertions(+), 38 deletions(-) diff --git a/Signal/src/Models/OWSAvatarBuilder.h b/Signal/src/Models/OWSAvatarBuilder.h index 8c51ff898..b669f0a7c 100644 --- a/Signal/src/Models/OWSAvatarBuilder.h +++ b/Signal/src/Models/OWSAvatarBuilder.h @@ -10,8 +10,9 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSAvatarBuilder : NSObject -+ (UIImage *)buildImageForThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager; -+ (UIImage *)buildImageForThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager diameter:(CGFloat)diameter; ++ (UIImage *)buildImageForThread:(TSThread *)thread + contactsManager:(OWSContactsManager *)contactsManager + diameter:(NSUInteger)diameter; - (nullable UIImage *)buildSavedImage; - (UIImage *)buildDefaultImage; diff --git a/Signal/src/Models/OWSAvatarBuilder.m b/Signal/src/Models/OWSAvatarBuilder.m index e125622a9..f5ab65b6d 100644 --- a/Signal/src/Models/OWSAvatarBuilder.m +++ b/Signal/src/Models/OWSAvatarBuilder.m @@ -12,13 +12,9 @@ NS_ASSUME_NONNULL_BEGIN @implementation OWSAvatarBuilder -+ (UIImage *)buildImageForThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager -{ - const CGFloat kDefaultAvatarDiameter = 100; - return [self buildImageForThread:thread contactsManager:contactsManager diameter:kDefaultAvatarDiameter]; -} - -+ (UIImage *)buildImageForThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager diameter:(CGFloat)diameter ++ (UIImage *)buildImageForThread:(TSThread *)thread + contactsManager:(OWSContactsManager *)contactsManager + diameter:(NSUInteger)diameter { OWSAvatarBuilder *avatarBuilder; if ([thread isKindOfClass:[TSContactThread class]]) { diff --git a/Signal/src/Models/OWSContactAvatarBuilder.h b/Signal/src/Models/OWSContactAvatarBuilder.h index 3a655459c..febc7966a 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.h +++ b/Signal/src/Models/OWSContactAvatarBuilder.h @@ -11,10 +11,6 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSContactAvatarBuilder : OWSAvatarBuilder -- (instancetype)initWithContactId:(NSString *)contactId - name:(NSString *)name - contactsManager:(OWSContactsManager *)contactsManager; - - (instancetype)initWithContactId:(NSString *)contactId name:(NSString *)name contactsManager:(OWSContactsManager *)contactsManager @@ -24,8 +20,6 @@ NS_ASSUME_NONNULL_BEGIN contactsManager:(OWSContactsManager *)contactsManager diameter:(NSUInteger)diameter; -- (instancetype)initWithThread:(TSContactThread *)thread contactsManager:(OWSContactsManager *)contactsManager; - @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/Models/OWSContactAvatarBuilder.m b/Signal/src/Models/OWSContactAvatarBuilder.m index 7faf973a5..0d399e2e3 100644 --- a/Signal/src/Models/OWSContactAvatarBuilder.m +++ b/Signal/src/Models/OWSContactAvatarBuilder.m @@ -24,14 +24,6 @@ NS_ASSUME_NONNULL_BEGIN @implementation OWSContactAvatarBuilder -- (instancetype)initWithContactId:(NSString *)contactId - name:(NSString *)name - contactsManager:(OWSContactsManager *)contactsManager -{ - const CGFloat kDefaultAvatarDiamater = 100; - return [self initWithContactId:contactId name:name contactsManager:contactsManager diameter:kDefaultAvatarDiamater]; -} - - (instancetype)initWithContactId:(NSString *)contactId name:(NSString *)name contactsManager:(OWSContactsManager *)contactsManager @@ -50,7 +42,9 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (instancetype)initWithThread:(TSContactThread *)thread contactsManager:(OWSContactsManager *)contactsManager diameter:(CGFloat)diameter +- (instancetype)initWithThread:(TSContactThread *)thread + contactsManager:(OWSContactsManager *)contactsManager + diameter:(NSUInteger)diameter { return [self initWithContactId:thread.contactIdentifier name:thread.name contactsManager:contactsManager diameter:diameter]; } diff --git a/Signal/src/ViewControllers/InboxTableViewCell.m b/Signal/src/ViewControllers/InboxTableViewCell.m index f2a29c088..2be8a27de 100644 --- a/Signal/src/ViewControllers/InboxTableViewCell.m +++ b/Signal/src/ViewControllers/InboxTableViewCell.m @@ -24,6 +24,8 @@ NS_ASSUME_NONNULL_BEGIN #define DATE_LABEL_SIZE 13 #define SWIPE_ARCHIVE_OFFSET -50 +const NSUInteger kContactPictureViewDiameter = 52; + @interface InboxTableViewCell () @property (nonatomic) NSUInteger unreadMessages; @@ -132,7 +134,9 @@ NS_ASSUME_NONNULL_BEGIN NSString *threadIdCopy = thread.uniqueId; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - UIImage *avatar = [OWSAvatarBuilder buildImageForThread:thread contactsManager:contactsManager]; + UIImage *avatar = [OWSAvatarBuilder buildImageForThread:thread + contactsManager:contactsManager + diameter:kContactPictureViewDiameter]; dispatch_async(dispatch_get_main_queue(), ^{ if ([_threadId isEqualToString:threadIdCopy]) { self.contactPictureView.image = avatar; diff --git a/Signal/src/ViewControllers/InboxTableViewCell.xib b/Signal/src/ViewControllers/InboxTableViewCell.xib index e4c55c963..024b2eb45 100644 --- a/Signal/src/ViewControllers/InboxTableViewCell.xib +++ b/Signal/src/ViewControllers/InboxTableViewCell.xib @@ -4,6 +4,7 @@ + @@ -19,11 +20,12 @@ - + - + + @@ -53,7 +55,7 @@