Let senders tap on outgoing messages with per-message expiration (until countdown completes). Countdown starts when message is sent (not sending, failed).
This commit is contained in:
parent
4ed4b15118
commit
ddcf10bf01
@ -265,7 +265,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return pendingColor;
|
||||
case PerMessageExpirationState_OutgoingSending:
|
||||
return self.conversationStyle.bubbleColorOutgoingSending;
|
||||
case PerMessageExpirationState_OutgoingSent:
|
||||
case PerMessageExpirationState_OutgoingSentAvailable:
|
||||
case PerMessageExpirationState_OutgoingSentExpired:
|
||||
return self.conversationStyle.bubbleColorOutgoingSent;
|
||||
case PerMessageExpirationState_IncomingInvalidContent:
|
||||
return Theme.backgroundColor;
|
||||
@ -285,7 +286,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
case PerMessageExpirationState_IncomingAvailable:
|
||||
case PerMessageExpirationState_OutgoingFailed:
|
||||
case PerMessageExpirationState_OutgoingSending:
|
||||
case PerMessageExpirationState_OutgoingSent:
|
||||
case PerMessageExpirationState_OutgoingSentAvailable:
|
||||
case PerMessageExpirationState_OutgoingSentExpired:
|
||||
return NO;
|
||||
case PerMessageExpirationState_IncomingInvalidContent:
|
||||
return YES;
|
||||
@ -309,7 +311,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
case PerMessageExpirationState_OutgoingFailed:
|
||||
return nil;
|
||||
case PerMessageExpirationState_OutgoingSending:
|
||||
case PerMessageExpirationState_OutgoingSent:
|
||||
case PerMessageExpirationState_OutgoingSentAvailable:
|
||||
case PerMessageExpirationState_OutgoingSentExpired:
|
||||
return nil;
|
||||
case PerMessageExpirationState_IncomingInvalidContent:
|
||||
return UIColor.ows_destructiveRedColor;
|
||||
@ -334,7 +337,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return ConversationStyle.bubbleTextColorIncoming;
|
||||
case PerMessageExpirationState_OutgoingFailed:
|
||||
case PerMessageExpirationState_OutgoingSending:
|
||||
case PerMessageExpirationState_OutgoingSent:
|
||||
case PerMessageExpirationState_OutgoingSentAvailable:
|
||||
case PerMessageExpirationState_OutgoingSentExpired:
|
||||
return ConversationStyle.bubbleTextColorOutgoing;
|
||||
case PerMessageExpirationState_IncomingInvalidContent:
|
||||
return Theme.secondaryColor;
|
||||
@ -359,7 +363,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
case PerMessageExpirationState_OutgoingFailed:
|
||||
return pendingColor;
|
||||
case PerMessageExpirationState_OutgoingSending:
|
||||
case PerMessageExpirationState_OutgoingSent:
|
||||
case PerMessageExpirationState_OutgoingSentAvailable:
|
||||
case PerMessageExpirationState_OutgoingSentExpired:
|
||||
return ConversationStyle.bubbleTextColorOutgoing;
|
||||
case PerMessageExpirationState_IncomingInvalidContent:
|
||||
return Theme.secondaryColor;
|
||||
@ -443,10 +448,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
self.label.text = CommonStrings.retryButton;
|
||||
break;
|
||||
case PerMessageExpirationState_OutgoingSending:
|
||||
case PerMessageExpirationState_OutgoingSent:
|
||||
self.label.text = NSLocalizedString(@"MESSAGE_STATUS_SENDING", @"message status while message is sending.");
|
||||
break;
|
||||
case PerMessageExpirationState_OutgoingSentExpired:
|
||||
self.label.text = NSLocalizedString(@"PER_MESSAGE_EXPIRATION_OUTGOING_MESSAGE",
|
||||
@"Label for outgoing messages with per-message expiration.");
|
||||
break;
|
||||
case PerMessageExpirationState_OutgoingSentAvailable:
|
||||
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.");
|
||||
break;
|
||||
case PerMessageExpirationState_IncomingInvalidContent:
|
||||
self.label.text = NSLocalizedString(@"PER_MESSAGE_EXPIRATION_INVALID_CONTENT",
|
||||
@"Label for messages with per-message expiration that have invalid content.");
|
||||
@ -487,8 +499,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
case PerMessageExpirationState_OutgoingFailed:
|
||||
return @"arrow-down-circle-outline-24";
|
||||
case PerMessageExpirationState_OutgoingSending:
|
||||
case PerMessageExpirationState_OutgoingSent:
|
||||
case PerMessageExpirationState_OutgoingSentExpired:
|
||||
return @"play-outline-24";
|
||||
case PerMessageExpirationState_OutgoingSentAvailable:
|
||||
return @"play-filled-24";
|
||||
case PerMessageExpirationState_IncomingInvalidContent:
|
||||
OWSFailDebug(@"Unexpected state.");
|
||||
return nil;
|
||||
@ -549,9 +563,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return self.viewItem.perMessageExpirationState == PerMessageExpirationState_IncomingFailed;
|
||||
}
|
||||
|
||||
- (BOOL)isIncomingAvailable
|
||||
- (BOOL)isAvailable
|
||||
{
|
||||
return self.viewItem.perMessageExpirationState == PerMessageExpirationState_IncomingAvailable;
|
||||
return (self.viewItem.perMessageExpirationState == PerMessageExpirationState_IncomingAvailable
|
||||
|| self.viewItem.perMessageExpirationState == PerMessageExpirationState_OutgoingSentAvailable);
|
||||
}
|
||||
|
||||
#pragma mark - Measurement
|
||||
@ -712,7 +727,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
if (self.isIncomingFailed) {
|
||||
[self.delegate didTapFailedIncomingAttachment:self.viewItem];
|
||||
} else if (self.isIncomingAvailable) {
|
||||
} else if (self.isAvailable) {
|
||||
[self.delegate didTapAttachmentWithPerMessageExpiration:self.viewItem
|
||||
attachmentStream:self.viewItem.attachmentStream];
|
||||
}
|
||||
|
||||
@ -32,9 +32,12 @@ typedef NS_ENUM(NSUInteger, PerMessageExpirationState) {
|
||||
PerMessageExpirationState_IncomingInvalidContent,
|
||||
PerMessageExpirationState_OutgoingSending,
|
||||
PerMessageExpirationState_OutgoingFailed,
|
||||
PerMessageExpirationState_OutgoingSent,
|
||||
PerMessageExpirationState_OutgoingSentAvailable,
|
||||
PerMessageExpirationState_OutgoingSentExpired,
|
||||
};
|
||||
|
||||
NSString *NSStringForPerMessageExpirationState(PerMessageExpirationState value);
|
||||
|
||||
@class ContactShareViewModel;
|
||||
@class ConversationViewCell;
|
||||
@class DisplayableText;
|
||||
|
||||
@ -41,6 +41,32 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||
}
|
||||
}
|
||||
|
||||
NSString *NSStringForPerMessageExpirationState(PerMessageExpirationState cellType)
|
||||
{
|
||||
switch (cellType) {
|
||||
case PerMessageExpirationState_Unknown:
|
||||
return @"PerMessageExpirationState_Unknown";
|
||||
case PerMessageExpirationState_IncomingExpired:
|
||||
return @"PerMessageExpirationState_IncomingExpired";
|
||||
case PerMessageExpirationState_IncomingDownloading:
|
||||
return @"PerMessageExpirationState_IncomingDownloading";
|
||||
case PerMessageExpirationState_IncomingFailed:
|
||||
return @"PerMessageExpirationState_IncomingFailed";
|
||||
case PerMessageExpirationState_IncomingAvailable:
|
||||
return @"PerMessageExpirationState_IncomingAvailable";
|
||||
case PerMessageExpirationState_IncomingInvalidContent:
|
||||
return @"PerMessageExpirationState_IncomingInvalidContent";
|
||||
case PerMessageExpirationState_OutgoingSending:
|
||||
return @"PerMessageExpirationState_OutgoingSending";
|
||||
case PerMessageExpirationState_OutgoingFailed:
|
||||
return @"PerMessageExpirationState_OutgoingFailed";
|
||||
case PerMessageExpirationState_OutgoingSentAvailable:
|
||||
return @"PerMessageExpirationState_OutgoingSentAvailable";
|
||||
case PerMessageExpirationState_OutgoingSentExpired:
|
||||
return @"PerMessageExpirationState_OutgoingSentExpired";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation ConversationMediaAlbumItem
|
||||
@ -856,10 +882,34 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||
switch (outgoingMessage.messageState) {
|
||||
case TSOutgoingMessageStateSending:
|
||||
self.perMessageExpirationState = PerMessageExpirationState_OutgoingSending;
|
||||
break;
|
||||
case TSOutgoingMessageStateFailed:
|
||||
self.perMessageExpirationState = PerMessageExpirationState_OutgoingFailed;
|
||||
break;
|
||||
default:
|
||||
self.perMessageExpirationState = PerMessageExpirationState_OutgoingSent;
|
||||
if (message.perMessageExpirationHasExpired) {
|
||||
self.perMessageExpirationState = PerMessageExpirationState_OutgoingSentExpired;
|
||||
} else {
|
||||
NSArray<TSAttachment *> *mediaAttachments = [message mediaAttachmentsWithTransaction:transaction];
|
||||
// TODO: We currently only support single attachments for messages
|
||||
// with per-message expiration.
|
||||
TSAttachment *_Nullable mediaAttachment = mediaAttachments.firstObject;
|
||||
if ([mediaAttachment isKindOfClass:[TSAttachmentPointer class]]) {
|
||||
OWSFailDebug(@"Invalid outgoing attachment.");
|
||||
self.perMessageExpirationState = PerMessageExpirationState_OutgoingSentExpired;
|
||||
} else if ([mediaAttachment isKindOfClass:[TSAttachmentStream class]]) {
|
||||
TSAttachmentStream *attachmentStream = (TSAttachmentStream *)mediaAttachment;
|
||||
if (attachmentStream.isValidVisualMedia
|
||||
&& (attachmentStream.isImage || attachmentStream.isAnimated)) {
|
||||
self.perMessageExpirationState = PerMessageExpirationState_OutgoingSentAvailable;
|
||||
self.attachmentStream = attachmentStream;
|
||||
} else {
|
||||
OWSFailDebug(@"Invalid outgoing attachment.");
|
||||
self.perMessageExpirationState = PerMessageExpirationState_OutgoingSentExpired;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
self.messageCellType = OWSMessageCellType_PerMessageExpiration;
|
||||
return;
|
||||
|
||||
@ -1429,12 +1429,18 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
};
|
||||
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[OWSDisappearingMessagesJob sharedJob] startAnyExpirationForMessage:message
|
||||
TSInteraction *_Nullable latestCopy =
|
||||
[TSInteraction anyFetchWithUniqueId:message.uniqueId transaction:transaction.asAnyRead];
|
||||
if (![latestCopy isKindOfClass:[TSOutgoingMessage class]]) {
|
||||
OWSLogWarn(@"Could not update expiration for deleted message.");
|
||||
return;
|
||||
}
|
||||
TSOutgoingMessage *latestMessage = (TSOutgoingMessage *)latestCopy;
|
||||
[[OWSDisappearingMessagesJob sharedJob] startAnyExpirationForMessage:latestMessage
|
||||
expirationStartedAt:[NSDate ows_millisecondTimeStamp]
|
||||
transaction:transaction];
|
||||
|
||||
[PerMessageExpiration expireIfNecessaryWithMessage:message
|
||||
transaction:transaction.asAnyWrite];
|
||||
|
||||
[PerMessageExpiration expireIfNecessaryWithMessage:latestMessage transaction:transaction.asAnyWrite];
|
||||
}];
|
||||
|
||||
if (!message.shouldSyncTranscript) {
|
||||
|
||||
@ -37,13 +37,6 @@ public class PerMessageExpiration: NSObject {
|
||||
@objc
|
||||
public class func startPerMessageExpiration(forMessage message: TSMessage,
|
||||
transaction: SDSAnyWriteTransaction) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
guard message.hasPerMessageExpiration else {
|
||||
owsFailDebug("Message does not have per-message expiration.")
|
||||
return
|
||||
}
|
||||
|
||||
// Start expiration using "now" as the read time.
|
||||
startPerMessageExpiration(forMessage: message,
|
||||
readTimestamp: nowMs(),
|
||||
@ -56,6 +49,15 @@ public class PerMessageExpiration: NSObject {
|
||||
sendSyncMessages: Bool,
|
||||
transaction: SDSAnyWriteTransaction) {
|
||||
|
||||
guard message.hasPerMessageExpiration else {
|
||||
owsFailDebug("Message does not have per-message expiration.")
|
||||
return
|
||||
}
|
||||
guard !isOutgoingNotYetSent(message: message) else {
|
||||
Logger.warn("Not starting expiration for not-yet-sent outgoing message.")
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure that timestamp is not later than now.
|
||||
let timestamp = min(readTimestamp, nowMs())
|
||||
|
||||
@ -131,13 +133,14 @@ public class PerMessageExpiration: NSObject {
|
||||
for message in messages {
|
||||
if shouldMessageAutoExpire(message) {
|
||||
completeExpiration(forMessage: message, transaction: transaction)
|
||||
} else if isOutgoingSent(message: message) {
|
||||
completeExpiration(forMessage: message, transaction: transaction)
|
||||
} else if message.hasPerMessageExpirationStarted {
|
||||
if shouldResumeNormalExpiration {
|
||||
// If expiration is started, resume countdown.
|
||||
schedulePerMessageExpiration(forMessage: message, transaction: transaction)
|
||||
}
|
||||
} else if isOutgoingSent(message: message),
|
||||
!message.hasPerMessageExpirationStarted {
|
||||
startPerMessageExpiration(forMessage: message, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -162,15 +165,16 @@ public class PerMessageExpiration: NSObject {
|
||||
return
|
||||
}
|
||||
|
||||
// If outgoing message and is "sent", expire.
|
||||
guard !isOutgoingSent(message: message) else {
|
||||
// If countdown has completed, expire.
|
||||
guard !hasExpirationCountdownCompleted(message: message) else {
|
||||
completeExpiration(forMessage: message, transaction: transaction)
|
||||
return
|
||||
}
|
||||
|
||||
// If countdown has completed, expire.
|
||||
guard !hasExpirationCountdownCompleted(message: message) else {
|
||||
completeExpiration(forMessage: message, transaction: transaction)
|
||||
// If outgoing message and is "sent", start expiration if necessary.
|
||||
if isOutgoingSent(message: message),
|
||||
!message.hasPerMessageExpirationStarted {
|
||||
startPerMessageExpiration(forMessage: message, transaction: transaction)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -181,6 +185,10 @@ public class PerMessageExpiration: NSObject {
|
||||
}
|
||||
|
||||
private class func isOutgoingSent(message: TSMessage) -> Bool {
|
||||
guard message.hasPerMessageExpiration else {
|
||||
owsFailDebug("Unexpected message.")
|
||||
return false
|
||||
}
|
||||
// If outgoing message and is "sent", expire.
|
||||
guard let outgoingMessage = message as? TSOutgoingMessage else {
|
||||
return false
|
||||
@ -191,6 +199,17 @@ public class PerMessageExpiration: NSObject {
|
||||
return true
|
||||
}
|
||||
|
||||
private class func isOutgoingNotYetSent(message: TSMessage) -> Bool {
|
||||
// If outgoing message and is "sent", expire.
|
||||
guard let outgoingMessage = message as? TSOutgoingMessage else {
|
||||
return false
|
||||
}
|
||||
guard outgoingMessage.messageState != .sent else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// We auto-expire messages after 30 days, even if the user hasn't seen them.
|
||||
private class func shouldMessageAutoExpire(_ message: TSMessage) -> Bool {
|
||||
let autoExpireDeadlineMs = min(message.timestamp, message.receivedAtTimestamp) + 30 * kDayInMs
|
||||
|
||||
Loading…
Reference in New Issue
Block a user