Revert 'new sort id'.

This commit is contained in:
Matthew Chen 2018-09-27 19:40:51 -04:00
parent 673dae83d9
commit ebae75af00
80 changed files with 462 additions and 796 deletions

2
Pods

@ -1 +1 @@
Subproject commit e90476016714371cc689f6fae35fe853a0ad16ae
Subproject commit 04a1de529ae10cfa32a2980de66dad52da80af27

View File

@ -438,7 +438,6 @@
4C63CC00210A620B003AE45C /* SignalTSan.supp in Resources */ = {isa = PBXBuildFile; fileRef = 4C63CBFF210A620B003AE45C /* SignalTSan.supp */; };
4C6F527C20FFE8400097DEEE /* SignalUBSan.supp in Resources */ = {isa = PBXBuildFile; fileRef = 4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */; };
4C858A52212DC5E1001B45D3 /* UIImage+OWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C858A51212DC5E1001B45D3 /* UIImage+OWS.swift */; };
4C858A562130CBEC001B45D3 /* OWS110SortIdMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C858A552130CBEC001B45D3 /* OWS110SortIdMigration.swift */; };
4C948FF72146EB4800349F0D /* BlockListCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C948FF62146EB4800349F0D /* BlockListCache.swift */; };
4CA5F793211E1F06008C2708 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA5F792211E1F06008C2708 /* Toast.swift */; };
4CB5F26720F6E1E2004D1B42 /* MenuActionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFF4C0920F55BBA005DA313 /* MenuActionsViewController.swift */; };
@ -1125,7 +1124,6 @@
4C63CBFF210A620B003AE45C /* SignalTSan.supp */ = {isa = PBXFileReference; lastKnownFileType = text; path = SignalTSan.supp; sourceTree = "<group>"; };
4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */ = {isa = PBXFileReference; lastKnownFileType = text; path = SignalUBSan.supp; sourceTree = "<group>"; };
4C858A51212DC5E1001B45D3 /* UIImage+OWS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+OWS.swift"; sourceTree = "<group>"; };
4C858A552130CBEC001B45D3 /* OWS110SortIdMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWS110SortIdMigration.swift; sourceTree = "<group>"; };
4C948FF62146EB4800349F0D /* BlockListCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListCache.swift; sourceTree = "<group>"; };
4CA5F792211E1F06008C2708 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = "<group>"; };
4CB5F26820F7D060004D1B42 /* MessageActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageActions.swift; sourceTree = "<group>"; };
@ -1634,7 +1632,6 @@
346129E41FD5C0C600532771 /* OWSDatabaseMigrationRunner.m */,
34ABB2C32090C59700C727A6 /* OWSResaveCollectionDBMigration.h */,
34ABB2C22090C59600C727A6 /* OWSResaveCollectionDBMigration.m */,
4C858A552130CBEC001B45D3 /* OWS110SortIdMigration.swift */,
);
path = migrations;
sourceTree = "<group>";
@ -3182,7 +3179,6 @@
34AC09E6211B39B100997B47 /* SelectRecipientViewController.m in Sources */,
4C858A52212DC5E1001B45D3 /* UIImage+OWS.swift in Sources */,
34480B671FD0AA9400BC14EF /* UIFont+OWS.m in Sources */,
4C858A562130CBEC001B45D3 /* OWS110SortIdMigration.swift in Sources */,
346129E61FD5C0C600532771 /* OWSDatabaseMigrationRunner.m in Sources */,
34AC0A11211B39EA00997B47 /* OWSLayerView.swift in Sources */,
34AC0A1B211B39EA00997B47 /* GradientView.swift in Sources */,

View File

