From 1fb1b5bbe27c6dd5b4657af743ac342327b3c229 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Sat, 21 Apr 2018 10:25:13 -0400 Subject: [PATCH] WIP unjank home screen verify `description` isn't used elsewhere (notifications? conversation view?) Probably want to remove overzealous asserts for now, but would be good to work towards leaving them enabled. // FREEBIE --- .../ViewControllers/HomeView/HomeViewCell.h | 4 +- .../ViewControllers/HomeView/HomeViewCell.m | 9 +++- .../HomeView/HomeViewController.m | 33 ++++++++++--- SignalServiceKit/src/Contacts/TSThread.h | 2 +- SignalServiceKit/src/Contacts/TSThread.m | 47 ++++++++++--------- ...sappearingConfigurationUpdateInfoMessage.m | 2 +- .../Messages/Interactions/TSErrorMessage.m | 3 +- .../src/Messages/Interactions/TSInfoMessage.m | 3 +- .../src/Messages/Interactions/TSInteraction.h | 6 +++ .../src/Messages/Interactions/TSInteraction.m | 1 + .../src/Messages/Interactions/TSMessage.h | 3 +- .../src/Messages/Interactions/TSMessage.m | 9 ++-- SignalServiceKit/src/Messages/TSCall.m | 16 ++++++- .../src/Storage/TSYapDatabaseObject.m | 5 +- 14 files changed, 96 insertions(+), 47 deletions(-) diff --git a/Signal/src/ViewControllers/HomeView/HomeViewCell.h b/Signal/src/ViewControllers/HomeView/HomeViewCell.h index 4e51d15fc..f5450b05c 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewCell.h +++ b/Signal/src/ViewControllers/HomeView/HomeViewCell.h @@ -6,6 +6,7 @@ NS_ASSUME_NONNULL_BEGIN @class OWSContactsManager; @class TSThread; +@class YapDatabaseReadTransaction; @interface HomeViewCell : UITableViewCell @@ -15,7 +16,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)configureWithThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager - blockedPhoneNumberSet:(NSSet *)blockedPhoneNumberSet; + blockedPhoneNumberSet:(NSSet *)blockedPhoneNumberSet + transaction:(YapDatabaseReadTransaction *)transaction; @end diff --git a/Signal/src/ViewControllers/HomeView/HomeViewCell.m b/Signal/src/ViewControllers/HomeView/HomeViewCell.m index 7281b65b2..4573a734f 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewCell.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewCell.m @@ -146,11 +146,13 @@ NS_ASSUME_NONNULL_BEGIN - (void)configureWithThread:(TSThread *)thread contactsManager:(OWSContactsManager *)contactsManager blockedPhoneNumberSet:(NSSet *)blockedPhoneNumberSet + transaction:(YapDatabaseReadTransaction *)transaction { OWSAssertIsOnMainThread(); OWSAssert(thread); OWSAssert(contactsManager); OWSAssert(blockedPhoneNumberSet); + OWSAssert(transaction); self.thread = thread; self.contactsManager = contactsManager; @@ -171,7 +173,9 @@ NS_ASSUME_NONNULL_BEGIN // changes to the dynamic type settings are reflected. self.snippetLabel.font = [self snippetFont]; self.snippetLabel.attributedText = - [self attributedSnippetForThread:thread blockedPhoneNumberSet:blockedPhoneNumberSet]; + [self attributedSnippetForThread:thread + blockedPhoneNumberSet:blockedPhoneNumberSet + transaction:transaction]; self.dateTimeLabel.text = [self stringForDate:thread.lastMessageDate]; @@ -253,6 +257,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSAttributedString *)attributedSnippetForThread:(TSThread *)thread blockedPhoneNumberSet:(NSSet *)blockedPhoneNumberSet + transaction:(YapDatabaseReadTransaction *)transaction { OWSAssert(thread); @@ -285,7 +290,7 @@ NS_ASSUME_NONNULL_BEGIN : [UIColor lightGrayColor]), }]]; } - NSString *displayableText = thread.lastMessageLabel.filterStringForDisplay; + NSString *displayableText = [thread lastMessageLabelWithTransaction:transaction]; if (displayableText) { [snippetText appendAttributedString:[[NSAttributedString alloc] initWithString:displayableText diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index fec465118..61d58c6a7 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -395,7 +395,11 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - if ([TSThread numberOfKeysInCollection] > 0) { + __block BOOL hasAnyMessages; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) { + hasAnyMessages = [self hasAnyMessagesWithTransaction:transaction]; + }]; + if (hasAnyMessages) { [self.contactsManager requestSystemContactsOnceWithCompletion:^(NSError *_Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ [self updateReminderViews]; @@ -490,7 +494,11 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; // If the user hasn't already granted contact access // we don't want to request until they receive a message. - if ([TSThread numberOfKeysInCollection] > 0) { + __block BOOL hasAnyMessages; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) { + hasAnyMessages = [self hasAnyMessagesWithTransaction:transaction]; + }]; + if (hasAnyMessages) { [self.contactsManager requestSystemContactsOnce]; } } @@ -506,11 +514,21 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; self.isAppInBackground = YES; } +- (BOOL)hasAnyMessagesWithTransaction:(YapDatabaseReadTransaction *)transaction +{ + return [TSThread numberOfKeysInCollectionWithTransaction:transaction] > 0; +} + - (void)applicationDidBecomeActive:(NSNotification *)notification { // It's possible a thread was created while we where in the background. But since we don't honor contact // requests unless the app is in the foregrond, we must check again here upon becoming active. - if ([TSThread numberOfKeysInCollection] > 0) { + __block BOOL hasAnyMessages; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) { + hasAnyMessages = [self hasAnyMessagesWithTransaction:transaction]; + }]; + + if (hasAnyMessages) { [self.contactsManager requestSystemContactsOnceWithCompletion:^(NSError *_Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ [self updateReminderViews]; @@ -584,9 +602,12 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; TSThread *thread = [self threadForIndexPath:indexPath]; - [cell configureWithThread:thread - contactsManager:self.contactsManager - blockedPhoneNumberSet:self.blockedPhoneNumberSet]; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) { + [cell configureWithThread:thread + contactsManager:self.contactsManager + blockedPhoneNumberSet:self.blockedPhoneNumberSet + transaction:transaction]; + }]; if ((unsigned long)indexPath.row == [self.threadMappings numberOfItemsInSection:0] - 1) { cell.separatorInset = UIEdgeInsetsMake(0.f, cell.bounds.size.width, 0.f, 0.f); diff --git a/SignalServiceKit/src/Contacts/TSThread.h b/SignalServiceKit/src/Contacts/TSThread.h index 8ed22a61f..ca952d0d8 100644 --- a/SignalServiceKit/src/Contacts/TSThread.h +++ b/SignalServiceKit/src/Contacts/TSThread.h @@ -90,7 +90,7 @@ NS_ASSUME_NONNULL_BEGIN * * @return Thread preview string. */ -- (NSString *)lastMessageLabel; +- (NSString *)lastMessageLabelWithTransaction:(YapDatabaseReadTransaction *)transaction; /** * Updates the thread's caches of the latest interaction. diff --git a/SignalServiceKit/src/Contacts/TSThread.m b/SignalServiceKit/src/Contacts/TSThread.m index f9cc5fe4c..aa5f60cc0 100644 --- a/SignalServiceKit/src/Contacts/TSThread.m +++ b/SignalServiceKit/src/Contacts/TSThread.m @@ -4,6 +4,7 @@ #import "TSThread.h" #import "NSDate+OWS.h" +#import "NSString+SSK.h" #import "OWSPrimaryStorage.h" #import "OWSReadTracking.h" #import "TSDatabaseView.h" @@ -246,26 +247,24 @@ NS_ASSUME_NONNULL_BEGIN return last; } -- (TSInteraction *)lastInteractionForInbox +- (TSInteraction *)lastInteractionForInboxWithTransaction:(YapDatabaseReadTransaction *)transaction { __block TSInteraction *last = nil; - [OWSPrimaryStorage.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - [[transaction ext:TSMessageDatabaseViewExtensionName] - enumerateRowsInGroup:self.uniqueId - withOptions:NSEnumerationReverse - usingBlock:^( - NSString *collection, NSString *key, id object, id metadata, NSUInteger index, BOOL *stop) { - - OWSAssert([object isKindOfClass:[TSInteraction class]]); - - TSInteraction *interaction = (TSInteraction *)object; - - if ([TSThread shouldInteractionAppearInInbox:interaction]) { - last = interaction; - *stop = YES; - } - }]; - }]; + [[transaction ext:TSMessageDatabaseViewExtensionName] + enumerateRowsInGroup:self.uniqueId + withOptions:NSEnumerationReverse + usingBlock:^( + NSString *collection, NSString *key, id object, id metadata, NSUInteger index, BOOL *stop) { + + OWSAssert([object isKindOfClass:[TSInteraction class]]); + + TSInteraction *interaction = (TSInteraction *)object; + + if ([TSThread shouldInteractionAppearInInbox:interaction]) { + last = interaction; + *stop = YES; + } + }]; return last; } @@ -277,12 +276,14 @@ NS_ASSUME_NONNULL_BEGIN } } -- (NSString *)lastMessageLabel { - TSInteraction *interaction = self.lastInteractionForInbox; - if (interaction == nil) { - return @""; +- (NSString *)lastMessageLabelWithTransaction:(YapDatabaseReadTransaction *)transaction +{ + TSInteraction *interaction = [self lastInteractionForInboxWithTransaction:transaction]; + if ([interaction conformsToProtocol:@protocol(OWSPreviewText)]) { + id previewable = (id)interaction; + return [previewable previewTextWithTransaction:transaction].filterStringForDisplay; } else { - return interaction.description; + return @""; } } diff --git a/SignalServiceKit/src/Messages/Interactions/OWSDisappearingConfigurationUpdateInfoMessage.m b/SignalServiceKit/src/Messages/Interactions/OWSDisappearingConfigurationUpdateInfoMessage.m index 1391aa271..8ae97209d 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSDisappearingConfigurationUpdateInfoMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/OWSDisappearingConfigurationUpdateInfoMessage.m @@ -56,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN return NO; } -- (NSString *)description +-(NSString *)previewTextWithTransaction:(YapDatabaseReadTransaction *)transaction { if (self.createdByRemoteName) { if (self.configurationIsEnabled && self.configurationDurationSeconds > 0) { diff --git a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m index 363605a73..1f130877a 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSErrorMessage.m @@ -97,7 +97,8 @@ NSUInteger TSErrorMessageSchemaVersion = 1; return OWSInteractionType_Error; } -- (NSString *)description { +- (NSString *)previewTextWithTransaction:(YapDatabaseReadTransaction *)transaction +{ switch (_errorType) { case TSErrorMessageNoSession: return NSLocalizedString(@"ERROR_MESSAGE_NO_SESSION", @""); diff --git a/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.m b/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.m index 10abeb18b..5e19dd446 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSInfoMessage.m @@ -91,7 +91,8 @@ NSUInteger TSInfoMessageSchemaVersion = 1; return OWSInteractionType_Info; } -- (NSString *)description { +- (NSString *)previewTextWithTransaction:(YapDatabaseReadTransaction *)transaction +{ switch (_messageType) { case TSInfoMessageTypeSessionDidEnd: return NSLocalizedString(@"SECURE_SESSION_RESET", nil); diff --git a/SignalServiceKit/src/Messages/Interactions/TSInteraction.h b/SignalServiceKit/src/Messages/Interactions/TSInteraction.h index 67044af1f..a6088803d 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInteraction.h +++ b/SignalServiceKit/src/Messages/Interactions/TSInteraction.h @@ -19,6 +19,12 @@ typedef NS_ENUM(NSInteger, OWSInteractionType) { OWSInteractionType_Offer, }; +@protocol OWSPreviewText + +- (NSString *)previewTextWithTransaction:(YapDatabaseReadTransaction *)transaction; + +@end + @interface TSInteraction : TSYapDatabaseObject - (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread; diff --git a/SignalServiceKit/src/Messages/Interactions/TSInteraction.m b/SignalServiceKit/src/Messages/Interactions/TSInteraction.m index b5319d9d0..fc796947e 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInteraction.m +++ b/SignalServiceKit/src/Messages/Interactions/TSInteraction.m @@ -128,6 +128,7 @@ NS_ASSUME_NONNULL_BEGIN } - (NSString *)description { + OWSFail(@"Abstract Method"); return @"Interaction description"; } diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage.h b/SignalServiceKit/src/Messages/Interactions/TSMessage.h index f08f13acf..66c359804 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage.h @@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN @class TSQuotedMessage; @class YapDatabaseReadWriteTransaction; -@interface TSMessage : TSInteraction +@interface TSMessage : TSInteraction @property (nonatomic, readonly) NSMutableArray *attachmentIds; @property (nonatomic, readonly, nullable) NSString *body; @@ -39,7 +39,6 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)hasAttachments; - (nullable TSAttachment *)attachmentWithTransaction:(YapDatabaseReadTransaction *)transaction; -- (NSString *)previewTextWithTransaction:(YapDatabaseReadTransaction *)transaction; - (void)setQuotedMessageThumbnailAttachmentStream:(TSAttachmentStream *)attachmentStream; - (BOOL)shouldStartExpireTimer; diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage.m b/SignalServiceKit/src/Messages/Interactions/TSMessage.m index 558af4613..da06a35ab 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage.m @@ -265,14 +265,11 @@ static const NSUInteger OWSMessageSchemaVersion = 4; } } -// TODO deprecate this and implement something like previewTextWithTransaction: for all TSInteractions - (NSString *)description { - __block NSString *result; - [self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - result = [self previewTextWithTransaction:transaction]; - }]; - return result; + // TODO verify this isn't exposed in the UI + OWSFail(@"%@ in %s verify this isn't being used anywhere except logging.", self.logTag, __PRETTY_FUNCTION__); + return [super description]; } - (void)removeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction diff --git a/SignalServiceKit/src/Messages/TSCall.m b/SignalServiceKit/src/Messages/TSCall.m index 7b37efb3a..cc49de57a 100644 --- a/SignalServiceKit/src/Messages/TSCall.m +++ b/SignalServiceKit/src/Messages/TSCall.m @@ -67,7 +67,13 @@ NSUInteger TSCallCurrentSchemaVersion = 1; return OWSInteractionType_Call; } -- (NSString *)description { +- (NSString *)previewTextWithTransaction:(YapDatabaseReadTransaction *)transaction +{ + return [self previewText]; +} + +- (NSString *)previewText +{ switch (_callType) { case RPRecentCallTypeIncoming: return NSLocalizedString(@"INCOMING_CALL", @""); @@ -83,10 +89,16 @@ NSUInteger TSCallCurrentSchemaVersion = 1; return NSLocalizedString(@"INFO_MESSAGE_MISSED_CALL_DUE_TO_CHANGED_IDENITY", @"info message text shown in conversation view"); case RPRecentCallTypeIncomingDeclined: return NSLocalizedString(@"INCOMING_DECLINED_CALL", - @"info message recorded in conversation history when local user declined a call"); + @"info message recorded in conversation history when local user declined a call"); } } +- (NSString *)description +{ + OWSFail(@"%@ in %s verify this isnt exposed in the UI", self.logTag, __PRETTY_FUNCTION__); + return [self previewText]; +} + #pragma mark - OWSReadTracking - (uint64_t)expireStartedAt diff --git a/SignalServiceKit/src/Storage/TSYapDatabaseObject.m b/SignalServiceKit/src/Storage/TSYapDatabaseObject.m index f9eafec5f..a11ac3d4e 100644 --- a/SignalServiceKit/src/Storage/TSYapDatabaseObject.m +++ b/SignalServiceKit/src/Storage/TSYapDatabaseObject.m @@ -109,17 +109,20 @@ NS_ASSUME_NONNULL_BEGIN + (YapDatabaseConnection *)dbReadConnection { + OWSAssert(![NSThread isMainThread]); + // We use TSYapDatabaseObject's dbReadWriteConnection (not OWSPrimaryStorage's // dbReadConnection) for consistency, since we tend to [TSYapDatabaseObject // save] and want to write to the same connection we read from. To get true // consistency, we'd want to update entities by reading & writing from within // the same transaction, but that'll be a big refactor. - return self.dbReadWriteConnection; } + (YapDatabaseConnection *)dbReadWriteConnection { + OWSAssert(![NSThread isMainThread]); + // Use a dedicated connection for model reads & writes. static YapDatabaseConnection *dbReadWriteConnection = nil; static dispatch_once_t onceToken;