From 31616804322a63fc50f0a51e487e9743813a78ce Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Thu, 16 May 2019 12:08:37 +1000 Subject: [PATCH] Redo friend request handling --- Signal/src/Loki/FriendRequestView.swift | 9 +++++- .../ConversationView/Cells/OWSMessageCell.m | 22 ++++----------- .../ConversationViewController.m | 9 +++--- .../translations/en.lproj/Localizable.strings | 3 +- SignalMessaging/utils/ThreadUtil.m | 4 +-- SignalServiceKit/src/Contacts/TSThread.h | 8 ++++-- SignalServiceKit/src/Contacts/TSThread.m | 9 +++--- .../src/Messages/Interactions/TSMessage.h | 1 + .../src/Messages/Interactions/TSMessage.m | 2 ++ .../src/Messages/OWSMessageManager.m | 9 ++++++ .../src/Messages/OWSMessageSender.m | 28 +++++++++++++------ 11 files changed, 64 insertions(+), 40 deletions(-) diff --git a/Signal/src/Loki/FriendRequestView.swift b/Signal/src/Loki/FriendRequestView.swift index f75ad58ad..2c6e9386c 100644 --- a/Signal/src/Loki/FriendRequestView.swift +++ b/Signal/src/Loki/FriendRequestView.swift @@ -4,6 +4,11 @@ @objc weak var delegate: FriendRequestViewDelegate? private let kind: Kind + private var didAcceptRequest: Bool { + guard let message = message as? TSIncomingMessage else { preconditionFailure() } + return message.thread.friendRequestStatus == .friends + } + private var didDeclineRequest: Bool { guard let message = message as? TSIncomingMessage else { preconditionFailure() } return message.thread.friendRequestStatus == .none @@ -81,7 +86,9 @@ guard let message = message as? TSIncomingMessage else { preconditionFailure() } buttonStackView.isHidden = didDeclineRequest let text: String = { - if didDeclineRequest { + 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) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m index 3ebc8ae68..8d725c715 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m @@ -124,18 +124,6 @@ NS_ASSUME_NONNULL_BEGIN return outgoingMessage.messageState == TSOutgoingMessageStateFailed; } -- (TSThreadFriendRequestStatus)friendRequestStatus -{ - return [self.message.thread getFriendRequestStatus]; -} - -- (BOOL)isFriendRequest -{ - TSThreadFriendRequestStatus friendRequestStatus = self.friendRequestStatus; - return friendRequestStatus == TSThreadFriendRequestStatusPendingSend || friendRequestStatus == TSThreadFriendRequestStatusRequestSent - || friendRequestStatus == TSThreadFriendRequestStatusRequestReceived; -} - #pragma mark - Load - (void)loadForDisplay @@ -218,10 +206,10 @@ NS_ASSUME_NONNULL_BEGIN } } - if (self.isFriendRequest) { - // At this point, self.friendRequestStatus should be either TSThreadFriendRequestStatusRequestReceived, + if (self.message.isFriendRequest) { + // At this point, self.message.thread.friendRequestStatus should be either TSThreadFriendRequestStatusRequestReceived, // TSThreadFriendRequestStatusPendingSend or TSThreadFriendRequestStatusRequestSent - NSString *rawKind = self.friendRequestStatus == TSThreadFriendRequestStatusRequestReceived ? @"incoming" : @"outgoing"; + NSString *rawKind = self.message.interactionType == OWSInteractionType_IncomingMessage ? @"incoming" : @"outgoing"; self.friendRequestView = [[FriendRequestView alloc] initWithRawKind:rawKind]; self.friendRequestView.message = self.message; self.friendRequestView.delegate = self.friendRequestViewDelegate; @@ -372,7 +360,7 @@ NS_ASSUME_NONNULL_BEGIN cellSize.width += self.sendFailureBadgeSize + self.sendFailureBadgeSpacing; } - if (self.isFriendRequest) { + if (self.message.isFriendRequest) { cellSize.height += [FriendRequestView calculateHeightWithMessage:self.message conversationStyle:self.conversationStyle]; } @@ -454,7 +442,7 @@ NS_ASSUME_NONNULL_BEGIN { OWSAssertDebug(self.delegate); - if (self.isFriendRequest) { + if (self.message.isFriendRequest) { return; } diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 4e557de76..48a3a888d 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -1587,11 +1587,9 @@ typedef enum : NSUInteger { #pragma mark - Updating - (void)updateInputToolbar { - TSThreadFriendRequestStatus friendRequestStatus = [self.thread getFriendRequestStatus]; - BOOL isFriendRequestPending = friendRequestStatus == TSThreadFriendRequestStatusPendingSend || friendRequestStatus == TSThreadFriendRequestStatusRequestSent - || friendRequestStatus == TSThreadFriendRequestStatusRequestReceived; - [self.inputToolbar setUserInteractionEnabled:!isFriendRequestPending]; - NSString *placeholderText = isFriendRequestPending ? NSLocalizedString(@"Pending Friend Request...", "") : NSLocalizedString(@"New Message", ""); + BOOL hasPendingFriendRequest = self.thread.hasPendingFriendRequest; + [self.inputToolbar setUserInteractionEnabled:!hasPendingFriendRequest]; + NSString *placeholderText = hasPendingFriendRequest ? NSLocalizedString(@"Pending Friend Request...", "") : NSLocalizedString(@"New Message", ""); [self.inputToolbar setPlaceholderText:placeholderText]; } @@ -4306,6 +4304,7 @@ typedef enum : NSUInteger { { // Reset friend request status self.thread.friendRequestStatus = TSThreadFriendRequestStatusNone; + [self.thread save]; // Delete prekeys NSString *contactID = self.thread.recipientIdentifiers.firstObject; OWSPrimaryStorage *primaryStorage = SSKEnvironment.shared.primaryStorage; diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 008744f3c..5095e3504 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -2577,4 +2577,5 @@ "Pending Friend Request..." = "Pending Friend Request..."; "New Message" = "New Message"; "Session" = "Session"; -"You've declined %@'s friend request" = "You've declined %@'s friend request" +"You've declined %@'s friend request" = "You've declined %@'s friend request"; +"You've accepted %@'s friend request" = "You've accepted %@'s friend request"; diff --git a/SignalMessaging/utils/ThreadUtil.m b/SignalMessaging/utils/ThreadUtil.m index 1299bcf1c..e9f030b4d 100644 --- a/SignalMessaging/utils/ThreadUtil.m +++ b/SignalMessaging/utils/ThreadUtil.m @@ -185,8 +185,8 @@ typedef void (^BuildOutgoingMessageCompletionBlock)(TSOutgoingMessage *savedMess BOOL isVoiceMessage = (attachments.count == 1 && attachments.lastObject.isVoiceMessage); // 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 - TSThreadFriendRequestStatus friendRequestStatus = [thread getFriendRequestStatusWithTransaction:transaction]; + // If we're friends then the assumption is that we have the other user's prekey bundle + TSThreadFriendRequestStatus friendRequestStatus = thread.friendRequestStatus; BOOL isFriend = friendRequestStatus == TSThreadFriendRequestStatusFriends; NSString *messageClassAsString = isFriend ? @"TSOutgoingMessage" : @"OWSFriendRequestMessage"; Class messageClass = NSClassFromString(messageClassAsString); diff --git a/SignalServiceKit/src/Contacts/TSThread.h b/SignalServiceKit/src/Contacts/TSThread.h index 4716f98d5..ae8ea7de3 100644 --- a/SignalServiceKit/src/Contacts/TSThread.h +++ b/SignalServiceKit/src/Contacts/TSThread.h @@ -53,7 +53,7 @@ typedef NS_ENUM(NSInteger, TSThreadFriendRequestStatus) { @property (nonatomic) BOOL shouldThreadBeVisible; @property (nonatomic, readonly) NSDate *creationDate; @property (nonatomic, readonly) BOOL isArchivedByLegacyTimestampForSorting; -@property (nonatomic, readonly) TSThreadFriendRequestStatus friendRequestStatus; +@property (nonatomic) TSThreadFriendRequestStatus friendRequestStatus; /** * Whether the object is a group thread or not. @@ -187,7 +187,11 @@ typedef NS_ENUM(NSInteger, TSThreadFriendRequestStatus) { - (void)updateWithMutedUntilDate:(NSDate *)mutedUntilDate transaction:(YapDatabaseReadWriteTransaction *)transaction; -@end +#pragma mark - Loki Friend Request Handling + +/// Shorthand for checking that `friendRequestStatus` is `TSThreadFriendRequestStatusPendingSend`, `TSThreadFriendRequestStatusRequestSent` or `TSThreadFriendRequestStatusRequestReceived`. +- (BOOL)hasPendingFriendRequest; +@end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Contacts/TSThread.m b/SignalServiceKit/src/Contacts/TSThread.m index e05270fe4..25748186d 100644 --- a/SignalServiceKit/src/Contacts/TSThread.m +++ b/SignalServiceKit/src/Contacts/TSThread.m @@ -696,11 +696,12 @@ ConversationColorName const kConversationColorName_Default = ConversationColorNa }]; } -- (void)setFriendRequestStatus:(TSThreadFriendRequestStatus)friendRequestStatus +#pragma mark - Loki Friend Request Handling + +- (BOOL)hasPendingFriendRequest { - [self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - _friendRequestStatus = friendRequestStatus; - }]; + return self.friendRequestStatus == TSThreadFriendRequestStatusPendingSend || self.friendRequestStatus == TSThreadFriendRequestStatusRequestSent + || self.friendRequestStatus == TSThreadFriendRequestStatusRequestReceived; } @end diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage.h b/SignalServiceKit/src/Messages/Interactions/TSMessage.h index 9f836b04c..803dc181d 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage.h @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly, nullable) TSQuotedMessage *quotedMessage; @property (nonatomic, readonly, nullable) OWSContact *contactShare; @property (nonatomic, readonly, nullable) OWSLinkPreview *linkPreview; +@property (nonatomic) BOOL isFriendRequest; - (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE; diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage.m b/SignalServiceKit/src/Messages/Interactions/TSMessage.m index ddcbca82c..14af436cf 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage.m @@ -438,6 +438,8 @@ static const NSUInteger OWSMessageSchemaVersion = 4; }]; } +#pragma mark - Loki Friend Request Handling + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 19ca5ef83..85c9d15a9 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -1442,6 +1442,15 @@ NS_ASSUME_NONNULL_BEGIN return; } + if (envelope.type == SSKProtoEnvelopeTypeFriendRequest) { + thread.friendRequestStatus = TSThreadFriendRequestStatusRequestReceived; + [thread saveWithTransaction:transaction]; + incomingMessage.isFriendRequest = YES; + } else if (incomingMessage.body == @"") { // Assumed to be an accept friend request message + thread.friendRequestStatus = TSThreadFriendRequestStatusFriends; + [thread saveWithTransaction:transaction]; + } + [incomingMessage saveWithTransaction:transaction]; // Any messages sent from the current user - from this device or another - should be automatically marked as read. diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m index cdd9c9043..f0a87597b 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.m +++ b/SignalServiceKit/src/Messages/OWSMessageSender.m @@ -1103,31 +1103,43 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; return messageSend.failure(error); } - // Update the thread's friend request status if needed - if (messageType == TSFriendRequestMessageType) { - message.thread.friendRequestStatus = TSThreadFriendRequestStatusPendingSend; - } - // Update the state to show that proof of work is being calculated [self setIsCalculatingProofOfWorkForMessage:messageSend]; // Convert the message to a Loki message and send it using the Loki messaging API NSDictionary *signalMessage = deviceMessages.firstObject; + // Update the thread's friend request status if needed + NSInteger *messageType = ((NSNumber *)signalMessage[@"type"]).integerValue; + if (messageType == TSFriendRequestMessageType) { + message.thread.friendRequestStatus = TSThreadFriendRequestStatusPendingSend; + [message.thread save]; + message.isFriendRequest = YES; + [message save]; + } BOOL isPoWRequired = YES; // TODO: Base on message type [[LokiAPI objc_sendSignalMessage:signalMessage to:recipient.recipientId timestamp:message.timestamp requiringPoW:isPoWRequired] .thenOn(OWSDispatch.sendingQueue, ^(id result) { - // Update the thread's friend request status if needed if (messageType == TSFriendRequestMessageType) { - message.thread.friendRequestStatus = TSThreadFriendRequestStatusSent; + message.thread.friendRequestStatus = TSThreadFriendRequestStatusRequestSent; + [message.thread save]; + } else if (message.body == @"") { // Assumed to be an accept friend request message + message.thread.friendRequestStatus = TSThreadFriendRequestStatusFriends; + [message.thread save]; } - + // Invoke the completion handler [self messageSendDidSucceed:messageSend deviceMessages:deviceMessages wasSentByUD:false wasSentByWebsocket:false]; }) .catchOn(OWSDispatch.sendingQueue, ^(NSError *error) { + // Update the thread's friend request status if needed + if (messageType == TSFriendRequestMessageType) { + message.thread.friendRequestStatus = TSThreadFriendRequestStatusNone; + [message.thread save]; + } + // Handle the error NSUInteger statusCode = 0; NSData *_Nullable responseData = nil; if ([error.domain isEqualToString:TSNetworkManagerErrorDomain]) {