Add “new contact” and “add to existing contact” buttons in 1:1 conversation settings view.
// FREEBIE
This commit is contained in:
parent
1e67bb52e3
commit
81555d1225
|
@ -76,6 +76,7 @@
|
|||
34B3F89F1E8DF5490035BE1A /* OWSTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */; };
|
||||
34B3F8A21E8EA6040035BE1A /* ViewControllerUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.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 */; };
|
||||
34D5CCA91EAE3D30005515DB /* GroupViewHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D5CCA81EAE3D30005515DB /* GroupViewHelper.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -980,6 +983,8 @@
|
|||
34B3F8581E8DF1700035BE1A /* NotificationSettingsViewController.h */,
|
||||
34B3F8591E8DF1700035BE1A /* NotificationSettingsViewController.m */,
|
||||
34B3F85A1E8DF1700035BE1A /* OversizeTextMessageViewController.swift */,
|
||||
34CCAF391F0C2748004084F4 /* OWSAddToContactViewController.h */,
|
||||
34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */,
|
||||
34533F161EA8D2070006114F /* OWSAudioAttachmentPlayer.h */,
|
||||
34533F171EA8D2070006114F /* OWSAudioAttachmentPlayer.m */,
|
||||
34B3F85B1E8DF1700035BE1A /* OWSConversationSettingsTableViewController.h */,
|
||||
|
@ -2229,6 +2234,7 @@
|
|||
34B3F8811E8DF1700035BE1A /* LockInteractionController.m in Sources */,
|
||||
3448BFCC1EDF0EA7005B2D69 /* OWSMessagesToolbarContentView.m in Sources */,
|
||||
3448BFD01EDF0EA7005B2D69 /* MessagesViewController.m in Sources */,
|
||||
34CCAF3B1F0C2748004084F4 /* OWSAddToContactViewController.m in Sources */,
|
||||
45F659731E1BD99C00444429 /* CallKitCallUIAdaptee.swift in Sources */,
|
||||
45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */,
|
||||
458DE9D61DEE3FD00071BB03 /* PeerConnectionClient.swift in Sources */,
|
||||
|
|
23
Signal/Images.xcassets/table_ic_add_to_existing_contact.imageset/Contents.json
vendored
Normal file
23
Signal/Images.xcassets/table_ic_add_to_existing_contact.imageset/Contents.json
vendored
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
BIN
Signal/Images.xcassets/table_ic_new_contact.imageset/table_ic_new_contact@1x.png
vendored
Normal file
BIN
Signal/Images.xcassets/table_ic_new_contact.imageset/table_ic_new_contact@1x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
Signal/Images.xcassets/table_ic_new_contact.imageset/table_ic_new_contact@2x.png
vendored
Normal file
BIN
Signal/Images.xcassets/table_ic_new_contact.imageset/table_ic_new_contact@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
BIN
Signal/Images.xcassets/table_ic_new_contact.imageset/table_ic_new_contact@3x.png
vendored
Normal file
BIN
Signal/Images.xcassets/table_ic_new_contact.imageset/table_ic_new_contact@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
|
@ -29,6 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@class OWSContactsManager;
|
||||
@class OWSBlockingManager;
|
||||
@class CNContact;
|
||||
|
||||
@interface ContactsViewHelper : NSObject
|
||||
|
||||
|
@ -70,6 +71,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController
|
||||
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
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -300,6 +300,17 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (void)presentContactViewControllerForRecipientId:(NSString *)recipientId
|
||||
fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController
|
||||
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];
|
||||
|
||||
|
@ -340,21 +351,49 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
|
||||
CNContactViewController *_Nullable contactViewController;
|
||||
if (signalAccount) {
|
||||
CNContact *_Nullable 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];
|
||||
CNContact *_Nullable cnContact = nil;
|
||||
if (addToExistingCnContact) {
|
||||
CNMutableContact *updatedContact = [addToExistingCnContact mutableCopy];
|
||||
NSMutableArray<CNLabeledValue *> *phoneNumbers
|
||||
= (updatedContact.phoneNumbers ? [updatedContact.phoneNumbers mutableCopy] : [NSMutableArray new]);
|
||||
// Only add recipientId as a phone number for the existing contact
|
||||
// if its not already present.
|
||||
BOOL hasPhoneNumber = NO;
|
||||
for (CNLabeledValue *existingPhoneNumber in phoneNumbers) {
|
||||
CNPhoneNumber *phoneNumber = existingPhoneNumber.value;
|
||||
if ([phoneNumber.stringValue isEqualToString:recipientId]) {
|
||||
hasPhoneNumber = YES;
|
||||
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) {
|
||||
|
|
|
@ -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 "Environment.h"
|
||||
#import "FingerprintViewController.h"
|
||||
#import "OWSAddToContactViewController.h"
|
||||
#import "OWSAvatarBuilder.h"
|
||||
#import "OWSBlockingManager.h"
|
||||
#import "OWSContactsManager.h"
|
||||
|
@ -149,7 +150,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
{
|
||||
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 =
|
||||
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"EDIT_TXT", nil)
|
||||
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
|
||||
|
||||
- (void)didFinishEditingContact
|
||||
{
|
||||
[self updateTableContents];
|
||||
|
||||
DDLogDebug(@"%@ %s", self.tag, __PRETTY_FUNCTION__);
|
||||
[self dismissViewControllerAnimated:NO completion:nil];
|
||||
}
|
||||
|
@ -171,6 +185,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (void)contactViewController:(CNContactViewController *)viewController
|
||||
didCompleteWithContact:(nullable CNContact *)contact
|
||||
{
|
||||
[self updateTableContents];
|
||||
|
||||
if (contact) {
|
||||
// Saving normally returns you to the "Show Contact" view
|
||||
// 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;
|
||||
|
||||
// First section.
|
||||
// Main section.
|
||||
|
||||
OWSTableSection *firstSection = [OWSTableSection new];
|
||||
OWSTableSection *mainSection = [OWSTableSection new];
|
||||
|
||||
firstSection.customHeaderView = [self firstSectionHeader];
|
||||
firstSection.customHeaderHeight = @(100.f);
|
||||
mainSection.customHeaderView = [self mainSectionHeader];
|
||||
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) {
|
||||
[firstSection addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
||||
[mainSection addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
||||
return [weakSelf
|
||||
disclosureCellWithName:
|
||||
NSLocalizedString(@"VERIFY_PRIVACY",
|
||||
@"Label for button or row which allows users to verify the safety number of another user.")
|
||||
iconName:@"table_ic_not_verified"];
|
||||
}
|
||||
actionBlock:^{
|
||||
[weakSelf showVerificationView];
|
||||
}]];
|
||||
actionBlock:^{
|
||||
[weakSelf showVerificationView];
|
||||
}]];
|
||||
}
|
||||
|
||||
[firstSection
|
||||
[mainSection
|
||||
addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
||||
UITableViewCell *cell = [UITableViewCell new];
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
@ -305,7 +347,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
actionBlock:nil]];
|
||||
|
||||
if (self.disappearingMessagesConfiguration.isEnabled) {
|
||||
[firstSection
|
||||
[mainSection
|
||||
addItem:[OWSTableItem
|
||||
itemWithCustomCellBlock:^{
|
||||
UITableViewCell *cell = [UITableViewCell new];
|
||||
|
@ -351,7 +393,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
actionBlock:nil]];
|
||||
}
|
||||
|
||||
[contents addSection:firstSection];
|
||||
[contents addSection:mainSection];
|
||||
|
||||
// Group settings section.
|
||||
|
||||
|
@ -513,11 +555,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return cell;
|
||||
}
|
||||
|
||||
- (UIView *)firstSectionHeader
|
||||
- (UIView *)mainSectionHeader
|
||||
{
|
||||
UIView *firstSectionHeader = [UIView new];
|
||||
UIView *mainSectionHeader = [UIView new];
|
||||
UIView *threadInfoView = [UIView new];
|
||||
[firstSectionHeader addSubview:threadInfoView];
|
||||
[mainSectionHeader addSubview:threadInfoView];
|
||||
[threadInfoView autoPinWidthToSuperviewWithMargin:16.f];
|
||||
[threadInfoView autoPinHeightToSuperviewWithMargin:16.f];
|
||||
|
||||
|
@ -596,12 +638,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
[lastTitleView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
|
||||
|
||||
[firstSectionHeader
|
||||
[mainSectionHeader
|
||||
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
|
||||
action:@selector(conversationNameTouched:)]];
|
||||
firstSectionHeader.userInteractionEnabled = YES;
|
||||
mainSectionHeader.userInteractionEnabled = YES;
|
||||
|
||||
return firstSectionHeader;
|
||||
return mainSectionHeader;
|
||||
}
|
||||
|
||||
- (void)conversationNameTouched:(UIGestureRecognizer *)sender
|
||||
|
@ -645,6 +687,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
// HACK to unselect rows when swiping back
|
||||
// http://stackoverflow.com/questions/19379510/uitableviewcell-doesnt-get-deselected-when-swiping-back-quickly
|
||||
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
|
||||
|
||||
[self updateTableContents];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
|
|
|
@ -19,6 +19,8 @@ extern NSString *const OWSContactsManagerSignalAccountsDidChangeNotification;
|
|||
|
||||
@property (nonnull, readonly) NSCache<NSString *, UIImage *> *avatarCache;
|
||||
|
||||
@property (atomic, readonly) NSArray<Contact *> *allContacts;
|
||||
|
||||
@property (atomic, readonly) NSDictionary<NSString *, Contact *> *allContactsMap;
|
||||
|
||||
// signalAccountMap and signalAccounts hold the same data.
|
||||
|
|
|
@ -215,14 +215,10 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account
|
|||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
// Preserve any existing values, so that contacts that have been removed
|
||||
// from system contacts still show up properly in the app.
|
||||
NSMutableDictionary<NSString *, NSString *> *cachedAccountNameMap
|
||||
= (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]);
|
||||
NSMutableDictionary<NSString *, NSString *> *cachedAccountNameMap = [NSMutableDictionary new];
|
||||
NSMutableDictionary<NSString *, NSString *> *cachedFirstNameMap = [NSMutableDictionary new];
|
||||
NSMutableDictionary<NSString *, NSString *> *cachedLastNameMap = [NSMutableDictionary new];
|
||||
|
||||
for (SignalAccount *signalAccount in self.signalAccounts) {
|
||||
NSString *baseName
|
||||
= (signalAccount.contact.fullName.length > 0 ? signalAccount.contact.fullName : signalAccount.recipientId);
|
||||
|
|
|
@ -292,6 +292,9 @@
|
|||
/* title for conversation settings screen */
|
||||
"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 */
|
||||
"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}}. */
|
||||
"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. */
|
||||
"CONVERSATION_SETTINGS_UNMUTE_ACTION" = "Unmute";
|
||||
|
||||
|
|
Loading…
Reference in New Issue