Ensure friend request uniqueness in a thread

This commit is contained in:
Niels Andriesse 2019-11-06 16:39:26 +11:00
parent ca1a419a45
commit 8281b23ec6
3 changed files with 37 additions and 2 deletions

View File

@ -213,6 +213,7 @@ NS_ASSUME_NONNULL_BEGIN
}
}
// Loki: Attach the friend request view if needed
if ([self shouldShowFriendRequestUIForMessage:self.message]) {
self.friendRequestView = [[LKFriendRequestView alloc] initWithMessage:self.message];
self.friendRequestView.delegate = self.friendRequestViewDelegate;
@ -298,6 +299,7 @@ NS_ASSUME_NONNULL_BEGIN
self.avatarView.image = authorAvatarImage;
[self.contentView addSubview:self.avatarView];
// Loki: Show the moderator icon if needed
if (self.viewItem.isGroupThread && !self.viewItem.isRSSFeed) {
__block LKPublicChat *publicChat;
[OWSPrimaryStorage.sharedManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
@ -383,6 +385,7 @@ NS_ASSUME_NONNULL_BEGIN
cellSize.width += self.sendFailureBadgeSize + self.sendFailureBadgeSpacing;
}
// Loki: Include the friend request view if needed
if ([self shouldShowFriendRequestUIForMessage:self.message]) {
cellSize.height += [LKFriendRequestView calculateHeightWithMessage:self.message conversationStyle:self.conversationStyle];
}
@ -542,7 +545,8 @@ NS_ASSUME_NONNULL_BEGIN
NSString *senderID = ((TSIncomingMessage *)message).authorId;
NSMutableSet<TSContactThread *> *threads = [NSMutableSet new];
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSSet<LKDeviceLink *> *deviceLinks = [LKDatabaseUtilities getDeviceLinksFor:senderID in:transaction];
NSString *masterHexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:senderID in:transaction] ?: senderID;
NSSet<LKDeviceLink *> *deviceLinks = [LKDatabaseUtilities getDeviceLinksFor:masterHexEncodedPublicKey in:transaction];
for (LKDeviceLink *deviceLink in deviceLinks) {
[threads addObject:[TSContactThread getThreadWithContactId:deviceLink.master.hexEncodedPublicKey transaction:transaction]];
[threads addObject:[TSContactThread getThreadWithContactId:deviceLink.slave.hexEncodedPublicKey transaction:transaction]];

View File

@ -102,6 +102,10 @@ typedef NS_ENUM(NSInteger, LKThreadFriendRequestStatus) {
#pragma mark Interactions
- (void)enumerateInteractionsWithTransaction:(YapDatabaseReadWriteTransaction *)transaction usingBlock:(void (^)(TSInteraction *interaction, YapDatabaseReadTransaction *transaction))block;
- (void)enumerateInteractionsUsingBlock:(void (^)(TSInteraction *interaction))block;
/**
* @return The number of interactions in this thread.
*/

View File

@ -1535,7 +1535,12 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)handleFriendRequestMessageIfNeededWithEnvelope:(SSKProtoEnvelope *)envelope data:(SSKProtoDataMessage *)data message:(TSIncomingMessage *)message thread:(TSThread *)thread transaction:(YapDatabaseReadWriteTransaction *)transaction {
if (envelope.isGroupChatMessage || envelope.type != SSKProtoEnvelopeTypeFriendRequest) return;
if (envelope.isGroupChatMessage) {
return NSLog(@"[Loki] Ignoring friend request in group chat.", @"");
}
if (envelope.type != SSKProtoEnvelopeTypeFriendRequest) {
return NSLog(@"[Loki] handleFriendRequestMessageIfNeededWithEnvelope:data:message:thread:transaction was called with an envelope that isn't of type SSKProtoEnvelopeTypeFriendRequest.");
}
if (thread.hasCurrentUserSentFriendRequest) {
// This can happen if Alice sent Bob a friend request, Bob declined, but then Bob changed his
// mind and sent a friend request to Alice. In this case we want Alice to auto-accept the request
@ -1563,6 +1568,28 @@ NS_ASSUME_NONNULL_BEGIN
// request. Alice's thread's friend request status is reset to
// LKThreadFriendRequestStatusRequestReceived.
[thread saveFriendRequestStatus:LKThreadFriendRequestStatusRequestReceived withTransaction:transaction];
// Except for the message.friendRequestStatus = LKMessageFriendRequestStatusPending line below, all of this is to ensure that
// there's only ever one message with status LKMessageFriendRequestStatusPending in a thread (where a thread is the combination
// of all threads belonging to the linked devices of a user).
NSString *senderID = ((TSIncomingMessage *)message).authorId;
NSMutableSet<TSContactThread *> *threads = [NSMutableSet new];
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSString *masterHexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:senderID in:transaction] ?: senderID;
NSSet<LKDeviceLink *> *deviceLinks = [LKDatabaseUtilities getDeviceLinksFor:masterHexEncodedPublicKey in:transaction];
for (LKDeviceLink *deviceLink in deviceLinks) {
[threads addObject:[TSContactThread getThreadWithContactId:deviceLink.master.hexEncodedPublicKey transaction:transaction]];
[threads addObject:[TSContactThread getThreadWithContactId:deviceLink.slave.hexEncodedPublicKey transaction:transaction]];
}
}];
for (TSContactThread *thread in threads) {
[thread enumerateInteractionsWithTransaction:transaction usingBlock:^(TSInteraction *interaction, YapDatabaseReadTransaction *transaction) {
if (![interaction isKindOfClass:TSIncomingMessage.class]) { return; }
TSIncomingMessage *message = (TSIncomingMessage *)interaction;
if (message.friendRequestStatus != LKMessageFriendRequestStatusNone) {
[message saveFriendRequestStatus:LKMessageFriendRequestStatusNone withTransaction:transaction];
}
}];
}
message.friendRequestStatus = LKMessageFriendRequestStatusPending; // Don't save yet. This is done in finalizeIncomingMessage:thread:masterThread:envelope:transaction.
} else {
// This can happen if Alice and Bob have a session, Bob deletes his app, restores from seed, and then sends a friend request to Alice again.