EnterLicenseViewController.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // _____ _
  2. // |_ _| |_ _ _ ___ ___ _ __ __ _
  3. // | | | ' \| '_/ -_) -_) ' \/ _` |_
  4. // |_| |_||_|_| \___\___|_|_|_\__,_(_)
  5. //
  6. // Threema iOS Client
  7. // Copyright (c) 2016-2020 Threema GmbH
  8. //
  9. // This program is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU Affero General Public License, version 3,
  11. // as published by the Free Software Foundation.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU Affero General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Affero General Public License
  19. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. #import "EnterLicenseViewController.h"
  21. #import "LicenseStore.h"
  22. #import "ServerConnector.h"
  23. #import "BundleUtil.h"
  24. #import "UIDefines.h"
  25. #import "ServerAPIRequest.h"
  26. #import "MDMSetup.h"
  27. #import "UIImage+ColoredImage.h"
  28. #import "WorkDataFetcher.h"
  29. #ifdef DEBUG
  30. static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
  31. #else
  32. static const DDLogLevel ddLogLevel = DDLogLevelWarning;
  33. #endif
  34. @interface EnterLicenseViewController () <UITextFieldDelegate, ZSWTappableLabelTapDelegate>
  35. @property LicenseStore *licenseStore;
  36. @end
  37. @implementation EnterLicenseViewController
  38. - (void)viewDidLoad {
  39. [super viewDidLoad];
  40. _confirmButton.layer.cornerRadius = 3;
  41. _licenseUsernameTextField.layer.cornerRadius = 3;
  42. _licensePasswordTextField.layer.cornerRadius = 3;
  43. _feedbackView.textColor = [UIColor whiteColor];
  44. _feedbackView.numberOfLines = 5;
  45. _descriptionLabel.text = [BundleUtil localizedStringForKey:@"enter_license_description"];
  46. [_confirmButton setTitle:[BundleUtil localizedStringForKey:@"next"] forState:UIControlStateNormal];
  47. NSString *placeholder = [BundleUtil localizedStringForKey:@"enter_license_username_placeholder"];
  48. _licenseUsernameTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:placeholder attributes:@{NSForegroundColorAttributeName: THREEMA_COLOR_PLACEHOLDER}];
  49. _licenseUsernameTextField.delegate = self;
  50. placeholder = [BundleUtil localizedStringForKey:@"enter_license_password_placeholder"];
  51. _licensePasswordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:placeholder attributes:@{NSForegroundColorAttributeName: THREEMA_COLOR_PLACEHOLDER}];
  52. _licensePasswordTextField.delegate = self;
  53. _licenseStore = [LicenseStore sharedLicenseStore];
  54. _licenseUsernameTextField.text = _licenseStore.licenseUsername;
  55. _licensePasswordTextField.text = _licenseStore.licensePassword;
  56. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateLicenseText) name:kNotificationLicenseMissing object:nil];
  57. UITapGestureRecognizer *mainTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedMainView:)];
  58. mainTapGesture.cancelsTouchesInView = false;
  59. [self.view addGestureRecognizer:mainTapGesture];
  60. self.threemaAppLinkLabel.font = [UIFont systemFontOfSize:16.0];
  61. self.threemaAppLinkLabel.tapDelegate = self;
  62. self.threemaAppLinkLabel.exclusiveTouch = true;
  63. NSDictionary *normalAttributes = @{NSFontAttributeName: _threemaAppLinkLabel.font, NSForegroundColorAttributeName: [UIColor whiteColor]};
  64. NSDictionary *linkAttributes = @{@"ZSWTappableLabelTappableRegionAttributeName": @YES,
  65. @"ZSWTappableLabelHighlightedForegroundAttributeName": [Colors red],
  66. NSForegroundColorAttributeName: [Colors privacyPolicyLink],
  67. NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),
  68. @"NSTextCheckingResult": @1
  69. };
  70. NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:[BundleUtil localizedStringForKey:@"enter_license_info"] attributes:normalAttributes];
  71. [attributedString addAttributes:linkAttributes range:[[BundleUtil localizedStringForKey:@"enter_license_info"] rangeOfString:[BundleUtil localizedStringForKey:@"enter_license_info_link"]]];
  72. _threemaAppLinkLabel.attributedText = attributedString;
  73. _confirmButton.backgroundColor = [Colors mainThemeDark];
  74. [_confirmButton setTitleColor:[Colors fontNormal] forState:UIControlStateNormal];
  75. _licenseUsernameTextField.tintColor = [Colors mainThemeDark];
  76. _licensePasswordTextField.tintColor = [Colors mainThemeDark];
  77. }
  78. - (void)dealloc {
  79. [[NSNotificationCenter defaultCenter] removeObserver:self];
  80. }
  81. - (void)updateLicenseText {
  82. dispatch_async(dispatch_get_main_queue(), ^{
  83. _licenseUsernameTextField.text = _licenseStore.licenseUsername;
  84. _licensePasswordTextField.text = _licenseStore.licensePassword;
  85. if (_licenseStore.errorMessage && ![_licenseStore.errorMessage isEqualToString:@"License username/password too short"]) {
  86. [_licenseUsernameTextField resignFirstResponder];
  87. [_licensePasswordTextField resignFirstResponder];
  88. _feedbackView.hidden = NO;
  89. _confirmButton.hidden = YES;
  90. [_feedbackView showErrorMessage:_licenseStore.errorMessage];
  91. }
  92. });
  93. }
  94. - (void)hideKeyboard {
  95. [_licenseUsernameTextField resignFirstResponder];
  96. [_licensePasswordTextField resignFirstResponder];
  97. }
  98. - (void)viewWillAppear:(BOOL)animated {
  99. [super viewWillAppear:animated];
  100. _keyImageView.image = [UIImage imageNamed:@"Key" inColor:[UIColor whiteColor]];
  101. [_licenseUsernameTextField becomeFirstResponder];
  102. [self updateConfirmButton];
  103. }
  104. - (BOOL)prefersStatusBarHidden {
  105. return YES;
  106. }
  107. -(UIInterfaceOrientationMask)supportedInterfaceOrientations {
  108. if (SYSTEM_IS_IPAD) {
  109. return UIInterfaceOrientationMaskAll;
  110. } else {
  111. return UIInterfaceOrientationMaskPortrait;
  112. }
  113. }
  114. - (void)updateConfirmButton {
  115. [self updateConfirmButtonUsername:_licenseUsernameTextField.text password:_licensePasswordTextField.text];
  116. }
  117. - (void)updateConfirmButtonUsername:(NSString*)username password:(NSString*)password {
  118. if (username.length > 0 && password.length > 0) {
  119. _confirmButton.enabled = YES;
  120. _confirmButton.alpha = 1.0;
  121. } else {
  122. _confirmButton.enabled = NO;
  123. _confirmButton.alpha = 0.7;
  124. }
  125. _confirmButton.hidden = NO;
  126. }
  127. #pragma mark - actions
  128. - (IBAction)confirmAction:(id)sender {
  129. [self updateConfirmButton];
  130. if (!_confirmButton.enabled)
  131. return;
  132. _feedbackView.hidden = NO;
  133. _confirmButton.hidden = YES;
  134. [_feedbackView showActivityIndicator];
  135. _feedbackView.text = [BundleUtil localizedStringForKey:@"enter_license_checking"];
  136. [_licenseUsernameTextField resignFirstResponder];
  137. [_licensePasswordTextField resignFirstResponder];
  138. [_licenseStore setLicenseUsername:_licenseUsernameTextField.text];
  139. [_licenseStore setLicensePassword:_licensePasswordTextField.text];
  140. [_licenseStore performLicenseCheckWithCompletion:^(BOOL success) {
  141. dispatch_async(dispatch_get_main_queue(), ^{
  142. if (success) {
  143. [WorkDataFetcher checkUpdateThreemaMDM:^{
  144. dispatch_async(dispatch_get_main_queue(), ^{
  145. [_feedbackView hideActivityIndicator];
  146. [_feedbackView showSuccessMessage:[BundleUtil localizedStringForKey:@"ok"]];
  147. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1000 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
  148. [_delegate licenseConfirmed];
  149. });
  150. });
  151. } onError:^(NSError *error) {
  152. dispatch_async(dispatch_get_main_queue(), ^{
  153. [_feedbackView hideActivityIndicator];
  154. [_feedbackView showErrorMessage:_licenseStore.errorMessage];
  155. // disable button, user has to change key first
  156. _confirmButton.enabled = NO;
  157. _confirmButton.alpha = 0.7;
  158. });
  159. }];
  160. } else {
  161. [_feedbackView hideActivityIndicator];
  162. [_feedbackView showErrorMessage:_licenseStore.errorMessage];
  163. // disable button, user has to change key first
  164. _confirmButton.enabled = NO;
  165. _confirmButton.alpha = 0.7;
  166. }
  167. });
  168. }];
  169. }
  170. #pragma mark - UITextFieldDelegate
  171. - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
  172. NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];
  173. if (textField == _licenseUsernameTextField)
  174. [self updateConfirmButtonUsername:newText password:_licensePasswordTextField.text];
  175. else
  176. [self updateConfirmButtonUsername:_licenseUsernameTextField.text password:newText];
  177. return YES;
  178. }
  179. - (void)textFieldDidBeginEditing:(UITextField *)textField {
  180. _confirmButton.hidden = NO;
  181. _feedbackView.hidden = YES;
  182. }
  183. - (BOOL)textFieldShouldReturn:(UITextField *)textField {
  184. if (textField == _licenseUsernameTextField) {
  185. [_licensePasswordTextField becomeFirstResponder];
  186. return NO;
  187. }
  188. [self updateConfirmButton];
  189. [self confirmAction:textField];
  190. return NO;
  191. }
  192. #pragma mark - UITapGestureRecognizer
  193. - (void)tappedMainView:(UITapGestureRecognizer *)sender
  194. {
  195. if (sender.state == UIGestureRecognizerStateEnded) {
  196. [self hideKeyboard];
  197. }
  198. }
  199. #pragma mark - ZSWTappableLabel delegate
  200. - (void)tappableLabel:(ZSWTappableLabel *)tappableLabel tappedAtIndex:(NSInteger)idx withAttributes:(NSDictionary *)attributes {
  201. NSURL *appStoreUrl = [NSURL URLWithString:@"https://itunes.apple.com/app/id578665578"];
  202. if ([[UIApplication sharedApplication] canOpenURL:appStoreUrl]) {
  203. [[UIApplication sharedApplication] openURL:appStoreUrl options:@{} completionHandler:nil];
  204. }
  205. }
  206. @end