Tweak 'group sender' avatars.

pull/1/head
Matthew Chen 7 years ago
parent e3a13dfd9e
commit 4effa56d50

@ -8,6 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
@class ConversationViewCell;
@class ConversationViewItem;
@class OWSContactOffersInteraction;
@class OWSContactsManager;
@class TSAttachmentPointer;
@class TSAttachmentStream;
@class TSInteraction;
@ -47,6 +48,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)didTapFailedOutgoingMessage:(TSOutgoingMessage *)message;
#pragma mark - Contacts
- (OWSContactsManager *)contactsManager;
@end
#pragma mark -

@ -3,6 +3,7 @@
//
#import "OWSMessageCell.h"
#import "OWSContactAvatarBuilder.h"
#import "OWSExpirationTimerView.h"
#import "OWSMessageBubbleView.h"
#import "Signal-Swift.h"
@ -24,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) OWSMessageBubbleView *messageBubbleView;
@property (nonatomic) UILabel *dateHeaderLabel;
@property (nonatomic) UIView *footerView;
@property (nonatomic) AvatarImageView *avatarView;
@property (nonatomic) UILabel *footerLabel;
@property (nonatomic, nullable) OWSExpirationTimerView *expirationTimerView;
@ -71,9 +73,15 @@ NS_ASSUME_NONNULL_BEGIN
self.footerLabel.textColor = [UIColor lightGrayColor];
[self.footerView addSubview:self.footerLabel];
self.avatarView = [[AvatarImageView alloc] init];
[self.contentView addSubview:self.avatarView];
[self.avatarView autoSetDimension:ALDimensionWidth toSize:self.avatarSize];
[self.avatarView autoSetDimension:ALDimensionHeight toSize:self.avatarSize];
// Hide these views by default.
self.dateHeaderLabel.hidden = YES;
self.footerLabel.hidden = YES;
self.avatarView.hidden = YES;
[self.messageBubbleView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.dateHeaderLabel];
@ -95,6 +103,11 @@ NS_ASSUME_NONNULL_BEGIN
[self addGestureRecognizer:panGesture];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)setLayoutInfo:(nullable ConversationLayoutInfo *)layoutInfo
{
[super setLayoutInfo:layoutInfo];
@ -168,6 +181,20 @@ NS_ASSUME_NONNULL_BEGIN
[self updateDateHeader];
[self updateFooter];
if ([self updateAvatarView]) {
CGFloat avatarBottomMargin = round(self.layoutInfo.lastTextLineAxis - self.avatarSize * 0.5f);
[self.viewConstraints addObjectsFromArray:@[
[self.messageBubbleView autoPinLeadingToTrailingEdgeOfView:self.avatarView offset:8],
// TODO: We actually want a slightly different alignment.
[self.messageBubbleView autoPinEdge:ALEdgeBottom
toEdge:ALEdgeBottom
ofView:self.avatarView
withOffset:avatarBottomMargin],
]];
[self.messageBubbleView logFrameLaterWithLabel:@"messageBubbleView"];
[self.avatarView logFrameLaterWithLabel:@"avatarView"];
}
}
// * If cell is visible, lazy-load (expensive) view contents.
@ -382,6 +409,74 @@ NS_ASSUME_NONNULL_BEGIN
return UIFont.ows_dynamicTypeCaption1Font;
}
#pragma mark - Avatar
// Returns YES IFF the avatar view is appropriate and configured.
- (BOOL)updateAvatarView
{
if (!self.viewItem.isGroupThread) {
return NO;
}
if (self.viewItem.interaction.interactionType != OWSInteractionType_IncomingMessage) {
return NO;
}
if (self.viewItem.shouldHideAvatar) {
return NO;
}
OWSContactsManager *contactsManager = self.delegate.contactsManager;
if (contactsManager == nil) {
OWSFail(@"%@ contactsManager should not be nil", self.logTag);
return NO;
}
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)self.viewItem.interaction;
OWSAvatarBuilder *avatarBuilder = [[OWSContactAvatarBuilder alloc] initWithSignalId:incomingMessage.authorId
diameter:self.avatarSize
contactsManager:contactsManager];
self.avatarView.image = [avatarBuilder build];
self.avatarView.hidden = NO;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(otherUsersProfileDidChange:)
name:kNSNotificationName_OtherUsersProfileDidChange
object:nil];
return YES;
}
- (NSUInteger)avatarSize
{
return 24.f;
}
- (void)otherUsersProfileDidChange:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
if (!self.viewItem.isGroupThread) {
return;
}
if (self.viewItem.interaction.interactionType != OWSInteractionType_IncomingMessage) {
return;
}
if (self.viewItem.shouldHideAvatar) {
return;
}
NSString *recipientId = notification.userInfo[kNSNotificationKey_ProfileRecipientId];
if (recipientId.length == 0) {
return;
}
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)self.viewItem.interaction;
if (![incomingMessage.authorId isEqualToString:recipientId]) {
return;
}
[self updateAvatarView];
}
#pragma mark - Measurement
- (CGSize)cellSizeWithTransaction:(YapDatabaseReadTransaction *)transaction
@ -421,7 +516,7 @@ NS_ASSUME_NONNULL_BEGIN
}
}
#pragma mark -
#pragma mark - Reuse
- (void)prepareForReuse
{
@ -437,12 +532,16 @@ NS_ASSUME_NONNULL_BEGIN
self.dateHeaderLabel.hidden = YES;
self.footerLabel.text = nil;
self.footerLabel.hidden = YES;
self.avatarView.image = nil;
self.avatarView.hidden = YES;
[self.expirationTimerView clearAnimations];
[self.expirationTimerView removeFromSuperview];
self.expirationTimerView = nil;
[self hideMenuControllerIfNecessary];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Notifications
@ -673,11 +772,6 @@ NS_ASSUME_NONNULL_BEGIN
self.isPresentingMenuController = NO;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
NS_ASSUME_NONNULL_END

@ -70,6 +70,14 @@ public class ConversationLayoutInfo: NSObject {
@objc public var textInsets = OWSDirectionalEdgeInsets.zero
// We want to align "group sender" avatars with the v-center of the
// "last line" of the message body text - or where it would be for
// non-text content.
//
// This is the distance from that v-center to the bottom of the
// message bubble.
@objc public var lastTextLineAxis: CGFloat = 0
@objc
public required init(thread: TSThread) {
@ -131,5 +139,6 @@ public class ConversationLayoutInfo: NSObject {
leading: 12,
bottom: textInsetBottom,
trailing: 12)
lastTextLineAxis = CGFloat(round(12 + messageTextFont.capHeight * 0.5))
}
}

@ -4882,7 +4882,7 @@ typedef enum : NSUInteger {
NSString *_Nullable lastIncomingSenderId = nil;
for (ConversationViewItem *viewItem in viewItems.reverseObjectEnumerator) {
BOOL shouldHideRecipientStatus = NO;
BOOL shouldHideBubbleTail = NO;
BOOL shouldHideAvatar = NO;
OWSInteractionType interactionType = viewItem.interaction.interactionType;
if (interactionType == OWSInteractionType_OutgoingMessage) {
@ -4899,14 +4899,12 @@ typedef enum : NSUInteger {
= (interactionType == lastInteractionType && receiptStatus == lastReceiptStatus);
}
shouldHideBubbleTail = interactionType == lastInteractionType;
lastReceiptStatus = receiptStatus;
} else if (interactionType == OWSInteractionType_IncomingMessage) {
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)viewItem.interaction;
NSString *incomingSenderId = incomingMessage.authorId;
OWSAssert(incomingSenderId.length > 0);
shouldHideBubbleTail = (interactionType == lastInteractionType &&
shouldHideAvatar = (interactionType == lastInteractionType &&
[NSObject isNullableObject:lastIncomingSenderId equalTo:incomingSenderId]);
lastIncomingSenderId = incomingSenderId;
}
@ -4919,7 +4917,7 @@ typedef enum : NSUInteger {
[rowsThatChangedSize addObject:@(viewItem.previousRow)];
}
viewItem.shouldHideRecipientStatus = shouldHideRecipientStatus;
viewItem.shouldHideBubbleTail = shouldHideBubbleTail;
viewItem.shouldHideAvatar = shouldHideAvatar;
}
self.viewItems = viewItems;

@ -56,7 +56,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
@property (nonatomic) BOOL shouldShowDate;
@property (nonatomic) BOOL shouldHideRecipientStatus;
@property (nonatomic) BOOL shouldHideBubbleTail;
// Used to suppress "group sender" avatars.
@property (nonatomic) BOOL shouldHideAvatar;
@property (nonatomic) NSInteger row;
// During updates, we sometimes need the previous row index

@ -162,13 +162,13 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
[self clearCachedLayoutState];
}
- (void)setShouldHideBubbleTail:(BOOL)shouldHideBubbleTail
- (void)setShouldHideAvatar:(BOOL)shouldHideAvatar
{
if (_shouldHideBubbleTail == shouldHideBubbleTail) {
if (_shouldHideAvatar == shouldHideAvatar) {
return;
}
_shouldHideBubbleTail = shouldHideBubbleTail;
_shouldHideAvatar = shouldHideAvatar;
[self clearCachedLayoutState];
}

@ -64,7 +64,6 @@ NS_ASSUME_NONNULL_BEGIN
_viewConstraints = [NSMutableArray new];
self.avatarView = [[AvatarImageView alloc] init];
[self.contentView addSubview:self.avatarView];
[self.avatarView autoSetDimension:ALDimensionWidth toSize:self.avatarSize];
[self.avatarView autoSetDimension:ALDimensionHeight toSize:self.avatarSize];
@ -125,6 +124,11 @@ NS_ASSUME_NONNULL_BEGIN
[self.unreadLabel setCompressionResistanceHigh];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
+ (NSString *)cellReuseIdentifier
{
return NSStringFromClass([self class]);
@ -418,6 +422,7 @@ NS_ASSUME_NONNULL_BEGIN
self.thread = nil;
self.contactsManager = nil;
self.avatarView.image = nil;
[self.unreadBadge removeFromSuperview];

Loading…
Cancel
Save