2017-03-31 05:05:26 +02:00
|
|
|
//
|
|
|
|
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "AddToBlockListViewController.h"
|
|
|
|
#import "CountryCodeViewController.h"
|
|
|
|
#import "PhoneNumber.h"
|
|
|
|
#import "StringUtil.h"
|
|
|
|
#import "UIFont+OWS.h"
|
|
|
|
#import "UIUtil.h"
|
|
|
|
#import "UIView+OWS.h"
|
|
|
|
#import "ViewControllerUtils.h"
|
|
|
|
#import <SignalServiceKit/PhoneNumberUtil.h>
|
|
|
|
#import <SignalServiceKit/TSBlockingManager.h>
|
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
|
|
|
NSString * const kAddToBlockListViewControllerCellIdentifier = @"kAddToBlockListViewControllerCellIdentifier";
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
// TODO: Add a list of contacts to make it easier to block contacts.
|
|
|
|
@interface AddToBlockListViewController () <CountryCodeViewControllerDelegate, UITextFieldDelegate>
|
|
|
|
|
|
|
|
@property (nonatomic, readonly) TSBlockingManager *blockingManager;
|
|
|
|
|
|
|
|
@property (nonatomic) UIButton *countryNameButton;
|
|
|
|
@property (nonatomic) UIButton *countryCodeButton;
|
|
|
|
|
|
|
|
@property (nonatomic) UITextField *phoneNumberTextField;
|
|
|
|
|
|
|
|
@property (nonatomic) UIButton *blockButton;
|
|
|
|
|
2017-03-31 17:57:58 +02:00
|
|
|
@property (nonatomic) NSString *callingCode;
|
2017-03-31 05:05:26 +02:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
@implementation AddToBlockListViewController
|
|
|
|
|
|
|
|
- (void)viewDidLoad
|
|
|
|
{
|
|
|
|
[super viewDidLoad];
|
|
|
|
[self.navigationController.navigationBar setTranslucent:NO];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)loadView
|
|
|
|
{
|
|
|
|
[super loadView];
|
|
|
|
|
|
|
|
self.view.backgroundColor = [UIColor whiteColor];
|
|
|
|
|
|
|
|
_blockingManager = [TSBlockingManager sharedManager];
|
|
|
|
|
|
|
|
self.title = NSLocalizedString(@"SETTINGS_ADD_TO_BLOCK_LIST_TITLE", @"");
|
|
|
|
|
|
|
|
[self createViews];
|
|
|
|
|
|
|
|
[self populateDefaultCountryNameAndCode];
|
|
|
|
|
|
|
|
[self addNotificationListeners];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)addNotificationListeners
|
|
|
|
{
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(blockedPhoneNumbersDidChange:)
|
|
|
|
name:kNSNotificationName_BlockedPhoneNumbersDidChange
|
|
|
|
object:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)createViews {
|
|
|
|
// Country Row
|
|
|
|
UIView *countryRow = [self createRowWithHeight:60 previousRow:nil];
|
|
|
|
|
|
|
|
_countryNameButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
_countryNameButton.titleLabel.font = [UIFont ows_mediumFontWithSize:16.f];
|
|
|
|
[_countryNameButton setTitleColor:[UIColor blackColor]
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[_countryNameButton setTitle:NSLocalizedString(@"REGISTRATION_DEFAULT_COUNTRY_NAME", @"")
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[_countryNameButton addTarget:self
|
|
|
|
action:@selector(showCountryCodeView:)
|
|
|
|
forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
[countryRow addSubview:_countryNameButton];
|
|
|
|
[_countryNameButton autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:20.f];
|
|
|
|
[_countryNameButton autoVCenterInSuperview];
|
|
|
|
|
|
|
|
_countryCodeButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
_countryCodeButton.titleLabel.font = [UIFont ows_mediumFontWithSize:16.f];
|
|
|
|
_countryCodeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
|
|
|
|
[_countryCodeButton setTitleColor:[UIColor ows_signalBrandBlueColor]
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[_countryCodeButton addTarget:self
|
|
|
|
action:@selector(showCountryCodeView:)
|
|
|
|
forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
[countryRow addSubview:_countryCodeButton];
|
|
|
|
[_countryCodeButton autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:16.f];
|
|
|
|
[_countryCodeButton autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:_countryNameButton withOffset:0];
|
|
|
|
[_countryCodeButton autoVCenterInSuperview];
|
|
|
|
|
|
|
|
// Border Row
|
|
|
|
UIView *borderRow1 = [self createRowWithHeight:1 previousRow:countryRow];
|
|
|
|
UIColor *borderColor = [UIColor colorWithRed:0.75f green:0.75f blue:0.75f alpha:1.f];
|
|
|
|
borderRow1.backgroundColor = borderColor;
|
|
|
|
|
|
|
|
// Phone Number Row
|
|
|
|
UIView *phoneNumberRow = [self createRowWithHeight:60 previousRow:borderRow1];
|
|
|
|
|
|
|
|
UILabel *phoneNumberLabel = [UILabel new];
|
|
|
|
phoneNumberLabel.font = [UIFont ows_mediumFontWithSize:16.f];
|
|
|
|
phoneNumberLabel.textColor = [UIColor blackColor];
|
|
|
|
phoneNumberLabel.text = NSLocalizedString(@"REGISTRATION_PHONENUMBER_BUTTON", @"");
|
|
|
|
[phoneNumberRow addSubview:phoneNumberLabel];
|
|
|
|
[phoneNumberLabel autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:20.f];
|
|
|
|
[phoneNumberLabel autoVCenterInSuperview];
|
|
|
|
|
|
|
|
_phoneNumberTextField = [UITextField new];
|
|
|
|
_phoneNumberTextField.font = [UIFont ows_mediumFontWithSize:16.f];
|
|
|
|
_phoneNumberTextField.textAlignment = NSTextAlignmentRight;
|
|
|
|
_phoneNumberTextField.textColor = [UIColor ows_signalBrandBlueColor];
|
|
|
|
_phoneNumberTextField.placeholder = NSLocalizedString(@"REGISTRATION_ENTERNUMBER_DEFAULT_TEXT", @"");
|
|
|
|
_phoneNumberTextField.keyboardType = UIKeyboardTypeNumberPad;
|
|
|
|
_phoneNumberTextField.delegate = self;
|
|
|
|
[_phoneNumberTextField addTarget:self
|
|
|
|
action:@selector(textFieldDidChange:)
|
|
|
|
forControlEvents:UIControlEventEditingChanged];
|
|
|
|
[phoneNumberRow addSubview:_phoneNumberTextField];
|
|
|
|
[_phoneNumberTextField autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:16.f];
|
|
|
|
[_phoneNumberTextField autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:phoneNumberLabel withOffset:0];
|
|
|
|
[_phoneNumberTextField autoVCenterInSuperview];
|
|
|
|
|
|
|
|
// Border Row
|
|
|
|
UIView *borderRow2 = [self createRowWithHeight:1 previousRow:phoneNumberRow];
|
|
|
|
borderRow2.backgroundColor = borderColor;
|
|
|
|
|
|
|
|
// Block Button Row
|
|
|
|
UIView *blockButtonRow = [self createRowWithHeight:60 previousRow:borderRow2];
|
|
|
|
|
2017-03-31 19:57:12 +02:00
|
|
|
// TODO: Eventually we should make a view factory that will allow us to
|
|
|
|
// create views with consistent appearance across the app and move
|
|
|
|
// towards a "design language."
|
2017-03-31 05:05:26 +02:00
|
|
|
_blockButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
_blockButton.titleLabel.font = [UIFont ows_mediumFontWithSize:16.f];
|
|
|
|
[_blockButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
|
|
|
[_blockButton setBackgroundColor:[UIColor ows_signalBrandBlueColor]];
|
|
|
|
_blockButton.clipsToBounds = YES;
|
|
|
|
_blockButton.layer.cornerRadius = 3.f;
|
|
|
|
[_blockButton setTitle:NSLocalizedString(
|
|
|
|
@"BLOCK_LIST_VIEW_BLOCK_BUTTON", @"A label for the block button in the block list view")
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[_blockButton addTarget:self action:@selector(blockButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
[blockButtonRow addSubview:_blockButton];
|
|
|
|
[_blockButton autoCenterInSuperview];
|
|
|
|
[_blockButton autoSetDimension:ALDimensionWidth toSize:160];
|
|
|
|
[_blockButton autoSetDimension:ALDimensionHeight toSize:40];
|
|
|
|
|
|
|
|
[self updateBlockButtonEnabling];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (UIView *)createRowWithHeight:(CGFloat)height previousRow:(nullable UIView *)previousRow
|
|
|
|
{
|
|
|
|
UIView *row = [UIView new];
|
|
|
|
[self.view addSubview:row];
|
|
|
|
[row autoPinWidthToSuperview];
|
|
|
|
if (previousRow) {
|
|
|
|
[row autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:previousRow withOffset:0];
|
|
|
|
} else {
|
|
|
|
[row autoPinToTopLayoutGuideOfViewController:self withInset:0];
|
|
|
|
}
|
|
|
|
[row autoSetDimension:ALDimensionHeight toSize:height];
|
|
|
|
return row;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Country
|
|
|
|
|
|
|
|
- (void)populateDefaultCountryNameAndCode {
|
|
|
|
NSLocale *locale = NSLocale.currentLocale;
|
|
|
|
NSString *countryCode = [locale objectForKey:NSLocaleCountryCode];
|
|
|
|
NSNumber *callingCode = [[PhoneNumberUtil sharedUtil].nbPhoneNumberUtil getCountryCodeForRegion:countryCode];
|
|
|
|
NSString *countryName = [PhoneNumberUtil countryNameFromCountryCode:countryCode];
|
|
|
|
[self updateCountryWithName:countryName
|
|
|
|
callingCode:[NSString stringWithFormat:@"%@%@",
|
|
|
|
COUNTRY_CODE_PREFIX,
|
|
|
|
callingCode]
|
|
|
|
countryCode:countryCode];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)updateCountryWithName:(NSString *)countryName
|
|
|
|
callingCode:(NSString *)callingCode
|
|
|
|
countryCode:(NSString *)countryCode {
|
2017-03-31 17:57:58 +02:00
|
|
|
|
|
|
|
_callingCode = callingCode;
|
2017-03-31 05:05:26 +02:00
|
|
|
|
|
|
|
NSString *title = [NSString stringWithFormat:@"%@ (%@)",
|
|
|
|
callingCode,
|
|
|
|
countryCode.uppercaseString];
|
|
|
|
[_countryCodeButton setTitle:title
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[_countryCodeButton layoutSubviews];
|
|
|
|
}
|
|
|
|
|
2017-03-31 17:57:58 +02:00
|
|
|
- (void)setcallingCode:(NSString *)callingCode
|
2017-03-31 05:05:26 +02:00
|
|
|
{
|
2017-03-31 17:57:58 +02:00
|
|
|
_callingCode = callingCode;
|
2017-03-31 05:05:26 +02:00
|
|
|
|
|
|
|
[self updateBlockButtonEnabling];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Actions
|
|
|
|
|
|
|
|
- (void)showCountryCodeView:(id)sender {
|
2017-03-31 17:57:58 +02:00
|
|
|
CountryCodeViewController *countryCodeController = [[UIStoryboard storyboardWithName:@"Registration" bundle:NULL]
|
|
|
|
instantiateViewControllerWithIdentifier:@"CountryCodeViewController"];
|
2017-03-31 05:05:26 +02:00
|
|
|
countryCodeController.delegate = self;
|
2017-03-31 17:57:58 +02:00
|
|
|
countryCodeController.shouldDismissWithoutSegue = YES;
|
|
|
|
UINavigationController *navigationController =
|
|
|
|
[[UINavigationController alloc] initWithRootViewController:countryCodeController];
|
|
|
|
[self presentViewController:navigationController animated:YES completion:[UIUtil modalCompletionBlock]];
|
2017-03-31 05:05:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blockButtonPressed:(id)sender
|
|
|
|
{
|
|
|
|
[self tryToBlockPhoneNumber];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)tryToBlockPhoneNumber
|
|
|
|
{
|
2017-03-31 17:57:58 +02:00
|
|
|
if (![self hasValidPhoneNumber]) {
|
2017-03-31 05:05:26 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-31 17:57:58 +02:00
|
|
|
NSString *possiblePhoneNumber = [self.callingCode stringByAppendingString:_phoneNumberTextField.text.digitsOnly];
|
2017-03-31 05:05:26 +02:00
|
|
|
PhoneNumber *parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:possiblePhoneNumber];
|
2017-03-31 17:57:58 +02:00
|
|
|
OWSAssert(parsedPhoneNumber);
|
2017-03-31 05:05:26 +02:00
|
|
|
|
|
|
|
[_blockingManager addBlockedPhoneNumber:[parsedPhoneNumber toE164]];
|
|
|
|
|
|
|
|
UIAlertController *controller = [UIAlertController
|
|
|
|
alertControllerWithTitle:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE",
|
|
|
|
@"The title of the 'phone number blocked' alert in the block view.")
|
|
|
|
message:[NSString
|
|
|
|
stringWithFormat:NSLocalizedString(@"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT",
|
|
|
|
@"The message format of the 'phone number blocked' alert in "
|
|
|
|
@"the block view. It is populated with the blocked phone "
|
|
|
|
@"number."),
|
|
|
|
[parsedPhoneNumber toE164]]
|
|
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
|
|
|
|
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
|
|
|
|
style:UIAlertActionStyleDefault
|
|
|
|
handler:nil]];
|
|
|
|
[self presentViewController:controller animated:YES completion:nil];
|
|
|
|
|
|
|
|
_phoneNumberTextField.text = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)textFieldDidChange:(id)sender
|
|
|
|
{
|
|
|
|
[self updateBlockButtonEnabling];
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: We could also do this in registration view.
|
|
|
|
- (BOOL)hasValidPhoneNumber
|
|
|
|
{
|
2017-03-31 17:57:58 +02:00
|
|
|
if (!self.callingCode) {
|
2017-03-31 05:05:26 +02:00
|
|
|
return NO;
|
|
|
|
}
|
2017-03-31 17:57:58 +02:00
|
|
|
NSString *possiblePhoneNumber = [self.callingCode stringByAppendingString:_phoneNumberTextField.text.digitsOnly];
|
2017-03-31 05:05:26 +02:00
|
|
|
PhoneNumber *parsedPhoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:possiblePhoneNumber];
|
2017-03-31 17:57:58 +02:00
|
|
|
// It'd be nice to use [PhoneNumber isValid] but it always returns false for some countries
|
|
|
|
// (like afghanistan) and there doesn't seem to be a good way to determine beforehand
|
|
|
|
// which countries it can validate for without forking libPhoneNumber.
|
|
|
|
return parsedPhoneNumber && parsedPhoneNumber.toE164.length > 1;
|
2017-03-31 05:05:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)updateBlockButtonEnabling
|
|
|
|
{
|
|
|
|
BOOL isEnabled = [self hasValidPhoneNumber];
|
|
|
|
_blockButton.enabled = isEnabled;
|
|
|
|
[_blockButton setBackgroundColor:(isEnabled ? [UIColor ows_signalBrandBlueColor] : [UIColor lightGrayColor])];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blockedPhoneNumbersDidChange:(id)notification
|
|
|
|
{
|
|
|
|
// TODO: Once we have a list of contacts, we should update it here.
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - CountryCodeViewControllerDelegate
|
|
|
|
|
|
|
|
- (void)countryCodeViewController:(CountryCodeViewController *)vc
|
|
|
|
didSelectCountryCode:(NSString *)countryCode
|
|
|
|
countryName:(NSString *)countryName
|
|
|
|
callingCode:(NSString *)callingCode {
|
|
|
|
|
|
|
|
[self updateCountryWithName:countryName
|
|
|
|
callingCode:callingCode
|
|
|
|
countryCode:countryCode];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - UITextFieldDelegate
|
|
|
|
|
|
|
|
// TODO: This logic resides in both RegistrationViewController and here.
|
|
|
|
// We should refactor it out into a utility function.
|
|
|
|
- (BOOL)textField:(UITextField *)textField
|
|
|
|
shouldChangeCharactersInRange:(NSRange)range
|
|
|
|
replacementString:(NSString *)insertionText
|
|
|
|
{
|
|
|
|
[ViewControllerUtils phoneNumberTextField:textField
|
|
|
|
shouldChangeCharactersInRange:range
|
|
|
|
replacementString:insertionText
|
2017-03-31 17:57:58 +02:00
|
|
|
countryCode:_callingCode];
|
2017-03-31 05:05:26 +02:00
|
|
|
|
|
|
|
[self updateBlockButtonEnabling];
|
|
|
|
|
|
|
|
return NO; // inform our caller that we took care of performing the change
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)textFieldShouldReturn:(UITextField *)textField
|
|
|
|
{
|
|
|
|
[textField resignFirstResponder];
|
|
|
|
[self tryToBlockPhoneNumber];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Logging
|
|
|
|
|
|
|
|
+ (NSString *)tag
|
|
|
|
{
|
|
|
|
return [NSString stringWithFormat:@"[%@]", self.class];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)tag
|
|
|
|
{
|
|
|
|
return self.class.tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_END
|