Proyectos de Subversion Iphone Microlearning - Nuevo Interface

Rev

Rev 8 | Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
//
2
//  LoginView.swift
3
//  twogetskills
4
//
5
//  Created by Efrain Yanez Recanatini on 1/27/22.
6
//
7
 
8
import SwiftUI
9
import AudioToolbox
10
import Network
11
import Alamofire
12
import SwiftyJSON
13
import SafariServices
14
import RNCryptor
15
 
16
 
17
 
18
 
19
 
20
struct SigninView: View {
21
 
22
    @Environment(\.openURL) var openURL
23
    @EnvironmentObject var appNavigation : AppNavigation
24
    @State var keyboardHeight : CGFloat = 0
25
 
26
    private let appData = AppData.sharedInstance
27
 
28
 
29
    @State private var email: String = "efrain.yanez@leaderslinked.com" {
30
        didSet {
31
            if email.count > 250 {
32
                email = String(email.prefix(250))
33
                AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) { return }
34
            }
35
        }
36
    }
37
    @State private var isValidEmail : Bool = true
38
    @State private var isEditingEmail : Bool = false
39
 
40
    @State private var password: String = "Cesa2020$" {
41
        didSet {
42
            if password.count > 25 {
43
                password = String(password.prefix(25))
44
                AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) { return }
45
            }
46
        }
47
    }
48
 
49
    @State private var isValidPassword : Bool = true
50
    @State private var isEditingPassword : Bool = false
51
 
52
    @State private var isPasswordShow: Bool = false
53
 
54
 
55
    @State private var goToMain : Bool = false
56
 
57
    @State private var showProgressView : Bool = false
58
 
59
 
60
 
61
 
62
    @State private var presentAlert : Bool = false
63
    @State private var titleAlert : String = ""
64
    @State private var messageAlert : String = ""
65
 
66
 
67
 
68
 
69
    var body: some View {
70
 
71
 
72
        ZStack {
73
 
74
            Color("color_window_background")
75
                    .edgesIgnoringSafeArea(.all)
76
 
77
            VStack(spacing: 0) {
78
 
79
                HeaderGroupView()
80
 
81
                EmailTextFieldGroup(email: self.$email, isEditingEmail: self.$isEditingEmail, isValidEmail: self.$isValidEmail, password: self.$password, isEditingPassword: self.$isEditingPassword, isValidPassword: self.$isValidPassword)
82
 
83
                PasswordTextFieldGroup(
84
                    password: self.$password,
85
                    isEditingPassword: self.$isEditingPassword,
86
                    isValidPassword: self.$isValidPassword,
87
                    isPasswordShow: self.$isPasswordShow
88
                ).padding(.top, isValidEmail ? 10 : 2)
89
 
90
 
91
 
92
                Button(action: {
93
                    if(validate()) {
94
                        signin()
95
                    }
96
                }, label: {
97
                    Text(Config.LANG_SIGNIN_BUTTON_SIGNIN)
98
                    .font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
99
                    .frame(width: UIScreen.main.bounds.width - 32, height: 35)
100
                    .foregroundColor(Color("color_button_foreground"))
101
                    .background(Color("color_button_background"))
102
                    .border(Color("color_button_border"), width: Config.BUTTON_BORDER_SIZE)
103
                                           .cornerRadius(Config.BUTTON_BORDER_RADIUS)
104
 
105
                                   })
106
 
107
                                   .padding(.top, 16)
108
                                   .padding(.leading, 16)
109
                                   .padding(.trailing, 16)
110
 
111
 
112
                ButtonSignUpGroup()
113
 
114
 
115
 
116
                Spacer()
117
 
118
                ButtonForgotPasswordGroup()
119
 
120
 
121
            }
122
 
123
 
124
        }
125
 
126
        //}.offset(y : CGFloat(-(self.keyboardHeight / 2)))
127
 
128
        .onAppear {
129
    /*
130
            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { (notification) in
131
                let keyboardHeight: CGFloat = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height ?? 0
132
 
133
 
134
                self.keyboardHeight = keyboardHeight
135
                print("keyboardHeightShow = \(keyboardHeight)")
136
 
137
            }*/
138
 
139
            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { (notification) in
140
 
141
 
142
                print("keyboardHeightHide ")
143
 
144
            }
145
        }
146
 
147
         .alert(isPresented: $presentAlert) {
148
            Alert(
149
                title: Text(self.titleAlert),
150
                message: Text(self.messageAlert),
151
                dismissButton: .default(Text("Ok"))
152
            )
153
        }
154
 
155
    }
