/* * Copyright (c) 2010-2020 Belledonne Communications SARL. * * This file is part of linphone-iphone * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import #import #import "AssistantLinkView.h" #import "UITextField+DoneButton.h" #import "UIAssistantTextField.h" @implementation AssistantLinkView { LinphoneAccountCreator *account_creator; } - (void)viewDidLoad { [super viewDidLoad]; // every UITextField subviews with phone keyboard must be tweaked to have a done button [self addDoneButtonRecursivelyInView:self.view]; self.phoneField.delegate = self; self.firstTime = TRUE; } - (void)addDoneButtonRecursivelyInView:(UIView *)subview { for (UIView *child in [subview subviews]) { if ([child isKindOfClass:UITextField.class]) { UITextField *tf = (UITextField *)child; if (tf.keyboardType == UIKeyboardTypePhonePad || tf.keyboardType == UIKeyboardTypeNumberPad) { [tf addDoneButton]; } } [self addDoneButtonRecursivelyInView:child]; } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; _linkAccountView.hidden = _activateSMSView.userInteractionEnabled = NO; _activateSMSView.hidden = _linkAccountView.userInteractionEnabled = YES; [self fitScrollContentSize]; if (!account_creator) { account_creator = linphone_account_creator_new( 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_link_account(linphone_account_creator_get_callbacks(account_creator), assistant_link_phone_number_with_account); linphone_account_creator_cbs_set_activate_alias(linphone_account_creator_get_callbacks(account_creator), assistant_activate_phone_number_link); LinphoneAccount *acc = linphone_core_get_default_account(LC); LinphoneAccountParams const *accParams = linphone_account_get_params(acc); if (acc && strcmp([LinphoneManager.instance lpConfigStringForKey:@"domain_name" inSection:@"app" withDefault:@"sip.linphone.org"] .UTF8String, linphone_account_params_get_domain(accParams)) == 0) { linphone_account_creator_set_username( account_creator, linphone_address_get_username(linphone_account_params_get_identity_address(accParams))); const LinphoneAuthInfo *info = linphone_account_find_auth_info(acc); if (info) { if (linphone_auth_info_get_passwd(info)) linphone_account_creator_set_password(account_creator, linphone_auth_info_get_passwd(info)); else linphone_account_creator_set_ha1(account_creator, linphone_auth_info_get_ha1(info)); } linphone_account_creator_set_domain(account_creator, linphone_account_params_get_domain(accParams)); } else { LOGW(@"Default proxy is NOT a sip.linphone.org, aborting"); [PhoneMainView.instance popToView:DialerView.compositeViewDescription]; } CTTelephonyNetworkInfo *networkInfo = [CTTelephonyNetworkInfo new]; CTCarrier *carrier = networkInfo.subscriberCellularProvider; NSDictionary *country = [CountryListView countryWithIso:carrier.isoCountryCode]; if (!country) { // fetch phone locale for (NSString *lang in [NSLocale preferredLanguages]) { NSUInteger idx = [lang rangeOfString:@"-"].location; idx = (idx == NSNotFound) ? idx = 0 : idx + 1; if ((country = [CountryListView countryWithIso:[lang substringFromIndex:idx]]) != nil) break; } } if (country && self.firstTime) { [self didSelectCountry:country]; } } - (void)viewDidDisappear:(BOOL)animated { if (account_creator) { linphone_account_creator_unref(account_creator); } account_creator = NULL; [super viewDidDisappear:animated]; } - (void)fitScrollContentSize { // make view scrollable only if next button is too away CGRect viewframe = _linkAccountView.frame; if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) { viewframe.size.height += 60; } [_linkAccountView setContentSize:viewframe.size]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [self fitScrollContentSize]; } #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:NO fragmentWith:nil]; compositeDescription.darkBackground = true; } return compositeDescription; } - (UICompositeViewDescription *)compositeViewDescription { return self.class.compositeViewDescription; } #pragma mark - popup - (void)showErrorPopup:(const char *)err { if (strcmp(err, "ERROR_KEY_DOESNT_MATCH") == 0) { UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Account configuration issue", nil) message:[AssistantView StringForXMLRPCError:err] preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { self.linkAccountView.hidden = NO; self.linkAccountView.userInteractionEnabled = YES; self.activateSMSView.userInteractionEnabled = NO; self.activateSMSView.hidden = YES; self.activationCodeField.text = @""; }]; [errView addAction:defaultAction]; [self presentViewController:errView animated:YES completion:nil]; } else { UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Account configuration issue", nil) message:[AssistantView StringForXMLRPCError:err] preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ }]; [errView addAction:defaultAction]; [self presentViewController:errView animated:YES completion:nil]; } } #pragma mark - cbs void assistant_link_phone_number_with_account(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status, const char *resp) { AssistantLinkView *thiz = (__bridge AssistantLinkView *)(linphone_account_creator_get_user_data(creator)); thiz.waitView.hidden = YES; if (status == LinphoneAccountCreatorStatusRequestOk) { thiz.linkAccountView.hidden = thiz.activateSMSView.userInteractionEnabled = YES; NSString* phoneNumber = [NSString stringWithUTF8String:linphone_account_creator_get_phone_number(creator)]; thiz.linkSMSText.text = [NSString stringWithFormat:NSLocalizedString(@"We have sent a SMS with a validation code to %@. To complete your phone number verification, please enter the 4 digit code below:",nil), phoneNumber]; thiz.activateSMSView.hidden = thiz.linkAccountView.userInteractionEnabled = NO; } else { if (strcmp(resp, "Missing required parameters") == 0) { [thiz showErrorPopup:"ERROR_NO_PHONE_NUMBER"]; } else { [thiz showErrorPopup:resp]; } } } void assistant_activate_phone_number_link(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status, const char *resp) { AssistantLinkView *thiz = (__bridge AssistantLinkView *)(linphone_account_creator_get_user_data(creator)); thiz.waitView.hidden = YES; if (status == LinphoneAccountCreatorStatusAccountActivated) { [LinphoneManager.instance lpConfigSetInt:0 forKey:@"must_link_account_time"]; // save country code prefix if none is already entered LinphoneAccount *acc = linphone_core_get_default_account(LC); LinphoneAccountParams const *accParams = linphone_account_get_params(acc); if (linphone_account_params_get_international_prefix(accParams) == NULL) { const char *prefix = thiz.countryCodeField.text.UTF8String; LinphoneAccountParams * newPrefixAccountParams = linphone_account_params_clone(accParams); linphone_account_params_set_international_prefix(newPrefixAccountParams, prefix[0] == '+' ? &prefix[1] : prefix); linphone_account_set_params(acc, newPrefixAccountParams); linphone_account_params_unref(newPrefixAccountParams); } [PhoneMainView.instance popToView:DialerView.compositeViewDescription]; [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneAddressBookUpdate object:NULL]; [LinphoneManager.instance.fastAddressBook fetchContactsInBackGroundThread]; } else { [thiz showErrorPopup:resp]; } } #pragma mark - other - (void)updateCountry:(BOOL)force { NSDictionary *c = [CountryListView countryWithCountryCode:_countryCodeField.text]; if (c || force) { [_countryButton setTitle:c ? [c objectForKey:@"name"] : NSLocalizedString(@"Unknown country code", nil) forState:UIControlStateNormal]; } if ([[_countryButton currentTitle] isEqualToString:NSLocalizedString(@"Unknown country code", nil)]) { _countryCodeField.layer.borderWidth = .8; _countryCodeField.layer.cornerRadius = 4.f; _countryCodeField.layer.borderColor = [[UIColor redColor] CGColor]; self.linkAccountButton.enabled = FALSE; } else { _countryCodeField.layer.borderColor = [[UIColor clearColor] CGColor]; if (_phoneField.layer.borderColor != [[UIColor redColor] CGColor]) { self.linkAccountButton.enabled = TRUE; } } } - (IBAction)onCountryCodeFieldChange:(id)sender { [self updateCountry:NO]; } - (IBAction)onCountryCodeFieldEnd:(id)sender { [self updateCountry:YES]; } - (IBAction)onCountryClick:(id)sender { self.firstTime = FALSE; CountryListView *view = VIEW(CountryListView); [view setDelegate:(id)self]; [PhoneMainView.instance changeCurrentView:view.compositeViewDescription]; } - (IBAction)onLinkAccount:(id)sender { _waitView.hidden = NO; NSString *newStr = [_countryCodeField.text substringWithRange:NSMakeRange(1, [_countryCodeField.text length]-1)]; linphone_account_creator_set_phone_number(account_creator, _phoneField.text.UTF8String, newStr.UTF8String); NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0]; linphone_account_creator_set_language(account_creator, [[language substringToIndex:2] UTF8String]); linphone_account_creator_link_account(account_creator); } - (IBAction)onCheckValidationButton:(id)sender { _waitView.hidden = NO; linphone_account_creator_set_activation_code(account_creator, _activationCodeField.text.UTF8String); linphone_account_creator_activate_alias(account_creator); } - (IBAction)onDialerClick:(id)sender { [PhoneMainView.instance popCurrentView]; } - (IBAction)onPhoneNumberDisclosureClick:(id)sender { UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"What will my phone number be used for?", nil) message:NSLocalizedString(@"Your friends will find your more easily if you link your account to your " @"phone number. \n\nYou will see in your address book who is using " @"Linphone and your friends will know that they can reach you on Linphone " @"as well. \n\nYou can use your phone number with only one Linphone " @"account. If you had already linked your number to an other account but " @"you prefer to use this one, simply link it now and your number will " @"automatically be moved to this account.", nil) preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}]; [errView addAction:defaultAction]; [self presentViewController:errView animated:YES completion:nil]; } - (IBAction)onMaybeLater:(id)sender { [PhoneMainView.instance popToView:DialerView.compositeViewDescription]; } #pragma mark - select country delegate - (void)didSelectCountry:(NSDictionary *)country { [_countryButton setTitle:[country objectForKey:@"name"] forState:UIControlStateNormal]; _countryCodeField.text = [country objectForKey:@"code"]; } #pragma mark - UITextFieldDelegate Functions - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { //remove the + from the country code to avoir error when checking its validity NSString *newStr = [_countryCodeField.text substringWithRange:NSMakeRange(1, [_countryCodeField.text length]-1)]; LinphoneAccountCreatorStatus status = linphone_account_creator_set_phone_number(account_creator, [_phoneField.text UTF8String], [newStr UTF8String]); if (status == LinphoneAccountCreatorPhoneNumberStatusTooLong || status == LinphoneAccountCreatorPhoneNumberStatusTooShort) { self.phoneField.layer.borderWidth = .8; self.phoneField.layer.cornerRadius = 4.f; self.phoneField.layer.borderColor = [[UIColor redColor] CGColor]; self.linkAccountButton.enabled = FALSE; } else { self.phoneField.layer.borderColor = [[UIColor clearColor] CGColor]; if (_countryCodeField.layer.borderColor != [[UIColor redColor] CGColor]){ self.linkAccountButton.enabled = TRUE; } } return YES; } @end