From a039aac36de7ee2cdd1576e02cc3b1741ba41d62 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 20 Jun 2017 10:24:29 -0400 Subject: [PATCH] =?UTF-8?q?Improve=20UX=20for=20multiple=20=E2=80=9Cno=20l?= =?UTF-8?q?onger=20verified=E2=80=9D=20members=20of=20a=20group.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit // FREEBIE --- .../ConversationView/MessagesViewController.m | 30 ++++++++-- .../ShowGroupMembersViewController.m | 58 +++++++++++++++++-- .../translations/en.lproj/Localizable.strings | 12 ++++ 3 files changed, 89 insertions(+), 11 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m index fe89dd006..bb460e72b 100644 --- a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m +++ b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m @@ -844,6 +844,12 @@ typedef enum : NSUInteger { - (void)noLongerVerifiedBannerViewWasTapped:(UIGestureRecognizer *)sender { if (sender.state == UIGestureRecognizerStateRecognized) { + NSArray *noLongerVerifiedRecipientIds = [self noLongerVerifiedRecipientIds]; + if (noLongerVerifiedRecipientIds.count < 1) { + return; + } + BOOL hasMultiple = noLongerVerifiedRecipientIds.count > 1; + UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:nil message:nil @@ -851,12 +857,14 @@ typedef enum : NSUInteger { __weak MessagesViewController *weakSelf = self; UIAlertAction *verifyAction = [UIAlertAction - actionWithTitle: - NSLocalizedString(@"VERIFY_PRIVACY", - @"Label for button or row which allows users to verify the safety number of another user.") - style:UIAlertActionStyleDefault + actionWithTitle:(hasMultiple ? NSLocalizedString(@"VERIFY_PRIVACY_MULTIPLE", + @"Label for button or row which allows users to verify the safety " + @"numbers of multiple users.") + : NSLocalizedString(@"VERIFY_PRIVACY", + @"Label for button or row which allows users to verify the safety " + @"number of another user."))style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) { - [weakSelf showConversationSettingsAndShowVerification:YES]; + [weakSelf showNoLongerVerifiedUI]; }]; [actionSheetController addAction:verifyAction]; @@ -1952,6 +1960,18 @@ typedef enum : NSUInteger { #pragma mark - Actions +- (void)showNoLongerVerifiedUI +{ + NSArray *noLongerVerifiedRecipientIds = [self noLongerVerifiedRecipientIds]; + if (noLongerVerifiedRecipientIds.count > 1) { + [self showConversationSettingsAndShowVerification:YES]; + } else if (noLongerVerifiedRecipientIds.count == 1) { + // Pick one in an arbitrary but deterministic manner. + NSString *recipientId = noLongerVerifiedRecipientIds.lastObject; + [self showFingerprintWithRecipientId:recipientId]; + } +} + - (void)showConversationSettings { [self showConversationSettingsAndShowVerification:NO]; diff --git a/Signal/src/ViewControllers/ShowGroupMembersViewController.m b/Signal/src/ViewControllers/ShowGroupMembersViewController.m index 76a0bf93f..150af575d 100644 --- a/Signal/src/ViewControllers/ShowGroupMembersViewController.m +++ b/Signal/src/ViewControllers/ShowGroupMembersViewController.m @@ -121,24 +121,60 @@ NS_ASSUME_NONNULL_BEGIN OWSTableContents *contents = [OWSTableContents new]; - __weak ShowGroupMembersViewController *weakSelf = self; ContactsViewHelper *helper = self.contactsViewHelper; + OWSTableSection *membersSection = [OWSTableSection new]; + // Group Members - OWSTableSection *section = [OWSTableSection new]; + // If there are "no longer verified" members of the group, + // highlight them in a special section. + NSSet *noLongerVerifiedRecipientIds = [NSSet setWithArray:[self noLongerVerifiedRecipientIds]]; + if (noLongerVerifiedRecipientIds.count > 0) { + OWSTableSection *noLongerVerifiedSection = [OWSTableSection new]; + noLongerVerifiedSection.headerTitle = NSLocalizedString(@"GROUP_MEMBERS_SECTION_TITLE_NO_LONGER_VERIFIED", + @"Title for the 'no longer verified' section of the 'group members' view."); + membersSection.headerTitle = NSLocalizedString( + @"GROUP_MEMBERS_SECTION_TITLE_MEMBERS", @"Title for the 'members' section of the 'group members' view."); + [self addMembers:noLongerVerifiedRecipientIds.allObjects + toSection:noLongerVerifiedSection + noLongerVerifiedRecipientIds:noLongerVerifiedRecipientIds]; + [contents addSection:noLongerVerifiedSection]; + } NSMutableSet *memberRecipientIds = [self.memberRecipientIds mutableCopy]; [memberRecipientIds removeObject:[helper localNumber]]; - for (NSString *recipientId in [memberRecipientIds.allObjects sortedArrayUsingSelector:@selector(compare:)]) { + [self addMembers:memberRecipientIds.allObjects + toSection:membersSection + noLongerVerifiedRecipientIds:noLongerVerifiedRecipientIds]; + [contents addSection:membersSection]; + + self.contents = contents; +} + +- (void)addMembers:(NSArray *)recipientIds + toSection:(OWSTableSection *)section + noLongerVerifiedRecipientIds:(NSSet *)noLongerVerifiedRecipientIds +{ + OWSAssert(recipientIds); + OWSAssert(section); + OWSAssert(noLongerVerifiedRecipientIds); + + __weak ShowGroupMembersViewController *weakSelf = self; + ContactsViewHelper *helper = self.contactsViewHelper; + for (NSString *recipientId in [recipientIds sortedArrayUsingSelector:@selector(compare:)]) { [section addItem:[OWSTableItem itemWithCustomCellBlock:^{ ShowGroupMembersViewController *strongSelf = weakSelf; OWSAssert(strongSelf); ContactTableViewCell *cell = [ContactTableViewCell new]; SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId]; + BOOL isNoLongerVerified = [noLongerVerifiedRecipientIds containsObject:recipientId]; BOOL isBlocked = [helper isRecipientIdBlocked:recipientId]; - if (isBlocked) { + if (isNoLongerVerified) { + cell.accessoryMessage = NSLocalizedString( + @"CONTACT_CELL_IS_NO_LONGER_VERIFIED", @"An indicator that a contact is no longer verified."); + } else if (isBlocked) { cell.accessoryMessage = NSLocalizedString(@"CONTACT_CELL_IS_BLOCKED", @"An indicator that a contact has been blocked."); } @@ -162,9 +198,19 @@ NS_ASSUME_NONNULL_BEGIN [weakSelf didSelectRecipientId:recipientId]; }]]; } - [contents addSection:section]; +} - self.contents = contents; +// Returns a collection of the group members who are "no longer verified". +- (NSArray *)noLongerVerifiedRecipientIds +{ + NSMutableArray *result = [NSMutableArray new]; + for (NSString *recipientId in self.thread.recipientIdentifiers) { + if ([[OWSIdentityManager sharedManager] verificationStateForRecipientId:recipientId] + == OWSVerificationStateNoLongerVerified) { + [result addObject:recipientId]; + } + } + return [result copy]; } - (void)didSelectRecipientId:(NSString *)recipientId diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index f45ea1fb0..1b32fac93 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -268,6 +268,9 @@ /* An indicator that a contact has been blocked. */ "CONTACT_CELL_IS_BLOCKED" = "Blocked"; +/* An indicator that a contact is no longer verified. */ +"CONTACT_CELL_IS_NO_LONGER_VERIFIED" = "Not Verified"; + /* No comment provided by engineer. */ "CONTACT_DETAIL_COMM_TYPE_INSECURE" = "Unregistered Number"; @@ -577,6 +580,12 @@ /* Button label for the 'call group member' button */ "GROUP_MEMBERS_CALL" = "Call"; +/* Title for the 'members' section of the 'group members' view. */ +"GROUP_MEMBERS_SECTION_TITLE_MEMBERS" = "Members"; + +/* Title for the 'no longer verified' section of the 'group members' view. */ +"GROUP_MEMBERS_SECTION_TITLE_NO_LONGER_VERIFIED" = "No Longer Marked as Verified"; + /* Button label for the 'send message to group member' button */ "GROUP_MEMBERS_SEND_MESSAGE" = "Send Message"; @@ -1441,6 +1450,9 @@ /* Label for button or row which allows users to verify the safety number of another user. */ "VERIFY_PRIVACY" = "Show Safety Number"; +/* Label for button or row which allows users to verify the safety numbers of multiple users. */ +"VERIFY_PRIVACY_MULTIPLE" = "Review Safety Numbers"; + /* Indicates how to cancel a voice message. */ "VOICE_MESSAGE_CANCEL_INSTRUCTIONS" = "Slide to Cancel";