Add “new contact” and “add to existing contact” buttons in 1:1 conversation settings view.

// FREEBIE
pull/1/head
Matthew Chen 7 years ago
parent 1e67bb52e3
commit 81555d1225

@ -76,6 +76,7 @@
34B3F89F1E8DF5490035BE1A /* OWSTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */; }; 34B3F89F1E8DF5490035BE1A /* OWSTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */; };
34B3F8A21E8EA6040035BE1A /* ViewControllerUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.m */; }; 34B3F8A21E8EA6040035BE1A /* ViewControllerUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.m */; };
34CCAF381F0C0599004084F4 /* AppUpdateNag.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */; }; 34CCAF381F0C0599004084F4 /* AppUpdateNag.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */; };
34CCAF3B1F0C2748004084F4 /* OWSAddToContactViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */; };
34D5CC961EA6AFAD005515DB /* OWSContactsSyncing.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CC951EA6AFAD005515DB /* OWSContactsSyncing.m */; }; 34D5CC961EA6AFAD005515DB /* OWSContactsSyncing.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CC951EA6AFAD005515DB /* OWSContactsSyncing.m */; };
34D5CCA91EAE3D30005515DB /* GroupViewHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCA81EAE3D30005515DB /* GroupViewHelper.m */; }; 34D5CCA91EAE3D30005515DB /* GroupViewHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCA81EAE3D30005515DB /* GroupViewHelper.m */; };
34D5CCB11EAE7E7F005515DB /* SelectRecipientViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCB01EAE7E7F005515DB /* SelectRecipientViewController.m */; }; 34D5CCB11EAE7E7F005515DB /* SelectRecipientViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCB01EAE7E7F005515DB /* SelectRecipientViewController.m */; };
@ -494,6 +495,8 @@
34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewControllerUtils.m; sourceTree = "<group>"; }; 34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewControllerUtils.m; sourceTree = "<group>"; };
34CCAF361F0C0599004084F4 /* AppUpdateNag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppUpdateNag.h; sourceTree = "<group>"; }; 34CCAF361F0C0599004084F4 /* AppUpdateNag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppUpdateNag.h; sourceTree = "<group>"; };
34CCAF371F0C0599004084F4 /* AppUpdateNag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppUpdateNag.m; sourceTree = "<group>"; }; 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppUpdateNag.m; sourceTree = "<group>"; };
34CCAF391F0C2748004084F4 /* OWSAddToContactViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAddToContactViewController.h; sourceTree = "<group>"; };
34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSAddToContactViewController.m; sourceTree = "<group>"; };
34D5CC941EA6AFAD005515DB /* OWSContactsSyncing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactsSyncing.h; sourceTree = "<group>"; }; 34D5CC941EA6AFAD005515DB /* OWSContactsSyncing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactsSyncing.h; sourceTree = "<group>"; };
34D5CC951EA6AFAD005515DB /* OWSContactsSyncing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSyncing.m; sourceTree = "<group>"; }; 34D5CC951EA6AFAD005515DB /* OWSContactsSyncing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSyncing.m; sourceTree = "<group>"; };
34D5CC981EA6EB79005515DB /* OWSMessageCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageCollectionViewCell.h; sourceTree = "<group>"; }; 34D5CC981EA6EB79005515DB /* OWSMessageCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageCollectionViewCell.h; sourceTree = "<group>"; };
@ -980,6 +983,8 @@
34B3F8581E8DF1700035BE1A /* NotificationSettingsViewController.h */, 34B3F8581E8DF1700035BE1A /* NotificationSettingsViewController.h */,
34B3F8591E8DF1700035BE1A /* NotificationSettingsViewController.m */, 34B3F8591E8DF1700035BE1A /* NotificationSettingsViewController.m */,
34B3F85A1E8DF1700035BE1A /* OversizeTextMessageViewController.swift */, 34B3F85A1E8DF1700035BE1A /* OversizeTextMessageViewController.swift */,
34CCAF391F0C2748004084F4 /* OWSAddToContactViewController.h */,
34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */,
34533F161EA8D2070006114F /* OWSAudioAttachmentPlayer.h */, 34533F161EA8D2070006114F /* OWSAudioAttachmentPlayer.h */,
34533F171EA8D2070006114F /* OWSAudioAttachmentPlayer.m */, 34533F171EA8D2070006114F /* OWSAudioAttachmentPlayer.m */,
34B3F85B1E8DF1700035BE1A /* OWSConversationSettingsTableViewController.h */, 34B3F85B1E8DF1700035BE1A /* OWSConversationSettingsTableViewController.h */,
@ -2229,6 +2234,7 @@
34B3F8811E8DF1700035BE1A /* LockInteractionController.m in Sources */, 34B3F8811E8DF1700035BE1A /* LockInteractionController.m in Sources */,
3448BFCC1EDF0EA7005B2D69 /* OWSMessagesToolbarContentView.m in Sources */, 3448BFCC1EDF0EA7005B2D69 /* OWSMessagesToolbarContentView.m in Sources */,
3448BFD01EDF0EA7005B2D69 /* MessagesViewController.m in Sources */, 3448BFD01EDF0EA7005B2D69 /* MessagesViewController.m in Sources */,
34CCAF3B1F0C2748004084F4 /* OWSAddToContactViewController.m in Sources */,
45F659731E1BD99C00444429 /* CallKitCallUIAdaptee.swift in Sources */, 45F659731E1BD99C00444429 /* CallKitCallUIAdaptee.swift in Sources */,
45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */, 45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */,
458DE9D61DEE3FD00071BB03 /* PeerConnectionClient.swift in Sources */, 458DE9D61DEE3FD00071BB03 /* PeerConnectionClient.swift in Sources */,

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "table_ic_add_to_existing_contact@1x.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "table_ic_add_to_existing_contact@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "table_ic_add_to_existing_contact@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "table_ic_new_contact@1x.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "table_ic_new_contact@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "table_ic_new_contact@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -29,6 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
@class OWSContactsManager; @class OWSContactsManager;
@class OWSBlockingManager; @class OWSBlockingManager;
@class CNContact;
@interface ContactsViewHelper : NSObject @interface ContactsViewHelper : NSObject
@ -70,6 +71,12 @@ NS_ASSUME_NONNULL_BEGIN
fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController
editImmediately:(BOOL)shouldEditImmediately; editImmediately:(BOOL)shouldEditImmediately;
// This method can be used to edit existing contacts.
- (void)presentContactViewControllerForRecipientId:(NSString *)recipientId
fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController
editImmediately:(BOOL)shouldEditImmediately
addToExistingCnContact:(CNContact *_Nullable)cnContact;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -300,6 +300,17 @@ NS_ASSUME_NONNULL_BEGIN
- (void)presentContactViewControllerForRecipientId:(NSString *)recipientId - (void)presentContactViewControllerForRecipientId:(NSString *)recipientId
fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController
editImmediately:(BOOL)shouldEditImmediately editImmediately:(BOOL)shouldEditImmediately
{
[self presentContactViewControllerForRecipientId:recipientId
fromViewController:fromViewController
editImmediately:shouldEditImmediately
addToExistingCnContact:nil];
}
- (void)presentContactViewControllerForRecipientId:(NSString *)recipientId
fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController
editImmediately:(BOOL)shouldEditImmediately
addToExistingCnContact:(CNContact *_Nullable)addToExistingCnContact
{ {
SignalAccount *signalAccount = [self signalAccountForRecipientId:recipientId]; SignalAccount *signalAccount = [self signalAccountForRecipientId:recipientId];
@ -340,21 +351,49 @@ NS_ASSUME_NONNULL_BEGIN
} }
CNContactViewController *_Nullable contactViewController; CNContactViewController *_Nullable contactViewController;
if (signalAccount) { CNContact *_Nullable cnContact = nil;
CNContact *_Nullable cnContact = signalAccount.contact.cnContact; if (addToExistingCnContact) {
if (cnContact) { CNMutableContact *updatedContact = [addToExistingCnContact mutableCopy];
if (shouldEditImmediately) { NSMutableArray<CNLabeledValue *> *phoneNumbers
// Not actually a "new" contact, but this brings up the edit form rather than the "Read" form = (updatedContact.phoneNumbers ? [updatedContact.phoneNumbers mutableCopy] : [NSMutableArray new]);
// saving our users a tap in some cases when we already know they want to edit. // Only add recipientId as a phone number for the existing contact
contactViewController = [CNContactViewController viewControllerForNewContact:cnContact]; // if its not already present.
BOOL hasPhoneNumber = NO;
// Default title is "New Contact". We could give a more descriptive title, but anything for (CNLabeledValue *existingPhoneNumber in phoneNumbers) {
// seems redundant - the context is sufficiently clear. CNPhoneNumber *phoneNumber = existingPhoneNumber.value;
contactViewController.title = @""; if ([phoneNumber.stringValue isEqualToString:recipientId]) {
} else { hasPhoneNumber = YES;
contactViewController = [CNContactViewController viewControllerForContact:cnContact]; break;
} }
} }
if (!hasPhoneNumber) {
CNPhoneNumber *phoneNumber = [CNPhoneNumber phoneNumberWithStringValue:recipientId];
CNLabeledValue<CNPhoneNumber *> *labeledPhoneNumber =
[CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMain value:phoneNumber];
[phoneNumbers addObject:labeledPhoneNumber];
updatedContact.phoneNumbers = phoneNumbers;
// When adding a phone number to an existing contact, immediately enter
// "edit" mode.
shouldEditImmediately = YES;
}
cnContact = updatedContact;
}
if (signalAccount && !cnContact) {
cnContact = signalAccount.contact.cnContact;
}
if (cnContact) {
if (shouldEditImmediately) {
// Not actually a "new" contact, but this brings up the edit form rather than the "Read" form
// saving our users a tap in some cases when we already know they want to edit.
contactViewController = [CNContactViewController viewControllerForNewContact:cnContact];
// Default title is "New Contact". We could give a more descriptive title, but anything
// seems redundant - the context is sufficiently clear.
contactViewController.title = @"";
} else {
contactViewController = [CNContactViewController viewControllerForContact:cnContact];
}
} }
if (!contactViewController) { if (!contactViewController) {

@ -0,0 +1,15 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSTableViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface OWSAddToContactViewController : OWSTableViewController
- (void)configureWithRecipientId:(NSString *)recipientId;
@end
NS_ASSUME_NONNULL_END

@ -0,0 +1,250 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSAddToContactViewController.h"
#import "ContactsViewHelper.h"
#import "Environment.h"
#import "OWSContactsManager.h"
#import "UIUtil.h"
@import ContactsUI;
NS_ASSUME_NONNULL_BEGIN
@interface NamedContact : NSObject
@property (nonatomic) Contact *contact;
@property (nonatomic) NSString *displayName;
@end
#pragma mark -
@implementation NamedContact
@end
#pragma mark -
@interface OWSAddToContactViewController () <ContactEditingDelegate, ContactsViewHelperDelegate>
@property (nonatomic) NSString *recipientId;
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper;
@end
#pragma mark -
@implementation OWSAddToContactViewController
- (instancetype)init
{
self = [super init];
if (!self) {
return self;
}
[self commonInit];
return self;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (!self) {
return self;
}
[self commonInit];
return self;
}
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (!self) {
return self;
}
[self commonInit];
return self;
}
- (void)commonInit
{
_contactsManager = [Environment getCurrent].contactsManager;
_contactsViewHelper = [[ContactsViewHelper alloc] initWithDelegate:self];
}
- (void)configureWithRecipientId:(NSString *)recipientId
{
OWSAssert(recipientId.length > 0);
_recipientId = recipientId;
}
#pragma mark - ContactEditingDelegate
- (void)didFinishEditingContact
{
DDLogDebug(@"%@ %s", self.tag, __PRETTY_FUNCTION__);
[self dismissViewControllerAnimated:NO
completion:^{
[self.navigationController popViewControllerAnimated:YES];
}];
}
#pragma mark - CNContactViewControllerDelegate
- (void)contactViewController:(CNContactViewController *)viewController
didCompleteWithContact:(nullable CNContact *)contact
{
if (contact) {
// Saving normally returns you to the "Show Contact" view
// which we're not interested in, so we skip it here. There is
// an unfortunate blip of the "Show Contact" view on slower devices.
DDLogDebug(@"%@ completed editing contact.", self.tag);
[self dismissViewControllerAnimated:NO
completion:^{
[self.navigationController popViewControllerAnimated:YES];
}];
} else {
DDLogDebug(@"%@ canceled editing contact.", self.tag);
[self dismissViewControllerAnimated:YES
completion:^{
[self.navigationController popViewControllerAnimated:YES];
}];
}
}
#pragma mark - ContactsViewHelperDelegate
- (void)contactsViewHelperDidUpdateContacts
{
[self updateTableContents];
}
#pragma mark - View Lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(@"CONVERSATION_SETTINGS_ADD_TO_EXISTING_CONTACT",
@"Label for 'new contact' button in conversation settings view.");
[self updateTableContents];
}
- (nullable NSString *)displayNameForContact:(Contact *)contact
{
OWSAssert(contact);
if (contact.fullName.length > 0) {
return contact.fullName;
}
for (NSString *email in contact.emails) {
if (email.length > 0) {
return email;
}
}
for (NSString *phoneNumber in contact.userTextPhoneNumbers) {
if (phoneNumber.length > 0) {
return phoneNumber;
}
}
return nil;
}
- (void)updateTableContents
{
OWSTableContents *contents = [OWSTableContents new];
contents.title = NSLocalizedString(@"CONVERSATION_SETTINGS", @"title for conversation settings screen");
__weak OWSAddToContactViewController *weakSelf = self;
OWSTableSection *section = [OWSTableSection new];
section.headerTitle = NSLocalizedString(
@"EDIT_GROUP_CONTACTS_SECTION_TITLE", @"a title for the contacts section of the 'new/update group' view.");
NSMutableArray<NamedContact *> *namedContacts = [NSMutableArray new];
for (Contact *contact in self.contactsViewHelper.contactsManager.allContacts) {
OWSAssert(contact.cnContact);
NSString *_Nullable displayName = [self displayNameForContact:contact];
if (displayName.length < 1) {
continue;
}
NamedContact *namedContact = [NamedContact new];
namedContact.contact = contact;
namedContact.displayName = displayName;
[namedContacts addObject:namedContact];
}
[namedContacts sortUsingComparator:^NSComparisonResult(NamedContact *_Nonnull left, NamedContact *_Nonnull right) {
return [left.displayName caseInsensitiveCompare:right.displayName];
}];
for (NamedContact *namedContact in namedContacts) {
[section addItem:[OWSTableItem disclosureItemWithText:namedContact.displayName
actionBlock:^{
[weakSelf
presentContactViewControllerForContact:namedContact.contact];
}]];
}
[contents addSection:section];
self.contents = contents;
[self.tableView reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// In case we're dismissing a CNContactViewController which requires default system appearance
[UIUtil applySignalAppearence];
}
#pragma mark - Actions
- (void)presentContactViewControllerForContact:(Contact *)contact
{
OWSAssert(contact);
OWSAssert(self.recipientId);
if (!self.contactsManager.supportsContactEditing) {
DDLogError(@"%@ Contact editing not supported", self.tag);
OWSAssert(NO);
return;
}
[self.contactsViewHelper presentContactViewControllerForRecipientId:self.recipientId
fromViewController:self
editImmediately:YES
addToExistingCnContact:contact.cnContact];
}
#pragma mark - Logging
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
}
@end
NS_ASSUME_NONNULL_END

