From 4382f336183a27c244b51fa06354b4649a128885 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 28 Aug 2017 16:45:24 -0400 Subject: [PATCH] Send blank PROFILE_MESSAGE after whitelisting someone So they can immediately fetch your profile. Note, we're going to put this behind a feature flag for initial release since iOS prints an empty bubble when receiving a message like this. // FREEBIE --- Signal/src/Profiles/OWSProfileManager.h | 8 ++ Signal/src/Profiles/OWSProfileManager.m | 73 ++++++++++++++++++- Signal/src/Profiles/ProfileFetcherJob.swift | 2 +- .../ConversationView/MessagesViewController.m | 57 +++++---------- .../OWSConversationSettingsViewController.m | 27 ++----- .../translations/en.lproj/Localizable.strings | 3 + 6 files changed, 110 insertions(+), 60 deletions(-) diff --git a/Signal/src/Profiles/OWSProfileManager.h b/Signal/src/Profiles/OWSProfileManager.h index 9040033a7..2b73b34cc 100644 --- a/Signal/src/Profiles/OWSProfileManager.h +++ b/Signal/src/Profiles/OWSProfileManager.h @@ -17,6 +17,7 @@ extern const NSUInteger kOWSProfileManager_MaxAvatarDiameter; @class TSThread; @class OWSAES256Key; +@class OWSMessageSender; // This class can be safely accessed and used from any thread. @interface OWSProfileManager : NSObject @@ -78,6 +79,13 @@ extern const NSUInteger kOWSProfileManager_MaxAvatarDiameter; profileNameEncrypted:(nullable NSData *)profileNameEncrypted avatarUrlPath:(nullable NSString *)avatarUrlPath; +#pragma mark - User Interface + +- (void)presentAddThreadToProfileWhitelist:(TSThread *)thread + fromViewController:(UIViewController *)fromViewController + messageSender:(OWSMessageSender *)messageSender + success:(void (^)())successHandler; + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/Profiles/OWSProfileManager.m b/Signal/src/Profiles/OWSProfileManager.m index 209b5415c..52cf696b0 100644 --- a/Signal/src/Profiles/OWSProfileManager.m +++ b/Signal/src/Profiles/OWSProfileManager.m @@ -1024,7 +1024,10 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; NSURLRequest *request = [NSURLRequest requestWithURL:avatarUrlPath]; NSURLSessionDownloadTask *downloadTask = [self.avatarHTTPManager downloadTaskWithRequest:request progress:^(NSProgress *_Nonnull downloadProgress) { - DDLogVerbose(@"%@ Downloading avatar for %@", self.tag, userProfile.recipientId); + DDLogVerbose(@"%@ Downloading avatar for %@ %f", + self.tag, + userProfile.recipientId, + downloadProgress.fractionCompleted); } destination:^NSURL *_Nonnull(NSURL *_Nonnull targetPath, NSURLResponse *_Nonnull response) { return [NSURL fileURLWithPath:tempFilePath]; @@ -1332,6 +1335,74 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; } } +#pragma mark - User Interface + +- (void)presentAddThreadToProfileWhitelist:(TSThread *)thread + fromViewController:(UIViewController *)fromViewController + messageSender:(OWSMessageSender *)messageSender + success:(void (^)())successHandler +{ + AssertIsOnMainThread(); + + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; + + NSString *shareTitle = NSLocalizedString(@"CONVERSATION_SETTINGS_VIEW_SHARE_PROFILE", + @"Button to confirm that user wants to share their profile with a user or group."); + [alertController addAction:[UIAlertAction actionWithTitle:shareTitle + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + [self addThreadToProfileWhitelist:thread + fromViewController:fromViewController + messageSender:messageSender + success:successHandler]; + }]]; + [alertController addAction:[OWSAlerts cancelAction]]; + + [fromViewController presentViewController:alertController animated:YES completion:nil]; +} + +- (void)addThreadToProfileWhitelist:(TSThread *)thread + fromViewController:(UIViewController *)fromViewController + messageSender:(OWSMessageSender *)messageSender + success:(void (^)())successHandler +{ + + OWSProfileKeyMessage *message = + [[OWSProfileKeyMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread]; + [messageSender sendMessage:message + success:^{ + DDLogInfo(@"%@ Successfully sent profile key message to thread: %@", self.tag, thread); + [OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread]; + + dispatch_async(dispatch_get_main_queue(), ^{ + successHandler(); + }); + } + failure:^(NSError *_Nonnull error) { + dispatch_async(dispatch_get_main_queue(), ^{ + DDLogError(@"%@ Failed to send profile key message to thread: %@", self.tag, thread); + UIAlertController *retryAlertController = [UIAlertController + alertControllerWithTitle:NSLocalizedString(@"SHARE_PROFILE_FAILED_TITLE", @"alert title") + message:error.localizedDescription + preferredStyle:UIAlertControllerStyleAlert]; + [retryAlertController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"RETRY_BUTTON_TEXT", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull retryAction) { + [self addThreadToProfileWhitelist:thread + fromViewController:fromViewController + messageSender:messageSender + success:successHandler]; + }]]; + + [retryAlertController addAction:[OWSAlerts cancelAction]]; + + [fromViewController presentViewController:retryAlertController animated:YES completion:nil]; + }); + }]; +} + #pragma mark - Notifications - (void)applicationDidBecomeActive:(NSNotification *)notification diff --git a/Signal/src/Profiles/ProfileFetcherJob.swift b/Signal/src/Profiles/ProfileFetcherJob.swift index 9e32c359d..0a8119c8d 100644 --- a/Signal/src/Profiles/ProfileFetcherJob.swift +++ b/Signal/src/Profiles/ProfileFetcherJob.swift @@ -60,7 +60,7 @@ class ProfileFetcherJob: NSObject { if remainingRetries > 0 { self.updateProfile(recipientId: recipientId, remainingRetries: remainingRetries - 1) } else { - owsFail("\(self.TAG) in \(#function) failed to get profile with error: \(error)") + Logger.error("\(self.TAG) in \(#function) failed to get profile with error: \(error)") } } }.retainUntilComplete() diff --git a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m index 5e714b676..38352d76a 100644 --- a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m +++ b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m @@ -78,6 +78,7 @@ #import #import #import +#import #import #import #import @@ -900,22 +901,9 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { return; } - UIAlertController *alertController = - [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; - - UIAlertAction *whitelistAction = [UIAlertAction - actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_VIEW_SHARE_PROFILE", - @"Button to confirm that user wants to share their profile with a user or group.") - style:UIAlertActionStyleDestructive - handler:^(UIAlertAction *_Nonnull action) { - [OWSProfileManager.sharedManager addThreadToProfileWhitelist:self.thread]; - - [self ensureBannerState]; - }]; - [alertController addAction:whitelistAction]; - [alertController addAction:[OWSAlerts cancelAction]]; - - [self presentViewController:alertController animated:YES completion:nil]; + [self presentAddThreadToProfileWhitelistWithSuccess:^{ + [self ensureBannerState]; + }]; } - (void)noLongerVerifiedBannerViewWasTapped:(UIGestureRecognizer *)sender @@ -2782,34 +2770,29 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { - (void)tappedAddToProfileWhitelistOfferMessage:(OWSContactOffersInteraction *)interaction { + // This is accessed via the contact offer. Group whitelisting happens via a different interaction. if (![self.thread isKindOfClass:[TSContactThread class]]) { OWSFail(@"%@ unexpected thread: %@ in %s", self.tag, self.thread, __PRETTY_FUNCTION__); return; } TSContactThread *contactThread = (TSContactThread *)self.thread; - UIAlertController *alertController = - [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; - - UIAlertAction *leaveAction = [UIAlertAction - actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_VIEW_SHARE_PROFILE", - @"Button to confirm that user wants to share their profile with a user or group.") - style:UIAlertActionStyleDestructive - handler:^(UIAlertAction *_Nonnull action) { - [OWSProfileManager.sharedManager addThreadToProfileWhitelist:self.thread]; - - // Delete the offers. - [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - contactThread.hasDismissedOffers = YES; - [contactThread saveWithTransaction:transaction]; - [interaction removeWithTransaction:transaction]; - }]; - }]; - [alertController addAction:leaveAction]; - - [alertController addAction:[OWSAlerts cancelAction]]; + [self presentAddThreadToProfileWhitelistWithSuccess:^() { + // Delete the offers. + [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + contactThread.hasDismissedOffers = YES; + [contactThread saveWithTransaction:transaction]; + [interaction removeWithTransaction:transaction]; + }]; + }]; +} - [self presentViewController:alertController animated:YES completion:nil]; +- (void)presentAddThreadToProfileWhitelistWithSuccess:(void (^)())successHandler +{ + [[OWSProfileManager sharedManager] presentAddThreadToProfileWhitelist:self.thread + fromViewController:self + messageSender:self.messageSender + success:successHandler]; } #pragma mark - OWSSystemMessageCellDelegate diff --git a/Signal/src/ViewControllers/OWSConversationSettingsViewController.m b/Signal/src/ViewControllers/OWSConversationSettingsViewController.m index 451ed3121..cfe2255a8 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsViewController.m +++ b/Signal/src/ViewControllers/OWSConversationSettingsViewController.m @@ -785,27 +785,12 @@ NS_ASSUME_NONNULL_BEGIN { [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; - UIAlertController *alertController = - [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; - - UIAlertAction *leaveAction = [UIAlertAction - actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_VIEW_SHARE_PROFILE", - @"Button to confirm that user wants to share their profile with a user or group.") - style:UIAlertActionStyleDestructive - handler:^(UIAlertAction *_Nonnull action) { - [self shareProfile]; - }]; - [alertController addAction:leaveAction]; - [alertController addAction:[OWSAlerts cancelAction]]; - - [self presentViewController:alertController animated:YES completion:nil]; -} - -- (void)shareProfile -{ - [OWSProfileManager.sharedManager addThreadToProfileWhitelist:self.thread]; - - [self updateTableContents]; + [OWSProfileManager.sharedManager presentAddThreadToProfileWhitelist:self.thread + fromViewController:self + messageSender:self.messageSender + success:^{ + [self updateTableContents]; + }]; } - (void)showVerificationView diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 8cdef9d5b..fbe710afa 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -1417,6 +1417,9 @@ /* action sheet item */ "SHARE_ACTION_TWEET" = "Twitter"; +/* alert title */ +"SHARE_PROFILE_FAILED_TITLE" = "Failed to Share Your Profile"; + /* Action sheet item */ "SHOW_SAFETY_NUMBER_ACTION" = "Show New Safety Number";