From 8c347699bba96de0b749f5b212dc59f1492ada57 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 4 Apr 2017 12:35:52 -0400 Subject: [PATCH 1/6] Block actions in message view for blocked contact conversations. // FREEBIE --- .../ViewControllers/MessagesViewController.m | 119 +++++++++++++++++- 1 file changed, 113 insertions(+), 6 deletions(-) diff --git a/Signal/src/ViewControllers/MessagesViewController.m b/Signal/src/ViewControllers/MessagesViewController.m index b5841f12c..573a9acb1 100644 --- a/Signal/src/ViewControllers/MessagesViewController.m +++ b/Signal/src/ViewControllers/MessagesViewController.m @@ -2,12 +2,14 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // +#import "MessagesViewController.h" #import "AppDelegate.h" #import "AttachmentSharing.h" +#import "BlockListUIUtils.h" +#import "DebugUITableViewController.h" #import "Environment.h" #import "FingerprintViewController.h" #import "FullImageViewController.h" -#import "MessagesViewController.h" #import "NSDate+millisecondTimeStamp.h" #import "NewGroupViewController.h" #import "OWSCall.h" @@ -34,6 +36,7 @@ #import "TSIncomingMessage.h" #import "TSInfoMessage.h" #import "TSInvalidIdentityKeyErrorMessage.h" +#import "ThreadUtil.h" #import "UIFont+OWS.h" #import "UIUtil.h" #import "UIViewController+CameraPermissions.h" @@ -51,19 +54,18 @@ #import #import #import +#import #import #import #import #import #import -#import #import #import #import #import +#import #import -#import "ThreadUtil.h" -#import "DebugUITableViewController.h" @import Photos; @@ -198,6 +200,7 @@ typedef enum : NSUInteger { @property (nonatomic) UILabel *navigationBarTitleLabel; @property (nonatomic) UILabel *navigationBarSubtitleLabel; @property (nonatomic) UIButton *attachButton; +@property (nonatomic) UIButton *blockStateIndicator; @property (nonatomic) CGFloat previousCollectionViewFrameWidth; @@ -213,6 +216,7 @@ typedef enum : NSUInteger { @property (nonatomic, readonly) TSMessagesManager *messagesManager; @property (nonatomic, readonly) TSNetworkManager *networkManager; @property (nonatomic, readonly) OutboundCallInitiator *outboundCallInitiator; +@property (nonatomic, readonly) OWSBlockingManager *blockingManager; @property (nonatomic) NSCache *messageAdapterCache; @@ -270,6 +274,26 @@ typedef enum : NSUInteger { _disappearingMessagesJob = [[OWSDisappearingMessagesJob alloc] initWithStorageManager:_storageManager]; _messagesManager = [TSMessagesManager sharedManager]; _networkManager = [TSNetworkManager sharedManager]; + _blockingManager = [OWSBlockingManager sharedManager]; + + [self addNotificationListeners]; +} + +- (void)addNotificationListeners +{ + // I have not added this to toggleObservers since I am + // not con + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(blockedPhoneNumbersDidChange:) + name:kNSNotificationName_BlockedPhoneNumbersDidChange + object:nil]; +} + +- (void)blockedPhoneNumbersDidChange:(id)notification +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [self ensureBlockStateIndicator]; + }); } - (void)peekSetup { @@ -500,6 +524,24 @@ typedef enum : NSUInteger { @"Short name for edit menu item to share contents of media message.") action:shareSelector], ]; + + [self ensureBlockStateIndicator]; +} + +- (void)ensureBlockStateIndicator +{ + [self.blockStateIndicator removeFromSuperview]; + self.blockStateIndicator = nil; +} + + +- (BOOL)isBlockedContactConversation +{ + if (![self.thread isKindOfClass:[TSContactThread class]]) { + return NO; + } + NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; + return [[_blockingManager blockedPhoneNumbers] containsObject:contactIdentifier]; } - (void)startReadTimer { @@ -693,7 +735,7 @@ typedef enum : NSUInteger { backItem, [[UIBarButtonItem alloc] initWithCustomView:self.navigationBarTitleView], ]; - + if (self.userLeftGroup) { self.navigationItem.rightBarButtonItems = @[]; return; @@ -842,6 +884,21 @@ typedef enum : NSUInteger { return; } + if ([self isBlockedContactConversation]) { + __weak MessagesViewController *weakSelf = self; + NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; + [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier + fromViewController:self + blockingManager:_blockingManager + contactsManager:_contactsManager + completionBlock:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf callAction:nil]; + } + }]; + return; + } + [self.outboundCallInitiator initiateCallWithRecipientId:self.thread.contactIdentifier]; } @@ -857,6 +914,25 @@ typedef enum : NSUInteger { senderDisplayName:(NSString *)senderDisplayName date:(NSDate *)date { + if ([self isBlockedContactConversation]) { + __weak MessagesViewController *weakSelf = self; + NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; + [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier + fromViewController:self + blockingManager:_blockingManager + contactsManager:_contactsManager + completionBlock:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf didPressSendButton:button + withMessageText:text + senderId:senderId + senderDisplayName:senderDisplayName + date:date]; + } + }]; + return; + } + text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; // Limit outgoing text messages to 64kb. @@ -2319,6 +2395,22 @@ typedef enum : NSUInteger { #pragma mark Accessory View - (void)didPressAccessoryButton:(UIButton *)sender { + + if ([self isBlockedContactConversation]) { + __weak MessagesViewController *weakSelf = self; + NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; + [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier + fromViewController:self + blockingManager:_blockingManager + contactsManager:_contactsManager + completionBlock:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf didPressAccessoryButton:nil]; + } + }]; + return; + } + UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; @@ -2551,7 +2643,22 @@ typedef enum : NSUInteger { DDLogError(@"%@ %s", self.tag, __PRETTY_FUNCTION__); - + + if ([self isBlockedContactConversation]) { + __weak MessagesViewController *weakSelf = self; + NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; + [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier + fromViewController:self + blockingManager:_blockingManager + contactsManager:_contactsManager + completionBlock:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf didPasteAttachment:attachment]; + } + }]; + return; + } + if (attachment == nil || [attachment hasError]) { DDLogWarn(@"%@ %s Invalid attachment: %@.", From 9c9060203e2bbef5fe625a7e36c8ff4c6121fca3 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 4 Apr 2017 15:38:00 -0400 Subject: [PATCH 2/6] Block actions in message view for blocked group conversations. * Add block status indicator view. // FREEBIE --- .../ViewControllers/MessagesViewController.m | 95 ++++++++++++++++++- .../translations/en.lproj/Localizable.strings | 15 +-- 2 files changed, 103 insertions(+), 7 deletions(-) diff --git a/Signal/src/ViewControllers/MessagesViewController.m b/Signal/src/ViewControllers/MessagesViewController.m index 573a9acb1..1dec6edda 100644 --- a/Signal/src/ViewControllers/MessagesViewController.m +++ b/Signal/src/ViewControllers/MessagesViewController.m @@ -7,6 +7,7 @@ #import "AttachmentSharing.h" #import "BlockListUIUtils.h" #import "DebugUITableViewController.h" +#import "BlockListViewController.h" #import "Environment.h" #import "FingerprintViewController.h" #import "FullImageViewController.h" @@ -200,7 +201,7 @@ typedef enum : NSUInteger { @property (nonatomic) UILabel *navigationBarTitleLabel; @property (nonatomic) UILabel *navigationBarSubtitleLabel; @property (nonatomic) UIButton *attachButton; -@property (nonatomic) UIButton *blockStateIndicator; +@property (nonatomic) UIView *blockStateIndicator; @property (nonatomic) CGFloat previousCollectionViewFrameWidth; @@ -530,10 +531,86 @@ typedef enum : NSUInteger { - (void)ensureBlockStateIndicator { + // This method should be called rarely, so it's simplest to discard and + // rebuild the indicator view every time. [self.blockStateIndicator removeFromSuperview]; self.blockStateIndicator = nil; + + NSString *blockStateMessage = nil; + if ([self isBlockedContactConversation]) { + blockStateMessage = NSLocalizedString(@"MESSAGES_VIEW_CONTACT_BLOCKED", + @"Indicates that this 1:1 conversation has been blocked."); + } else { + int blockedGroupMemberCount = [self blockedGroupMemberCount]; + if (blockedGroupMemberCount == 1) { + blockStateMessage = [NSString stringWithFormat:NSLocalizedString(@"MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED_FORMAT", + @"Indicates that a single member of this group has been blocked."), + blockedGroupMemberCount]; + } else if (blockedGroupMemberCount > 1) { + blockStateMessage = [NSString stringWithFormat:NSLocalizedString(@"MESSAGES_VIEW_GROUP_N_MEMBERS_BLOCKED_FORMAT", + @"Indicates that some members of this group has been blocked. Embeds " + @"{{the number of blocked user in this group}}."), + blockedGroupMemberCount]; + } + } + + if (blockStateMessage) { + UILabel *label = [UILabel new]; + label.font = [UIFont ows_mediumFontWithSize:14.f]; + label.text = blockStateMessage; + label.textColor = [UIColor whiteColor]; + + UIView * blockStateIndicator = [UIView new]; + blockStateIndicator.backgroundColor = [UIColor ows_signalBrandBlueColor]; + blockStateIndicator.layer.cornerRadius = 2.5f; + + // Use a shadow to "pop" the indicator above the other views. + blockStateIndicator.layer.shadowColor = [UIColor blackColor].CGColor; + blockStateIndicator.layer.shadowOffset = CGSizeMake(2, 3); + blockStateIndicator.layer.shadowRadius = 2.f; + blockStateIndicator.layer.shadowOpacity = 0.35f; + + [blockStateIndicator addSubview:label]; + [label autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:5]; + [label autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:5]; + [label autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:15]; + [label autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:15]; + + [blockStateIndicator addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self + action:@selector(blockStateIndicatorWasTapped:)]]; + + [self.view addSubview:blockStateIndicator]; + [blockStateIndicator autoHCenterInSuperview]; + [blockStateIndicator autoPinToTopLayoutGuideOfViewController:self withInset:10]; + [self.view layoutSubviews]; + + self.blockStateIndicator = blockStateIndicator; + } } + +- (void)blockStateIndicatorWasTapped:(UIGestureRecognizer *)sender { + if (sender.state != UIGestureRecognizerStateRecognized) { + return; + } + if ([self isBlockedContactConversation]) { + // If this a blocked 1:1 conversation, offer to unblock the user. + NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; + [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier + fromViewController:self + blockingManager:_blockingManager + contactsManager:_contactsManager + completionBlock:nil]; + } else { + // If this a group conversation with at least one blocked member, + // Show the block list view. + int blockedGroupMemberCount = [self blockedGroupMemberCount]; + if (blockedGroupMemberCount > 0) { + BlockListViewController *vc = [[BlockListViewController alloc] init]; + [self.navigationController pushViewController:vc animated:YES]; + } + } +} - (BOOL)isBlockedContactConversation { @@ -544,6 +621,22 @@ typedef enum : NSUInteger { return [[_blockingManager blockedPhoneNumbers] containsObject:contactIdentifier]; } +- (int)blockedGroupMemberCount +{ + if (![self.thread isKindOfClass:[TSGroupThread class]]) { + return 0; + } + TSGroupThread *groupThread = (TSGroupThread *)self.thread; + int blockedMemberCount = 0; + NSArray *blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers]; + for (NSString *contactIdentifier in groupThread.groupModel.groupMemberIds) { + if ([blockedPhoneNumbers containsObject:contactIdentifier]) { + blockedMemberCount++; + } + } + return blockedMemberCount; +} + - (void)startReadTimer { self.readTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index b3ddf3077..4fe8c68a8 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -346,9 +346,6 @@ /* No comment provided by engineer. */ "ERROR_MESSAGE_WRONG_TRUSTED_IDENTITY_KEY" = "Safety number changed. Tap to verify."; -/* No comment provided by engineer. */ -"ERROR_WAS_DETECTED_TITLE" = "Bummer!"; - /* during registration */ "EXISTING_USER_REGISTRATION_ALERT_BODY" = "At this time Signal can only be active on one mobile device per phone number."; @@ -529,6 +526,15 @@ /* message footer while attachment is uploading */ "MESSAGE_STATUS_UPLOADING" = "Uploading..."; +/* Indicates that this 1:1 conversation has been blocked. */ +"MESSAGES_VIEW_CONTACT_BLOCKED" = "This user is blocked"; + +/* Indicates that some members of this group has been blocked. Embeds {{the number of blocked user in this group}}. */ +"MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED_FORMAT" = "1 Blocked Member of this Group"; + +/* Indicates that some members of this group has been blocked. Embeds {{the number of blocked user in this group}}. */ +"MESSAGES_VIEW_GROUP_N_MEMBERS_BLOCKED_FORMAT" = "%d Blocked Members of this Group"; + /* The subtitle for the messages view title indicates that the title can be tapped to access settings for this conversation. */ "MESSAGES_VIEW_TITLE_SUBTITLE" = "Tap here for settings"; @@ -970,9 +976,6 @@ /* No comment provided by engineer. */ "SUCCESSFUL_VERIFICATION_TITLE" = "Safety Number Verified!"; -/* No comment provided by engineer. */ -"TIMEOUT_CONTACTS_DETAIL" = "We couldn't fetch an updated contact list from the server. Please try again later."; - /* No comment provided by engineer. */ "TXT_CANCEL_TITLE" = "Cancel"; From c500e7890f9ef5a359a0a0240da1be7db5fa4615 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 4 Apr 2017 15:54:11 -0400 Subject: [PATCH 3/6] Improve completion handling of block actions. // FREEBIE --- Signal/src/ViewControllers/BlockListUIUtils.m | 51 +++++++---- .../ViewControllers/MessagesViewController.m | 89 ++++++++----------- .../translations/en.lproj/Localizable.strings | 10 ++- 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/Signal/src/ViewControllers/BlockListUIUtils.m b/Signal/src/ViewControllers/BlockListUIUtils.m index 1af210bf0..ba329101e 100644 --- a/Signal/src/ViewControllers/BlockListUIUtils.m +++ b/Signal/src/ViewControllers/BlockListUIUtils.m @@ -10,6 +10,8 @@ NS_ASSUME_NONNULL_BEGIN +typedef void (^BlockAlertCompletionBlock)(); + @implementation BlockListUIUtils + (void)showBlockContactActionSheet:(Contact *)contact @@ -27,10 +29,12 @@ NS_ASSUME_NONNULL_BEGIN if (phoneNumbers.count < 1) { DDLogError(@"%@ Contact has no phone numbers", self.tag); OWSAssert(0); - [self showBlockFailedAlert:fromViewController]; - if (completionBlock) { - completionBlock(NO); - } + [self showBlockFailedAlert:fromViewController + completionBlock:^{ + if (completionBlock) { + completionBlock(NO); + } + }]; return; } NSString *displayName = [contactsManager displayNameForContact:contact]; @@ -81,10 +85,12 @@ NS_ASSUME_NONNULL_BEGIN [self blockPhoneNumbers:phoneNumbers displayName:displayName fromViewController:fromViewController - blockingManager:blockingManager]; - if (completionBlock) { - completionBlock(YES); - } + blockingManager:blockingManager + completionBlock:^{ + if (completionBlock) { + completionBlock(YES); + } + }]; }]; [actionSheetController addAction:unblockAction]; @@ -104,6 +110,7 @@ NS_ASSUME_NONNULL_BEGIN displayName:(NSString *)displayName fromViewController:(UIViewController *)fromViewController blockingManager:(OWSBlockingManager *)blockingManager + completionBlock:(BlockAlertCompletionBlock)completionBlock { OWSAssert(phoneNumbers.count > 0); OWSAssert(displayName.length > 0); @@ -122,7 +129,8 @@ NS_ASSUME_NONNULL_BEGIN @"The message format of the 'user blocked' " @"alert. Embeds {{the blocked user's name or phone number}}."), [self formatDisplayNameForAlertMessage:displayName]] - fromViewController:fromViewController]; + fromViewController:fromViewController + completionBlock:completionBlock]; } + (void)showUnblockPhoneNumberActionSheet:(NSString *)phoneNumber @@ -153,10 +161,12 @@ NS_ASSUME_NONNULL_BEGIN [BlockListUIUtils unblockPhoneNumber:phoneNumber displayName:displayName fromViewController:fromViewController - blockingManager:blockingManager]; - if (completionBlock) { - completionBlock(NO); - } + blockingManager:blockingManager + completionBlock:^{ + if (completionBlock) { + completionBlock(NO); + } + }]; }]; [actionSheetController addAction:unblockAction]; @@ -176,6 +186,7 @@ NS_ASSUME_NONNULL_BEGIN displayName:(NSString *)displayName fromViewController:(UIViewController *)fromViewController blockingManager:(OWSBlockingManager *)blockingManager + completionBlock:(BlockAlertCompletionBlock)completionBlock { OWSAssert(phoneNumber.length > 0); OWSAssert(displayName.length > 0); @@ -191,10 +202,12 @@ NS_ASSUME_NONNULL_BEGIN @"The message format of the 'user unblocked' " @"alert. Embeds {{the blocked user's name or phone number}}."), [self formatDisplayNameForAlertMessage:displayName]] - fromViewController:fromViewController]; + fromViewController:fromViewController + completionBlock:completionBlock]; } + (void)showBlockFailedAlert:(UIViewController *)fromViewController + completionBlock:(BlockAlertCompletionBlock)completionBlock { OWSAssert(fromViewController); @@ -202,10 +215,12 @@ NS_ASSUME_NONNULL_BEGIN @"The title of the 'block user failed' alert.") message:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_MESSAGE", @"The title of the 'block user failed' alert.") - fromViewController:fromViewController]; + fromViewController:fromViewController + completionBlock:completionBlock]; } + (void)showUnblockFailedAlert:(UIViewController *)fromViewController + completionBlock:(BlockAlertCompletionBlock)completionBlock { OWSAssert(fromViewController); @@ -213,12 +228,14 @@ NS_ASSUME_NONNULL_BEGIN @"The title of the 'unblock user failed' alert.") message:NSLocalizedString(@"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_MESSAGE", @"The title of the 'unblock user failed' alert.") - fromViewController:fromViewController]; + fromViewController:fromViewController + completionBlock:completionBlock]; } + (void)showOkAlertWithTitle:(NSString *)title message:(NSString *)message fromViewController:(UIViewController *)fromViewController + completionBlock:(BlockAlertCompletionBlock)completionBlock { OWSAssert(title.length > 0); OWSAssert(message.length > 0); @@ -229,7 +246,7 @@ NS_ASSUME_NONNULL_BEGIN [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault - handler:nil]]; + handler:completionBlock]]; [fromViewController presentViewController:controller animated:YES completion:nil]; } diff --git a/Signal/src/ViewControllers/MessagesViewController.m b/Signal/src/ViewControllers/MessagesViewController.m index 1dec6edda..894c91adb 100644 --- a/Signal/src/ViewControllers/MessagesViewController.m +++ b/Signal/src/ViewControllers/MessagesViewController.m @@ -282,8 +282,6 @@ typedef enum : NSUInteger { - (void)addNotificationListeners { - // I have not added this to toggleObservers since I am - // not con [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(blockedPhoneNumbersDidChange:) name:kNSNotificationName_BlockedPhoneNumbersDidChange @@ -595,12 +593,7 @@ typedef enum : NSUInteger { if ([self isBlockedContactConversation]) { // If this a blocked 1:1 conversation, offer to unblock the user. - NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; - [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier - fromViewController:self - blockingManager:_blockingManager - contactsManager:_contactsManager - completionBlock:nil]; + [self showUnblockContactUI:nil]; } else { // If this a group conversation with at least one blocked member, // Show the block list view. @@ -612,6 +605,18 @@ typedef enum : NSUInteger { } } +- (void)showUnblockContactUI:(BlockActionCompletionBlock)completionBlock +{ + OWSAssert([self.thread isKindOfClass:[TSContactThread class]]); + + NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; + [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier + fromViewController:self + blockingManager:_blockingManager + contactsManager:_contactsManager + completionBlock:completionBlock]; +} + - (BOOL)isBlockedContactConversation { if (![self.thread isKindOfClass:[TSContactThread class]]) { @@ -979,16 +984,11 @@ typedef enum : NSUInteger { if ([self isBlockedContactConversation]) { __weak MessagesViewController *weakSelf = self; - NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; - [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier - fromViewController:self - blockingManager:_blockingManager - contactsManager:_contactsManager - completionBlock:^(BOOL isBlocked) { - if (!isBlocked) { - [weakSelf callAction:nil]; - } - }]; + [self showUnblockContactUI:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf callAction:nil]; + } + }]; return; } @@ -1009,20 +1009,15 @@ typedef enum : NSUInteger { { if ([self isBlockedContactConversation]) { __weak MessagesViewController *weakSelf = self; - NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; - [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier - fromViewController:self - blockingManager:_blockingManager - contactsManager:_contactsManager - completionBlock:^(BOOL isBlocked) { - if (!isBlocked) { - [weakSelf didPressSendButton:button - withMessageText:text - senderId:senderId - senderDisplayName:senderDisplayName - date:date]; - } - }]; + [self showUnblockContactUI:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf didPressSendButton:button + withMessageText:text + senderId:senderId + senderDisplayName:senderDisplayName + date:date]; + } + }]; return; } @@ -2491,16 +2486,11 @@ typedef enum : NSUInteger { if ([self isBlockedContactConversation]) { __weak MessagesViewController *weakSelf = self; - NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; - [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier - fromViewController:self - blockingManager:_blockingManager - contactsManager:_contactsManager - completionBlock:^(BOOL isBlocked) { - if (!isBlocked) { - [weakSelf didPressAccessoryButton:nil]; - } - }]; + [self showUnblockContactUI:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf didPressAccessoryButton:nil]; + } + }]; return; } @@ -2739,16 +2729,11 @@ typedef enum : NSUInteger { if ([self isBlockedContactConversation]) { __weak MessagesViewController *weakSelf = self; - NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; - [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier - fromViewController:self - blockingManager:_blockingManager - contactsManager:_contactsManager - completionBlock:^(BOOL isBlocked) { - if (!isBlocked) { - [weakSelf didPasteAttachment:attachment]; - } - }]; + [self showUnblockContactUI:^(BOOL isBlocked) { + if (!isBlocked) { + [weakSelf didPasteAttachment:attachment]; + } + }]; return; } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 4fe8c68a8..16f165ac7 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -346,6 +346,9 @@ /* No comment provided by engineer. */ "ERROR_MESSAGE_WRONG_TRUSTED_IDENTITY_KEY" = "Safety number changed. Tap to verify."; +/* No comment provided by engineer. */ +"ERROR_WAS_DETECTED_TITLE" = "ERROR_WAS_DETECTED_TITLE"; + /* during registration */ "EXISTING_USER_REGISTRATION_ALERT_BODY" = "At this time Signal can only be active on one mobile device per phone number."; @@ -527,9 +530,9 @@ "MESSAGE_STATUS_UPLOADING" = "Uploading..."; /* Indicates that this 1:1 conversation has been blocked. */ -"MESSAGES_VIEW_CONTACT_BLOCKED" = "This user is blocked"; +"MESSAGES_VIEW_CONTACT_BLOCKED" = "This User is Blocked"; -/* Indicates that some members of this group has been blocked. Embeds {{the number of blocked user in this group}}. */ +/* Indicates that a single member of this group has been blocked. */ "MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED_FORMAT" = "1 Blocked Member of this Group"; /* Indicates that some members of this group has been blocked. Embeds {{the number of blocked user in this group}}. */ @@ -976,6 +979,9 @@ /* No comment provided by engineer. */ "SUCCESSFUL_VERIFICATION_TITLE" = "Safety Number Verified!"; +/* No comment provided by engineer. */ +"TIMEOUT_CONTACTS_DETAIL" = "TIMEOUT_CONTACTS_DETAIL"; + /* No comment provided by engineer. */ "TXT_CANCEL_TITLE" = "Cancel"; From 7f21a1bf62376725b52499b6d0366df95f260859 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 4 Apr 2017 18:08:51 -0400 Subject: [PATCH 4/6] =?UTF-8?q?Dismiss=20=E2=80=9Cblock=20state=20indicato?= =?UTF-8?q?r=E2=80=9D=20if=20user=20scrolls=20message=20view.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit // FREEBIE --- .../ViewControllers/MessagesViewController.m | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Signal/src/ViewControllers/MessagesViewController.m b/Signal/src/ViewControllers/MessagesViewController.m index 894c91adb..8602e87bd 100644 --- a/Signal/src/ViewControllers/MessagesViewController.m +++ b/Signal/src/ViewControllers/MessagesViewController.m @@ -220,6 +220,7 @@ typedef enum : NSUInteger { @property (nonatomic, readonly) OWSBlockingManager *blockingManager; @property (nonatomic) NSCache *messageAdapterCache; +@property (nonatomic) BOOL userHasScrolled; @end @@ -527,6 +528,12 @@ typedef enum : NSUInteger { [self ensureBlockStateIndicator]; } +- (void)setUserHasScrolled:(BOOL)userHasScrolled { + _userHasScrolled = userHasScrolled; + + [self ensureBlockStateIndicator]; +} + - (void)ensureBlockStateIndicator { // This method should be called rarely, so it's simplest to discard and @@ -534,6 +541,10 @@ typedef enum : NSUInteger { [self.blockStateIndicator removeFromSuperview]; self.blockStateIndicator = nil; + if (self.userHasScrolled) { + return; + } + NSString *blockStateMessage = nil; if ([self isBlockedContactConversation]) { blockStateMessage = NSLocalizedString(@"MESSAGES_VIEW_CONTACT_BLOCKED", @@ -725,6 +736,7 @@ typedef enum : NSUInteger { - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; self.inputToolbar.contentView.textView.editable = NO; + self.userHasScrolled = NO; } #pragma mark - Initiliazers @@ -2781,6 +2793,13 @@ typedef enum : NSUInteger { completion:nil]; } +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView +{ + self.userHasScrolled = YES; +} + #pragma mark - Class methods + (UINib *)nib From 99a1b4e9f43ba3fb94f624623b4378bbc85aebcd Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 5 Apr 2017 09:41:32 -0400 Subject: [PATCH 5/6] Revert unintended l10n changes. // FREEBIE --- Signal/translations/en.lproj/Localizable.strings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 16f165ac7..022b4f660 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -347,7 +347,7 @@ "ERROR_MESSAGE_WRONG_TRUSTED_IDENTITY_KEY" = "Safety number changed. Tap to verify."; /* No comment provided by engineer. */ -"ERROR_WAS_DETECTED_TITLE" = "ERROR_WAS_DETECTED_TITLE"; +"ERROR_WAS_DETECTED_TITLE" = "Bummer!"; /* during registration */ "EXISTING_USER_REGISTRATION_ALERT_BODY" = "At this time Signal can only be active on one mobile device per phone number."; @@ -980,7 +980,7 @@ "SUCCESSFUL_VERIFICATION_TITLE" = "Safety Number Verified!"; /* No comment provided by engineer. */ -"TIMEOUT_CONTACTS_DETAIL" = "TIMEOUT_CONTACTS_DETAIL"; +"TIMEOUT_CONTACTS_DETAIL" = "We couldn't fetch an updated contact list from the server. Please try again later."; /* No comment provided by engineer. */ "TXT_CANCEL_TITLE" = "Cancel"; From 7273e6faa5576704f96abd2445043c559d06f049 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 5 Apr 2017 12:16:54 -0400 Subject: [PATCH 6/6] Respond to CR. // FREEBIE --- .../ViewControllers/MessagesViewController.m | 52 ++++++++++++++----- .../translations/en.lproj/Localizable.strings | 6 +-- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/Signal/src/ViewControllers/MessagesViewController.m b/Signal/src/ViewControllers/MessagesViewController.m index 8602e87bd..8390e6c61 100644 --- a/Signal/src/ViewControllers/MessagesViewController.m +++ b/Signal/src/ViewControllers/MessagesViewController.m @@ -549,16 +549,15 @@ typedef enum : NSUInteger { if ([self isBlockedContactConversation]) { blockStateMessage = NSLocalizedString(@"MESSAGES_VIEW_CONTACT_BLOCKED", @"Indicates that this 1:1 conversation has been blocked."); - } else { + } else if (isGroupConversation) { int blockedGroupMemberCount = [self blockedGroupMemberCount]; if (blockedGroupMemberCount == 1) { - blockStateMessage = [NSString stringWithFormat:NSLocalizedString(@"MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED_FORMAT", - @"Indicates that a single member of this group has been blocked."), - blockedGroupMemberCount]; + blockStateMessage = NSLocalizedString(@"MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED", + @"Indicates that a single member of this group has been blocked."); } else if (blockedGroupMemberCount > 1) { blockStateMessage = [NSString stringWithFormat:NSLocalizedString(@"MESSAGES_VIEW_GROUP_N_MEMBERS_BLOCKED_FORMAT", @"Indicates that some members of this group has been blocked. Embeds " - @"{{the number of blocked user in this group}}."), + @"{{the number of blocked users in this group}}."), blockedGroupMemberCount]; } } @@ -570,7 +569,7 @@ typedef enum : NSUInteger { label.textColor = [UIColor whiteColor]; UIView * blockStateIndicator = [UIView new]; - blockStateIndicator.backgroundColor = [UIColor ows_signalBrandBlueColor]; + blockStateIndicator.backgroundColor = [UIColor ows_redColor]; blockStateIndicator.layer.cornerRadius = 2.5f; // Use a shadow to "pop" the indicator above the other views. @@ -605,7 +604,7 @@ typedef enum : NSUInteger { if ([self isBlockedContactConversation]) { // If this a blocked 1:1 conversation, offer to unblock the user. [self showUnblockContactUI:nil]; - } else { + } else if (isGroupConversation) { // If this a group conversation with at least one blocked member, // Show the block list view. int blockedGroupMemberCount = [self blockedGroupMemberCount]; @@ -620,6 +619,16 @@ typedef enum : NSUInteger { { OWSAssert([self.thread isKindOfClass:[TSContactThread class]]); + self.userHasScrolled = NO; + + // To avoid "noisy" animations (hiding the keyboard before showing + // the action sheet, re-showing it after), hide the keyboard before + // showing the "unblock" action sheet. + // + // Unblocking is a rare interaction, so it's okay to leave the keyboard + // hidden. + [self dismissKeyBoard]; + NSString *contactIdentifier = ((TSContactThread *)self.thread).contactIdentifier; [BlockListUIUtils showUnblockPhoneNumberActionSheet:contactIdentifier fromViewController:self @@ -639,9 +648,9 @@ typedef enum : NSUInteger { - (int)blockedGroupMemberCount { - if (![self.thread isKindOfClass:[TSGroupThread class]]) { - return 0; - } + OWSAssert(isGroupConversation); + OWSAssert([self.thread isKindOfClass:[TSGroupThread class]]); + TSGroupThread *groupThread = (TSGroupThread *)self.thread; int blockedMemberCount = 0; NSArray *blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers]; @@ -1018,6 +1027,21 @@ typedef enum : NSUInteger { senderId:(NSString *)senderId senderDisplayName:(NSString *)senderDisplayName date:(NSDate *)date +{ + [self didPressSendButton:button + withMessageText:text + senderId:senderId + senderDisplayName:senderDisplayName + date:date + updateKeyboardState:YES]; +} + +- (void)didPressSendButton:(UIButton *)button + withMessageText:(NSString *)text + senderId:(NSString *)senderId + senderDisplayName:(NSString *)senderDisplayName + date:(NSDate *)date + updateKeyboardState:(BOOL)updateKeyboardState { if ([self isBlockedContactConversation]) { __weak MessagesViewController *weakSelf = self; @@ -1027,7 +1051,8 @@ typedef enum : NSUInteger { withMessageText:text senderId:senderId senderDisplayName:senderDisplayName - date:date]; + date:date + updateKeyboardState:NO]; } }]; return; @@ -1064,7 +1089,10 @@ typedef enum : NSUInteger { [ThreadUtil sendMessageWithText:text inThread:self.thread messageSender:self.messageSender]; - [self toggleDefaultKeyboard]; + if (updateKeyboardState) + { + [self toggleDefaultKeyboard]; + } [self finishSendingMessage]; } } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 022b4f660..edcda7c21 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -530,13 +530,13 @@ "MESSAGE_STATUS_UPLOADING" = "Uploading..."; /* Indicates that this 1:1 conversation has been blocked. */ -"MESSAGES_VIEW_CONTACT_BLOCKED" = "This User is Blocked"; +"MESSAGES_VIEW_CONTACT_BLOCKED" = "You Blocked this User"; /* Indicates that a single member of this group has been blocked. */ -"MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED_FORMAT" = "1 Blocked Member of this Group"; +"MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED" = "You Blocked 1 Member of this Group"; /* Indicates that some members of this group has been blocked. Embeds {{the number of blocked user in this group}}. */ -"MESSAGES_VIEW_GROUP_N_MEMBERS_BLOCKED_FORMAT" = "%d Blocked Members of this Group"; +"MESSAGES_VIEW_GROUP_N_MEMBERS_BLOCKED_FORMAT" = "You Blocked %d Members of this Group"; /* The subtitle for the messages view title indicates that the title can be tapped to access settings for this conversation. */ "MESSAGES_VIEW_TITLE_SUBTITLE" = "Tap here for settings";