From a0b612c64ba83890d5a0d8cb98ece44e79f5ccb2 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 27 Jun 2018 14:53:31 -0400 Subject: [PATCH 1/8] Tweak generic attachments. --- .../generic-attachment.imageset/Contents.json | 23 +++ .../generic-attachment.imageset/File@1x.png | Bin 0 -> 808 bytes .../generic-attachment.imageset/File@2x.png | Bin 0 -> 1859 bytes .../generic-attachment.imageset/File@3x.png | Bin 0 -> 3091 bytes .../Cells/OWSGenericAttachmentView.h | 4 +- .../Cells/OWSGenericAttachmentView.m | 82 +++----- .../Cells/OWSMessageBubbleView.m | 186 +++++++++++------- 7 files changed, 163 insertions(+), 132 deletions(-) create mode 100644 Signal/Images.xcassets/generic-attachment.imageset/Contents.json create mode 100644 Signal/Images.xcassets/generic-attachment.imageset/File@1x.png create mode 100644 Signal/Images.xcassets/generic-attachment.imageset/File@2x.png create mode 100644 Signal/Images.xcassets/generic-attachment.imageset/File@3x.png diff --git a/Signal/Images.xcassets/generic-attachment.imageset/Contents.json b/Signal/Images.xcassets/generic-attachment.imageset/Contents.json new file mode 100644 index 000000000..53e5e34c0 --- /dev/null +++ b/Signal/Images.xcassets/generic-attachment.imageset/Contents.json @@ -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" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/generic-attachment.imageset/File@1x.png b/Signal/Images.xcassets/generic-attachment.imageset/File@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..cd817594a1171f79cd89c312432c1acb3d49ae74 GIT binary patch literal 808 zcmV+@1K0eCP)Px%;z>k7R9Fe^n9r`#P!Psj5J8v3a=22`=59L4aHiAKnP0#5kes^CzPbB{i5vxSstACL zyfzOn!;4{z!EU8e>EOh2x!fQ*h5uD2V?psc0?`ZAYV~q78h!FS?>dNSo6RPe&*xX| zcKbDIJyvz~4I_QK2}};tE(jBo!%Qa(eYIKzlgY$uwOVgc?+KiBr3b?Qn@r|~PtQ?C zZh%1R^*WeNr@?SI^t#>dSx^Kb4BwqgDSpmKAly(eo6Um3V89Yyr_*_dx+g0|5HSIh zTmsAdlc6+_ zrOtUNJ~kTOCtX0GULkq(@udb-C={IWcx;3EfOqOB6mLbGtLzz8#&>;NabsNXVCg%H z#lpezcYNPJC;*3>Rc{ooQDi1nO|qF-r$Fg?NG{leb6d m{2ufW6{KDCSn_F)JFtHW&{^I)Y8A8q0000005(qcJ3!cp5&&m z;7K<_jG!j~J#fEl1JL`STmTR}LfKhkVn7>3POfU6GF@>uNly*jIK{8UhS_?vcCYiQ zafz3lL1_#-VNU~)7ADlLPIRdOs@Eh?=g`mp5Gs_v9ZCpQzN=L^yl{Wwuf65 zB|?*DAer0O!&@`fSa&3FSJ&4cHNJbdb@cP+&ywZkWtLlFA@sbBm6_SNmygfk?OV4N zq*Ld?+!Udy%xtFf)T8;O>joq`hr`L*-P!s5&ZTTzT>BHag+(SBjsA0LYU)@+L!+5I zJVWju$2G-1nortVk~btAy8rf%iL|(u)ZoN~_oLy6zdZ8RYQG!^zQENG2GB_GatI^!cCFNg{;@w0OUi7laTm8iny;~b8gnkO_oJlvj2r9Q)q)+4a$s_0JI=4|6#NpB)vmfiPx zVQM9jmfTm{1M^NU?g|SD;VMI+VUFqy0^rbaTI8!|c<`wFm2qL@XW@|0(8|*CLNQ_e znpiD`p#Q12eQQ;e3?ppqeV;FRQ(kT*SEo8g(M5#7p_BDEYi5*)k|@>(SXF;YNp z)(I{oQm@QY$clU@e(X?^4Jxj*45NT=D(@sf`R?vYrsG}OEm3RA^71jvrluc@dwY9l zv9KIsJMs*qWjsa12)Waak>m@+(jZ7gz*zL&vhhKHa-^xL>En};AEAdIQ>4Y!C+ChM z{!TpC(&(9F7Z51GWpDBb5(PUOTrOTs;|G71J$AOWUi~euM!DMkN*O3=93+t0191J6x*|iK~FVA>pY-4TJ{zP2wHz*>UuoH(TmpS1`ZDn zEXm-Rwp$a0@ZG?Gu&^*(K){!Xo<%!zS3SpUth1vo>6K8h%6{5bW18KLaFN6!gKpLB zfiDqz_rBIs8tbs$4PvNha%sv7X+_Uq@)Tz?NuS9Ik0AxfQ4}|3*5rd!Y`&uMrzfFp z#zF&Y1R}Arl%41Iho^fDdF2xwBvqipsP87DSmc{p`dJPNxg*KkIaz6-)!}m3?A465 zbmQ1xcN@Vyjrg!t()vZ2G1Jj|)3=T9RxDSS(v^D`K|OERjuiF#)0DbOiz9gyIccEH zTayx%G4*D7+kC7FX}&oK35@Riu#X8!$SHdDQr%B!OvcXu54Qg-X%)2u@q3}WJlk8N z!;sn-PCxfPDZ4eeJjpvt;jyUjA5Cg?77@MRbX{XYQw`B-ha(a=G_svQW9Sy%@W`nV zY|pC=oA$k$;B9h|LhE|kY){U$4k+r>)Z@TmrVQ#(t2KF>P|;Q1+X~k*&p!s424zRy Tt9H9|@`?b;9&JarxtZ`UA|`ej literal 0 HcmV?d00001 diff --git a/Signal/Images.xcassets/generic-attachment.imageset/File@3x.png b/Signal/Images.xcassets/generic-attachment.imageset/File@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..26c2172dbab39e20df37514f4b385c270aeb90b9 GIT binary patch literal 3091 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≪hONJhQLgDhJpWyDWaRP7vP(mWfi!G>UNuP4cxo_S z89C{9h*SNyOd{aLv^(P6(2l= zQNvTz*wwBnMLRobO@SUqTx8^?PKLDg1qjVHY@XYEY`UB(;#O1CV(z0}xp^)w*Af)s zpV45xs8A *)textViews +- (BOOL)canFooterOverlayMedia +{ + return self.hasBodyMediaWithThumbnail; +} + +- (nullable UIView *)insertAnyTextViewsIntoStackView:(NSArray *)textViews { if (textViews.count < 1) { - return; + return nil; } UIStackView *textStackView = [[UIStackView alloc] initWithArrangedSubviews:textViews]; @@ -497,6 +508,7 @@ NS_ASSUME_NONNULL_BEGIN self.conversationStyle.textInsetBottom, self.conversationStyle.textInsetHorizontal); [self.stackView addArrangedSubview:textStackView]; + return textStackView; } // 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 // Size of "message body" text, not quoted reply text. -- (CGSize)bodyTextSizeWithIncludeMargins:(BOOL)includeMargins +- (nullable NSValue *)bodyTextSize { OWSAssert(self.conversationStyle); OWSAssert(self.conversationStyle.maxMessageWidth > 0); if (!self.hasBodyText) { - return CGSizeZero; + return nil; } CGFloat hMargins = self.conversationStyle.textInsetHorizontal * 2; @@ -947,15 +959,10 @@ NS_ASSUME_NONNULL_BEGIN const int kMaxIterations = 5; CGSize result = [self.bodyTextView compactSizeThatFitsMaxWidth:maxTextWidth maxIterations:kMaxIterations]; - if (includeMargins) { - result.width += hMargins; - result.height += (self.conversationStyle.textInsetTop + self.conversationStyle.textInsetBottom); - } - - return CGSizeCeil(result); + return [NSValue valueWithCGSize:CGSizeCeil(result)]; } -- (CGSize)bodyMediaSize +- (nullable NSValue *)bodyMediaSize { OWSAssert(self.conversationStyle); OWSAssert(self.conversationStyle.maxMessageWidth > 0); @@ -967,8 +974,7 @@ NS_ASSUME_NONNULL_BEGIN case OWSMessageCellType_Unknown: case OWSMessageCellType_TextMessage: case OWSMessageCellType_OversizeTextMessage: { - result = CGSizeZero; - break; + return nil; } case OWSMessageCellType_StillImage: case OWSMessageCellType_AnimatedImage: @@ -1024,10 +1030,10 @@ NS_ASSUME_NONNULL_BEGIN break; } - return CGSizeCeil(result); + return [NSValue valueWithCGSize:CGSizeCeil(result)]; } -- (CGSize)quotedMessageSize +- (nullable NSValue *)quotedMessageSize { OWSAssert(self.conversationStyle); OWSAssert(self.conversationStyle.maxMessageWidth > 0); @@ -1035,7 +1041,7 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert([self.viewItem.interaction isKindOfClass:[TSMessage class]]); if (!self.isQuotedReply) { - return CGSizeZero; + return nil; } BOOL isOutgoing = [self.viewItem.interaction isKindOfClass:TSOutgoingMessage.class]; @@ -1047,16 +1053,16 @@ NS_ASSUME_NONNULL_BEGIN displayableQuotedText:displayableQuotedText isOutgoing:isOutgoing]; 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.maxMessageWidth > 0); if (!self.shouldShowSenderName) { - return CGSizeZero; + return nil; } CGFloat hMargins = self.conversationStyle.textInsetHorizontal * 2; @@ -1064,18 +1070,7 @@ NS_ASSUME_NONNULL_BEGIN [self configureSenderNameLabel]; CGSize result = CGSizeCeil([self.senderNameLabel sizeThatFits:CGSizeMake(maxTextWidth, CGFLOAT_MAX)]); - BOOL hasSeparateTextStackView = (self.isQuotedReply || bodyMediaSize.width > 0 || bodyMediaSize.height > 0); - - if (includeMargins) { - result.width += hMargins; - - if (hasSeparateTextStackView) { - result.height += (self.conversationStyle.textInsetTop + self.conversationStyle.textInsetBottom); - } else { - result.height += self.textViewVSpacing; - } - } - return result; + return [NSValue valueWithCGSize:result]; } - (CGSize)measureSize @@ -1087,24 +1082,56 @@ NS_ASSUME_NONNULL_BEGIN CGSize cellSize = CGSizeZero; - // TODO: Reflect "sender name" and "footer" layout. - // shouldFooterOverlayMedia = self.canFooterOverlayMedia; + NSMutableArray *textViewSizes = [NSMutableArray new]; - CGSize quotedMessageSize = [self quotedMessageSize]; - cellSize.width = MAX(cellSize.width, quotedMessageSize.width); - cellSize.height += quotedMessageSize.height; + NSValue *_Nullable senderNameSize = [self senderNameSize]; + if (senderNameSize) { + [textViewSizes addObject:senderNameSize]; + } - CGSize bodyMediaSize = [self bodyMediaSize]; - cellSize.width = MAX(cellSize.width, bodyMediaSize.width); - cellSize.height += bodyMediaSize.height; + NSValue *_Nullable quotedMessageSize = [self quotedMessageSize]; + if (quotedMessageSize) { + cellSize.width = MAX(cellSize.width, quotedMessageSize.CGSizeValue.width); + cellSize.height += quotedMessageSize.CGSizeValue.height; + } - CGSize senderNameSize = [self senderNameSizeWithBodyMediaSize:bodyMediaSize includeMargins:YES]; - cellSize.width = MAX(cellSize.width, senderNameSize.width); - cellSize.height += senderNameSize.height; + NSValue *_Nullable bodyMediaSize = [self bodyMediaSize]; + if (bodyMediaSize) { + 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]; - cellSize.width = MAX(cellSize.width, textContentSize.width); - cellSize.height += textContentSize.height; + if (bodyMediaSize || quotedMessageSize) { + if (textViewSizes.count > 0) { + 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. cellSize.width = MAX(cellSize.width, OWSBubbleView.minWidth); @@ -1115,23 +1142,32 @@ NS_ASSUME_NONNULL_BEGIN 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); + DDLogVerbose(@"%@ ---- cellSize: %@", self.logTag, NSStringFromCGSize(cellSize)); + return cellSize; } +- (CGSize)sizeForTextViewGroup:(NSArray *)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 { return UIFont.ows_dynamicTypeCaption1Font; From dc79d302c6b87ccc5e1e387f7d885e5d65c583ac Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 27 Jun 2018 15:13:15 -0400 Subject: [PATCH 2/8] Tweak audio messages. --- .../Cells/OWSAudioMessageView.h | 2 +- .../Cells/OWSAudioMessageView.m | 95 +++++++++---------- .../Cells/OWSGenericAttachmentView.m | 32 +++++-- .../Cells/OWSMessageBubbleView.m | 23 +---- 4 files changed, 75 insertions(+), 77 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.h b/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.h index d96257833..065e69c90 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.h +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.h @@ -9,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN @class ConversationViewItem; @class TSAttachmentStream; -@interface OWSAudioMessageView : UIView +@interface OWSAudioMessageView : UIStackView - (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream isIncoming:(BOOL)isIncoming diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m index 98a9403af..bcb003e5e 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m @@ -93,13 +93,14 @@ NS_ASSUME_NONNULL_BEGIN - (void)setAudioIcon:(UIImage *)icon iconColor:(UIColor *)iconColor { + OWSAssert(icon.size.height == self.iconSize); + icon = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [_audioPlayPauseButton setImage:icon forState:UIControlStateNormal]; [_audioPlayPauseButton setImage:icon forState:UIControlStateDisabled]; _audioPlayPauseButton.imageView.tintColor = self.bubbleBackgroundColor; _audioPlayPauseButton.backgroundColor = iconColor; - _audioPlayPauseButton.layer.cornerRadius - = MIN(_audioPlayPauseButton.bounds.size.width, _audioPlayPauseButton.bounds.size.height) * 0.5f; + _audioPlayPauseButton.layer.cornerRadius = self.iconSize * 0.5f; } - (void)setAudioIconToPlay @@ -127,29 +128,33 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - -- (CGFloat)audioIconHMargin +- (CGFloat)hMargin { - return 12.f; + return 0.f; } -- (CGFloat)audioIconHSpacing +- (CGFloat)hSpacing { return 8.f; } -+ (CGFloat)audioIconVMargin ++ (CGFloat)vMargin { - return 12.f; + return 0.f; } -- (CGFloat)audioIconVMargin +- (CGFloat)vMargin { - return [OWSAudioMessageView audioIconVMargin]; + return [OWSAudioMessageView vMargin]; } + (CGFloat)bubbleHeight { - return self.iconSize + self.audioIconVMargin * 2; + CGFloat iconHeight = self.iconSize; + CGFloat labelsHeight = ([OWSAudioMessageView labelFont].lineHeight * 2 + + [OWSAudioMessageView audioProgressViewHeight] + [OWSAudioMessageView labelVSpacing] * 2); + CGFloat contentHeight = MAX(iconHeight, labelsHeight); + return contentHeight + self.vMargin * 2; } - (CGFloat)bubbleHeight @@ -195,36 +200,21 @@ NS_ASSUME_NONNULL_BEGIN { UIColor *textColor = [self audioTextColor]; - self.backgroundColor = self.bubbleBackgroundColor; - 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.audioIconVMargin]; - [contentView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:self.audioIconVMargin]; + self.axis = UILayoutConstraintAxisHorizontal; + self.alignment = UIStackViewAlignmentCenter; + self.spacing = self.hSpacing; _audioPlayPauseButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.audioPlayPauseButton.enabled = NO; - [contentView addSubview:self.audioPlayPauseButton]; - [self.audioPlayPauseButton autoPinLeadingToSuperviewMarginWithInset:self.audioIconHMargin]; - [self.audioPlayPauseButton autoVCenterInSuperview]; - [self.audioPlayPauseButton autoSetDimension:ALDimensionWidth toSize:self.iconSize]; - [self.audioPlayPauseButton autoSetDimension:ALDimensionHeight toSize:self.iconSize]; - - const CGFloat kLabelHSpacing = self.audioIconHSpacing; + [self addArrangedSubview:self.audioPlayPauseButton]; + [self.audioPlayPauseButton setContentHuggingHigh]; - UIView *labelsView = [UIView containerView]; - [contentView addSubview:labelsView]; - [labelsView autoPinLeadingToTrailingEdgeOfView:self.audioPlayPauseButton offset:kLabelHSpacing]; - [labelsView autoPinTrailingToSuperviewMarginWithInset:self.audioIconHMargin]; - [labelsView autoVCenterInSuperview]; + UIStackView *labelsView = [UIStackView new]; + labelsView.axis = UILayoutConstraintAxisVertical; + labelsView.spacing = [OWSAudioMessageView labelVSpacing]; + labelsView.alignment = UIStackViewAlignmentFill; + [self addArrangedSubview:labelsView]; - const CGFloat kLabelVSpacing = 2; NSString *filename = self.attachmentStream.sourceFilename; if (!filename) { filename = [[self.attachmentStream filePath] lastPathComponent]; @@ -243,34 +233,41 @@ NS_ASSUME_NONNULL_BEGIN topLabel.text = topText; topLabel.textColor = [textColor colorWithAlphaComponent:0.85f]; topLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - topLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)]; - [labelsView addSubview:topLabel]; - [topLabel autoPinEdgeToSuperviewEdge:ALEdgeTop]; - [topLabel autoPinWidthToSuperview]; + topLabel.font = [OWSAudioMessageView labelFont]; + [labelsView addArrangedSubview:topLabel]; - const CGFloat kAudioProgressViewHeight = 12.f; AudioProgressView *audioProgressView = [AudioProgressView new]; self.audioProgressView = audioProgressView; [self updateAudioProgressView]; - [labelsView addSubview:audioProgressView]; - [audioProgressView autoPinWidthToSuperview]; - [audioProgressView autoSetDimension:ALDimensionHeight toSize:kAudioProgressViewHeight]; - [audioProgressView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:topLabel withOffset:kLabelVSpacing]; + [labelsView addArrangedSubview:audioProgressView]; + [audioProgressView autoSetDimension:ALDimensionHeight toSize:[OWSAudioMessageView audioProgressViewHeight]]; UILabel *bottomLabel = [UILabel new]; self.audioBottomLabel = bottomLabel; [self updateAudioBottomLabel]; bottomLabel.textColor = [textColor colorWithAlphaComponent:0.85f]; bottomLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - bottomLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)]; - [labelsView addSubview:bottomLabel]; - [bottomLabel autoPinWidthToSuperview]; - [bottomLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:audioProgressView withOffset:kLabelVSpacing]; - [bottomLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom]; + bottomLabel.font = [OWSAudioMessageView labelFont]; + [labelsView addArrangedSubview:bottomLabel]; [self updateContents]; } ++ (CGFloat)audioProgressViewHeight +{ + return 12.f; +} + ++ (UIFont *)labelFont +{ + return [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)]; +} + ++ (CGFloat)labelVSpacing +{ + return 2.f; +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSGenericAttachmentView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSGenericAttachmentView.m index 78599afb4..0e44ce564 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSGenericAttachmentView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSGenericAttachmentView.m @@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN return 0.f; } -- (CGFloat)iconHSpacing +- (CGFloat)hSpacing { return 8.f; } @@ -63,7 +63,11 @@ NS_ASSUME_NONNULL_BEGIN + (CGFloat)bubbleHeight { - return self.iconHeight + self.vMargin * 2; + CGFloat iconHeight = self.iconHeight; + CGFloat labelsHeight = ([OWSGenericAttachmentView topLabelFont].lineHeight + + [OWSGenericAttachmentView bottomLabelFont].lineHeight + [OWSGenericAttachmentView labelVSpacing]); + CGFloat contentHeight = MAX(iconHeight, labelsHeight); + return contentHeight + self.vMargin * 2; } - (CGFloat)bubbleHeight @@ -100,10 +104,9 @@ NS_ASSUME_NONNULL_BEGIN { UIColor *textColor = (self.isIncoming ? [UIColor colorWithWhite:0.2 alpha:1.f] : [UIColor whiteColor]); - self.layoutMargins = UIEdgeInsetsZero; self.axis = UILayoutConstraintAxisHorizontal; self.alignment = UIStackViewAlignmentCenter; - self.spacing = self.iconHSpacing; + self.spacing = self.hSpacing; // attachment_file UIImage *image = [UIImage imageNamed:@"generic-attachment"]; @@ -117,7 +120,7 @@ NS_ASSUME_NONNULL_BEGIN UIStackView *labelsView = [UIStackView new]; labelsView.axis = UILayoutConstraintAxisVertical; - labelsView.spacing = 2; + labelsView.spacing = [OWSGenericAttachmentView labelVSpacing]; labelsView.alignment = UIStackViewAlignmentLeading; [self addArrangedSubview:labelsView]; @@ -132,7 +135,7 @@ NS_ASSUME_NONNULL_BEGIN topLabel.text = topText; topLabel.textColor = textColor; topLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - topLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(13.f, 15.f)]; + topLabel.font = [OWSGenericAttachmentView bottomLabelFont]; [labelsView addArrangedSubview:topLabel]; NSError *error; @@ -144,10 +147,25 @@ NS_ASSUME_NONNULL_BEGIN bottomLabel.text = bottomText; bottomLabel.textColor = [textColor colorWithAlphaComponent:0.85f]; bottomLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - bottomLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)]; + bottomLabel.font = [OWSGenericAttachmentView bottomLabelFont]; [labelsView addArrangedSubview:bottomLabel]; } ++ (UIFont *)topLabelFont +{ + return [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(13.f, 15.f)]; +} + ++ (UIFont *)bottomLabelFont +{ + return [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)]; +} + ++ (CGFloat)labelVSpacing +{ + return 2.f; +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m index 31c0d62d9..9116fd033 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m @@ -425,31 +425,14 @@ NS_ASSUME_NONNULL_BEGIN ]]; }]; - [self updateBubbleColorWithBodyMediaView:bodyMediaView]; + [self updateBubbleColor]; [self logFrameLaterWithLabel:@"----- message bubble"]; } -- (void)updateBubbleColorWithBodyMediaView:(nullable UIView *)bodyMediaView +- (void)updateBubbleColor { - OWSAssert([self.viewItem.interaction isKindOfClass:[TSMessage class]]); - - BOOL hasOnlyBodyMediaView = NO; - switch (self.cellType) { - case OWSMessageCellType_Unknown: - case OWSMessageCellType_TextMessage: - case OWSMessageCellType_OversizeTextMessage: - case OWSMessageCellType_GenericAttachment: - case OWSMessageCellType_DownloadingAttachment: - case OWSMessageCellType_ContactShare: - break; - case OWSMessageCellType_StillImage: - case OWSMessageCellType_AnimatedImage: - case OWSMessageCellType_Audio: - case OWSMessageCellType_Video: - hasOnlyBodyMediaView = (bodyMediaView && self.stackView.subviews.count == 1); - break; - } + BOOL hasOnlyBodyMediaView = ([self hasBodyMediaWithThumbnail] && self.stackView.subviews.count == 1); if (!hasOnlyBodyMediaView) { self.bubbleView.bubbleColor = self.bubbleColor; } else { From 3c4d14034b2cc200bd9e5fa27d6c3ffb609db215 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 27 Jun 2018 15:32:28 -0400 Subject: [PATCH 3/8] Tweak contact shares. --- .../ConversationView/Cells/OWSBubbleView.m | 2 + .../Cells/OWSMessageBubbleView.m | 89 ++++++++++++------- 2 files changed, 61 insertions(+), 30 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSBubbleView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSBubbleView.m index 5ba4bde79..db7795629 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSBubbleView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSBubbleView.m @@ -29,6 +29,8 @@ const CGFloat kOWSMessageCellCornerRadius = 16; return self; } + self.layoutMargins = UIEdgeInsetsZero; + self.shapeLayer = [CAShapeLayer new]; [self.layer addSublayer:self.shapeLayer]; diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m index 9116fd033..381353023 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m @@ -27,6 +27,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) OWSBubbleShapeView *mediaClipView; +@property (nonatomic) OWSBubbleShapeView *bubbleStrokeView; + @property (nonatomic) UIStackView *stackView; @property (nonatomic) UILabel *senderNameLabel; @@ -81,6 +83,7 @@ NS_ASSUME_NONNULL_BEGIN self.mediaShadowView = [OWSBubbleShapeView bubbleShadowView]; self.mediaClipView = [OWSBubbleShapeView bubbleClipView]; + self.bubbleStrokeView = [OWSBubbleShapeView bubbleDrawView]; self.stackView = [UIStackView new]; self.stackView.axis = UILayoutConstraintAxisVertical; @@ -333,44 +336,57 @@ NS_ASSUME_NONNULL_BEGIN bodyMediaView.layer.opacity = 0.75f; } - if (self.hasBodyMediaWithThumbnail) { + if (self.hasFullWidthMediaView) { // Flush any pending "text" subviews. OWSAssert(!topTextStackView); topTextStackView = [self insertAnyTextViewsIntoStackView:textViews]; [textViews removeAllObjects]; - // 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 - // view and then insert the body media view above its proxy so that - // it floats above the other content of the bubble view. + if (self.hasBodyMediaWithThumbnail) { + + // 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 + // view and then insert the body media view above its proxy so that + // it floats above the other content of the bubble view. - UIView *bodyProxyView = [UIView new]; - [self.stackView addArrangedSubview:bodyProxyView]; + UIView *bodyProxyView = [UIView new]; + [self.stackView addArrangedSubview:bodyProxyView]; - [self addSubview:self.mediaShadowView]; - [self.mediaShadowView autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:bodyProxyView]; - [self.mediaShadowView autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:bodyProxyView]; - [self.mediaShadowView autoPinEdge:ALEdgeLeading toEdge:ALEdgeLeading ofView:bodyProxyView]; - [self.mediaShadowView autoPinEdge:ALEdgeTrailing toEdge:ALEdgeTrailing ofView:bodyProxyView]; + [self addSubview:self.mediaShadowView]; + [self.mediaShadowView autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:bodyProxyView]; + [self.mediaShadowView autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:bodyProxyView]; + [self.mediaShadowView autoPinEdge:ALEdgeLeading toEdge:ALEdgeLeading ofView:bodyProxyView]; + [self.mediaShadowView autoPinEdge:ALEdgeTrailing toEdge:ALEdgeTrailing ofView:bodyProxyView]; - [self.mediaShadowView addSubview:self.mediaClipView]; - [self.mediaClipView autoPinToSuperviewEdges]; + [self.mediaShadowView addSubview:self.mediaClipView]; + [self.mediaClipView autoPinToSuperviewEdges]; - [self.mediaClipView addSubview:bodyMediaView]; - [bodyMediaView autoPinToSuperviewEdges]; + [self.mediaClipView addSubview:bodyMediaView]; + [bodyMediaView autoPinToSuperviewEdges]; - [self.bubbleView addPartnerView:self.mediaClipView]; - [self.bubbleView addPartnerView:self.mediaShadowView]; + [self.bubbleView addPartnerView:self.mediaClipView]; + [self.bubbleView addPartnerView:self.mediaShadowView]; + + // TODO: Constants + // TODO: What's the difference between an inner and outer shadow? + self.mediaShadowView.fillColor = self.bubbleColor; + self.mediaShadowView.layer.shadowColor = [UIColor blackColor].CGColor; + self.mediaShadowView.layer.shadowOpacity = 0.12f; + self.mediaShadowView.layer.shadowOffset = CGSizeMake(0.f, 0.f); + self.mediaShadowView.layer.shadowRadius = 0.5f; + } else { + OWSAssert(self.cellType == OWSMessageCellType_ContactShare); - // TODO: Constants - // TODO: What's the difference between an inner and outer shadow? - self.mediaShadowView.fillColor = self.bubbleColor; - self.mediaShadowView.layer.shadowColor = [UIColor blackColor].CGColor; - self.mediaShadowView.layer.shadowOpacity = 0.12f; - self.mediaShadowView.layer.shadowOffset = CGSizeMake(0.f, 0.f); - self.mediaShadowView.layer.shadowRadius = 0.5f; + [self.stackView addArrangedSubview:bodyMediaView]; + + // TODO: Constants. + self.bubbleStrokeView.strokeColor = [UIColor lightGrayColor]; + self.bubbleStrokeView.strokeThickness = 1.f; + [self.bubbleView addSubview:self.bubbleStrokeView]; + [self.bubbleStrokeView autoPinToSuperviewEdges]; + [self.bubbleView addPartnerView:self.bubbleStrokeView]; + } } else { - // [self.stackView addArrangedSubview:bodyMediaView]; [textViews addObject:bodyMediaView]; } } @@ -432,7 +448,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateBubbleColor { - BOOL hasOnlyBodyMediaView = ([self hasBodyMediaWithThumbnail] && self.stackView.subviews.count == 1); + BOOL hasOnlyBodyMediaView = ([self hasFullWidthMediaView] && self.stackView.subviews.count == 1); if (!hasOnlyBodyMediaView) { self.bubbleView.bubbleColor = self.bubbleColor; } else { @@ -469,11 +485,25 @@ NS_ASSUME_NONNULL_BEGIN } } +- (BOOL)hasFullWidthMediaView +{ + return (self.hasBodyMediaWithThumbnail || self.cellType == OWSMessageCellType_ContactShare); +} + +// Returns YES if there is a footer displayed _at the bottom_ +// of the message bubble (as opposed to overlaid on a body media +// thumbnail). - (BOOL)canFooterOverlayMedia { return self.hasBodyMediaWithThumbnail; } +- (BOOL)hasBottomFooter +{ + BOOL shouldFooterOverlayMedia = (self.canFooterOverlayMedia && !self.hasBodyText); + return !self.viewItem.shouldHideFooter && !shouldFooterOverlayMedia; +} + - (nullable UIView *)insertAnyTextViewsIntoStackView:(NSArray *)textViews { if (textViews.count < 1) { @@ -1080,7 +1110,7 @@ NS_ASSUME_NONNULL_BEGIN NSValue *_Nullable bodyMediaSize = [self bodyMediaSize]; if (bodyMediaSize) { - if (self.hasBodyMediaWithThumbnail) { + if (self.hasFullWidthMediaView) { cellSize.width = MAX(cellSize.width, bodyMediaSize.CGSizeValue.width); cellSize.height += bodyMediaSize.CGSizeValue.height; } else { @@ -1104,8 +1134,7 @@ NS_ASSUME_NONNULL_BEGIN [textViewSizes addObject:bodyTextSize]; } - BOOL shouldFooterOverlayMedia = (self.canFooterOverlayMedia && !self.hasBodyText); - if (!self.viewItem.shouldHideFooter && !shouldFooterOverlayMedia) { + if (self.hasBottomFooter) { CGSize footerSize = [self.footerView measureWithConversationViewItem:self.viewItem]; [textViewSizes addObject:[NSValue valueWithCGSize:footerSize]]; } From 2b457c6499ba3f4c76f44a48d98572b9957ba64d Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 27 Jun 2018 15:42:05 -0400 Subject: [PATCH 4/8] Tweak contact shares. --- SignalMessaging/Views/ContactCellView.h | 2 +- SignalMessaging/Views/ContactCellView.m | 22 ++++++---------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/SignalMessaging/Views/ContactCellView.h b/SignalMessaging/Views/ContactCellView.h index 72797009f..93c1b4675 100644 --- a/SignalMessaging/Views/ContactCellView.h +++ b/SignalMessaging/Views/ContactCellView.h @@ -11,7 +11,7 @@ extern const CGFloat kContactCellAvatarTextMargin; @class SignalAccount; @class TSThread; -@interface ContactCellView : UIView +@interface ContactCellView : UIStackView @property (nonatomic, nullable) NSString *accessoryMessage; diff --git a/SignalMessaging/Views/ContactCellView.m b/SignalMessaging/Views/ContactCellView.m index a0c756657..e353063e1 100644 --- a/SignalMessaging/Views/ContactCellView.m +++ b/SignalMessaging/Views/ContactCellView.m @@ -84,22 +84,12 @@ const CGFloat kContactCellAvatarTextMargin = 12; [self.nameContainerView setContentHuggingHorizontalLow]; [self.accessoryViewContainer setContentHuggingHorizontalHigh]; - UIStackView *hStackView = [[UIStackView alloc] initWithArrangedSubviews:@[ - self.avatarView, - self.nameContainerView, - self.accessoryViewContainer, - ]]; - hStackView.axis = UILayoutConstraintAxisHorizontal; - hStackView.spacing = kContactCellAvatarTextMargin; - hStackView.distribution = UIStackViewDistributionFill; - [self addSubview:hStackView]; - [hStackView autoVCenterInSuperview]; - [hStackView autoPinEdgeToSuperviewMargin:ALEdgeLeading]; - [hStackView autoPinEdgeToSuperviewMargin:ALEdgeTrailing]; - - // Ensure that the cell's contents never overflow the cell bounds. - [hStackView autoPinEdgeToSuperviewMargin:ALEdgeTop relation:NSLayoutRelationGreaterThanOrEqual]; - [hStackView autoPinEdgeToSuperviewMargin:ALEdgeBottom relation:NSLayoutRelationGreaterThanOrEqual]; + self.axis = UILayoutConstraintAxisHorizontal; + self.spacing = kContactCellAvatarTextMargin; + self.alignment = UIStackViewAlignmentCenter; + [self addArrangedSubview:self.avatarView]; + [self addArrangedSubview:self.nameContainerView]; + [self addArrangedSubview:self.accessoryViewContainer]; [self configureFonts]; } From 416a52b74a20a9a65b2a1d4730b14544509dc749 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 27 Jun 2018 16:00:44 -0400 Subject: [PATCH 5/8] Tweak contact shares. --- .../Cells/OWSAudioMessageView.m | 2 +- .../Cells/OWSContactShareView.m | 58 ++++++------------- .../Cells/OWSGenericAttachmentView.m | 6 +- 3 files changed, 23 insertions(+), 43 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m index bcb003e5e..79cbe3ab9 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m @@ -260,7 +260,7 @@ NS_ASSUME_NONNULL_BEGIN + (UIFont *)labelFont { - return [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)]; + return [UIFont ows_dynamicTypeCaption2Font]; } + (CGFloat)labelVSpacing diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSContactShareView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSContactShareView.m index 2e3323cec..ca6c04e97 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSContactShareView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSContactShareView.m @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - -- (CGFloat)iconHMargin +- (CGFloat)hMargin { return 12.f; } @@ -143,11 +143,6 @@ NS_ASSUME_NONNULL_BEGIN return 10.f; } -- (UIColor *)bubbleBackgroundColor -{ - return self.isIncoming ? [UIColor ows_messageBubbleLightGrayColor] : [UIColor ows_materialBlueColor]; -} - + (UIFont *)nameFont { return [UIFont ows_dynamicTypeBodyFont]; @@ -175,18 +170,8 @@ NS_ASSUME_NONNULL_BEGIN - (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]; - AvatarImageView *avatarView = [AvatarImageView new]; avatarView.image = [self.contactShare getAvatarImageWithDiameter:self.iconSize contactsManager:self.contactsManager]; @@ -226,23 +211,23 @@ NS_ASSUME_NONNULL_BEGIN [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 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:avatarView]; - [stackView addArrangedSubview:labelsView]; - [stackView addArrangedSubview:disclosureImageView]; + UIStackView *hStackView = [UIStackView new]; + hStackView.axis = UILayoutConstraintAxisHorizontal; + hStackView.spacing = self.iconHSpacing; + hStackView.alignment = UIStackViewAlignmentCenter; + hStackView.layoutMarginsRelativeArrangement = YES; + hStackView.layoutMargins = UIEdgeInsetsMake(self.vMargin, self.hMargin, self.vMargin, self.hMargin); + [hStackView addArrangedSubview:avatarView]; + [hStackView addArrangedSubview:labelsView]; + [hStackView addArrangedSubview:disclosureImageView]; + + UIStackView *vStackView = [UIStackView new]; + vStackView.axis = UILayoutConstraintAxisVertical; + vStackView.spacing = 0; + vStackView.alignment = UIStackViewAlignmentFill; + [self addSubview:vStackView]; + [vStackView autoPinToSuperviewEdges]; + [vStackView addArrangedSubview:hStackView]; if ([OWSContactShareView hasAnyButton:self.contactShare contactsManager:self.contactsManager]) { UILabel *label = [UILabel new]; @@ -261,13 +246,8 @@ NS_ASSUME_NONNULL_BEGIN label.textColor = UIColor.ows_materialBlueColor; label.textAlignment = NSTextAlignmentCenter; label.backgroundColor = [UIColor whiteColor]; - [self addSubview:label]; - [label autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:contentView withOffset:self.vMargin]; - [label autoPinWidthToSuperview]; - [label autoPinEdgeToSuperviewEdge:ALEdgeBottom]; + [vStackView addArrangedSubview:label]; [label autoSetDimension:ALDimensionHeight toSize:OWSContactShareView.buttonHeight]; - } else { - [contentView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:self.vMargin]; } } diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSGenericAttachmentView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSGenericAttachmentView.m index 0e44ce564..fbde10c75 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSGenericAttachmentView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSGenericAttachmentView.m @@ -135,7 +135,7 @@ NS_ASSUME_NONNULL_BEGIN topLabel.text = topText; topLabel.textColor = textColor; topLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - topLabel.font = [OWSGenericAttachmentView bottomLabelFont]; + topLabel.font = [OWSGenericAttachmentView topLabelFont]; [labelsView addArrangedSubview:topLabel]; NSError *error; @@ -153,12 +153,12 @@ NS_ASSUME_NONNULL_BEGIN + (UIFont *)topLabelFont { - return [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(13.f, 15.f)]; + return [UIFont ows_dynamicTypeCaption1Font]; } + (UIFont *)bottomLabelFont { - return [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(11.f, 13.f)]; + return [UIFont ows_dynamicTypeCaption2Font]; } + (CGFloat)labelVSpacing From 3beac83a125da098a2e961f1744f2428164d3996 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 27 Jun 2018 17:07:14 -0400 Subject: [PATCH 6/8] Clean up ahead of PRs. --- .../ConversationView/Cells/OWSMessageBubbleView.m | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m index 381353023..813175a4f 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m @@ -263,11 +263,9 @@ NS_ASSUME_NONNULL_BEGIN [textViews addObject:self.senderNameLabel]; } - UIView *_Nullable topTextStackView = nil; if (self.isQuotedReply) { // Flush any pending "text" subviews. - OWSAssert(!topTextStackView); - topTextStackView = [self insertAnyTextViewsIntoStackView:textViews]; + [self insertAnyTextViewsIntoStackView:textViews]; [textViews removeAllObjects]; BOOL isOutgoing = [self.viewItem.interaction isKindOfClass:TSOutgoingMessage.class]; @@ -338,8 +336,7 @@ NS_ASSUME_NONNULL_BEGIN if (self.hasFullWidthMediaView) { // Flush any pending "text" subviews. - OWSAssert(!topTextStackView); - topTextStackView = [self insertAnyTextViewsIntoStackView:textViews]; + [self insertAnyTextViewsIntoStackView:textViews]; [textViews removeAllObjects]; if (self.hasBodyMediaWithThumbnail) { @@ -448,7 +445,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateBubbleColor { - BOOL hasOnlyBodyMediaView = ([self hasFullWidthMediaView] && self.stackView.subviews.count == 1); + BOOL hasOnlyBodyMediaView = (self.hasBodyMediaWithThumbnail && self.stackView.subviews.count == 1); if (!hasOnlyBodyMediaView) { self.bubbleView.bubbleColor = self.bubbleColor; } else { @@ -504,10 +501,10 @@ NS_ASSUME_NONNULL_BEGIN return !self.viewItem.shouldHideFooter && !shouldFooterOverlayMedia; } -- (nullable UIView *)insertAnyTextViewsIntoStackView:(NSArray *)textViews +- (void)insertAnyTextViewsIntoStackView:(NSArray *)textViews { if (textViews.count < 1) { - return nil; + return; } UIStackView *textStackView = [[UIStackView alloc] initWithArrangedSubviews:textViews]; @@ -521,7 +518,6 @@ NS_ASSUME_NONNULL_BEGIN self.conversationStyle.textInsetBottom, self.conversationStyle.textInsetHorizontal); [self.stackView addArrangedSubview:textStackView]; - return textStackView; } // We now eagerly create our view hierarchy (to do this exactly once per cell usage) From ffb1c3538302710094d08a2bb94c31c1a620a206 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 27 Jun 2018 17:08:46 -0400 Subject: [PATCH 7/8] Clean up ahead of PRs. --- .../ConversationView/Cells/OWSMessageBubbleView.m | 5 ----- .../ConversationView/Cells/OWSQuotedMessageView.m | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m index 813175a4f..1ff883d54 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m @@ -439,8 +439,6 @@ NS_ASSUME_NONNULL_BEGIN }]; [self updateBubbleColor]; - - [self logFrameLaterWithLabel:@"----- message bubble"]; } - (void)updateBubbleColor @@ -1110,7 +1108,6 @@ NS_ASSUME_NONNULL_BEGIN cellSize.width = MAX(cellSize.width, bodyMediaSize.CGSizeValue.width); cellSize.height += bodyMediaSize.CGSizeValue.height; } else { - DDLogVerbose(@"%@ ---- bodyMediaSize: %@", self.logTag, bodyMediaSize); [textViewSizes addObject:bodyMediaSize]; bodyMediaSize = nil; } @@ -1152,8 +1149,6 @@ NS_ASSUME_NONNULL_BEGIN cellSize = CGSizeCeil(cellSize); - DDLogVerbose(@"%@ ---- cellSize: %@", self.logTag, NSStringFromCGSize(cellSize)); - return cellSize; } diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSQuotedMessageView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSQuotedMessageView.m index 4c194cdfe..46d793978 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSQuotedMessageView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSQuotedMessageView.m @@ -176,6 +176,7 @@ NS_ASSUME_NONNULL_BEGIN quotedAttachmentView.backgroundColor = self.highlightColor; quotedAttachmentView.layer.cornerRadius = self.quotedAttachmentSize * 0.5f; + // TODO: Use new icons. UIImage *contentIcon = [UIImage imageNamed:(self.isAudioAttachment ? @"attachment_audio" : @"attachment_file")]; contentIcon = [contentIcon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; From 7634e3a44de4ea9e78a7f13978cef151a67c1eca Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 28 Jun 2018 13:16:59 -0400 Subject: [PATCH 8/8] Respond to CR. --- .../ConversationView/Cells/OWSAudioMessageView.m | 1 - .../ConversationView/Cells/OWSContactOffersCell.m | 2 -- .../ConversationView/Cells/OWSContactShareView.m | 1 - .../ConversationView/Cells/OWSMessageBubbleView.m | 5 ----- Signal/src/ViewControllers/HomeView/HomeViewCell.m | 2 ++ SignalMessaging/Views/ContactCellView.m | 1 - SignalMessaging/Views/ContactTableViewCell.m | 1 + 7 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m index 79cbe3ab9..02988d157 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSAudioMessageView.m @@ -212,7 +212,6 @@ NS_ASSUME_NONNULL_BEGIN UIStackView *labelsView = [UIStackView new]; labelsView.axis = UILayoutConstraintAxisVertical; labelsView.spacing = [OWSAudioMessageView labelVSpacing]; - labelsView.alignment = UIStackViewAlignmentFill; [self addArrangedSubview:labelsView]; NSString *filename = self.attachmentStream.sourceFilename; diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSContactOffersCell.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSContactOffersCell.m index adfc7894a..e7af806eb 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSContactOffersCell.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSContactOffersCell.m @@ -72,8 +72,6 @@ NS_ASSUME_NONNULL_BEGIN ]]; buttonStackView.axis = UILayoutConstraintAxisVertical; buttonStackView.spacing = self.vSpacing; - // Ensure all of the buttons have the same width. - buttonStackView.alignment = UIStackViewAlignmentFill; self.stackView = [[UIStackView alloc] initWithArrangedSubviews:@[ self.titleLabel, diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSContactShareView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSContactShareView.m index ca6c04e97..fcc555e68 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSContactShareView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSContactShareView.m @@ -224,7 +224,6 @@ NS_ASSUME_NONNULL_BEGIN UIStackView *vStackView = [UIStackView new]; vStackView.axis = UILayoutConstraintAxisVertical; vStackView.spacing = 0; - vStackView.alignment = UIStackViewAlignmentFill; [self addSubview:vStackView]; [vStackView autoPinToSuperviewEdges]; [vStackView addArrangedSubview:hStackView]; diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m index 1ff883d54..69f3256a0 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageBubbleView.m @@ -87,7 +87,6 @@ NS_ASSUME_NONNULL_BEGIN self.stackView = [UIStackView new]; self.stackView.axis = UILayoutConstraintAxisVertical; - self.stackView.alignment = UIStackViewAlignmentFill; self.senderNameLabel = [UILabel new]; @@ -485,9 +484,6 @@ NS_ASSUME_NONNULL_BEGIN return (self.hasBodyMediaWithThumbnail || self.cellType == OWSMessageCellType_ContactShare); } -// Returns YES if there is a footer displayed _at the bottom_ -// of the message bubble (as opposed to overlaid on a body media -// thumbnail). - (BOOL)canFooterOverlayMedia { return self.hasBodyMediaWithThumbnail; @@ -507,7 +503,6 @@ NS_ASSUME_NONNULL_BEGIN UIStackView *textStackView = [[UIStackView alloc] initWithArrangedSubviews:textViews]; textStackView.axis = UILayoutConstraintAxisVertical; - textStackView.alignment = UIStackViewAlignmentFill; // TODO: Review textStackView.spacing = self.textViewVSpacing; textStackView.layoutMarginsRelativeArrangement = YES; diff --git a/Signal/src/ViewControllers/HomeView/HomeViewCell.m b/Signal/src/ViewControllers/HomeView/HomeViewCell.m index 90228c83c..ffa9e4988 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewCell.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewCell.m @@ -122,6 +122,8 @@ NS_ASSUME_NONNULL_BEGIN [self.unreadLabel autoCenterInSuperview]; [self.unreadLabel setContentHuggingHigh]; [self.unreadLabel setCompressionResistanceHigh]; + + self.payloadView.userInteractionEnabled = NO; } - (void)dealloc diff --git a/SignalMessaging/Views/ContactCellView.m b/SignalMessaging/Views/ContactCellView.m index e353063e1..56b2026f8 100644 --- a/SignalMessaging/Views/ContactCellView.m +++ b/SignalMessaging/Views/ContactCellView.m @@ -78,7 +78,6 @@ const CGFloat kContactCellAvatarTextMargin = 12; self.subtitleLabel, ]]; self.nameContainerView.axis = UILayoutConstraintAxisVertical; - self.nameContainerView.alignment = UIStackViewAlignmentFill; [self.avatarView setContentHuggingHorizontalHigh]; [self.nameContainerView setContentHuggingHorizontalLow]; diff --git a/SignalMessaging/Views/ContactTableViewCell.m b/SignalMessaging/Views/ContactTableViewCell.m index 90d9e3316..c990bcb02 100644 --- a/SignalMessaging/Views/ContactTableViewCell.m +++ b/SignalMessaging/Views/ContactTableViewCell.m @@ -45,6 +45,7 @@ NS_ASSUME_NONNULL_BEGIN self.cellView = [ContactCellView new]; [self.contentView addSubview:self.cellView]; [self.cellView autoPinEdgesToSuperviewMargins]; + self.cellView.userInteractionEnabled = NO; } - (void)configureWithSignalAccount:(SignalAccount *)signalAccount contactsManager:(OWSContactsManager *)contactsManager