Merge pull request #16 from loki-project/message-expiration

Added friend request message expiration.
This commit is contained in:
Niels Andriesse 2019-05-20 12:57:29 +10:00 committed by GitHub
commit 8a815e1496
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 406 additions and 45 deletions

2
Pods

@ -1 +1 @@
Subproject commit 76e8209c9ef47b3d1e4e9a5d2039b883e4cd4640
Subproject commit 7fc33eedb29c3e93aacbc5c04b2a26571771c39b

View file

@ -158,6 +158,11 @@ static NSTimeInterval launchStartedAt;
return AppEnvironment.shared.legacyNotificationActionHandler;
}
- (OWSLokiFriendRequestExpireJob *)lokiFriendRequestExpireJob
{
return SSKEnvironment.shared.lokiFriendRequestExpireJob;
}
#pragma mark -
- (void)applicationDidEnterBackground:(UIApplication *)application
@ -682,6 +687,9 @@ static NSTimeInterval launchStartedAt;
// Clean up any messages that expired since last launch immediately
// and continue cleaning in the background.
[self.disappearingMessagesJob startIfNecessary];
// Start loki friend request expire job
[self.lokiFriendRequestExpireJob startIfNecessary];
[self enableBackgroundRefreshIfNecessary];
@ -1317,6 +1325,9 @@ static NSTimeInterval launchStartedAt;
// enables this feature
[self.disappearingMessagesJob startIfNecessary];
[self.profileManager ensureLocalProfileCached];
// Start loki friend request expire job
[self.lokiFriendRequestExpireJob startIfNecessary];
// For non-legacy users, read receipts are on by default.
[self.readReceiptManager setAreReadReceiptsEnabled:YES];

View file

@ -143,7 +143,7 @@ public class SessionResetOperation: OWSOperation, DurableOperation {
*/
if (self.contactThread.sessionResetState != .requestReceived) {
let message = TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: self.contactThread, messageType: .typeLokiSessionResetProgress)
let message = TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: self.contactThread, messageType: .typeLokiSessionResetInProgress)
message.save(with: transaction)
// Loki: We have initiated a session reset

View file

