diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m index ad4d61411..1ebab0d74 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m @@ -43,7 +43,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) @property (nonatomic) UILabel *dateHeaderLabel; @property (nonatomic) OWSMessageTextView *bodyTextView; -@property (nonatomic) OWSMessageTextView *quotedTextView; +@property (nonatomic) UILabel *quotedTextView; @property (nonatomic, nullable) UIImageView *failedSendBadgeView; @property (nonatomic) UIView *footerView; @property (nonatomic) UILabel *footerLabel; @@ -101,7 +101,9 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) self.bodyTextView.dataDetectorTypes = (UIDataDetectorTypeLink | UIDataDetectorTypeAddress | UIDataDetectorTypeCalendarEvent); - self.quotedTextView = [self newTextView]; + self.quotedTextView = [UILabel new]; + self.quotedTextView.numberOfLines = 3; + self.quotedTextView.lineBreakMode = NSLineBreakByWordWrapping; self.footerLabel = [UILabel new]; self.footerLabel.font = [UIFont ows_regularFontWithSize:12.f]; @@ -418,22 +420,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) [self.bubbleView logFrameLaterWithLabel:@"bubbleView"]; [quotedMessageView logFrameLaterWithLabel:@"quotedMessageView"]; - - // BOOL shouldStrokeMediaView = [bodyMediaView isKindOfClass:[UIImageView class]]; - // if (shouldStrokeMediaView) { - // OWSBubbleStrokeView *bubbleStrokeView = [OWSBubbleStrokeView new]; - // bubbleStrokeView.strokeThickness = 1.f; - // bubbleStrokeView.strokeColor = [UIColor colorWithWhite:0.f alpha:0.1f]; - // bubbleStrokeView.bubbleView = self.bubbleView; - // - // [self.bubbleView addSubview:bubbleStrokeView]; - // [bubbleStrokeView autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:bodyMediaView]; - // [bubbleStrokeView autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:bodyMediaView]; - // [bubbleStrokeView autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:bodyMediaView]; - // [bubbleStrokeView autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:bodyMediaView]; - // self.bubbleView.bubbleStrokeView = bubbleStrokeView; - // OWSAssert(self.bubbleView.bubbleStrokeView); - // } + // TODO: Consider stroking the quoted thumbnail. } UIView *_Nullable bodyMediaView = nil; @@ -810,13 +797,14 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) return [UIFont systemFontOfSize:12.0f]; } -- (OWSMessageTextView *)createQuotedTextViewIfNecessary +- (UILabel *)createQuotedTextView { - [self.class loadForTextDisplay:self.quotedTextView - text:self.displayableQuotedText.displayText - textColor:self.textColor - font:self.textMessageFont - shouldIgnoreEvents:YES]; + self.quotedTextView.hidden = NO; + self.quotedTextView.text = self.displayableQuotedText.displayText; + self.quotedTextView.textColor = self.quotedTextColor; + + // Honor dynamic type in the message bodies. + self.quotedTextView.font = self.textMessageFont; return self.quotedTextView; } @@ -831,7 +819,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) } [self.class loadForTextDisplay:self.bodyTextView text:self.displayableBodyText.displayText - textColor:self.textColor + textColor:self.bodyTextColor font:self.textMessageFont shouldIgnoreEvents:shouldIgnoreEvents]; return self.bodyTextView; @@ -877,7 +865,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) tapForMoreLabel.text = NSLocalizedString(@"CONVERSATION_VIEW_OVERSIZE_TEXT_TAP_FOR_MORE", @"Indicator on truncated text messages that they can be tapped to see the entire text message."); tapForMoreLabel.font = [self tapForMoreFont]; - tapForMoreLabel.textColor = [self.textColor colorWithAlphaComponent:0.85]; + tapForMoreLabel.textColor = [self.bodyTextColor colorWithAlphaComponent:0.85]; tapForMoreLabel.textAlignment = [tapForMoreLabel textAlignmentUnnatural]; return tapForMoreLabel; @@ -915,14 +903,18 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) [quotedThumbnailView autoSetDimension:ALDimensionHeight toSize:self.quotedThumbnailSize]; } + OWSContactsManager *contactsManager = Environment.current.contactsManager; + NSString *quotedAuthor = [contactsManager displayNameForPhoneIdentifier:self.viewItem.quotedRecipientId]; + UILabel *quotedAuthorLabel = [UILabel new]; + quotedAuthorLabel.text = quotedAuthor; quotedAuthorLabel.font = self.quotedAuthorFont; quotedAuthorLabel.textColor = (self.isIncoming ? [UIColor colorWithRGBHex:0xd84315] : [UIColor colorWithRGBHex:0x007884]); quotedAuthorLabel.numberOfLines = 1; quotedAuthorLabel.lineBreakMode = NSLineBreakByTruncatingTail; [quotedMessageView addSubview:quotedAuthorLabel]; - [quotedAuthorLabel autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:self.quotedAuthorTopInset]; + [quotedAuthorLabel autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:self.quotedContentTopInset]; [quotedAuthorLabel autoPinLeadingToView:quoteStripView margin:self.quotedReplyStripeHSpacing]; if (quotedThumbnailView) { [quotedAuthorLabel autoPinTrailingToView:quotedThumbnailView margin:self.quotedThumbnailHSpacing]; @@ -930,12 +922,22 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) [quotedAuthorLabel autoPinTrailingToSuperviewWithMargin:self.quotedContentTrailingMargin]; } - // - (CGFloat)quotedAuthorTopInset - // { - // return 2.f; - // } - // - // - (CGFloat)quotedAuthorBottomSpacing + if (self.hasQuotedText) { + UILabel *quotedTextView = [self createQuotedTextView]; + + [quotedMessageView addSubview:quotedTextView]; + [quotedTextView autoPinEdge:ALEdgeTop + toEdge:ALEdgeBottom + ofView:quotedAuthorLabel + withOffset:self.quotedAuthorBottomSpacing]; + [quotedTextView autoPinLeadingToView:quoteStripView margin:self.quotedReplyStripeHSpacing]; + if (quotedThumbnailView) { + [quotedTextView autoPinTrailingToView:quotedThumbnailView margin:self.quotedThumbnailHSpacing]; + } else { + [quotedTextView autoPinTrailingToSuperviewWithMargin:self.quotedContentTrailingMargin]; + } + [quotedTextView autoPinBottomToSuperviewWithMargin:self.quotedContentBottomInset]; + } return quotedMessageView; } @@ -1234,37 +1236,6 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) return CGSizeCeil(textViewSize); } -// Size of "quoted reply" text. -- (CGSize)quotedTextSizeForContentWidth:(int)contentWidth includeMargins:(BOOL)includeMargins -{ - if (!self.hasBodyText) { - return CGSizeZero; - } - - CGFloat hMarginTotal = (self.textTrailingMargin + self.textLeadingMargin + self.quotedReplyStripeThickness - + self.quotedReplyStripeHSpacing); - // BOOL isRTL = self.isRTL; - // CGFloat leftMargin = isRTL ? self.textTrailingMargin : self.textLeadingMargin; - // CGFloat rightMargin = isRTL ? self.textLeadingMargin : self.textTrailingMargin; - - const int maxMessageWidth = [self maxMessageWidthForContentWidth:contentWidth]; - const int maxTextWidth = (int)floor(maxMessageWidth - hMarginTotal); - - self.quotedTextView.text = self.displayableBodyText.displayText; - // Honor dynamic type in the message bodies. - self.quotedTextView.font = [self textMessageFont]; - CGSize textSize = CGSizeCeil([self.quotedTextView sizeThatFits:CGSizeMake(maxTextWidth, CGFLOAT_MAX)]); - CGSize textViewSize = textSize; - - if (includeMargins) { - // TODO: - textViewSize.width += hMarginTotal; - textViewSize.height += self.textTopMargin + self.textBottomMargin; - } - - return CGSizeCeil(textViewSize); -} - - (CGSize)bodyMediaSizeForContentWidth:(int)contentWidth { const int maxMessageWidth = [self maxMessageWidthForContentWidth:contentWidth]; @@ -1319,15 +1290,6 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) OWSAssert(self.viewItem); OWSAssert([self.viewItem.interaction isKindOfClass:[TSMessage class]]); - // CGSize mediaContentSize = [self bodyMediaSizeForContentWidth:contentWidth]; - // CGSize textContentSize = [self bodyTextSizeForContentWidth:contentWidth includeMargins:YES]; - // - // CGFloat cellContentWidth = fmax(mediaContentSize.width, textContentSize.width); - // CGFloat cellContentHeight = mediaContentSize.height + textContentSize.height; - // CGSize cellSize = CGSizeMake(cellContentWidth, cellContentHeight); - // - // OWSAssert(cellSize.width > 0 && cellSize.height > 0); - CGSize result = CGSizeZero; if (!self.isQuotedReply) { @@ -1337,24 +1299,57 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) result.width += self.quotedMessageHInset; result.width += self.quotedReplyStripeThickness; result.width += self.quotedReplyStripeHSpacing; - // TODO: Content width. result.height += self.quotedMessageTopInset; - result.height += self.quotedAuthorHeight; - result.height += self.quotedAuthorBottomSpacing; - // TODO: Content height. + CGFloat thumbnailHeight = 0.f; if (self.hasQuotedAttachmentThumbnail) { - result.width = MAX(result.width, self.quotedThumbnailHSpacing); - result.width = MAX(result.width, self.quotedThumbnailSize); + result.width += self.quotedThumbnailHSpacing; + result.width += self.quotedThumbnailSize; - result.height = MAX(result.height, self.quotedThumbnailSize); + thumbnailHeight = self.quotedThumbnailSize; } else { - result.width = MAX(result.width, self.quotedContentTrailingMargin); + result.width += self.quotedContentTrailingMargin; } result.width += self.quotedMessageHInset; + const int maxMessageWidth = [self maxMessageWidthForContentWidth:contentWidth]; + CGFloat maxContentWidth = (maxMessageWidth - (self.textTrailingMargin + self.textLeadingMargin + result.width)); + CGFloat textWidth = 0.f; + + // Author + { + OWSContactsManager *contactsManager = Environment.current.contactsManager; + NSString *quotedAuthor = [contactsManager displayNameForPhoneIdentifier:self.viewItem.quotedRecipientId]; + + UILabel *quotedAuthorLabel = [UILabel new]; + quotedAuthorLabel.text = quotedAuthor; + quotedAuthorLabel.font = self.quotedAuthorFont; + quotedAuthorLabel.lineBreakMode = NSLineBreakByTruncatingTail; + quotedAuthorLabel.numberOfLines = 1; + + CGSize quotedAuthorSize = [quotedAuthorLabel sizeThatFits:CGSizeMake(maxContentWidth, CGFLOAT_MAX)]; + textWidth = MAX(textWidth, quotedAuthorSize.width); + result.height += self.quotedContentTopInset; + result.height += self.quotedAuthorHeight; + } + + if (self.hasQuotedText) { + UILabel *quotedTextView = [self createQuotedTextView]; + + CGSize textSize = CGSizeCeil([quotedTextView sizeThatFits:CGSizeMake(maxContentWidth, CGFLOAT_MAX)]); + + textWidth = MAX(textWidth, textSize.width); + result.height += self.quotedAuthorBottomSpacing; + result.height += textSize.height; + } + + result.width += textWidth; + result.height += self.quotedContentBottomInset; + + result.height = MAX(result.height, thumbnailHeight); + return result; } @@ -1414,74 +1409,51 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) return (CGFloat)ceil([self tapForMoreFont].lineHeight * 1.25); } +// TODO: - (UIFont *)quotedAuthorFont { return [UIFont ows_regularFontWithSize:10.f]; } +// TODO: - (CGFloat)quotedAuthorHeight { return (CGFloat)ceil([self quotedAuthorFont].lineHeight * 1.25); } -- (CGFloat)quotedAuthorTopInset +// TODO: +- (CGFloat)quotedAuthorBottomSpacing { return 2.f; } -- (CGFloat)quotedAuthorBottomSpacing +// TODO: +- (CGFloat)quotedContentTopInset { - return 2.f; + return 3.f; } -//- (UIFont *)quoteIndicatorFont -//{ -// return [UIFont ows_regularFontWithSize:10.f]; -//} -// -//- (CGFloat)quoteIndicatorHeight -//{ -// return (CGFloat)ceil([self quoteIndicatorFont].lineHeight * 1.25); -//} - -//- (CGFloat)quotedMessageHMargin -//{ -// return 10.f; -//} - -//- (CGFloat)quotedMessageTopMargin -//{ -// return 10.f; -//} -// -//- (CGFloat)quotedMessageBottomMargin -//{ -// return 10.f; -//} -// -//- (CGFloat)quotedMessageHMargin -//{ -// return 10.f; -//} +// TODO: +- (CGFloat)quotedContentBottomInset +{ + return 3.f; +} // Distance from top edge of "quoted message" bubble to top of message bubble. +// TODO: - (CGFloat)quotedMessageTopInset { return 3.f; } -//// Distance from bottom edge of "quoted message" bubble to other bubble content. -//- (CGFloat)quotedMessageBottomInset -//{ -// return 3.f; -//} - // Distance from side of "quoted message" bubble to side of message bubble. +// TODO: - (CGFloat)quotedMessageHInset { return 3.f; } +// TODO: - (CGFloat)quotedReplyStripeThickness { return 3.f; @@ -1489,21 +1461,25 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) // The spacing between the vertical "quoted reply stripe" // and the quoted message content. +// TODO: - (CGFloat)quotedReplyStripeHSpacing { return 10.f; } +// TODO: - (CGFloat)quotedThumbnailSize { return 30.f; } +// TODO: - (CGFloat)quotedThumbnailHSpacing { return 10.f; } +// TODO: - (CGFloat)quotedContentTrailingMargin { return 10.f; @@ -1549,11 +1525,16 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) return kBubbleTextVInset + kBubbleThornVInset; } -- (UIColor *)textColor +- (UIColor *)bodyTextColor { return self.isIncoming ? [UIColor blackColor] : [UIColor whiteColor]; } +- (UIColor *)quotedTextColor +{ + return [UIColor blackColor]; +} + - (BOOL)isMediaBeingSent { if (self.isIncoming) { diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h index 8dd152759..073249231 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h @@ -93,6 +93,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType); - (nullable DisplayableText *)displayableQuotedText; - (nullable NSString *)quotedAttachmentMimetype; +- (nullable NSString *)quotedRecipientId; // We don't want to try to load the media for this item (if any) // if a load has previously failed.