// // SettingsController.swift // Befund // // Created by Artur Savitskiy on 21.07.22. // Copyright © 2022 MVZ Dr. Stein und Kollegen. All rights reserved. // import Foundation import UIKit class SettingsController: UIViewController, UITextFieldDelegate, UpdatingParentCheckBox { public enum PopupType: Int { case Setting case ChangePWD case Support case FAQ case AGB } private var Settings: Core.Models.Settings? = nil @IBOutlet weak var settingsContent: UIView! @IBOutlet weak var LBL_TITLE: UILabel! @IBOutlet weak var LBL_REGISTER: UILabel! @IBOutlet weak var menuContent_btnBack: UIButton! //@IBOutlet weak var menuContent_labelBack: UILabel! @IBOutlet weak var menuContent_btnSettings: UIButton! @IBOutlet weak var menuContent_btnChangePassword: UIButton! @IBOutlet weak var menuContent_btnSupport: UIButton! @IBOutlet weak var menuContent_btnFAQ: UIButton! @IBOutlet weak var menuContent_btnAGB: UIButton! //Settings-Popup @IBOutlet weak var PopupSettings_Overlay: UIView! @IBOutlet weak var PopupSettings: UIView! @IBOutlet weak var menuSettingsView: UIView! @IBOutlet weak var menuChangePWDView: UIView! @IBOutlet weak var menuSupportView: UIView! @IBOutlet weak var menuFAQView: UIView! @IBOutlet weak var menuAGBView: UIView! @IBOutlet weak var popupSettings_labelSettings: UILabel! @IBOutlet weak var popupSettings_labelYourLabor: UILabel! @IBOutlet weak var popupSettings_labelName: UILabel! @IBOutlet weak var popupSettings_labelStreet: UILabel! @IBOutlet weak var popupSettings_labelCity: UILabel! @IBOutlet weak var popupSettings_labelTel: UILabel! @IBOutlet weak var popupSettings_labelWeb: UILabel! @IBOutlet weak var popupSettings_labelStatus: UILabel! @IBOutlet weak var popupSettings_laborLogo: UIImageView! @IBOutlet weak var popupSettings_labelLanguage: UILabel! @IBOutlet weak var popupSettings_btnDE: UIButton! @IBOutlet weak var popupSettings_markerDE: UIView! @IBOutlet weak var popupSettings_btnEN: UIButton! @IBOutlet weak var popupSettings_markerEN: UIView! @IBOutlet weak var popupSettings_btnBack: UIButton! //ChangePassword-Popup @IBOutlet weak var PopupChangePWD_Overlay: UIView! @IBOutlet weak var PopupChangePWD: UIView! @IBOutlet weak var popupChangePWD_btnBack: UIButton! @IBOutlet weak var popupChangePWD_btnChange: UIButton! @IBOutlet weak var popupChangePWD_Loading: UIActivityIndicatorView! @IBOutlet weak var popupChangePWD_Status: UILabel! @IBOutlet weak var popupChangePWD_txtOldPassword: UITextField! @IBOutlet weak var popupChangePWD_txtNewPassword: UITextField! @IBOutlet weak var popupChangePWD_txtNewPasswordConfirm: UITextField! @IBOutlet weak var popupChangePWD_txtNewPin: UITextField! @IBOutlet weak var popupChangePWD_labPwdHinweis: UILabel! //private let faqLink = "https://www.limbachgruppe.com/fileadmin/downloads/098672600.html" @IBOutlet var PopupPrivatePolicy_Checkbox: CheckBoxButton! public var confirmCheckBox: CheckBoxButton! { get { return PopupPrivatePolicy_Checkbox } } override func viewDidLoad() { super.viewDidLoad() self.Initialize() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) self.InitLabels() self.EnableButtonViews() } override func loadView() { super.loadView() } /** * Initializes view */ private func Initialize() { Settings = Core.Models.Settings.loadFromFile(atPath: Core.System.SettingsPath()) self.PopupSettings_Overlay.frame = self.view.frame self.view.addSubview(self.PopupSettings_Overlay) self.PopupSettings_Overlay.isHidden = true self.PopupChangePWD_Overlay.frame = self.view.frame self.view.addSubview(self.PopupChangePWD_Overlay) self.PopupChangePWD_Overlay.isHidden = true self.popupSettings_btnDE.tag = 0 self.popupSettings_btnEN.tag = 1 self.MarkSelectedLanguage(lang: Settings?.lang) self.popupChangePWD_txtOldPassword.delegate = self self.popupChangePWD_txtOldPassword.returnKeyType = .next self.popupChangePWD_txtNewPassword.delegate = self self.popupChangePWD_txtNewPassword.returnKeyType = .next self.popupChangePWD_txtNewPasswordConfirm.delegate = self self.popupChangePWD_txtNewPasswordConfirm.returnKeyType = .next self.popupChangePWD_txtNewPin.delegate = self self.popupChangePWD_txtNewPin.returnKeyType = .done self.popupChangePWD_labPwdHinweis.text = "" self.popupChangePWD_labPwdHinweis.isHidden = false self.popupChangePWD_txtNewPassword.addTarget(self, action: #selector(self.ShowPWDHinweis), for: .editingDidBegin) self.popupChangePWD_txtNewPassword.addTarget(self, action: #selector(self.HidePWDHinweis), for: .editingDidEnd) self.popupChangePWD_txtNewPasswordConfirm.addTarget(self, action: #selector(self.ShowPWDHinweis), for: .editingDidBegin) self.popupChangePWD_txtNewPasswordConfirm.addTarget(self, action: #selector(self.HidePWDHinweis), for: .editingDidEnd) self.popupChangePWD_txtNewPin.addTarget(self, action: #selector(self.ShowPinHinweis), for: .editingDidBegin) self.popupChangePWD_txtNewPin.addTarget(self, action: #selector(self.HidePWDHinweis), for: .editingDidEnd) self.addDoneToolbar([popupChangePWD_txtOldPassword, popupChangePWD_txtNewPassword, popupChangePWD_txtNewPasswordConfirm, popupChangePWD_txtNewPin]) self.hideKeyboardWhenTappedAround() } @objc func ShowPWDHinweis() { self.popupChangePWD_Status.text = "" self.popupChangePWD_labPwdHinweis.text = Core.Lang.Get(key: "ERROR_ENTER_STRONG_PASSWORD") self.popupChangePWD_labPwdHinweis.isHidden = false } @objc func ShowPinHinweis() { self.popupChangePWD_Status.text = "" self.popupChangePWD_labPwdHinweis.text = Core.Lang.Get(key: "ERROR_PIN_LENGTH") self.popupChangePWD_labPwdHinweis.isHidden = false } @objc func HidePWDHinweis() { self.popupChangePWD_labPwdHinweis.text = "" self.popupChangePWD_labPwdHinweis.isHidden = true } internal func textFieldShouldReturn(_ textField: UITextField) -> Bool { self.switchBasedNextTextField(textField) return true } private func switchBasedNextTextField(_ textField: UITextField) { switch textField { case self.popupChangePWD_txtOldPassword: self.popupChangePWD_txtNewPassword.becomeFirstResponder() case self.popupChangePWD_txtNewPassword: self.popupChangePWD_txtNewPasswordConfirm.becomeFirstResponder() case self.popupChangePWD_txtNewPasswordConfirm: self.popupChangePWD_txtNewPin.becomeFirstResponder() default: self.view.endEditing(true) } } private func EnableButtonViews() { let pwdIsNotDefined = ((AppDelegate.Session.DevicePassword ?? "").count == 0) self.LBL_REGISTER.isHidden = !pwdIsNotDefined self.menuSettingsView.isHidden = pwdIsNotDefined self.menuChangePWDView.isHidden = pwdIsNotDefined let fullHeight = self.settingsContent.frame.size.height var showHeight = self.LBL_TITLE.frame.size.height showHeight += (pwdIsNotDefined ? self.LBL_REGISTER.frame.size.height : 0) showHeight += (!pwdIsNotDefined ? self.menuSettingsView.frame.size.height : 0) showHeight += (!pwdIsNotDefined ? self.menuChangePWDView.frame.size.height : 0) showHeight += self.menuSupportView.frame.size.height showHeight += self.menuFAQView.frame.size.height showHeight += self.menuAGBView.frame.size.height var begY = (fullHeight - showHeight) / 2 var vFrame = self.LBL_TITLE.frame vFrame.origin.y = begY self.LBL_TITLE.frame = vFrame begY += self.LBL_TITLE.frame.size.height if(pwdIsNotDefined) { vFrame = self.LBL_REGISTER.frame vFrame.origin.y = begY self.LBL_REGISTER.frame = vFrame begY += self.LBL_REGISTER.frame.size.height } if(!pwdIsNotDefined) { vFrame = self.menuSettingsView.frame vFrame.origin.y = begY self.menuSettingsView.frame = vFrame begY += self.menuSettingsView.frame.size.height vFrame = self.menuChangePWDView.frame vFrame.origin.y = begY self.menuChangePWDView.frame = vFrame begY += self.menuChangePWDView.frame.size.height } vFrame = self.menuSupportView.frame vFrame.origin.y = begY self.menuSupportView.frame = vFrame begY += self.menuSupportView.frame.size.height vFrame = self.menuFAQView.frame vFrame.origin.y = begY self.menuFAQView.frame = vFrame begY += self.menuFAQView.frame.size.height vFrame = self.menuAGBView.frame vFrame.origin.y = begY self.menuAGBView.frame = vFrame begY += self.menuAGBView.frame.size.height } private func MarkSelectedLanguage(lang: Core.Lang.Languages?) { if (lang == Core.Lang.Languages.EN) { self.popupSettings_markerDE.isHidden=true self.popupSettings_markerEN.isHidden=false } else { self.popupSettings_markerDE.isHidden=false self.popupSettings_markerEN.isHidden=true } } private func InitLabels() { self.LBL_TITLE.text = Core.Lang.Get(key: "LBL_MENU") self.LBL_REGISTER.text = Core.Lang.Get(key: "MSG_YOU_ARE_NOT_REGISTERED") self.menuContent_btnSettings.setTitle(Core.Lang.Get(key: "BTN_SETTINGS"), for: .normal) self.menuContent_btnSettings.tag = PopupType.Setting.rawValue self.menuContent_btnChangePassword.setTitle(Core.Lang.Get(key: "BTN_CHANGE_PASSWORD"), for: .normal) self.menuContent_btnChangePassword.tag = PopupType.ChangePWD.rawValue self.menuContent_btnSupport.setTitle(Core.Lang.Get(key: "BTN_SUPPORT"), for: .normal) self.menuContent_btnSupport.tag = PopupType.Support.rawValue self.menuContent_btnFAQ.setTitle(Core.Lang.Get(key: "BTN_FAQ"), for: .normal) self.menuContent_btnFAQ.tag = PopupType.FAQ.rawValue self.menuContent_btnAGB.setTitle(Core.Lang.Get(key: "LBL_PRIVACY_POLICY"), for: .normal) self.menuContent_btnAGB.tag = PopupType.AGB.rawValue self.menuContent_btnBack.setTitle("", for: .normal) //self.menuContent_labelBack.text = Core.Lang.Get(key: "BTN_CLOSE") self.popupSettings_btnBack.setTitle(Core.Lang.Get(key: "BTN_CLOSE"), for: .normal) self.popupSettings_btnBack.tag = PopupType.Setting.rawValue self.popupSettings_labelLanguage.text = Core.Lang.Get(key: "LBL_LANGUAGE") //popup "Password change" self.popupChangePWD_btnChange.setTitle(Core.Lang.Get(key: "BTN_CHANGE"), for: .normal) self.popupChangePWD_btnBack.setTitle(Core.Lang.Get(key: "BTN_BACK"), for: .normal) self.popupChangePWD_btnBack.tag = PopupType.ChangePWD.rawValue self.popupChangePWD_Loading.isHidden = true self.popupChangePWD_Loading.stopAnimating() self.popupChangePWD_txtOldPassword.placeholder = Core.Lang.Get(key: "LBL_CURRENT_PASSWORD") self.popupChangePWD_txtOldPassword.enablePasswordToggle() self.popupChangePWD_txtNewPassword.placeholder = Core.Lang.Get(key: "LBL_NEW_PASSWORD") self.popupChangePWD_txtNewPassword.enablePasswordToggle() self.popupChangePWD_txtNewPasswordConfirm.placeholder = Core.Lang.Get(key: "LBL_PASSWORD_CONFIRM") self.popupChangePWD_txtNewPasswordConfirm.enablePasswordToggle() self.popupChangePWD_txtNewPin.placeholder = Core.Lang.Get(key: "LBL_NEW_PIN") self.popupSettings_labelSettings.text = Core.Lang.Get(key: "LBL_YOUR_LABOR") self.popupSettings_labelYourLabor.text = "" if(Settings?.labor != nil) { self.popupSettings_labelName.text = Settings?.labor?.name self.popupSettings_labelStreet.text = Settings?.labor?.street self.popupSettings_labelCity.text = Settings?.labor?.city self.popupSettings_labelTel.text = Settings?.labor?.tel self.popupSettings_labelWeb.text = Settings?.labor?.web self.popupSettings_laborLogo.image = Settings?.labor?.logo if(AppDelegate.Session.Maintenance) { self.popupSettings_labelStatus.text = Core.Lang.Get(key: "MSG_MAINTENANCE") self.popupSettings_labelStatus.backgroundColor = UIColor.red } else { self.CheckHostLabor() } } } @IBAction func BtnFAQ_Click(_ sender: Any) { //var localUrl = getLocalFAQLink() //guard let url = URL(string: localUrl) else { // localUrl = faqLink // return //} let localUrl = Core.Lang.Get(key: "FAQ_LINK") let settingsAGBController = AGBPolicyController.InitWebViewController(url: localUrl, previewOnly: true, btnText: Core.Lang.Get(key: "BTN_BACK"), labText: "FAQ") settingsAGBController.modalPresentationStyle = .fullScreen let transition = CATransition() transition.duration = 0.25 transition.type = .push transition.subtype = .fromRight self.view.window!.layer.add(transition, forKey: kCATransition) self.present(settingsAGBController, animated: false) //self.ShowFAQInWeb() } private func getLocalFAQLink() -> String { let baseURL = Bundle.main.path(forResource: "faq", ofType: "html") return baseURL ?? "" } private func ShowFAQInWeb() { let faqLink = Core.Lang.Get(key: "FAQ_LINK") guard let url = URL(string: faqLink) else { return } let localUrl = URL(string: getLocalFAQLink()) ?? url let vc = WebViewController(url: url, title: Core.Lang.Get(key: "BTN_BACK"), localUrl: localUrl) vc.parentView = self let navVC = UINavigationController(rootViewController: vc) present(navVC, animated: true) } private func CheckHostLabor() { let requestKeyPair = Core.Security.Curve25519.GenerateKeyPair() let currentHost = (Settings?.labor?.host) Core.Https.Request.KeyExchangeAsync(host: currentHost!, keyPair: requestKeyPair, onSuccess: { publicKey in DispatchQueue.main.async { self.popupSettings_labelStatus.text = Core.Lang.Get(key: "LBL_CONNECTED") self.popupSettings_labelStatus.backgroundColor = UIColor.green } }, onError: { error in DispatchQueue.main.async { self.popupSettings_labelStatus.text = Core.Lang.Get(key: "LBL_DISCONNECTED") self.popupSettings_labelStatus.backgroundColor = UIColor.red } }) } @IBAction func goBack(_ sender: Any) { self.view.endEditing(true) self.dismiss(animated: true, completion: nil) } @IBAction func ButtonSupportOpenClick(_ sender: Any) { let storyboard = UIStoryboard(name: "Main", bundle: nil) let settingsSupportController = storyboard.instantiateViewController(identifier: "SupportController") settingsSupportController.modalPresentationStyle = .fullScreen let transition = CATransition() transition.duration = 0.25 transition.type = .push transition.subtype = .fromRight self.view.window!.layer.add(transition, forKey: kCATransition) self.present(settingsSupportController, animated: false) } @IBAction func ButtonAGBOpenClick(_ sender: Any) { let localUrl = Core.Lang.Get(key: "AGB_POLICY_LINK") let settingsAGBController = AGBPolicyController.InitWebViewController(url: localUrl, previewOnly: true, btnText: Core.Lang.Get(key: "BTN_BACK"), labText: "Datenschutzerklärung") settingsAGBController.modalPresentationStyle = .fullScreen let transition = CATransition() transition.duration = 0.25 transition.type = .push transition.subtype = .fromRight self.view.window!.layer.add(transition, forKey: kCATransition) self.present(settingsAGBController, animated: false) } @IBAction func PopupSettingsShow(_ sender: Any) { let popupT = PopupType(rawValue: (sender as! UIButton).tag) var popupOverlay: UIView! = nil var popup: UIView! = nil switch popupT { case .Setting: popupOverlay = self.PopupSettings_Overlay popup = self.PopupSettings break case .ChangePWD: self.popupChangePWD_txtOldPassword.text = "" self.popupChangePWD_txtNewPassword.text = "" self.popupChangePWD_txtNewPasswordConfirm.text = "" popupOverlay = self.PopupChangePWD_Overlay popup = self.PopupChangePWD break case .Support: break default: break } if (popup != nil) { popup.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) popupOverlay.alpha = 0.0 popupOverlay.isHidden = false UIView.animate(withDuration: 0.24) { popup.transform = CGAffineTransform.identity popupOverlay.alpha = 70.0 } } } @IBAction func PopupSettings_BtnBackClick(_ sender: Any) { let popupT = PopupType(rawValue: (sender as! UIButton).tag) self.HidePopup(popupType: popupT!) } private func HidePopup(popupType: PopupType) { var popupOverlay: UIView! = nil var popup: UIView! = nil switch popupType { case .Setting: popupOverlay = self.PopupSettings_Overlay popup = self.PopupSettings break case .ChangePWD: popupOverlay = self.PopupChangePWD_Overlay popup = self.PopupChangePWD break case .Support: break default: break } if (popup != nil) { UIView.animate(withDuration: 0.24, animations: { popupOverlay.alpha = 0.0 popup.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) }) {_ in popupOverlay.isHidden = true } } } @IBAction func PopupSettings_BtnLangClick(_ sender: Any) { let curBut = sender as! UIButton let curType = curBut.tag switch curType { case 1: Core.Lang.SetLanguage(lang: Core.Lang.Languages.EN) Settings?.lang = Core.Lang.Languages.EN break default: Core.Lang.SetLanguage(lang: Core.Lang.Languages.DE) Settings?.lang = Core.Lang.Languages.DE break } self.MarkSelectedLanguage(lang: Settings?.lang) Settings?.save(atPath: Core.System.SettingsPath()) self.InitLabels() } private func PasswordActivity_HideLoading(message: String) { self.popupChangePWD_Loading.isHidden = true if(!message.isEmpty) { self.popupChangePWD_Status.text = message } } @IBAction func popupPasswordChange_BtnChangeClick() { self.popupChangePWD_Loading.isHidden=false self.popupChangePWD_Loading.startAnimating() let old_password = self.popupChangePWD_txtOldPassword.text ?? "" if(old_password.count == 0) { self.PasswordActivity_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_OLD_PASSWORD")) } else { let tmp_decrypted_key = Core.Security.AES.Decrypt(value: SettingsController.Settings?.hashed_private_key ?? "", password: String( decoding:Core.Security.AES.GetKey(password: old_password), as: UTF8.self)) if(tmp_decrypted_key != nil) { let newPass = self.popupChangePWD_txtNewPassword.text ?? "" let confirmPass = self.popupChangePWD_txtNewPasswordConfirm.text ?? "" let pinNew = self.popupChangePWD_txtNewPin.text ?? "" if(!Core.Models.Request.ChangeVerificatorHashProvider.IsPasswordStrong(password: newPass)) { self.PasswordActivity_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_STRONG_PASSWORD")) } else if(newPass != confirmPass) { self.PasswordActivity_HideLoading(message: Core.Lang.Get(key: "ERROR_PASSWORD_MISMATCH")) } else if(pinNew.count == 0) { self.PasswordActivity_HideLoading( message: Core.Lang.Get(key: "ERROR_ENTER_PIN")) } else if(pinNew.count != 5) { self.PasswordActivity_HideLoading( message: Core.Lang.Get(key: "ERROR_PIN_LENGTH")) } else { self.popupChangePWD_Status.text = "" let newPassAESkey = Core.Security.AES.GetKey(password: newPass) let decrypted_private_key = Core.Security.AES.Decrypt(value: SettingsController.Settings?.hashed_private_key ?? "", password: String( decoding:Core.Security.AES.GetKey(password: old_password), as: UTF8.self)) var requestKeyPair = Core.Security.Curve25519.GenerateKeyPair(); let changeVerificatorHash = Core.Models.Request.ChangeVerificatorHash() changeVerificatorHash.old_verificator_hash = SettingsController.Settings?.verificator_hash changeVerificatorHash.new_verificator_hash = Core.Security.SHA512.HMAC(message: Core.Security.SHA512.VerificatorHashingValue.data(using: .utf8)!, key: String(decoding: newPassAESkey, as: UTF8.self)) changeVerificatorHash.udid = SettingsController.Settings?.udid changeVerificatorHash.pin = pinNew let results = Core.Database.Results.GetResults() if(results != nil && results!.count>0) { for res in results! { let file = Core.System.GetPathForStorageEncryptedFile(filename: res.pgs!) if(file != nil && Core.System.FileExists(atPath: file!)) { let encrypted_content = Core.System.ReadFromEncryptedStorage(filename: res.pgs!) if(!encrypted_content!.isEmpty) { let oldKey=Core.Security.AES.GetKey(password: old_password) let decrypted_content = Core.Security.AES.Decrypt( value: String (decoding: encrypted_content!, as: UTF8.self), password: String(decoding: oldKey, as: UTF8.self)) if(decrypted_content != nil) { let newKey = Core.Security.AES.GetKey(password: newPass) let local_encrypted = Core.Security.AES.Encrypt( value: decrypted_content!, password: String(decoding: newKey, as: UTF8.self)) if(local_encrypted != nil) { Core.System.WriteToEncryptedStorage(filename: res.pgs!, data: local_encrypted!.data(using: .utf8)!) } } } } } } requestKeyPair = Core.Security.Curve25519.GenerateKeyPair() let currentHost = ViewController.Settings!.labor?.host ?? .DEVELOPMENT Core.Https.Request.KeyExchangeAsync(host: (ViewController.Settings!.labor?.host ?? .DEVELOPMENT), keyPair: requestKeyPair, onSuccess: { publicKey in let sharedKey = requestKeyPair.GetSharedKey(peerPublicKeyBase64: publicKey.key) let encryptedRequest = Core.Models.Request.EncryptedRequest(descriptor: "ChangeVerificatorHash", contentObject: changeVerificatorHash, requestType: .REQUEST_VERIFICATOR_HASH, key: sharedKey!) Core.Https.Request.EncryptedRequestAsync(host: currentHost, controller: "results", action: "update_verificator_hash", request: encryptedRequest, serverPublicKey: publicKey, keyPair: requestKeyPair, onSuccess: { encryptedResponse in encryptedResponse.Decrypt(key: sharedKey!) DispatchQueue.main.async { if(encryptedResponse.descriptor!.lowercased() == "success") { let keyNewPass = Core.Security.AES.GetKey(password: newPass) SettingsController.Settings!.password_reset_hash = NSUUID().uuidString let pwdPlus = (SettingsController.Settings!.password_reset_hash ?? "") + changeVerificatorHash.pin! let passwordHashKey = Core.Security.AES.GetKey( password: pwdPlus) SettingsController.Settings!.password_hash = Core.Security.AES.Encrypt(value: newPass, password: String(decoding: passwordHashKey, as: UTF8.self)) SettingsController.Settings!.verificator_hash = Core.Security.SHA512.HMAC( message: Core.Security.SHA512.VerificatorHashingValue.data(using: .utf8)!, key: String(decoding: keyNewPass, as: UTF8.self)) SettingsController.Settings!.hashed_private_key = Core.Security.AES.Encrypt(value: decrypted_private_key!, password: String(decoding: keyNewPass, as: UTF8.self)) if(!SettingsController.Settings!.save(atPath: Core.System.SettingsPath())) { self.PasswordActivity_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_SAVE")) Core.Log.Critical(msg: "Could not save settings to the file", namespace: "SettingsController", method: "PasswordChange") } else { ViewController.Settings = Core.Models.Settings.loadFromFile(atPath: Core.System.SettingsPath()) } AppDelegate.Session.DevicePassword = newPass self.PasswordActivity_HideLoading(message: "") DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.HidePopup(popupType: PopupType.ChangePWD) self.ShowMessagePopup(title: "", message: Core.Lang.Get(key: "MSG_PASSWORD_HAS_BEEN_CHANGED").replacingOccurrences(of: "[PIN]", with: changeVerificatorHash.pin!)) } } else { self.PasswordActivity_HideLoading(message: encryptedResponse.descriptor!) } } }, onError: { error in DispatchQueue.main.async { self.PasswordActivity_HideLoading(message: error) Core.Log.Critical(msg: "Server not reachable", namespace: "ViewController", method: "requestPGS") } }) }, onError: { error in DispatchQueue.main.async { self.PasswordActivity_HideLoading(message: error) Core.Log.Critical(msg: "Server not reachable", namespace: "ViewController", method: "requestPGS") } }) } } else { self.PasswordActivity_HideLoading(message: Core.Lang.Get(key: "ERROR_INVALID_PASSWORD")) } } } }