156
 
157
    private func signin() -> Void
158
    {
159
        self.isEditingEmail = false
160
        self.isValidEmail = Validator.checkEmail(email: self.email)
161
        self.isEditingPassword = false
162
        self.isValidPassword = Validator.checkPassword(password: self.password)
163
 
164
        if !self.isValidEmail || !self.isValidPassword {
165
            return
166
        }
167
 
168
 
169
 
170
        let device_uuid = appData.deviceUuid
171
 
172
        print("signin")
173
        print(" aes  = \(appData.aes) " )
174
        print(" email  = \(self.email) " )
175
        print(" password  = \(self.password) " )
176
 
177
 
178
        let syncDao = SyncDao.sharedInstance
179
        if appData.aes.isEmpty  {
180
 
181
            let syncRecord = syncDao.selectOneByType(type: Constants.SYNC_ADAPTER_TYPE_DEVICE)
182
 
183
            if syncRecord.id > 0 {
184
                let syncAdapter = SyncAdapter()
185
                syncAdapter.sync {
186
                    success in
187
                }
188
            }
189
 
190
            self.titleAlert = Config.LANG_ERROR_DEVICE_NOT_REGISTER_TITLE
191
            self.messageAlert = Config.LANG_ERROR_DEVICE_NOT_REGISTER_MESSAGE
192
            self.presentAlert = true
193
 
194
            return
195
        }
196
 
197
        self.showProgressView = true;
198
 
199
        let emailData = email.data(using: .utf8)!
200
        let emailCipherData = RNCryptor.encrypt(data: emailData, withPassword: appData.aes)
201
        let emailEncrypted = emailCipherData.base64EncodedString()
202
 
203
        let passwordData = password.data(using: .utf8)!
204
        let passwordCipherData = RNCryptor.encrypt(data: passwordData, withPassword: appData.aes)
205
        let passwordEncrypted = passwordCipherData.base64EncodedString()
206
 
207
 
208
        print(" email encrypted = \(emailEncrypted) " )
209
        print(" password encrypted = \(passwordEncrypted) " )
210
 
211
        let parameters = [
212
            Constants.POST_SIGNIN_FIELD_APPLICATION_ID: "\(Constants.GLOBAL_APPLICATION_ID)",
213
            Constants.POST_SYNC_FIELD_DEVICE_UUID: device_uuid,
214
            Constants.POST_SIGNIN_FIELD_EMAIL: emailEncrypted,
215
            Constants.POST_SIGNIN_FIELD_PASSWORD: passwordEncrypted,
216
            Constants.POST_SIGNIN_FIELD_ENCRYPTER: Constants.GLOBAL_ENCRYPTER
217
        ]
218
 
219
        let headers: HTTPHeaders = [
220
            .accept(Constants.HTTP_HEADER_ACCEPT)
221
        ]
222
 
223
        print("URL signin : \(Config.URL_SIGNIN)")
224
 
225
        self.showProgressView = true
226
        AF.request(Config.URL_SIGNIN, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON{(response) in
227
            self.showProgressView = false
228
 
229
            switch response.result {
230
                case .success:
231
                    let json = try? JSON(data: response.data!)
232
 
233
                    print("json : \(json)")
234
 
235
                    if json?["success"] ?? "" != false {
236
                        let dataService = DataService()
237
 
238
                        if dataService.syncFromServer(json : json) {
239
 
240
                            let now = Date()
241
                            let dateFormatter = DateFormatter()
242
                            dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
243
                            let dateOn = dateFormatter.string(from: now)
244
 
245
                            var userLog = UserLogModel()
246
                            userLog.userUuid = appData.userUuid
247
                            userLog.activity = Constants.USER_LOG_ACTIVITY_SIGNIN
248
                            userLog.addedOn = dateOn
249
 
250
                            let userLogDao = UserLogDao.sharedInstance
251
                            userLogDao.insert(record: userLog)
252
 
253
                            var sync = SyncModel()
254
 
255
                            var json = userLog.toJson()
256
                            json[Constants.SYNC_ADAPTER_DATA_TYPE_FIELD_NAME] = Constants.SYNC_ADAPTER_DATA_TYPE_USER_LOG
257
 
258
                            sync = SyncModel();
259
                            sync.type = Constants.SYNC_ADAPTER_TYPE_SYNC
260
                            if let theJSONData = try?  JSONSerialization.data(withJSONObject: json, options: .prettyPrinted),
261
                                let data = String(data: theJSONData, encoding: String.Encoding.ascii) {
262
                                    sync.data = data
263
                                }
264
 
265
                            syncDao.insert(record : sync);
266
 
267
                            appNavigation.pageActive = AppMainPage.home
268
 
269
 
270
 
271
                            //self.goToMain = true
272
                        }
273
                    } else {
274
                        let message = json?["data"].string ?? ""
275
                        if !message.isEmpty {
276
                            self.titleAlert = Config.LANG_ERROR_GENERIC_TITLE
277
                            self.messageAlert = message
278
                            self.presentAlert = true
279
                        }
280
                    }
281
 
282
                   return
283
 
284
                case .failure :
285
                    self.titleAlert = Config.LANG_ERROR_COMMUNICATION_TITLE
286
                    self.messageAlert = Config.LANG_ERROR_COMMUNICATION_MESSAGE
287
                    self.presentAlert = true
288
 
289
                    return
290
            }
291
 
292
 
293
 
294
 
295
            /*
296
            switch response.result {
297
                case .success:
298
 
299
 
300
                    print("Response Data : \(response.data!) ")
301
 
302
                    let json = try? JSON(data: response.data!)
303
                    if json?["success"] ?? "" != false {
304
                        let dataService = DataService()
305
 
306
                        if dataService.syncFromServer(json : json) {
307
                            self.goToMain = true
308
                        }
309
                    } else {
310
                        let message = json?["data"].string ?? ""
311
                        if !message.isEmpty {
312
                            self.titleAlert = "Error"
313
                            self.messageAlert = message
314
                            self.presentAlert = true
315
                        }
316
                    }
317
 
318
 
319
                    return
320
 
321
                case .failure:
322
                    self.titleAlert = "Servidor no encontrado"
323
                    self.messageAlert = "Ocurrio un error de comunicación"
324
                    self.presentAlert = true
325
 
326
                    return
327
            }*/
328
        }
329
    }
330
 
331
 
332
    private func validate() -> Bool
333
    {
334
 
335
        print("validate - email : \(email)")
336
        print("validate - password : \(password)")
337
 
338
 
339
        if email.isEmpty {
340
            self.isValidEmail = false
341
        } else  if !checkEmail(email: email) {
342
            self.isValidEmail = false
343
        } else {
344
            self.isValidEmail = true
345
        }
346
 
347
 
348
 
349
        if password.isEmpty {
350
            self.isValidPassword = false
351
        } else if(!checkPassword(password: password)) {
352
            self.isValidPassword = false
353
 
354
        } else {
355
            self.isValidPassword = true
356
        }
357
 
358
        return  self.isValidEmail &&  self.isValidPassword
359
    }
360
 
361
 
362
    private func checkEmail(email : String) -> Bool {
363
        let regex = #"^[a-zA-Z0-9_\-\.~]{2,}@[a-zA-Z0-9_\-\.~]{2,}\.[a-zA-Z]{2,}$"#
364
 
365
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
366
        return predicate.evaluate(with: email) ? true : false;
367
    }
368
 
369
    private func checkPassword(password : String) -> Bool {
370
        let regexOld = #"^(?=.*\d+)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{6,16}$"#
371
        let regexNew = #"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[\#\?\!\@\$\^\%\*\-]).{6,16}$"#
372
 
373
        let predicateNew = NSPredicate(format: "SELF MATCHES %@", regexNew)
374
        let predicateOld = NSPredicate(format: "SELF MATCHES %@", regexOld)
375
        if(predicateOld.evaluate(with: password)) {
376
            return true
377
        } else  if(predicateNew.evaluate(with: password)) {
378
            return true
379
        } else {
380
            return false
381
        }
382
    }
383
 
384
 
385
}
386
 
