Bubble collapse.

This commit is contained in:
Matthew Chen 2018-03-29 11:49:02 -04:00
parent 578f40d791
commit 3ca2c08b06
5 changed files with 65 additions and 37 deletions

View File

@ -40,6 +40,17 @@ const CGFloat kBubbleTextVInset = 10.f;
}
}
- (void)setHideTail:(BOOL)hideTail
{
BOOL didChange = _hideTail != hideTail;
_hideTail = hideTail;
if (didChange || !self.shapeLayer) {
[self updateLayers];
}
}
- (void)setFrame:(CGRect)frame
{
BOOL didChange = !CGSizeEqualToSize(self.frame.size, frame.size);
@ -100,24 +111,25 @@ const CGFloat kBubbleTextVInset = 10.f;
UIBezierPath *bezierPath = [self maskPath];
self.shapeLayer.fillColor = self.bubbleColor.CGColor;
// self.shapeLayer.bounds = self.bounds;
self.shapeLayer.path = bezierPath.CGPath;
// self.maskLayer.bounds = self.bounds;
self.maskLayer.path = bezierPath.CGPath;
}
- (UIBezierPath *)maskPath
{
return [self.class maskPathForSize:self.bounds.size isOutgoing:self.isOutgoing isRTL:self.isRTL];
return [self.class maskPathForSize:self.bounds.size
isOutgoing:self.isOutgoing
hideTail:self.hideTail
isRTL:self.isRTL];
}
+ (UIBezierPath *)maskPathForSize:(CGSize)size isOutgoing:(BOOL)isOutgoing isRTL:(BOOL)isRTL
+ (UIBezierPath *)maskPathForSize:(CGSize)size isOutgoing:(BOOL)isOutgoing hideTail:(BOOL)hideTail isRTL:(BOOL)isRTL
{
UIBezierPath *bezierPath = [UIBezierPath new];
CGFloat bubbleLeft = 0.f;
CGFloat bubbleRight = size.width - kBubbleThornSideInset;
CGFloat bubbleRight = size.width - (hideTail ? 0.f : kBubbleThornSideInset);
CGFloat bubbleTop = 0.f;
CGFloat bubbleBottom = size.height - kBubbleThornVInset;
@ -135,15 +147,17 @@ const CGFloat kBubbleTextVInset = 10.f;
[bezierPath addQuadCurveToPoint:CGPointMake(bubbleLeft + kBubbleHRounding, bubbleTop)
controlPoint:CGPointMake(bubbleLeft, bubbleTop)];
// Thorn Tip
CGPoint thornTip = CGPointMake(size.width + 1, size.height);
CGPoint thornA = CGPointMake(bubbleRight - kBubbleHRounding * 0.5f, bubbleBottom - kBubbleVRounding);
CGPoint thornB = CGPointMake(bubbleRight, bubbleBottom - kBubbleVRounding);
[bezierPath moveToPoint:thornTip];
[bezierPath addQuadCurveToPoint:thornA controlPoint:CGPointMake(thornA.x, bubbleBottom)];
[bezierPath addLineToPoint:thornB];
[bezierPath addQuadCurveToPoint:thornTip controlPoint:CGPointMake(thornB.x, bubbleBottom)];
[bezierPath addLineToPoint:thornTip];
if (!hideTail) {
// Thorn Tip
CGPoint thornTip = CGPointMake(size.width + 1, size.height);
CGPoint thornA = CGPointMake(bubbleRight - kBubbleHRounding * 0.5f, bubbleBottom - kBubbleVRounding);
CGPoint thornB = CGPointMake(bubbleRight, bubbleBottom - kBubbleVRounding);
[bezierPath moveToPoint:thornTip];
[bezierPath addQuadCurveToPoint:thornA controlPoint:CGPointMake(thornA.x, bubbleBottom)];
[bezierPath addLineToPoint:thornB];
[bezierPath addQuadCurveToPoint:thornTip controlPoint:CGPointMake(thornB.x, bubbleBottom)];
[bezierPath addLineToPoint:thornTip];
}
// Horizontal Flip If Necessary
BOOL shouldFlip = isOutgoing == isRTL;

View File

@ -21,8 +21,6 @@
NS_ASSUME_NONNULL_BEGIN
// TODO: Review all comments.
CG_INLINE CGSize CGSizeCeil(CGSize size)
{
return CGSizeMake((CGFloat)ceil(size.width), (CGFloat)ceil(size.height));
@ -308,7 +306,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size)
// TODO: We might not need to hide it.
self.bubbleView.hidden = NO;
self.bubbleView.isOutgoing = self.isOutgoing;
// TODO: Hide tails/thorns here?
self.bubbleView.hideTail = self.viewItem.shouldHideBubbleTail;
if (self.shouldHaveFailedSendBadge) {
self.failedSendBadgeView = [UIImageView new];
@ -344,15 +342,6 @@ CG_INLINE CGSize CGSizeCeil(CGSize size)
[self updateDateHeader];
[self updateFooter];
// TODO: Do we need to pin the bubble size?
{
// - (CGSize)cellSizeForViewWidth:(int)viewWidth contentWidth:(int)contentWidth
// CGSize mediaSize = [self bodyMediaSizeForContentWidth:self.contentWidth];
// TODO:
// [self.viewConstraints addObjectsFromArray:[self.mediaMaskingView
// autoSetDimensionsToSize:mediaSize]];
}
UIView *_Nullable lastSubview = nil;
CGFloat bottomMargin = 0;
UIView *_Nullable bodyMediaView = nil;
@ -549,8 +538,7 @@ CG_INLINE CGSize CGSizeCeil(CGSize size)
} else {
DDLogError(@"%@ Failed to load cell media: %@", [self logTag], [self.attachmentStream mediaURL]);
self.viewItem.didCellMediaFailToLoad = YES;
[mediaView removeFromSuperview];
// TODO: We need to hide/remove the media view.
// TODO: Do we need to hide/remove the media view?
[self showAttachmentErrorView:mediaView];
}
return cellMedia;
@ -560,10 +548,6 @@ CG_INLINE CGSize CGSizeCeil(CGSize size)
// * If cell is not visible, eagerly unload view contents.
- (void)ensureMediaLoadState
{
// CGSize mediaSize = [self bodyMediaSizeForContentWidth:self.contentWidth];
// TODO:
// [self.viewConstraints addObjectsFromArray:[self.mediaMaskingView autoSetDimensionsToSize:mediaSize]];
if (!self.isCellVisible) {
// Eagerly unload.
if (self.unloadCellContentBlock) {
@ -1092,8 +1076,6 @@ CG_INLINE CGSize CGSizeCeil(CGSize size)
OWSAssert(self.mediaSize.height > 0);
// TODO: Adjust this behavior.
// TODO: This behavior is a bit different than the old behavior defined
// in JSQMediaItem+OWS.h. Let's discuss.
CGFloat contentAspectRatio = self.mediaSize.width / self.mediaSize.height;
// Clamp the aspect ratio so that very thin/wide content is presented
@ -1187,12 +1169,20 @@ CG_INLINE CGSize CGSizeCeil(CGSize size)
- (CGFloat)textLeadingMargin
{
return (self.isIncoming ? kBubbleTextHInset + kBubbleThornSideInset : kBubbleTextHInset);
CGFloat result = kBubbleTextHInset;
if (self.isIncoming && !self.viewItem.shouldHideBubbleTail) {
result += kBubbleThornSideInset;
}
return result;
}
- (CGFloat)textTrailingMargin
{
return (self.isIncoming ? kBubbleTextHInset : kBubbleTextHInset + kBubbleThornSideInset);
CGFloat result = kBubbleTextHInset;
if (!self.isIncoming && !self.viewItem.shouldHideBubbleTail) {
result += kBubbleThornSideInset;
}
return result;
}
- (CGFloat)textTopMargin

View File

@ -4463,8 +4463,10 @@ typedef enum : NSUInteger {
// Update the "shouldShowDate" property of the view items.
OWSInteractionType lastInteractionType = OWSInteractionType_Unknown;
MessageRecipientStatus lastRecipientStatus = MessageRecipientStatusUploading;
NSString *_Nullable lastIncomingSenderId = nil;
for (ConversationViewItem *viewItem in viewItems.reverseObjectEnumerator) {
BOOL shouldHideRecipientStatus = NO;
BOOL shouldHideBubbleTail = NO;
OWSInteractionType interactionType = viewItem.interaction.interactionType;
if (interactionType == OWSInteractionType_OutgoingMessage) {
@ -4473,14 +4475,23 @@ typedef enum : NSUInteger {
[MessageRecipientStatusUtils recipientStatusWithOutgoingMessage:outgoingMessage];
if (outgoingMessage.messageState == TSOutgoingMessageStateUnsent) {
// always sow "failed to send" status
// always show "failed to send" status
shouldHideRecipientStatus = NO;
} else {
shouldHideRecipientStatus
= (interactionType == lastInteractionType && recipientStatus == lastRecipientStatus);
}
shouldHideBubbleTail = (interactionType == lastInteractionType && recipientStatus == lastRecipientStatus);
lastRecipientStatus = recipientStatus;
} else if (interactionType == OWSInteractionType_IncomingMessage) {
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)viewItem.interaction;
NSString *incomingSenderId = incomingMessage.authorId;
OWSAssert(incomingSenderId.length > 0);
shouldHideBubbleTail = (interactionType == lastInteractionType &&
[NSObject isNullableObject:lastIncomingSenderId equalTo:incomingSenderId]);
lastIncomingSenderId = incomingSenderId;
}
lastInteractionType = interactionType;
@ -4491,6 +4502,7 @@ typedef enum : NSUInteger {
[rowsThatChangedSize addObject:@(viewItem.previousRow)];
}
viewItem.shouldHideRecipientStatus = shouldHideRecipientStatus;
viewItem.shouldHideBubbleTail = shouldHideBubbleTail;
}
self.viewItems = viewItems;

View File

@ -46,6 +46,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
@property (nonatomic, readonly) BOOL hasBodyText;
@property (nonatomic) BOOL shouldShowDate;
@property (nonatomic) BOOL shouldHideRecipientStatus;
@property (nonatomic) BOOL shouldHideBubbleTail;
@property (nonatomic) NSInteger row;
// During updates, we sometimes need the previous row index

View File

@ -134,6 +134,17 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
[self clearCachedLayoutState];
}
- (void)setShouldHideBubbleTail:(BOOL)shouldHideBubbleTail
{
if (_shouldHideBubbleTail == shouldHideBubbleTail) {
return;
}
_shouldHideBubbleTail = shouldHideBubbleTail;
[self clearCachedLayoutState];
}
- (void)clearCachedLayoutState
{
self.cachedCellSize = nil;