diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageFooterView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageFooterView.m index f5269da75..6d118046e 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageFooterView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageFooterView.m @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) UILabel *timestampLabel; @property (nonatomic) UIImageView *statusIndicatorImageView; -@property (nonatomic, nullable) OWSMessageTimerView *messageTimerView; +@property (nonatomic) OWSMessageTimerView *messageTimerView; @end @@ -44,6 +44,9 @@ NS_ASSUME_NONNULL_BEGIN self.timestampLabel = [UILabel new]; [self addArrangedSubview:self.timestampLabel]; + self.messageTimerView = [OWSMessageTimerView new]; + [self addArrangedSubview:self.messageTimerView]; + self.statusIndicatorImageView = [UIImageView new]; [self.statusIndicatorImageView setContentHuggingHigh]; [self addArrangedSubview:self.statusIndicatorImageView]; @@ -92,6 +95,18 @@ NS_ASSUME_NONNULL_BEGIN } self.timestampLabel.textColor = textColor; + if ([self isDisappearingMessage:viewItem]) { + TSMessage *message = (TSMessage *)viewItem.interaction; + uint64_t expirationTimestamp = message.expiresAt; + uint32_t expiresInSeconds = message.expiresInSeconds; + [self.messageTimerView configureWithExpirationTimestamp:expirationTimestamp + initialDurationSeconds:expiresInSeconds + tintColor:textColor]; + self.messageTimerView.hidden = NO; + } else { + self.messageTimerView.hidden = YES; + } + if (viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) { TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)viewItem.interaction; @@ -257,8 +272,7 @@ NS_ASSUME_NONNULL_BEGIN { [self.statusIndicatorImageView.layer removeAllAnimations]; - [self.messageTimerView removeFromSuperview]; - self.messageTimerView = nil; + [self.messageTimerView prepareForReuse]; } @end diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.h b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.h index 2a40d4b6c..0fad8f9f0 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.h +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.h @@ -8,12 +8,15 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSMessageTimerView : UIView -- (instancetype)init NS_UNAVAILABLE; +- (instancetype)init NS_DESIGNATED_INITIALIZER; - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; -- (instancetype)initWithExpiration:(uint64_t)expirationTimestamp - initialDurationSeconds:(uint32_t)initialDurationSeconds NS_DESIGNATED_INITIALIZER; +- (void)configureWithExpirationTimestamp:(uint64_t)expirationTimestamp + initialDurationSeconds:(uint32_t)initialDurationSeconds + tintColor:(UIColor *)tintColor; + +- (void)prepareForReuse; + (CGSize)measureSize; diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.m index 29bf545dd..df37661a5 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.m @@ -25,6 +25,7 @@ const CGFloat kDisappearingMessageIconSize = 12.f; @property (nonatomic, nullable) NSTimer *animationTimer; +// 0 == about to expire, 12 == just started countdown. @property (nonatomic) NSInteger progress12; @@ -36,23 +37,16 @@ const CGFloat kDisappearingMessageIconSize = 12.f; - (void)dealloc { - [self.animationTimer invalidate]; - self.animationTimer = nil; + [self clearAnimation]; } -- (instancetype)initWithExpiration:(uint64_t)expirationTimestamp - initialDurationSeconds:(uint32_t)initialDurationSeconds - tintColor:(UIColor *)tintColor; +- (instancetype)init { self = [super initWithFrame:CGRectZero]; if (!self) { return self; } - self.expirationTimestamp = expirationTimestamp; - self.initialDurationSeconds = initialDurationSeconds; - self.tintColor = tintColor; - [self commonInit]; return self; @@ -65,15 +59,19 @@ const CGFloat kDisappearingMessageIconSize = 12.f; [self.imageView autoPinToSuperviewEdges]; [self.imageView autoSetDimension:ALDimensionWidth toSize:kDisappearingMessageIconSize]; [self.imageView autoSetDimension:ALDimensionHeight toSize:kDisappearingMessageIconSize]; +} + +- (void)configureWithExpirationTimestamp:(uint64_t)expirationTimestamp + initialDurationSeconds:(uint32_t)initialDurationSeconds + tintColor:(UIColor *)tintColor; +{ + self.expirationTimestamp = expirationTimestamp; + self.initialDurationSeconds = initialDurationSeconds; + self.tintColor = tintColor; [self updateProgress12]; [self updateIcon]; - - self.animationTimer = [NSTimer weakScheduledTimerWithTimeInterval:1.f - target:self - selector:@selector(updateProgress12) - userInfo:nil - repeats:YES]; + [self startAnimation]; } - (void)updateProgress12 @@ -81,7 +79,7 @@ const CGFloat kDisappearingMessageIconSize = 12.f; CGFloat secondsLeft = MAX(0, (self.expirationTimestamp - [NSDate ows_millisecondTimeStamp]) / 1000.f); CGFloat progress = 0.f; if (self.initialDurationSeconds > 0) { - progress = CGFloatClamp(1.f - (secondsLeft / self.initialDurationSeconds), 0.f, 1.f); + progress = CGFloatClamp(secondsLeft / self.initialDurationSeconds, 0.f, 1.f); } OWSAssert(progress >= 0.f); OWSAssert(progress <= 1.f); @@ -159,6 +157,28 @@ const CGFloat kDisappearingMessageIconSize = 12.f; return image; } +- (void)startAnimation +{ + [self clearAnimation]; + + self.animationTimer = [NSTimer weakScheduledTimerWithTimeInterval:0.1f + target:self + selector:@selector(updateProgress12) + userInfo:nil + repeats:YES]; +} + +- (void)clearAnimation +{ + [self.animationTimer invalidate]; + self.animationTimer = nil; +} + +- (void)prepareForReuse +{ + [self clearAnimation]; +} + + (CGSize)measureSize { return CGSizeMake(kDisappearingMessageIconSize, kDisappearingMessageIconSize);