diff --git a/SignalMessaging/utils/ThreadUtil.m b/SignalMessaging/utils/ThreadUtil.m index a1516c539..33b3795c5 100644 --- a/SignalMessaging/utils/ThreadUtil.m +++ b/SignalMessaging/utils/ThreadUtil.m @@ -182,7 +182,7 @@ typedef void (^BuildOutgoingMessageCompletionBlock)(TSOutgoingMessage *savedMess // Loki: If we're not friends then always set the message to a friend request message. // If we're friends then the assumption is that we have the other user's pre key bundle. - NSString *messageClassAsString = (thread.isContactFriend || thread.isGroupThread || thread.isNoteToSelf) ? @"TSOutgoingMessage" : @"LKFriendRequestMessage"; + NSString *messageClassAsString = (thread.isContactFriend || thread.isGroupThread) ? @"TSOutgoingMessage" : @"LKFriendRequestMessage"; Class messageClass = NSClassFromString(messageClassAsString); TSOutgoingMessage *message = diff --git a/SignalServiceKit/src/Contacts/TSThread.h b/SignalServiceKit/src/Contacts/TSThread.h index dcc4d2fa0..0fa7e711f 100644 --- a/SignalServiceKit/src/Contacts/TSThread.h +++ b/SignalServiceKit/src/Contacts/TSThread.h @@ -182,18 +182,6 @@ extern ConversationColorName const kConversationColorName_Default; - (void)updateWithMutedUntilDate:(NSDate *)mutedUntilDate transaction:(YapDatabaseReadWriteTransaction *)transaction; -#pragma mark - Loki Friend Request Handling - -/** - Remove any old outgoing friend request messages that failed to send. - */ -- (void)removeOldOutgoingFriendRequestMessagesIfNeededWithTransaction:(YapDatabaseReadWriteTransaction *)transaction; - -/** - Remove any old incoming friend request messages that are pending. - */ -- (void)removeOldIncomingFriendRequestMessagesIfNeededWithTransaction:(YapDatabaseReadWriteTransaction *)transaction; - @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Contacts/TSThread.m b/SignalServiceKit/src/Contacts/TSThread.m index 3696e266a..8ec851b3d 100644 --- a/SignalServiceKit/src/Contacts/TSThread.m +++ b/SignalServiceKit/src/Contacts/TSThread.m @@ -710,65 +710,6 @@ ConversationColorName const kConversationColorName_Default = ConversationColorNa #pragma mark - Loki Friend Request Handling -- (void)removeOldOutgoingFriendRequestMessagesIfNeededWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - [self removeOldFriendRequestMessagesIfNeeded:OWSInteractionType_OutgoingMessage withTransaction:transaction]; -} - -- (void)removeOldIncomingFriendRequestMessagesIfNeededWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - [self removeOldFriendRequestMessagesIfNeeded:OWSInteractionType_IncomingMessage withTransaction:transaction]; -} - -- (void)removeOldFriendRequestMessagesIfNeeded:(OWSInteractionType)interactionType withTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - // Friend request status doesn't apply to group threads - if (self.isGroupThread) { return; } - // If we're friends with the other person then we don't need to remove any friend request messages - if ([LKFriendRequestProtocol isFriendsWithAnyLinkedDeviceOfHexEncodedPublicKey:self.contactIdentifier]) { return; } - - NSMutableArray *idsToRemove = [NSMutableArray new]; - __block TSMessage *_Nullable messageToKeep = nil; - - [self enumerateInteractionsWithTransaction:transaction usingBlock:^(TSInteraction *interaction, YapDatabaseReadTransaction *transaction) { - if (interaction.interactionType != interactionType) { return; } - - BOOL removeMessage = false; - TSMessage *message = (TSMessage *)interaction; - - // We want to keep the most recent message - if (messageToKeep == nil || messageToKeep.timestamp < message.timestamp) { - messageToKeep = message; - } - - // We want to remove any old incoming friend request messages which are pending - if (interactionType == OWSInteractionType_IncomingMessage) { - removeMessage = YES; - } else { - // Or if we're sending then remove any failed friend request messages - TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)message; - removeMessage = outgoingMessage.friendRequestStatus == LKMessageFriendRequestStatusSendingOrFailed; - } - - if (removeMessage) { - [idsToRemove addObject:interaction.uniqueId]; - } - }]; - - for (NSString *interactionID in idsToRemove) { - // Don't delete the most recent message - if (messageToKeep != nil && interactionID == messageToKeep.uniqueId) { continue; } - - // We need to fetch each interaction, since [TSInteraction removeWithTransaction:] does important work - TSInteraction *_Nullable interaction = [TSInteraction fetchObjectWithUniqueID:interactionID transaction:transaction]; - if (interaction == nil) { - OWSFailDebug(@"Couldn't load interaction."); - continue; - } - [interaction removeWithTransaction:transaction]; - } -} - - (BOOL)isContactFriend { return [LKFriendRequestProtocol getFriendRequestUIStatusForThread:self] == LKFriendRequestUIStatusFriends; diff --git a/SignalServiceKit/src/Loki/Protocol/Friend Requests/FriendRequestProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Friend Requests/FriendRequestProtocol.swift index 95ec4e1eb..f7c90a434 100644 --- a/SignalServiceKit/src/Loki/Protocol/Friend Requests/FriendRequestProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Friend Requests/FriendRequestProtocol.swift @@ -118,7 +118,14 @@ public final class FriendRequestProtocol : NSObject { if friendRequestStatus == .requestReceived { storage.setFriendRequestStatus(.friends, for: device, transaction: transaction) sendFriendRequestAcceptanceMessage(to: device, using: transaction) - } else if (friendRequestStatus == .none || friendRequestStatus == .requestExpired) && !ourDevices.contains(device) { + // Send a contact sync message if needed + guard !ourDevices.contains(hexEncodedPublicKey) else { return } + let masterHexEncodedPublicKey = storage.getMasterHexEncodedPublicKey(for: hexEncodedPublicKey, in: transaction) ?? hexEncodedPublicKey + let syncManager = SSKEnvironment.shared.syncManager + syncManager.syncContact(masterHexEncodedPublicKey, transaction: transaction) + } else if friendRequestStatus == .requestSent { + // We sent a friend request to this device before, how can we be sure that it hasn't expired? + } else if friendRequestStatus == .none || friendRequestStatus == .requestExpired && !ourDevices.contains(device) { // TODO: We should track these so that we can expire them and resend if needed MultiDeviceProtocol.getAutoGeneratedMultiDeviceFRMessageSend(for: device, in: transaction) .done(on: OWSDispatch.sendingQueue()) { autoGeneratedFRMessageSend in @@ -127,12 +134,6 @@ public final class FriendRequestProtocol : NSObject { } } } - // Send a contact sync message if we became friends with another user - if (!ourDevices.contains(hexEncodedPublicKey)) { - let masterHexEncodedPublicKey = storage.getMasterHexEncodedPublicKey(for: hexEncodedPublicKey, in: transaction) ?? hexEncodedPublicKey - let syncManager = SSKEnvironment.shared.syncManager - syncManager.syncContact(masterHexEncodedPublicKey, transaction: transaction) - } } @objc(sendFriendRequestAcceptanceMessageToHexEncodedPublicKey:using:) @@ -245,7 +246,8 @@ public final class FriendRequestProtocol : NSObject { guard friendRequestStatus != .none else { return } // Become friends storage.setFriendRequestStatus(.friends, for: hexEncodedPublicKey, transaction: transaction) - // Send a contact sync message + // Send a contact sync message if needed + guard !LokiDatabaseUtilities.isUserLinkedDevice(hexEncodedPublicKey, transaction: transaction) else { return } let masterHexEncodedPublicKey = storage.getMasterHexEncodedPublicKey(for: hexEncodedPublicKey, in: transaction) ?? hexEncodedPublicKey let syncManager = SSKEnvironment.shared.syncManager syncManager.syncContact(masterHexEncodedPublicKey, transaction: transaction) diff --git a/SignalServiceKit/src/Loki/Protocol/Friend Requests/LKFriendRequestMessage.m b/SignalServiceKit/src/Loki/Protocol/Friend Requests/LKFriendRequestMessage.m index 97d8b65b5..b7070bedf 100644 --- a/SignalServiceKit/src/Loki/Protocol/Friend Requests/LKFriendRequestMessage.m +++ b/SignalServiceKit/src/Loki/Protocol/Friend Requests/LKFriendRequestMessage.m @@ -3,6 +3,7 @@ #import "ProfileManagerProtocol.h" #import "SignalRecipient.h" #import "SSKEnvironment.h" +#import "TSThread.h" #import @@ -42,6 +43,6 @@ #pragma mark Settings - (uint)ttl { return (uint)[LKTTLUtilities getTTLFor:LKMessageTypeFriendRequest]; } -- (BOOL)shouldSyncTranscript { return NO; } +- (BOOL)shouldSyncTranscript { return self.thread.isNoteToSelf; } @end diff --git a/SignalServiceKit/src/Loki/Protocol/Meta/SessionMetaProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Meta/SessionMetaProtocol.swift index 068291781..6ab716cba 100644 --- a/SignalServiceKit/src/Loki/Protocol/Meta/SessionMetaProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Meta/SessionMetaProtocol.swift @@ -114,6 +114,7 @@ public final class SessionMetaProtocol : NSObject { @objc(updateDisplayNameIfNeededForHexEncodedPublicKey:using:appendingShortID:in:) public static func updateDisplayNameIfNeeded(for hexEncodedPublicKey: String, using dataMessage: SSKProtoDataMessage, appendingShortID appendShortID: Bool, in transaction: YapDatabaseReadWriteTransaction) { guard let profile = dataMessage.profile, let rawDisplayName = profile.displayName else { return } + guard !rawDisplayName.isEmpty else { return } let displayName: String // TODO: Figure out why we sometimes don't append the short ID if appendShortID { @@ -122,7 +123,6 @@ public final class SessionMetaProtocol : NSObject { } else { displayName = rawDisplayName } - guard !displayName.isEmpty else { return } let profileManager = SSKEnvironment.shared.profileManager profileManager.updateProfileForContact(withID: hexEncodedPublicKey, displayName: displayName, with: transaction) } diff --git a/SignalServiceKit/src/Loki/Protocol/Sync Messages/SyncMessagesProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Sync Messages/SyncMessagesProtocol.swift index 81626bca9..6e856ca9f 100644 --- a/SignalServiceKit/src/Loki/Protocol/Sync Messages/SyncMessagesProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Sync Messages/SyncMessagesProtocol.swift @@ -190,9 +190,10 @@ public final class SyncMessagesProtocol : NSObject { } }) case .requestReceived: - storage.setFriendRequestStatus(.friends, for: hexEncodedPublicKey, transaction: transaction) // Not sendFriendRequestAcceptanceMessage(to:using:) to take into account multi device FriendRequestProtocol.acceptFriendRequest(from: hexEncodedPublicKey, using: transaction) + // It's important that the line below happens after the one above + storage.setFriendRequestStatus(.friends, for: hexEncodedPublicKey, transaction: transaction) default: break } } diff --git a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m index 1b415f2e9..8b2b148c5 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m @@ -2,6 +2,8 @@ // Copyright (c) 2019 Open Whisper Systems. All rights reserved. // +@import Foundation; + #import "TSOutgoingMessage.h" #import "NSString+SSK.h" #import "OWSContact.h" @@ -1097,7 +1099,13 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt // Loki: Set display name & profile picture (exclude the profile picture if this is a friend request // to prevent unsolicited content from being sent) id profileManager = SSKEnvironment.shared.profileManager; - NSString *displayName = profileManager.localProfileName; + NSString *displayName; + NSString *masterHexEncodedPublicKey = [NSUserDefaults.standardUserDefaults stringForKey:@"masterDeviceHexEncodedPublicKey"]; + if (masterHexEncodedPublicKey != nil) { + displayName = [profileManager profileNameForRecipientWithID:masterHexEncodedPublicKey]; + } else { + displayName = profileManager.localProfileName; + } NSString *profilePictureURL = profileManager.profilePictureURL; SSKProtoDataMessageLokiProfileBuilder *profileBuilder = [SSKProtoDataMessageLokiProfile builder]; [profileBuilder setDisplayName:displayName]; diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 5b3d9f59f..832d61f83 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -1603,11 +1603,6 @@ NS_ASSUME_NONNULL_BEGIN } [incomingMessage saveWithTransaction:transaction]; - - // Loki: Remove any old incoming friend requests - if (incomingMessage.isFriendRequest) { - [thread removeOldIncomingFriendRequestMessagesIfNeededWithTransaction:transaction]; - } // Any messages sent from the current user - from this device or another - should be automatically marked as read. if ([(masterThread.contactIdentifier ?: envelope.source) isEqualToString:self.tsAccountManager.localNumber]) { diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m index 27dbe2645..7233d4548 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.m +++ b/SignalServiceKit/src/Messages/OWSMessageSender.m @@ -1219,10 +1219,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; if (shouldUpdateFriendRequest) { [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { if (!message.skipSave) { - [message.thread removeOldOutgoingFriendRequestMessagesIfNeededWithTransaction:transaction]; - if ([message.thread isKindOfClass:[TSContactThread class]]) { - [((TSContactThread *) message.thread) removeAllSessionRestoreDevicesWithTransaction:transaction]; - } // Update the message NSTimeInterval expirationInterval = 72 * kHourInterval; NSDate *expirationDate = [[NSDate new] dateByAddingTimeInterval:expirationInterval]; @@ -1553,6 +1549,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; failure(error); }]; + if ([LKMultiDeviceProtocol isMultiDeviceRequiredForMessage:message]) { // Avoid the write transaction if possible dispatch_async(dispatch_get_main_queue(), ^{ [self.primaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {