Rev 19 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
//
// LoginView.swift
// twogetskills
//
// Created by Efrain Yanez Recanatini on 1/27/22.
//
import SwiftUI
import AudioToolbox
import Network
import Alamofire
import SwiftyJSON
import SafariServices
import RNCryptor
struct SigninView: View {
@EnvironmentObject var networkMonitor : NetworkMonitor
@EnvironmentObject var appNavigation : AppNavigation
@State private var keyboardHeight : CGFloat = 0
private var appData = AppData.sharedInstance
@State private var email: String = "" {
didSet {
if email.count > 250 {
email = String(email.prefix(250))
AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) { return }
}
}
}
@State private var isProcessing : Bool = false
@State private var isValidEmail : Bool = true
@State private var isEditingEmail : Bool = false
@State private var password: String = "" {
didSet {
if password.count > 25 {
password = String(password.prefix(25))
AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) { return }
}
}
}
@State private var isValidPassword : Bool = true
@State private var isEditingPassword : Bool = false
@State private var isPasswordShow: Bool = false
@State private var showProgressView : Bool = false
@State private var presentAlert : Bool = false
@State private var titleAlert : String = ""
@State private var messageAlert : String = ""
@State private var openForgotPassword : Bool = false
@State private var openSignup : Bool = false
var body: some View {
ZStack {
Color("color_window_background")
.edgesIgnoringSafeArea(.all)
if self.showProgressView {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: Color("color_progress_view_foreground")))
.scaleEffect(3, anchor: .center).zIndex(100000)
}
VStack(spacing: 0) {
if networkMonitor.status == .disconnected {
HStack {
Text(Config.LANG_ERROR_NETWORK_MESSAGE_SHORT)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_APP_BAR_HEAD1 ))
.foregroundColor(Color("color_network_disconnected_foreground"))
.padding(.leading, 16)
Spacer()
}
.edgesIgnoringSafeArea(.top)
.frame(height: 50)
.background(Color("color_network_disconnected_background"))
Divider().background(Color("color_network_disconnected_background"))
}
HeaderGroupView()
EmailTextFieldGroup(email: self.$email, isEditingEmail: self.$isEditingEmail, isValidEmail: self.$isValidEmail, password: self.$password, isEditingPassword: self.$isEditingPassword, isValidPassword: self.$isValidPassword)
PasswordTextFieldGroup(
password: self.$password,
isEditingPassword: self.$isEditingPassword,
isValidPassword: self.$isValidPassword,
isPasswordShow: self.$isPasswordShow
).padding(.top, isValidEmail ? 10 : 2)
Button(action: {
if(validate()) {
signin()
}
}, label: {
Text(Config.LANG_SIGNIN_BUTTON_SIGNIN)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
.frame(width: UIScreen.main.bounds.width - 32, height: 35)
.foregroundColor(Color("color_button_foreground"))
.background(Color("color_button_background"))
.border(Color("color_button_border"), width: Config.BUTTON_BORDER_SIZE)
.cornerRadius(Config.BUTTON_BORDER_RADIUS)
})
.padding(.top, 16)
.padding(.leading, 16)
.padding(.trailing, 16)
ButtonSignUpGroup(openSignup: self.$openSignup)
Spacer()
ButtonForgotPasswordGroup(openForgotPassword: self.$openForgotPassword)
}
}
//}.offset(y : CGFloat(-(self.keyboardHeight / 2)))
.onAppear {
/*
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { (notification) in
let keyboardHeight: CGFloat = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height ?? 0
self.keyboardHeight = keyboardHeight
//print("keyboardHeightShow = \(keyboardHeight)")
}*/
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { (notification) in
// print("keyboardHeightHide ")
}
}.popover(isPresented: self.$openSignup, content: {
SafariView(sURL: Config.URL_SIGNUP_ENDPOINT)
}).popover(isPresented: self.$openForgotPassword, content: {
SafariView(sURL: Config.URL_FORGOT_PASSWORD_ENDPOINT)
}).alert(isPresented: $presentAlert) {
Alert(
title: Text(self.titleAlert),
message: Text(self.messageAlert),
dismissButton: .default(Text(Config.LANG_COMMON_OK))
)
}
}
private func signin() -> Void
{
if isProcessing {
self.titleAlert = Config.LANG_ERROR_SIGNIN_IN_PROGRESS_TITLE
self.messageAlert = Config.LANG_ERROR_SIGNIN_IN_PROGRESS_MESSAGE
self.presentAlert = true
return
}
self.isEditingEmail = false
self.isValidEmail = Validator.checkEmail(email: self.email)
self.isEditingPassword = false
self.isValidPassword = Validator.checkPassword(password: self.password)
if !self.isValidEmail || !self.isValidPassword {
return
}
let device_uuid = appData.deviceUuid
let emailTrimming = email.trimmingCharacters(in: .whitespaces)
let passwordTrimming = password.trimmingCharacters(in: .whitespaces)
//print("signin")
//print(" aes = \(appData.deviceAes) " )
//print(" email = \(self.email) " )
//print(" password = \(self.password) " )
let syncDao = SyncDao()
if appData.deviceAes.isEmpty {
let syncRecord = syncDao.selectOneByType(type: Constants.SYNC_ADAPTER_TYPE_DEVICE)
if syncRecord.id > 0 {
let syncAdapter = SyncAdapter()
syncAdapter.sync(isForeground: true){
success in
}
}
self.titleAlert = Config.LANG_ERROR_DEVICE_NOT_REGISTER_TITLE
self.messageAlert = Config.LANG_ERROR_DEVICE_NOT_REGISTER_MESSAGE
self.presentAlert = true
return
}
if networkMonitor.status == .disconnected {
self.titleAlert = Config.LANG_ERROR_NETWORK_TITLE
self.messageAlert = Config.LANG_ERROR_NETWORK_MESSAGE_SHORT
self.presentAlert = true
return
}
self.showProgressView = true;
let emailData = emailTrimming.data(using: .utf8)!
let emailCipherData = RNCryptor.encrypt(data: emailData, withPassword: appData.deviceAes)
let emailEncrypted = emailCipherData.base64EncodedString()
let passwordData = passwordTrimming.data(using: .utf8)!
let passwordCipherData = RNCryptor.encrypt(data: passwordData, withPassword: appData.deviceAes)
let passwordEncrypted = passwordCipherData.base64EncodedString()
//print(" email encrypted = \(emailEncrypted) " )
//print(" password encrypted = \(passwordEncrypted) " )
let parameters = [
Constants.POST_SIGNIN_FIELD_APPLICATION_ID: "\(Config.APPLICATION_ID)",
Constants.POST_SIGNIN_FIELD_VARIANT_ID: "\(Config.VARIANT_ID)",
Constants.POST_SYNC_FIELD_DEVICE_UUID: device_uuid,
Constants.POST_SIGNIN_FIELD_EMAIL: emailEncrypted,
Constants.POST_SIGNIN_FIELD_PASSWORD: passwordEncrypted,
Constants.POST_SIGNIN_FIELD_ENCRYPTER: Constants.GLOBAL_ENCRYPTER
]
let headers: HTTPHeaders = [
.accept(Constants.HTTP_HEADER_ACCEPT)
]
//print("URL signin : \(Config.URL_SIGNIN)")
self.showProgressView = true
AF.request(Config.URL_SIGNIN, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON{(response) in
self.showProgressView = false
switch response.result {
case .success:
let json = try? JSON(data: response.data!)
//print("json : \(json)")
if json?["success"] ?? "" != false {
let dataService = DataService()
if dataService.syncFromServer(json : json) {
let userinfo = [
"title" : Config.LANG_TITLE_NOTIFICATION_SIGNIN_PUSH,
"body" : Config.LANG_BODY_NOTIFICATION_SIGNIN_PUSH,
"url" : ""
]
NotificationCenter.default.post(name: Constants.NOTIFICATION_NAME_PUSH , object: self, userInfo: userinfo)
let now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
let dateOn = dateFormatter.string(from: now)
var userLog = UserLogModel()
userLog.userUuid = appData.userUuid
userLog.activity = Constants.USER_LOG_ACTIVITY_SIGNIN
userLog.addedOn = dateOn
let userLogDao = UserLogDao()
userLogDao.insert(record: userLog)
var sync = SyncModel()
var json = userLog.toJson()
json[Constants.SYNC_ADAPTER_DATA_TYPE_FIELD_NAME] = Constants.SYNC_ADAPTER_DATA_TYPE_USER_LOG
sync = SyncModel();
sync.type = Constants.SYNC_ADAPTER_TYPE_SYNC
if let theJSONData = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted),
let data = String(data: theJSONData, encoding: String.Encoding.ascii) {
sync.data = data
}
syncDao.insert(record : sync);
appNavigation.subpageActive = AppMainSubPage.mycapsules
appNavigation.pageActive = AppMainPage.home
//self.goToMain = true
}
} else {
let message = json?["data"].string ?? ""
if !message.isEmpty {
self.titleAlert = Config.LANG_ERROR_GENERIC_TITLE
self.messageAlert = message
self.presentAlert = true
}
}
return
case .failure :
self.titleAlert = Config.LANG_ERROR_COMMUNICATION_TITLE
self.messageAlert = Config.LANG_ERROR_COMMUNICATION_MESSAGE
self.presentAlert = true
return
}
}
}
private func validate() -> Bool
{
//print("validate - email : \(email)")
//print("validate - password : \(password)")
if email.isEmpty {
self.isValidEmail = false
} else if !Validator.checkEmail(email: email) {
self.isValidEmail = false
} else {
self.isValidEmail = true
}
if password.isEmpty {
self.isValidPassword = false
} else if(!Validator.checkPassword(password: password)) {
self.isValidPassword = false
} else {
self.isValidPassword = true
}
return self.isValidEmail && self.isValidPassword
}
}
struct SigninView_Previews: PreviewProvider {
static var previews: some View {
SigninView()
}
}
struct HeaderGroupView: View {
var body: some View {
//Inicio Logo
HStack {
Image("logo")
.resizable()
.frame(width: 50, height: 50)
Text(Config.LANG_SIGNIN_APP_NAME)
.font(Font.custom(Config.FONT_NAME_BOLD, size: 24))
.foregroundColor(Color("color_textview_foreground"))
Spacer()
}
.padding(.leading, 16)
.padding(.top, 66)
//Fin logo
//Inicio Saludo
HStack {
Text(Config.LANG_SIGNIN_GREATING)
.font(Font.custom(Config.FONT_NAME_BOLD, size: 32))
.foregroundColor(Color("color_textview_foreground"))
Spacer()
}
.padding(.leading, 16)
.padding(.top, 10)
//Fin Saludo
//Inicio Encabezado
HStack {
Text(Config.LANG_SIGNIN_HEAD_LINE1)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: 16))
.foregroundColor(Color("color_textview_foreground"))
Spacer()
}
.padding(.leading, 16)
.padding(.top, 10)
//Fin Encabezado
}
}
struct EmailTextFieldGroup : View {
@Binding var email: String
@Binding var isEditingEmail : Bool
@Binding var isValidEmail : Bool
@Binding var password: String
@Binding var isEditingPassword: Bool
@Binding var isValidPassword: Bool
var body : some View {
//Inicio Label Email
HStack {
Text(Config.LANG_SIGNIN_TITLE_EMAIL_FIELD)
.font(Font.custom(Config .FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD_LABEL))
.foregroundColor(Color("color_textview_foreground"))
Spacer()
}
.padding(.leading, 16)
.padding(.top, 10)
//Fin Label Email
//Inicio TextField Email
Group {
HStack {
/*
Image("ui_mail")
.resizable()
.frame(width: 24, height: 24)
.padding(.horizontal, 4)
*/
TextField("",
text: self.$email,
onEditingChanged: { (changed) in
if changed {
if self.isEditingPassword {
self.isValidPassword = Validator.checkPassword(password: self.password)
self.isEditingPassword = false
}
self.isEditingEmail = true
} else {
self.isEditingEmail = false
self.isValidEmail = Validator.checkEmail(email: self.email)
}
}, onCommit: {
self.isEditingEmail = false
self.isValidEmail = Validator.checkEmail(email: self.email)
}
)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD))
.textFieldStyle(PlainTextFieldStyle())
.frame(height: 32)
.keyboardType(.emailAddress)
.autocapitalization(.none)
//.foregroundColor(Color("color_textfield_foreground"))
//.background(Color("color_textfield_background"))
.padding(.leading, 4)
Spacer()
}
}
.foregroundColor(Color("color_textfield_foreground"))
.background(Color("color_textfield_background"))
.overlay(RoundedRectangle(cornerRadius: 5).stroke(
Color(self.isEditingEmail ? "color_textfield_border_active" : self.isValidEmail ? "color_textfield_border" : "color_textfield_border_error" )
))
.padding(.leading, 16)
.padding(.trailing, 16)
.padding(.top, self.isValidEmail ? 10 : 2)
if !self.isValidEmail {
HStack {
Spacer()
Text(Config.LANG_SIGNIN_ERROR_EMAIL_FIELD)
.foregroundColor(.red)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD_ERROR))
}
.padding(.top, 5)
.padding(.trailing, 16)
}
//Fin TextField Email
}
}
struct PasswordTextFieldGroup : View {
@Binding var password: String
@Binding var isEditingPassword: Bool
@Binding var isValidPassword: Bool
@Binding var isPasswordShow: Bool
var body : some View {
//Inicio Label Password
HStack {
Text(Config.LANG_SIGNIN_TITLE_PASSWORD_FIELD)
.font(Font.custom(Config .FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD_LABEL))
.foregroundColor(Color("color_textview_foreground"))
Spacer()
}
.padding(.leading, 16)
//Fin Label Password
//Inicio TextField Password
Group {
HStack {
/*
Image("ui_key")
.resizable()
.frame(width: 24, height: 24)
.padding(.horizontal, 4)
*/
if isPasswordShow {
TextField("",
text: self.$password,
onEditingChanged: { (changed) in
if changed {
self.isEditingPassword = true
} else {
self.isEditingPassword = false
self.isValidPassword = Validator.checkPassword(password: self.password)
}
}, onCommit: {
self.isEditingPassword = false
self.isValidPassword = Validator.checkPassword(password: self.password)
}
)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD))
.textFieldStyle(PlainTextFieldStyle())
.frame(height: 32)
.keyboardType(.default)
.autocapitalization(.none)
/*
.foregroundColor(Color("color_textfield_foreground"))
.background(Color("color_textfield_background"))
*/
.padding(.leading, 4)
Spacer()
Button(action: {
self.isPasswordShow.toggle()
}, label: {
Image("ui_visibility_off")
.resizable()
.frame(width: 24, height: 24)
.padding(.horizontal, 4)
})
} else {
SecureField("", text: self.$password, onCommit: {
self.isEditingPassword = false
self.isValidPassword = Validator.checkPassword(password: self.password)
})
.onTapGesture {
self.isEditingPassword = true
}
.font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD))
.textFieldStyle(PlainTextFieldStyle())
.frame(height: 32)
.keyboardType(.default)
.autocapitalization(.none)
/*
.foregroundColor(Color("color_textfield_foreground"))
.background(Color("color_textfield_background"))*/
.padding(.leading, 4)
Spacer()
Button(action: {
self.isPasswordShow.toggle()
}, label: {
Image("ui_visibility")
.resizable()
.frame(width: 24, height: 24)
.padding(.horizontal, 4)
})
}
//
//ui_visibility
}
}
.foregroundColor(Color("color_textfield_foreground"))
.background(Color("color_textfield_background"))
.overlay(RoundedRectangle(cornerRadius: 5).stroke(
Color(self.isEditingPassword ? "color_textfield_border_active" : self.isValidPassword ? "color_textfield_border" : "color_textfield_border_error" )
))
.padding(.leading, 16)
.padding(.trailing, 16)
.padding(.top, 2)
if !self.isValidPassword {
HStack {
Spacer()
Text(Config.LANG_SIGNIN_ERROR_PASSWORD_FIELD)
.foregroundColor(.red)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD_ERROR))
}
.padding(.top, 5)
.padding(.trailing, 16)
}
//Fin TextField Password
}
}
struct ButtonSignUpGroup : View {
@Binding var openSignup : Bool
var body : some View {
Button(action: {
openSignup = true
}, label: {
Text(Config.LANG_SIGNIN_BUTTON_SIGNUP)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
.frame(width: UIScreen.main.bounds.width - 32, height: 35)
.foregroundColor(Color("color_button_foreground"))
.background(Color("color_button_background"))
.border(Color("color_button_border"), width: Config.BUTTON_BORDER_SIZE)
.cornerRadius(Config.BUTTON_BORDER_RADIUS)
})
.padding(.top, 16)
.padding(.leading, 16)
.padding(.trailing, 16)
}
}
struct ButtonForgotPasswordGroup : View {
@Binding var openForgotPassword : Bool
var body : some View {
Button(action: {
openForgotPassword = true
}, label: {
Text(Config.LANG_SIGNIN_BUTTON_FORGOT_PASSWORD)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
.foregroundColor(Color("color_button_foreground"))
})
.padding(.vertical, 16)
}
}