Merge branch 'charlesmchen/perMessageTimerTombstone'
This commit is contained in:
commit
b9428471cf
@ -37,8 +37,10 @@ typedef NS_OPTIONS(NSUInteger, OWSDirectionalRectCorner) {
|
||||
wideCornerRadius:(CGFloat)wideCornerRadius
|
||||
sharpCorners:(OWSDirectionalRectCorner)sharpCorners;
|
||||
|
||||
@property (nonatomic, nullable) UIColor *bubbleColor;
|
||||
@property (nonatomic, nullable) NSArray<UIColor *> *bubbleGradientColors;
|
||||
@property (nonatomic, nullable) UIColor *fillColor;
|
||||
@property (nonatomic, nullable) NSArray<UIColor *> *fillGradientColors;
|
||||
@property (nonatomic, nullable) UIColor *strokeColor;
|
||||
@property (nonatomic) CGFloat strokeThickness;
|
||||
|
||||
@property (nonatomic) OWSDirectionalRectCorner sharpCorners;
|
||||
|
||||
|
||||
@ -124,22 +124,36 @@ const CGFloat kOWSMessageCellCornerRadius_Small = 4;
|
||||
[self updatePartnerViews];
|
||||
}
|
||||
|
||||
- (void)setBubbleColor:(nullable UIColor *)bubbleColor
|
||||
- (void)setFillColor:(nullable UIColor *)fillColor
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
|
||||
_bubbleColor = bubbleColor;
|
||||
_bubbleGradientColors = nil;
|
||||
_fillColor = fillColor;
|
||||
_fillGradientColors = nil;
|
||||
|
||||
[self updateLayers];
|
||||
}
|
||||
|
||||
- (void)setBubbleGradientColors:(nullable NSArray<UIColor *> *)bubbleGradientColors
|
||||
- (void)setFillGradientColors:(nullable NSArray<UIColor *> *)fillGradientColors
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
|
||||
_bubbleColor = nil;
|
||||
_bubbleGradientColors = bubbleGradientColors;
|
||||
_fillColor = nil;
|
||||
_fillGradientColors = fillGradientColors;
|
||||
|
||||
[self updateLayers];
|
||||
}
|
||||
|
||||
- (void)setStrokeColor:(nullable UIColor *)strokeColor
|
||||
{
|
||||
_strokeColor = strokeColor;
|
||||
|
||||
[self updateLayers];
|
||||
}
|
||||
|
||||
- (void)setStrokeThickness:(CGFloat)strokeThickness
|
||||
{
|
||||
_strokeThickness = strokeThickness;
|
||||
|
||||
[self updateLayers];
|
||||
}
|
||||
@ -169,13 +183,15 @@ const CGFloat kOWSMessageCellCornerRadius_Small = 4;
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
|
||||
self.shapeLayer.fillColor = self.bubbleColor.CGColor;
|
||||
self.shapeLayer.hidden = self.bubbleColor == nil;
|
||||
self.shapeLayer.fillColor = self.fillColor.CGColor;
|
||||
self.shapeLayer.strokeColor = self.strokeColor.CGColor;
|
||||
self.shapeLayer.lineWidth = self.strokeThickness;
|
||||
self.shapeLayer.path = bezierPath.CGPath;
|
||||
self.shapeLayer.hidden = (self.fillColor == nil) && (self.strokeColor == nil);
|
||||
|
||||
NSArray *bubbleGradientCGColors = self.bubbleGradientCGColors;
|
||||
self.gradientLayer.colors = bubbleGradientCGColors;
|
||||
self.gradientLayer.hidden = bubbleGradientCGColors.count < 1;
|
||||
NSArray *_Nullable fillGradientCGColors = self.fillGradientCGColors;
|
||||
self.gradientLayer.colors = fillGradientCGColors;
|
||||
self.gradientLayer.hidden = fillGradientCGColors.count < 1;
|
||||
// Currently this view only supports linear (or axial) gradients
|
||||
// from the top-left to bottom-right.
|
||||
self.gradientLayer.startPoint = CGPointMake(0, 0);
|
||||
@ -187,10 +203,13 @@ const CGFloat kOWSMessageCellCornerRadius_Small = 4;
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
- (NSArray *)bubbleGradientCGColors
|
||||
- (nullable NSArray *)fillGradientCGColors
|
||||
{
|
||||
if (self.fillGradientColors.count < 1) {
|
||||
return nil;
|
||||
}
|
||||
NSMutableArray *result = [NSMutableArray new];
|
||||
for (UIColor *color in self.bubbleGradientColors) {
|
||||
for (UIColor *color in self.fillGradientColors) {
|
||||
[result addObject:(id)color.CGColor];
|
||||
}
|
||||
return result;
|
||||
|
||||
@ -557,11 +557,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
{
|
||||
BOOL hasOnlyBodyMediaView = (self.hasBodyMediaWithThumbnail && self.stackView.subviews.count == 1);
|
||||
if (!hasOnlyBodyMediaView) {
|
||||
self.bubbleView.bubbleColor = self.bubbleColor;
|
||||
self.bubbleView.fillColor = self.bubbleColor;
|
||||
} else {
|
||||
// Media-only messages should have no background color; they will fill the bubble's bounds
|
||||
// and we don't want artifacts at the edges.
|
||||
self.bubbleView.bubbleColor = nil;
|
||||
self.bubbleView.fillColor = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1369,7 +1369,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
self.bodyTextView.attributedText = nil;
|
||||
self.bodyTextView.hidden = YES;
|
||||
|
||||
self.bubbleView.bubbleColor = nil;
|
||||
self.bubbleView.fillColor = nil;
|
||||
[self.bubbleView clearPartnerViews];
|
||||
|
||||
for (UIView *subview in self.bubbleView.subviews) {
|
||||
|
||||
@ -129,11 +129,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return self.viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage;
|
||||
}
|
||||
|
||||
- (BOOL)perMessageExpirationHasExpired
|
||||
{
|
||||
return self.viewItem.perMessageExpirationHasExpired;
|
||||
}
|
||||
|
||||
#pragma mark - Load
|
||||
|
||||
- (void)configureViews
|
||||
@ -167,7 +162,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
conversationStyle:self.conversationStyle
|
||||
isIncoming:self.isIncoming
|
||||
isOverlayingMedia:NO
|
||||
isOutsideBubble:NO];
|
||||
isOutsideBubble:self.isExpired];
|
||||
[textViews addObject:self.footerView];
|
||||
}
|
||||
|
||||
@ -181,6 +176,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[self updateBubbleColor];
|
||||
|
||||
[self configureBubbleRounding];
|
||||
|
||||
if (self.isExpired) {
|
||||
self.bubbleView.strokeColor = self.contentForegroundColor;
|
||||
self.bubbleView.strokeThickness = 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)senderNameBottomSpacing
|
||||
@ -250,15 +250,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)updateBubbleColor
|
||||
{
|
||||
if (self.perMessageExpirationHasExpired) {
|
||||
self.bubbleView.bubbleColor = UIColor.ows_gray15Color;
|
||||
if (self.isExpired) {
|
||||
self.bubbleView.fillColor = Theme.backgroundColor;
|
||||
} else if (self.isIncoming) {
|
||||
self.bubbleView.bubbleGradientColors = @[
|
||||
self.bubbleView.fillGradientColors = @[
|
||||
[UIColor.ows_gray05Color blendWithColor:UIColor.ows_blackColor alpha:0.15],
|
||||
UIColor.ows_gray05Color,
|
||||
];
|
||||
} else {
|
||||
self.bubbleView.bubbleGradientColors = @[
|
||||
self.bubbleView.fillGradientColors = @[
|
||||
[UIColor.ows_signalBlueColor blendWithColor:UIColor.ows_blackColor alpha:0.15],
|
||||
UIColor.ows_signalBlueColor,
|
||||
];
|
||||
@ -272,7 +272,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (UIColor *)contentForegroundColor
|
||||
{
|
||||
if (self.perMessageExpirationHasExpired) {
|
||||
if (self.isExpired) {
|
||||
return UIColor.ows_gray60Color;
|
||||
} else if (self.isIncoming) {
|
||||
return UIColor.ows_gray90Color;
|
||||
@ -330,19 +330,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
self.label.textColor = self.contentForegroundColor;
|
||||
self.label.font = UIFont.ows_dynamicTypeSubheadlineFont.ows_mediumWeight;
|
||||
|
||||
if (self.isFailedDownload) {
|
||||
if (self.isExpired) {
|
||||
self.label.text = NSLocalizedString(@"PER_MESSAGE_EXPIRATION_VIEWED",
|
||||
@"Label for messages with per-message expiration indicating that "
|
||||
@"the local user has viewed the message's contents.");
|
||||
} else if (self.isFailedDownload) {
|
||||
self.label.text = NSLocalizedString(
|
||||
@"ATTACHMENT_DOWNLOADING_STATUS_FAILED", @"Status label when an attachment download has failed.");
|
||||
} else if (self.isAvailable) {
|
||||
if (self.perMessageExpirationHasExpired) {
|
||||
self.label.text = NSLocalizedString(@"PER_MESSAGE_EXPIRATION_VIEWED",
|
||||
@"Label for messages with per-message expiration indicating that "
|
||||
@"user has viewed the message's contents.");
|
||||
} else {
|
||||
self.label.text = NSLocalizedString(@"PER_MESSAGE_EXPIRATION_TAP_TO_VIEW",
|
||||
@"Label for messages with per-message expiration indicating that "
|
||||
@"user can tap to view the message's contents.");
|
||||
}
|
||||
self.label.text = NSLocalizedString(@"PER_MESSAGE_EXPIRATION_TAP_TO_VIEW",
|
||||
@"Label for messages with per-message expiration indicating that "
|
||||
@"user can tap to view the message's contents.");
|
||||
} else {
|
||||
OWSFailDebug(@"Unexpected view state.");
|
||||
}
|
||||
@ -354,8 +352,21 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
{
|
||||
OWSAssertDebug(self.iconView);
|
||||
|
||||
[self.iconView setTemplateImageName:(self.perMessageExpirationHasExpired ? @"play-outline-24" : @"play-filled-24")
|
||||
tintColor:self.contentForegroundColor];
|
||||
[self.iconView setTemplateImageName:self.iconName tintColor:self.contentForegroundColor];
|
||||
}
|
||||
|
||||
- (NSString *)iconName
|
||||
{
|
||||
if (self.isExpired) {
|
||||
return @"play-outline-24";
|
||||
} else if (self.isAvailable) {
|
||||
return @"play-filled-24";
|
||||
} else if (self.isFailedDownload) {
|
||||
// TODO: Waiting on design.
|
||||
return @"play-outline-24";
|
||||
} else {
|
||||
return @"play-filled-24";
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable UIView *)createDownloadViewIfNecessary
|
||||
@ -403,12 +414,20 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (BOOL)shouldShowIcon
|
||||
{
|
||||
return self.isAvailable;
|
||||
// TODO: Pending design.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)isExpired
|
||||
{
|
||||
return self.viewItem.perMessageExpirationHasExpired;
|
||||
}
|
||||
|
||||
- (BOOL)isAvailable
|
||||
{
|
||||
if (self.viewItem.attachmentStream) {
|
||||
if (self.isExpired) {
|
||||
return NO;
|
||||
} else if (self.viewItem.attachmentStream) {
|
||||
return YES;
|
||||
} else if (self.viewItem.attachmentPointer) {
|
||||
return NO;
|
||||
@ -420,7 +439,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (BOOL)isFailedDownload
|
||||
{
|
||||
if (self.viewItem.attachmentStream) {
|
||||
if (self.isExpired) {
|
||||
return NO;
|
||||
} else if (self.viewItem.attachmentStream) {
|
||||
return NO;
|
||||
} else if (self.viewItem.attachmentPointer) {
|
||||
return self.viewItem.attachmentPointer.state == TSAttachmentPointerStateFailed;
|
||||
@ -432,7 +453,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (BOOL)isOngoingDownload
|
||||
{
|
||||
if (self.viewItem.attachmentStream) {
|
||||
if (self.isExpired) {
|
||||
return NO;
|
||||
} else if (self.viewItem.attachmentStream) {
|
||||
return NO;
|
||||
} else if (self.viewItem.attachmentPointer) {
|
||||
return self.viewItem.attachmentPointer.state != TSAttachmentPointerStateFailed;
|
||||
@ -565,7 +588,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
self.label.text = nil;
|
||||
self.iconView.image = nil;
|
||||
|
||||
self.bubbleView.bubbleColor = nil;
|
||||
self.bubbleView.fillColor = nil;
|
||||
self.bubbleView.fillGradientColors = nil;
|
||||
self.bubbleView.strokeColor = nil;
|
||||
self.bubbleView.strokeThickness = 0.f;
|
||||
[self.bubbleView clearPartnerViews];
|
||||
|
||||
for (UIView *subview in self.bubbleView.subviews) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -50,7 +50,7 @@ public class TypingIndicatorCell: ConversationViewCell {
|
||||
return
|
||||
}
|
||||
|
||||
bubbleView.bubbleColor = conversationStyle.bubbleColor(isIncoming: true)
|
||||
bubbleView.fillColor = conversationStyle.bubbleColor(isIncoming: true)
|
||||
typingIndicatorView.startAnimation()
|
||||
|
||||
viewConstraints.append(contentsOf: [
|
||||
|
||||
@ -686,6 +686,12 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||
TSMessage *message = (TSMessage *)self.interaction;
|
||||
|
||||
if (message.hasPerMessageExpiration) {
|
||||
if (message.perMessageExpirationHasExpired) {
|
||||
self.messageCellType = OWSMessageCellType_PerMessageExpiration;
|
||||
self.perMessageExpirationHasExpired = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
if (transaction.transitional_yapReadTransaction) {
|
||||
NSArray<TSAttachment *> *mediaAttachments =
|
||||
[message mediaAttachmentsWithTransaction:transaction.transitional_yapReadTransaction];
|
||||
@ -694,14 +700,14 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||
TSAttachment *_Nullable mediaAttachment = mediaAttachments.firstObject;
|
||||
if ([mediaAttachment isKindOfClass:[TSAttachmentPointer class]]) {
|
||||
self.messageCellType = OWSMessageCellType_PerMessageExpiration;
|
||||
self.perMessageExpirationHasExpired = message.perMessageExpirationHasExpired;
|
||||
self.perMessageExpirationHasExpired = NO;
|
||||
self.attachmentPointer = (TSAttachmentPointer *)mediaAttachment;
|
||||
return;
|
||||
} else if ([mediaAttachment isKindOfClass:[TSAttachmentStream class]]) {
|
||||
TSAttachmentStream *attachmentStream = (TSAttachmentStream *)mediaAttachment;
|
||||
if (attachmentStream.isValidVisualMedia) {
|
||||
self.messageCellType = OWSMessageCellType_PerMessageExpiration;
|
||||
self.perMessageExpirationHasExpired = message.perMessageExpirationHasExpired;
|
||||
self.perMessageExpirationHasExpired = NO;
|
||||
self.attachmentStream = attachmentStream;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1640,7 +1640,7 @@
|
||||
/* Label for messages with per-message expiration indicating that user can tap to view the message's contents. */
|
||||
"PER_MESSAGE_EXPIRATION_TAP_TO_VIEW" = "Tap to view";
|
||||
|
||||
/* Label for messages with per-message expiration indicating that user has viewed the message's contents. */
|
||||
/* Label for messages with per-message expiration indicating that the local user has viewed the message's contents. */
|
||||
"PER_MESSAGE_EXPIRATION_VIEWED" = "Viewed";
|
||||
|
||||
/* A format for a label showing an example phone number. Embeds {{the example phone number}}. */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user