Merge branch 'charlesmchen/contactShareMessageBubble'

This commit is contained in:
Matthew Chen 2018-05-02 11:01:38 -04:00
commit 0e858bc090
12 changed files with 306 additions and 19 deletions

View file

@ -188,6 +188,7 @@
34C6B0AB1FA0E46F00D35993 /* test-mp3.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 34C6B0A71FA0E46F00D35993 /* test-mp3.mp3 */; };
34C6B0AC1FA0E46F00D35993 /* test-mp4.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 34C6B0A81FA0E46F00D35993 /* test-mp4.mp4 */; };
34C6B0AE1FA0E4AA00D35993 /* test-jpg.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 34C6B0AD1FA0E4AA00D35993 /* test-jpg.jpg */; };
34CA631B2097806F00E526A0 /* OWSContactShareView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CA631A2097806E00E526A0 /* OWSContactShareView.m */; };
34CCAF381F0C0599004084F4 /* AppUpdateNag.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */; };
34CE88E71F2FB9A10098030F /* ProfileViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CE88E61F2FB9A10098030F /* ProfileViewController.m */; };
34CF0787203E6B78005C4D61 /* busy_tone_ansi.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0783203E6B77005C4D61 /* busy_tone_ansi.caf */; };
@ -802,6 +803,8 @@
34C6B0AD1FA0E4AA00D35993 /* test-jpg.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "test-jpg.jpg"; sourceTree = "<group>"; };
34CA1C261F7156F300E51C51 /* MessageDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageDetailViewController.swift; sourceTree = "<group>"; };
34CA1C281F7164F700E51C51 /* MediaMessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaMessageView.swift; sourceTree = "<group>"; };
34CA63192097806E00E526A0 /* OWSContactShareView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactShareView.h; sourceTree = "<group>"; };
34CA631A2097806E00E526A0 /* OWSContactShareView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactShareView.m; sourceTree = "<group>"; };
34CCAF361F0C0599004084F4 /* AppUpdateNag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppUpdateNag.h; sourceTree = "<group>"; };
34CCAF371F0C0599004084F4 /* AppUpdateNag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppUpdateNag.m; sourceTree = "<group>"; };
34CE88E51F2FB9A10098030F /* ProfileViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfileViewController.h; sourceTree = "<group>"; };
@ -1711,6 +1714,8 @@
34DBF001206BD5A500025978 /* OWSBubbleView.m */,
34D1F09A1F867BFC0066283D /* OWSContactOffersCell.h */,
34D1F09B1F867BFC0066283D /* OWSContactOffersCell.m */,
34CA63192097806E00E526A0 /* OWSContactShareView.h */,
34CA631A2097806E00E526A0 /* OWSContactShareView.m */,
34D1F09C1F867BFC0066283D /* OWSExpirableMessageView.h */,
34D1F09D1F867BFC0066283D /* OWSExpirationTimerView.h */,
34D1F09E1F867BFC0066283D /* OWSExpirationTimerView.m */,
@ -3276,6 +3281,7 @@
34A910601FFEB114000C4745 /* OWSBackup.m in Sources */,
34D1F0B01F867BFC0066283D /* OWSSystemMessageCell.m in Sources */,
45A663C51F92EC760027B59E /* GroupTableViewCell.swift in Sources */,
34CA631B2097806F00E526A0 /* OWSContactShareView.m in Sources */,
34D1F0861F8678AA0066283D /* ConversationViewController.m in Sources */,
B90418E6183E9DD40038554A /* DateUtil.m in Sources */,
340FC8BD204DAC8D007AEB0F /* ShowGroupMembersViewController.m in Sources */,

View file