@ -83,27 +83,22 @@
switch kind {
case .incoming:
guard let message = message as? TSIncomingMessage else { preconditionFailure() }
buttonStackView.isHidden = didAcceptRequest || didDeclineRequest
let text: String = {
if didAcceptRequest {
return String(format: NSLocalizedString("You've accepted %@'s friend request", comment: ""), message.authorId)
} else if didDeclineRequest {
return String(format: NSLocalizedString("You've declined %@'s friend request", comment: ""), message.authorId)
} else {
return String(format: NSLocalizedString("%@ sent you a friend request", comment: ""), message.authorId)
}
buttonStackView.isHidden = didAcceptRequest || didDeclineRequest || message.isFriendRequestExpired
let format: String = {
if didAcceptRequest { return NSLocalizedString("You've accepted %@'s friend request", comment: "") }
else if didDeclineRequest { return NSLocalizedString("You've declined %@'s friend request", comment: "") }
else if message.isFriendRequestExpired { return NSLocalizedString("%@'s friend request has expired", comment: "") }
else { return NSLocalizedString("%@ sent you a friend request", comment: "") }
}()
label.text = text
label.text = String(format: format, message.authorId)
case .outgoing:
guard let message = message as? TSOutgoingMessage else { preconditionFailure() }
let text: String = {
if didAcceptRequest {
return String(format: NSLocalizedString("%@ accepted your friend request", comment: ""), message.thread.contactIdentifier()!)
} else {
return String(format: NSLocalizedString("You've sent %@ a friend request", comment: ""), message.thread.contactIdentifier()!)
}
let format: String = {
if didAcceptRequest { return NSLocalizedString("%@ accepted your friend request", comment: "") }
else if message.isFriendRequestExpired { return NSLocalizedString("Your friend request to %@ has expired", comment: "") }
else { return NSLocalizedString("You've sent %@ a friend request", comment: "") }
}()
label.text = text
label.text = String(format: format, message.thread.contactIdentifier()!)
}
}

View file

@ -4315,7 +4315,7 @@ typedef enum : NSUInteger {
- (void)acceptFriendRequest:(TSIncomingMessage *)friendRequest
{
// Update the thread's friend request state
[self.thread setFriendRequestStatus:TSThreadFriendRequestStatusFriends withTransaction:nil];
[self.thread saveFriendRequestStatus:TSThreadFriendRequestStatusFriends withTransaction:nil];
// Send friend request accepted message
[ThreadUtil enqueueAcceptFriendRequestMessageInThread:self.thread];
}
@ -4323,7 +4323,7 @@ typedef enum : NSUInteger {
- (void)declineFriendRequest:(TSIncomingMessage *)friendRequest
{
// Reset friend request status
[self.thread setFriendRequestStatus:TSThreadFriendRequestStatusNone withTransaction:nil];
[self.thread saveFriendRequestStatus:TSThreadFriendRequestStatusNone withTransaction:nil];
// Delete prekeys
NSString *contactID = self.thread.recipientIdentifiers.firstObject;
OWSPrimaryStorage *primaryStorage = SSKEnvironment.shared.primaryStorage;

View file

@ -2582,3 +2582,5 @@
"You've declined %@'s friend request" = "You've declined %@'s friend request";
"You've accepted %@'s friend request" = "You've accepted %@'s friend request";
"%@ accepted your friend request" = "%@ accepted your friend request";
"%@'s friend request has expired" = "%@'s friend request has expired";
"Your friend request to %@ has expired" = "Your friend request to %@ has expired";

View file

@ -125,6 +125,10 @@ NS_ASSUME_NONNULL_BEGIN
syncManager:syncManager
typingIndicators:typingIndicators
attachmentDownloads:attachmentDownloads]];
// Loki
OWSLokiFriendRequestExpireJob *lokiFriendRequestExpireJob = [[OWSLokiFriendRequestExpireJob alloc] initWithPrimaryStorage:primaryStorage];
[SSKEnvironment.shared setLokiFriendRequestExpireJob:lokiFriendRequestExpireJob];
appSpecificSingletonBlock();

View file

@ -198,7 +198,7 @@ typedef NS_ENUM(NSInteger, TSThreadFriendRequestStatus) {
#pragma mark - Loki Friend Request Handling
- (void)setFriendRequestStatus:(TSThreadFriendRequestStatus)friendRequestStatus withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction;
- (void)saveFriendRequestStatus:(TSThreadFriendRequestStatus)friendRequestStatus withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction;
@end

View file

@ -698,19 +698,18 @@ ConversationColorName const kConversationColorName_Default = ConversationColorNa
#pragma mark - Loki Friend Request Handling
- (void)setFriendRequestStatus:(TSThreadFriendRequestStatus)friendRequestStatus withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction
- (void)saveFriendRequestStatus:(TSThreadFriendRequestStatus)friendRequestStatus withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction
{
self.friendRequestStatus = friendRequestStatus;
void (^postNotification)() = ^() {
[NSNotificationCenter.defaultCenter postNotificationName:NSNotification.threadFriendRequestStatusChanged object:self.uniqueId];
};
if (transaction == nil) {
[self save];
[self.dbReadWriteConnection flushTransactionsWithCompletionQueue:dispatch_get_main_queue() completionBlock:^{
[NSNotificationCenter.defaultCenter postNotificationName:NSNotification.threadFriendRequestStatusChanged object:self.uniqueId];
}];
[self.dbReadWriteConnection flushTransactionsWithCompletionQueue:dispatch_get_main_queue() completionBlock:^{ postNotification(); }];
} else {
[self saveWithTransaction:transaction];
[transaction.connection flushTransactionsWithCompletionQueue:dispatch_get_main_queue() completionBlock:^{
[NSNotificationCenter.defaultCenter postNotificationName:NSNotification.threadFriendRequestStatusChanged object:self.uniqueId];
}];
[transaction.connection flushTransactionsWithCompletionQueue:dispatch_get_main_queue() completionBlock:^{ postNotification(); }];
}
}

View file

@ -16,13 +16,7 @@
@objc public func createPreKeyBundle(withTransaction transaction: YapDatabaseReadWriteTransaction) -> PreKeyBundle? {
let registrationId = TSAccountManager.sharedInstance().getOrGenerateRegistrationId(transaction)
return PreKeyBundle(registrationId: Int32(registrationId),
deviceId: Int32(deviceID),
preKeyId: Int32(prekeyID),
preKeyPublic: prekey,
signedPreKeyPublic: signedKey,
signedPreKeyId: Int32(signedKeyID),
signedPreKeySignature: signature,
identityKey: identityKey)
return PreKeyBundle(registrationId: Int32(registrationId), deviceId: Int32(deviceID), preKeyId: Int32(prekeyID), preKeyPublic: prekey,
signedPreKeyPublic: signedKey, signedPreKeyId: Int32(signedKeyID), signedPreKeySignature: signature, identityKey: identityKey)
}
}

View file

@ -0,0 +1,214 @@
/*
This class is used for settings friend requests to expired
This is modelled after `OWSDisappearingMessagesJob`.
*/
@objc(OWSLokiFriendRequestExpireJob)
public class FriendRequestExpireJob: NSObject {
private let databaseConnection: YapDatabaseConnection
private let messageFinder: FriendRequestExpireMessageFinder
// These three properties should only be accessed on the main thread.
private var hasStarted = false
private var fallbackTimer: Timer?
private var nextExpireTimer: Timer?
private var nextExpireDate: Date?
// Our queue
public static var serialQueue: DispatchQueue = {
return DispatchQueue(label: "network.loki.friendrequest.expire")
}()
/// Create a `FriendRequestExpireJob`.
/// This will create a auto-running job which will set friend requests to expired.
///
/// - Parameter primaryStorage: The primary storage.
@objc public init(withPrimaryStorage primaryStorage: OWSPrimaryStorage) {
databaseConnection = primaryStorage.newDatabaseConnection()
messageFinder = FriendRequestExpireMessageFinder()
super.init()
// This makes sure we only ever have one instance of this class
SwiftSingletons.register(self)
// Setup a timer that runs periodically to check for new friend request messages that will soon expire
AppReadiness.runNowOrWhenAppDidBecomeReady {
if (CurrentAppContext().isMainApp) {
let fallbackInterval = 5 * kMinuteInterval
self.fallbackTimer = WeakTimer.scheduledTimer(timeInterval: fallbackInterval, target: self, userInfo: nil, repeats: true) { [weak self] _ in
AssertIsOnMainThread()
guard let strongSelf = self else {
return
}
strongSelf.timerDidFire(mainTimer: false)
}
}
}
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: .OWSApplicationDidBecomeActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: .OWSApplicationWillResignActive, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
/// Start the job if we haven't done it yet
@objc public func startIfNecessary() {
DispatchQueue.main.async {
guard !self.hasStarted else {
return
}
self.hasStarted = true;
FriendRequestExpireJob.serialQueue.async {
self.runLoop()
}
}
}
/// The main loop
private func runLoop() {
AssertIsOnFriendRequestExpireQueue();
// Expire any messages
self.expireMessages()
var nextExpirationTimestamp: UInt64? = nil
self.databaseConnection.readWrite { transaction in
nextExpirationTimestamp = self.messageFinder.nextExpirationTimestamp(with: transaction)
}
guard let timestamp = nextExpirationTimestamp,
let nextExpireDate = NSDate.ows_date(withMillisecondsSince1970: timestamp) as? Date else {
return
}
// Schedule the next timer
self.scheduleRun(by: nextExpireDate)
}
// Schedule the next timer to run
private func scheduleRun(by date: Date) {
DispatchQueue.main.async {
guard CurrentAppContext().isMainAppAndActive else {
// Don't schedule run when inactive or not in main app.
return
}
let minDelaySeconds: TimeInterval = 1.0
let delaySeconds = max(minDelaySeconds, date.timeIntervalSinceNow)
let newTimerScheduleDate = Date(timeIntervalSinceNow: delaySeconds)
// check that we only set the date if needed
if let previousDate = self.nextExpireDate, previousDate < date {
// If the date is later than the one we have stored then just ignore
return
}
self.resetNextExpireTimer()
self.nextExpireDate = newTimerScheduleDate
self.nextExpireTimer = WeakTimer.scheduledTimer(timeInterval: delaySeconds, target: self, userInfo: nil, repeats: false) { [weak self] _ in
guard let strongSelf = self else {
return
}
strongSelf.timerDidFire(mainTimer: true)
}
}
}
// Expire any friend request messages
private func expireMessages() {
AssertIsOnFriendRequestExpireQueue()
let now = NSDate.ows_millisecondTimeStamp()
var backgroundTask: OWSBackgroundTask? = OWSBackgroundTask(label: "\(#function)", completionBlock: { [weak self] status in
AssertIsOnMainThread()
guard status == .expired else {
return
}
guard let strongSelf = self else {
return
}
strongSelf.databaseConnection.readWrite { transaction in
strongSelf.messageFinder.enumurateExpiredMessages(with: { message in
// Sanity check
guard message.friendRequestExpiresAt <= now else {
owsFailDebug("Refusing to expire friend request which doesn't expire until: \(message.friendRequestExpiresAt)")
return;
}
// Check that we only expire sent messages
guard message.thread.friendRequestStatus == .requestSent else {
// Set message to not expire, so our other logic works correctly
message.saveFriendRequestExpires(at: 0, with: transaction)
return;
}
// Loki: Expire the friend request message
message.thread.saveFriendRequestStatus(.requestExpired, with: transaction)
message.saveFriendRequestExpires(at: 0, with: transaction)
message.saveIsFriendRequestExpired(true, with: transaction)
}, transaction: transaction)
}
})
}
private func resetNextExpireTimer() {
nextExpireTimer?.invalidate()
nextExpireTimer = nil
nextExpireDate = nil
}
private func timerDidFire(mainTimer: Bool) {
guard CurrentAppContext().isMainAppAndActive else {
let infoString = mainTimer ? "Main timer fired while main app is inactive" : "Ignoring fallbacktimer for app which is not main and active."
Logger.info("[Loki Friend Request Expire Job] \(infoString)")
return
}
if (mainTimer) { self.resetNextExpireTimer() }
FriendRequestExpireJob.serialQueue.async {
self.runLoop()
}
}
}
// MARK: Events
private extension FriendRequestExpireJob {
@objc func didBecomeActive() {
AssertIsOnMainThread()
AppReadiness.runNowOrWhenAppDidBecomeReady {
FriendRequestExpireJob.serialQueue.async {
self.runLoop()
}
}
}
@objc func willResignActive() {
AssertIsOnMainThread()
resetNextExpireTimer()
}
}
// MARK: Asserts
private extension FriendRequestExpireJob {
func AssertIsOnFriendRequestExpireQueue() {
#if DEBUG
guard #available(iOS 10.0, *) else { return }
dispatchPrecondition(condition: .onQueue(FriendRequestExpireJob.serialQueue))
#endif
}
}

View file

@ -0,0 +1,88 @@
/*
This class is used for finding friend request messages which are expired.
This is modelled after `OWSDisappearingMessagesFinder`.
*/
@objc(OWSLokiFriendRequestExpireMessageFinder)
public class FriendRequestExpireMessageFinder: NSObject {
public static let friendRequestExpireColumn = "friend_request_expires_at"
public static let friendRequestExpireIndex = "loki_index_friend_request_expires_at"
public func nextExpirationTimestamp(with transaction: YapDatabaseReadTransaction) -> UInt64? {
let query = "WHERE \(FriendRequestExpireMessageFinder.friendRequestExpireColumn) > 0 ORDER BY \(FriendRequestExpireMessageFinder.friendRequestExpireColumn) ASC"
let dbQuery = YapDatabaseQuery(string: query, parameters: [])
let ext = transaction.ext(FriendRequestExpireMessageFinder.friendRequestExpireIndex) as? YapDatabaseSecondaryIndexTransaction
var firstMessage: TSMessage? = nil
ext?.enumerateKeysAndObjects(matching: dbQuery) { (collection, key, object, stop) in
firstMessage = object as? TSMessage
stop.pointee = true
}
guard let expireTime = firstMessage?.friendRequestExpiresAt, expireTime > 0 else {
return nil
}
return expireTime
}
public func enumurateExpiredMessages(with block: (TSMessage) -> Void, transaction: YapDatabaseReadTransaction) {
for messageId in self.fetchExpiredMessageIds(with: transaction) {
guard let message = TSMessage.fetch(uniqueId: messageId, transaction: transaction) else {
continue
}
block(message)
}
}
private func fetchExpiredMessageIds(with transaction: YapDatabaseReadTransaction) -> [String] {
var messageIds = [String]()
let now = NSDate.ows_millisecondTimeStamp()
let query = "WHERE \(FriendRequestExpireMessageFinder.friendRequestExpireColumn) > 0 AND \(FriendRequestExpireMessageFinder.friendRequestExpireColumn) <= \(now)"
// When (expireAt == 0) then the friend request SHOULD NOT expire
let dbQuery = YapDatabaseQuery(string: query, parameters: [])
let ext = transaction.ext(FriendRequestExpireMessageFinder.friendRequestExpireIndex) as? YapDatabaseSecondaryIndexTransaction
ext?.enumerateKeys(matching: dbQuery) { (collection, key, stop) in
messageIds.append(key)
}
return Array(messageIds)
}
}
// MARK: YapDatabaseExtension
public extension FriendRequestExpireMessageFinder {
@objc public static var indexDatabaseExtension: YapDatabaseSecondaryIndex {
let setup = YapDatabaseSecondaryIndexSetup()
setup.addColumn(friendRequestExpireColumn, with: .integer)
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { (transaction, dict, collection, key, object) in
guard let message = object as? TSMessage else {
return
}
// Only select messages whose status is sent
guard message.thread.friendRequestStatus == .requestSent else {
return
}
// TODO: Replace this with unlock timer
dict[friendRequestExpireColumn] = message.expiresAt
}
return YapDatabaseSecondaryIndex(setup: setup, handler: handler)
}
@objc public static var databaseExtensionName: String {
return friendRequestExpireIndex
}
@objc public static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) {
storage.register(self.indexDatabaseExtension, withName: friendRequestExpireIndex)
}
}

View file

@ -29,6 +29,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly, nullable) OWSContact *contactShare;
@property (nonatomic, readonly, nullable) OWSLinkPreview *linkPreview;
@property (nonatomic) BOOL isFriendRequest; // Loki
@property (nonatomic) uint64_t friendRequestExpiresAt;
@property (nonatomic) BOOL isFriendRequestExpired;
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;
@ -71,7 +73,9 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Loki Friend Request Handling
- (void)setIsFriendRequest:(BOOL)isFriendRequest withTransaction:(YapDatabaseReadWriteTransaction *)transaction;
- (void)saveIsFriendRequest:(BOOL)isFriendRequest withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction;
- (void)saveFriendRequestExpiresAt:(u_int64_t)expiresAt withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction;
- (void)saveIsFriendRequestExpired:(BOOL)isFriendRequestExpired withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction;
@end

View file

@ -82,6 +82,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
_quotedMessage = quotedMessage;
_contactShare = contactShare;
_linkPreview = linkPreview;
_friendRequestExpiresAt = 0;
return self;
}
@ -440,7 +441,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
#pragma mark - Loki Friend Request Handling
- (void)setIsFriendRequest:(BOOL)isFriendRequest withTransaction:(YapDatabaseReadWriteTransaction *)transaction
- (void)saveIsFriendRequest:(BOOL)isFriendRequest withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction
{
self.isFriendRequest = isFriendRequest;
if (transaction == nil) {
@ -450,6 +451,26 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
}
}
- (void)saveFriendRequestExpiresAt:(u_int64_t)expiresAt withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction
{
self.friendRequestExpiresAt = expiresAt;
if (transaction == nil) {
[self save];
} else {
[self saveWithTransaction:transaction];
}
}
- (void)saveIsFriendRequestExpired:(BOOL)isFriendRequestExpired withTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction
{
self.isFriendRequest = isFriendRequestExpired;
if (transaction == nil) {
[self save];
} else {
[self saveWithTransaction:transaction];
}
}
@end
NS_ASSUME_NONNULL_END

