Tweak generic attachments.

pull/1/head
Matthew Chen 7 years ago
parent 1623bf91ba
commit a0b612c64b

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "File@1x.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "File@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "File@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -1,12 +1,12 @@
// //
// Copyright (c) 2017 Open Whisper Systems. All rights reserved. // Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// //
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@class TSAttachmentStream; @class TSAttachmentStream;
@interface OWSGenericAttachmentView : UIView @interface OWSGenericAttachmentView : UIStackView
- (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream isIncoming:(BOOL)isIncoming; - (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream isIncoming:(BOOL)isIncoming;

@ -41,9 +41,9 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - #pragma mark -
- (CGFloat)iconHMargin - (CGFloat)hMargin
{ {
return 12.f; return 0.f;
} }
- (CGFloat)iconHSpacing - (CGFloat)iconHSpacing
@ -51,19 +51,19 @@ NS_ASSUME_NONNULL_BEGIN
return 8.f; return 8.f;
} }
+ (CGFloat)iconVMargin + (CGFloat)vMargin
{ {
return 12.f; return 0.f;
} }
- (CGFloat)iconVMargin - (CGFloat)vMargin
{ {
return [OWSGenericAttachmentView iconVMargin]; return [OWSGenericAttachmentView vMargin];
} }
+ (CGFloat)bubbleHeight + (CGFloat)bubbleHeight
{ {
return self.iconSize + self.iconVMargin * 2; return self.iconHeight + self.vMargin * 2;
} }
- (CGFloat)bubbleHeight - (CGFloat)bubbleHeight
@ -71,19 +71,14 @@ NS_ASSUME_NONNULL_BEGIN
return [OWSGenericAttachmentView bubbleHeight]; return [OWSGenericAttachmentView bubbleHeight];
} }
+ (CGFloat)iconSize + (CGFloat)iconHeight
{ {
return 44.f; return 48.f;
} }
- (CGFloat)iconSize - (CGFloat)iconHeight
{
return [OWSGenericAttachmentView iconSize];
}
- (CGFloat)vMargin
{ {
return 10.f; return [OWSGenericAttachmentView iconHeight];
} }
- (UIColor *)bubbleBackgroundColor - (UIColor *)bubbleBackgroundColor
@ -105,45 +100,27 @@ NS_ASSUME_NONNULL_BEGIN
{ {
UIColor *textColor = (self.isIncoming ? [UIColor colorWithWhite:0.2 alpha:1.f] : [UIColor whiteColor]); UIColor *textColor = (self.isIncoming ? [UIColor colorWithWhite:0.2 alpha:1.f] : [UIColor whiteColor]);
self.backgroundColor = self.bubbleBackgroundColor;
self.layoutMargins = UIEdgeInsetsZero; self.layoutMargins = UIEdgeInsetsZero;
self.axis = UILayoutConstraintAxisHorizontal;
self.alignment = UIStackViewAlignmentCenter;
self.spacing = self.iconHSpacing;
// TODO: Verify that this layout works in RTL. // attachment_file
const CGFloat kBubbleTailWidth = 6.f; UIImage *image = [UIImage imageNamed:@"generic-attachment"];
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
= (self.isIncoming ? [UIColor colorWithRGBHex:0x9e9e9e] : [self foregroundColorWithOpacity:0.15f]);
iconCircleView.layer.cornerRadius = self.iconSize * 0.5f;
[contentView addSubview:iconCircleView];
[iconCircleView autoPinLeadingToSuperviewMarginWithInset:self.iconHMargin];
[iconCircleView autoVCenterInSuperview];
[iconCircleView autoSetDimension:ALDimensionWidth toSize:self.iconSize];
[iconCircleView autoSetDimension:ALDimensionHeight toSize:self.iconSize];
UIImage *image = [UIImage imageNamed:@"attachment_file"];
OWSAssert(image); OWSAssert(image);
OWSAssert(image.size.height == self.iconHeight);
UIImageView *imageView = [UIImageView new]; UIImageView *imageView = [UIImageView new];
imageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; imageView.image = image;
imageView.tintColor = self.bubbleBackgroundColor; imageView.tintColor = self.bubbleBackgroundColor;
[iconCircleView addSubview:imageView]; [self addArrangedSubview:imageView];
[imageView autoCenterInSuperview]; [imageView setContentHuggingHigh];
const CGFloat kLabelHSpacing = self.iconHSpacing; UIStackView *labelsView = [UIStackView new];
UIView *labelsView = [UIView containerView]; labelsView.axis = UILayoutConstraintAxisVertical;
[contentView addSubview:labelsView]; labelsView.spacing = 2;
[labelsView autoPinLeadingToTrailingEdgeOfView:iconCircleView offset:kLabelHSpacing]; labelsView.alignment = UIStackViewAlignmentLeading;
[labelsView autoPinTrailingToSuperviewMarginWithInset:self.iconHMargin]; [self addArrangedSubview:labelsView];
[labelsView autoVCenterInSuperview];
const CGFloat kLabelVSpacing = 2;
NSString *topText = [self.attachmentStream.sourceFilename ows_stripped]; NSString *topText = [self.attachmentStream.sourceFilename ows_stripped];
if (topText.length < 1) { if (topText.length < 1) {
topText = [MIMETypeUtil fileExtensionForMIMEType:self.attachmentStream.contentType].uppercaseString; topText = [MIMETypeUtil fileExtensionForMIMEType:self.attachmentStream.contentType].uppercaseString;
@ -156,9 +133,7 @@ NS_ASSUME_NONNULL_BEGIN
topLabel.textColor = textColor; topLabel.textColor = textColor;
topLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; topLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
topLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(13.f, 15.f)]; topLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(13.f, 15.f)];
[labelsView addSubview:topLabel]; [labelsView addArrangedSubview:topLabel];
[topLabel autoPinEdgeToSuperviewEdge:ALEdgeTop];
[topLabel autoPinWidthToSuperview];
NSError *error; NSError *error;
unsigned long long fileSize = unsigned long long fileSize =
@ -170,10 +145,7 @@ NS_ASSUME_NONNULL_BEGIN
bottomLabel.textColor = [textColor colorWithAlphaComponent:0.85f]; bottomLabel.textColor = [textColor colorWithAlphaComponent:0.85f];
bottomLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; bottomLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
bottomLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)]; bottomLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)];
[labelsView addSubview:bottomLabel]; [labelsView addArrangedSubview:bottomLabel];
[bottomLabel autoPinWidthToSuperview];
[bottomLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:topLabel withOffset:kLabelVSpacing];
[bottomLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom];
} }
@end @end