@ -125,7 +125,7 @@ NS_ASSUME_NONNULL_BEGIN
: [self audioColorWithOpacity:0.4f]);
}
#pragma mark - JSQMessageMediaData protocol
#pragma mark -
- (CGFloat)audioIconHMargin
{

View file

@ -0,0 +1,19 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@class OWSContact;
@interface OWSContactShareView : UIView
- (instancetype)initWithContactShare:(OWSContact *)contactShare isIncoming:(BOOL)isIncoming;
- (void)createContents;
+ (CGFloat)bubbleHeight;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,176 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSContactShareView.h"
#import "UIColor+JSQMessages.h"
#import "UIColor+OWS.h"
#import "UIFont+OWS.h"
#import "UIView+OWS.h"
#import <SignalServiceKit/OWSContact.h>
NS_ASSUME_NONNULL_BEGIN
@interface OWSContactShareView ()
@property (nonatomic) OWSContact *contactShare;
@property (nonatomic) BOOL isIncoming;
@end
#pragma mark -
@implementation OWSContactShareView
- (instancetype)initWithContactShare:(OWSContact *)contactShare isIncoming:(BOOL)isIncoming
{
self = [super init];
if (self) {
_contactShare = contactShare;
_isIncoming = isIncoming;
}
return self;
}
#pragma mark -
- (CGFloat)iconHMargin
{
return 12.f;
}
- (CGFloat)iconHSpacing
{
return 10.f;
}
+ (CGFloat)iconVMargin
{
return 12.f;
}
- (CGFloat)iconVMargin
{
return [OWSContactShareView iconVMargin];
}
+ (CGFloat)bubbleHeight
{
return self.iconSize + self.iconVMargin * 2;
}
- (CGFloat)bubbleHeight
{
return [OWSContactShareView bubbleHeight];
}
+ (CGFloat)iconSize
{
return 44.f;
}
- (CGFloat)iconSize
{
return [OWSContactShareView iconSize];
}
- (CGFloat)vMargin
{
return 10.f;
}
- (UIColor *)bubbleBackgroundColor
{
return self.isIncoming ? [UIColor jsq_messageBubbleLightGrayColor] : [UIColor ows_materialBlueColor];
}
- (void)createContents
{
self.backgroundColor = [UIColor colorWithRGBHex:0xefeff4];
self.layoutMargins = UIEdgeInsetsZero;
// TODO: Verify that this layout works in RTL.
const CGFloat kBubbleTailWidth = 6.f;
UIView *contentView = [UIView containerView];
[self addSubview:contentView];
[contentView autoPinLeadingToSuperviewMarginWithInset:self.isIncoming ? kBubbleTailWidth : 0.f];
[contentView autoPinTrailingToSuperviewMarginWithInset:self.isIncoming ? 0.f : kBubbleTailWidth];
[contentView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:self.vMargin];
[contentView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:self.vMargin];
UIView *iconCircleView = [UIView containerView];
iconCircleView.backgroundColor = [UIColor colorWithRGBHex:0x00ffff];
iconCircleView.layer.cornerRadius = self.iconSize * 0.5f;
[iconCircleView autoSetDimension:ALDimensionWidth toSize:self.iconSize];
[iconCircleView autoSetDimension:ALDimensionHeight toSize:self.iconSize];
[iconCircleView setCompressionResistanceHigh];
[iconCircleView setContentHuggingHigh];
// TODO: Use avatar, if present and downloaded. else default.
UIImage *image = [UIImage imageNamed:@"attachment_file"];
OWSAssert(image);
UIImageView *imageView = [UIImageView new];
imageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
imageView.tintColor = self.bubbleBackgroundColor;
[iconCircleView addSubview:imageView];
[imageView autoCenterInSuperview];
UILabel *topLabel = [UILabel new];
topLabel.text = self.contactShare.displayName;
topLabel.textColor = [UIColor blackColor];
topLabel.lineBreakMode = NSLineBreakByTruncatingTail;
topLabel.font = [UIFont ows_dynamicTypeBodyFont];
UIStackView *labelsView = [UIStackView new];
labelsView.axis = UILayoutConstraintAxisVertical;
labelsView.spacing = 2;
[labelsView addArrangedSubview:topLabel];
// TODO: Should we just try to show the _first_ phone number?
// What about email?
// What if the second phone number is a signal account?
NSString *_Nullable firstPhoneNumber = self.contactShare.phoneNumbers.firstObject.phoneNumber;
if (firstPhoneNumber.length > 0) {
UILabel *bottomLabel = [UILabel new];
bottomLabel.text = firstPhoneNumber;
// TODO:
bottomLabel.textColor = [UIColor ows_darkGrayColor];
bottomLabel.lineBreakMode = NSLineBreakByTruncatingTail;
bottomLabel.font = [UIFont ows_dynamicTypeCaption1Font];
[labelsView addArrangedSubview:bottomLabel];
}
UIImage *disclosureImage =
[UIImage imageNamed:(self.isRTL ? @"system_disclosure_indicator_rtl" : @"system_disclosure_indicator")];
OWSAssert(disclosureImage);
UIImageView *disclosureImageView = [UIImageView new];
disclosureImageView.image = [disclosureImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
disclosureImageView.tintColor = [UIColor blackColor];
[disclosureImageView setCompressionResistanceHigh];
[disclosureImageView setContentHuggingHigh];
UIStackView *stackView = [UIStackView new];
stackView.axis = UILayoutConstraintAxisHorizontal;
stackView.spacing = self.iconHSpacing;
stackView.alignment = UIStackViewAlignmentCenter;
[contentView addSubview:stackView];
[stackView autoPinLeadingToSuperviewMarginWithInset:self.iconHMargin];
[stackView autoPinTrailingToSuperviewMarginWithInset:self.iconHMargin];
[stackView autoVCenterInSuperview];
// Ensure that the cell's contents never overflow the cell bounds.
// We pin pin to the superview _edge_ and not _margin_ for the purposes
// of overflow, so that changes to the margins do not trip these safe guards.
[stackView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:0 relation:NSLayoutRelationGreaterThanOrEqual];
[stackView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:0 relation:NSLayoutRelationGreaterThanOrEqual];
[stackView addArrangedSubview:iconCircleView];
[stackView addArrangedSubview:labelsView];
[stackView addArrangedSubview:disclosureImageView];
}
@end
NS_ASSUME_NONNULL_END

View file

@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
#pragma mark - JSQMessageMediaData protocol
#pragma mark -
- (CGFloat)iconHMargin
{

View file

@ -8,6 +8,7 @@
#import "OWSAudioMessageView.h"
#import "OWSBubbleStrokeView.h"
#import "OWSBubbleView.h"
#import "OWSContactShareView.h"
#import "OWSGenericAttachmentView.h"
#import "OWSMessageTextView.h"
#import "OWSQuotedMessageView.h"
@ -194,7 +195,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
- (BOOL)hasNonImageBodyContent
- (BOOL)hasBubbleBackground
{
switch (self.cellType) {
case OWSMessageCellType_Unknown:
@ -202,6 +203,7 @@ NS_ASSUME_NONNULL_BEGIN
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_GenericAttachment:
case OWSMessageCellType_DownloadingAttachment:
case OWSMessageCellType_ContactShare:
return YES;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
@ -226,6 +228,8 @@ NS_ASSUME_NONNULL_BEGIN
case OWSMessageCellType_Video:
// Is there a caption?
return self.hasBodyText;
case OWSMessageCellType_ContactShare:
return NO;
}
}
@ -245,7 +249,7 @@ NS_ASSUME_NONNULL_BEGIN
self.bubbleView.isOutgoing = self.isOutgoing;
self.bubbleView.hideTail = self.viewItem.shouldHideBubbleTail && !self.alwaysShowBubbleTail;
if ([self.viewItem.interaction isKindOfClass:[TSMessage class]] && self.hasNonImageBodyContent) {
if ([self.viewItem.interaction isKindOfClass:[TSMessage class]] && self.hasBubbleBackground) {
TSMessage *message = (TSMessage *)self.viewItem.interaction;
self.bubbleView.bubbleColor = [self.bubbleFactory bubbleColorWithMessage:message];
} else {
@ -327,6 +331,10 @@ NS_ASSUME_NONNULL_BEGIN
bodyMediaView = [self loadViewForDownloadingAttachment];
bodyMediaViewHasGreedyWidth = YES;
break;
case OWSMessageCellType_ContactShare:
bodyMediaView = [self loadViewForContactShare];
bodyMediaViewHasGreedyWidth = YES;
break;
}
if (bodyMediaView) {
@ -784,6 +792,26 @@ NS_ASSUME_NONNULL_BEGIN
return customView;
}
- (UIView *)loadViewForContactShare
{
OWSAssert(self.viewItem.contactShare);
OWSContactShareView *contactShareView =
[[OWSContactShareView alloc] initWithContactShare:self.viewItem.contactShare
isIncoming:self.isIncoming];
[contactShareView createContents];
// TODO: Should we change appearance if contact avatar is uploading?
self.loadCellContentBlock = ^{
// Do nothing.
};
self.unloadCellContentBlock = ^{
// Do nothing.
};
return contactShareView;
}
- (void)addAttachmentUploadViewIfNecessary:(UIView *)attachmentView
{
[self addAttachmentUploadViewIfNecessary:attachmentView
@ -902,6 +930,8 @@ NS_ASSUME_NONNULL_BEGIN
return CGSizeMake(maxMessageWidth, [OWSGenericAttachmentView bubbleHeight]);
case OWSMessageCellType_DownloadingAttachment:
return CGSizeMake(200, 90);
case OWSMessageCellType_ContactShare:
return CGSizeMake(maxMessageWidth, [OWSContactShareView bubbleHeight]);
}
}
@ -1022,6 +1052,10 @@ NS_ASSUME_NONNULL_BEGIN
if (self.cellType == OWSMessageCellType_DownloadingAttachment) {
return NO;
}
if (self.cellType == OWSMessageCellType_ContactShare) {
// TODO: Handle this case.
return NO;
}
if (!self.attachmentStream) {
return NO;
}
@ -1168,6 +1202,9 @@ NS_ASSUME_NONNULL_BEGIN
}
break;
}
case OWSMessageCellType_ContactShare:
// TODO:
break;
}
}