@ -30,7 +30,6 @@ public class SessionResetJob: NSObject {
self.primaryStorage.deleteAllSessions(forContact: self.recipientId, protocolContext: transaction)
DispatchQueue.main.async {
// MJK TODO - should be safe to remove this senderTimestamp
let endSessionMessage = EndSessionMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: self.thread)
self.messageSender.enqueue(endSessionMessage, success: {
@ -41,7 +40,6 @@ public class SessionResetJob: NSObject {
self.primaryStorage.archiveAllSessions(forContact: self.recipientId, protocolContext: transaction)
}
Logger.info("successfully sent EndSessionMessage.")
// MJK TODO - should be safe to remove this senderTimestamp
let message = TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(),
in: self.thread,
messageType: TSInfoMessageType.typeSessionDidEnd)

View File

@ -126,7 +126,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
{
OWSAssertDebug(viewItem);
NSDate *date = viewItem.interaction.receivedAtDate;
NSDate *date = viewItem.interaction.dateForSorting;
NSString *dateString = [DateUtil formatDateForConversationDateBreaks:date].localizedUppercaseString;
// Update cell to reflect changes in dynamic text.

View File

@ -64,6 +64,7 @@
#import <SignalServiceKit/NSDate+OWS.h>
#import <SignalServiceKit/NSTimer+OWS.h>
#import <SignalServiceKit/OWSAddToContactsOfferMessage.h>
#import <SignalServiceKit/OWSAddToProfileWhitelistOfferMessage.h>
#import <SignalServiceKit/OWSAttachmentsProcessor.h>
#import <SignalServiceKit/OWSBlockingManager.h>
#import <SignalServiceKit/OWSDisappearingMessagesConfiguration.h>
@ -214,7 +215,7 @@ typedef enum : NSUInteger {
@property (nonatomic) BOOL hasClearedUnreadMessagesIndicator;
@property (nonatomic) BOOL showLoadMoreHeader;
@property (nonatomic) UILabel *loadMoreHeader;
@property (nonatomic) uint64_t lastVisibleSortId;
@property (nonatomic) uint64_t lastVisibleTimestamp;
@property (nonatomic) BOOL isUserScrolling;
@ -705,7 +706,7 @@ typedef enum : NSUInteger {
[self scrollToDefaultPosition];
}
[self updateLastVisibleSortId];
[self updateLastVisibleTimestamp];
if (!self.viewHasEverAppeared) {
NSTimeInterval appearenceDuration = CACurrentMediaTime() - self.viewControllerCreatedAt;
@ -1890,11 +1891,7 @@ typedef enum : NSUInteger {
// DEPRECATED: we're no longer creating these incoming SN error's per message,
// but there will be some legacy ones in the wild, behind which await
// as-of-yet-undecrypted messages
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if ([errorMessage isKindOfClass:[TSInvalidIdentityKeyReceivingErrorMessage class]]) {
#pragma clang diagnostic pop
[errorMessage acceptNewIdentityKey];
}
}];
@ -2679,7 +2676,7 @@ typedef enum : NSUInteger {
ConversationViewItem *lastViewItem = [self.viewItems lastObject];
OWSAssertDebug(lastViewItem);
if (lastViewItem.interaction.sortId > self.lastVisibleSortId) {
if (lastViewItem.interaction.timestampForSorting > self.lastVisibleTimestamp) {
shouldShowScrollDownButton = YES;
} else if (isScrolledUp) {
shouldShowScrollDownButton = YES;
@ -2778,6 +2775,7 @@ typedef enum : NSUInteger {
OWSAssertIsOnMainThread();
OWSAssertDebug(message);
[self updateLastVisibleTimestamp:message.timestampForSorting];
self.lastMessageSentDate = [NSDate new];
[self clearUnreadMessagesIndicator];
self.inputToolbar.quotedReply = nil;
@ -3329,7 +3327,7 @@ typedef enum : NSUInteger {
// using the more extreme actions in the debug UI.
OWSFailDebug(@"hasMalformedRowChange");
[self resetMappings];
[self updateLastVisibleSortId];
[self updateLastVisibleTimestamp];
[self scrollToBottomAnimated:NO];
return;
}
@ -3339,7 +3337,7 @@ typedef enum : NSUInteger {
// These errors are rare.
OWSFailDebug(@"could not reload view items; hard resetting message mappings.");
[self resetMappings];
[self updateLastVisibleSortId];
[self updateLastVisibleTimestamp];
[self scrollToBottomAnimated:NO];
return;
}
@ -3417,8 +3415,8 @@ typedef enum : NSUInteger {
if (!finished) {
OWSLogInfo(@"performBatchUpdates did not finish");
}
[self updateLastVisibleSortId];
[self updateLastVisibleTimestamp];
if (scrollToBottom && shouldAnimateUpdates) {
[self scrollToBottomAnimated:shouldAnimateScrollToBottom];
@ -3874,8 +3872,8 @@ typedef enum : NSUInteger {
ConversationViewItem *_Nullable lastVisibleViewItem = [self.viewItems lastObject];
if (lastVisibleViewItem) {
uint64_t lastVisibleSortId = lastVisibleViewItem.interaction.sortId;
self.lastVisibleSortId = MAX(self.lastVisibleSortId, lastVisibleSortId);
uint64_t lastVisibleTimestamp = lastVisibleViewItem.interaction.timestampForSorting;
self.lastVisibleTimestamp = MAX(self.lastVisibleTimestamp, lastVisibleTimestamp);
}
self.scrollDownButton.hidden = YES;
@ -3883,12 +3881,12 @@ typedef enum : NSUInteger {
self.hasUnreadMessages = NO;
}
- (void)updateLastVisibleSortId
- (void)updateLastVisibleTimestamp
{
ConversationViewItem *_Nullable lastVisibleViewItem = [self lastVisibleViewItem];
if (lastVisibleViewItem) {
uint64_t lastVisibleSortId = lastVisibleViewItem.interaction.sortId;
self.lastVisibleSortId = MAX(self.lastVisibleSortId, lastVisibleSortId);
uint64_t lastVisibleTimestamp = lastVisibleViewItem.interaction.timestampForSorting;
self.lastVisibleTimestamp = MAX(self.lastVisibleTimestamp, lastVisibleTimestamp);
}
[self ensureScrollDownButton];
@ -3901,6 +3899,15 @@ typedef enum : NSUInteger {
self.hasUnreadMessages = numberOfUnreadMessages > 0;
}
- (void)updateLastVisibleTimestamp:(uint64_t)timestamp
{
OWSAssertDebug(timestamp > 0);
self.lastVisibleTimestamp = MAX(self.lastVisibleTimestamp, timestamp);
[self ensureScrollDownButton];
}
- (void)markVisibleMessagesAsRead
{
if (self.presentedViewController) {
@ -3916,16 +3923,15 @@ typedef enum : NSUInteger {
return;
}
[self updateLastVisibleSortId];
[self updateLastVisibleTimestamp];
uint64_t lastVisibleSortId = self.lastVisibleSortId;
uint64_t lastVisibleTimestamp = self.lastVisibleTimestamp;
if (lastVisibleSortId == 0) {
if (lastVisibleTimestamp == 0) {
// No visible messages yet. New Thread.
return;
}
[OWSReadReceiptManager.sharedManager markAsReadLocallyBeforeSortId:self.lastVisibleSortId thread:self.thread];
[OWSReadReceiptManager.sharedManager markAsReadLocallyBeforeTimestamp:lastVisibleTimestamp thread:self.thread];
}
- (void)updateGroupModelTo:(TSGroupModel *)newGroupModel successCompletion:(void (^_Nullable)(void))successCompletion
@ -4322,7 +4328,7 @@ typedef enum : NSUInteger {
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self updateLastVisibleSortId];
[self updateLastVisibleTimestamp];
[self autoLoadMoreIfNecessary];
}
@ -4842,7 +4848,7 @@ typedef enum : NSUInteger {
{
OWSAssertIsOnMainThread();
[self updateLastVisibleSortId];
[self updateLastVisibleTimestamp];
self.conversationStyle.viewWidth = self.collectionView.width;
}
@ -4926,7 +4932,7 @@ typedef enum : NSUInteger {
break;
}
uint64_t viewItemTimestamp = viewItem.interaction.receivedAtTimestamp;
uint64_t viewItemTimestamp = viewItem.interaction.timestampForSorting;
OWSAssertDebug(viewItemTimestamp > 0);
BOOL shouldShowDate = NO;
@ -4958,15 +4964,17 @@ typedef enum : NSUInteger {
&& !((id<OWSReadTracking>)viewItem.interaction).wasRead);
if (isItemUnread && !unreadIndicator && !hasPlacedUnreadIndicator && !self.hasClearedUnreadMessagesIndicator) {
unreadIndicator = [[OWSUnreadIndicator alloc] initWithFirstUnseenSortId:viewItem.interaction.sortId
hasMoreUnseenMessages:NO
missingUnseenSafetyNumberChangeCount:0
unreadIndicatorPosition:0];
unreadIndicator =
[[OWSUnreadIndicator alloc] initUnreadIndicatorWithTimestamp:viewItem.interaction.timestamp
hasMoreUnseenMessages:NO
missingUnseenSafetyNumberChangeCount:0
unreadIndicatorPosition:0
firstUnseenInteractionTimestamp:viewItem.interaction.timestamp];
}
// Place the unread indicator onto the first appropriate view item,
// if any.
if (unreadIndicator && viewItem.interaction.sortId >= unreadIndicator.firstUnseenSortId) {
if (unreadIndicator && viewItem.interaction.timestampForSorting >= unreadIndicator.timestamp) {
viewItem.unreadIndicator = unreadIndicator;
unreadIndicator = nil;
hasPlacedUnreadIndicator = YES;
@ -5116,8 +5124,7 @@ typedef enum : NSUInteger {
}
}
// Avoid animation churn by supressing footer-collapse on messages received recently.
if (viewItem.interaction.receivedAtTimestamp > collapseCutoffTimestamp) {
if (viewItem.interaction.timestampForSorting > collapseCutoffTimestamp) {
shouldHideFooter = NO;
}

View File

@ -94,7 +94,7 @@ NS_ASSUME_NONNULL_BEGIN
NSUInteger index,
BOOL *stop) {
NSTimeInterval ageSeconds
= fabs(interaction.receivedAtDate.timeIntervalSinceNow);
= fabs(interaction.dateForSorting.timeIntervalSinceNow);
if (ageSeconds < maxAgeSeconds) {
*stop = YES;
return;

View File

@ -3441,7 +3441,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
[[OWSDisappearingMessagesConfiguration alloc] initWithThreadId:thread.uniqueId
enabled:YES
durationSeconds:(uint32_t)[durationSeconds intValue]];
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[OWSDisappearingConfigurationUpdateInfoMessage alloc]
initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
@ -3456,7 +3455,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
[[OWSDisappearingMessagesConfiguration alloc] initWithThreadId:thread.uniqueId
enabled:YES
durationSeconds:(uint32_t)[durationSeconds intValue]];
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[OWSDisappearingConfigurationUpdateInfoMessage alloc]
initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
@ -3471,7 +3469,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
[[OWSDisappearingMessagesConfiguration alloc] initWithThreadId:thread.uniqueId
enabled:YES
durationSeconds:(uint32_t)[durationSeconds intValue]];
// MJK TODO - remove senderTimestamp
[result addObject:[[OWSDisappearingConfigurationUpdateInfoMessage alloc]
initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
@ -3484,7 +3481,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
[[OWSDisappearingMessagesConfiguration alloc] initWithThreadId:thread.uniqueId
enabled:NO
durationSeconds:0];
// MJK TODO - remove senderTimestamp
[result addObject:[[OWSDisappearingConfigurationUpdateInfoMessage alloc]
initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
@ -3495,55 +3491,44 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
[result addObject:[TSInfoMessage userNotRegisteredMessageInThread:thread recipientId:@"+19174054215"]];
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageType:TSInfoMessageTypeSessionDidEnd]];
// TODO: customMessage?
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageType:TSInfoMessageTypeGroupUpdate]];
// TODO: customMessage?
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageType:TSInfoMessageTypeGroupQuit]];
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
recipientId:@"+19174054215"
verificationState:OWSVerificationStateDefault
isLocalChange:YES]];
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
recipientId:@"+19174054215"
verificationState:OWSVerificationStateVerified
isLocalChange:YES]];
// MJK - should be safe to remove this senderTimestamp
[result
addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
recipientId:@"+19174054215"
verificationState:OWSVerificationStateNoLongerVerified
isLocalChange:YES]];
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
recipientId:@"+19174054215"
verificationState:OWSVerificationStateDefault
isLocalChange:NO]];
// MJK - should be safe to remove this senderTimestamp
[result addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
recipientId:@"+19174054215"
verificationState:OWSVerificationStateVerified
isLocalChange:NO]];
// MJK - should be safe to remove this senderTimestamp
[result
addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
@ -3559,17 +3544,13 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
withTransaction:transaction]];
[result addObject:[TSErrorMessage corruptedMessageWithEnvelope:[self createEnvelopeForThread:thread]
withTransaction:transaction]];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
TSInvalidIdentityKeyReceivingErrorMessage *_Nullable blockingSNChangeMessage =
[TSInvalidIdentityKeyReceivingErrorMessage untrustedKeyWithEnvelope:[self createEnvelopeForThread:thread]
withTransaction:transaction];
#pragma clang diagnostic pop
OWSAssertDebug(blockingSNChangeMessage);
[result addObject:blockingSNChangeMessage];
// MJK TODO - should be safe to remove this senderTimestamp
[result addObject:[[TSErrorMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
failedMessageType:TSErrorMessageNonBlockingIdentityChange
@ -3732,10 +3713,9 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
OWSLogInfo(@"sendFakeMessages: %lu", (unsigned long)counter);
for (NSUInteger i = 0; i < counter; i++) {
NSString *randomText = [[self randomText] stringByAppendingFormat:@" (sequence: %lu)", (unsigned long)i + 1];
NSString *randomText = [self randomText];
switch (arc4random_uniform(isTextOnly ? 2 : 4)) {
case 0: {
// MJK - should be safe to remove this senderTimestamp
TSIncomingMessage *message =
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
@ -3773,7 +3753,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
attachmentType:TSAttachmentTypeDefault];
pointer.state = TSAttachmentPointerStateFailed;
[pointer saveWithTransaction:transaction];
// MJK - should be safe to remove this senderTimestamp
TSIncomingMessage *message =
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
@ -4172,7 +4151,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
OWSDisappearingMessagesConfiguration *configuration =
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId
transaction:initialTransaction];
// MJK TODO - remove senderTimestamp
TSOutgoingMessage *message = [[TSOutgoingMessage alloc]
initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
@ -4240,7 +4218,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
for (NSNumber *timestamp in timestamps) {
NSString *randomText = [self randomText];
{
// Legit usage of SenderTimestamp to backdate incoming sent messages for Debug
TSIncomingMessage *message =
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp.unsignedLongLongValue
inThread:thread
@ -4254,7 +4231,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
[message markAsReadNowWithSendReadReceipt:NO transaction:transaction];
}
{
// MJK TODO - this might be the one place we actually use senderTimestamp
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:timestamp.unsignedLongLongValue
inThread:thread
@ -4281,8 +4257,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
+ (void)createDisappearingMessagesWhichFailedToStartInThread:(TSThread *)thread
{
uint64_t now = [NSDate ows_millisecondTimeStamp];
// MJK TODO - should be safe to remove this senderTimestamp
TSIncomingMessage *message = [[TSIncomingMessage alloc]
initIncomingMessageWithTimestamp:now
inThread:thread
@ -4516,7 +4490,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
[attachmentIds addObject:attachmentId];
}
// MJK TODO - remove senderTimestamp
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
@ -4606,7 +4579,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac
// uint64_t millisAgo = (uint64_t)(((double)arc4random() / ((double)0xffffffff)) * yearsMillis);
// uint64_t timestamp = [NSDate ows_millisecondTimeStamp] - millisAgo;
// MJK TODO - should be safe to remove this senderTimestamp
TSIncomingMessage *message =
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread

View File

@ -41,7 +41,6 @@ class DebugUIProfile: DebugUIPage {
OWSTableItem(title: "Send Profile Key Message") { [weak self] in
guard let strongSelf = self else { return }
// MJK TODO - should be safe to remove this senderTimestamp
let message = OWSProfileKeyMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: aThread)
strongSelf.messageSender.sendPromise(message: message).then {
Logger.info("Successfully sent profile key message to thread: \(String(describing: aThread))")

View File

@ -54,7 +54,7 @@ public struct GalleryDate: Hashable, Comparable, Equatable {
let month: Int
init(message: TSMessage) {
let date = message.receivedAtDate()
let date = message.dateForSorting()
self.year = Calendar.current.component(.year, from: date)
self.month = Calendar.current.component(.month, from: date)
@ -730,13 +730,13 @@ class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSourc
Bench(title: "sorting gallery items") {
galleryItems.sort { lhs, rhs -> Bool in
return lhs.message.sortId < rhs.message.sortId
return lhs.message.timestampForSorting() < rhs.message.timestampForSorting()
}
sectionDates.sort()
for (date, galleryItems) in sections {
sortedSections[date] = galleryItems.sorted { lhs, rhs -> Bool in
return lhs.message.sortId < rhs.message.sortId
return lhs.message.timestampForSorting() < rhs.message.timestampForSorting()
}
}
}

View File

@ -294,7 +294,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
if message as? TSIncomingMessage != nil {
rows.append(valueRow(name: NSLocalizedString("MESSAGE_METADATA_VIEW_RECEIVED_DATE_TIME",
comment: "Label for the 'received date & time' field of the 'message metadata' view."),
value: DateUtil.formatPastTimestampRelativeToNow(message.receivedAtTimestamp)))
value: DateUtil.formatPastTimestampRelativeToNow(message.timestampForSorting())))
}
rows += addAttachmentMetadataRows()

View File

@ -464,7 +464,6 @@ NS_ASSUME_NONNULL_BEGIN
// Add an error message to the new group indicating
// that group creation didn't succeed.
// MJK TODO should be safe to remove senderTimestamp and just save immediately
TSErrorMessage *errorMessage = [[TSErrorMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
failedMessageType:TSErrorMessageGroupCreationFailed];

View File

@ -909,9 +909,7 @@ const CGFloat kIconViewLength = 24;
}
if (self.disappearingMessagesConfiguration.dictionaryValueDidChange) {
// TODO - put these two saves in a single transaction
[self.disappearingMessagesConfiguration save];
// MJK TODO - should be safe to remove this senderTimestamp
OWSDisappearingConfigurationUpdateInfoMessage *infoMessage =
[[OWSDisappearingConfigurationUpdateInfoMessage alloc]
initWithTimestamp:[NSDate ows_millisecondTimeStamp]

View File

@ -372,7 +372,6 @@ private class SignalCallData: NSObject {
let callData = SignalCallData(call: call)
self.callData = callData
// MJK TODO remove this timestamp param
let callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(), withCallNumber: call.remotePhoneNumber, callType: RPRecentCallTypeOutgoingIncomplete, in: call.thread)
callRecord.save()
call.callRecord = callRecord
@ -528,7 +527,6 @@ private class SignalCallData: NSObject {
callRecord.updateCallType(RPRecentCallTypeIncomingMissed)
}
} else {
// MJK TODO remove this timestamp param
call.callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(),
withCallNumber: call.thread.contactIdentifier(),
callType: RPRecentCallTypeIncomingMissed,
@ -615,7 +613,6 @@ private class SignalCallData: NSObject {
self.notificationsAdapter.presentMissedCallBecauseOfNoLongerVerifiedIdentity(call: newCall, callerName: callerName)
}
// MJK TODO remove this timestamp param
let callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(),
withCallNumber: thread.contactIdentifier(),
callType: RPRecentCallTypeIncomingMissedBecauseOfChangedIdentity,
@ -1038,7 +1035,6 @@ private class SignalCallData: NSObject {
Logger.info("\(call.identifiersForLogs).")
// MJK TODO remove this timestamp param
let callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(), withCallNumber: call.remotePhoneNumber, callType: RPRecentCallTypeIncomingIncomplete, in: call.thread)
callRecord.save()
call.callRecord = callRecord
@ -1128,7 +1124,6 @@ private class SignalCallData: NSObject {
owsFailDebug("Not expecting callrecord to already be set")
callRecord.updateCallType(RPRecentCallTypeIncomingDeclined)
} else {
// MJK TODO remove this timestamp param
let callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(), withCallNumber: call.remotePhoneNumber, callType: RPRecentCallTypeIncomingDeclined, in: call.thread)
callRecord.save()
call.callRecord = callRecord

View File

@ -4,8 +4,6 @@
#import <SignalServiceKit/TSInteraction.h>
@class YapDatabaseReadWriteTransaction;
NS_ASSUME_NONNULL_BEGIN
@interface OWSContactOffersInteraction : TSInteraction
@ -13,16 +11,12 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) BOOL hasBlockOffer;
@property (nonatomic, readonly) BOOL hasAddToContactsOffer;
@property (nonatomic, readonly) BOOL hasAddToProfileWhitelistOffer;
// TODO - remove this recipientId param
// it's redundant with the interaction's TSContactThread
@property (nonatomic, readonly) NSString *recipientId;
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
// MJK TODO should be safe to remove this timestamp param
- (instancetype)initContactOffersWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasBlockOffer:(BOOL)hasBlockOffer
@ -30,11 +24,6 @@ NS_ASSUME_NONNULL_BEGIN
hasAddToProfileWhitelistOffer:(BOOL)hasAddToProfileWhitelistOffer
recipientId:(NSString *)recipientId NS_DESIGNATED_INITIALIZER;
- (void)updateHasBlockOffer:(BOOL)hasBlockOffer
hasAddToContactsOffer:(BOOL)hasAddToContactsOffer
hasAddToProfileWhitelistOffer:(BOOL)hasAddToProfileWhitelistOffer
transaction:(YapDatabaseReadWriteTransaction *)transaction;
@end
NS_ASSUME_NONNULL_END

View File

@ -6,14 +6,6 @@
NS_ASSUME_NONNULL_BEGIN
@interface OWSContactOffersInteraction ()
@property (nonatomic) BOOL hasBlockOffer;
@property (nonatomic) BOOL hasAddToContactsOffer;
@property (nonatomic) BOOL hasAddToProfileWhitelistOffer;
@end
@implementation OWSContactOffersInteraction
- (instancetype)initWithCoder:(NSCoder *)coder
@ -60,18 +52,6 @@ NS_ASSUME_NONNULL_BEGIN
return OWSInteractionType_Offer;
}
- (void)updateHasBlockOffer:(BOOL)hasBlockOffer
hasAddToContactsOffer:(BOOL)hasAddToContactsOffer
hasAddToProfileWhitelistOffer:(BOOL)hasAddToProfileWhitelistOffer
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSContactOffersInteraction *offers) {
offers.hasBlockOffer = hasBlockOffer;
offers.hasAddToContactsOffer = hasAddToContactsOffer;
offers.hasAddToProfileWhitelistOffer = hasAddToProfileWhitelistOffer;
}];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -7,7 +7,6 @@
NS_ASSUME_NONNULL_BEGIN
// This class is vestigial.
__attribute__((deprecated))
@interface TSUnreadIndicatorInteraction : TSInteraction
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View File

@ -6,10 +6,7 @@
NS_ASSUME_NONNULL_BEGIN
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
@implementation TSUnreadIndicatorInteraction
#pragma clang diagnostic pop
- (instancetype)initWithCoder:(NSCoder *)coder
{

View File

@ -50,6 +50,7 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
#import <SignalMessaging/SelectRecipientViewController.h>
#import <SignalMessaging/SharingThreadPickerViewController.h>
#import <SignalMessaging/SignalKeyingStorage.h>
#import <SignalMessaging/TSUnreadIndicatorInteraction.h>
#import <SignalMessaging/Theme.h>
#import <SignalMessaging/ThreadUtil.h>
#import <SignalMessaging/ThreadViewHelper.h>

View File

@ -241,7 +241,6 @@ NS_ASSUME_NONNULL_BEGIN
{
NSArray *attachments = self.attachmentStream ? @[ self.attachmentStream ] : @[];
// Legit usage of senderTimestamp to reference existing message
return [[TSQuotedMessage alloc] initWithTimestamp:self.timestamp
authorId:self.authorId
body:self.body

View File

@ -25,14 +25,12 @@ public class ThreadViewModel: NSObject {
@objc
public init(thread: TSThread, transaction: YapDatabaseReadTransaction) {
self.threadRecord = thread
self.lastMessageDate = thread.lastMessageDate()
self.isGroupThread = thread.isGroupThread()
self.name = thread.name()
self.isMuted = thread.isMuted
self.lastMessageText = thread.lastMessageText(transaction: transaction)
let lastInteraction = thread.lastInteractionForInbox(transaction: transaction)
self.lastMessageForInbox = lastInteraction
self.lastMessageDate = lastInteraction?.receivedAtDate() ?? thread.creationDate
self.lastMessageForInbox = thread.lastInteractionForInbox(transaction: transaction)
if let contactThread = thread as? TSContactThread {
self.contactIdentifier = contactThread.contactIdentifier()

View File

@ -1,82 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
class OWS110SortIdMigration: OWSDatabaseMigration {
// increment a similar constant for each migration.
@objc
class func migrationId() -> String {
return "110"
}
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
Logger.debug("")
BenchAsync(title: "Sort Migration") { completeBenchmark in
self.doMigration {
completeBenchmark()
completion()
}
}
}
private func doMigration(completion: @escaping OWSDatabaseMigrationCompletion) {
// TODO batch this?
self.dbReadWriteConnection().readWrite { transaction in
var archivedThreads: [TSThread] = []
// get archived threads before migration
TSThread.enumerateCollectionObjects(with: transaction) { (object, _) in
guard let thread = object as? TSThread else {
owsFailDebug("unexpected object: \(type(of: object))")
return
}
if thread.isArchivedByLegacyTimestampForSorting {
archivedThreads.append(thread)
}
}
guard let legacySorting: YapDatabaseAutoViewTransaction = transaction.extension(TSMessageDatabaseViewExtensionName_Legacy) as? YapDatabaseAutoViewTransaction else {
owsFailDebug("legacySorting was unexpectedly nil")
return
}
let totalCount: UInt = legacySorting.numberOfItemsInAllGroups()
var completedCount: UInt = 0
legacySorting.enumerateGroups { group, _ in
autoreleasepool {
legacySorting.enumerateKeysAndObjects(inGroup: group) { (_, _, object, _, _) in
autoreleasepool {
guard let interaction = object as? TSInteraction else {
owsFailDebug("unexpected object: \(type(of: object))")
return
}
interaction.saveNextSortId(transaction: transaction)
completedCount += 1
if completedCount % 100 == 0 {
// Legit usage of legacy sorting for migration to new sorting
Logger.info("thread: \(interaction.uniqueThreadId), timestampForLegacySorting:\(interaction.timestampForLegacySorting()), sortId: \(interaction.sortId) totalCount: \(totalCount), completedcount: \(completedCount)")
}
}
}
}
}
Logger.info("re-archiving \(archivedThreads.count) threads which were previously archived")
for archivedThread in archivedThreads {
archivedThread.archiveThread(with: transaction)
}
self.save(with: transaction)
}
completion()
}
}

View File

@ -44,8 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
[[OWS106EnsureProfileComplete alloc] initWithPrimaryStorage:primaryStorage],
[[OWS107LegacySounds alloc] initWithPrimaryStorage:primaryStorage],
[[OWS108CallLoggingPreference alloc] initWithPrimaryStorage:primaryStorage],
[[OWS109OutgoingMessageState alloc] initWithPrimaryStorage:primaryStorage],
[[OWS110SortIdMigration alloc] initWithPrimaryStorage:primaryStorage]
[[OWS109OutgoingMessageState alloc] initWithPrimaryStorage:primaryStorage]
];
}

View File

@ -1124,7 +1124,6 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
{
OWSAssertIsOnMainThread();
// MJK TODO - should be safe to remove this senderTimestamp
OWSProfileKeyMessage *message =
[[OWSProfileKeyMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread];

View File

@ -4,16 +4,7 @@
import Foundation
/// Benchmark async code by calling the passed in block parameter when the work
/// is done.
///
/// BenchAsync(title: "my benchmark") { completeBenchmark in
/// foo {
/// completeBenchmark()
/// fooCompletion()
/// }
/// }
public func BenchAsync(title: String, block: (@escaping () -> Void) -> Void) {
public func BenchAsync(title: String, block: (() -> Void) -> Void) {
let startTime = CFAbsoluteTimeGetCurrent()
block {

View File

@ -5,21 +5,7 @@
import Foundation
import SignalServiceKit
public typealias MessageSortKey = UInt64
public struct ConversationSortKey: Comparable {
let creationDate: Date
let lastMessageReceivedAtDate: Date?
// MARK: Comparable
public static func < (lhs: ConversationSortKey, rhs: ConversationSortKey) -> Bool {
let lhsDate = lhs.lastMessageReceivedAtDate ?? lhs.creationDate
let rhsDate = rhs.lastMessageReceivedAtDate ?? rhs.creationDate
return lhsDate < rhsDate
}
}
public class ConversationSearchResult<SortKey>: Comparable where SortKey: Comparable {
public class ConversationSearchResult: Comparable {
public let thread: ThreadViewModel
public let messageId: String?
@ -27,9 +13,9 @@ public class ConversationSearchResult<SortKey>: Comparable where SortKey: Compar
public let snippet: String?
private let sortKey: SortKey
private let sortKey: UInt64
init(thread: ThreadViewModel, sortKey: SortKey, messageId: String? = nil, messageDate: Date? = nil, snippet: String? = nil) {
init(thread: ThreadViewModel, sortKey: UInt64, messageId: String? = nil, messageDate: Date? = nil, snippet: String? = nil) {
self.thread = thread
self.sortKey = sortKey
self.messageId = messageId
@ -79,11 +65,11 @@ public class ContactSearchResult: Comparable {
public class SearchResultSet {
public let searchText: String
public let conversations: [ConversationSearchResult<ConversationSortKey>]
public let conversations: [ConversationSearchResult]
public let contacts: [ContactSearchResult]
public let messages: [ConversationSearchResult<MessageSortKey>]
public let messages: [ConversationSearchResult]
public init(searchText: String, conversations: [ConversationSearchResult<ConversationSortKey>], contacts: [ContactSearchResult], messages: [ConversationSearchResult<MessageSortKey>]) {
public init(searchText: String, conversations: [ConversationSearchResult], contacts: [ContactSearchResult], messages: [ConversationSearchResult]) {
self.searchText = searchText
self.conversations = conversations
self.contacts = contacts
@ -115,9 +101,9 @@ public class ConversationSearcher: NSObject {
transaction: YapDatabaseReadTransaction,
contactsManager: ContactsManagerProtocol) -> SearchResultSet {
var conversations: [ConversationSearchResult<ConversationSortKey>] = []
var conversations: [ConversationSearchResult] = []
var contacts: [ContactSearchResult] = []
var messages: [ConversationSearchResult<MessageSortKey>] = []
var messages: [ConversationSearchResult] = []
var existingConversationRecipientIds: Set<String> = Set()
@ -125,8 +111,7 @@ public class ConversationSearcher: NSObject {
if let thread = match as? TSThread {
let threadViewModel = ThreadViewModel(thread: thread, transaction: transaction)
let sortKey = ConversationSortKey(creationDate: thread.creationDate,
lastMessageReceivedAtDate: thread.lastInteractionForInbox(transaction: transaction)?.receivedAtDate())
let sortKey = NSDate.ows_millisecondsSince1970(for: threadViewModel.lastMessageDate)
let searchResult = ConversationSearchResult(thread: threadViewModel, sortKey: sortKey)
if let contactThread = thread as? TSContactThread {
@ -139,7 +124,7 @@ public class ConversationSearcher: NSObject {
let thread = message.thread(with: transaction)
let threadViewModel = ThreadViewModel(thread: thread, transaction: transaction)
let sortKey = message.sortId
let sortKey = message.timestamp
let searchResult = ConversationSearchResult(thread: threadViewModel,
sortKey: sortKey,
messageId: message.uniqueId,

View File

@ -6,11 +6,13 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSUnreadIndicator : NSObject
@property (nonatomic, readonly) uint64_t timestamp;
@property (nonatomic, readonly) BOOL hasMoreUnseenMessages;
@property (nonatomic, readonly) NSUInteger missingUnseenSafetyNumberChangeCount;
// The sortId of the oldest unseen message.
// The timestamp of the oldest unseen message.
//
// Once we enter messages view, we mark all messages read, so we need
// a snapshot of what the first unread message was when we entered the
@ -18,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
// repeatedly. The unread indicator should continue to show up until
// it has been cleared, at which point hideUnreadMessagesIndicator is
// YES in ensureDynamicInteractionsForThread:...
@property (nonatomic, readonly) uint64_t firstUnseenSortId;
@property (nonatomic, readonly) uint64_t firstUnseenInteractionTimestamp;
// The index of the unseen indicator, counting from the _end_ of the conversation
// history.
@ -30,10 +32,11 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithFirstUnseenSortId:(uint64_t)firstUnseenSortId
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:(NSInteger)unreadIndicatorPosition NS_DESIGNATED_INITIALIZER;
- (instancetype)initUnreadIndicatorWithTimestamp:(uint64_t)timestamp
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:(NSInteger)unreadIndicatorPosition
firstUnseenInteractionTimestamp:(uint64_t)firstUnseenInteractionTimestamp NS_DESIGNATED_INITIALIZER;
@end

View File

@ -8,10 +8,11 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSUnreadIndicator
- (instancetype)initWithFirstUnseenSortId:(uint64_t)firstUnseenSortId
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:(NSInteger)unreadIndicatorPosition
- (instancetype)initUnreadIndicatorWithTimestamp:(uint64_t)timestamp
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:(NSInteger)unreadIndicatorPosition
firstUnseenInteractionTimestamp:(uint64_t)firstUnseenInteractionTimestamp
{
self = [super init];
@ -19,10 +20,11 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
_firstUnseenSortId = firstUnseenSortId;
_timestamp = timestamp;
_hasMoreUnseenMessages = hasMoreUnseenMessages;
_missingUnseenSafetyNumberChangeCount = missingUnseenSafetyNumberChangeCount;
_unreadIndicatorPosition = unreadIndicatorPosition;
_firstUnseenInteractionTimestamp = firstUnseenInteractionTimestamp;
return self;
}
@ -38,8 +40,7 @@ NS_ASSUME_NONNULL_BEGIN
}
OWSUnreadIndicator *other = object;
return (self.firstUnseenSortId == other.firstUnseenSortId
&& self.hasMoreUnseenMessages == other.hasMoreUnseenMessages
return (self.timestamp == other.timestamp && self.hasMoreUnseenMessages == other.hasMoreUnseenMessages
&& self.missingUnseenSafetyNumberChangeCount == other.missingUnseenSafetyNumberChangeCount
&& self.unreadIndicatorPosition == other.unreadIndicatorPosition);
}

View File

@ -128,7 +128,6 @@ NS_ASSUME_NONNULL_BEGIN
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
uint32_t expiresInSeconds = (configuration.isEnabled ? configuration.durationSeconds : 0);
// MJK TODO - remove senderTimestamp
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
@ -180,7 +179,6 @@ NS_ASSUME_NONNULL_BEGIN
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
uint32_t expiresInSeconds = (configuration.isEnabled ? configuration.durationSeconds : 0);
// MJK TODO - remove senderTimestamp
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
@ -305,31 +303,20 @@ NS_ASSUME_NONNULL_BEGIN
enumerateRowsInGroup:thread.uniqueId
usingBlock:^(
NSString *collection, NSString *key, id object, id metadata, NSUInteger index, BOOL *stop) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if ([object isKindOfClass:[OWSUnknownContactBlockOfferMessage class]]) {
#pragma clang diagnostic pop
// Delete this legacy interactions, which has been superseded by
// the OWSContactOffersInteraction.
[interactionsToDelete addObject:object];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
} else if ([object isKindOfClass:[OWSAddToContactsOfferMessage class]]) {
#pragma clang diagnostic pop
// Delete this legacy interactions, which has been superseded by
// the OWSContactOffersInteraction.
[interactionsToDelete addObject:object];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
} else if ([object isKindOfClass:[OWSAddToProfileWhitelistOfferMessage class]]) {
#pragma clang diagnostic pop
// Delete this legacy interactions, which has been superseded by
// the OWSContactOffersInteraction.
[interactionsToDelete addObject:object];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
} else if ([object isKindOfClass:[TSUnreadIndicatorInteraction class]]) {
#pragma clang diagnostic pop
// Remove obsolete unread indicator interactions;
[interactionsToDelete addObject:object];
} else if ([object isKindOfClass:[OWSContactOffersInteraction class]]) {
@ -363,14 +350,14 @@ NS_ASSUME_NONNULL_BEGIN
// have been marked as read.
//
// IFF this variable is non-null, there are unseen messages in the thread.
NSNumber *_Nullable firstUnseenSortId = nil;
NSNumber *_Nullable firstUnseenInteractionTimestamp = nil;
if (lastUnreadIndicator) {
firstUnseenSortId = @(lastUnreadIndicator.firstUnseenSortId);
firstUnseenInteractionTimestamp = @(lastUnreadIndicator.firstUnseenInteractionTimestamp);
} else {
TSInteraction *_Nullable firstUnseenInteraction =
[[TSDatabaseView unseenDatabaseViewExtension:transaction] firstObjectInGroup:thread.uniqueId];
if (firstUnseenInteraction) {
firstUnseenSortId = @(firstUnseenInteraction.sortId);
firstUnseenInteractionTimestamp = @(firstUnseenInteraction.timestampForSorting);
}
}
@ -481,51 +468,59 @@ NS_ASSUME_NONNULL_BEGIN
}
}
if (existingContactOffers && !shouldHaveContactOffers) {
OWSLogInfo(
@"Removing contact offers: %@ (%llu)", existingContactOffers.uniqueId, existingContactOffers.sortId);
[existingContactOffers removeWithTransaction:transaction];
} else if (shouldHaveContactOffers) {
if (existingContactOffers) {
// If the contact offers' properties have changed, update them
if (existingContactOffers.hasBlockOffer != shouldHaveBlockOffer
|| existingContactOffers.hasAddToContactsOffer != shouldHaveAddToContactsOffer
|| existingContactOffers.hasAddToProfileWhitelistOffer != shouldHaveAddToProfileWhitelistOffer) {
OWSLogInfo(@"Updating stale contact offers: %@ (%llu)",
existingContactOffers.uniqueId,
existingContactOffers.sortId);
// We want the offers to be the first interactions in their
// conversation's timeline, so we back-date them to slightly before
// the first message - or at an aribtrary old timestamp if the
// conversation has no messages.
uint64_t contactOffersTimestamp = [NSDate ows_millisecondTimeStamp];
[existingContactOffers updateHasBlockOffer:shouldHaveBlockOffer
hasAddToContactsOffer:shouldHaveAddToContactsOffer
hasAddToProfileWhitelistOffer:shouldHaveAddToProfileWhitelistOffer
transaction:transaction];
}
} else {
NSString *recipientId = ((TSContactThread *)thread).contactIdentifier;
// TODO MJK - remove this timestamp
TSInteraction *offersMessage = [[OWSContactOffersInteraction alloc]
initContactOffersWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
hasBlockOffer:shouldHaveBlockOffer
hasAddToContactsOffer:shouldHaveAddToContactsOffer
hasAddToProfileWhitelistOffer:shouldHaveAddToProfileWhitelistOffer
recipientId:recipientId];
[offersMessage saveWithTransaction:transaction];
OWSLogInfo(@"Creating contact offers: %@ (%llu)", offersMessage.uniqueId, offersMessage.sortId);
// If the contact offers' properties have changed, discard the current
// one and create a new one.
if (existingContactOffers) {
if (existingContactOffers.hasBlockOffer != shouldHaveBlockOffer
|| existingContactOffers.hasAddToContactsOffer != shouldHaveAddToContactsOffer
|| existingContactOffers.hasAddToProfileWhitelistOffer != shouldHaveAddToProfileWhitelistOffer) {
OWSLogInfo(@"Removing stale contact offers: %@ (%llu)",
existingContactOffers.uniqueId,
existingContactOffers.timestampForSorting);
// Preserve the timestamp of the existing "contact offers" so that
// we replace it in the same position in the timeline.
contactOffersTimestamp = existingContactOffers.timestamp;
[existingContactOffers removeWithTransaction:transaction];
existingContactOffers = nil;
}
}
if (existingContactOffers && !shouldHaveContactOffers) {
OWSLogInfo(@"Removing contact offers: %@ (%llu)",
existingContactOffers.uniqueId,
existingContactOffers.timestampForSorting);
[existingContactOffers removeWithTransaction:transaction];
} else if (!existingContactOffers && shouldHaveContactOffers) {
NSString *recipientId = ((TSContactThread *)thread).contactIdentifier;
TSInteraction *offersMessage =
[[OWSContactOffersInteraction alloc] initContactOffersWithTimestamp:contactOffersTimestamp
thread:thread
hasBlockOffer:shouldHaveBlockOffer
hasAddToContactsOffer:shouldHaveAddToContactsOffer
hasAddToProfileWhitelistOffer:shouldHaveAddToProfileWhitelistOffer
recipientId:recipientId];
[offersMessage saveWithTransaction:transaction];
OWSLogInfo(
@"Creating contact offers: %@ (%llu)", offersMessage.uniqueId, offersMessage.timestampForSorting);
}
[self ensureUnreadIndicator:result
thread:thread
transaction:transaction
shouldHaveContactOffers:shouldHaveContactOffers
maxRangeSize:maxRangeSize
blockingSafetyNumberChanges:blockingSafetyNumberChanges
nonBlockingSafetyNumberChanges:nonBlockingSafetyNumberChanges
hideUnreadMessagesIndicator:hideUnreadMessagesIndicator
firstUnseenSortId:firstUnseenSortId];
thread:thread
transaction:transaction
shouldHaveContactOffers:shouldHaveContactOffers
maxRangeSize:maxRangeSize
blockingSafetyNumberChanges:blockingSafetyNumberChanges
nonBlockingSafetyNumberChanges:nonBlockingSafetyNumberChanges
hideUnreadMessagesIndicator:hideUnreadMessagesIndicator
firstUnseenInteractionTimestamp:firstUnseenInteractionTimestamp];
// Determine the position of the focus message _after_ performing any mutations
// around dynamic interactions.
@ -539,14 +534,14 @@ NS_ASSUME_NONNULL_BEGIN
}
+ (void)ensureUnreadIndicator:(ThreadDynamicInteractions *)dynamicInteractions
thread:(TSThread *)thread
transaction:(YapDatabaseReadWriteTransaction *)transaction
shouldHaveContactOffers:(BOOL)shouldHaveContactOffers
maxRangeSize:(int)maxRangeSize
blockingSafetyNumberChanges:(NSArray<TSInvalidIdentityKeyErrorMessage *> *)blockingSafetyNumberChanges
nonBlockingSafetyNumberChanges:(NSArray<TSInteraction *> *)nonBlockingSafetyNumberChanges
hideUnreadMessagesIndicator:(BOOL)hideUnreadMessagesIndicator
firstUnseenSortId:(nullable NSNumber *)firstUnseenSortId
thread:(TSThread *)thread
transaction:(YapDatabaseReadWriteTransaction *)transaction
shouldHaveContactOffers:(BOOL)shouldHaveContactOffers
maxRangeSize:(int)maxRangeSize
blockingSafetyNumberChanges:(NSArray<TSInvalidIdentityKeyErrorMessage *> *)blockingSafetyNumberChanges
nonBlockingSafetyNumberChanges:(NSArray<TSInteraction *> *)nonBlockingSafetyNumberChanges
hideUnreadMessagesIndicator:(BOOL)hideUnreadMessagesIndicator
firstUnseenInteractionTimestamp:(nullable NSNumber *)firstUnseenInteractionTimestamp
{
OWSAssertDebug(dynamicInteractions);
OWSAssertDebug(thread);
@ -557,7 +552,7 @@ NS_ASSUME_NONNULL_BEGIN
if (hideUnreadMessagesIndicator) {
return;
}
if (!firstUnseenSortId) {
if (!firstUnseenInteractionTimestamp) {
// If there are no unseen interactions, don't show an unread indicator.
return;
}
@ -593,7 +588,7 @@ NS_ASSUME_NONNULL_BEGIN
return;
}
if (interaction.sortId < firstUnseenSortId.unsignedLongLongValue) {
if (interaction.timestampForSorting < firstUnseenInteractionTimestamp.unsignedLongLongValue) {
// By default we want the unread indicator to appear just before
// the first unread message.
*stop = YES;
@ -625,12 +620,13 @@ NS_ASSUME_NONNULL_BEGIN
if (hasMoreUnseenMessages) {
NSMutableSet<NSData *> *missingUnseenSafetyNumberChanges = [NSMutableSet set];
for (TSInvalidIdentityKeyErrorMessage *safetyNumberChange in blockingSafetyNumberChanges) {
BOOL isUnseen = safetyNumberChange.sortId >= firstUnseenSortId.unsignedLongLongValue;
BOOL isUnseen
= safetyNumberChange.timestampForSorting >= firstUnseenInteractionTimestamp.unsignedLongLongValue;
if (!isUnseen) {
continue;
}
BOOL isMissing = safetyNumberChange.sortId < interactionAfterUnreadIndicator.sortId;
BOOL isMissing
= safetyNumberChange.timestampForSorting < interactionAfterUnreadIndicator.timestampForSorting;
if (!isMissing) {
continue;
}
@ -655,12 +651,13 @@ NS_ASSUME_NONNULL_BEGIN
unreadIndicatorPosition++;
}
dynamicInteractions.unreadIndicator =
[[OWSUnreadIndicator alloc] initWithFirstUnseenSortId:firstUnseenSortId.unsignedLongLongValue
hasMoreUnseenMessages:hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:unreadIndicatorPosition];
OWSLogInfo(@"Creating Unread Indicator: %llu", dynamicInteractions.unreadIndicator.firstUnseenSortId);
dynamicInteractions.unreadIndicator = [[OWSUnreadIndicator alloc]
initUnreadIndicatorWithTimestamp:interactionAfterUnreadIndicator.timestampForSorting
hasMoreUnseenMessages:hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:unreadIndicatorPosition
firstUnseenInteractionTimestamp:firstUnseenInteractionTimestamp.unsignedLongLongValue];
OWSLogInfo(@"Creating Unread Indicator: %llu", dynamicInteractions.unreadIndicator.timestamp);
}
+ (nullable NSNumber *)focusMessagePositionForThread:(TSThread *)thread

View File

@ -18,8 +18,6 @@ NS_ASSUME_NONNULL_BEGIN
// YES IFF this thread has ever had a message.
@property (nonatomic) BOOL hasEverHadMessage;
@property (nonatomic, readonly) NSDate *creationDate;
@property (nonatomic, readonly) BOOL isArchivedByLegacyTimestampForSorting;
/**
* Whether the object is a group thread or not.
@ -61,10 +59,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Get all messages in the thread we weren't able to decrypt
*/
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (NSArray<TSInvalidIdentityKeyReceivingErrorMessage *> *)receivedMessagesForInvalidKey:(NSData *)key;
#pragma clang diagnostic pop
- (NSUInteger)unreadMessageCountWithTransaction:(YapDatabaseReadTransaction *)transaction
NS_SWIFT_NAME(unreadMessageCount(transaction:));
@ -73,6 +68,14 @@ NS_ASSUME_NONNULL_BEGIN
- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
/**
* Returns the latest date of a message in the thread or the thread creation date if there are no messages in that
*thread.
*
* @return The date of the last message or thread creation date.
*/
- (NSDate *)lastMessageDate;
/**
* Returns the string that will be displayed typically in a conversations view as a preview of the last message
*received in this thread.
@ -96,19 +99,31 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark Archival
/**
* @return YES if no new messages have been sent or received since the thread was last archived.
* Returns the last date at which a string was archived or nil if the thread was never archived or brought back to the
*inbox.
*
* @return Last archival date.
*/
- (BOOL)isArchivedWithTransaction:(YapDatabaseReadTransaction *)transaction;
- (nullable NSDate *)archivalDate;
/**
* Archives a thread
* Archives a thread with the current date.
*
* @param transaction Database transaction.
*/
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
/**
* Unarchives a thread
* Archives a thread with the reference date. This is currently only used for migrating older data that has already
* been archived.
*
* @param transaction Database transaction.
* @param date Date at which the thread was archived.
*/
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction referenceDate:(NSDate *)date;
/**
* Unarchives a thread that was archived previously.
*
* @param transaction Database transaction.
*/

View File

@ -15,7 +15,6 @@
#import "TSInteraction.h"
#import "TSInvalidIdentityKeyReceivingErrorMessage.h"
#import "TSOutgoingMessage.h"
#import <SignalServiceKit/SignalServiceKit-Swift.h>
#import <YapDatabase/YapDatabase.h>
NS_ASSUME_NONNULL_BEGIN
@ -23,8 +22,10 @@ NS_ASSUME_NONNULL_BEGIN
@interface TSThread ()
@property (nonatomic) NSDate *creationDate;
@property (nonatomic, copy, nullable) NSDate *archivalDate;
@property (nonatomic) NSString *conversationColorName;
@property (nonatomic) NSNumber *archivedAsOfMessageSortId;
@property (nonatomic, nullable) NSDate *lastMessageDate;
@property (nonatomic, copy, nullable) NSString *messageDraft;
@property (atomic, nullable) NSDate *mutedUntilDate;
@ -43,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN
self = [super initWithUniqueId:uniqueId];
if (self) {
_archivalDate = nil;
_lastMessageDate = nil;
_creationDate = [NSDate date];
_messageDraft = nil;
@ -74,12 +77,7 @@ NS_ASSUME_NONNULL_BEGIN
_conversationColorName = [self.class stableConversationColorNameForString:self.uniqueId];
}
}
NSDate *_Nullable lastMessageDate = [coder decodeObjectOfClass:NSDate.class forKey:@"lastMessageDate"];
NSDate *_Nullable archivalDate = [coder decodeObjectOfClass:NSDate.class forKey:@"archivalDate"];
_isArchivedByLegacyTimestampForSorting =
[self.class legacyIsArchivedWithLastMessageDate:lastMessageDate archivalDate:archivalDate];
return self;
}
@ -209,8 +207,6 @@ NS_ASSUME_NONNULL_BEGIN
return [interactions copy];
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (NSArray<TSInvalidIdentityKeyReceivingErrorMessage *> *)receivedMessagesForInvalidKey:(NSData *)key
{
NSMutableArray *errorMessages = [NSMutableArray new];
@ -225,7 +221,6 @@ NS_ASSUME_NONNULL_BEGIN
return [errorMessages copy];
}
#pragma clang diagnostic pop
- (NSUInteger)numberOfInteractions
{
@ -303,6 +298,14 @@ NS_ASSUME_NONNULL_BEGIN
return last;
}
- (NSDate *)lastMessageDate {
if (_lastMessageDate) {
return _lastMessageDate;
} else {
return _creationDate;
}
}
- (NSString *)lastMessageTextWithTransaction:(YapDatabaseReadTransaction *)transaction
{
TSInteraction *interaction = [self lastInteractionForInboxWithTransaction:transaction];
@ -348,8 +351,12 @@ NS_ASSUME_NONNULL_BEGIN
return;
}
if (!self.hasEverHadMessage) {
self.hasEverHadMessage = YES;
self.hasEverHadMessage = YES;
NSDate *lastMessageDate = [lastMessage dateForSorting];
if (!_lastMessageDate || [lastMessageDate timeIntervalSinceDate:self.lastMessageDate] > 0) {
_lastMessageDate = lastMessageDate;
[self saveWithTransaction:transaction];
}
}
@ -374,54 +381,30 @@ NS_ASSUME_NONNULL_BEGIN
}
}
#pragma mark - Archival
#pragma mark Archival
- (BOOL)isArchivedWithTransaction:(YapDatabaseReadTransaction *)transaction;
- (nullable NSDate *)archivalDate
{
if (!self.archivedAsOfMessageSortId) {
return NO;
}
TSInteraction *_Nullable latestInteraction = [self lastInteractionForInboxWithTransaction:transaction];
uint64_t latestSortIdForInbox = latestInteraction ? latestInteraction.sortId : 0;
return self.archivedAsOfMessageSortId.unsignedLongLongValue >= latestSortIdForInbox;
return _archivalDate;
}
+ (BOOL)legacyIsArchivedWithLastMessageDate:(nullable NSDate *)lastMessageDate
archivalDate:(nullable NSDate *)archivalDate
{
if (!archivalDate) {
return NO;
}
if (!lastMessageDate) {
return YES;
}
return [archivalDate compare:lastMessageDate] != NSOrderedAscending;
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction {
[self archiveThreadWithTransaction:transaction referenceDate:[NSDate date]];
}
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(TSThread *thread) {
uint64_t latestId = [SSKIncrementingIdFinder previousIdWithKey:TSInteraction.collection
transaction:transaction];
thread.archivedAsOfMessageSortId = @(latestId);
}];
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction referenceDate:(NSDate *)date {
[self markAllAsReadWithTransaction:transaction];
_archivalDate = date;
[self saveWithTransaction:transaction];
}
- (void)unarchiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(TSThread *thread) {
thread.archivedAsOfMessageSortId = nil;
}];
- (void)unarchiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction {
_archivalDate = nil;
[self saveWithTransaction:transaction];
}
#pragma mark - Drafts
#pragma mark Drafts
- (NSString *)currentDraftWithTransaction:(YapDatabaseReadTransaction *)transaction {
TSThread *thread = [TSThread fetchObjectWithUniqueID:self.uniqueId transaction:transaction];

View File

@ -21,7 +21,6 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithThread:(nullable TSThread *)thread messageTimestamps:(NSArray<NSNumber *> *)messageTimestamps
{
// MJK TODO - remove senderTimestamp
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil

View File

@ -70,8 +70,6 @@ NS_ASSUME_NONNULL_BEGIN
if (transcript.isEndSessionMessage) {
OWSLogInfo(@"EndSession was sent to recipient: %@.", transcript.recipientId);
[self.primaryStorage deleteAllSessionsForContact:transcript.recipientId protocolContext:transaction];
// MJK TODO - we don't use this timestamp, safe to remove
[[[TSInfoMessage alloc] initWithTimestamp:transcript.timestamp
inThread:transcript.thread
messageType:TSInfoMessageTypeSessionDidEnd] saveWithTransaction:transaction];
@ -129,13 +127,12 @@ NS_ASSUME_NONNULL_BEGIN
}
}
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:outgoingMessage.expiresInSeconds
thread:transcript.thread
createdByRemoteRecipientId:nil
createdInExistingGroup:NO
transaction:transaction];
if (transcript.isExpirationTimerUpdate) {
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithConfigurationForMessage:outgoingMessage
contactsManager:self.contactsManager
transaction:transaction];
// early return to avoid saving an empty incoming message.
OWSAssertDebug(transcript.body.length == 0);
OWSAssertDebug(outgoingMessage.attachmentIds.count == 0);
@ -150,6 +147,9 @@ NS_ASSUME_NONNULL_BEGIN
[outgoingMessage saveWithTransaction:transaction];
[outgoingMessage updateWithWasSentFromLinkedDeviceWithTransaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithConfigurationForMessage:outgoingMessage
contactsManager:self.contactsManager
transaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] startAnyExpirationForMessage:outgoingMessage
expirationStartedAt:transcript.expirationStartedAt
transaction:transaction];

View File

@ -19,7 +19,6 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init
{
// MJK TODO - remove SenderTimestamp
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:nil
messageBody:nil

View File

@ -20,7 +20,6 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithThread:(nullable TSThread *)thread groupId:(NSData *)groupId
{
// MJK TODO - remove senderTimestamp
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil

View File

@ -16,7 +16,6 @@ NS_ASSUME_NONNULL_BEGIN
/**
* @param remoteName is nil when created by the local user
*/
// MJK TODO - can we remove sendertimestamp here
- (instancetype)initWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
configuration:(OWSDisappearingMessagesConfiguration *)configuration

View File

@ -74,7 +74,7 @@ NS_ASSUME_NONNULL_BEGIN
return [NSString stringWithFormat:infoFormat, self.createdByRemoteName];
}
} else {
// Changed by localNumber on this device or via synced transcript
// Changed by local request
if (self.configurationIsEnabled && self.configurationDurationSeconds > 0) {
NSString *infoFormat = NSLocalizedString(@"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION",
@"Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context.");

View File

@ -10,7 +10,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSDisappearingMessagesConfigurationMessage : TSOutgoingMessage
// MJK TODO - remove senderTimestamp
- (instancetype)initOutgoingMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body

View File

@ -26,7 +26,6 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithConfiguration:(OWSDisappearingMessagesConfiguration *)configuration thread:(TSThread *)thread
{
// MJK TODO - remove sender timestamp
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil

View File

@ -11,7 +11,6 @@ NS_ASSUME_NONNULL_BEGIN
typedef NSData *_Nonnull (^DynamicOutgoingMessageBlock)(SignalRecipient *);
/// This class is only used in debug tools
@interface OWSDynamicOutgoingMessage : TSOutgoingMessage
- (instancetype)initOutgoingMessageWithTimestamp:(uint64_t)timestamp

View File

@ -23,7 +23,6 @@ NS_ASSUME_NONNULL_BEGIN
return [self initWithPlainTextDataBlock:block timestamp:[NSDate ows_millisecondTimeStamp] thread:thread];
}
// MJK TODO can we remove sender timestamp?
- (instancetype)initWithPlainTextDataBlock:(DynamicOutgoingMessageBlock)block
timestamp:(uint64_t)timestamp
thread:(nullable TSThread *)thread

View File

@ -20,7 +20,6 @@ NS_SWIFT_NAME(EndSessionMessage)
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare NS_UNAVAILABLE;
// MJK TODO can we remove the sender timestamp?
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSRecipientIdentity.h"

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSVerificationStateChangeMessage.h"

View File

@ -51,6 +51,10 @@ typedef NS_ENUM(int32_t, TSErrorMessageType) {
failedMessageType:(TSErrorMessageType)errorMessageType
recipientId:(nullable NSString *)recipientId NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
failedMessageType:(TSErrorMessageType)errorMessageType;
+ (instancetype)corruptedMessageWithEnvelope:(SSKProtoEnvelope *)envelope
withTransaction:(YapDatabaseReadWriteTransaction *)transaction;

View File

@ -91,11 +91,14 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
TSContactThread *contactThread =
[TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
// Legit usage of senderTimestamp. We don't actually currently surface it in the UI, but it serves as
// a reference to the envelope which we failed to process.
return [self initWithTimestamp:envelope.timestamp inThread:contactThread failedMessageType:errorMessageType];
}
- (instancetype)initWithFailedMessageType:(TSErrorMessageType)errorMessageType
{
return [self initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:nil failedMessageType:errorMessageType];
}
- (OWSInteractionType)interactionType
{
return OWSInteractionType_Error;
@ -153,10 +156,7 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
+ (instancetype)corruptedMessageInUnknownThread
{
// MJK TODO - Seems like we could safely remove this timestamp
return [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:nil
failedMessageType:TSErrorMessageInvalidMessage];
return [[self alloc] initWithFailedMessageType:TSErrorMessageInvalidMessage];
}
+ (instancetype)invalidVersionWithEnvelope:(SSKProtoEnvelope *)envelope
@ -184,7 +184,6 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
+ (instancetype)nonblockingIdentityChangeInThread:(TSThread *)thread recipientId:(NSString *)recipientId
{
// MJK TODO - should be safe to remove this senderTimestamp
return [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
failedMessageType:TSErrorMessageNonBlockingIdentityChange

View File

@ -4,16 +4,17 @@
#import "TSErrorMessage.h"
NS_ASSUME_NONNULL_BEGIN
@interface TSErrorMessage ()
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
inThread:(TSThread *)thread
failedMessageType:(TSErrorMessageType)errorMessageType NS_DESIGNATED_INITIALIZER;
@property (atomic, nullable) NSData *envelopeData;
@end
@property NSDictionary *pendingOutgoingMessage;
NS_ASSUME_NONNULL_END
#define TSPendingOutgoingMessageKey @"TSPendingOutgoingMessageKey"
#define TSPendingOutgoingMessageRecipientKey @"TSPendingOutgoingMessageRecipientKey"
@end

View File

@ -48,7 +48,6 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
inThread:(TSThread *)thread
messageType:(TSInfoMessageType)infoMessage
{
// MJK TODO - remove senderTimestamp
self = [super initMessageWithTimestamp:timestamp
inThread:thread
messageBody:nil
@ -101,7 +100,6 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
OWSAssertDebug(thread);
OWSAssertDebug(recipientId);
// MJK TODO - remove senderTimestamp
return [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageType:TSInfoMessageUserNotRegistered

View File

@ -33,9 +33,6 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value);
@property (nonatomic, readonly) NSString *uniqueThreadId;
@property (nonatomic, readonly) TSThread *thread;
@property (nonatomic, readonly) uint64_t timestamp;
@property (nonatomic, readonly) uint64_t sortId;
@property (nonatomic, readonly) uint64_t receivedAtTimestamp;
- (NSDate *)receivedAtDate;
- (OWSInteractionType)interactionType;
@ -57,8 +54,8 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value);
filter:(BOOL (^_Nonnull)(TSInteraction *))filter
withTransaction:(YapDatabaseReadTransaction *)transaction;
- (NSDate *)dateForLegacySorting;
- (uint64_t)timestampForLegacySorting;
- (NSDate *)dateForSorting;
- (uint64_t)timestampForSorting;
- (NSComparisonResult)compareForSorting:(TSInteraction *)other;
// "Dynamic" interactions are not messages or static events (like
@ -69,9 +66,6 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value);
// unseen message indicators, etc.
- (BOOL)isDynamicInteraction;
- (void)saveNextSortIdWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
NS_SWIFT_NAME(saveNextSortId(transaction:));
@end
NS_ASSUME_NONNULL_END

View File

@ -7,7 +7,6 @@
#import "OWSPrimaryStorage+messageIDs.h"
#import "TSDatabaseSecondaryIndexes.h"
#import "TSThread.h"
#import <SignalServiceKit/SignalServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
@ -31,12 +30,6 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
}
}
@interface TSInteraction ()
@property (nonatomic) uint64_t sortId;
@end
@implementation TSInteraction
+ (NSArray<TSInteraction *> *)interactionsWithTimestamp:(uint64_t)timestamp
@ -64,6 +57,7 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
[TSDatabaseSecondaryIndexes
enumerateMessagesWithTimestamp:timestamp
withBlock:^(NSString *collection, NSString *key, BOOL *stop) {
TSInteraction *interaction =
[TSInteraction fetchObjectWithUniqueID:key transaction:transaction];
if (!filter(interaction)) {
@ -92,37 +86,6 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
_timestamp = timestamp;
_uniqueThreadId = thread.uniqueId;
_receivedAtTimestamp = [NSDate ows_millisecondTimeStamp];
return self;
}
- (nullable instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (!self) {
return nil;
}
// Previously the receivedAtTimestamp field lived on TSMessage, but we've moved it up
// to the TSInteraction superclass.
if (_receivedAtTimestamp == 0) {
// Upgrade from the older "TSMessage.receivedAtDate" and "TSMessage.receivedAt" properties if
// necessary.
NSDate *receivedAtDate = [coder decodeObjectForKey:@"receivedAtDate"];
if (!receivedAtDate) {
receivedAtDate = [coder decodeObjectForKey:@"receivedAt"];
}
if (receivedAtDate) {
_receivedAtTimestamp = [NSDate ows_millisecondsSince1970ForDate:receivedAtDate];
}
// For TSInteractions which are not TSMessage's, the timestamp *is* the receivedAtTimestamp
if (_receivedAtTimestamp == 0) {
_receivedAtTimestamp = _timestamp;
}
}
return self;
}
@ -147,31 +110,26 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
#pragma mark Date operations
- (NSDate *)dateForLegacySorting
- (NSDate *)dateForSorting
{
return [NSDate ows_dateWithMillisecondsSince1970:self.timestampForLegacySorting];
return [NSDate ows_dateWithMillisecondsSince1970:self.timestampForSorting];
}
- (uint64_t)timestampForLegacySorting
- (uint64_t)timestampForSorting
{
return self.timestamp;
}
- (NSDate *)receivedAtDate
{
return [NSDate ows_dateWithMillisecondsSince1970:self.receivedAtTimestamp];
}
- (NSComparisonResult)compareForSorting:(TSInteraction *)other
{
OWSAssertDebug(other);
uint64_t sortId1 = self.sortId;
uint64_t sortId2 = self.sortId;
uint64_t timestamp1 = self.timestampForSorting;
uint64_t timestamp2 = other.timestampForSorting;
if (sortId1 > sortId2) {
if (timestamp1 > timestamp2) {
return NSOrderedDescending;
} else if (sortId1 < sortId2) {
} else if (timestamp1 < timestamp2) {
return NSOrderedAscending;
} else {
return NSOrderedSame;
@ -193,20 +151,14 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
(unsigned long)self.timestamp];
}
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
// MJK can we remove this? We can't trust the legacy order of this id field. Any reason not to use UUID like for
// other objects?
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction {
if (!self.uniqueId) {
self.uniqueId = [OWSPrimaryStorage getAndIncrementMessageIdWithTransaction:transaction];
}
if (self.sortId == 0) {
self.sortId = [SSKIncrementingIdFinder nextIdWithKey:[TSInteraction collection] transaction:transaction];
}
[super saveWithTransaction:transaction];
TSThread *fetchedThread = [self threadWithTransaction:transaction];
TSThread *fetchedThread = [TSThread fetchObjectWithUniqueID:self.uniqueThreadId transaction:transaction];
[fetchedThread updateWithLastMessage:self transaction:transaction];
}
@ -223,20 +175,6 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
return NO;
}
#pragma mark - sorting migration
- (void)saveNextSortIdWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
if (self.sortId != 0) {
// This could happen if something else in our startup process saved the interaction
// e.g. another migration ran.
// During the migration, since we're enumerating the interactions in the proper order,
// we want to ignore any previously assigned sortId
self.sortId = 0;
}
[self saveWithTransaction:transaction];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -47,6 +47,13 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
*/
@property (nonatomic, readonly) NSUInteger schemaVersion;
// The timestamp property is populated by the envelope,
// which is created by the sender.
//
// We typically want to order messages locally by when
// they were received & decrypted, not by when they were sent.
@property (nonatomic) uint64_t receivedAtTimestamp;
@end
#pragma mark -
@ -75,6 +82,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
_expiresInSeconds = expiresInSeconds;
_expireStartedAt = expireStartedAt;
[self updateExpiresAt];
_receivedAtTimestamp = [NSDate ows_millisecondTimeStamp];
_quotedMessage = quotedMessage;
_contactShare = contactShare;
@ -127,6 +135,18 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
_attachmentIds = [NSMutableArray new];
}
if (_receivedAtTimestamp == 0) {
// Upgrade from the older "receivedAtDate" and "receivedAt" properties if
// necessary.
NSDate *receivedAtDate = [coder decodeObjectForKey:@"receivedAtDate"];
if (!receivedAtDate) {
receivedAtDate = [coder decodeObjectForKey:@"receivedAt"];
}
if (receivedAtDate) {
_receivedAtTimestamp = [NSDate ows_millisecondsSince1970ForDate:receivedAtDate];
}
}
_schemaVersion = OWSMessageSchemaVersion;
return self;
@ -320,7 +340,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
return self.expiresInSeconds > 0;
}
- (uint64_t)timestampForLegacySorting
- (uint64_t)timestampForSorting
{
if ([self shouldUseReceiptDateForSorting] && self.receivedAtTimestamp > 0) {
return self.receivedAtTimestamp;

View File

@ -77,7 +77,6 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare NS_UNAVAILABLE;
// MJK TODO - Can we remove the sender timestamp param?
- (instancetype)initOutgoingMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body

View File

@ -261,7 +261,6 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
[attachmentIds addObject:attachmentId];
}
// MJK TODO remove SenderTimestamp?
return [[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:body
@ -278,7 +277,6 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage
expiresInSeconds:(uint32_t)expiresInSeconds;
{
// MJK TODO remove SenderTimestamp?
return [[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil

View File

@ -208,7 +208,6 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
// Legit usage of senderTimestamp - this class references the message it is quoting by it's sender timestamp
return [[TSQuotedMessage alloc] initWithTimestamp:timestamp
authorId:authorId
body:body
@ -230,6 +229,7 @@ NS_ASSUME_NONNULL_BEGIN
NSArray<TSMessage *> *quotedMessages = (NSArray<TSMessage *> *)[TSInteraction
interactionsWithTimestamp:timestamp
filter:^BOOL(TSInteraction *interaction) {
if (![threadId isEqual:interaction.uniqueThreadId]) {
return NO;
}
@ -243,6 +243,7 @@ NS_ASSUME_NONNULL_BEGIN
// ignore other interaction types
return NO;
}
}
withTransaction:transaction];

View File

@ -10,13 +10,10 @@ NS_ASSUME_NONNULL_BEGIN
// DEPRECATED - we no longer create new instances of this class (as of mid-2017); However, existing instances may
// exist, so we should keep this class around to honor their old behavior.
__attribute__((deprecated))
@interface TSInvalidIdentityKeyReceivingErrorMessage : TSInvalidIdentityKeyErrorMessage
#ifdef DEBUG
+ (nullable instancetype)untrustedKeyWithEnvelope:(SSKProtoEnvelope *)envelope
withTransaction:(YapDatabaseReadWriteTransaction *)transaction;
#endif
@end

View File

@ -19,7 +19,7 @@
NS_ASSUME_NONNULL_BEGIN
__attribute__((deprecated))
/// TODO we can eventually deprecate this, since incoming messages are now always decrypted.
@interface TSInvalidIdentityKeyReceivingErrorMessage ()
@property (nonatomic, readonly, copy) NSString *authorId;
@ -33,20 +33,15 @@ __attribute__((deprecated))
@synthesize envelopeData = _envelopeData;
#ifdef DEBUG
// We no longer create these messages, but they might exist on legacy clients so it's useful to be able to
// create them with the debug UI
+ (nullable instancetype)untrustedKeyWithEnvelope:(SSKProtoEnvelope *)envelope
withTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
TSContactThread *contactThread =
[TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
// Legit usage of senderTimestamp, references message which failed to decrypt
TSInvalidIdentityKeyReceivingErrorMessage *errorMessage =
[[self alloc] initForUnknownIdentityKeyWithTimestamp:envelope.timestamp
inThread:contactThread
incomingEnvelope:envelope];
[[self alloc] initForUnknownIdentityKeyWithTimestamp:envelope.timestamp
inThread:contactThread
incomingEnvelope:envelope];
return errorMessage;
}
@ -70,7 +65,6 @@ __attribute__((deprecated))
return self;
}
#endif
- (nullable SSKProtoEnvelope *)envelope
{

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "TSInvalidIdentityKeyErrorMessage.h"
@ -13,9 +13,6 @@ NS_ASSUME_NONNULL_BEGIN
extern NSString *TSInvalidPreKeyBundleKey;
extern NSString *TSInvalidRecipientKey;
// DEPRECATED - we no longer create new instances of this class (as of mid-2017); However, existing instances may
// exist, so we should keep this class around to honor their old behavior.
__attribute__((deprecated))
@interface TSInvalidIdentityKeySendingErrorMessage : TSInvalidIdentityKeyErrorMessage
@property (nonatomic, readonly) NSString *messageId;

View File

@ -24,12 +24,26 @@ NSString *TSInvalidRecipientKey = @"TSInvalidRecipientKey";
@end
// DEPRECATED - we no longer create new instances of this class (as of mid-2017); However, existing instances may
// exist, so we should keep this class around to honor their old behavior.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
@implementation TSInvalidIdentityKeySendingErrorMessage
#pragma clang diagnostic pop
- (instancetype)initWithOutgoingMessage:(TSOutgoingMessage *)message
inThread:(TSThread *)thread
forRecipient:(NSString *)recipientId
preKeyBundle:(PreKeyBundle *)preKeyBundle
{
// We want the error message to appear after the message.
self = [super initWithTimestamp:message.timestamp + 1
inThread:thread
failedMessageType:TSErrorMessageWrongTrustedIdentityKey
recipientId:recipientId];
if (self) {
_messageId = message.uniqueId;
_preKeyBundle = preKeyBundle;
}
return self;
}
- (void)acceptNewIdentityKey
{

View File

@ -1,19 +1,14 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "TSInfoMessage.h"
NS_ASSUME_NONNULL_BEGIN
// This is a deprecated class, we're keeping it around to avoid YapDB serialization errors
// TODO - remove this class, clean up existing instances, ensure any missed ones don't explode (UnknownDBObject)
__attribute__((deprecated))
@interface OWSAddToContactsOfferMessage : TSInfoMessage
+ (instancetype)addToContactsOfferMessageWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
contactId:(NSString *)contactId;
+ (instancetype)addToContactsOfferMessage:(uint64_t)timestamp thread:(TSThread *)thread contactId:(NSString *)contactId;
@property (nonatomic, readonly) NSString *contactId;

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSAddToContactsOfferMessage.h"
@ -14,16 +14,9 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
// This is a deprecated class, we're keeping it around to avoid YapDB serialization errors
// TODO - remove this class, clean up existing instances, ensure any missed ones don't explode (UnknownDBObject)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
@implementation OWSAddToContactsOfferMessage
#pragma clang diagnostic pop
+ (instancetype)addToContactsOfferMessageWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
contactId:(NSString *)contactId
+ (instancetype)addToContactsOfferMessage:(uint64_t)timestamp thread:(TSThread *)thread contactId:(NSString *)contactId
{
return [[OWSAddToContactsOfferMessage alloc] initWithTimestamp:timestamp thread:thread contactId:contactId];
}

View File

@ -1,16 +1,14 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "TSInfoMessage.h"
NS_ASSUME_NONNULL_BEGIN
// This is a deprecated class, we're keeping it around to avoid YapDB serialization errors
// TODO - remove this class, clean up existing instances, ensure any missed ones don't explode (UnknownDBObject)
__attribute__((deprecated)) @interface OWSAddToProfileWhitelistOfferMessage : TSInfoMessage
@interface OWSAddToProfileWhitelistOfferMessage : TSInfoMessage
+ (instancetype)addToProfileWhitelistOfferMessageWithTimestamp:(uint64_t)timestamp thread:(TSThread *)thread;
+ (instancetype)addToProfileWhitelistOfferMessage:(uint64_t)timestamp thread:(TSThread *)thread;
@property (nonatomic, readonly) NSString *contactId;

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSAddToProfileWhitelistOfferMessage.h"
@ -7,14 +7,9 @@
NS_ASSUME_NONNULL_BEGIN
// This is a deprecated class, we're keeping it around to avoid YapDB serialization errors
// TODO - remove this class, clean up existing instances, ensure any missed ones don't explode (UnknownDBObject)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
@implementation OWSAddToProfileWhitelistOfferMessage
#pragma clang diagnostic pop
+ (instancetype)addToProfileWhitelistOfferMessageWithTimestamp:(uint64_t)timestamp thread:(TSThread *)thread
+ (instancetype)addToProfileWhitelistOfferMessage:(uint64_t)timestamp thread:(TSThread *)thread
{
return [[OWSAddToProfileWhitelistOfferMessage alloc]
initWithTimestamp:timestamp

View File

@ -21,23 +21,41 @@ NS_ASSUME_NONNULL_BEGIN
expirationStartedAt:(uint64_t)expirationStartedAt
transaction:(YapDatabaseReadWriteTransaction *_Nonnull)transaction;
/**
* Synchronize our disappearing messages settings with that of the given message. Useful so we can
* become eventually consistent with remote senders.
*
* @param message
* Can be an expiring or non expiring message. We match the expiration timer of the message, including disabling
* expiring messages if the message is not an expiring message.
*
* @param contactsManager
* Provides the contact name responsible for any configuration changes in an info message.
*/
- (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
contactsManager:(id<ContactsManagerProtocol>)contactsManager
transaction:(YapDatabaseReadWriteTransaction *)transaction;
/**
* Synchronize our disappearing messages settings with that of the given message. Useful so we can
* become eventually consistent with remote senders.
*
* @param duration
* Can be 0, indicating a non-expiring message, or greater, indicating an expiring message. We match the expiration
* timer of the message, including disabling expiring messages if the message is not an expiring message.
* timer of the message, including disabling expiring messages if the message is not an expiring message.
*
* @param remoteRecipientId
* nil for outgoing messages, otherwise the recipientId of the sender
* @param timestampForSorting
* timestampForSorting of the message before which we want to appear.
*
* @param remoteContactName
* nil for outgoing messages, otherwise the name of the sender
* @param createdInExistingGroup
* YES when being added to a group which already has DM enabled, otherwise NO
*/
- (void)becomeConsistentWithDisappearingDuration:(uint32_t)duration
thread:(TSThread *)thread
createdByRemoteRecipientId:(nullable NSString *)remoteRecipientId
appearBeforeTimestamp:(uint64_t)timestampForSorting
createdByRemoteContactName:(nullable NSString *)remoteContactName
createdInExistingGroup:(BOOL)createdInExistingGroup
transaction:(YapDatabaseReadWriteTransaction *)transaction;

View File

@ -13,7 +13,6 @@
#import "OWSDisappearingMessagesConfiguration.h"
#import "OWSDisappearingMessagesFinder.h"
#import "OWSPrimaryStorage.h"
#import "SSKEnvironment.h"
#import "TSIncomingMessage.h"
#import "TSMessage.h"
#import "TSThread.h"
@ -111,15 +110,6 @@ void AssertIsOnDisappearingMessagesQueue()
return queue;
}
#pragma mark - Dependencies
- (id<ContactsManagerProtocol>)contactsManager
{
return SSKEnvironment.shared.contactsManager;
}
#pragma mark -
- (NSUInteger)deleteExpiredMessages
{
AssertIsOnDisappearingMessagesQueue();
@ -203,25 +193,38 @@ void AssertIsOnDisappearingMessagesQueue()
}];
}
- (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
contactsManager:(id<ContactsManagerProtocol>)contactsManager
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
TSThread *thread = [message threadWithTransaction:transaction];
NSString *remoteContactName = nil;
if ([message isKindOfClass:[TSIncomingMessage class]]) {
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)message;
remoteContactName = [contactsManager displayNameForPhoneIdentifier:incomingMessage.messageAuthorId];
}
#pragma mark - Apply Remote Configuration
[self becomeConsistentWithDisappearingDuration:message.expiresInSeconds
thread:thread
appearBeforeTimestamp:message.timestampForSorting
createdByRemoteContactName:remoteContactName
createdInExistingGroup:NO
transaction:transaction];
}
- (void)becomeConsistentWithDisappearingDuration:(uint32_t)duration
thread:(TSThread *)thread
createdByRemoteRecipientId:(nullable NSString *)remoteRecipientId
appearBeforeTimestamp:(uint64_t)timestampForSorting
createdByRemoteContactName:(nullable NSString *)remoteContactName
createdInExistingGroup:(BOOL)createdInExistingGroup
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssertDebug(thread);
OWSAssertDebug(timestampForSorting > 0);
OWSAssertDebug(transaction);
OWSBackgroundTask *_Nullable backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
NSString *_Nullable remoteContactName = nil;
if (remoteRecipientId) {
remoteContactName = [self.contactsManager displayNameForPhoneIdentifier:remoteRecipientId];
}
// Become eventually consistent in the case that the remote changed their settings at the same time.
// Also in case remote doesn't support expiring messages
OWSDisappearingMessagesConfiguration *disappearingMessagesConfiguration =
@ -243,9 +246,9 @@ void AssertIsOnDisappearingMessagesQueue()
[disappearingMessagesConfiguration saveWithTransaction:transaction];
// MJK TODO - should be safe to remove this senderTimestamp
// We want the info message to appear _before_ the message.
OWSDisappearingConfigurationUpdateInfoMessage *infoMessage =
[[OWSDisappearingConfigurationUpdateInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
[[OWSDisappearingConfigurationUpdateInfoMessage alloc] initWithTimestamp:timestampForSorting - 1
thread:thread
configuration:disappearingMessagesConfiguration
createdByRemoteName:remoteContactName
@ -256,8 +259,6 @@ void AssertIsOnDisappearingMessagesQueue()
backgroundTask = nil;
}
#pragma mark -
- (void)startIfNecessary
{
dispatch_async(dispatch_get_main_queue(), ^{
@ -393,7 +394,7 @@ void AssertIsOnDisappearingMessagesQueue()
OWSFailDebug(@"starting old timer for message timestamp: %lu", (unsigned long)message.timestamp);
// We don't know when it was actually read, so assume it was read as soon as it was received.
uint64_t readTimeBestGuess = message.receivedAtTimestamp;
uint64_t readTimeBestGuess = message.timestampForSorting;
[self startAnyExpirationForMessage:message expirationStartedAt:readTimeBestGuess transaction:transaction];
}
transaction:transaction];

View File

@ -528,7 +528,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
[messages addObject:[TSErrorMessage nonblockingIdentityChangeInThread:groupThread recipientId:recipientId]];
}
// MJK TODO - why not save immediately, why build up this array?
for (TSMessage *message in messages) {
[message saveWithTransaction:transaction];
}
@ -846,7 +845,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
TSContactThread *contactThread =
[TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
OWSAssertDebug(contactThread);
// MJK TODO - should be safe to remove senderTimestamp
[messages addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:contactThread
recipientId:recipientId
@ -855,7 +853,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
for (TSGroupThread *groupThread in
[TSGroupThread groupThreadsWithRecipientId:recipientId transaction:transaction]) {
// MJK TODO - should be safe to remove senderTimestamp
[messages
addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:groupThread
@ -864,7 +861,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
isLocalChange:isLocalChange]];
}
// MJK TODO - why not save in-line, vs storing in an array and saving the array?
for (TSMessage *message in messages) {
[message saveWithTransaction:transaction];
}

View File

@ -879,7 +879,6 @@ NS_ASSUME_NONNULL_BEGIN
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
// MJK TODO - safe to remove senderTimestamp
[[[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageType:TSInfoMessageTypeSessionDidEnd] saveWithTransaction:transaction];
@ -928,7 +927,6 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssertDebug(disappearingMessagesConfiguration);
[disappearingMessagesConfiguration saveWithTransaction:transaction];
NSString *name = [self.contactsManager displayNameForPhoneIdentifier:envelope.source];
// MJK TODO - safe to remove senderTimestamp
OWSDisappearingConfigurationUpdateInfoMessage *message =
[[OWSDisappearingConfigurationUpdateInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
thread:thread
@ -1146,6 +1144,8 @@ NS_ASSUME_NONNULL_BEGIN
TSGroupThread *newGroupThread =
[TSGroupThread getOrCreateThreadWithGroupId:groupId transaction:transaction];
uint64_t now = [NSDate ows_millisecondTimeStamp];
TSGroupModel *newGroupModel = [[TSGroupModel alloc] initWithTitle:dataMessage.group.name
memberIds:newMemberIds.allObjects
image:oldGroupThread.groupModel.groupImage
@ -1155,19 +1155,22 @@ NS_ASSUME_NONNULL_BEGIN
newGroupThread.groupModel = newGroupModel;
[newGroupThread saveWithTransaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
thread:newGroupThread
createdByRemoteRecipientId:nil
createdInExistingGroup:NO
transaction:transaction];
// MJK TODO - should be safe to remove senderTimestamp
TSInfoMessage *infoMessage = [[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
TSInfoMessage *infoMessage = [[TSInfoMessage alloc] initWithTimestamp:now
inThread:newGroupThread
messageType:TSInfoMessageTypeGroupUpdate
customMessage:updateGroupInfo];
[infoMessage saveWithTransaction:transaction];
if (dataMessage.hasExpireTimer && dataMessage.expireTimer > 0) {
[[OWSDisappearingMessagesJob sharedJob]
becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
thread:newGroupThread
appearBeforeTimestamp:now
createdByRemoteContactName:nil
createdInExistingGroup:YES
transaction:transaction];
}
return nil;
}
case SSKProtoGroupContextTypeQuit: {
@ -1182,7 +1185,6 @@ NS_ASSUME_NONNULL_BEGIN
NSString *nameString = [self.contactsManager displayNameForPhoneIdentifier:envelope.source];
NSString *updateGroupInfo =
[NSString stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_LEFT", @""), nameString];
// MJK TODO - should be safe to remove senderTimestamp
[[[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:oldGroupThread
messageType:TSInfoMessageTypeGroupUpdate
@ -1203,12 +1205,6 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
thread:oldGroupThread
createdByRemoteRecipientId:envelope.source
createdInExistingGroup:YES
transaction:transaction];
TSQuotedMessage *_Nullable quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:dataMessage
thread:oldGroupThread
transaction:transaction];
@ -1218,7 +1214,6 @@ NS_ASSUME_NONNULL_BEGIN
groupId,
(unsigned long)timestamp);
// Legit usage of senderTimestamp when creating an incoming group message record
TSIncomingMessage *incomingMessage =
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp
inThread:oldGroupThread
@ -1254,17 +1249,10 @@ NS_ASSUME_NONNULL_BEGIN
TSContactThread *thread =
[TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
thread:thread
createdByRemoteRecipientId:envelope.source
createdInExistingGroup:NO
transaction:transaction];
TSQuotedMessage *_Nullable quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:dataMessage
thread:thread
transaction:transaction];
// Legit usage of senderTimestamp when creating incoming message from received envelope
TSIncomingMessage *incomingMessage =
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp
inThread:thread
@ -1374,6 +1362,10 @@ NS_ASSUME_NONNULL_BEGIN
[OWSReadReceiptManager.sharedManager applyEarlyReadReceiptsForIncomingMessage:incomingMessage
transaction:transaction];
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithConfigurationForMessage:incomingMessage
contactsManager:self.contactsManager
transaction:transaction];
// Update thread preview in inbox
[thread touchWithTransaction:transaction];

View File

@ -467,7 +467,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *recipientId in message.sendingRecipientIds) {
[message updateWithReadRecipientId:recipientId
readTimestamp:message.timestamp
readTimestamp:message.timestampForSorting
transaction:transaction];
}
}];
@ -1416,13 +1416,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// TODO: Why is this necessary?
[message save];
} else if (message.groupMetaMessage == TSGroupMetaMessageQuit) {
// MJK TODO - remove senderTimestamp
[[[TSInfoMessage alloc] initWithTimestamp:message.timestamp
inThread:thread
messageType:TSInfoMessageTypeGroupQuit
customMessage:message.customMessage] save];
} else {
// MJK TODO - remove senderTimestamp
[[[TSInfoMessage alloc] initWithTimestamp:message.timestamp
inThread:thread
messageType:TSInfoMessageTypeGroupUpdate

View File

@ -15,7 +15,8 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithThread:(TSThread *)thread
{
// MJK TODO - safe to remove senderTimestamp
// These records aren't saved, but their timestamp is used in the event
// of a failing message send to insert the error at the appropriate place.
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil

View File

@ -24,7 +24,6 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithContactThread:(TSContactThread *)contactThread
verificationStateSyncMessage:(OWSVerificationStateSyncMessage *)verificationStateSyncMessage
{
// MJK TODO - remove senderTimestamp
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:contactThread
messageBody:nil

View File

@ -69,7 +69,7 @@ extern NSString *const kIncomingMessageMarkedAsReadNotification;
// This method can be called from any thread.
- (void)messageWasReadLocally:(TSIncomingMessage *)message;
- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread;
- (void)markAsReadLocallyBeforeTimestamp:(uint64_t)timestamp thread:(TSThread *)thread;
#pragma mark - Settings

View File

@ -281,17 +281,17 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
#pragma mark - Mark as Read Locally
- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread
- (void)markAsReadLocallyBeforeTimestamp:(uint64_t)timestamp thread:(TSThread *)thread
{
OWSAssertDebug(thread);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self markAsReadBeforeSortId:sortId
thread:thread
readTimestamp:[NSDate ows_millisecondTimeStamp]
wasLocal:YES
transaction:transaction];
[self markAsReadBeforeTimestamp:timestamp
thread:thread
readTimestamp:[NSDate ows_millisecondTimeStamp]
wasLocal:YES
transaction:transaction];
}];
});
}
@ -493,23 +493,26 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
// Always re-mark the message as read to ensure any earlier read time is applied to disappearing messages.
[message markAsReadAtTimestamp:readTimestamp sendReadReceipt:NO transaction:transaction];
// Also mark any unread messages appearing earlier in the thread as read as well.
[self markAsReadBeforeSortId:message.sortId
thread:[message threadWithTransaction:transaction]
readTimestamp:readTimestamp
wasLocal:NO
transaction:transaction];
// Also mark any messages appearing earlier in the thread as read.
//
// Use `timestampForSorting` which reflects local received order, rather than `timestamp`
// which reflect sender time.
[self markAsReadBeforeTimestamp:message.timestampForSorting
thread:[message threadWithTransaction:transaction]
readTimestamp:readTimestamp
wasLocal:NO
transaction:transaction];
}
#pragma mark - Mark As Read
- (void)markAsReadBeforeSortId:(uint64_t)sortId
thread:(TSThread *)thread
readTimestamp:(uint64_t)readTimestamp
wasLocal:(BOOL)wasLocal
transaction:(YapDatabaseReadWriteTransaction *)transaction
- (void)markAsReadBeforeTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
readTimestamp:(uint64_t)readTimestamp
wasLocal:(BOOL)wasLocal
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssertDebug(sortId > 0);
OWSAssertDebug(timestamp > 0);
OWSAssertDebug(thread);
OWSAssertDebug(transaction);
@ -533,11 +536,12 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
return;
}
id<OWSReadTracking> possiblyRead = (id<OWSReadTracking>)object;
if (possiblyRead.sortId > sortId) {
if (possiblyRead.timestampForSorting > timestamp) {
*stop = YES;
return;
}
OWSAssertDebug(!possiblyRead.read);
OWSAssertDebug(possiblyRead.expireStartedAt == 0);
if (!possiblyRead.read) {

View File

@ -16,7 +16,7 @@
@property (nonatomic, readonly, getter=wasRead) BOOL read;
@property (nonatomic, readonly) uint64_t expireStartedAt;
@property (nonatomic, readonly) uint64_t sortId;
@property (nonatomic, readonly) uint64_t timestampForSorting;
@property (nonatomic, readonly) NSString *uniqueThreadId;

View File

@ -1,16 +1,17 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "TSErrorMessage.h"
NS_ASSUME_NONNULL_BEGIN
// This is a deprecated class, we're keeping it around to avoid YapDB serialization errors
// TODO - remove this class, clean up existing instances, ensure any missed ones don't explode (UnknownDBObject)
__attribute__((deprecated))
@interface OWSUnknownContactBlockOfferMessage : TSErrorMessage
+ (instancetype)unknownContactBlockOfferMessage:(uint64_t)timestamp
thread:(TSThread *)thread
contactId:(NSString *)contactId;
@property (nonatomic, readonly) NSString *contactId;
@end

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSUnknownContactBlockOfferMessage.h"
@ -14,12 +14,25 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
// This is a deprecated class, we're keeping it around to avoid YapDB serialization errors
// TODO - remove this class, clean up existing instances, ensure any missed ones don't explode (UnknownDBObject)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
@implementation OWSUnknownContactBlockOfferMessage
#pragma clang diagnostic pop
+ (instancetype)unknownContactBlockOfferMessage:(uint64_t)timestamp
thread:(TSThread *)thread
contactId:(NSString *)contactId
{
return [[OWSUnknownContactBlockOfferMessage alloc] initWithTimestamp:timestamp thread:thread contactId:contactId];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp thread:(TSThread *)thread contactId:(NSString *)contactId
{
self = [super initWithTimestamp:timestamp inThread:thread failedMessageType:TSErrorMessageUnknownContactBlockOffer];
if (self) {
_contactId = contactId;
}
return self;
}
- (BOOL)shouldUseReceiptDateForSorting
{

View File

@ -1,27 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
public class SSKIncrementingIdFinder: NSObject {
private static let collectionName = "IncrementingIdCollection"
@objc
public class func previousId(key: String, transaction: YapDatabaseReadTransaction) -> UInt64 {
let previousId: UInt64 = transaction.object(forKey: key, inCollection: collectionName) as? UInt64 ?? 0
return previousId
}
@objc
public class func nextId(key: String, transaction: YapDatabaseReadWriteTransaction) -> UInt64 {
let previousId: UInt64 = transaction.object(forKey: key, inCollection: collectionName) as? UInt64 ?? 0
let nextId: UInt64 = previousId + 1
transaction.setObject(nextId, forKey: key, inCollection: collectionName)
Logger.debug("key: \(key) nextId: \(nextId)")
return nextId
}
}

View File

@ -137,7 +137,8 @@ static NSString *const OWSMediaGalleryFinderExtensionName = @"OWSMediaGalleryFin
return NSOrderedSame;
}
TSMessage *message2 = (TSMessage *)object2;
return [message1 compareForSorting:message2];
return [@(message1.timestampForSorting) compare:@(message2.timestampForSorting)];
}];
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withObjectBlock:^NSString * _Nullable(YapDatabaseReadTransaction * _Nonnull transaction, NSString * _Nonnull collection, NSString * _Nonnull key, id _Nonnull object) {
@ -163,7 +164,7 @@ static NSString *const OWSMediaGalleryFinderExtensionName = @"OWSMediaGalleryFin
YapDatabaseViewOptions *options = [YapDatabaseViewOptions new];
options.allowedCollections = [[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:TSMessage.collection]];
return [[YapDatabaseAutoView alloc] initWithGrouping:grouping sorting:sorting versionTag:@"4" options:options];
return [[YapDatabaseAutoView alloc] initWithGrouping:grouping sorting:sorting versionTag:@"3" options:options];
}
+ (BOOL)attachmentIdShouldAppearInMediaGallery:(NSString *)attachmentId transaction:(YapDatabaseReadTransaction *)transaction

View File

@ -190,7 +190,6 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
//
// All sync registrations must be done before all async registrations,
// or the sync registrations will block on the async registrations.
[TSDatabaseView asyncRegisterLegacyThreadInteractionsDatabaseView:self];
[TSDatabaseView asyncRegisterThreadInteractionsDatabaseView:self];
[TSDatabaseView asyncRegisterThreadDatabaseView:self];
[TSDatabaseView asyncRegisterUnreadDatabaseView:self];

View File

@ -13,8 +13,6 @@ extern NSString *const TSSecondaryDevicesGroup;
extern NSString *const TSThreadDatabaseViewExtensionName;
extern NSString *const TSMessageDatabaseViewExtensionName;
extern NSString *const TSMessageDatabaseViewExtensionName_Legacy;
extern NSString *const TSUnreadDatabaseViewExtensionName;
extern NSString *const TSSecondaryDevicesDatabaseViewExtensionName;
@ -44,8 +42,6 @@ extern NSString *const TSLazyRestoreAttachmentsDatabaseViewExtensionName;
+ (void)asyncRegisterThreadDatabaseView:(OWSStorage *)storage;
+ (void)asyncRegisterThreadInteractionsDatabaseView:(OWSStorage *)storage;
+ (void)asyncRegisterLegacyThreadInteractionsDatabaseView:(OWSStorage *)storage;
+ (void)asyncRegisterThreadOutgoingMessagesDatabaseView:(OWSStorage *)storage;
// Instances of OWSReadTracking for wasRead is NO and shouldAffectUnreadCounts is YES.

View File

@ -24,18 +24,7 @@ NSString *const TSSecondaryDevicesGroup = @"TSSecondaryDevicesGroup";
// YAPDB BUG: when changing from non-persistent to persistent view, we had to rename TSThreadDatabaseViewExtensionName
// -> TSThreadDatabaseViewExtensionName2 to work around https://github.com/yapstudios/YapDatabase/issues/324
NSString *const TSThreadDatabaseViewExtensionName = @"TSThreadDatabaseViewExtensionName2";
// We sort interactions by a monotonically increasing counter.
//
// Previously we sorted the interactions database by local timestamp, which was problematic if the local clock changed.
// We need to maintain the legacy extension for purposes of migration.
//
// The "Legacy" sorting extension name constant has the same value as always, so that it won't need to be rebuilt, while
// the "Modern" sorting extension name constant has the same symbol name as we've always used for sorting interactions,
// so that the callsites won't need to change.
NSString *const TSMessageDatabaseViewExtensionName = @"TSMessageDatabaseViewExtensionName_Monotonic";
NSString *const TSMessageDatabaseViewExtensionName_Legacy = @"TSMessageDatabaseViewExtensionName";
NSString *const TSMessageDatabaseViewExtensionName = @"TSMessageDatabaseViewExtensionName";
NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName = @"TSThreadOutgoingMessageDatabaseViewExtensionName";
NSString *const TSUnreadDatabaseViewExtensionName = @"TSUnreadDatabaseViewExtensionName";
NSString *const TSUnseenDatabaseViewExtensionName = @"TSUnseenDatabaseViewExtensionName";
@ -111,7 +100,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
[self registerMessageDatabaseViewWithName:TSUnreadDatabaseViewExtensionName
viewGrouping:viewGrouping
version:@"2"
version:@"1"
storage:storage];
}
@ -130,7 +119,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
[self registerMessageDatabaseViewWithName:TSUnseenDatabaseViewExtensionName
viewGrouping:viewGrouping
version:@"2"
version:@"1"
storage:storage];
}
@ -158,77 +147,10 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
[self registerMessageDatabaseViewWithName:TSThreadSpecialMessagesDatabaseViewExtensionName
viewGrouping:viewGrouping
version:@"2"
version:@"1"
storage:storage];
}
+ (void)asyncRegisterLegacyThreadInteractionsDatabaseView:(OWSStorage *)storage
{
OWSAssertIsOnMainThread();
OWSAssert(storage);
YapDatabaseView *existingView = [storage registeredExtension:TSMessageDatabaseViewExtensionName_Legacy];
if (existingView) {
OWSFailDebug(@"Registered database view twice: %@", TSMessageDatabaseViewExtensionName_Legacy);
return;
}
YapDatabaseViewGrouping *viewGrouping = [YapDatabaseViewGrouping withObjectBlock:^NSString *(
YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object) {
if (![object isKindOfClass:[TSInteraction class]]) {
OWSFailDebug(@"%@ Unexpected entity %@ in collection: %@", self.logTag, [object class], collection);
return nil;
}
TSInteraction *interaction = (TSInteraction *)object;
return interaction.uniqueThreadId;
}];
YapDatabaseViewSorting *viewSorting =
[YapDatabaseViewSorting withObjectBlock:^NSComparisonResult(YapDatabaseReadTransaction *transaction,
NSString *group,
NSString *collection1,
NSString *key1,
id object1,
NSString *collection2,
NSString *key2,
id object2) {
if (![object1 isKindOfClass:[TSInteraction class]]) {
OWSFailDebug(@"%@ Unexpected entity %@ in collection: %@", self.logTag, [object1 class], collection1);
return NSOrderedSame;
}
if (![object2 isKindOfClass:[TSInteraction class]]) {
OWSFailDebug(@"%@ Unexpected entity %@ in collection: %@", self.logTag, [object2 class], collection2);
return NSOrderedSame;
}
TSInteraction *interaction1 = (TSInteraction *)object1;
TSInteraction *interaction2 = (TSInteraction *)object2;
// Legit usage of timestampForLegacySorting since we're registering the
// legacy extension
uint64_t timestamp1 = interaction1.timestampForLegacySorting;
uint64_t timestamp2 = interaction2.timestampForLegacySorting;
if (timestamp1 > timestamp2) {
return NSOrderedDescending;
} else if (timestamp1 < timestamp2) {
return NSOrderedAscending;
} else {
return NSOrderedSame;
}
}];
YapDatabaseViewOptions *options = [YapDatabaseViewOptions new];
options.isPersistent = YES;
options.allowedCollections =
[[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSInteraction collection]]];
YapDatabaseView *view =
[[YapDatabaseAutoView alloc] initWithGrouping:viewGrouping sorting:viewSorting versionTag:@"1" options:options];
[storage asyncRegisterExtension:view withName:TSMessageDatabaseViewExtensionName_Legacy];
}
+ (void)asyncRegisterThreadInteractionsDatabaseView:(OWSStorage *)storage
{
YapDatabaseViewGrouping *viewGrouping = [YapDatabaseViewGrouping withObjectBlock:^NSString *(
@ -244,7 +166,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
[self registerMessageDatabaseViewWithName:TSMessageDatabaseViewExtensionName
viewGrouping:viewGrouping
version:@"2"
version:@"1"
storage:storage];
}
@ -260,7 +182,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
[self registerMessageDatabaseViewWithName:TSThreadOutgoingMessageDatabaseViewExtensionName
viewGrouping:viewGrouping
version:@"3"
version:@"2"
storage:storage];
}
@ -293,7 +215,13 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
}
}
return [thread isArchivedWithTransaction:transaction] ? TSArchiveGroup : TSInboxGroup;
if (thread.archivalDate) {
return ([self threadShouldBeInInbox:thread]) ? TSInboxGroup : TSArchiveGroup;
} else if (thread.archivalDate) {
return TSArchiveGroup;
} else {
return TSInboxGroup;
}
}];
YapDatabaseViewSorting *viewSorting = [self threadSorting];
@ -304,11 +232,34 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
[[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSThread collection]]];
YapDatabaseView *databaseView =
[[YapDatabaseAutoView alloc] initWithGrouping:viewGrouping sorting:viewSorting versionTag:@"4" options:options];
[[YapDatabaseAutoView alloc] initWithGrouping:viewGrouping sorting:viewSorting versionTag:@"3" options:options];
[storage asyncRegisterExtension:databaseView withName:TSThreadDatabaseViewExtensionName];
}
/**
* Determines whether a thread belongs to the archive or inbox
*
* @param thread TSThread
*
* @return Inbox if true, Archive if false
*/
+ (BOOL)threadShouldBeInInbox:(TSThread *)thread {
NSDate *lastMessageDate = thread.lastMessageDate;
NSDate *archivalDate = thread.archivalDate;
if (lastMessageDate && archivalDate) { // this is what is called
return ([lastMessageDate timeIntervalSinceDate:archivalDate] > 0)
? YES
: NO; // if there hasn't been a new message since the archive date, it's in the archive. an issue is
// that empty threads are always given with a lastmessage date of the present on every launch
} else if (archivalDate) {
return NO;
}
return YES;
}
+ (YapDatabaseViewSorting *)threadSorting {
return [YapDatabaseViewSorting withObjectBlock:^NSComparisonResult(YapDatabaseReadTransaction *transaction,
NSString *group,
@ -329,16 +280,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
TSThread *thread1 = (TSThread *)object1;
TSThread *thread2 = (TSThread *)object2;
if ([group isEqualToString:TSArchiveGroup] || [group isEqualToString:TSInboxGroup]) {
TSInteraction *_Nullable lastInteractionForInbox1 =
[thread1 lastInteractionForInboxWithTransaction:transaction];
NSDate *date1 = lastInteractionForInbox1 ? lastInteractionForInbox1.receivedAtDate : thread1.creationDate;
TSInteraction *_Nullable lastInteractionForInbox2 =
[thread2 lastInteractionForInboxWithTransaction:transaction];
NSDate *date2 = lastInteractionForInbox2 ? lastInteractionForInbox2.receivedAtDate : thread2.creationDate;
return [date1 compare:date2];
return [thread1.lastMessageDate compare:thread2.lastMessageDate];
}
return NSOrderedSame;
@ -485,7 +427,6 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
return result;
}
// MJK TODO - dynamic interactions
+ (id)threadOutgoingMessageDatabaseView:(YapDatabaseReadTransaction *)transaction
{
OWSAssertDebug(transaction);

View File

@ -95,7 +95,6 @@ NS_ASSUME_NONNULL_BEGIN
* Assign the latest persisted values from the database.
*/
- (void)reload;
- (void)reloadWithTransaction:(YapDatabaseReadTransaction *)transaction;
/**
* Saves the object with the shared readWrite connection - does not block.

View File

@ -218,19 +218,9 @@ NS_ASSUME_NONNULL_BEGIN
}
}
#pragma mark Reload
- (void)reload
{
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[self reloadWithTransaction:transaction];
}];
}
- (void)reloadWithTransaction:(YapDatabaseReadTransaction *)transaction
{
TSYapDatabaseObject *latest = [[self class] fetchObjectWithUniqueID:self.uniqueId transaction:transaction];
TSYapDatabaseObject *latest = [[self class] fetchObjectWithUniqueID:self.uniqueId];
if (!latest) {
OWSFailDebug(@"`latest` was unexpectedly nil");
return;