Edit 1:1 contact details

// FREEBIE
This commit is contained in:
Michael Kirk 2017-05-09 17:55:18 -04:00
parent 8871331cfa
commit 3754b6f264
5 changed files with 182 additions and 78 deletions

View File

@ -7,15 +7,24 @@ NS_ASSUME_NONNULL_BEGIN
@class ContactsViewHelper;
@class Contact;
@class SignalAccount;
@protocol CNContactViewControllerDelegate;
@protocol ContactsViewHelperDelegate <NSObject>
- (void)contactsViewHelperDidUpdateContacts;
@optional
- (BOOL)shouldHideLocalNumber;
@end
@protocol ContactEditingDelegate <CNContactViewControllerDelegate>
- (void)didFinishEditingContact;
@end
#pragma mark -
@class OWSContactsManager;
@ -46,6 +55,10 @@ NS_ASSUME_NONNULL_BEGIN
- (NSArray<Contact *> *)nonSignalContactsMatchingSearchString:(NSString *)searchText;
- (void)presentContactViewControllerForRecipientId:(NSString *)recipientId
fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController
editImmediately:(BOOL)shouldEditImmediately;
@end
NS_ASSUME_NONNULL_END

View File

@ -5,12 +5,15 @@
#import "ContactsViewHelper.h"
#import "ContactTableViewCell.h"
#import "Environment.h"
#import "Signal-Swift.h"
#import <SignalServiceKit/Contact.h>
#import <SignalServiceKit/OWSBlockingManager.h>
#import <SignalServiceKit/PhoneNumber.h>
#import <SignalServiceKit/SignalAccount.h>
#import <SignalServiceKit/TSAccountManager.h>
@import ContactsUI;
NS_ASSUME_NONNULL_BEGIN
@interface ContactsViewHelper ()
@ -95,7 +98,10 @@ NS_ASSUME_NONNULL_BEGIN
{
OWSAssert([NSThread isMainThread]);
if ([self.delegate shouldHideLocalNumber] && [self isCurrentUser:signalAccount]) {
if ([self.delegate respondsToSelector:@selector(shouldHideLocalNumber)] && [self.delegate shouldHideLocalNumber] &&
[self isCurrentUser:signalAccount]) {
return YES;
}
@ -277,6 +283,91 @@ NS_ASSUME_NONNULL_BEGIN
return _nonSignalContacts;
}
#pragma mark - Editing
- (void)presentContactViewControllerForRecipientId:(NSString *)recipientId
fromViewController:(UIViewController<ContactEditingDelegate> *)fromViewController
editImmediately:(BOOL)shouldEditImmediately
{
SignalAccount *signalAccount = [self signalAccountForRecipientId:recipientId];
if (!self.contactsManager.isSystemContactsAuthorized) {
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:NSLocalizedString(@"EDIT_CONTACT_WITHOUT_CONTACTS_PERMISSION_ALERT_TITLE", comment
: @"Alert title for when the user has just tried to edit a "
@"contacts after declining to give Signal contacts "
@"permissions")
message:NSLocalizedString(@"EDIT_CONTACT_WITHOUT_CONTACTS_PERMISSION_ALERT_BODY", comment
: @"Alert body for when the user has just tried to edit a "
@"contacts after declining to give Signal contacts "
@"permissions")
preferredStyle:UIAlertControllerStyleAlert];
[alertController
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"AB_PERMISSION_MISSING_ACTION_NOT_NOW",
@"Button text to dismiss missing contacts permission alert")
style:UIAlertActionStyleCancel
handler:nil]];
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OPEN_SETTINGS_BUTTON",
@"Button text which opens the settings app")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
[[UIApplication sharedApplication] openSystemSettings];
}]];
[fromViewController presentViewController:alertController animated:YES completion:nil];
return;
}
CNContactViewController *_Nullable contactViewController;
if (signalAccount) {
CNContact *_Nullable cnContact = signalAccount.contact.cnContact;
if (cnContact) {
if (shouldEditImmediately) {
// Not acutally 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];
} else {
contactViewController = [CNContactViewController viewControllerForContact:cnContact];
}
}
}
if (!contactViewController) {
CNMutableContact *newContact = [CNMutableContact new];
CNPhoneNumber *phoneNumber = [CNPhoneNumber phoneNumberWithStringValue:recipientId];
CNLabeledValue<CNPhoneNumber *> *labeledPhoneNumber =
[CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMain value:phoneNumber];
newContact.phoneNumbers = @[ labeledPhoneNumber ];
contactViewController = [CNContactViewController viewControllerForNewContact:newContact];
}
contactViewController.delegate = fromViewController;
contactViewController.allowsActions = NO;
contactViewController.allowsEditing = YES;
contactViewController.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
style:UIBarButtonItemStylePlain
target:fromViewController
action:@selector(didFinishEditingContact)];
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:contactViewController];
// We want the presentation to imply a "replacement" in this case.
if (shouldEditImmediately) {
navigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
}
[fromViewController presentViewController:navigationController animated:YES completion:nil];
// HACK otherwise CNContactViewController Navbar is shown as black.
// RADAR rdar://28433898 http://www.openradar.me/28433898
// CNContactViewController incompatible with opaque navigation bar
[UIUtil applyDefaultSystemAppearence];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -4,6 +4,7 @@
#import "OWSConversationSettingsTableViewController.h"
#import "BlockListUIUtils.h"
#import "ContactsViewHelper.h"
#import "Environment.h"
#import "FingerprintViewController.h"
#import "OWSAvatarBuilder.h"
@ -29,9 +30,11 @@
#import <SignalServiceKit/TSStorageManager.h>
#import <SignalServiceKit/TSThread.h>
@import ContactsUI;
NS_ASSUME_NONNULL_BEGIN
@interface OWSConversationSettingsTableViewController ()
@interface OWSConversationSettingsTableViewController () <ContactEditingDelegate, ContactsViewHelperDelegate>
@property (nonatomic) TSThread *thread;
@ -42,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
@property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper;
@property (nonatomic, readonly) UIImageView *avatarView;
@property (nonatomic, readonly) UILabel *disappearingMessagesDurationLabel;
@ -93,6 +96,8 @@ NS_ASSUME_NONNULL_BEGIN
_contactsManager = [Environment getCurrent].contactsManager;
_messageSender = [Environment getCurrent].messageSender;
_blockingManager = [OWSBlockingManager sharedManager];
_contactsViewHelper = [ContactsViewHelper new];
_contactsViewHelper.delegate = self;
}
- (NSString *)threadName
@ -115,6 +120,58 @@ NS_ASSUME_NONNULL_BEGIN
- (void)configureWithThread:(TSThread *)thread
{
self.thread = thread;
[self updateEditButton];
}
- (void)updateEditButton
{
OWSAssert(self.thread);
if ([self.thread isKindOfClass:[TSContactThread class]]) {
self.navigationItem.rightBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"EDIT_TXT", nil)
style:UIBarButtonItemStylePlain
target:self
action:@selector(didTapEditButton)];
}
}
- (void)didTapEditButton
{
if (![self.thread isKindOfClass:[TSContactThread class]]) {
DDLogError(@"%@ unexpected thread: %@ in %s", self.tag, self.thread, __PRETTY_FUNCTION__);
OWSAssert(NO);
return;
}
TSContactThread *contactThread = (TSContactThread *)self.thread;
[self.contactsViewHelper presentContactViewControllerForRecipientId:contactThread.contactIdentifier
fromViewController:self
editImmediately:YES];
}
#pragma mark - ContactEditingDelegate
- (void)didFinishEditingContact
{
DDLogDebug(@"%@ %s", self.tag, __PRETTY_FUNCTION__);
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - CNContactViewControllerDelegate
- (void)contactViewController:(CNContactViewController *)viewController
didCompleteWithContact:(nullable CNContact *)contact
{
DDLogDebug(@"%@ done editing contact.", self.tag);
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - ContactsViewHelperDelegate
- (void)contactsViewHelperDidUpdateContacts
{
[self updateTableContents];
}
#pragma mark - View Lifecycle
@ -568,6 +625,9 @@ NS_ASSUME_NONNULL_BEGIN
{
[super viewWillAppear:animated];
// In case we're dismissing a CNContactViewController which requires default system appearance
[UIUtil applySignalAppearence];
// 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];

View File

@ -22,7 +22,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface ShowGroupMembersViewController () <ContactsViewHelperDelegate, CNContactViewControllerDelegate>
@interface ShowGroupMembersViewController () <ContactsViewHelperDelegate, ContactEditingDelegate>
@property (nonatomic, readonly) TSGroupThread *thread;
@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper;
@ -265,74 +265,9 @@ NS_ASSUME_NONNULL_BEGIN
{
OWSAssert(recipientId.length > 0);
ContactsViewHelper *helper = self.contactsViewHelper;
SignalAccount *signalAccount = [helper signalAccountForRecipientId:recipientId];
if (!helper.contactsManager.isSystemContactsAuthorized) {
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:NSLocalizedString(@"EDIT_CONTACT_WITHOUT_CONTACTS_PERMISSION_ALERT_TITLE", comment
: @"Alert title for when the user has just tried to edit a "
@"contacts after declining to give Signal contacts "
@"permissions")
message:NSLocalizedString(@"EDIT_CONTACT_WITHOUT_CONTACTS_PERMISSION_ALERT_BODY", comment
: @"Alert body for when the user has just tried to edit a "
@"contacts after declining to give Signal contacts "
@"permissions")
preferredStyle:UIAlertControllerStyleAlert];
[alertController
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"AB_PERMISSION_MISSING_ACTION_NOT_NOW",
@"Button text to dismiss missing contacts permission alert")
style:UIAlertActionStyleCancel
handler:nil]];
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OPEN_SETTINGS_BUTTON",
@"Button text which opens the settings app")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
[[UIApplication sharedApplication] openSystemSettings];
}]];
[self presentViewController:alertController animated:YES completion:nil];
return;
}
CNContactViewController *_Nullable contactViewController;
if (signalAccount) {
CNContact *_Nullable cnContact = signalAccount.contact.cnContact;
if (cnContact) {
contactViewController = [CNContactViewController viewControllerForContact:cnContact];
}
}
if (!contactViewController) {
CNMutableContact *newContact = [CNMutableContact new];
CNPhoneNumber *phoneNumber = [CNPhoneNumber phoneNumberWithStringValue:recipientId];
CNLabeledValue<CNPhoneNumber *> *labeledPhoneNumber = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMain
value:phoneNumber];
newContact.phoneNumbers = @[labeledPhoneNumber];
contactViewController = [CNContactViewController viewControllerForNewContact:newContact];
}
contactViewController.delegate = self;
contactViewController.allowsActions = NO;
contactViewController.allowsEditing = YES;
contactViewController.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
style:UIBarButtonItemStylePlain
target:self
action:@selector(dismissPressed)];
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:contactViewController];
[self presentViewController:navigationController animated:YES completion:nil];
// HACK otherwise CNContactViewController Navbar is shown as black.
// RADAR rdar://28433898 http://www.openradar.me/28433898
// CNContactViewController incompatible with opaque navigation bar
[UIUtil applyDefaultSystemAppearence];
[self.contactsViewHelper presentContactViewControllerForRecipientId:recipientId
fromViewController:self
editImmediately:NO];
}
- (void)showConversationViewForRecipientId:(NSString *)recipientId
@ -347,12 +282,6 @@ NS_ASSUME_NONNULL_BEGIN
[Environment callUserWithIdentifier:recipientId];
}
- (void)dismissPressed
{
DDLogDebug(@"%@ %s", self.tag, __PRETTY_FUNCTION__);
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - ContactsViewHelperDelegate
- (void)contactsViewHelperDidUpdateContacts
@ -365,6 +294,14 @@ NS_ASSUME_NONNULL_BEGIN
return YES;
}
#pragma mark - ContactEditingDelegate
- (void)didFinishEditingContact
{
DDLogDebug(@"%@ %s", self.tag, __PRETTY_FUNCTION__);
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - CNContactViewControllerDelegate
- (void)contactViewController:(CNContactViewController *)viewController

View File

@ -364,6 +364,9 @@
/* Short name for edit menu item to share contents of media message. */
"EDIT_ITEM_SHARE_ACTION" = "Share";
/* No comment provided by engineer. */
"EDIT_TXT" = "Edit";
/* body of email sent to contacts when inviting to install Signal. Embeds {{link to install Signal}} and {{link to WhisperSystems home page}} */
"EMAIL_INVITE_BODY" = "Hey,\n\nLately I've been using Signal to keep the conversations on my iPhone private. I'd like you to install it too, so we can be confident that only you and I can read our messages or hear our calls.\n\nSignal is available for iPhones and Android. Get it here: %@\n\nSignal works like your existing messaging app. We can send pictures and video, make calls, and start group chats. The best part is, no one else can see any of it, not even the people who make Signal!\n\nYou can read more about Open Whisper Systems, the people who make Signal, here: %@";