View file

@ -1474,7 +1474,8 @@ NS_ASSUME_NONNULL_BEGIN
// before updating Alice's thread's friend request status to TSThreadFriendRequestStatusFriends,
// we can end up in a deadlock where both users' threads' friend request statuses are
// TSThreadFriendRequestStatusRequestSent.
[thread setFriendRequestStatus:TSThreadFriendRequestStatusFriends withTransaction:transaction];
[thread saveFriendRequestStatus:TSThreadFriendRequestStatusFriends withTransaction:transaction];
// The two lines below are equivalent to calling [ThreadUtil enqueueAcceptFriendRequestMessageInThread:thread]
OWSEphemeralMessage *emptyMessage = [OWSEphemeralMessage createEmptyOutgoingMessageInThread:thread];
[self.messageSenderJobQueue addMessage:emptyMessage transaction:transaction];
@ -1484,13 +1485,13 @@ NS_ASSUME_NONNULL_BEGIN
// friend request status is reset to TSThreadFriendRequestStatusNone. Bob now sends Alice a friend
// request. Alice's thread's friend request status is reset to
// TSThreadFriendRequestStatusRequestReceived.
[thread setFriendRequestStatus:TSThreadFriendRequestStatusRequestReceived withTransaction:transaction];
[thread saveFriendRequestStatus:TSThreadFriendRequestStatusRequestReceived withTransaction:transaction];
message.isFriendRequest = YES;
}
} else if (!thread.isContactFriend) {
// If the thread's friend request status is not TSThreadFriendRequestStatusFriends, but we're receiving a message,
// it must be a friend request accepted message. Declining a friend request doesn't send a message.
[thread setFriendRequestStatus:TSThreadFriendRequestStatusFriends withTransaction:transaction];
[thread saveFriendRequestStatus:TSThreadFriendRequestStatusFriends withTransaction:transaction];
}
}

