2014-10-29 21:58:58 +01:00
|
|
|
//
|
2017-02-01 17:43:46 +01:00
|
|
|
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
2014-10-29 21:58:58 +01:00
|
|
|
//
|
|
|
|
|
2015-01-30 23:11:35 +01:00
|
|
|
#import "MessageComposeTableViewController.h"
|
2015-01-14 22:30:01 +01:00
|
|
|
|
|
|
|
#import <MessageUI/MessageUI.h>
|
2014-10-29 21:58:58 +01:00
|
|
|
|
|
|
|
#import "ContactTableViewCell.h"
|
2015-12-22 12:45:09 +01:00
|
|
|
#import "ContactsUpdater.h"
|
|
|
|
#import "Environment.h"
|
2016-11-18 23:11:56 +01:00
|
|
|
#import "OWSContactsSearcher.h"
|
|
|
|
#import "Signal-Swift.h"
|
2015-01-14 22:30:01 +01:00
|
|
|
#import "UIColor+OWS.h"
|
2015-01-30 09:49:40 +01:00
|
|
|
#import "UIUtil.h"
|
2017-04-03 16:45:48 +02:00
|
|
|
#import <SignalServiceKit/OWSBlockingManager.h>
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
@interface MessageComposeTableViewController () <UISearchBarDelegate,
|
|
|
|
UISearchResultsUpdating,
|
2016-06-28 06:36:42 +02:00
|
|
|
MFMessageComposeViewControllerDelegate>
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2017-04-03 16:45:48 +02:00
|
|
|
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
|
|
|
|
@property (nonatomic, readonly) NSArray<NSString *> *blockedPhoneNumbers;
|
|
|
|
|
2017-02-01 17:43:46 +01:00
|
|
|
@property (nonatomic) IBOutlet UITableViewCell *inviteCell;
|
|
|
|
@property (nonatomic) IBOutlet OWSNoSignalContactsView *noSignalContactsView;
|
2016-11-18 23:11:56 +01:00
|
|
|
|
2017-02-01 17:43:46 +01:00
|
|
|
@property (nonatomic) UISearchController *searchController;
|
|
|
|
@property (nonatomic) UIActivityIndicatorView *activityIndicator;
|
|
|
|
@property (nonatomic) UIView *loadingBackgroundView;
|
2016-11-30 18:05:05 +01:00
|
|
|
|
2017-03-15 21:56:26 +01:00
|
|
|
@property (nonatomic, copy) NSArray<Contact *> *contacts;
|
|
|
|
@property (nonatomic, copy) NSArray<Contact *> *searchResults;
|
2016-11-18 23:11:56 +01:00
|
|
|
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
2015-01-30 23:11:35 +01:00
|
|
|
|
2017-03-15 21:56:26 +01:00
|
|
|
// A list of possible phone numbers parsed from the search text as
|
|
|
|
// E164 values.
|
2017-03-16 18:11:05 +01:00
|
|
|
@property (nonatomic) NSArray<NSString *> *searchPhoneNumbers;
|
2017-03-15 21:56:26 +01:00
|
|
|
// A list of possible phone numbers parsed from the search text
|
|
|
|
// that correspond to known accounts as E164 values.
|
2017-03-16 18:11:05 +01:00
|
|
|
@property (nonatomic) NSArray<NSString *> *searchPhoneNumberWithAccounts;
|
2017-02-02 17:48:41 +01:00
|
|
|
// This dictionary is used to cache the set of phone numbers
|
|
|
|
// which are known to correspond to Signal accounts.
|
2017-02-03 04:46:10 +01:00
|
|
|
@property (nonatomic, nonnull, readonly) NSMutableSet *phoneNumberAccountSet;
|
2017-02-02 17:48:41 +01:00
|
|
|
|
2017-02-17 04:47:12 +01:00
|
|
|
@property (nonatomic) BOOL isNoContactsViewVisible;
|
2017-03-28 22:40:00 +02:00
|
|
|
@property (nonatomic) UIBarButtonItem *createGroupBarButtonItem;
|
2017-02-01 17:43:46 +01:00
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
@end
|
|
|
|
|
2017-02-02 17:48:41 +01:00
|
|
|
// The "special" sections are used to display (at most) one of three cells:
|
|
|
|
//
|
|
|
|
// * "New conversation for non-contact" if user has entered a phone
|
|
|
|
// number which corresponds to a signal account, or:
|
|
|
|
// * "Send invite via SMS" if user has entered a phone number
|
|
|
|
// which is not known to correspond to a signal account, or:
|
|
|
|
// * "Invite contacts" if the invite flow is available, or:
|
|
|
|
// * Nothing, otherwise.
|
2017-02-03 04:46:10 +01:00
|
|
|
typedef NS_ENUM(NSInteger, AdvancedSettingsTableViewControllerSection) {
|
|
|
|
MessageComposeTableViewControllerSectionInviteNonContactConversation = 0,
|
|
|
|
MessageComposeTableViewControllerSectionInviteViaSMS,
|
|
|
|
MessageComposeTableViewControllerSectionInviteFlow,
|
|
|
|
MessageComposeTableViewControllerSectionContacts,
|
|
|
|
MessageComposeTableViewControllerSection_Count // meta section
|
|
|
|
};
|
2016-11-18 23:11:56 +01:00
|
|
|
|
|
|
|
NSString *const MessageComposeTableViewControllerCellContact = @"ContactTableViewCell";
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
@implementation MessageComposeTableViewController
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
|
|
|
|
{
|
|
|
|
self = [super initWithCoder:aDecoder];
|
|
|
|
if (!self) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
_contactsManager = [Environment getCurrent].contactsManager;
|
2017-02-03 04:46:10 +01:00
|
|
|
_phoneNumberAccountSet = [NSMutableSet set];
|
2017-04-03 16:45:48 +02:00
|
|
|
|
|
|
|
_blockingManager = [OWSBlockingManager sharedManager];
|
|
|
|
_blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers];
|
|
|
|
|
2017-02-08 17:59:02 +01:00
|
|
|
[self observeNotifications];
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype)init
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (!self) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
_contactsManager = [Environment getCurrent].contactsManager;
|
|
|
|
|
2017-02-08 17:59:02 +01:00
|
|
|
[self observeNotifications];
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2017-02-08 17:59:02 +01:00
|
|
|
- (void)observeNotifications
|
|
|
|
{
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
2017-02-08 20:25:31 +01:00
|
|
|
selector:@selector(signalRecipientsDidChange:)
|
|
|
|
name:OWSContactsManagerSignalRecipientsDidChangeNotification
|
2017-02-08 17:59:02 +01:00
|
|
|
object:nil];
|
2017-04-03 16:45:48 +02:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(blockedPhoneNumbersDidChange:)
|
|
|
|
name:kNSNotificationName_BlockedPhoneNumbersDidChange
|
|
|
|
object:nil];
|
2017-02-08 17:59:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
}
|
|
|
|
|
2017-02-08 20:25:31 +01:00
|
|
|
- (void)signalRecipientsDidChange:(NSNotification *)notification {
|
2017-04-03 16:45:48 +02:00
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self updateContacts];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blockedPhoneNumbersDidChange:(id)notification
|
|
|
|
{
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
_blockedPhoneNumbers = [_blockingManager blockedPhoneNumbers];
|
|
|
|
|
|
|
|
[self updateContacts];
|
|
|
|
});
|
2017-02-08 17:59:02 +01:00
|
|
|
}
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
- (void)viewDidLoad {
|
|
|
|
[super viewDidLoad];
|
2015-04-30 15:03:57 +02:00
|
|
|
[self.navigationController.navigationBar setTranslucent:NO];
|
2017-03-28 22:40:00 +02:00
|
|
|
|
|
|
|
self.createGroupBarButtonItem = self.navigationItem.rightBarButtonItem;
|
2017-01-31 04:59:39 +01:00
|
|
|
self.navigationItem.rightBarButtonItem.accessibilityLabel = NSLocalizedString(
|
|
|
|
@"CREATE_NEW_GROUP", @"Accessibility label for the create group new group button");
|
|
|
|
|
2016-11-23 17:07:38 +01:00
|
|
|
self.tableView.estimatedRowHeight = (CGFloat)60.0;
|
|
|
|
self.tableView.rowHeight = UITableViewAutomaticDimension;
|
|
|
|
|
2017-04-03 16:45:48 +02:00
|
|
|
self.contacts = [self filteredContacts];
|
2016-06-28 06:36:42 +02:00
|
|
|
self.searchResults = self.contacts;
|
2015-01-27 02:20:11 +01:00
|
|
|
[self initializeSearch];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
self.searchController.searchBar.hidden = NO;
|
2015-02-12 23:52:49 +01:00
|
|
|
self.searchController.searchBar.backgroundColor = [UIColor whiteColor];
|
2016-11-18 23:11:56 +01:00
|
|
|
self.inviteCell.textLabel.text = NSLocalizedString(
|
|
|
|
@"INVITE_FRIENDS_CONTACT_TABLE_BUTTON", @"Text for button at the top of the contact picker");
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
|
2015-01-30 23:11:35 +01:00
|
|
|
[self createLoadingAndBackgroundViews];
|
2015-02-18 23:21:03 +01:00
|
|
|
self.title = NSLocalizedString(@"MESSAGE_COMPOSEVIEW_TITLE", @"");
|
2015-01-30 23:11:35 +01:00
|
|
|
}
|
|
|
|
|
2017-02-17 04:34:20 +01:00
|
|
|
- (void)viewWillAppear:(BOOL)animated {
|
|
|
|
[super viewWillAppear:animated];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2017-02-17 04:47:12 +01:00
|
|
|
[self showEmptyBackgroundViewIfNecessary];
|
2015-01-30 23:11:35 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (UILabel *)createLabelWithFirstLine:(NSString *)firstLine andSecondLine:(NSString *)secondLine {
|
|
|
|
UILabel *label = [[UILabel alloc] init];
|
|
|
|
label.textColor = [UIColor grayColor];
|
|
|
|
label.font = [UIFont ows_regularFontWithSize:18.f];
|
2015-01-30 23:11:35 +01:00
|
|
|
label.textAlignment = NSTextAlignmentCenter;
|
|
|
|
label.numberOfLines = 4;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
NSMutableAttributedString *fullLabelString =
|
|
|
|
[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@", firstLine, secondLine]];
|
|
|
|
|
|
|
|
[fullLabelString addAttribute:NSFontAttributeName
|
|
|
|
value:[UIFont ows_boldFontWithSize:15.f]
|
|
|
|
range:NSMakeRange(0, firstLine.length)];
|
|
|
|
[fullLabelString addAttribute:NSFontAttributeName
|
|
|
|
value:[UIFont ows_regularFontWithSize:14.f]
|
|
|
|
range:NSMakeRange(firstLine.length + 1, secondLine.length)];
|
|
|
|
[fullLabelString addAttribute:NSForegroundColorAttributeName
|
|
|
|
value:[UIColor blackColor]
|
|
|
|
range:NSMakeRange(0, firstLine.length)];
|
|
|
|
[fullLabelString addAttribute:NSForegroundColorAttributeName
|
|
|
|
value:[UIColor ows_darkGrayColor]
|
|
|
|
range:NSMakeRange(firstLine.length + 1, secondLine.length)];
|
2015-01-30 23:11:35 +01:00
|
|
|
label.attributedText = fullLabelString;
|
2015-12-22 12:45:09 +01:00
|
|
|
// 250, 66, 140
|
|
|
|
[label setFrame:CGRectMake([self marginSize], 100 + 140, [self contentWidth], 66)];
|
2015-01-30 23:11:35 +01:00
|
|
|
return label;
|
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)createLoadingAndBackgroundViews {
|
|
|
|
// This will be further tweaked per design recs. It must currently be hardcoded (or we can place in separate .xib I
|
|
|
|
// suppose) as the controller must be a TableViewController to have access to the native pull to refresh
|
|
|
|
// capabilities. That means we can't do a UIView in the storyboard
|
|
|
|
_loadingBackgroundView = [[UIView alloc] initWithFrame:self.tableView.frame];
|
2015-01-27 02:20:11 +01:00
|
|
|
UIImageView *loadingImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"uiEmpty"]];
|
|
|
|
[loadingImageView setBackgroundColor:[UIColor whiteColor]];
|
|
|
|
[loadingImageView setContentMode:UIViewContentModeCenter];
|
2015-12-22 12:45:09 +01:00
|
|
|
[loadingImageView setFrame:CGRectMake(self.tableView.frame.size.width / 2.0f - 115.0f / 2.0f, 100, 115, 110)];
|
2015-01-30 23:11:35 +01:00
|
|
|
loadingImageView.contentMode = UIViewContentModeCenter;
|
|
|
|
loadingImageView.contentMode = UIViewContentModeScaleAspectFit;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
UIActivityIndicatorView *loadingProgressView =
|
|
|
|
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
|
|
|
[loadingProgressView
|
|
|
|
setFrame:CGRectMake(self.tableView.frame.size.width / 2.0f - loadingProgressView.frame.size.width / 2.0f,
|
|
|
|
100 + 110 / 2.0f - loadingProgressView.frame.size.height / 2.0f,
|
|
|
|
loadingProgressView.frame.size.width,
|
|
|
|
loadingProgressView.frame.size.height)];
|
2015-01-30 23:11:35 +01:00
|
|
|
[loadingProgressView setHidesWhenStopped:NO];
|
|
|
|
[loadingProgressView startAnimating];
|
2015-12-22 12:45:09 +01:00
|
|
|
UILabel *loadingLabel = [self createLabelWithFirstLine:NSLocalizedString(@"LOADING_CONTACTS_LABEL_LINE1", @"")
|
|
|
|
andSecondLine:NSLocalizedString(@"LOADING_CONTACTS_LABEL_LINE2", @"")];
|
2015-01-30 23:11:35 +01:00
|
|
|
[_loadingBackgroundView addSubview:loadingImageView];
|
|
|
|
[_loadingBackgroundView addSubview:loadingProgressView];
|
|
|
|
[_loadingBackgroundView addSubview:loadingLabel];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2017-02-02 17:48:41 +01:00
|
|
|
UIButton *inviteButton = self.noSignalContactsView.inviteButton;
|
|
|
|
[inviteButton addTarget:self
|
|
|
|
action:@selector(presentInviteFlow)
|
|
|
|
forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
[inviteButton setTitleColor:[UIColor ows_materialBlueColor]
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[inviteButton.titleLabel setFont:[UIFont ows_regularFontWithSize:17.f]];
|
|
|
|
|
|
|
|
UIButton *searchByPhoneNumberButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
[searchByPhoneNumberButton setTitle:NSLocalizedString(@"NO_CONTACTS_SEARCH_BY_PHONE_NUMBER",
|
|
|
|
@"Label for a button that lets users search for contacts by phone number")
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[searchByPhoneNumberButton setTitleColor:[UIColor ows_materialBlueColor]
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[searchByPhoneNumberButton.titleLabel setFont:[UIFont ows_regularFontWithSize:17.f]];
|
|
|
|
[inviteButton.superview addSubview:searchByPhoneNumberButton];
|
|
|
|
[searchByPhoneNumberButton autoHCenterInSuperview];
|
|
|
|
[searchByPhoneNumberButton autoPinEdge:ALEdgeTop
|
|
|
|
toEdge:ALEdgeBottom
|
|
|
|
ofView:inviteButton
|
|
|
|
withOffset:20];
|
|
|
|
[searchByPhoneNumberButton addTarget:self
|
|
|
|
action:@selector(hideBackgroundView)
|
|
|
|
forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)hideBackgroundView {
|
2017-02-17 04:47:12 +01:00
|
|
|
[[Environment preferences] setHasDeclinedNoContactsView:YES];
|
2017-02-02 17:48:41 +01:00
|
|
|
|
2017-02-17 04:47:12 +01:00
|
|
|
[self showEmptyBackgroundViewIfNecessary];
|
2016-11-30 18:05:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)presentInviteFlow
|
|
|
|
{
|
|
|
|
OWSInviteFlow *inviteFlow =
|
|
|
|
[[OWSInviteFlow alloc] initWithPresentingViewController:self contactsManager:self.contactsManager];
|
|
|
|
[self presentViewController:inviteFlow.actionSheetController animated:YES completion:nil];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)showLoadingBackgroundView:(BOOL)show {
|
2017-02-17 04:47:12 +01:00
|
|
|
if (show) {
|
2015-01-30 23:11:35 +01:00
|
|
|
self.searchController.searchBar.hidden = YES;
|
2015-12-22 12:45:09 +01:00
|
|
|
self.tableView.backgroundView = _loadingBackgroundView;
|
|
|
|
self.tableView.backgroundView.opaque = YES;
|
|
|
|
} else {
|
2015-01-30 23:11:35 +01:00
|
|
|
self.searchController.searchBar.hidden = NO;
|
2015-12-22 12:45:09 +01:00
|
|
|
self.tableView.backgroundView = nil;
|
2015-01-30 23:11:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-17 04:47:12 +01:00
|
|
|
- (void)showEmptyBackgroundViewIfNecessary {
|
|
|
|
self.isNoContactsViewVisible = ([self.contacts count] == 0 &&
|
|
|
|
![[Environment preferences] hasDeclinedNoContactsView]);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setIsNoContactsViewVisible:(BOOL)isNoContactsViewVisible {
|
|
|
|
if (isNoContactsViewVisible == _isNoContactsViewVisible) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_isNoContactsViewVisible = isNoContactsViewVisible;
|
|
|
|
|
|
|
|
if (isNoContactsViewVisible) {
|
2015-01-30 23:11:35 +01:00
|
|
|
self.searchController.searchBar.hidden = YES;
|
2016-11-30 18:05:05 +01:00
|
|
|
self.tableView.backgroundView = self.noSignalContactsView;
|
2015-12-22 12:45:09 +01:00
|
|
|
self.tableView.backgroundView.opaque = YES;
|
2017-03-28 22:40:00 +02:00
|
|
|
self.navigationItem.rightBarButtonItem = nil;
|
2015-12-22 12:45:09 +01:00
|
|
|
} else {
|
2015-01-30 23:11:35 +01:00
|
|
|
self.searchController.searchBar.hidden = NO;
|
2015-12-22 12:45:09 +01:00
|
|
|
self.tableView.backgroundView = nil;
|
2017-03-28 22:40:00 +02:00
|
|
|
self.navigationItem.rightBarButtonItem = self.createGroupBarButtonItem;
|
2017-03-15 21:56:26 +01:00
|
|
|
}
|
2017-03-28 22:40:00 +02:00
|
|
|
|
2017-02-17 04:47:12 +01:00
|
|
|
[self.tableView reloadData];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Initializers
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)initializeSearch {
|
2014-10-29 21:58:58 +01:00
|
|
|
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
self.searchController.searchResultsUpdater = self;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
self.searchController.dimsBackgroundDuringPresentation = NO;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
self.searchController.hidesNavigationBarDuringPresentation = NO;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x,
|
|
|
|
self.searchController.searchBar.frame.origin.y,
|
|
|
|
self.searchController.searchBar.frame.size.width,
|
|
|
|
44.0);
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
self.tableView.tableHeaderView = self.searchController.searchBar;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal;
|
2015-12-22 12:45:09 +01:00
|
|
|
self.searchController.searchBar.delegate = self;
|
|
|
|
self.searchController.searchBar.placeholder = NSLocalizedString(@"SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT", @"");
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - UISearchResultsUpdating
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
|
2014-10-29 21:58:58 +01:00
|
|
|
NSString *searchString = [self.searchController.searchBar text];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
[self filterContentForSearchText:searchString];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
[self.tableView reloadData];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - UISearchBarDelegate
|
|
|
|
|
|
|
|
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope {
|
|
|
|
[self updateSearchResultsForSearchController:self.searchController];
|
2015-01-14 22:30:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Filter
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
- (void)filterContentForSearchText:(NSString *)searchText
|
|
|
|
{
|
2016-06-28 17:57:35 +02:00
|
|
|
OWSContactsSearcher *contactsSearcher = [[OWSContactsSearcher alloc] initWithContacts: self.contacts];
|
|
|
|
self.searchResults = [contactsSearcher filterWithString:searchText];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2017-03-16 18:11:05 +01:00
|
|
|
NSMutableArray<NSString *> *searchPhoneNumbers = [NSMutableArray new];
|
2017-03-15 21:56:26 +01:00
|
|
|
for (PhoneNumber *phoneNumber in [PhoneNumber tryParsePhoneNumbersFromsUserSpecifiedText:searchText
|
|
|
|
clientPhoneNumber:[TSStorageManager localNumber]]) {
|
|
|
|
[searchPhoneNumbers addObject:phoneNumber.toE164];
|
|
|
|
}
|
2015-01-14 22:30:01 +01:00
|
|
|
// text to a non-signal number if we have no results and a valid phone #
|
2017-03-15 21:56:26 +01:00
|
|
|
if (self.searchResults.count == 0 && searchText.length > 8 && searchPhoneNumbers.count > 0) {
|
|
|
|
self.searchPhoneNumbers = searchPhoneNumbers;
|
2017-02-02 17:48:41 +01:00
|
|
|
// Kick off account lookup if necessary.
|
2017-03-15 21:56:26 +01:00
|
|
|
[self checkForAccountsForPhoneNumbers:searchPhoneNumbers];
|
2015-01-14 22:30:01 +01:00
|
|
|
} else {
|
2017-03-15 21:56:26 +01:00
|
|
|
_searchPhoneNumbers = nil;
|
2015-01-14 22:30:01 +01:00
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2017-03-15 21:56:26 +01:00
|
|
|
- (void)checkForAccountsForPhoneNumbers:(NSArray *)phoneNumbers
|
2017-02-02 17:48:41 +01:00
|
|
|
{
|
2017-03-15 21:56:26 +01:00
|
|
|
NSMutableArray<NSString *> *unknownPhoneNumbers = [NSMutableArray new];
|
|
|
|
for (NSString *phoneNumber in phoneNumbers) {
|
|
|
|
if (![self.phoneNumberAccountSet containsObject:phoneNumber]) {
|
|
|
|
[unknownPhoneNumbers addObject:phoneNumber];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ([unknownPhoneNumbers count] < 1) {
|
2017-02-02 17:57:59 +01:00
|
|
|
return;
|
2017-02-01 17:43:46 +01:00
|
|
|
}
|
|
|
|
|
2017-02-02 17:48:41 +01:00
|
|
|
__weak MessageComposeTableViewController *weakSelf = self;
|
2017-03-15 21:56:26 +01:00
|
|
|
[[ContactsUpdater sharedUpdater] lookupIdentifiers:unknownPhoneNumbers
|
|
|
|
success:^(NSArray<SignalRecipient *> *recipients) {
|
2017-02-02 17:48:41 +01:00
|
|
|
MessageComposeTableViewController *strongSelf = weakSelf;
|
|
|
|
if (!strongSelf) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-15 21:56:26 +01:00
|
|
|
NSUInteger oldCount = strongSelf.phoneNumberAccountSet.count;
|
|
|
|
for (SignalRecipient *recipient in recipients) {
|
|
|
|
NSString *phoneNumber = recipient.uniqueId;
|
2017-02-02 17:48:41 +01:00
|
|
|
[strongSelf.phoneNumberAccountSet addObject:phoneNumber];
|
2017-03-15 21:56:26 +01:00
|
|
|
}
|
|
|
|
if (oldCount != strongSelf.phoneNumberAccountSet.count) {
|
|
|
|
[strongSelf ensureSearchPhoneNumberWithAccounts];
|
2017-02-02 17:48:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
failure:^(NSError *error) {
|
2017-02-02 17:57:59 +01:00
|
|
|
// Ignore.
|
2017-02-02 17:48:41 +01:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2017-03-16 18:11:05 +01:00
|
|
|
- (void)setSearchPhoneNumbers:(NSArray<NSString *> *)searchPhoneNumbers {
|
2017-03-15 21:56:26 +01:00
|
|
|
if ([_searchPhoneNumbers isEqual:searchPhoneNumbers]) {
|
2017-02-02 17:48:41 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-03-15 21:56:26 +01:00
|
|
|
|
|
|
|
_searchPhoneNumbers = searchPhoneNumbers;
|
|
|
|
|
|
|
|
[self ensureSearchPhoneNumberWithAccounts];
|
|
|
|
|
|
|
|
[self.tableView reloadData];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)ensureSearchPhoneNumberWithAccounts {
|
2017-03-16 18:11:05 +01:00
|
|
|
NSMutableArray<NSString *> *searchPhoneNumberWithAccounts = [NSMutableArray new];
|
2017-03-15 21:56:26 +01:00
|
|
|
for (NSString *phoneNumber in self.searchPhoneNumbers) {
|
2017-03-16 18:11:05 +01:00
|
|
|
if ([self.phoneNumberAccountSet containsObject:phoneNumber] &&
|
|
|
|
![searchPhoneNumberWithAccounts containsObject:phoneNumber]) {
|
2017-03-15 21:56:26 +01:00
|
|
|
[searchPhoneNumberWithAccounts addObject:phoneNumber];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.searchPhoneNumberWithAccounts = searchPhoneNumberWithAccounts;
|
|
|
|
}
|
2017-02-02 17:48:41 +01:00
|
|
|
|
2017-03-16 18:11:05 +01:00
|
|
|
- (void)setSearchPhoneNumberWithAccounts:(NSArray<NSString *> *)searchPhoneNumberWithAccounts {
|
2017-03-15 21:56:26 +01:00
|
|
|
if ([_searchPhoneNumberWithAccounts isEqual:searchPhoneNumberWithAccounts]) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_searchPhoneNumberWithAccounts = searchPhoneNumberWithAccounts;
|
2017-02-01 17:43:46 +01:00
|
|
|
|
|
|
|
[self.tableView reloadData];
|
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
#pragma mark - Send Normal Text to Unknown Contact
|
|
|
|
|
2017-03-15 21:56:26 +01:00
|
|
|
- (void)sendTextToPhoneNumber:(NSString *)phoneNumber {
|
|
|
|
OWSAssert([phoneNumber length] > 0);
|
2015-02-18 23:21:03 +01:00
|
|
|
NSString *confirmMessage = NSLocalizedString(@"SEND_SMS_CONFIRM_TITLE", @"");
|
2017-03-15 21:56:26 +01:00
|
|
|
if ([phoneNumber length] > 0) {
|
|
|
|
confirmMessage = [[NSLocalizedString(@"SEND_SMS_INVITE_TITLE", @"")
|
|
|
|
stringByAppendingString:phoneNumber]
|
|
|
|
stringByAppendingString:NSLocalizedString(@"QUESTIONMARK_PUNCTUATION", @"")];
|
2015-01-30 23:11:35 +01:00
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
UIAlertController *alertController =
|
|
|
|
[UIAlertController alertControllerWithTitle:NSLocalizedString(@"CONFIRMATION_TITLE", @"")
|
|
|
|
message:confirmMessage
|
|
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
|
2016-05-23 20:39:30 +02:00
|
|
|
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
2015-12-22 12:45:09 +01:00
|
|
|
style:UIAlertActionStyleCancel
|
|
|
|
handler:^(UIAlertAction *action) {
|
|
|
|
DDLogDebug(@"Cancel action");
|
|
|
|
}];
|
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
UIAlertAction *okAction = [UIAlertAction
|
2015-12-22 12:45:09 +01:00
|
|
|
actionWithTitle:NSLocalizedString(@"OK", @"")
|
|
|
|
style:UIAlertActionStyleDefault
|
|
|
|
handler:^(UIAlertAction *action) {
|
|
|
|
[self.searchController setActive:NO];
|
|
|
|
|
2016-05-23 20:39:30 +02:00
|
|
|
if ([MFMessageComposeViewController canSendText]) {
|
2015-12-22 12:45:09 +01:00
|
|
|
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
|
|
|
|
picker.messageComposeDelegate = self;
|
|
|
|
|
2017-03-15 21:56:26 +01:00
|
|
|
picker.recipients = @[phoneNumber,];
|
2015-12-22 12:45:09 +01:00
|
|
|
picker.body = [NSLocalizedString(@"SMS_INVITE_BODY", @"")
|
|
|
|
stringByAppendingString:
|
|
|
|
@" https://itunes.apple.com/us/app/signal-private-messenger/id874139669?mt=8"];
|
|
|
|
[self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]];
|
|
|
|
} else {
|
|
|
|
UIAlertView *notPermitted =
|
|
|
|
[[UIAlertView alloc] initWithTitle:@""
|
|
|
|
message:NSLocalizedString(@"UNSUPPORTED_FEATURE_ERROR", @"")
|
|
|
|
delegate:nil
|
|
|
|
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
|
|
|
otherButtonTitles:nil];
|
|
|
|
[notPermitted show];
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
[alertController addAction:cancelAction];
|
|
|
|
[alertController addAction:okAction];
|
|
|
|
self.searchController.searchBar.text = @"";
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2016-05-17 00:52:11 +02:00
|
|
|
//must dismiss search controller before presenting alert.
|
2016-05-23 20:39:30 +02:00
|
|
|
if ([self presentedViewController]) {
|
|
|
|
[self dismissViewControllerAnimated:YES completion:^{
|
|
|
|
[self presentViewController:alertController animated:YES completion:[UIUtil modalCompletionBlock]];
|
|
|
|
}];
|
|
|
|
} else {
|
2016-05-17 00:52:11 +02:00
|
|
|
[self presentViewController:alertController animated:YES completion:[UIUtil modalCompletionBlock]];
|
2016-05-23 20:39:30 +02:00
|
|
|
}
|
2015-01-14 22:30:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - SMS Composer Delegate
|
|
|
|
|
|
|
|
// called on completion of message screen
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
|
|
|
|
didFinishWithResult:(MessageComposeResult)result {
|
2015-01-14 22:30:01 +01:00
|
|
|
switch (result) {
|
|
|
|
case MessageComposeResultCancelled:
|
|
|
|
break;
|
|
|
|
case MessageComposeResultFailed: {
|
2015-12-22 12:45:09 +01:00
|
|
|
UIAlertView *warningAlert =
|
|
|
|
[[UIAlertView alloc] initWithTitle:@""
|
2016-11-18 23:11:56 +01:00
|
|
|
message:NSLocalizedString(@"SEND_INVITE_FAILURE", @"")
|
2015-12-22 12:45:09 +01:00
|
|
|
delegate:nil
|
|
|
|
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
|
|
|
otherButtonTitles:nil];
|
2015-01-14 22:30:01 +01:00
|
|
|
[warningAlert show];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MessageComposeResultSent: {
|
2015-12-22 12:45:09 +01:00
|
|
|
[self dismissViewControllerAnimated:NO
|
|
|
|
completion:^{
|
|
|
|
DDLogDebug(@"view controller dismissed");
|
|
|
|
}];
|
|
|
|
UIAlertView *successAlert =
|
|
|
|
[[UIAlertView alloc] initWithTitle:@""
|
2016-11-18 23:11:56 +01:00
|
|
|
message:NSLocalizedString(@"SEND_INVITE_SUCCESS", @"Alert body after invite succeeded")
|
2015-12-22 12:45:09 +01:00
|
|
|
delegate:nil
|
|
|
|
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
|
|
|
otherButtonTitles:nil];
|
2015-01-14 22:30:01 +01:00
|
|
|
[successAlert show];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Table View Data Source
|
2014-10-29 21:58:58 +01:00
|
|
|
|
|
|
|
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
2017-02-17 04:47:12 +01:00
|
|
|
return (self.isNoContactsViewVisible
|
|
|
|
? 0
|
|
|
|
: MessageComposeTableViewControllerSection_Count);
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
2017-02-02 17:57:59 +01:00
|
|
|
// This logic will determine which one (if any) of the following special controls
|
|
|
|
// should be shown. No more than one should be shown at a time.
|
2017-02-02 17:48:41 +01:00
|
|
|
BOOL showNonContactConversation = NO;
|
|
|
|
BOOL showInviteViaSMS = NO;
|
|
|
|
BOOL showInviteFlow = NO;
|
|
|
|
|
2017-03-15 21:56:26 +01:00
|
|
|
BOOL hasPhoneNumber = self.searchPhoneNumbers.count > 0;
|
|
|
|
BOOL hasKnownSignalUser = self.searchPhoneNumberWithAccounts.count > 0;
|
2017-02-03 04:46:10 +01:00
|
|
|
BOOL isInviteFlowSupported = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(9, 0);
|
2017-03-15 21:56:26 +01:00
|
|
|
if (hasKnownSignalUser) {
|
2017-02-02 17:48:41 +01:00
|
|
|
showNonContactConversation = YES;
|
|
|
|
} else if (hasPhoneNumber) {
|
|
|
|
showInviteViaSMS = YES;
|
|
|
|
} else if (isInviteFlowSupported) {
|
|
|
|
showInviteFlow = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (section == MessageComposeTableViewControllerSectionInviteNonContactConversation) {
|
2017-03-15 21:56:26 +01:00
|
|
|
return showNonContactConversation ? (NSInteger) self.searchPhoneNumberWithAccounts.count : 0;
|
2017-02-02 17:48:41 +01:00
|
|
|
} else if (section == MessageComposeTableViewControllerSectionInviteViaSMS) {
|
2017-03-15 21:56:26 +01:00
|
|
|
return showInviteViaSMS ? (NSInteger) self.searchPhoneNumbers.count : 0;
|
2017-02-02 17:48:41 +01:00
|
|
|
} else if (section == MessageComposeTableViewControllerSectionInviteFlow) {
|
|
|
|
return showInviteFlow ? 1 : 0;
|
2014-10-29 21:58:58 +01:00
|
|
|
} else {
|
2017-02-02 17:48:41 +01:00
|
|
|
OWSAssert(section == MessageComposeTableViewControllerSectionContacts)
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
if (self.searchController.active) {
|
|
|
|
return (NSInteger)[self.searchResults count];
|
|
|
|
} else {
|
|
|
|
return (NSInteger)[self.contacts count];
|
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
|
|
{
|
2017-02-02 17:48:41 +01:00
|
|
|
if (indexPath.section == MessageComposeTableViewControllerSectionInviteNonContactConversation) {
|
2017-03-15 21:56:26 +01:00
|
|
|
if (indexPath.row < 0 ||
|
|
|
|
indexPath.row >= (NSInteger) self.searchPhoneNumberWithAccounts.count) {
|
|
|
|
OWSAssert(0);
|
|
|
|
}
|
|
|
|
NSString *phoneNumber = self.searchPhoneNumberWithAccounts[(NSUInteger) indexPath.row];
|
|
|
|
UITableViewCell *conversationForNonContactCell = [UITableViewCell new];
|
|
|
|
conversationForNonContactCell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(@"NEW_CONVERSATION_FOR_NON_CONTACT_FORMAT",
|
2017-02-01 17:43:46 +01:00
|
|
|
@"Text for button to start a new conversation with a non-contact"),
|
2017-03-15 21:56:26 +01:00
|
|
|
phoneNumber];
|
|
|
|
return conversationForNonContactCell;
|
2017-02-02 17:48:41 +01:00
|
|
|
} else if (indexPath.section == MessageComposeTableViewControllerSectionInviteViaSMS) {
|
2017-03-15 21:56:26 +01:00
|
|
|
if (indexPath.row < 0 ||
|
|
|
|
indexPath.row >= (NSInteger) self.searchPhoneNumbers.count) {
|
|
|
|
OWSAssert(0);
|
|
|
|
}
|
|
|
|
NSString *phoneNumber = self.searchPhoneNumbers[(NSUInteger) indexPath.row];
|
|
|
|
UITableViewCell *inviteViaSMSCell = [UITableViewCell new];
|
|
|
|
inviteViaSMSCell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(@"SEND_INVITE_VIA_SMS_BUTTON_FORMAT",
|
2017-02-03 04:46:10 +01:00
|
|
|
@"Text for button to send a Signal invite via SMS. %@ is placeholder for the receipient's phone number."),
|
2017-03-15 21:56:26 +01:00
|
|
|
phoneNumber];
|
|
|
|
return inviteViaSMSCell;
|
2017-02-02 17:48:41 +01:00
|
|
|
} else if (indexPath.section == MessageComposeTableViewControllerSectionInviteFlow) {
|
|
|
|
return self.inviteCell;
|
2016-11-18 23:11:56 +01:00
|
|
|
} else {
|
2017-02-02 17:48:41 +01:00
|
|
|
OWSAssert(indexPath.section == MessageComposeTableViewControllerSectionContacts)
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
ContactTableViewCell *cell = (ContactTableViewCell *)[tableView
|
|
|
|
dequeueReusableCellWithIdentifier:MessageComposeTableViewControllerCellContact];
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
[cell configureWithContact:[self contactForIndexPath:indexPath] contactsManager:self.contactsManager];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
return cell;
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Table View delegate
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
2017-02-02 17:48:41 +01:00
|
|
|
if (indexPath.section == MessageComposeTableViewControllerSectionInviteNonContactConversation) {
|
2017-03-15 21:56:26 +01:00
|
|
|
if (indexPath.row < 0 ||
|
|
|
|
indexPath.row >= (NSInteger) self.searchPhoneNumberWithAccounts.count) {
|
|
|
|
OWSAssert(0);
|
|
|
|
}
|
|
|
|
NSString *phoneNumber = self.searchPhoneNumberWithAccounts[(NSUInteger) indexPath.row];
|
|
|
|
OWSAssert(phoneNumber.length > 0);
|
2017-02-02 17:48:41 +01:00
|
|
|
|
2017-03-15 21:56:26 +01:00
|
|
|
if (phoneNumber.length > 0) {
|
2017-02-02 17:48:41 +01:00
|
|
|
[self dismissViewControllerAnimated:YES
|
|
|
|
completion:^() {
|
2017-03-15 21:56:26 +01:00
|
|
|
[Environment messageIdentifier:phoneNumber withCompose:YES];
|
2017-02-02 17:48:41 +01:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
} else if (indexPath.section == MessageComposeTableViewControllerSectionInviteViaSMS) {
|
2017-03-15 21:56:26 +01:00
|
|
|
if (indexPath.row < 0 ||
|
|
|
|
indexPath.row >= (NSInteger) self.searchPhoneNumbers.count) {
|
|
|
|
OWSAssert(0);
|
|
|
|
}
|
|
|
|
NSString *phoneNumber = self.searchPhoneNumbers[(NSUInteger) indexPath.row];
|
|
|
|
[self sendTextToPhoneNumber:phoneNumber];
|
2017-02-02 17:48:41 +01:00
|
|
|
} else if (indexPath.section == MessageComposeTableViewControllerSectionInviteFlow) {
|
2016-11-18 23:11:56 +01:00
|
|
|
void (^showInvite)() = ^{
|
2016-11-23 17:07:38 +01:00
|
|
|
OWSInviteFlow *inviteFlow =
|
|
|
|
[[OWSInviteFlow alloc] initWithPresentingViewController:self contactsManager:self.contactsManager];
|
2016-11-18 23:11:56 +01:00
|
|
|
[self presentViewController:inviteFlow.actionSheetController
|
|
|
|
animated:YES
|
|
|
|
completion:^{
|
|
|
|
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
|
2015-12-22 12:45:09 +01:00
|
|
|
}];
|
2016-11-18 23:11:56 +01:00
|
|
|
};
|
2015-04-30 15:03:57 +02:00
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
if (self.presentedViewController) {
|
|
|
|
// If search controller is active, dismiss it first.
|
|
|
|
[self dismissViewControllerAnimated:YES completion:showInvite];
|
|
|
|
} else {
|
|
|
|
showInvite();
|
|
|
|
}
|
|
|
|
} else {
|
2017-02-02 17:57:59 +01:00
|
|
|
OWSAssert(indexPath.section == MessageComposeTableViewControllerSectionContacts)
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
NSString *identifier = [[[self contactForIndexPath:indexPath] textSecureIdentifiers] firstObject];
|
|
|
|
|
|
|
|
[self dismissViewControllerAnimated:YES
|
|
|
|
completion:^() {
|
|
|
|
[Environment messageIdentifier:identifier withCompose:YES];
|
|
|
|
}];
|
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (Contact *)contactForIndexPath:(NSIndexPath *)indexPath {
|
2014-10-29 21:58:58 +01:00
|
|
|
Contact *contact = nil;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
if (self.searchController.active) {
|
2016-06-28 06:36:42 +02:00
|
|
|
contact = [self.searchResults objectAtIndex:(NSUInteger)indexPath.row];
|
2014-10-29 21:58:58 +01:00
|
|
|
} else {
|
2016-06-28 06:36:42 +02:00
|
|
|
contact = [self.contacts objectAtIndex:(NSUInteger)indexPath.row];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
return contact;
|
|
|
|
}
|
|
|
|
|
2017-04-03 16:45:48 +02:00
|
|
|
- (void)updateContacts {
|
|
|
|
OWSAssert([NSThread isMainThread]);
|
2015-01-14 22:30:01 +01:00
|
|
|
|
2017-04-03 16:45:48 +02:00
|
|
|
self.contacts = [self filteredContacts];
|
|
|
|
[self updateSearchResultsForSearchController:self.searchController];
|
|
|
|
[self.tableView reloadData];
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2017-04-05 18:22:35 +02:00
|
|
|
- (BOOL)isContactBlockedOrHidden:(Contact *)contact
|
2017-04-03 16:45:48 +02:00
|
|
|
{
|
|
|
|
if (contact.parsedPhoneNumbers.count < 1) {
|
2017-04-05 18:22:35 +02:00
|
|
|
// Hide contacts without any valid phone numbers.
|
2017-04-03 16:45:48 +02:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
|
|
|
|
if ([_blockedPhoneNumbers containsObject:phoneNumber.toE164]) {
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NO;
|
2015-01-14 22:30:01 +01:00
|
|
|
}
|
|
|
|
|
2017-04-03 16:45:48 +02:00
|
|
|
- (NSArray<Contact *> *_Nonnull)filteredContacts
|
|
|
|
{
|
|
|
|
NSMutableArray<Contact *> *result = [NSMutableArray new];
|
|
|
|
for (Contact *contact in self.contactsManager.signalContacts) {
|
2017-04-05 18:22:35 +02:00
|
|
|
if (![self isContactBlockedOrHidden:contact]) {
|
2017-04-03 16:45:48 +02:00
|
|
|
[result addObject:contact];
|
|
|
|
}
|
|
|
|
}
|
2017-04-05 18:22:35 +02:00
|
|
|
return [result copy];
|
2017-02-08 17:59:02 +01:00
|
|
|
}
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
#pragma mark - Navigation
|
|
|
|
|
2016-11-18 23:11:56 +01:00
|
|
|
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender
|
|
|
|
{
|
2015-01-25 06:19:09 +01:00
|
|
|
self.searchController.active = NO;
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (IBAction)closeAction:(id)sender {
|
2017-02-17 04:21:57 +01:00
|
|
|
[self.searchController setActive:NO];
|
2014-10-29 21:58:58 +01:00
|
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
}
|
|
|
|
|
2015-03-20 14:01:28 +01:00
|
|
|
- (CGFloat)contentWidth {
|
2015-12-22 12:45:09 +01:00
|
|
|
return [UIScreen mainScreen].bounds.size.width - 2 * [self marginSize];
|
2015-03-20 14:01:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (CGFloat)marginSize {
|
|
|
|
return 20;
|
|
|
|
}
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
@end
|
2016-11-18 23:11:56 +01:00
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_END
|