From 4becd4397308085938bd80ba923645f6748c284d Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 17 May 2017 10:02:46 -0400 Subject: [PATCH 1/2] "Bob's SN changed" displayed in every group containing Bob // FREEBIE --- src/Contacts/Threads/TSGroupThread.h | 8 +++-- src/Contacts/Threads/TSGroupThread.m | 33 +++++++++++++++++-- .../TSStorageManager+IdentityKeyStore.m | 14 +++++++- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/Contacts/Threads/TSGroupThread.h b/src/Contacts/Threads/TSGroupThread.h index 56b6d5a83..39aa892b3 100644 --- a/src/Contacts/Threads/TSGroupThread.h +++ b/src/Contacts/Threads/TSGroupThread.h @@ -1,5 +1,6 @@ -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "TSGroupModel.h" #import "TSThread.h" @@ -22,6 +23,9 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)threadIdFromGroupId:(NSData *)groupId; +// all group threads conrtaining recipient as a member ++ (NSArray *)groupThreadsWithRecipientId:(NSString *)recipientId; + - (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream; @end diff --git a/src/Contacts/Threads/TSGroupThread.m b/src/Contacts/Threads/TSGroupThread.m index 327ce7f0f..b655ef169 100644 --- a/src/Contacts/Threads/TSGroupThread.m +++ b/src/Contacts/Threads/TSGroupThread.m @@ -1,5 +1,6 @@ -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "TSGroupThread.h" #import "NSData+Base64.h" @@ -85,6 +86,34 @@ NS_ASSUME_NONNULL_BEGIN return [NSData dataFromBase64String:[threadId substringWithRange:NSMakeRange(1, threadId.length - 1)]]; } + +// Group and Contact threads share a collection, this is a convenient way to enumerate *just* the group threads ++ (void)enumerateGroupThreadsUsingBlock:(void (^)(TSGroupThread *groupThread, BOOL *stop))block +{ + [self enumerateCollectionObjectsUsingBlock:^(id obj, BOOL *stop) { + if ([obj isKindOfClass:[TSGroupThread class]]) { + block((TSGroupThread *)obj, stop); + } + }]; +} + +// @returns all threads to which the recipient is a member. +// +// @note If this becomes a hotspot we can extract into a YapDB View. +// As is, the number of groups should be small (dozens, *maybe* hundreds), and we only enumerate them upon SN changes. ++ (NSArray *)groupThreadsWithRecipientId:(NSString *)recipientId +{ + NSMutableArray *groupThreads = [NSMutableArray new]; + + [self enumerateGroupThreadsUsingBlock:^(TSGroupThread *_Nonnull groupThread, BOOL *_Nonnull stop) { + if ([groupThread.groupModel.groupMemberIds containsObject:recipientId]) { + [groupThreads addObject:groupThread]; + } + }]; + + return [groupThreads copy]; +} + - (BOOL)isGroupThread { return true; diff --git a/src/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m b/src/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m index 95122b2dd..5cc32417d 100644 --- a/src/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m +++ b/src/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m @@ -6,6 +6,7 @@ #import "TSAccountManager.h" #import "TSContactThread.h" #import "TSErrorMessage.h" +#import "TSGroupThread.h" #import "TSPrivacyPreferences.h" #import "TSStorageManager+IdentityKeyStore.h" #import "TSStorageManager+SessionStore.h" @@ -83,10 +84,21 @@ - (void)createIdentityChangeInfoMessageForRecipientId:(NSString *)recipientId { + // TODO But should they be marked as dirty/play an alert? Probably not. + + UInt64 nowTimestamp = [NSDate ows_millisecondTimeStamp]; + TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:recipientId]; - [[[TSErrorMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + [[[TSErrorMessage alloc] initWithTimestamp:nowTimestamp inThread:contactThread failedMessageType:TSErrorMessageNonBlockingIdentityChange] save]; + + for (TSGroupThread *groupThread in [TSGroupThread groupThreadsWithRecipientId:recipientId]) { + [[[TSErrorMessage alloc] initWithTimestamp:nowTimestamp + inThread:groupThread + failedMessageType:TSErrorMessageNonBlockingIdentityChange] save]; + } } + @end From fcbfde3874abd9ae10a6d7771cff5c6ef0848074 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 17 May 2017 10:35:04 -0400 Subject: [PATCH 2/2] nonblocking SN change notifications don't percolate group threads to the top unless there is a message in that thread. Otherwise the user is overwhelmed by a bunch of group threads with redundant notifications. The notifications will be there if the user later enters the threads. The affect is that only the thread with the relevant message will pop to the top. // FREEBIE --- src/Contacts/TSThread.m | 13 +++++++++++++ src/Contacts/Threads/TSGroupThread.h | 2 +- .../TSStorageManager+IdentityKeyStore.m | 2 -- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Contacts/TSThread.m b/src/Contacts/TSThread.m index a056d098f..ccdfc564c 100644 --- a/src/Contacts/TSThread.m +++ b/src/Contacts/TSThread.m @@ -251,6 +251,19 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateWithLastMessage:(TSInteraction *)lastMessage transaction:(YapDatabaseReadWriteTransaction *)transaction { NSDate *lastMessageDate = [lastMessage receiptDateForSorting]; + if ([lastMessage isKindOfClass:[TSErrorMessage class]]) { + TSErrorMessage *errorMessage = (TSErrorMessage *)lastMessage; + if (errorMessage.errorType == TSErrorMessageNonBlockingIdentityChange) { + // Otherwise all group threads with the recipient will percolate to the top of the inbox, even though + // there was no meaningful interaction. + DDLogDebug(@"%@ not updating lastMessage for thread:%@ nonblocking identity change: %@", + self.tag, + self, + errorMessage.debugDescription); + return; + } + } + if (!_lastMessageDate || [lastMessageDate timeIntervalSinceDate:self.lastMessageDate] > 0) { _lastMessageDate = lastMessageDate; diff --git a/src/Contacts/Threads/TSGroupThread.h b/src/Contacts/Threads/TSGroupThread.h index 39aa892b3..68a5a2004 100644 --- a/src/Contacts/Threads/TSGroupThread.h +++ b/src/Contacts/Threads/TSGroupThread.h @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)threadIdFromGroupId:(NSData *)groupId; -// all group threads conrtaining recipient as a member +// all group threads containing recipient as a member + (NSArray *)groupThreadsWithRecipientId:(NSString *)recipientId; - (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream; diff --git a/src/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m b/src/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m index 5cc32417d..66b9bcf62 100644 --- a/src/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m +++ b/src/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m @@ -84,8 +84,6 @@ - (void)createIdentityChangeInfoMessageForRecipientId:(NSString *)recipientId { - // TODO But should they be marked as dirty/play an alert? Probably not. - UInt64 nowTimestamp = [NSDate ows_millisecondTimeStamp]; TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:recipientId];