parent
9f569d376c
commit
6e52009ff0
|
@ -17,7 +17,6 @@ NSString *const OWSReadReceiptsProcessorMarkedMessageAsReadNotification =
|
|||
@interface OWSReadReceiptsProcessor ()
|
||||
|
||||
@property (nonatomic, readonly) NSArray<OWSReadReceipt *> *readReceipts;
|
||||
@property (nonatomic, readonly) OWSDisappearingMessagesJob *disappearingMessagesJob;
|
||||
@property (nonatomic, readonly) TSStorageManager *storageManager;
|
||||
|
||||
@end
|
||||
|
@ -34,7 +33,6 @@ NSString *const OWSReadReceiptsProcessorMarkedMessageAsReadNotification =
|
|||
|
||||
_readReceipts = [readReceipts copy];
|
||||
_storageManager = storageManager;
|
||||
_disappearingMessagesJob = [[OWSDisappearingMessagesJob alloc] initWithStorageManager:storageManager];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -85,7 +83,7 @@ NSString *const OWSReadReceiptsProcessorMarkedMessageAsReadNotification =
|
|||
[TSIncomingMessage findMessageWithAuthorId:readReceipt.senderId timestamp:readReceipt.timestamp];
|
||||
if (message) {
|
||||
[message markAsReadFromReadReceipt];
|
||||
[self.disappearingMessagesJob setExpirationForMessage:message expirationStartedAt:readReceipt.timestamp];
|
||||
[OWSDisappearingMessagesJob setExpirationForMessage:message expirationStartedAt:readReceipt.timestamp];
|
||||
// If it was previously saved, no need to keep it around any longer.
|
||||
[readReceipt remove];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#import "OWSRecordTranscriptJob.h"
|
||||
#import "OWSAttachmentsProcessor.h"
|
||||
#import "OWSDisappearingMessagesJob.h"
|
||||
#import "OWSIncomingSentMessageTranscript.h"
|
||||
#import "OWSMessageSender.h"
|
||||
#import "TSInfoMessage.h"
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#import "TSMessage.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "OWSDisappearingMessagesJob.h"
|
||||
#import "TSAttachment.h"
|
||||
#import "TSAttachmentPointer.h"
|
||||
#import "TSThread.h"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Created by Michael Kirk on 9/23/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
@ -10,15 +11,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@interface OWSDisappearingMessagesJob : NSObject
|
||||
|
||||
+ (instancetype)sharedJob;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithStorageManager:(TSStorageManager *)storageManager NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)run;
|
||||
- (void)setExpirationsForThread:(TSThread *)thread;
|
||||
- (void)setExpirationForMessage:(TSMessage *)message;
|
||||
- (void)setExpirationForMessage:(TSMessage *)message expirationStartedAt:(uint64_t)expirationStartedAt;
|
||||
- (void)runBy:(uint64_t)millisecondTimestamp;
|
||||
|
||||
+ (void)setExpirationsForThread:(TSThread *)thread;
|
||||
+ (void)setExpirationForMessage:(TSMessage *)message;
|
||||
+ (void)setExpirationForMessage:(TSMessage *)message expirationStartedAt:(uint64_t)expirationStartedAt;
|
||||
|
||||
/**
|
||||
* Synchronize our disappearing messages settings with that of the given message. Useful so we can
|
||||
|
@ -31,9 +30,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
* @param contactsManager
|
||||
* Provides the contact name responsible for any configuration changes in an info message.
|
||||
*/
|
||||
- (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
|
||||
+ (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
|
||||
contactsManager:(id<ContactsManagerProtocol>)contactsManager;
|
||||
|
||||
// Clean up any messages that expired since last launch immediately
|
||||
// and continue cleaning in the background.
|
||||
- (void)startIfNecessary;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1,26 +1,46 @@
|
|||
// Created by Michael Kirk on 9/23/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDisappearingMessagesJob.h"
|
||||
#import "ContactsManagerProtocol.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "NSTimer+OWS.h"
|
||||
#import "OWSDisappearingConfigurationUpdateInfoMessage.h"
|
||||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
#import "OWSDisappearingMessagesFinder.h"
|
||||
#import "TSIncomingMessage.h"
|
||||
#import "TSMessage.h"
|
||||
#import "TSStorageManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSDisappearingMessagesJob ()
|
||||
|
||||
// This property should only be accessed on the serialQueue.
|
||||
@property (nonatomic, readonly) OWSDisappearingMessagesFinder *disappearingMessagesFinder;
|
||||
@property (atomic) uint64_t scheduledAt;
|
||||
|
||||
// These three properties should only be accessed on the main thread.
|
||||
@property (nonatomic) BOOL hasStarted;
|
||||
@property (nonatomic, nullable) NSTimer *timer;
|
||||
@property (nonatomic, nullable) NSDate *timerScheduleDate;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation OWSDisappearingMessagesJob
|
||||
|
||||
+ (instancetype)sharedJob
|
||||
{
|
||||
static OWSDisappearingMessagesJob *sharedJob = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedJob = [[self alloc] initWithStorageManager:[TSStorageManager sharedManager]];
|
||||
});
|
||||
return sharedJob;
|
||||
}
|
||||
|
||||
- (instancetype)initWithStorageManager:(TSStorageManager *)storageManager
|
||||
{
|
||||
self = [super init];
|
||||
|
@ -28,12 +48,23 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return self;
|
||||
}
|
||||
|
||||
_scheduledAt = ULLONG_MAX;
|
||||
_disappearingMessagesFinder = [[OWSDisappearingMessagesFinder alloc] initWithStorageManager:storageManager];
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (dispatch_queue_t)serialQueue
|
||||
{
|
||||
static dispatch_queue_t queue = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
queue = dispatch_queue_create("org.whispersystems.disappearing.messages", DISPATCH_QUEUE_SERIAL);
|
||||
});
|
||||
return queue;
|
||||
}
|
||||
|
||||
- (void)run
|
||||
{
|
||||
uint64_t now = [NSDate ows_millisecondTimeStamp];
|
||||
|
@ -46,18 +77,17 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ removing message which expired at: %lld", self.tag, message.expiresAt);
|
||||
DDLogDebug(@"%@ Removing message which expired at: %lld", self.tag, message.expiresAt);
|
||||
[message remove];
|
||||
expirationCount++;
|
||||
}];
|
||||
|
||||
DDLogDebug(@"%@ removed %u expired messages", self.tag, expirationCount);
|
||||
DDLogDebug(@"%@ Removed %u expired messages", self.tag, expirationCount);
|
||||
}
|
||||
|
||||
- (void)runLoop
|
||||
{
|
||||
// allow next runAt to schedule.
|
||||
self.scheduledAt = ULLONG_MAX;
|
||||
DDLogVerbose(@"%@ Run", self.tag);
|
||||
|
||||
[self run];
|
||||
|
||||
|
@ -69,23 +99,19 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
unsigned int delaySeconds = (10 * 60); // 10 minutes.
|
||||
DDLogDebug(
|
||||
@"%@ No more expiring messages. Setting next check %u seconds into the future", self.tag, delaySeconds);
|
||||
[self runBy:now + delaySeconds * 1000];
|
||||
[self runByDate:[NSDate ows_dateWithMillisecondsSince1970:now + delaySeconds * 1000]];
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t nextExpirationAt = [nextExpirationTimestampNumber unsignedLongLongValue];
|
||||
uint64_t runByMilliseconds;
|
||||
if (nextExpirationAt < now + 1000) {
|
||||
DDLogWarn(@"%@ Next run requested at %llu, which is too soon. Delaying by 1 sec to prevent churn",
|
||||
self.tag,
|
||||
nextExpirationAt);
|
||||
runByMilliseconds = now + 1000;
|
||||
} else {
|
||||
runByMilliseconds = nextExpirationAt;
|
||||
}
|
||||
[self runByDate:[NSDate ows_dateWithMillisecondsSince1970:MAX(nextExpirationAt, now)]];
|
||||
}
|
||||
|
||||
DDLogVerbose(@"%@ Requesting next expiration to run by: %llu", self.tag, nextExpirationAt);
|
||||
[self runBy:runByMilliseconds];
|
||||
+ (void)setExpirationForMessage:(TSMessage *)message
|
||||
{
|
||||
dispatch_async(self.serialQueue, ^{
|
||||
[[self sharedJob] setExpirationForMessage:message];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setExpirationForMessage:(TSMessage *)message
|
||||
|
@ -104,6 +130,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[self setExpirationForMessage:message expirationStartedAt:[NSDate ows_millisecondTimeStamp]];
|
||||
}
|
||||
|
||||
+ (void)setExpirationForMessage:(TSMessage *)message expirationStartedAt:(uint64_t)expirationStartedAt
|
||||
{
|
||||
dispatch_async(self.serialQueue, ^{
|
||||
[[self sharedJob] setExpirationForMessage:message expirationStartedAt:expirationStartedAt];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setExpirationForMessage:(TSMessage *)message expirationStartedAt:(uint64_t)expirationStartedAt
|
||||
{
|
||||
if (!message.isExpiringMessage) {
|
||||
|
@ -120,7 +153,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
|
||||
// Necessary that the async expiration run happens *after* the message is saved with expiration configuration.
|
||||
[self runBy:message.expiresAt];
|
||||
[self runByDate:[NSDate ows_dateWithMillisecondsSince1970:message.expiresAt]];
|
||||
}
|
||||
|
||||
+ (void)setExpirationsForThread:(TSThread *)thread
|
||||
{
|
||||
dispatch_async(self.serialQueue, ^{
|
||||
[[self sharedJob] setExpirationsForThread:thread];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setExpirationsForThread:(TSThread *)thread
|
||||
|
@ -138,26 +178,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}];
|
||||
}
|
||||
|
||||
- (void)runBy:(uint64_t)timestamp
|
||||
+ (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
|
||||
contactsManager:(id<ContactsManagerProtocol>)contactsManager
|
||||
{
|
||||
// Prevent amplification.
|
||||
if (timestamp >= self.scheduledAt) {
|
||||
DDLogVerbose(@"%@ expiration already scheduled before %llu", self.tag, timestamp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Schedule
|
||||
DDLogVerbose(@"%@ Scheduled expiration run at %llu", self.tag, timestamp);
|
||||
self.scheduledAt = timestamp;
|
||||
uint64_t millisecondsDelay = timestamp - [NSDate ows_millisecondTimeStamp];
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC * millisecondsDelay),
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||
^{
|
||||
[self runLoop];
|
||||
});
|
||||
dispatch_async(self.serialQueue, ^{
|
||||
[[self sharedJob] becomeConsistentWithConfigurationForMessage:message contactsManager:contactsManager];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
- (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
|
||||
contactsManager:(id<ContactsManagerProtocol>)contactsManager
|
||||
{
|
||||
|
@ -206,6 +234,83 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
}
|
||||
|
||||
- (void)startIfNecessary
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.hasStarted) {
|
||||
return;
|
||||
}
|
||||
self.hasStarted = YES;
|
||||
|
||||
[self runNow];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)runNow
|
||||
{
|
||||
[self runByDate:[NSDate new] ignoreMinDelay:YES];
|
||||
}
|
||||
|
||||
- (void)runByDate:(NSDate *)date
|
||||
{
|
||||
[self runByDate:date ignoreMinDelay:NO];
|
||||
}
|
||||
|
||||
- (void)runByDate:(NSDate *)date ignoreMinDelay:(BOOL)ignoreMinDelay
|
||||
{
|
||||
OWSAssert(date);
|
||||
|
||||
NSDateFormatter *dateFormatter = [NSDateFormatter new];
|
||||
dateFormatter.dateStyle = NSDateFormatterShortStyle;
|
||||
dateFormatter.timeStyle = kCFDateFormatterMediumStyle;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// Don't run more often than once per second.
|
||||
const NSTimeInterval kMinDelaySeconds = ignoreMinDelay ? 0.f : 1.f;
|
||||
// Don't run less often than once per N minutes.
|
||||
const NSTimeInterval kMaxDelaySeconds = 5 * 60.f;
|
||||
NSTimeInterval delaySeconds
|
||||
= MAX(kMinDelaySeconds, MIN(kMaxDelaySeconds, [date timeIntervalSinceDate:[NSDate new]]));
|
||||
NSDate *timerScheduleDate = [NSDate dateWithTimeIntervalSinceNow:delaySeconds];
|
||||
if (self.timerScheduleDate && [timerScheduleDate timeIntervalSinceDate:self.timerScheduleDate] > 0) {
|
||||
DDLogVerbose(@"%@ Request to run at %@ (%d sec.) ignored due to scheduled run at %@ (%d sec.)",
|
||||
self.tag,
|
||||
[dateFormatter stringFromDate:date],
|
||||
(int)round(MAX(0, [date timeIntervalSinceDate:[NSDate new]])),
|
||||
[dateFormatter stringFromDate:self.timerScheduleDate],
|
||||
(int)round(MAX(0, [self.timerScheduleDate timeIntervalSinceDate:[NSDate new]])));
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Schedule
|
||||
NSDateFormatter *dateFormatter = [NSDateFormatter new];
|
||||
dateFormatter.dateStyle = NSDateFormatterShortStyle;
|
||||
dateFormatter.timeStyle = kCFDateFormatterMediumStyle;
|
||||
DDLogVerbose(@"%@ Scheduled run at %@ (%d sec.)",
|
||||
self.tag,
|
||||
[dateFormatter stringFromDate:timerScheduleDate],
|
||||
(int)round(MAX(0, [timerScheduleDate timeIntervalSinceDate:[NSDate new]])));
|
||||
self.timerScheduleDate = timerScheduleDate;
|
||||
[self.timer invalidate];
|
||||
self.timer = [NSTimer weakScheduledTimerWithTimeInterval:delaySeconds
|
||||
target:self
|
||||
selector:@selector(timerDidFire)
|
||||
userInfo:nil
|
||||
repeats:NO];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)timerDidFire
|
||||
{
|
||||
[self.timer invalidate];
|
||||
self.timer = nil;
|
||||
self.timerScheduleDate = nil;
|
||||
|
||||
dispatch_async(OWSDisappearingMessagesJob.serialQueue, ^{
|
||||
[self runLoop];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
+ (NSString *)tag
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Created by Michael Kirk on 9/24/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSIncomingMessageReadObserver.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
|
@ -13,7 +14,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@interface OWSIncomingMessageReadObserver ()
|
||||
|
||||
@property BOOL isObserving;
|
||||
@property (nonatomic, readonly) OWSDisappearingMessagesJob *disappearingMessagesJob;
|
||||
@property (nonatomic, readonly) OWSSendReadReceiptsJob *sendReadReceiptsJob;
|
||||
|
||||
@end
|
||||
|
@ -34,7 +34,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
|
||||
_isObserving = NO;
|
||||
_disappearingMessagesJob = [[OWSDisappearingMessagesJob alloc] initWithStorageManager:storageManager];
|
||||
_sendReadReceiptsJob = [[OWSSendReadReceiptsJob alloc] initWithMessageSender:messageSender];
|
||||
|
||||
return self;
|
||||
|
@ -61,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
|
||||
TSIncomingMessage *message = (TSIncomingMessage *)notification.object;
|
||||
[self.disappearingMessagesJob setExpirationForMessage:message];
|
||||
[OWSDisappearingMessagesJob setExpirationForMessage:message];
|
||||
[self.sendReadReceiptsJob runWith:message];
|
||||
}
|
||||
|
||||
|
|
|
@ -341,7 +341,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
||||
@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
|
||||
@property (nonatomic, readonly) ContactsUpdater *contactsUpdater;
|
||||
@property (nonatomic, readonly) OWSDisappearingMessagesJob *disappearingMessagesJob;
|
||||
@property (atomic, readonly) NSMutableDictionary<NSString *, NSOperationQueue *> *sendingQueueMap;
|
||||
|
||||
@end
|
||||
|
@ -366,7 +365,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
|
||||
_uploadingService = [[OWSUploadingService alloc] initWithNetworkManager:networkManager];
|
||||
_dbConnection = storageManager.newDatabaseConnection;
|
||||
_disappearingMessagesJob = [[OWSDisappearingMessagesJob alloc] initWithStorageManager:storageManager];
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
|
@ -1060,20 +1058,20 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
[self sendSyncTranscriptForMessage:message];
|
||||
}
|
||||
|
||||
[self.disappearingMessagesJob setExpirationForMessage:message];
|
||||
[OWSDisappearingMessagesJob setExpirationForMessage:message];
|
||||
}
|
||||
|
||||
- (void)handleMessageSentRemotely:(TSOutgoingMessage *)message sentAt:(uint64_t)sentAt
|
||||
{
|
||||
[message updateWithWasSentAndDelivered];
|
||||
[self becomeConsistentWithDisappearingConfigurationForMessage:message];
|
||||
[self.disappearingMessagesJob setExpirationForMessage:message expirationStartedAt:sentAt];
|
||||
[OWSDisappearingMessagesJob setExpirationForMessage:message expirationStartedAt:sentAt];
|
||||
}
|
||||
|
||||
- (void)becomeConsistentWithDisappearingConfigurationForMessage:(TSOutgoingMessage *)outgoingMessage
|
||||
{
|
||||
[self.disappearingMessagesJob becomeConsistentWithConfigurationForMessage:outgoingMessage
|
||||
contactsManager:self.contactsManager];
|
||||
[OWSDisappearingMessagesJob becomeConsistentWithConfigurationForMessage:outgoingMessage
|
||||
contactsManager:self.contactsManager];
|
||||
}
|
||||
|
||||
- (void)handleSendToMyself:(TSOutgoingMessage *)outgoingMessage
|
||||
|
|
|
@ -13,7 +13,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@class OWSSignalServiceProtosEnvelope;
|
||||
@class OWSSignalServiceProtosDataMessage;
|
||||
@class ContactsUpdater;
|
||||
@class OWSDisappearingMessagesJob;
|
||||
@class OWSMessageSender;
|
||||
@protocol ContactsManagerProtocol;
|
||||
@protocol OWSCallMessageHandler;
|
||||
|
|
|
@ -48,12 +48,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
|
||||
@property (nonatomic, readonly) TSStorageManager *storageManager;
|
||||
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
||||
@property (nonatomic, readonly) OWSDisappearingMessagesJob *disappearingMessagesJob;
|
||||
@property (nonatomic, readonly) OWSIncomingMessageFinder *incomingMessageFinder;
|
||||
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation TSMessagesManager
|
||||
|
||||
+ (instancetype)sharedManager {
|
||||
|
@ -103,7 +104,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
_messageSender = messageSender;
|
||||
|
||||
_dbConnection = storageManager.newDatabaseConnection;
|
||||
_disappearingMessagesJob = [[OWSDisappearingMessagesJob alloc] initWithStorageManager:storageManager];
|
||||
_incomingMessageFinder = [[OWSIncomingMessageFinder alloc] initWithDatabase:storageManager.database];
|
||||
_blockingManager = [OWSBlockingManager sharedManager];
|
||||
|
||||
|
@ -940,8 +940,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
storageManager:self.storageManager];
|
||||
[readReceiptsProcessor process];
|
||||
|
||||
[self.disappearingMessagesJob becomeConsistentWithConfigurationForMessage:incomingMessage
|
||||
contactsManager:self.contactsManager];
|
||||
[OWSDisappearingMessagesJob becomeConsistentWithConfigurationForMessage:incomingMessage
|
||||
contactsManager:self.contactsManager];
|
||||
|
||||
// Update thread preview in inbox
|
||||
[thread touch];
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSTimer (OWS)
|
||||
|
||||
// This method avoids the classic NSTimer retain cycle bug
|
||||
// by using a weak reference to the target.
|
||||
+ (NSTimer *)weakScheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval
|
||||
target:(id)target
|
||||
selector:(SEL)selector
|
||||
userInfo:(nullable id)userInfo
|
||||
repeats:(BOOL)repeats;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSTimer+OWS.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSTimerProxy : NSObject
|
||||
|
||||
@property (nonatomic, weak) id target;
|
||||
@property (nonatomic) SEL selector;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation NSTimerProxy
|
||||
|
||||
- (void)timerFired:(NSDictionary *)userInfo
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
[self.target performSelector:self.selector withObject:userInfo];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
static void *kNSTimer_OWS_Proxy = &kNSTimer_OWS_Proxy;
|
||||
|
||||
@implementation NSTimer (OWS)
|
||||
|
||||
- (NSTimerProxy *)ows_proxy
|
||||
{
|
||||
return objc_getAssociatedObject(self, kNSTimer_OWS_Proxy);
|
||||
}
|
||||
|
||||
- (void)ows_setProxy:(NSTimerProxy *)proxy
|
||||
{
|
||||
OWSAssert(proxy);
|
||||
|
||||
objc_setAssociatedObject(self, kNSTimer_OWS_Proxy, proxy, OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
|
||||
+ (NSTimer *)weakScheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval
|
||||
target:(id)target
|
||||
selector:(SEL)selector
|
||||
userInfo:(nullable id)userInfo
|
||||
repeats:(BOOL)repeats
|
||||
{
|
||||
NSTimerProxy *proxy = [NSTimerProxy new];
|
||||
proxy.target = target;
|
||||
proxy.selector = selector;
|
||||
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval
|
||||
target:proxy
|
||||
selector:@selector(timerFired:)
|
||||
userInfo:userInfo
|
||||
repeats:repeats];
|
||||
[timer ows_setProxy:proxy];
|
||||
return timer;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
Loading…
Reference in New Issue