View file

@ -1110,7 +1110,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// Update the thread's friend request status if needed
NSInteger *messageType = ((NSNumber *)signalMessage[@"type"]).integerValue;
if (messageType == TSFriendRequestMessageType) {
[message.thread setFriendRequestStatus:TSThreadFriendRequestStatusRequestSending withTransaction:nil];
[message.thread saveFriendRequestStatus:TSThreadFriendRequestStatusRequestSending withTransaction:nil];
}
BOOL isPoWRequired = YES; // TODO: Base on message type
[[LokiAPI objc_sendSignalMessage:signalMessage to:recipient.recipientId timestamp:message.timestamp requiringPoW:isPoWRequired]
@ -1118,7 +1118,14 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// Loki
// ========
if (messageType == TSFriendRequestMessageType) {
[message.thread setFriendRequestStatus:TSThreadFriendRequestStatusRequestSent withTransaction:nil];
[message.thread saveFriendRequestStatus:TSThreadFriendRequestStatusRequestSent withTransaction:nil];
// We also want to expire the message after 72 hours
NSTimeInterval expireTimeInterval = 72 * kHourInterval;
NSDate *expireDate = [[NSDate new] dateByAddingTimeInterval:expireTimeInterval];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[message saveFriendRequestExpiresAt:[NSDate ows_millisecondsSince1970ForDate:expireDate] withTransaction:transaction];
}];
}
// ========
// Invoke the completion handler
@ -1131,7 +1138,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// Loki
// ========
if (messageType == TSFriendRequestMessageType) {
[message.thread setFriendRequestStatus:TSThreadFriendRequestStatusNone withTransaction:nil];
[message.thread saveFriendRequestStatus:TSThreadFriendRequestStatusNone withTransaction:nil];
}
// ========
// Handle the error