387
 
388
 
389
struct SigninView_Previews: PreviewProvider {
390
    static var previews: some View {
391
        SigninView()
392
    }
393
}
394
 
395
struct HeaderGroupView: View {
396
 
397
 
398
    var body: some View {
399
        //Inicio Logo
400
        HStack {
401
            Image("logo")
402
            .resizable()
403
            .frame(width: 50, height: 50)
404
 
405
            Text(Config.LANG_SIGNIN_APP_NAME)
406
            .font(Font.custom(Config.FONT_NAME_BOLD, size: 24))
407
            .foregroundColor(Color("color_textview"))
408
 
409
            Spacer()
410
        }
411
        .padding(.leading, 16)
412
        .padding(.top, 66)
413
        //Fin logo
414
 
415
        //Inicio Saludo
416
        HStack {
417
            Text(Config.LANG_SIGNIN_GREATING)
418
            .font(Font.custom(Config.FONT_NAME_BOLD, size: 32))
419
            .foregroundColor(Color("color_textview"))
420
            Spacer()
421
        }
422
        .padding(.leading, 16)
423
        .padding(.top, 10)
424
        //Fin Saludo
425
 
426
        //Inicio Encabezado
427
        HStack {
428
            Text(Config.LANG_SIGNIN_HEAD_LINE1)
429
            .font(Font.custom(Config.FONT_NAME_REGULAR, size: 16))
430
            .foregroundColor(Color("color_textview"))
431
            Spacer()
432
        }
433
        .padding(.leading, 16)
434
        .padding(.top, 10)
435
        //Fin Encabezado
436
    }
437
}
438
 
439
struct EmailTextFieldGroup : View {
440
 
441
 
442
 
443
    @Binding var email: String
444
    @Binding var isEditingEmail : Bool
445
    @Binding var isValidEmail : Bool
446
 
447
    @Binding var password: String
448
    @Binding var isEditingPassword: Bool
449
    @Binding var isValidPassword: Bool
450
 
451
 
452
    var body : some View {
453
        //Inicio Label Email
454
        HStack {
455
            Text(Config.LANG_SIGNIN_TITLE_EMAIL_FIELD)
456
            .font(Font.custom(Config  .FONT_NAME_REGULAR, size: 11))
457
            .foregroundColor(Color("color_textview"))
458
            Spacer()
459
        }
460
        .padding(.leading, 16)
461
        .padding(.top, 10)
462
        //Fin Label Email
463
 
464
        //Inicio TextField  Email
465
 
466
        Group {
467
            HStack {
468
                /*
469
                Image("ui_mail")
470
                .resizable()
471
                .frame(width: 24, height: 24)
472
                         .padding(.horizontal, 4)
473
                */
474
 
475
 
476
                TextField("",
477
                    text: self.$email,
478
                    onEditingChanged: { (changed) in
479
 
480
                        if changed {
481
 
482
                            if self.isEditingPassword {
483
                                self.isValidPassword = Validator.checkPassword(password: self.password)
484
                                self.isEditingPassword = false
485
                            }
486
 
487
 
488
                            self.isEditingEmail = true
489
                        } else {
490
                            self.isEditingEmail = false
491
                            self.isValidEmail = Validator.checkEmail(email: self.email)
492
                        }
493
 
494
                    }, onCommit: {
495
                        self.isEditingEmail = false
496
                        self.isValidEmail = Validator.checkEmail(email: self.email)
497
                    }
498
                )
499
 
500
                .font(Font.custom(Config.FONT_NAME_REGULAR, size: 12))
501
                .textFieldStyle(PlainTextFieldStyle())
502
                .frame(height: 32)
503
                .keyboardType(.emailAddress)
504
                .autocapitalization(.none)
505
                //.foregroundColor(Color("color_textfield_foreground"))
506
                //.background(Color("color_textfield_background"))
507
                .padding(.leading, 4)
508
                Spacer()
509
 
510
            }
511
        }
512
 
513
        .foregroundColor(Color("color_textfield_foreground"))
514
        .background(Color("color_textfield_background"))
515
        .overlay(RoundedRectangle(cornerRadius: 5).stroke(
516
            Color(self.isEditingEmail ? "color_textfield_border_active" : self.isValidEmail ? "color_textfield_border" : "color_textfield_border_error" )
517
        ))
518
        .padding(.leading, 16)
519
        .padding(.trailing, 16)
520
        .padding(.top, self.isValidEmail ? 10 : 2)
521
 
522
 
523
        if !self.isValidEmail {
524
            HStack {
525
                Spacer()
526
 
527
                Text(Config.LANG_SIGNIN_ERROR_EMAIL_FIELD)
528
                .foregroundColor(.red)
529
                    .font(Font.custom(Config.FONT_NAME_REGULAR, size: 11))
530
 
531
            }
532
            .padding(.top, 5)
533
            .padding(.trailing, 16)
534
        }
535
 
536
        //Fin TextField Email
537
    }
538
 
539
}
540
 
