diff --git a/Classes/AssistantView.h b/Classes/AssistantView.h index fc9d42873..bea9d732a 100644 --- a/Classes/AssistantView.h +++ b/Classes/AssistantView.h @@ -21,6 +21,7 @@ #import #import "UICompositeView.h" #import "TPKeyboardAvoidingScrollView.h" +#import "PhoneMainView.h" @interface AssistantView : UIViewController { @private @@ -30,6 +31,8 @@ NSMutableArray *historyViews; LinphoneProxyConfig *new_config; int number_of_configs_before; + BOOL mustRestoreView; + long phone_number_length; } @property(nonatomic, strong) IBOutlet TPKeyboardAvoidingScrollView *contentView; @@ -38,11 +41,12 @@ @property(nonatomic, strong) IBOutlet UIView *welcomeView; @property(nonatomic, strong) IBOutlet UIView *createAccountView; -@property(nonatomic, strong) IBOutlet UIView *createAccountActivationView; +@property(nonatomic, strong) IBOutlet UIView *createAccountActivateEmailView; @property(nonatomic, strong) IBOutlet UIView *linphoneLoginView; @property(nonatomic, strong) IBOutlet UIView *loginView; @property(nonatomic, strong) IBOutlet UIView *remoteProvisioningLoginView; @property(strong, nonatomic) IBOutlet UIView *remoteProvisioningView; +@property (strong, nonatomic) IBOutlet UIView *createAccountActivateSMSView; @property(nonatomic, strong) IBOutlet UIImageView *welcomeLogoImage; @property(nonatomic, strong) IBOutlet UIButton *gotoCreateAccountButton; @@ -50,6 +54,9 @@ @property(nonatomic, strong) IBOutlet UIButton *gotoLoginButton; @property(nonatomic, strong) IBOutlet UIButton *gotoRemoteProvisioningButton; +@property (weak, nonatomic) IBOutlet UILabel *accountLabel; +@property (weak, nonatomic) IBOutlet UIButton *countryButton; + + (NSString *)errorForStatus:(LinphoneAccountCreatorStatus)status; - (void)reset; @@ -69,5 +76,11 @@ - (IBAction)onLoginClick:(id)sender; - (IBAction)onRemoteProvisioningLoginClick:(id)sender; - (IBAction)onRemoteProvisioningDownloadClick:(id)sender; +- (IBAction)onCreateAccountCheckActivatedClick:(id)sender; +- (IBAction)onFormSwitchToggle:(id)sender; +- (IBAction)onCountryCodeClick:(id)sender; +- (IBAction)onCountryCodeFieldChange:(id)sender; +- (IBAction)onCountryCodeFieldEnd:(id)sender; +- (IBAction)onPhoneNumberDisclosureClick:(id)sender; @end diff --git a/Classes/AssistantView.m b/Classes/AssistantView.m index 42b59074e..853fd289c 100644 --- a/Classes/AssistantView.m +++ b/Classes/AssistantView.m @@ -18,11 +18,16 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#import +#import + #import "AssistantView.h" #import "LinphoneManager.h" #import "PhoneMainView.h" #import "UITextField+DoneButton.h" #import "UIAssistantTextField.h" +#import "CountryListViewController.h" #import #import @@ -37,10 +42,16 @@ typedef enum _ViewElement { ViewElement_Domain = 104, ViewElement_URL = 105, ViewElement_DisplayName = 106, - ViewElement_TextFieldCount = 7, + ViewElement_Phone = 107, + ViewElement_SMSCode = 108, + ViewElement_PhoneCC = 109, + ViewElement_TextFieldCount = ViewElement_PhoneCC - 100 + 1, ViewElement_Transport = 110, ViewElement_Username_Label = 120, ViewElement_NextButton = 130, + + ViewElement_UsernameFormView = 181, + ViewElement_EmailFormView = 182, } ViewElement; @implementation AssistantView @@ -53,6 +64,7 @@ typedef enum _ViewElement { [[NSBundle mainBundle] loadNibNamed:@"AssistantViewScreens" owner:self options:nil]; historyViews = [[NSMutableArray alloc] init]; currentView = nil; + mustRestoreView = NO; } return self; } @@ -82,8 +94,17 @@ static UICompositeViewDescription *compositeDescription = nil; #pragma mark - ViewController Functions +- (void)viewDidLoad { + [super viewDidLoad]; + _countryButton.layer.borderWidth = .8; + _countryButton.layer.borderColor = _countryButton.backgroundColor.CGColor; + _countryButton.layer.cornerRadius = 4.f; + _countryButton.layer.masksToBounds = YES; +} + - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(registrationUpdateEvent:) name:kLinphoneRegistrationUpdate @@ -93,10 +114,13 @@ static UICompositeViewDescription *compositeDescription = nil; name:kLinphoneConfiguringStateUpdate object:nil]; - new_config = NULL; - [self resetTextFields]; - [self changeView:_welcomeView back:FALSE animation:FALSE]; - number_of_configs_before = ms_list_size(linphone_core_get_proxy_config_list(LC)); + if (!mustRestoreView) { + new_config = NULL; + number_of_configs_before = ms_list_size(linphone_core_get_proxy_config_list(LC)); + [self resetTextFields]; + [self changeView:_welcomeView back:FALSE animation:FALSE]; + } + mustRestoreView = NO; } - (void)viewWillDisappear:(BOOL)animated { @@ -130,12 +154,20 @@ static UICompositeViewDescription *compositeDescription = nil; LC, [LinphoneManager.instance lpConfigStringForKey:@"xmlrpc_url" inSection:@"assistant" withDefault:@""] .UTF8String); linphone_account_creator_set_user_data(account_creator, (__bridge void *)(self)); - linphone_account_creator_cbs_set_existence_tested(linphone_account_creator_get_callbacks(account_creator), - assistant_existence_tested); + linphone_account_creator_cbs_set_is_account_used(linphone_account_creator_get_callbacks(account_creator), + assistant_is_account_used); linphone_account_creator_cbs_set_create_account(linphone_account_creator_get_callbacks(account_creator), assistant_create_account); - linphone_account_creator_cbs_set_validation_tested(linphone_account_creator_get_callbacks(account_creator), - assistant_validation_tested); + linphone_account_creator_cbs_set_activate_account(linphone_account_creator_get_callbacks(account_creator), + assistant_activate_account); + linphone_account_creator_cbs_set_is_account_activated(linphone_account_creator_get_callbacks(account_creator), + assistant_is_account_activated); + + linphone_account_creator_cbs_set_link_phone_number_with_account(linphone_account_creator_get_callbacks(account_creator), + assistant_link_phone_number_with_account); + linphone_account_creator_cbs_set_activate_phone_number_link(linphone_account_creator_get_callbacks(account_creator), + assistant_activate_phone_number_link); + } - (void)loadAssistantConfig:(NSString *)rcFilename { NSString *fullPath = [@"file://" stringByAppendingString:[LinphoneManager bundleFile:rcFilename]]; @@ -173,6 +205,11 @@ static UICompositeViewDescription *compositeDescription = nil; case LinphoneAccountCreatorUsernameInvalidSize: return usePhoneNumber ? NSLocalizedString(@"Phone number length invalid.", nil) : NSLocalizedString(@"Username length invalid.", nil); + case LinphoneAccountCreatorPhoneNumberTooShort: + case LinphoneAccountCreatorPhoneNumberTooLong: + return nil; /* this is not an error, just user has to finish typing */ + case LinphoneAccountCreatorPhoneNumberInvalid: + return NSLocalizedString(@"Invalid phone number.", nil); case LinphoneAccountCreatorPasswordTooShort: return NSLocalizedString(@"Password too short.", nil); case LinphoneAccountCreatorPasswordTooLong: @@ -191,8 +228,8 @@ static UICompositeViewDescription *compositeDescription = nil; case LinphoneAccountCreatorAccountExist: case LinphoneAccountCreatorAccountNotCreated: case LinphoneAccountCreatorAccountNotExist: - case LinphoneAccountCreatorAccountNotValidated: - case LinphoneAccountCreatorAccountValidated: + case LinphoneAccountCreatorAccountNotActivated: + case LinphoneAccountCreatorAccountActivated: case LinphoneAccountCreatorOK: break; } @@ -336,10 +373,9 @@ static UICompositeViewDescription *compositeDescription = nil; currentView = view; [_contentView insertSubview:currentView atIndex:0]; [_contentView setContentOffset:CGPointMake(0, -_contentView.contentInset.top) animated:NO]; - [self fitContent]; // Resize next button to fix text length - UIButton *button = [self findButton:ViewElement_NextButton]; + UIRoundBorderedButton *button = [self findButton:ViewElement_NextButton]; CGSize size = [button.titleLabel.text sizeWithFont:button.titleLabel.font]; size.width += 60; CGRect frame = button.frame; @@ -347,7 +383,28 @@ static UICompositeViewDescription *compositeDescription = nil; frame.size.width = size.width; [button setFrame:frame]; + // also force next button alignement on create account page + if (currentView == _createAccountView) { + CTTelephonyNetworkInfo *networkInfo = [CTTelephonyNetworkInfo new]; + CTCarrier *carrier = networkInfo.subscriberCellularProvider; + NSDictionary *country = [CountryListViewController countryWithIso:carrier.isoCountryCode]; + if (!country) { + //fetch phone locale + for (NSString* lang in [NSLocale preferredLanguages]) { + if ((country = [CountryListViewController countryWithIso:[lang substringFromIndex:[lang rangeOfString:@"-"].location+1]]) != nil) + break; + } + } + + if (country) { + [self didSelectCountry:country]; + [self onFormSwitchToggle:nil]; + } + } + [self prepareErrorLabels]; + + [self fitContent]; } - (void)fillDefaultValues { @@ -380,7 +437,8 @@ static UICompositeViewDescription *compositeDescription = nil; _createAccountView, _linphoneLoginView, _loginView, - _createAccountActivationView, + _createAccountActivateEmailView, + _createAccountActivateSMSView, _remoteProvisioningLoginView ]) { [AssistantView cleanTextField:view]; @@ -390,6 +448,7 @@ static UICompositeViewDescription *compositeDescription = nil; atf.text = @"test.linphone.org"; #endif } + phone_number_length = 0; } - (void)displayUsernameAsPhoneOrUsername { @@ -418,20 +477,9 @@ static UICompositeViewDescription *compositeDescription = nil; } } -- (void)shouldEnableNextButton { - BOOL invalidInputs = NO; - for (int i = 0; i < ViewElement_TextFieldCount; i++) { - UIAssistantTextField *field = [self findTextField:100 + i]; - if (field) { - invalidInputs |= field.isInvalid; - } - } - [self findButton:ViewElement_NextButton].enabled = !invalidInputs; -} - - (UIView *)findView:(ViewElement)tag inView:view ofType:(Class)type { for (UIView *child in [view subviews]) { - if (child.tag == tag) { + if (child.tag == tag && child.class == type) { return child; } else { UIView *o = [self findView:tag inView:child ofType:type]; @@ -446,8 +494,8 @@ static UICompositeViewDescription *compositeDescription = nil; return (UIAssistantTextField *)[self findView:tag inView:self.contentView ofType:[UIAssistantTextField class]]; } -- (UIButton *)findButton:(ViewElement)tag { - return (UIButton *)[self findView:tag inView:self.contentView ofType:[UIButton class]]; +- (UIRoundBorderedButton *)findButton:(ViewElement)tag { + return (UIRoundBorderedButton *)[self findView:tag inView:self.contentView ofType:[UIRoundBorderedButton class]]; } - (UILabel *)findLabel:(ViewElement)tag { @@ -460,9 +508,21 @@ static UICompositeViewDescription *compositeDescription = nil; when:^BOOL(NSString *inputEntry) { LinphoneAccountCreatorStatus s = linphone_account_creator_set_username(account_creator, inputEntry.UTF8String); + if (s != LinphoneAccountCreatorOK) linphone_account_creator_set_username(account_creator, NULL); createUsername.errorLabel.text = [AssistantView errorForStatus:s]; return s != LinphoneAccountCreatorOK; }]; + UIAssistantTextField *createPhone = [self findTextField:ViewElement_Phone]; + [createPhone showError:[AssistantView errorForStatus:LinphoneAccountCreatorPhoneNumberInvalid] + when:^BOOL(NSString *inputEntry) { + UIAssistantTextField* countryCodeField = [self findTextField:ViewElement_PhoneCC]; + NSString* prefix = countryCodeField.text.length > 0 ? [countryCodeField.text substringFromIndex:1] : nil; + LinphoneAccountCreatorStatus s = + linphone_account_creator_set_phone_number(account_creator, inputEntry.UTF8String, prefix.UTF8String); + if (s != LinphoneAccountCreatorOK) linphone_account_creator_set_phone_number(account_creator, NULL, NULL); + createPhone.errorLabel.text = [AssistantView errorForStatus:s]; + return s != LinphoneAccountCreatorOK; + }]; UIAssistantTextField *password = [self findTextField:ViewElement_Password]; [password showError:[AssistantView errorForStatus:LinphoneAccountCreatorPasswordTooShort] @@ -521,9 +581,27 @@ static UICompositeViewDescription *compositeDescription = nil; return s != LinphoneAccountCreatorOK; }]; + UIAssistantTextField *smsCode = [self findTextField:ViewElement_SMSCode]; + [smsCode showError:nil when:^BOOL(NSString *inputEntry) { + return inputEntry.length != 4; + }]; + [self shouldEnableNextButton]; } +- (void)shouldEnableNextButton { + BOOL invalidInputs = NO; + for (int i = 0; !invalidInputs && i < ViewElement_TextFieldCount; i++) { + ViewElement ve = (ViewElement)100+i; + if ([self findTextField:ve].isInvalid) { + invalidInputs = YES; + break; + } + } + + [self findButton:ViewElement_NextButton].enabled = !invalidInputs; +} + #pragma mark - Event Functions - (void)registrationUpdateEvent:(NSNotification *)notif { @@ -612,16 +690,28 @@ static UICompositeViewDescription *compositeDescription = nil; } } +- (void)genericError { + UIAlertView *errorView = [[UIAlertView alloc] + initWithTitle:NSLocalizedString(@"Account creation issue", nil) + message:NSLocalizedString(@"Your account could not be created, please try again later.", nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Continue", nil) + otherButtonTitles:nil, nil]; + [errorView show]; +} + #pragma mark - Account creator callbacks -void assistant_existence_tested(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status) { +void assistant_is_account_used(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status) { AssistantView *thiz = (__bridge AssistantView *)(linphone_account_creator_get_user_data(creator)); thiz.waitView.hidden = YES; if (status == LinphoneAccountCreatorAccountExist) { - [[thiz findTextField:ViewElement_Username] showError:NSLocalizedString(@"This name is already taken.", nil)]; + [[thiz findTextField:ViewElement_Username] showError:NSLocalizedString(@"This account already exists.", nil)]; [thiz findButton:ViewElement_NextButton].enabled = NO; } else if (status == LinphoneAccountCreatorAccountNotExist) { linphone_account_creator_create_account(thiz->account_creator); + } else { + [thiz genericError]; } } @@ -629,24 +719,41 @@ void assistant_create_account(LinphoneAccountCreator *creator, LinphoneAccountCr AssistantView *thiz = (__bridge AssistantView *)(linphone_account_creator_get_user_data(creator)); thiz.waitView.hidden = YES; if (status == LinphoneAccountCreatorAccountCreated) { - [thiz changeView:thiz.createAccountActivationView back:FALSE animation:TRUE]; + if (linphone_account_creator_get_phone_number(creator)) { + [thiz changeView:thiz.createAccountActivateSMSView back:FALSE animation:TRUE]; + } else { + [thiz changeView:thiz.createAccountActivateEmailView back:FALSE animation:TRUE]; + } } else { - UIAlertView *errorView = [[UIAlertView alloc] - initWithTitle:NSLocalizedString(@"Account creation issue", nil) - message:NSLocalizedString(@"Your account could not be created, please try again later.", nil) - delegate:nil - cancelButtonTitle:NSLocalizedString(@"Continue", nil) - otherButtonTitles:nil, nil]; - [errorView show]; + [thiz genericError]; } } -void assistant_validation_tested(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status) { +void assistant_activate_account(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status) { AssistantView *thiz = (__bridge AssistantView *)(linphone_account_creator_get_user_data(creator)); thiz.waitView.hidden = YES; - if (status == LinphoneAccountCreatorAccountValidated) { + if (status == LinphoneAccountCreatorAccountActivated) { [thiz configureProxyConfig]; - } else if (status == LinphoneAccountCreatorAccountNotValidated) { + } else if (status == LinphoneAccountCreatorAccountNotActivated) { + UIAlertView *errorView = [[UIAlertView alloc] + initWithTitle:NSLocalizedString(@"Account activation issue", nil) + message:NSLocalizedString(@"Your account could not be activated, please check SMS code.", nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Continue", nil) + otherButtonTitles:nil, nil]; + [errorView show]; + } else { + // in case we are actually trying to link account, let's try it now + linphone_account_creator_activate_phone_number_link(creator); + } +} + +void assistant_is_account_activated(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status) { + AssistantView *thiz = (__bridge AssistantView *)(linphone_account_creator_get_user_data(creator)); + thiz.waitView.hidden = YES; + if (status == LinphoneAccountCreatorAccountActivated) { + [thiz configureProxyConfig]; + } else if (status == LinphoneAccountCreatorAccountNotActivated) { DTAlertView *alert = [[DTAlertView alloc] initWithTitle:NSLocalizedString(@"Account validation failed", nil) message: @@ -660,6 +767,40 @@ void assistant_validation_tested(LinphoneAccountCreator *creator, LinphoneAccoun [PhoneMainView.instance popToView:DialerView.compositeViewDescription]; }]; [alert show]; + } else { + [thiz genericError]; + } +} + +void assistant_link_phone_number_with_account(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status) { + AssistantView *thiz = (__bridge AssistantView *)(linphone_account_creator_get_user_data(creator)); + thiz.waitView.hidden = YES; + if (status == LinphoneAccountCreatorOK) { + [thiz changeView:thiz.createAccountActivateSMSView back:FALSE animation:TRUE]; + } else { + UIAlertView *errorView = [[UIAlertView alloc] + initWithTitle:NSLocalizedString(@"Account link issue", nil) + message:NSLocalizedString(@"Could not link your phone number with your account, please try again later.", nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Continue", nil) + otherButtonTitles:nil, nil]; + [errorView show]; + } +} + +void assistant_activate_phone_number_link(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status) { + AssistantView *thiz = (__bridge AssistantView *)(linphone_account_creator_get_user_data(creator)); + thiz.waitView.hidden = YES; + if (status == LinphoneAccountCreatorOK) { + [thiz configureProxyConfig]; + } else { + UIAlertView *errorView = [[UIAlertView alloc] + initWithTitle:NSLocalizedString(@"Account link issue", nil) + message:NSLocalizedString(@"Could not link your phone number with your account, please try again later.", nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Continue", nil) + otherButtonTitles:nil, nil]; + [errorView show]; } } @@ -693,19 +834,28 @@ void assistant_validation_tested(LinphoneAccountCreator *creator, LinphoneAccoun - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { - UIAssistantTextField *atf = (UIAssistantTextField *)textField; - BOOL replace = YES; - // if we are hitting backspace on secure entry, this will clear all text - if ([string isEqual:@""] && textField.isSecureTextEntry) { - range = NSMakeRange(0, atf.text.length); + if (textField.tag == ViewElement_SMSCode) { + // max 4 length + return range.location + range.length <= 4; + } else { + UIAssistantTextField *atf = (UIAssistantTextField *)textField; + BOOL replace = YES; + // if we are hitting backspace on secure entry, this will clear all text + if ([string isEqual:@""] && textField.isSecureTextEntry) { + range = NSMakeRange(0, atf.text.length); + } + [atf textField:atf shouldChangeCharactersInRange:range replacementString:string]; + if (atf.tag == ViewElement_Username && currentView == _createAccountView) { + atf.text = [atf.text stringByReplacingCharactersInRange:range withString:string.lowercaseString]; + replace = NO; + } + + if (textField.tag == ViewElement_Phone || textField.tag == ViewElement_Username) { + [self refreshYourUsername]; + } + [self shouldEnableNextButton]; + return replace; } - [atf textField:atf shouldChangeCharactersInRange:range replacementString:string]; - if (atf.tag == ViewElement_Username && currentView == _createAccountView) { - atf.text = [atf.text stringByReplacingCharactersInRange:range withString:string.lowercaseString]; - replace = NO; - } - [self shouldEnableNextButton]; - return replace; } #pragma mark - Action Functions @@ -734,17 +884,29 @@ void assistant_validation_tested(LinphoneAccountCreator *creator, LinphoneAccoun - (IBAction)onCreateAccountClick:(id)sender { _waitView.hidden = NO; - linphone_account_creator_test_existence(account_creator); + linphone_account_creator_is_account_used(account_creator); } - (IBAction)onCreateAccountActivationClick:(id)sender { _waitView.hidden = NO; - linphone_account_creator_test_validation(account_creator); + linphone_account_creator_set_activation_code(account_creator, ((UITextField*)[self findView:ViewElement_SMSCode inView:_contentView ofType:UITextField.class]).text.UTF8String); + linphone_account_creator_activate_account(account_creator); +} + +- (IBAction)onCreateAccountCheckActivatedClick:(id)sender { + _waitView.hidden = NO; + linphone_account_creator_is_account_activated(account_creator); } - (IBAction)onLinphoneLoginClick:(id)sender { _waitView.hidden = NO; - [self configureProxyConfig]; + + NSString *phone = [self findTextField:ViewElement_Phone].text; + if (phone.length > 0) { + linphone_account_creator_link_phone_number_with_account(account_creator); + } else { + [self configureProxyConfig]; + } } - (IBAction)onLoginClick:(id)sender { @@ -763,6 +925,96 @@ void assistant_validation_tested(LinphoneAccountCreator *creator, LinphoneAccoun [self resetLiblinphone]; } +- (void)refreshYourUsername { + UIAssistantTextField *username = [self findTextField:ViewElement_Username]; + UIAssistantTextField *phone = [self findTextField:ViewElement_Phone]; + const char* uri = NULL; + if (!username.superview.hidden) { + uri = linphone_account_creator_get_username(account_creator); + } else if (!phone.superview.hidden) { + uri = linphone_account_creator_get_phone_number(account_creator); + } + + if (uri) { + _accountLabel.text = [NSString stringWithFormat:NSLocalizedString(@"Your SIP address will be sip:%s@sip.linphone.org", nil), uri]; + } else if (!username.superview.hidden) { + _accountLabel.text = NSLocalizedString(@"Please enter your username", nil); + } else { + _accountLabel.text = NSLocalizedString(@"Please enter your phone number", nil); + } +} + +- (IBAction)onFormSwitchToggle:(UISwitch*)sender { + UISwitch *usernameSwitch = (UISwitch *)[self findView:ViewElement_UsernameFormView inView:self.contentView ofType:UISwitch.class]; + UISwitch *emailSwitch = (UISwitch *)[self findView:ViewElement_EmailFormView inView:self.contentView ofType:UISwitch.class]; + + UIView * usernameView = [self findView:ViewElement_UsernameFormView inView:self.contentView ofType:UIView.class]; + UIView * emailView = [self findView:ViewElement_EmailFormView inView:self.contentView ofType:UIView.class]; + usernameView.hidden = !usernameSwitch.isOn && !emailSwitch.isOn; + emailView.hidden = !emailSwitch.isOn; + + UIAssistantTextField* countryCodeField = [self findTextField:ViewElement_PhoneCC]; + usernameSwitch.enabled = _countryButton.enabled = countryCodeField.enabled = countryCodeField.userInteractionEnabled = [self findTextField:ViewElement_Phone].userInteractionEnabled = [self findTextField:ViewElement_Phone].enabled = !emailSwitch.isOn; + + [self refreshYourUsername]; + + // put next button right after latest field (avoid blanks) + UIRoundBorderedButton* nextButton = [self findButton:ViewElement_NextButton]; + CGRect pos = nextButton.frame; + if (usernameView.hidden) { + pos.origin.y = usernameView.frame.origin.y; + } else if (emailView.hidden) { + pos.origin.y = emailView.frame.origin.y; + } else { + pos.origin.y = emailView.frame.origin.y + emailView.frame.size.height; + } + nextButton.frame = pos; + + // make view scrollable only if next button is too away + CGRect viewframe = currentView.frame; + viewframe.size.height = pos.origin.y + pos.size.height; + currentView.autoresizesSubviews = NO; + currentView.frame = viewframe; + currentView.autoresizesSubviews = YES; + [self fitContent]; + + [self shouldEnableNextButton]; +} + +- (IBAction)onCountryCodeClick:(id)sender { + mustRestoreView = YES; + + CountryListViewController *view = VIEW(CountryListViewController); + [view setDelegate:(id)self]; + [PhoneMainView.instance changeCurrentView:view.compositeViewDescription]; +} + +- (void)updateCountry:(BOOL)force { + UIAssistantTextField* countryCodeField = [self findTextField:ViewElement_PhoneCC]; + NSDictionary *c = [CountryListViewController countryWithCountryCode:countryCodeField.text]; + if (c || force) { + [_countryButton setTitle:c ? [c objectForKey:@"name"] : NSLocalizedString(@"Unknown country code", nil) forState:UIControlStateNormal]; + } +} + +- (IBAction)onCountryCodeFieldChange:(id)sender { + [self updateCountry:NO]; +} + +- (IBAction)onCountryCodeFieldEnd:(id)sender { + [self updateCountry:YES]; +} + +- (IBAction)onPhoneNumberDisclosureClick:(id)sender { + UIAlertView *errorView = [[UIAlertView alloc] + initWithTitle:NSLocalizedString(@"What is my phone number for?", nil) + message:NSLocalizedString(@"A SMS code will be sent to your phone number to validate your account.", nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", nil) + otherButtonTitles:nil, nil]; + [errorView show]; +} + - (IBAction)onBackClick:(id)sender { if ([historyViews count] > 0) { UIView *view = [historyViews lastObject]; @@ -782,4 +1034,14 @@ void assistant_validation_tested(LinphoneAccountCreator *creator, LinphoneAccoun } } +#pragma mark - select country delegate + +- (void)didSelectCountry:(NSDictionary *)country{ + [_countryButton setTitle:[country objectForKey:@"name"] forState:UIControlStateNormal]; + UIAssistantTextField* countryCodeField = [self findTextField:ViewElement_PhoneCC]; + countryCodeField.text = countryCodeField.lastText = [country objectForKey:@"code"]; + phone_number_length = [[country objectForKey:@"phone_length"] integerValue]; + [self shouldEnableNextButton]; +} + @end diff --git a/Classes/Base.lproj/AssistantViewScreens.xib b/Classes/Base.lproj/AssistantViewScreens.xib index 3554be5c4..b9c2746f0 100644 --- a/Classes/Base.lproj/AssistantViewScreens.xib +++ b/Classes/Base.lproj/AssistantViewScreens.xib @@ -1,5 +1,5 @@ - + @@ -7,7 +7,10 @@ - + + + + @@ -53,6 +56,7 @@ + @@ -67,7 +71,7 @@ - + @@ -84,7 +88,7 @@ - + @@ -101,7 +105,7 @@ - + @@ -115,7 +119,7 @@ - + - - + - - + + - + + + + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -629,6 +857,7 @@ Once it is done, come back here and click on the button. + @@ -637,7 +866,7 @@ Once it is done, come back here and click on the button. - + @@ -701,6 +930,7 @@ Once it is done, come back here and click on the button. + @@ -709,7 +939,7 @@ Once it is done, come back here and click on the button. - + @@ -803,6 +1033,7 @@ Once it is done, come back here and click on the button. + @@ -811,7 +1042,7 @@ Once it is done, come back here and click on the button. - + @@ -819,4 +1050,7 @@ Once it is done, come back here and click on the button. + + + diff --git a/Classes/Base.lproj/CountryListViewController.xib b/Classes/Base.lproj/CountryListViewController.xib new file mode 100755 index 000000000..101a9371f --- /dev/null +++ b/Classes/Base.lproj/CountryListViewController.xib @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Classes/Contact.m b/Classes/Contact.m index d33c68248..2acfb64ca 100644 --- a/Classes/Contact.m +++ b/Classes/Contact.m @@ -93,9 +93,9 @@ - (NSString *)displayName { if (_friend) { - const char *dp = linphone_address_get_display_name(linphone_friend_get_address(_friend)); - if (dp) - return [NSString stringWithUTF8String:dp]; + // const char *dp = linphone_address_get_display_name(linphone_friend_get_address(_friend)); + //if (dp) + // return [NSString stringWithUTF8String:dp]; } if (_person != nil) { diff --git a/Classes/CountryListViewController.h b/Classes/CountryListViewController.h new file mode 100755 index 000000000..968364c30 --- /dev/null +++ b/Classes/CountryListViewController.h @@ -0,0 +1,28 @@ +// +// CountryListViewController.h +// Country List +// +// Created by Pradyumna Doddala on 18/12/13. +// Copyright (c) 2013 Pradyumna Doddala. All rights reserved. +// + +#import +#import "PhoneMainView.h" + +@protocol CountryListViewDelegate +- (void)didSelectCountry:(NSDictionary *)country; +@end + +@interface CountryListViewController : UIViewController + +@property (nonatomic, weak) iddelegate; + +- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope; + +- (IBAction)onCancelClick:(id)sender; + ++ (NSDictionary *)countryWithIso:(NSString*)iso; + ++ (NSDictionary *)countryWithCountryCode:(NSString*)cc; + +@end diff --git a/Classes/CountryListViewController.m b/Classes/CountryListViewController.m new file mode 100755 index 000000000..151c92dff --- /dev/null +++ b/Classes/CountryListViewController.m @@ -0,0 +1,153 @@ +// +// CountryListViewController.m +// Country List +// +// Created by Pradyumna Doddala on 18/12/13. +// Copyright (c) 2013 Pradyumna Doddala. All rights reserved. +// + +#import "CountryListViewController.h" + +#import "linphone/linphonecore_utils.h" + +@interface CountryListViewController () + +@property (strong, nonatomic) IBOutlet UITableView *tableView; +@property (strong, nonatomic) NSArray *searchResults; + +@end + +@implementation CountryListViewController + +static NSMutableArray * dataRows = nil; + ++ (NSArray*) getData { + if (!dataRows) { + dataRows = [[NSMutableArray alloc] init]; + + for (const LinphoneDialPlan* dial_plan=linphone_dial_plan_get_all(); dial_plan->country!=NULL; dial_plan++) { + [dataRows addObject:@{ + @"name":[NSString stringWithUTF8String:dial_plan->country], + @"iso":[NSString stringWithUTF8String:dial_plan->iso_country_code], + @"code":[NSString stringWithFormat:@"+%s",dial_plan->ccc], + @"phone_length":@(dial_plan->nnl) + }]; + } + } + return dataRows; +} +#pragma mark - UICompositeViewDelegate Functions + +static UICompositeViewDescription *compositeDescription = nil; + ++ (UICompositeViewDescription *)compositeViewDescription { + if (compositeDescription == nil) { + compositeDescription = [[UICompositeViewDescription alloc] init:self.class + statusBar:StatusBarView.class + tabBar:nil + sideMenu:SideMenuView.class + fullscreen:false + isLeftFragment:YES + fragmentWith:nil]; + } + return compositeDescription; +} + +- (UICompositeViewDescription *)compositeViewDescription { + return self.class.compositeViewDescription; +} + +#pragma mark - Other + +- (void)viewDidLoad { + [super viewDidLoad]; + + _searchResults = [[NSArray alloc] init]; + [_tableView reloadData]; +} + +#pragma mark - UITableView Datasource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + if (tableView == self.searchDisplayController.searchResultsTableView){ + return _searchResults.count; + }else{ + return [self.class getData].count; + } + + +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *cellIdentifier = @"Cell"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; + if(cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; + } + + if (tableView == self.searchDisplayController.searchResultsTableView) { + cell.textLabel.text = [[_searchResults objectAtIndex:indexPath.row] valueForKey:@"name"]; + cell.detailTextLabel.text = [[_searchResults objectAtIndex:indexPath.row] valueForKey:@"code"]; + }else{ + cell.textLabel.text = [[[self.class getData] objectAtIndex:indexPath.row] valueForKey:@"name"]; + cell.detailTextLabel.text = [[[self.class getData] objectAtIndex:indexPath.row] valueForKey:@"code"]; + } + return cell; +} + +#pragma mark - UITableView Delegate methods + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + if ([_delegate respondsToSelector:@selector(didSelectCountry:)]) { + NSDictionary* dict = nil; + if (tableView == self.searchDisplayController.searchResultsTableView) { + dict = [_searchResults objectAtIndex:indexPath.row]; + }else{ + dict = [[self.class getData] objectAtIndex:indexPath.row]; + } + + [self.delegate didSelectCountry:dict]; + } + [PhoneMainView.instance popCurrentView]; +} + +#pragma mark - Filtering + +- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{ + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[c] %@ or code contains %@", searchText, searchText]; + _searchResults = [[self.class getData] filteredArrayUsingPredicate:predicate]; +} + +- (IBAction)onCancelClick:(id)sender { + [PhoneMainView.instance popCurrentView]; +} + +- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{ + [self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]]; + return YES; +} + ++ (NSDictionary *)countryWithIso:(NSString *)iso { + for (NSDictionary *dict in [self.class getData]) { + if ([[dict objectForKey:@"iso"] isEqualToString:iso.uppercaseString]) { + return dict; + } + } + return nil; +} + ++ (NSDictionary *)countryWithCountryCode:(NSString *)cc { + for (NSDictionary *dict in [self.class getData]) { + if ([[dict objectForKey:@"code"] isEqualToString:cc.uppercaseString]) { + return dict; + } + } + return nil; +} + +@end diff --git a/Classes/FirstLoginView.m b/Classes/FirstLoginView.m index 0752161f3..cbb1ef807 100644 --- a/Classes/FirstLoginView.m +++ b/Classes/FirstLoginView.m @@ -133,6 +133,11 @@ static UICompositeViewDescription *compositeDescription = nil; case LinphoneAccountCreatorUsernameInvalidSize: return usePhoneNumber ? NSLocalizedString(@"Phone number length invalid.", nil) : NSLocalizedString(@"Username length invalid.", nil); + case LinphoneAccountCreatorPhoneNumberTooShort: + case LinphoneAccountCreatorPhoneNumberTooLong: + return nil; /* this is not an error, just user has to finish typing */ + case LinphoneAccountCreatorPhoneNumberInvalid: + return NSLocalizedString(@"Invalid phone number.", nil); case LinphoneAccountCreatorPasswordTooShort: return NSLocalizedString(@"Password too short.", nil); case LinphoneAccountCreatorPasswordTooLong: @@ -151,8 +156,8 @@ static UICompositeViewDescription *compositeDescription = nil; case LinphoneAccountCreatorAccountExist: case LinphoneAccountCreatorAccountNotCreated: case LinphoneAccountCreatorAccountNotExist: - case LinphoneAccountCreatorAccountNotValidated: - case LinphoneAccountCreatorAccountValidated: + case LinphoneAccountCreatorAccountNotActivated: + case LinphoneAccountCreatorAccountActivated: case LinphoneAccountCreatorOK: break; } diff --git a/Classes/LinphoneUI/UIAssistantTextField.h b/Classes/LinphoneUI/UIAssistantTextField.h index d6b1a7e9f..37c81105e 100644 --- a/Classes/LinphoneUI/UIAssistantTextField.h +++ b/Classes/LinphoneUI/UIAssistantTextField.h @@ -8,17 +8,18 @@ #import -typedef BOOL (^UIDisplayError)(NSString *inputEntry); +typedef BOOL (^DisplayErrorPred)(NSString *inputEntry); @interface UIAssistantTextField : UITextField @property(nonatomic, strong) IBOutlet UILabel *errorLabel; -@property(nonatomic, readonly) UIDisplayError showErrorPredicate; +@property(nonatomic, readonly) DisplayErrorPred showErrorPredicate; + @property(nonatomic, strong) NSString *lastText; // we should show error only when user finished editted the field at least once @property(atomic) BOOL canShowError; -- (void)showError:(NSString *)msg when:(UIDisplayError)pred; +- (void)showError:(NSString *)msg when:(DisplayErrorPred)pred; - (void)showError:(NSString *)msg; - (BOOL)isInvalid; diff --git a/Classes/LinphoneUI/UIAssistantTextField.m b/Classes/LinphoneUI/UIAssistantTextField.m index 1a83a877a..76692d91f 100644 --- a/Classes/LinphoneUI/UIAssistantTextField.m +++ b/Classes/LinphoneUI/UIAssistantTextField.m @@ -27,7 +27,7 @@ INIT_WITH_COMMON_CF { self.layer.borderColor = _errorLabel.hidden ? [[UIColor clearColor] CGColor] : [[UIColor redColor] CGColor]; } -- (void)showError:(NSString *)msg when:(UIDisplayError)apred { +- (void)showError:(NSString *)msg when:(DisplayErrorPred)apred { _showErrorPredicate = apred; [self showError:msg]; [self checkDisplayError]; @@ -38,8 +38,21 @@ INIT_WITH_COMMON_CF { self.layer.borderColor = _errorLabel.hidden ? [[UIColor clearColor] CGColor] : [[UIColor redColor] CGColor]; } +- (BOOL)isVisible { + UIView* aview = self; + while (aview) { + if (aview.isHidden) return NO; + aview = aview.superview; + } + return YES; +} + - (BOOL)isInvalid { - return _showErrorPredicate && _showErrorPredicate(_lastText); + return self.isVisible && _showErrorPredicate && _showErrorPredicate(_lastText); +} + +- (void)setEnabled:(BOOL)enabled { + self.backgroundColor = [self.backgroundColor colorWithAlphaComponent:enabled?1:0.5]; } #pragma mark - UITextFieldDelegate Functions @@ -47,6 +60,8 @@ INIT_WITH_COMMON_CF { - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + // we must not show any error until user typed at least one character + _canShowError |= (string.length > 0); _lastText = [textField.text stringByReplacingCharactersInRange:range withString:string]; [self checkDisplayError]; return YES; @@ -54,7 +69,6 @@ INIT_WITH_COMMON_CF { - (void)textFieldDidEndEditing:(UITextField *)textField { _lastText = textField.text; - _canShowError = YES; [self checkDisplayError]; } diff --git a/Classes/LinphoneUI/UIRoundBorderedButton.m b/Classes/LinphoneUI/UIRoundBorderedButton.m index 91ed97758..ca6e59ec0 100644 --- a/Classes/LinphoneUI/UIRoundBorderedButton.m +++ b/Classes/LinphoneUI/UIRoundBorderedButton.m @@ -1,3 +1,4 @@ + // // UIRoundBorderedButton.m // linphone diff --git a/Resources/assistant_linphone_create.rc b/Resources/assistant_linphone_create.rc index 1e52020df..8427fd932 100644 --- a/Resources/assistant_linphone_create.rc +++ b/Resources/assistant_linphone_create.rc @@ -28,6 +28,6 @@ 64 1 ^[a-z0-9_.\-]*$ - https://www.linphone.org/assistant.php + http://sip3.linphone.org/xmlrpc.php diff --git a/Resources/assistant_linphone_existing.rc b/Resources/assistant_linphone_existing.rc index f22df59b3..da64ddffb 100644 --- a/Resources/assistant_linphone_existing.rc +++ b/Resources/assistant_linphone_existing.rc @@ -2,7 +2,7 @@
- 1 + 1 0 0 sip:voip-metrics@sip.linphone.org;transport=tls @@ -28,6 +28,6 @@ 64 1 ^[a-z0-9_.\-]*$ - https://www.linphone.org/assistant.php + http://sip3.linphone.org/xmlrpc.php
diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj index 42294ee50..91db2122e 100755 --- a/linphone.xcodeproj/project.pbxproj +++ b/linphone.xcodeproj/project.pbxproj @@ -76,6 +76,8 @@ 6306440E1BECB08500134C72 /* FirstLoginView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6306440C1BECB08500134C72 /* FirstLoginView.m */; }; 6308F9C51BF0DD6600D1234B /* XMLRPCHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 6308F9C41BF0DD6600D1234B /* XMLRPCHelper.m */; }; 630CF5571AF7CE1500539F7A /* UITextField+DoneButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 630CF5561AF7CE1500539F7A /* UITextField+DoneButton.m */; }; + 631098491D4660580041F2B3 /* CountryListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 631098481D4660580041F2B3 /* CountryListViewController.m */; }; + 631098521D4660630041F2B3 /* CountryListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 631098501D4660630041F2B3 /* CountryListViewController.xib */; }; 63130FB21C1ED06900371918 /* SideMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 63130FB01C1ED06900371918 /* SideMenuView~ipad.xib */; }; 631348301B6F7B6600C6BDCB /* UIRoundBorderedButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 6313482F1B6F7B6600C6BDCB /* UIRoundBorderedButton.m */; }; 631348321B6FA53300C6BDCB /* rootca.pem in Resources */ = {isa = PBXBuildFile; fileRef = 631348311B6FA53300C6BDCB /* rootca.pem */; }; @@ -981,6 +983,9 @@ 6308F9C41BF0DD6600D1234B /* XMLRPCHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMLRPCHelper.m; path = Utils/XMLRPCHelper.m; sourceTree = ""; }; 630CF5551AF7CE1500539F7A /* UITextField+DoneButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITextField+DoneButton.h"; sourceTree = ""; }; 630CF5561AF7CE1500539F7A /* UITextField+DoneButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITextField+DoneButton.m"; sourceTree = ""; }; + 631098471D4660580041F2B3 /* CountryListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryListViewController.h; sourceTree = ""; }; + 631098481D4660580041F2B3 /* CountryListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CountryListViewController.m; sourceTree = ""; }; + 631098511D4660630041F2B3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/CountryListViewController.xib; sourceTree = ""; }; 63130FB11C1ED06900371918 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Base.lproj/SideMenuView~ipad.xib"; sourceTree = ""; }; 6313482E1B6F7B6600C6BDCB /* UIRoundBorderedButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIRoundBorderedButton.h; sourceTree = ""; }; 6313482F1B6F7B6600C6BDCB /* UIRoundBorderedButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIRoundBorderedButton.m; sourceTree = ""; }; @@ -1778,6 +1783,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 340751971506459A00B89C47 /* CoreTelephony.framework in Frameworks */, 637835A51CFD971D00599382 /* libbv16.a in Frameworks */, 63FD3F091CA17F9100E9AECC /* libmbedcrypto.a in Frameworks */, 63FD3F0A1CA17F9100E9AECC /* libmbedtls.a in Frameworks */, @@ -1830,7 +1836,6 @@ 2274401A106F31BD006EC466 /* CoreAudio.framework in Frameworks */, 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, 22276E8913C73DC000210156 /* CoreMedia.framework in Frameworks */, - 340751971506459A00B89C47 /* CoreTelephony.framework in Frameworks */, 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, F0B89C2218DC89E30050B60E /* MediaPlayer.framework in Frameworks */, D37DC7181594AF3400B2A5EB /* MessageUI.framework in Frameworks */, @@ -1928,7 +1933,6 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( - 63E27A311C4FECD000D332AE /* LaunchScreen.xib */, 22E0A81D111C44E100B04932 /* AboutView.h */, 22E0A81C111C44E100B04932 /* AboutView.m */, 636316D31A1DEBCB0009B839 /* AboutView.xib */, @@ -1978,6 +1982,9 @@ D35497FB15875372000081D8 /* ContactsListView.h */, D35497FC15875372000081D8 /* ContactsListView.m */, D38187C015FE342800C3EDCA /* ContactsListView.xib */, + 631098471D4660580041F2B3 /* CountryListViewController.h */, + 631098481D4660580041F2B3 /* CountryListViewController.m */, + 631098501D4660630041F2B3 /* CountryListViewController.xib */, 22F2508B107141E100AC9B3F /* DialerView.h */, 22F2508C107141E100AC9B3F /* DialerView.m */, D38187C415FE345B00C3EDCA /* DialerView.xib */, @@ -2002,6 +2009,7 @@ D37EE11016035793003608A6 /* ImageView.xib */, 63E59A3D1ADE6ECB00646FB3 /* InAppProductsManager.h */, 63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */, + 63E27A311C4FECD000D332AE /* LaunchScreen.xib */, 1D3623240D0F684500981E51 /* LinphoneAppDelegate.h */, 1D3623250D0F684500981E51 /* LinphoneAppDelegate.m */, D37DC6BF1594AE1800B2A5EB /* LinphoneCoreSettingsStore.h */, @@ -3473,6 +3481,7 @@ 633FEDC91D3CD5590014B822 /* call_missed@2x.png in Resources */, 633FEEAE1D3CD55A0014B822 /* numpad_2_over@2x.png in Resources */, 633FEDB51D3CD5590014B822 /* call_alt_back_disabled@2x.png in Resources */, + 631098521D4660630041F2B3 /* CountryListViewController.xib in Resources */, 633FEF271D3CD55A0014B822 /* route_bluetooth_selected@2x.png in Resources */, 633FEE111D3CD5590014B822 /* chat_list_indicator~ipad@2x.png in Resources */, 633FEEFC1D3CD55A0014B822 /* options_add_call_default.png in Resources */, @@ -3861,6 +3870,7 @@ D3F26BF115986B73005F9CAB /* CallIncomingView.m in Sources */, D31B4B21159876C0002E6C72 /* UICompositeView.m in Sources */, D31AAF5E159B3919002C6B02 /* CallPausedTableView.m in Sources */, + 631098491D4660580041F2B3 /* CountryListViewController.m in Sources */, D32B9DFC15A2F131000B6DEC /* FastAddressBook.m in Sources */, D350F20E15A43BB100149E54 /* AssistantView.m in Sources */, D3F795D615A582810077328B /* ChatConversationView.m in Sources */, @@ -4023,6 +4033,14 @@ name = InfoPlist.strings; sourceTree = ""; }; + 631098501D4660630041F2B3 /* CountryListViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + 631098511D4660630041F2B3 /* Base */, + ); + name = CountryListViewController.xib; + sourceTree = ""; + }; 63130FB01C1ED06900371918 /* SideMenuView~ipad.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/submodules/cmake-builder b/submodules/cmake-builder index aa0677fcc..86e76b621 160000 --- a/submodules/cmake-builder +++ b/submodules/cmake-builder @@ -1 +1 @@ -Subproject commit aa0677fcc261a0adabe315593d452e1f65c9484c +Subproject commit 86e76b62194506cbd50d201def3d4db2b93c8bc7 diff --git a/submodules/linphone b/submodules/linphone index 9ed5462f9..dec784f7a 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 9ed5462f9041a5533aa4863bcb829357f57ad20b +Subproject commit dec784f7a4f1f85401be644d2c0ca6300a08c114