@ -7,6 +7,7 @@
#import "ContactsViewHelper.h" #import "ContactsViewHelper.h"
#import "Environment.h" #import "Environment.h"
#import "FingerprintViewController.h" #import "FingerprintViewController.h"
#import "OWSAddToContactViewController.h"
#import "OWSAvatarBuilder.h" #import "OWSAvatarBuilder.h"
#import "OWSBlockingManager.h" #import "OWSBlockingManager.h"
#import "OWSContactsManager.h" #import "OWSContactsManager.h"
@ -149,7 +150,8 @@ NS_ASSUME_NONNULL_BEGIN
{ {
OWSAssert(self.thread); OWSAssert(self.thread);
if ([self.thread isKindOfClass:[TSContactThread class]] && self.contactsManager.supportsContactEditing) { if ([self.thread isKindOfClass:[TSContactThread class]] && self.contactsManager.supportsContactEditing
&& self.hasExistingContact) {
self.navigationItem.rightBarButtonItem = self.navigationItem.rightBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"EDIT_TXT", nil) [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"EDIT_TXT", nil)
style:UIBarButtonItemStylePlain style:UIBarButtonItemStylePlain
@ -158,10 +160,22 @@ NS_ASSUME_NONNULL_BEGIN
} }
} }
- (BOOL)hasExistingContact
{
OWSAssert([self.thread isKindOfClass:[TSContactThread class]]);
TSContactThread *contactThread = (TSContactThread *)self.thread;
NSString *recipientId = contactThread.contactIdentifier;
SignalAccount *signalAccount = [self.contactsViewHelper signalAccountForRecipientId:recipientId];
return signalAccount.contact;
}
#pragma mark - ContactEditingDelegate #pragma mark - ContactEditingDelegate
- (void)didFinishEditingContact - (void)didFinishEditingContact
{ {
[self updateTableContents];
DDLogDebug(@"%@ %s", self.tag, __PRETTY_FUNCTION__); DDLogDebug(@"%@ %s", self.tag, __PRETTY_FUNCTION__);
[self dismissViewControllerAnimated:NO completion:nil]; [self dismissViewControllerAnimated:NO completion:nil];
} }
@ -171,6 +185,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)contactViewController:(CNContactViewController *)viewController - (void)contactViewController:(CNContactViewController *)viewController
didCompleteWithContact:(nullable CNContact *)contact didCompleteWithContact:(nullable CNContact *)contact
{ {
[self updateTableContents];
if (contact) { if (contact) {
// Saving normally returns you to the "Show Contact" view // Saving normally returns you to the "Show Contact" view
// which we're not interested in, so we skip it here. There is // which we're not interested in, so we skip it here. There is
@ -232,27 +248,53 @@ NS_ASSUME_NONNULL_BEGIN
__weak OWSConversationSettingsTableViewController *weakSelf = self; __weak OWSConversationSettingsTableViewController *weakSelf = self;
// First section. // Main section.
OWSTableSection *firstSection = [OWSTableSection new]; OWSTableSection *mainSection = [OWSTableSection new];
firstSection.customHeaderView = [self firstSectionHeader]; mainSection.customHeaderView = [self mainSectionHeader];
firstSection.customHeaderHeight = @(100.f); mainSection.customHeaderHeight = @(100.f);
if ([self.thread isKindOfClass:[TSContactThread class]] && self.contactsManager.supportsContactEditing
&& !self.hasExistingContact) {
[mainSection addItem:[OWSTableItem itemWithCustomCellBlock:^{
return
[weakSelf disclosureCellWithName:NSLocalizedString(@"CONVERSATION_SETTINGS_NEW_CONTACT",
@"Label for 'new contact' button in conversation settings view.")
iconName:@"table_ic_new_contact"];
}
actionBlock:^{
[weakSelf presentContactViewController];
}]];
[mainSection addItem:[OWSTableItem itemWithCustomCellBlock:^{
return
[weakSelf disclosureCellWithName:NSLocalizedString(@"CONVERSATION_SETTINGS_ADD_TO_EXISTING_CONTACT",
@"Label for 'new contact' button in conversation settings view.")
iconName:@"table_ic_add_to_existing_contact"];
}
actionBlock:^{
TSContactThread *contactThread = (TSContactThread *)self.thread;
NSString *recipientId = contactThread.contactIdentifier;
OWSAddToContactViewController *view = [OWSAddToContactViewController new];
[view configureWithRecipientId:recipientId];
[weakSelf.navigationController pushViewController:view animated:YES];
}]];
}
if (!self.isGroupThread && self.thread.hasSafetyNumbers) { if (!self.isGroupThread && self.thread.hasSafetyNumbers) {
[firstSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ [mainSection addItem:[OWSTableItem itemWithCustomCellBlock:^{
return [weakSelf return [weakSelf
disclosureCellWithName: disclosureCellWithName:
NSLocalizedString(@"VERIFY_PRIVACY", NSLocalizedString(@"VERIFY_PRIVACY",
@"Label for button or row which allows users to verify the safety number of another user.") @"Label for button or row which allows users to verify the safety number of another user.")
iconName:@"table_ic_not_verified"]; iconName:@"table_ic_not_verified"];
} }
actionBlock:^{ actionBlock:^{
[weakSelf showVerificationView]; [weakSelf showVerificationView];
}]]; }]];
} }
[firstSection [mainSection
addItem:[OWSTableItem itemWithCustomCellBlock:^{ addItem:[OWSTableItem itemWithCustomCellBlock:^{
UITableViewCell *cell = [UITableViewCell new]; UITableViewCell *cell = [UITableViewCell new];
cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.selectionStyle = UITableViewCellSelectionStyleNone;
@ -305,7 +347,7 @@ NS_ASSUME_NONNULL_BEGIN
actionBlock:nil]]; actionBlock:nil]];
if (self.disappearingMessagesConfiguration.isEnabled) { if (self.disappearingMessagesConfiguration.isEnabled) {
[firstSection [mainSection
addItem:[OWSTableItem addItem:[OWSTableItem
itemWithCustomCellBlock:^{ itemWithCustomCellBlock:^{
UITableViewCell *cell = [UITableViewCell new]; UITableViewCell *cell = [UITableViewCell new];
@ -351,7 +393,7 @@ NS_ASSUME_NONNULL_BEGIN
actionBlock:nil]]; actionBlock:nil]];
} }
[contents addSection:firstSection]; [contents addSection:mainSection];
// Group settings section. // Group settings section.
@ -513,11 +555,11 @@ NS_ASSUME_NONNULL_BEGIN
return cell; return cell;
} }
- (UIView *)firstSectionHeader - (UIView *)mainSectionHeader
{ {
UIView *firstSectionHeader = [UIView new]; UIView *mainSectionHeader = [UIView new];
UIView *threadInfoView = [UIView new]; UIView *threadInfoView = [UIView new];
[firstSectionHeader addSubview:threadInfoView]; [mainSectionHeader addSubview:threadInfoView];
[threadInfoView autoPinWidthToSuperviewWithMargin:16.f]; [threadInfoView autoPinWidthToSuperviewWithMargin:16.f];
[threadInfoView autoPinHeightToSuperviewWithMargin:16.f]; [threadInfoView autoPinHeightToSuperviewWithMargin:16.f];
@ -596,12 +638,12 @@ NS_ASSUME_NONNULL_BEGIN
[lastTitleView autoPinEdgeToSuperviewEdge:ALEdgeBottom]; [lastTitleView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[firstSectionHeader [mainSectionHeader
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(conversationNameTouched:)]]; action:@selector(conversationNameTouched:)]];
firstSectionHeader.userInteractionEnabled = YES; mainSectionHeader.userInteractionEnabled = YES;
return firstSectionHeader; return mainSectionHeader;
} }
- (void)conversationNameTouched:(UIGestureRecognizer *)sender - (void)conversationNameTouched:(UIGestureRecognizer *)sender
@ -645,6 +687,8 @@ NS_ASSUME_NONNULL_BEGIN
// HACK to unselect rows when swiping back // HACK to unselect rows when swiping back
// http://stackoverflow.com/questions/19379510/uitableviewcell-doesnt-get-deselected-when-swiping-back-quickly // http://stackoverflow.com/questions/19379510/uitableviewcell-doesnt-get-deselected-when-swiping-back-quickly
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated]; [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
[self updateTableContents];
} }
- (void)viewWillDisappear:(BOOL)animated - (void)viewWillDisappear:(BOOL)animated

@ -19,6 +19,8 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification;
@property (nonnull, readonly) NSCache<NSString *, UIImage *> *avatarCache; @property (nonnull, readonly) NSCache<NSString *, UIImage *> *avatarCache;
@property (atomic, readonly) NSArray<Contact *> *allContacts;
@property (atomic, readonly) NSDictionary<NSString *, Contact *> *allContactsMap; @property (atomic, readonly) NSDictionary<NSString *, Contact *> *allContactsMap;
// signalAccountMap and signalAccounts hold the same data. // signalAccountMap and signalAccounts hold the same data.

@ -215,14 +215,10 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account
{ {
OWSAssert([NSThread isMainThread]); OWSAssert([NSThread isMainThread]);
// Preserve any existing values, so that contacts that have been removed NSMutableDictionary<NSString *, NSString *> *cachedAccountNameMap = [NSMutableDictionary new];
// from system contacts still show up properly in the app. NSMutableDictionary<NSString *, NSString *> *cachedFirstNameMap = [NSMutableDictionary new];
NSMutableDictionary<NSString *, NSString *> *cachedAccountNameMap NSMutableDictionary<NSString *, NSString *> *cachedLastNameMap = [NSMutableDictionary new];
= (self.cachedAccountNameMap ? [self.cachedAccountNameMap mutableCopy] : [NSMutableDictionary new]);
NSMutableDictionary<NSString *, NSString *> *cachedFirstNameMap
= (self.cachedFirstNameMap ? [self.cachedFirstNameMap mutableCopy] : [NSMutableDictionary new]);
NSMutableDictionary<NSString *, NSString *> *cachedLastNameMap
= (self.cachedLastNameMap ? [self.cachedLastNameMap mutableCopy] : [NSMutableDictionary new]);
for (SignalAccount *signalAccount in self.signalAccounts) { for (SignalAccount *signalAccount in self.signalAccounts) {
NSString *baseName NSString *baseName
= (signalAccount.contact.fullName.length > 0 ? signalAccount.contact.fullName : signalAccount.recipientId); = (signalAccount.contact.fullName.length > 0 ? signalAccount.contact.fullName : signalAccount.recipientId);

@ -292,6 +292,9 @@
/* title for conversation settings screen */ /* title for conversation settings screen */
"CONVERSATION_SETTINGS" = "Conversation Settings"; "CONVERSATION_SETTINGS" = "Conversation Settings";
/* Label for 'new contact' button in conversation settings view. */
"CONVERSATION_SETTINGS_ADD_TO_EXISTING_CONTACT" = "Add to Existing Contact";
/* table cell label in conversation settings */ /* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Block this user"; "CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Block this user";
@ -328,6 +331,9 @@
/* Indicates that this thread is muted until a given date or time. Embeds {{The date or time which the thread is muted until}}. */ /* Indicates that this thread is muted until a given date or time. Embeds {{The date or time which the thread is muted until}}. */
"CONVERSATION_SETTINGS_MUTED_UNTIL_FORMAT" = "until %@"; "CONVERSATION_SETTINGS_MUTED_UNTIL_FORMAT" = "until %@";
/* Label for 'new contact' button in conversation settings view. */
"CONVERSATION_SETTINGS_NEW_CONTACT" = "New Contact";
/* Label for button to unmute a thread. */ /* Label for button to unmute a thread. */
"CONVERSATION_SETTINGS_UNMUTE_ACTION" = "Unmute"; "CONVERSATION_SETTINGS_UNMUTE_ACTION" = "Unmute";

Loading…
Cancel
Save