541
 
542
 
543
struct PasswordTextFieldGroup : View {
544
    @Binding var password: String
545
    @Binding var isEditingPassword: Bool
546
    @Binding var isValidPassword: Bool
547
    @Binding var isPasswordShow: Bool
548
 
549
    var body : some View {
550
        //Inicio Label Password
551
        HStack {
552
            Text(Config.LANG_SIGNIN_TITLE_PASSWORD_FIELD)
553
            .font(Font.custom(Config  .FONT_NAME_REGULAR, size: 11))
554
            .foregroundColor(Color("color_textview"))
555
            Spacer()
556
        }
557
        .padding(.leading, 16)
558
        //Fin Label Password
559
 
560
 
561
        //Inicio TextField  Password
562
 
563
        Group {
564
            HStack {
565
                /*
566
                Image("ui_key")
567
                .resizable()
568
                .frame(width: 24, height: 24)
569
                         .padding(.horizontal, 4)
570
                 */
571
                if isPasswordShow {
572
 
573
                    TextField("",
574
                        text: self.$password,
575
                        onEditingChanged: { (changed) in
576
 
577
                            if changed {
578
                                self.isEditingPassword = true
579
                            } else {
580
                                self.isEditingPassword = false
581
                                self.isValidPassword = Validator.checkPassword(password: self.password)
582
                            }
583
 
584
                        }, onCommit: {
585
                            self.isEditingPassword = false
586
                            self.isValidPassword = Validator.checkPassword(password:  self.password)
587
                        }
588
                    )
589
                    .font(Font.custom(Config.FONT_NAME_REGULAR, size: 12))
590
                    .textFieldStyle(PlainTextFieldStyle())
591
                    .frame(height: 32)
592
                        .keyboardType(.default)
593
                    .autocapitalization(.none)
594
                    /*
595
                    .foregroundColor(Color("color_textfield_foreground"))
596
                    .background(Color("color_textfield_background"))
597
 */
598
                    .padding(.leading, 4)
599
                    Spacer()
600
 
601
                    Button(action: {
602
                        self.isPasswordShow.toggle()
603
                    }, label: {
604
                        Image("ui_visibility_off")
605
                        .resizable()
606
                        .frame(width: 24, height: 24)
607
                                 .padding(.horizontal, 4)
608
                    })
609
                } else {
610
 
611
                    SecureField("", text: self.$password, onCommit: {
612
                        self.isEditingPassword = false
613
                        self.isValidPassword = Validator.checkPassword(password: self.password)
614
                    })
615
                    .onHover { hovering in
616
                        if hovering {
617
                            print("onHover")
618
                        } else {
619
                            print("offHover")
620
                        }
621
                                }
622
                    .onTapGesture {
623
                        self.isEditingPassword = true
624
                    }
625
                    .font(Font.custom(Config.FONT_NAME_REGULAR, size: 11))
626
                    .textFieldStyle(PlainTextFieldStyle())
627
                    .frame(height: 32)
628
                        .keyboardType(.default)
629
                    .autocapitalization(.none)
630
                    /*
631
                    .foregroundColor(Color("color_textfield_foreground"))
632
                    .background(Color("color_textfield_background"))*/
633
                        .padding(.leading, 4)
634
                    Spacer()
635
 
636
                    Button(action: {
637
                        self.isPasswordShow.toggle()
638
                    }, label: {
639
                        Image("ui_visibility")
640
                        .resizable()
641
                        .frame(width: 24, height: 24)
642
                                 .padding(.horizontal, 4)
643
 
644
                    })
645
 
646
                }
647
 
648
                //
649
                //ui_visibility
650
 
651
            }
652
        }
653
        .foregroundColor(Color("color_textfield_foreground"))
654
        .background(Color("color_textfield_background"))
655
        .overlay(RoundedRectangle(cornerRadius: 5).stroke(
656
            Color(self.isEditingPassword ? "color_textfield_border_active" : self.isValidPassword ? "color_textfield_border" : "color_textfield_border_error" )
657
        ))
658
        .padding(.leading, 16)
659
        .padding(.trailing, 16)
660
        .padding(.top, 2)
661
 
662
        if !self.isValidPassword {
663
            HStack {
664
                Spacer()
665
 
666
                Text(Config.LANG_SIGNIN_ERROR_PASSWORD_FIELD)
667
                .foregroundColor(.red)
668
                    .font(Font.custom(Config.FONT_NAME_REGULAR, size: 11))
669
 
670
            }
671
            .padding(.top, 5)
672
            .padding(.trailing, 16)
673
        }
674
 
675
        //Fin TextField Password
676
 
677
 
678
    }
679
 
680
 
681
 
682
}
683
 