@ -246,10 +246,10 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(self.viewItem.interaction); OWSAssert(self.viewItem.interaction);
OWSAssert([self.viewItem.interaction isKindOfClass:[TSMessage class]]); OWSAssert([self.viewItem.interaction isKindOfClass:[TSMessage class]]);
CGSize quotedMessageContentSize = [self quotedMessageSize]; NSValue *_Nullable quotedMessageSize = [self quotedMessageSize];
// TODO: // TODO:
CGSize bodyMediaContentSize = [self bodyMediaSize]; // CGSize bodyMediaContentSize = [self bodyMediaSize];
CGSize bodyTextContentSize = [self bodyTextSizeWithIncludeMargins:NO]; NSValue *_Nullable bodyTextSize = [self bodyTextSize];
[self.bubbleView addSubview:self.stackView]; [self.bubbleView addSubview:self.stackView];
[self.viewConstraints addObjectsFromArray:[self.stackView autoPinEdgesToSuperviewEdges]]; [self.viewConstraints addObjectsFromArray:[self.stackView autoPinEdgesToSuperviewEdges]];
@ -260,9 +260,11 @@ NS_ASSUME_NONNULL_BEGIN
[textViews addObject:self.senderNameLabel]; [textViews addObject:self.senderNameLabel];
} }
UIView *_Nullable topTextStackView = nil;
if (self.isQuotedReply) { if (self.isQuotedReply) {
// Flush any pending "text" subviews. // Flush any pending "text" subviews.
[self insertAnyTextViewsIntoStackView:textViews]; OWSAssert(!topTextStackView);
topTextStackView = [self insertAnyTextViewsIntoStackView:textViews];
[textViews removeAllObjects]; [textViews removeAllObjects];
BOOL isOutgoing = [self.viewItem.interaction isKindOfClass:TSOutgoingMessage.class]; BOOL isOutgoing = [self.viewItem.interaction isKindOfClass:TSOutgoingMessage.class];
@ -278,14 +280,14 @@ NS_ASSUME_NONNULL_BEGIN
self.quotedMessageView = quotedMessageView; self.quotedMessageView = quotedMessageView;
[quotedMessageView createContents]; [quotedMessageView createContents];
[self.stackView addArrangedSubview:quotedMessageView]; [self.stackView addArrangedSubview:quotedMessageView];
[self.viewConstraints OWSAssert(quotedMessageSize);
addObject:[quotedMessageView autoSetDimension:ALDimensionHeight toSize:quotedMessageContentSize.height]]; [self.viewConstraints addObject:[quotedMessageView autoSetDimension:ALDimensionHeight
toSize:quotedMessageSize.CGSizeValue.height]];
[self.bubbleView addPartnerView:quotedMessageView.boundsStrokeView]; [self.bubbleView addPartnerView:quotedMessageView.boundsStrokeView];
} }
UIView *_Nullable bodyMediaView = nil; UIView *_Nullable bodyMediaView = nil;
BOOL hasThumbnailForBodyMedia = NO;
switch (self.cellType) { switch (self.cellType) {
case OWSMessageCellType_Unknown: case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage: case OWSMessageCellType_TextMessage:
@ -294,17 +296,14 @@ NS_ASSUME_NONNULL_BEGIN
case OWSMessageCellType_StillImage: case OWSMessageCellType_StillImage:
OWSAssert(self.viewItem.attachmentStream); OWSAssert(self.viewItem.attachmentStream);
bodyMediaView = [self loadViewForStillImage]; bodyMediaView = [self loadViewForStillImage];
hasThumbnailForBodyMedia = YES;
break; break;
case OWSMessageCellType_AnimatedImage: case OWSMessageCellType_AnimatedImage:
OWSAssert(self.viewItem.attachmentStream); OWSAssert(self.viewItem.attachmentStream);
bodyMediaView = [self loadViewForAnimatedImage]; bodyMediaView = [self loadViewForAnimatedImage];
hasThumbnailForBodyMedia = YES;
break; break;
case OWSMessageCellType_Video: case OWSMessageCellType_Video:
OWSAssert(self.viewItem.attachmentStream); OWSAssert(self.viewItem.attachmentStream);
bodyMediaView = [self loadViewForVideo]; bodyMediaView = [self loadViewForVideo];
hasThumbnailForBodyMedia = YES;
break; break;
case OWSMessageCellType_Audio: case OWSMessageCellType_Audio:
OWSAssert(self.viewItem.attachmentStream); OWSAssert(self.viewItem.attachmentStream);
@ -325,19 +324,21 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(self.loadCellContentBlock); OWSAssert(self.loadCellContentBlock);
OWSAssert(self.unloadCellContentBlock); OWSAssert(self.unloadCellContentBlock);
// Flush any pending "text" subviews.
[self insertAnyTextViewsIntoStackView:textViews];
[textViews removeAllObjects];
bodyMediaView.clipsToBounds = YES; bodyMediaView.clipsToBounds = YES;
self.bodyMediaView = bodyMediaView; self.bodyMediaView = bodyMediaView;
bodyMediaView.userInteractionEnabled = NO; bodyMediaView.userInteractionEnabled = NO;
if (self.isMediaBeingSent) { if (self.isMediaBeingSent) {
// TODO:
bodyMediaView.layer.opacity = 0.75f; bodyMediaView.layer.opacity = 0.75f;
} }
if (hasThumbnailForBodyMedia) { if (self.hasBodyMediaWithThumbnail) {
// Flush any pending "text" subviews.
OWSAssert(!topTextStackView);
topTextStackView = [self insertAnyTextViewsIntoStackView:textViews];
[textViews removeAllObjects];
// The "body media" view casts a shadow "downward" onto adjacent views, // The "body media" view casts a shadow "downward" onto adjacent views,
// so we use a "proxy" view to take its place within the v-stack // so we use a "proxy" view to take its place within the v-stack
// view and then insert the body media view above its proxy so that // view and then insert the body media view above its proxy so that
@ -369,7 +370,8 @@ NS_ASSUME_NONNULL_BEGIN
self.mediaShadowView.layer.shadowOffset = CGSizeMake(0.f, 0.f); self.mediaShadowView.layer.shadowOffset = CGSizeMake(0.f, 0.f);
self.mediaShadowView.layer.shadowRadius = 0.5f; self.mediaShadowView.layer.shadowRadius = 0.5f;
} else { } else {
[self.stackView addArrangedSubview:bodyMediaView]; // [self.stackView addArrangedSubview:bodyMediaView];
[textViews addObject:bodyMediaView];
} }
} }
@ -379,8 +381,10 @@ NS_ASSUME_NONNULL_BEGIN
[self configureBodyTextView]; [self configureBodyTextView];
[textViews addObject:self.bodyTextView]; [textViews addObject:self.bodyTextView];
// TODO: Media?
OWSAssert(bodyTextSize);
[self.viewConstraints addObjectsFromArray:@[ [self.viewConstraints addObjectsFromArray:@[
[self.bodyTextView autoSetDimension:ALDimensionHeight toSize:bodyTextContentSize.height], [self.bodyTextView autoSetDimension:ALDimensionHeight toSize:bodyTextSize.CGSizeValue.height],
]]; ]];
UIView *_Nullable tapForMoreLabel = [self createTapForMoreLabelIfNecessary]; UIView *_Nullable tapForMoreLabel = [self createTapForMoreLabelIfNecessary];
@ -422,6 +426,8 @@ NS_ASSUME_NONNULL_BEGIN
}]; }];
[self updateBubbleColorWithBodyMediaView:bodyMediaView]; [self updateBubbleColorWithBodyMediaView:bodyMediaView];
[self logFrameLaterWithLabel:@"----- message bubble"];
} }
- (void)updateBubbleColorWithBodyMediaView:(nullable UIView *)bodyMediaView - (void)updateBubbleColorWithBodyMediaView:(nullable UIView *)bodyMediaView
@ -461,7 +467,7 @@ NS_ASSUME_NONNULL_BEGIN
return [self.bubbleFactory bubbleColorWithMessage:message]; return [self.bubbleFactory bubbleColorWithMessage:message];
} }
- (BOOL)canFooterOverlayMedia - (BOOL)hasBodyMediaWithThumbnail
{ {
switch (self.cellType) { switch (self.cellType) {
case OWSMessageCellType_Unknown: case OWSMessageCellType_Unknown:
@ -480,10 +486,15 @@ NS_ASSUME_NONNULL_BEGIN
} }
} }
- (void)insertAnyTextViewsIntoStackView:(NSArray<UIView *> *)textViews - (BOOL)canFooterOverlayMedia
{
return self.hasBodyMediaWithThumbnail;
}
- (nullable UIView *)insertAnyTextViewsIntoStackView:(NSArray<UIView *> *)textViews
{ {
if (textViews.count < 1) { if (textViews.count < 1) {
return; return nil;
} }
UIStackView *textStackView = [[UIStackView alloc] initWithArrangedSubviews:textViews]; UIStackView *textStackView = [[UIStackView alloc] initWithArrangedSubviews:textViews];
@ -497,6 +508,7 @@ NS_ASSUME_NONNULL_BEGIN
self.conversationStyle.textInsetBottom, self.conversationStyle.textInsetBottom,
self.conversationStyle.textInsetHorizontal); self.conversationStyle.textInsetHorizontal);
[self.stackView addArrangedSubview:textStackView]; [self.stackView addArrangedSubview:textStackView];
return textStackView;
} }
// We now eagerly create our view hierarchy (to do this exactly once per cell usage) // We now eagerly create our view hierarchy (to do this exactly once per cell usage)
@ -930,13 +942,13 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Measurement #pragma mark - Measurement
// Size of "message body" text, not quoted reply text. // Size of "message body" text, not quoted reply text.
- (CGSize)bodyTextSizeWithIncludeMargins:(BOOL)includeMargins - (nullable NSValue *)bodyTextSize
{ {
OWSAssert(self.conversationStyle); OWSAssert(self.conversationStyle);
OWSAssert(self.conversationStyle.maxMessageWidth > 0); OWSAssert(self.conversationStyle.maxMessageWidth > 0);
if (!self.hasBodyText) { if (!self.hasBodyText) {
return CGSizeZero; return nil;
} }
CGFloat hMargins = self.conversationStyle.textInsetHorizontal * 2; CGFloat hMargins = self.conversationStyle.textInsetHorizontal * 2;
@ -947,15 +959,10 @@ NS_ASSUME_NONNULL_BEGIN
const int kMaxIterations = 5; const int kMaxIterations = 5;
CGSize result = [self.bodyTextView compactSizeThatFitsMaxWidth:maxTextWidth maxIterations:kMaxIterations]; CGSize result = [self.bodyTextView compactSizeThatFitsMaxWidth:maxTextWidth maxIterations:kMaxIterations];
if (includeMargins) { return [NSValue valueWithCGSize:CGSizeCeil(result)];
result.width += hMargins;
result.height += (self.conversationStyle.textInsetTop + self.conversationStyle.textInsetBottom);
}
return CGSizeCeil(result);
} }
- (CGSize)bodyMediaSize - (nullable NSValue *)bodyMediaSize
{ {
OWSAssert(self.conversationStyle); OWSAssert(self.conversationStyle);
OWSAssert(self.conversationStyle.maxMessageWidth > 0); OWSAssert(self.conversationStyle.maxMessageWidth > 0);
@ -967,8 +974,7 @@ NS_ASSUME_NONNULL_BEGIN
case OWSMessageCellType_Unknown: case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage: case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: { case OWSMessageCellType_OversizeTextMessage: {
result = CGSizeZero; return nil;
break;
} }
case OWSMessageCellType_StillImage: case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage: case OWSMessageCellType_AnimatedImage:
@ -1024,10 +1030,10 @@ NS_ASSUME_NONNULL_BEGIN
break; break;
} }
return CGSizeCeil(result); return [NSValue valueWithCGSize:CGSizeCeil(result)];
} }
- (CGSize)quotedMessageSize - (nullable NSValue *)quotedMessageSize
{ {
OWSAssert(self.conversationStyle); OWSAssert(self.conversationStyle);
OWSAssert(self.conversationStyle.maxMessageWidth > 0); OWSAssert(self.conversationStyle.maxMessageWidth > 0);
@ -1035,7 +1041,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert([self.viewItem.interaction isKindOfClass:[TSMessage class]]); OWSAssert([self.viewItem.interaction isKindOfClass:[TSMessage class]]);
if (!self.isQuotedReply) { if (!self.isQuotedReply) {
return CGSizeZero; return nil;
} }
BOOL isOutgoing = [self.viewItem.interaction isKindOfClass:TSOutgoingMessage.class]; BOOL isOutgoing = [self.viewItem.interaction isKindOfClass:TSOutgoingMessage.class];
@ -1047,16 +1053,16 @@ NS_ASSUME_NONNULL_BEGIN
displayableQuotedText:displayableQuotedText displayableQuotedText:displayableQuotedText
isOutgoing:isOutgoing]; isOutgoing:isOutgoing];
CGSize result = [quotedMessageView sizeForMaxWidth:self.conversationStyle.maxMessageWidth]; CGSize result = [quotedMessageView sizeForMaxWidth:self.conversationStyle.maxMessageWidth];
return CGSizeCeil(result); return [NSValue valueWithCGSize:CGSizeCeil(result)];
} }
- (CGSize)senderNameSizeWithBodyMediaSize:(CGSize)bodyMediaSize includeMargins:(BOOL)includeMargins - (nullable NSValue *)senderNameSize
{ {
OWSAssert(self.conversationStyle); OWSAssert(self.conversationStyle);
OWSAssert(self.conversationStyle.maxMessageWidth > 0); OWSAssert(self.conversationStyle.maxMessageWidth > 0);
if (!self.shouldShowSenderName) { if (!self.shouldShowSenderName) {
return CGSizeZero; return nil;
} }
CGFloat hMargins = self.conversationStyle.textInsetHorizontal * 2; CGFloat hMargins = self.conversationStyle.textInsetHorizontal * 2;
@ -1064,18 +1070,7 @@ NS_ASSUME_NONNULL_BEGIN
[self configureSenderNameLabel]; [self configureSenderNameLabel];
CGSize result = CGSizeCeil([self.senderNameLabel sizeThatFits:CGSizeMake(maxTextWidth, CGFLOAT_MAX)]); CGSize result = CGSizeCeil([self.senderNameLabel sizeThatFits:CGSizeMake(maxTextWidth, CGFLOAT_MAX)]);
BOOL hasSeparateTextStackView = (self.isQuotedReply || bodyMediaSize.width > 0 || bodyMediaSize.height > 0); return [NSValue valueWithCGSize:result];
if (includeMargins) {
result.width += hMargins;
if (hasSeparateTextStackView) {
result.height += (self.conversationStyle.textInsetTop + self.conversationStyle.textInsetBottom);
} else {
result.height += self.textViewVSpacing;
}
}
return result;
} }
- (CGSize)measureSize - (CGSize)measureSize
@ -1087,24 +1082,56 @@ NS_ASSUME_NONNULL_BEGIN
CGSize cellSize = CGSizeZero; CGSize cellSize = CGSizeZero;
// TODO: Reflect "sender name" and "footer" layout. NSMutableArray<NSValue *> *textViewSizes = [NSMutableArray new];
// shouldFooterOverlayMedia = self.canFooterOverlayMedia;
CGSize quotedMessageSize = [self quotedMessageSize]; NSValue *_Nullable senderNameSize = [self senderNameSize];
cellSize.width = MAX(cellSize.width, quotedMessageSize.width); if (senderNameSize) {
cellSize.height += quotedMessageSize.height; [textViewSizes addObject:senderNameSize];
}
CGSize bodyMediaSize = [self bodyMediaSize]; NSValue *_Nullable quotedMessageSize = [self quotedMessageSize];
cellSize.width = MAX(cellSize.width, bodyMediaSize.width); if (quotedMessageSize) {
cellSize.height += bodyMediaSize.height; cellSize.width = MAX(cellSize.width, quotedMessageSize.CGSizeValue.width);
cellSize.height += quotedMessageSize.CGSizeValue.height;
}
CGSize senderNameSize = [self senderNameSizeWithBodyMediaSize:bodyMediaSize includeMargins:YES]; NSValue *_Nullable bodyMediaSize = [self bodyMediaSize];
cellSize.width = MAX(cellSize.width, senderNameSize.width); if (bodyMediaSize) {
cellSize.height += senderNameSize.height; if (self.hasBodyMediaWithThumbnail) {
cellSize.width = MAX(cellSize.width, bodyMediaSize.CGSizeValue.width);
cellSize.height += bodyMediaSize.CGSizeValue.height;
} else {
DDLogVerbose(@"%@ ---- bodyMediaSize: %@", self.logTag, bodyMediaSize);
[textViewSizes addObject:bodyMediaSize];
bodyMediaSize = nil;
}
}
CGSize textContentSize = [self bodyTextSizeWithIncludeMargins:YES]; if (bodyMediaSize || quotedMessageSize) {
cellSize.width = MAX(cellSize.width, textContentSize.width); if (textViewSizes.count > 0) {
cellSize.height += textContentSize.height; CGSize groupSize = [self sizeForTextViewGroup:textViewSizes];
cellSize.width = MAX(cellSize.width, groupSize.width);
cellSize.height += groupSize.height;
[textViewSizes removeAllObjects];
}
}
NSValue *_Nullable bodyTextSize = [self bodyTextSize];
if (bodyTextSize) {
[textViewSizes addObject:bodyTextSize];
}
BOOL shouldFooterOverlayMedia = (self.canFooterOverlayMedia && !self.hasBodyText);
if (!self.viewItem.shouldHideFooter && !shouldFooterOverlayMedia) {
CGSize footerSize = [self.footerView measureWithConversationViewItem:self.viewItem];
[textViewSizes addObject:[NSValue valueWithCGSize:footerSize]];
}
if (textViewSizes.count > 0) {
CGSize groupSize = [self sizeForTextViewGroup:textViewSizes];
cellSize.width = MAX(cellSize.width, groupSize.width);
cellSize.height += groupSize.height;
}
// Make sure the bubble is always wide enough to complete it's bubble shape. // Make sure the bubble is always wide enough to complete it's bubble shape.
cellSize.width = MAX(cellSize.width, OWSBubbleView.minWidth); cellSize.width = MAX(cellSize.width, OWSBubbleView.minWidth);
@ -1115,23 +1142,32 @@ NS_ASSUME_NONNULL_BEGIN
cellSize.height += self.tapForMoreHeight + self.textViewVSpacing; cellSize.height += self.tapForMoreHeight + self.textViewVSpacing;
} }
// TODO: Update this to reflect generic attachment, downloading attachments and
// contact shares.
BOOL shouldFooterOverlayMedia = (self.canFooterOverlayMedia && !self.hasBodyText);
if (!self.viewItem.shouldHideFooter && !shouldFooterOverlayMedia) {
CGSize footerSize = [self.footerView measureWithConversationViewItem:self.viewItem];
cellSize.width = MAX(cellSize.width, footerSize.width + self.conversationStyle.textInsetHorizontal * 2);
cellSize.height += self.textViewVSpacing + footerSize.height;
if (!self.hasBodyText) {
cellSize.height += (self.conversationStyle.textInsetTop + self.conversationStyle.textInsetBottom);
}
}
cellSize = CGSizeCeil(cellSize); cellSize = CGSizeCeil(cellSize);
DDLogVerbose(@"%@ ---- cellSize: %@", self.logTag, NSStringFromCGSize(cellSize));
return cellSize; return cellSize;
} }
- (CGSize)sizeForTextViewGroup:(NSArray<NSValue *> *)textViewSizes
{
OWSAssert(textViewSizes);
OWSAssert(textViewSizes.count > 0);
OWSAssert(self.conversationStyle);
OWSAssert(self.conversationStyle.maxMessageWidth > 0);
CGSize result = CGSizeZero;
for (NSValue *size in textViewSizes) {
result.width = MAX(result.width, size.CGSizeValue.width);
result.height += size.CGSizeValue.height;
}
result.height += self.textViewVSpacing * (textViewSizes.count - 1);
result.height += (self.conversationStyle.textInsetTop + self.conversationStyle.textInsetBottom);
result.width += self.conversationStyle.textInsetHorizontal * 2;
return result;
}
- (UIFont *)tapForMoreFont - (UIFont *)tapForMoreFont
{ {
return UIFont.ows_dynamicTypeCaption1Font; return UIFont.ows_dynamicTypeCaption1Font;

Loading…
Cancel
Save