View file

@ -17,6 +17,7 @@ typedef NS_ENUM(NSInteger, OWSMessageCellType) {
OWSMessageCellType_Video,
OWSMessageCellType_GenericAttachment,
OWSMessageCellType_DownloadingAttachment,
OWSMessageCellType_ContactShare,
};
NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
@ -26,6 +27,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
@class ConversationViewCell;
@class DisplayableText;
@class OWSAudioMessageView;
@class OWSContact;
@class OWSQuotedReplyModel;
@class TSAttachmentPointer;
@class TSAttachmentStream;
@ -101,6 +103,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
// if a load has previously failed.
@property (nonatomic) BOOL didCellMediaFailToLoad;
- (nullable OWSContact *)contactShare;
#pragma mark - UIMenuController
- (NSArray<UIMenuItem *> *)textMenuControllerItems;

View file

@ -11,6 +11,7 @@
#import "Signal-Swift.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <SignalMessaging/NSString+OWS.h>
#import <SignalServiceKit/OWSContact.h>
#import <SignalServiceKit/TSInteraction.h>
NS_ASSUME_NONNULL_BEGIN
@ -36,6 +37,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
return @"OWSMessageCellType_DownloadingAttachment";
case OWSMessageCellType_Unknown:
return @"OWSMessageCellType_Unknown";
case OWSMessageCellType_ContactShare:
return @"OWSMessageCellType_ContactShare";
}
}
@ -62,6 +65,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
@property (nonatomic, readonly, nullable) NSString *quotedRecipientId;
@property (nonatomic, nullable) TSAttachmentStream *attachmentStream;
@property (nonatomic, nullable) TSAttachmentPointer *attachmentPointer;
@property (nonatomic, nullable) OWSContact *contactShare;
@property (nonatomic) CGSize mediaSize;
@end
@ -401,6 +405,11 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
self.hasViewState = YES;
TSMessage *message = (TSMessage *)self.interaction;
if (message.contactShare) {
self.contactShare = message.contactShare;
self.messageCellType = OWSMessageCellType_ContactShare;
return;
}
TSAttachment *_Nullable attachment = [self firstAttachmentIfAnyOfMessage:message transaction:transaction];
if (attachment) {
if ([attachment isKindOfClass:[TSAttachmentStream class]]) {
@ -712,6 +721,11 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
OWSFail(@"%@ No text to copy", self.logTag);
break;
}
case OWSMessageCellType_ContactShare: {
// TODO: Implement copy contact.
OWSFail(@"%@ Not implemented yet", self.logTag);
break;
}
}
}
@ -720,7 +734,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
switch (self.messageCellType) {
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: {
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_ContactShare: {
OWSFail(@"%@ No media to copy", self.logTag);
break;
}
@ -802,6 +817,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_ContactShare:
return NO;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
@ -824,6 +840,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_ContactShare:
OWSFail(@"%@ Cannot save text data.", self.logTag);
break;
case OWSMessageCellType_StillImage:
@ -879,6 +896,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_ContactShare:
return NO;
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:

View file

@ -97,7 +97,7 @@ NS_ASSUME_NONNULL_BEGIN
// Exemplary
[DebugUIMessages allFakeAction:thread],
[DebugUIMessages allFakeBackDatedAction:thread],
[DebugUIMessages allShareContactAction:thread],
[DebugUIMessages allContactShareAction:thread],
]]];
[items addObjectsFromArray:@[
@ -2658,7 +2658,7 @@ NS_ASSUME_NONNULL_BEGIN
[actions addObjectsFromArray:[self allFakeSequenceActions:thread includeLabels:includeLabels]];
[actions addObjectsFromArray:[self allFakeQuotedReplyActions:thread includeLabels:includeLabels]];
[actions addObjectsFromArray:[self allFakeBackDatedActions:thread includeLabels:includeLabels]];
[actions addObjectsFromArray:[self allShareContactActions:thread includeLabels:includeLabels]];
[actions addObjectsFromArray:[self allContactShareActions:thread includeLabels:includeLabels]];
return actions;
}
@ -2902,7 +2902,7 @@ NS_ASSUME_NONNULL_BEGIN
typedef OWSContact * (^OWSContactBlock)(void);
+ (DebugUIMessagesAction *)fakeShareContactMessageAction:(TSThread *)thread
+ (DebugUIMessagesAction *)fakeContactShareMessageAction:(TSThread *)thread
label:(NSString *)label
contactBlock:(OWSContactBlock)contactBlock
{
@ -2925,7 +2925,7 @@ typedef OWSContact * (^OWSContactBlock)(void);
}];
}
+ (NSArray<DebugUIMessagesAction *> *)allShareContactActions:(TSThread *)thread includeLabels:(BOOL)includeLabels
+ (NSArray<DebugUIMessagesAction *> *)allContactShareActions:(TSThread *)thread includeLabels:(BOOL)includeLabels
{
OWSAssert(thread);
@ -2937,7 +2937,7 @@ typedef OWSContact * (^OWSContactBlock)(void);
text:@"⚠️ Share Contact ⚠️"]];
}
[actions addObject:[self fakeShareContactMessageAction:thread
[actions addObject:[self fakeContactShareMessageAction:thread
label:@"Name & Number"
contactBlock:^{
OWSContact *contact = [OWSContact new];
@ -2950,7 +2950,7 @@ typedef OWSContact * (^OWSContactBlock)(void);
];
return contact;
}]];
[actions addObject:[self fakeShareContactMessageAction:thread
[actions addObject:[self fakeContactShareMessageAction:thread
label:@"Name & Email"
contactBlock:^{
OWSContact *contact = [OWSContact new];
@ -2963,7 +2963,7 @@ typedef OWSContact * (^OWSContactBlock)(void);
];
return contact;
}]];
[actions addObject:[self fakeShareContactMessageAction:thread
[actions addObject:[self fakeContactShareMessageAction:thread
label:@"Complicated"
contactBlock:^{
OWSContact *contact = [OWSContact new];
@ -2973,7 +2973,6 @@ typedef OWSContact * (^OWSContactBlock)(void);
contact.namePrefix = @"Ms.";
contact.nameSuffix = @"Esq.";
contact.organizationName = @"Falafel Hut";
contact.displayName = @"Ms. Alice Bob Carol Esq.";
OWSContactPhoneNumber *phoneNumber1 = [OWSContactPhoneNumber new];
phoneNumber1.phoneType = OWSContactPhoneType_Home;
@ -3028,12 +3027,12 @@ typedef OWSContact * (^OWSContactBlock)(void);
return actions;
}
+ (DebugUIMessagesAction *)allShareContactAction:(TSThread *)thread
+ (DebugUIMessagesAction *)allContactShareAction:(TSThread *)thread
{
OWSAssert(thread);
return [DebugUIMessagesGroupAction allGroupActionWithLabel:@"All Fake Share Contact"
subactions:[self allShareContactActions:thread includeLabels:YES]];
return [DebugUIMessagesGroupAction allGroupActionWithLabel:@"All Fake Contact Shares"
subactions:[self allContactShareActions:thread includeLabels:YES]];
}
#pragma mark -

View file

@ -84,8 +84,8 @@ NS_ASSUME_NONNULL_BEGIN
[self.payloadView autoPinLeadingToTrailingEdgeOfView:self.avatarView offset:self.avatarHSpacing];
[self.payloadView autoVCenterInSuperview];
// Ensure that the cell's contents never overflow the cell bounds.
//
// NOTE: It's critical that we pin to the superview top and bottom _edge_ and not _margin_.
// We pin pin to the superview _edge_ and not _margin_ for the purposes
// of overflow, so that changes to the margins do not trip these safe guards.
[self.payloadView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:0 relation:NSLayoutRelationGreaterThanOrEqual];
[self.payloadView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:0 relation:NSLayoutRelationGreaterThanOrEqual];
// We pin the payloadView traillingEdge later, as part of the "Unread Badge" logic.

View file

@ -748,7 +748,9 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
// Constrain to cell margins.
[stackView autoPinEdgeToSuperviewMargin:ALEdgeLeading relation:NSLayoutRelationGreaterThanOrEqual];
[stackView autoPinEdgeToSuperviewMargin:ALEdgeTrailing relation:NSLayoutRelationGreaterThanOrEqual];
// NOTE: It's critical that we pin to the superview top and bottom _edge_ and not _margin_.
// Ensure that the cell's contents never overflow the cell bounds.
// We pin pin to the superview _edge_ and not _margin_ for the purposes
// of overflow, so that changes to the margins do not trip these safe guards.
[stackView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:0 relation:NSLayoutRelationGreaterThanOrEqual];
[stackView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:0 relation:NSLayoutRelationGreaterThanOrEqual];

View file

@ -186,6 +186,28 @@ NS_ASSUME_NONNULL_BEGIN
return hasValue;
}
- (nullable NSString *)displayName
{
[self ensureDisplayName];
return _displayName;
}
- (void)ensureDisplayName
{
if (_displayName.length < 1) {
CNContact *_Nullable systemContact = [OWSContacts systemContactForContact:self];
_displayName = [CNContactFormatter stringFromContact:systemContact style:CNContactFormatterStyleFullName];
}
if (_displayName.length < 1) {
// Fall back to using the organization name.
_displayName = self.organizationName;
}
if (_displayName.length < 1) {
OWSProdLogAndFail(@"%@ could not derive a valid display name.", self.logTag);
}
}
@end
#pragma mark -
@ -318,6 +340,8 @@ NS_ASSUME_NONNULL_BEGIN
// @property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) NSData *imageData;
// @property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) NSData *thumbnailImageData;
[contact ensureDisplayName];
return contact;
}
@ -635,6 +659,8 @@ NS_ASSUME_NONNULL_BEGIN
// TODO: Avatar
[contact ensureDisplayName];
return contact;
}