684
struct ButtonSignUpGroup : View {
685
    @Environment(\.openURL) var openURL
686
 
687
 
688
    var body : some View {
689
        Button(action: {
690
            openURL(URL(string: Config.URL_SIGNUP_ENDPOINT)!)
691
 
692
        }, label: {
693
            Text(Config.LANG_SIGNIN_BUTTON_SIGNUP)
694
             .font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
695
             .frame(width: UIScreen.main.bounds.width - 32, height: 35)
696
                .foregroundColor(Color("color_button_foreground"))
697
                .background(Color("color_button_background"))
698
                .border(Color("color_button_border"), width: Config.BUTTON_BORDER_SIZE)
699
                .cornerRadius(Config.BUTTON_BORDER_RADIUS)
700
 
701
        })
702
        .padding(.top, 16)
703
        .padding(.leading, 16)
704
        .padding(.trailing, 16)
705
    }
706
}
707
 
708
struct ButtonForgotPasswordGroup : View {
709
    @Environment(\.openURL) var openURL
710
 
711
 
712
    var body : some View {
713
        Button(action: {
714
            openURL(URL(string: Config.URL_FORGOT_PASSWORD_ENDPOINT)!)
715
 
716
        }, label: {
717
            Text(Config.LANG_SIGNIN_BUTTON_FORGOT_PASSWORD)
718
             .font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
719
 
720
                .foregroundColor(Color("color_button_foreground"))
721
 
722
 
723
 
724
        })
725
        .padding(.vertical, 16)
726
    }
727
}