View file

@ -27,6 +27,9 @@ NS_ASSUME_NONNULL_BEGIN
@class TSSocketManager;
@class YapDatabaseConnection;
// Loki
@class OWSLokiFriendRequestExpireJob;
@protocol ContactsManagerProtocol;
@protocol NotificationsProtocol;
@protocol OWSCallMessageHandler;
@ -111,6 +114,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (atomic, readonly) YapDatabaseConnection *migrationDBConnection;
@property (atomic, readonly) YapDatabaseConnection *analyticsDBConnection;
// Loki
@property (nonatomic, readonly) OWSLokiFriendRequestExpireJob *lokiFriendRequestExpireJob;
- (void)setLokiFriendRequestExpireJob:(OWSLokiFriendRequestExpireJob *)lokiFriendRequestExpireJob;
- (BOOL)isComplete;
@end

View file

@ -37,6 +37,9 @@ static SSKEnvironment *sharedSSKEnvironment;
@property (nonatomic) id<OWSTypingIndicators> typingIndicators;
@property (nonatomic) OWSAttachmentDownloads *attachmentDownloads;
// Loki
@property (nonatomic) OWSLokiFriendRequestExpireJob *lokiFriendRequestExpireJob;
@end
#pragma mark -
@ -196,6 +199,15 @@ static SSKEnvironment *sharedSSKEnvironment;
}
}
- (void)setLokiFriendRequestExpireJob:(OWSLokiFriendRequestExpireJob *)lokiFriendRequestExpireJob {
@synchronized(self) {
OWSAssertDebug(lokiFriendRequestExpireJob);
OWSAssertDebug(!_lokiFriendRequestExpireJob);
_lokiFriendRequestExpireJob = lokiFriendRequestExpireJob;
}
}
- (BOOL)isComplete
{
return (self.callMessageHandler != nil && self.notificationsManager != nil);

View file

@ -214,6 +214,8 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
[OWSMediaGalleryFinder asyncRegisterDatabaseExtensionsWithPrimaryStorage:self];
[TSDatabaseView asyncRegisterLazyRestoreAttachmentsDatabaseView:self];
[SSKJobRecordFinder asyncRegisterDatabaseExtensionObjCWithStorage:self];
[OWSLokiFriendRequestExpireMessageFinder asyncRegisterDatabaseExtensions:self];
[self.database
flushExtensionRequestsWithCompletionQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)