// // KMSignUpViewModel.swift // PDF Reader Pro // // Created by wanjun on 2024/10/24. // import Foundation import Combine @objc enum KMSignUpState : Int { case verificationCode = 0 // 验证码 case password // 密码 } @objc enum KMSuccessLoginJump : Int { case null = 0 // case compare // 比较表 } @objc enum KMLoginScreenType : Int { case signUp = 0 // case forgotPassword // case enterVerificationCode // case enterNewPassword // } typealias ForgotPasswordComplete = (_ success: Bool,_ msg: String) -> Void @objcMembers class KMSignUpViewModel: ObservableObject { /** 是否可视,默认不可视 */ @Published var isVisible: Bool = false /** 是否保持登录,默认保持登录 */ @Published var stayState: Bool = true /** 是否同意隐私权限 */ @Published var privacyState: Bool = false /** 登录界面是验证码验证还是邮箱验证 */ @Published var signUpState: KMSignUpState = .verificationCode /** 用户邮箱,字符串格式,默认为空 */ @Published var email: String = "" /** 用户邮箱登录的验证码,字符串格式,默认为空 */ @Published var verificationCode: String = "" /** 用户邮箱登录的密码,字符串格式,默认为空 */ @Published var password: String = "" /** 邮件 错误提示文案 */ @Published var emailErrorMessage: String = "" /** 验证码 / 密码 错误提示文案 */ @Published var passwordErrorMessage: String = "" /** 序列码按钮 文案 */ @Published var sendContent: String = NSLocalizedString("Send", tableName: "MemberCenterLocalizable", comment: "") /** 当前视图类型 */ @Published var screenType: KMLoginScreenType = .signUp @Published private var timer: AnyCancellable? private var remainingSeconds: Int = 60 var sendBoxSelect: Bool = false // MARK: Public Method func signUpStateChange(state: KMSignUpState) -> Void { if state == signUpState { return } emailErrorMessage = "" passwordErrorMessage = "" if signUpState == .verificationCode { signUpState = .password } else { signUpState = .verificationCode } } func countDown(type: KMVerificationCodeType, count: Int = 60, callback: ((Bool?, Any ...)->Void)?) -> Void { if emailErrorMessage.count > 0 || !isValidEmail() { return } getVerificationCode(type, callback: callback) sendBoxSelect = true remainingSeconds = count timer = Timer.publish(every: 1, on: .main, in: .common) .autoconnect() .sink { [weak self] _ in guard let self = self else { return } if self.remainingSeconds > 0 { self.remainingSeconds -= 1 self.sendContent = String(format: "%d", self.remainingSeconds) } else { // 倒计时结束,停止定时器 self.timer?.cancel() self.sendContent = NSLocalizedString("Resend", tableName: "MemberCenterLocalizable", comment: "") self.sendBoxSelect = false } } } /** 邮件 错误提示文案 */ func emailError() -> Bool { if emailErrorMessage.count > 0 { return true } return false } /** 验证码 / 密码 格式错误 */ func passwordError() -> Bool { if passwordErrorMessage.count > 0 { return true } return false } /** @abstract 验证邮箱是否合规 */ func isValidEmail() -> Bool { let emailRegex = "^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$" let emailTest = NSPredicate(format: "SELF MATCHES %@", emailRegex) return emailTest.evaluate(with: email) } /** @abstract 验证验证码是否合规 */ func isValidVerificationCode() -> Bool { let pattern = "^\\d{6}$" let regex = try! NSRegularExpression(pattern: pattern) return regex.firstMatch(in: verificationCode, options: [], range: NSRange(location: 0, length: verificationCode.utf16.count)) != nil } func stayStateAction() -> Void { if !stayState { UserDefaults.standard.setValue("", forKey: "MemberAccessToken") UserDefaults.standard.synchronize() } } // MARK: Private Method /** @abstract 刷新用户个人信息 */ private func refreshUserInfo(callback: ((Bool?, Any ...)->Void)?) -> Void { if KMMemberCenterManager.manager.isConnectionAvailable() == false { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Error Information", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() callback?(nil) return } KMUserInfoVCModel().refreshUserInfo(networkAlert: false) { success, msg in callback?(success) if success { KMMemberInfo.shared.isLogin = true NotificationCenter.default.post(name: NSNotification.Name(rawValue: "MemberCenterLoginSuccess"), object: nil) } else { KMMemberInfo.shared.isLogin = false } } } // MARK: Action Method /** @abstract KMSignUpView Sign Up 登录按钮响应事件 @param */ func signUpAction(callback: ((Bool?, Any ...)->Void)?) -> Void { if KMMemberCenterManager.manager.isConnectionAvailable() == false { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Error Information", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() callback?(nil) return } if email.isEmpty { emailErrorMessage = NSLocalizedString("Please enter email address", tableName: "MemberCenterLocalizable", comment: "") callback?(nil) return } if email.count <= 0 || email.count > 100 || !isValidEmail() { emailErrorMessage = NSLocalizedString("Email format error. Please enter the correct email.", tableName: "MemberCenterLocalizable", comment: "") callback?(nil) return } var code: String = "" if signUpState == .verificationCode { if verificationCode.isEmpty { passwordErrorMessage = NSLocalizedString("Please enter code", tableName: "MemberCenterLocalizable", comment: "") callback?(nil) return } if verificationCode.count <= 0 || verificationCode.count > 6 || !isValidVerificationCode() { passwordErrorMessage = NSLocalizedString("Verification code error.", tableName: "MemberCenterLocalizable", comment: "") callback?(nil) return } code = verificationCode } else if signUpState == .password { if password.count <= 0 || password.count > 30 { passwordErrorMessage = NSLocalizedString("Password cannot exceed 30 characters.", tableName: "MemberCenterLocalizable", comment: "") callback?(nil) return } code = password } if !privacyState { DispatchQueue.main.async { let alert = NSAlert() alert.messageText = NSLocalizedString("Please agree and check the above agreement first.", tableName: "MemberCenterLocalizable", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) // alert.beginSheetModal(for: NSApp.mainWindow!) let result = alert.runModal() if (result == .alertFirstButtonReturn) { self.privacyState = true } callback?(nil) } return } KMMemberCenterManager.manager.emailLogin(email: email, code: code, type: signUpState) { [weak self] success, wrapper in guard let self = self else { return } let resultDict = wrapper! as KMMemberCenterResult let msg = resultDict.msg if success { let result: KMMemberLoginResult = resultDict.login_Result! let refresh_token = result.refreshToken let access_token = result.accessToken let token_type = result.tokenType let expires_in = result.expiresIn let scope = result.scope if self.stayState { UserDefaults.standard.setValue(refresh_token, forKey: "MemberRefreshToken") UserDefaults.standard.setValue(access_token, forKey: "MemberAccessToken") UserDefaults.standard.synchronize() } else { UserDefaults.standard.setValue("", forKey: "MemberRefreshToken") UserDefaults.standard.setValue("", forKey: "MemberAccessToken") UserDefaults.standard.synchronize() } KMMemberInfo.shared.refresh_token = refresh_token! KMMemberInfo.shared.access_token = access_token! KMMemberInfo.shared.token_type = token_type! self.refreshUserInfo(callback: callback) self.timer?.cancel() self.sendContent = NSLocalizedString("Resend", tableName: "MemberCenterLocalizable", comment: "") } else { if(resultDict.code == 305) { if KMMemberCenterManager.manager.isConnectionAvailable() == false { DispatchQueue.main.async { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Error Information", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() callback?(false) } return } KMMemberCenterManager.manager.getUserDeviceList(email: self.email) { [weak self] success, result in callback?(false) guard self != nil else { return } if success { KMMemberCenterWindowController.shared.showWindow(nil) KMMemberCenterWindowController.shared.signUpViewModel = self KMMemberCenterWindowController.shared.memberCenterdeviceResult = result ?? KMMemberCenterResult(loginResult: KMMemberLoginResult(refreshToken: "", accessToken: "", tokenType: "", expiresIn: "")) } } } else { callback?(false) print("错误信息:%@", msg as Any) DispatchQueue.main.async { let alert = NSAlert() alert.messageText = NSLocalizedString(msg!, comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) let response = alert.runModal() if response == .alertFirstButtonReturn { if(resultDict.code == 317) { self.signUpState = .verificationCode self.countDown(type: .login, callback: nil) } else { } } } } } } } /** @abstract KMForgotPasswordView 登录弹窗(忘记密码)Next 按钮响应事件 @param */ func forgotPasswordNextAction(_ complete: @escaping ForgotPasswordComplete) -> Void { if KMMemberCenterManager.manager.isConnectionAvailable() == false { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Error Information", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() return } if email.count <= 0 || email.count > 100 || !isValidEmail() { emailErrorMessage = NSLocalizedString("Please enter the correct email format", tableName: "MemberCenterLocalizable", comment: "") return } if emailErrorMessage.count > 0 { return } KMMemberCenterManager.manager.emailVerification(email: email) { [weak self] success, wrapper in guard let self = self else { return } let resultDict = wrapper! as KMMemberCenterResult let msg = resultDict.msg! as String if success { complete(true, msg) } else { complete(false, msg) } } } /** @abstract KMEnterVerificationCodeView 登录弹窗(输入验证码)Next 按钮响应事件 @param */ func enterVerificationCodeNextAction(_ complete: @escaping ForgotPasswordComplete) -> Void { if KMMemberCenterManager.manager.isConnectionAvailable() == false { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Error Information", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() return } if verificationCode.count <= 0 || verificationCode.count > 6 || !isValidVerificationCode() { emailErrorMessage = NSLocalizedString("Verification code error.", tableName: "MemberCenterLocalizable", comment: "") complete(false, "") return } KMMemberCenterManager.manager.checkVerificationCode(type: .reset, account: email, code: verificationCode) { [weak self] success, wrapper in guard let self = self else { return } let resultDict = wrapper! as KMMemberCenterResult let msg = resultDict.msg let result: Bool = resultDict.result ?? false if success { complete(true, "") } else { self.passwordErrorMessage = NSLocalizedString("Verification code error.", tableName: "MemberCenterLocalizable", comment: "") complete(false, "") } } } /** @abstract 获取邮箱验证码 @param */ func getVerificationCode(_ type: KMVerificationCodeType, callback: ((Bool?, Any ...)->Void)?) -> Void { if KMMemberCenterManager.manager.isConnectionAvailable() == false { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Error Information", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() callback?(nil) return } if !isValidEmail() { emailErrorMessage = NSLocalizedString("Please enter the correct email format", tableName: "MemberCenterLocalizable", comment: "") callback?(nil) return } KMMemberCenterManager.manager.getVerificationCode(action: type, receiver: email) { [weak self] success, wrapper in callback?(success) guard let self = self else { return } let resultDict = wrapper! as KMMemberCenterResult let msg = resultDict.msg let result: Bool = resultDict.result ?? false if success { print("验证邮箱成功") } else { self.emailErrorMessage = NSLocalizedString("Please enter the correct email format", tableName: "MemberCenterLocalizable", comment: "") } } } /** @abstract 重置密码 @param */ func resetPassword(_ complete: @escaping ForgotPasswordComplete) -> Void { if KMMemberCenterManager.manager.isConnectionAvailable() == false { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Error Information", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() return } if password.count <= 0 || verificationCode.count > 30 { passwordErrorMessage = NSLocalizedString("Password error.", tableName: "MemberCenterLocalizable", comment: "") return } KMMemberCenterManager.manager.resetPassword(email: email, verifyCode: verificationCode, password: password) { [weak self] success, wrapper in guard let self = self else { return } let resultDict = wrapper! as KMMemberCenterResult let msg = resultDict.msg! as String let result: Bool = resultDict.result ?? false complete(success, msg) } } }