Update existing contact offers in place

WIP: migration / autoincrement logic

TODO:

-[x] contact offer
-[ ] verify all paths that utilized timestampForSorting, e.g. make sure SN appear before the message they affect, etc.
-[x] Monotonic ID
-[x] New extension which sorts by id
-[x] Migration
  -[ ] batch migration?

fixup contact offers
This commit is contained in:
Michael Kirk 2018-09-18 15:17:27 -06:00
parent a60d8eb161
commit 6c5fbc6de5
4 changed files with 62 additions and 38 deletions

View file

@ -444,8 +444,8 @@
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 */; };
4C948FF72146EB4800349F0D /* BlockListCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C948FF62146EB4800349F0D /* BlockListCache.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 */; };
4CB5F26920F7D060004D1B42 /* MessageActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB5F26820F7D060004D1B42 /* MessageActions.swift */; };
@ -1136,8 +1136,8 @@
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>"; };
4C948FF62146EB4800349F0D /* BlockListCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListCache.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>"; };
4CC0B59B20EC5F2E00CF6EE0 /* ConversationConfigurationSyncOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationConfigurationSyncOperation.swift; sourceTree = "<group>"; };

View file

@ -4,6 +4,8 @@
#import <SignalServiceKit/TSInteraction.h>
@class YapDatabaseReadWriteTransaction;
NS_ASSUME_NONNULL_BEGIN
@interface OWSContactOffersInteraction : TSInteraction
@ -11,6 +13,9 @@ 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;
@ -24,6 +29,11 @@ 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,6 +6,14 @@
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
@ -52,6 +60,18 @@ 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

@ -255,7 +255,6 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Dynamic Interactions
// MJK TODO - dynamic interactions
+ (ThreadDynamicInteractions *)ensureDynamicInteractionsForThread:(TSThread *)thread
contactsManager:(OWSContactsManager *)contactsManager
blockingManager:(OWSBlockingManager *)blockingManager
@ -464,53 +463,48 @@ NS_ASSUME_NONNULL_BEGIN
= (shouldHaveBlockOffer || shouldHaveAddToContactsOffer || shouldHaveAddToProfileWhitelistOffer);
if (isContactThread) {
TSContactThread *contactThread = (TSContactThread *)thread;
// MJK only place where `hasDismissedOffers` is read
if (contactThread.hasDismissedOffers) {
shouldHaveContactOffers = NO;
}
}
// 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];
// 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;
} 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.timestampForSorting);
TSInteraction *offersMessage =
[[OWSContactOffersInteraction alloc] initContactOffersWithTimestamp:contactOffersTimestamp
thread:thread
hasBlockOffer:shouldHaveBlockOffer
hasAddToContactsOffer:shouldHaveAddToContactsOffer
hasAddToProfileWhitelistOffer:shouldHaveAddToProfileWhitelistOffer
recipientId:recipientId];
[offersMessage saveWithTransaction:transaction];
[existingContactOffers updateHasBlockOffer:shouldHaveBlockOffer
hasAddToContactsOffer:shouldHaveAddToContactsOffer
hasAddToProfileWhitelistOffer:shouldHaveAddToProfileWhitelistOffer
transaction:transaction];
}
} else {
NSString *recipientId = ((TSContactThread *)thread).contactIdentifier;
OWSLogInfo(
@"Creating contact offers: %@ (%llu)", offersMessage.uniqueId, offersMessage.timestampForSorting);
// 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.timestampForSorting);
}
}
[self ensureUnreadIndicator:result