· 9 years ago · Apr 26, 2017, 10:10 AM
1 //
2// Auth02ViewController.swift
3// Sparker
4//
5// Created by Miroslav on 6/30/16.
6// Copyright © 2016 Samuel Harrison. All rights reserved.
7//
8
9import UIKit
10import MBProgressHUD
11import TTTAttributedLabel
12import KumulosSDK
13import Firebase
14
15class Auth02ViewController: UIViewController, UITextViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIScrollViewDelegate {
16
17 @IBOutlet weak var lbUploadProfiles: TTTAttributedLabel!
18 @IBOutlet weak var scMain: UIScrollView!
19 @IBOutlet weak var viPhoto1: UIView!
20 @IBOutlet weak var ivPhoto1: UIImageView!
21 @IBOutlet weak var ivPlus1: UIImageView!
22 @IBOutlet weak var viPhoto2: UIView!
23 @IBOutlet weak var ivPhoto2: UIImageView!
24 @IBOutlet weak var ivPlus2: UIImageView!
25 @IBOutlet weak var viPhoto3: UIView!
26 @IBOutlet weak var ivPhoto3: UIImageView!
27 @IBOutlet weak var ivPlus3: UIImageView!
28 @IBOutlet weak var viPhoto4: UIView!
29 @IBOutlet weak var ivPhoto4: UIImageView!
30 @IBOutlet weak var ivPlus4: UIImageView!
31 @IBOutlet weak var viPhoto5: UIView!
32 @IBOutlet weak var ivPhoto5: UIImageView!
33 @IBOutlet weak var ivPlus5: UIImageView!
34 @IBOutlet weak var viPhoto6: UIView!
35 @IBOutlet weak var ivPhoto6: UIImageView!
36 @IBOutlet weak var ivPlus6: UIImageView!
37 @IBOutlet weak var tvStatus: UITextView!
38 @IBOutlet weak var statusLettersCounter: UILabel!
39 @IBOutlet weak var lettersCounter: UILabel!
40 @IBOutlet weak var tvAboutMe: UITextView!
41 @IBOutlet weak var btFinish: UIButton!
42 @IBOutlet weak var toolbar: UIToolbar!
43 @IBOutlet weak var titleToolbar: UIBarButtonItem!
44
45 let imagePicker = UIImagePickerController()
46 var currentImageIndex: Int! = 0
47 var selectedTextView: UITextView!
48 var selectedImageIndexArray : [Int] = []
49 var animationAdded: Bool = false
50 var scrollViewOffset: CGFloat = 0
51
52 let appDelegate = UIApplication.shared.delegate as! AppDelegate
53 var selectedImages = [UIImage]()
54
55 override func viewDidLoad() {
56 super.viewDidLoad()
57
58 self.navigationItem.title = "UPLOAD PICTURE"
59 self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "btn_back"), style: UIBarButtonItemStyle.plain, target: self, action: #selector(didTapBackButton))
60
61 let text = "Please upload a minimum of 3 pictures,\nat least one clear picture showing your face. It's statistically proven to increase your likes. (All photos will be blurred and only revealed when you match)".uppercased() as NSString
62 let mutableString: NSMutableAttributedString = NSMutableAttributedString(
63 string: text as String,
64 attributes: [
65 NSFontAttributeName: UIFont(name: "Moon-Bold", size: 12.0)!,
66 NSForegroundColorAttributeName: UIColor(red: 112 / 255, green: 112 / 255, blue: 112 / 255, alpha: 1.0)
67 ]
68 )
69 let boldRange = text.range(of: "MINIMUM OF 3 PICTURES,")
70 let boldFont = UIFont(name: "Moon-Bold", size: 14.0)!
71 mutableString.addAttribute(NSFontAttributeName, value: boldFont, range: boldRange)
72 mutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.black, range: boldRange)
73 lbUploadProfiles.attributedText = mutableString
74
75 imagePicker.delegate = self
76 scMain.delegate = self
77
78 viPhoto1.layer.borderWidth = 2.0
79 viPhoto1.layer.borderColor = AppConfig.lightGray.cgColor
80
81 viPhoto2.layer.borderWidth = 2.0
82 viPhoto2.layer.borderColor = AppConfig.lightGray.cgColor
83
84 viPhoto3.layer.borderWidth = 2.0
85 viPhoto3.layer.borderColor = AppConfig.lightGray.cgColor
86
87 viPhoto4.layer.borderWidth = 2.0
88 viPhoto4.layer.borderColor = AppConfig.lightGray.cgColor
89
90 viPhoto5.layer.borderWidth = 2.0
91 viPhoto5.layer.borderColor = AppConfig.lightGray.cgColor
92
93 viPhoto6.layer.borderWidth = 2.0
94 viPhoto6.layer.borderColor = AppConfig.lightGray.cgColor
95
96 btFinish.layer.cornerRadius = AppConfig.textFieldCornerRadius
97
98 tvAboutMe.inputAccessoryView = toolbar
99 tvStatus.inputAccessoryView = toolbar
100 }
101
102 override func viewWillAppear(_ animated: Bool) {
103 super.viewWillAppear(animated)
104 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
105 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
106 }
107
108 override func viewWillDisappear(_ animated: Bool) {
109 super.viewWillDisappear(animated)
110 NotificationCenter.default.removeObserver(self)
111 }
112
113 override func didReceiveMemoryWarning() {
114 super.didReceiveMemoryWarning()
115 // Dispose of any resources that can be recreated.
116 }
117
118 @IBAction func actionAddPhoto(_ sender: UIButton!) {
119
120 currentImageIndex = sender.tag
121 let alertController = UIAlertController(title: "Choose Source", message: "Please choose an image source", preferredStyle: .actionSheet)
122 let cameraAction = UIAlertAction(title: "Camera", style: .default) { (action) -> Void in
123 self.imagePicker.allowsEditing = true
124 self.imagePicker.sourceType = .camera
125 self.present(self.imagePicker, animated: true, completion: nil)
126 }
127 alertController.addAction(cameraAction)
128 let photoLibraryAction = UIAlertAction(title: "Photo Library", style: .default) { (action) -> Void in
129 self.imagePicker.allowsEditing = true
130 self.imagePicker.sourceType = .photoLibrary
131 self.present(self.imagePicker, animated: true, completion: nil)
132 }
133 alertController.addAction(photoLibraryAction)
134
135 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) -> Void in
136 }
137 alertController.addAction(cancelAction)
138 self.present(alertController, animated: true, completion: nil)
139 }
140
141 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
142 if let pickedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
143 if currentImageIndex == 0 {
144 ivPhoto1.image = pickedImage
145 ivPlus1.isHidden = true
146 }
147 else if currentImageIndex == 1 {
148 ivPhoto2.image = pickedImage
149 ivPlus2.isHidden = true
150 }
151 else if currentImageIndex == 2 {
152 ivPhoto3.image = pickedImage
153 ivPlus3.isHidden = true
154 }
155 else if currentImageIndex == 3 {
156 ivPhoto4.image = pickedImage
157 ivPlus4.isHidden = true
158 }
159 else if currentImageIndex == 4 {
160 ivPhoto5.image = pickedImage
161 ivPlus5.isHidden = true
162 }
163 else if currentImageIndex == 5 {
164 ivPhoto6.image = pickedImage
165 ivPlus6.isHidden = true
166 }
167 }
168 dismiss(animated: true, completion: nil)
169 }
170
171 func didTapBackButton() {
172 self.navigationController?.popViewController(animated: true)
173 }
174
175 @IBAction func actionFinish() {
176 self.hideKeyboard()
177 let my_status = tvStatus.text
178 let about_me = tvAboutMe.text
179
180 // let my_status = "anuj"
181 // let about_me = "Anuj"
182//
183 if my_status != nil && (my_status?.characters.count)! < AppConfig.myStatusMaxLength {
184 Profile.sharedInstnce.bio = my_status!
185 } else {
186 Utility.presentAlertMessage("Warning", message: AppConfig.messageInvalidMyStatus, cancelActionText: "Ok", presentingViewContoller: self)
187 return
188 }
189 if about_me != nil && (about_me?.characters.count)! > AppConfig.aboutMeMinLength {
190 Profile.sharedInstnce.about_me = about_me!
191 } else {
192 Utility.presentAlertMessage("Warning", message: AppConfig.messageInvalidAboutMe, cancelActionText: "Ok", presentingViewContoller: self)
193 return
194 }
195
196 Profile.sharedInstnce.installId = Kumulos.installId
197//
198 selectedImageIndexArray.removeAll()
199 selectedImages.removeAll()
200 if ivPhoto1.image != nil {
201 selectedImages.append(ivPhoto1.image!)
202 selectedImageIndexArray.append(1)
203 }
204
205 if ivPhoto2.image != nil {
206 selectedImages.append(ivPhoto2.image!)
207 selectedImageIndexArray.append(2)
208 }
209
210 if ivPhoto3.image != nil {
211 selectedImages.append(ivPhoto3.image!)
212 selectedImageIndexArray.append(3)
213 }
214
215 if ivPhoto4.image != nil {
216 selectedImages.append(ivPhoto4.image!)
217 selectedImageIndexArray.append(4)
218 }
219
220 if ivPhoto5.image != nil {
221 selectedImages.append(ivPhoto5.image!)
222 selectedImageIndexArray.append(5)
223 }
224
225 if ivPhoto6.image != nil {
226 selectedImages.append(ivPhoto6.image!)
227 selectedImageIndexArray.append(6)
228 }
229
230 if selectedImages.count < AppConfig.minPhotoCount {
231 Utility.presentAlertMessage("Warning", message: AppConfig.messageInvalidPhoto, cancelActionText: "Ok", presentingViewContoller: self)
232 return
233 }
234
235 MBProgressHUD.showAdded(to: self.view, animated: true)
236
237 //self.uploadPhotos()
238 self.uploadCurrentUserProfile()
239 }
240
241 //********************** For Uploading Photos On Kumulos Server Code **********************************
242
243 func uploadPhotos() {
244
245 if(selectedImages.count == 0){
246 self.creationFinished()
247 return
248 }
249
250 var image = selectedImages[0]
251 let imageSelectedIndex : Int = selectedImageIndexArray[0]
252
253
254 var imageData = UIImageJPEGRepresentation(image, 0.4)!
255 while (imageData.count >= 47676) {
256 image = self.imageWithImage(image: image, width: image.size.width/1.1, height: image.size.height/1.1)
257 imageData = UIImageJPEGRepresentation(image, 0.4)!
258 }
259 self.selectedImages.remove(at: 0)
260 selectedImageIndexArray.remove(at: 0)
261 self.uploadImage(imageData, imageSelectedIndex : imageSelectedIndex)
262 }
263
264
265 func imageWithImage(image : UIImage , width : CGFloat , height : CGFloat) -> UIImage {
266 UIGraphicsBeginImageContext(CGSize(width: width, height: height))
267 image.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
268 let image = UIGraphicsGetImageFromCurrentImageContext()
269 UIGraphicsEndImageContext();
270 return image!
271
272
273 }
274
275 func uploadImage(_ imageData:Data , imageSelectedIndex : Int){
276
277 /*if let dataForServer = imageData
278 {
279 //let strBase64Image : Data = imageData.base64EncodedData()
280 let params = ["baseString": dataForServer as AnyObject, "imageIndex" : imageSelectedIndex as AnyObject , "phoneNumber" : Profile.sharedInstnce.phoneNumber as AnyObject]
281 let _ = Kumulos.call("imageUpload", parameters: params ).success { (response, operation) in
282 if let response = response.payload{
283 Profile.sharedInstnce.images.append(response as! Int)
284 self.uploadPhotos()
285 }
286
287 }
288 .failure { (error, operation) in
289 self.uploadPhotos()
290 }
291 }*/
292
293 let metadata = FIRStorageMetadata()
294 metadata.contentType = "image/jpeg"
295 let storageRef = FIRStorage.storage().reference().child("user_images/\(Profile.sharedInstnce.phoneNumber)/\(UUID().uuidString)")
296 let uploadTask = storageRef.put(imageData, metadata: metadata)
297
298 uploadTask.observe(.success) { snapshot in
299 // Upload completed successfully
300 let params = ["storageRef": storageRef.fullPath as AnyObject, "imageIndex" : imageSelectedIndex as AnyObject , "user": Profile.sharedInstnce.userID as AnyObject ]
301
302 let _ = Kumulos.call("imageUpload", parameters: params ).success { (response, operation) in
303 if let response = response.payload{
304 Profile.sharedInstnce.userImages.append(ImageModel.setDataInModel(responseData: [
305 "imageIndex":imageSelectedIndex as AnyObject,
306 "imageId":response as AnyObject,
307 "storageRef":storageRef.fullPath as AnyObject]))
308 self.uploadPhotos()
309 }
310
311 }
312 .failure { (error, operation) in
313 self.uploadPhotos()
314 }
315 }
316
317 uploadTask.observe(.failure) { snapshot in
318 print("Error uploading file!")
319 self.uploadPhotos()
320 }
321
322 }
323
324 func uploadCurrentUserProfile() {
325
326
327// if(Utility.sharedInstance.currentlyUploading){
328// Utility.sharedInstance.uploadAgain = true
329// return
330// }
331
332 var countryName = ""
333 if let country : String = Utility.sharedInstance.currentCountry {
334
335 countryName = country
336 }
337
338 Utility.sharedInstance.uploadAgain = false
339 Utility.sharedInstance.currentlyUploading = true
340
341 var firebasetoken = ""
342 if let firebaseToken = UserDefaults.standard.value(forKey: firebaseTokenKey) as? String
343 {
344 firebasetoken = firebaseToken
345 }
346
347 let stringImageId = Profile.sharedInstnce.images.map(String.init).joined(separator: ",")
348 let isAdminValue = false
349
350
351
352
353 let params = ["phoneNumber" : Profile.sharedInstnce.phoneNumber as AnyObject , "userName" : Profile.sharedInstnce.name as AnyObject , "bio" : Profile.sharedInstnce.bio as AnyObject , "education" : Profile.sharedInstnce.education as AnyObject , "profession" :Profile.sharedInstnce.profession as AnyObject , "language" : Profile.sharedInstnce.language as AnyObject , "nationality" : Profile.sharedInstnce.nationality as AnyObject , "height" : Profile.sharedInstnce.height as AnyObject , "ethnicity" : Profile.sharedInstnce.ethnicity as AnyObject, "gender" : Profile.sharedInstnce.gender as AnyObject, "faith" : Profile.sharedInstnce.faith as AnyObject , "religion" : Profile.sharedInstnce.religion as AnyObject , "relation" : Profile.sharedInstnce.relation as AnyObject, "about_me" : Profile.sharedInstnce.about_me as AnyObject, "phoneUserId" : Profile.sharedInstnce.phoneUserId as AnyObject , "age" : Profile.sharedInstnce.age as AnyObject , "birthday" : Profile.sharedInstnce.birthday as AnyObject , "imagesId" : stringImageId as AnyObject , "latitude" : Profile.sharedInstnce.location.coordinate.latitude as AnyObject , "longitude" : Profile.sharedInstnce.location.coordinate.longitude as AnyObject ,"push_booster" : 1 as AnyObject, "firbaseToken" : firebasetoken as AnyObject , "isAdmin" : isAdminValue as AnyObject , "country" : countryName as AnyObject , "push_message" : 1 as AnyObject , "push_match" : 1 as AnyObject, "installId": Profile.sharedInstnce.installId as AnyObject]
354
355
356 let _ = Kumulos.call("updateProfileData", parameters: params as Dictionary<String, AnyObject>).success{ (response, operation) in
357 print(response.payload)
358 if let response : Array = response.payload as? Array<AnyObject> {
359 if response.count > 0{
360
361 //let images = Profile.sharedInstnce.userImages
362 let profile = Profile.setDatainModel(dict: response[0] as! [String : AnyObject])
363 //profile.userImages = images
364
365 Profile.saveUserData(userData: profile)
366 self.appDelegate.setDataInModel()
367 Profile.updateDeviceToken()
368
369 NotificationCenter.default.post(name: NSNotification.Name(rawValue: "setProfilePicture"), object: nil, userInfo: nil )
370
371 if(self.selectedImages.count != 0)
372 {
373 self.uploadPhotos()
374 }else{
375 self.creationFinished()
376 }
377
378 }
379 }
380
381 }
382 .failure { (error, operation) in
383 DispatchQueue.main.async {
384 MBProgressHUD.hide(for: self.view, animated: true)
385 }
386
387 Utility.sharedInstance.currentlyUploading = false
388 let alert = UIAlertController(title: "Error", message: "There was an error during creating your profile", preferredStyle: UIAlertControllerStyle.alert)
389 alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.cancel, handler: nil))
390 self.present(alert, animated: true, completion: nil)
391
392 print("Error updating user profile: \(error?.localizedDescription)")
393 }
394
395
396
397
398 // Utility.sharedInstance.uploadCurrentUser({ () -> Void in
399 ////
400 //// self.appDelegate.swipeViewController.resaveLocalProfilePicture()
401 //// self.appDelegate.swipeViewController.loginViewControllerDidLogUserIn()
402 //// DispatchQueue.main.async(execute: { () -> Void in
403 //// MBProgressHUD.hide(for: self.view, animated: true)
404 ////
405 //// })
406 //// }) { () -> Void in
407 //// let alert = UIAlertController(title: "Error", message: "There was an error updating your profile", preferredStyle: UIAlertControllerStyle.alert)
408 //// alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.cancel, handler: nil))
409 //// self.present(alert, animated: true, completion: nil)
410 //// }
411
412 }
413
414 func creationFinished(){
415 self.appDelegate.swipeViewController.resaveLocalProfilePicture()
416
417 // self.handleFirebaseRegister()
418 self.appDelegate.swipeViewController.loginViewControllerDidLogUserIn()
419
420 self.handleFirebaseLogin()
421 }
422
423
424 func handleFirebaseLogin() {
425 FIRAuth.auth()?.signIn(withEmail : Profile.sharedInstnce.phoneNumber + "@gmail.com", password: Profile.sharedInstnce.phoneNumber, completion: { (user, error) in
426
427 if error != nil {
428 print(error)
429 self.handleFirebaseRegister()
430 // self.navigateToLoginScreen()
431 return
432
433 }
434
435 guard let uid = user?.uid else {
436 self.navigateToLoginScreen()
437 return
438 }
439 self.updateFirebaseIdOnKumulos(firebaseId: uid)
440
441 MBProgressHUD.hide(for: self.view, animated: true)
442
443
444 })
445 }
446
447
448
449
450 func handleFirebaseRegister() {
451
452 FIRAuth.auth()?.createUser(withEmail : Profile.sharedInstnce.phoneNumber + "@gmail.com", password: Profile.sharedInstnce.phoneNumber, completion: { (user: FIRUser?, error) in
453
454 if error != nil {
455 print(error)
456 self.navigateToLoginScreen()
457 return
458 }
459
460 guard let uid = user?.uid else {
461 self.navigateToLoginScreen()
462 return
463 }
464
465 self.updateFirebaseIdOnKumulos(firebaseId: uid)
466
467 let values = ["email": Profile.sharedInstnce.phoneNumber + "@gmail.com", "phoneNumber": Profile.sharedInstnce.phoneNumber,"isOnline":0,"lastSeen":0.0,"isTyping":0] as [String : Any]
468
469 self.registerUserIntoDatabaseWithUID(uid: uid, values: values as [String : AnyObject])
470
471
472 //successfully authenticated user
473 })
474 }
475
476 func registerUserIntoDatabaseWithUID(uid: String, values: [String: AnyObject]) {
477 let ref = FIRDatabase.database().reference()
478 let usersReference = ref.child("users").child(uid)
479
480 usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
481
482 if err != nil {
483 print(err)
484 return
485 }
486
487 })
488 }
489
490
491
492 func navigateToLoginScreen()
493 {
494 let alert = UIAlertController(title: "Error", message: "Some Error Occurred. Please try again.", preferredStyle: UIAlertControllerStyle.alert)
495 alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.cancel, handler: nil))
496 self.present(alert, animated: true, completion: nil)
497
498
499 for controller in (self.navigationController?.viewControllers)!
500 {
501 if controller is LoginViewController
502 {
503 self.navigationController?.popToViewController(controller, animated: true)
504 break
505
506 }
507 }
508 }
509
510 func updateFirebaseIdOnKumulos(firebaseId:String)
511 {
512
513 Profile.sharedInstnce.fbID = firebaseId
514 Profile.saveUserData(userData: Profile.sharedInstnce)
515
516 let params = ["phoneNumber" : Profile.sharedInstnce.phoneNumber as AnyObject , "firebaseId" : firebaseId as AnyObject]
517 let _ = Kumulos.call("updateUser", parameters: params).success{ (response, operation) in
518 print(response.payload)
519
520 self.appDelegate.swipeViewController.loginViewControllerDidLogUserIn()
521 DispatchQueue.main.async {
522
523 MBProgressHUD.hide(for: self.view, animated: true)
524 Profile.sharedInstnce.images.removeAll()
525 self.presentingViewController?.dismiss(animated: true, completion: nil)
526 // self.present(alert, animated: true, completion: nil)
527 }
528
529
530
531 }
532 .failure { (error, operation) in
533 self.navigateToLoginScreen()
534 }
535 }
536
537
538
539 // MARK: UITextView Delegate.
540 func textViewDidBeginEditing(_ textView: UITextView) {
541 if textView == tvStatus {
542 titleToolbar.title = "Status"
543 }
544 else if textView == tvAboutMe {
545 titleToolbar.title = "About Me"
546 }
547 }
548
549 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
550 if textView == tvStatus {
551 return textView.text.characters.count + (text.characters.count - range.length) <= 45
552 }
553 return true
554 }
555
556 func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
557 selectedTextView = textView
558 scrollViewOffset = scMain.contentOffset.y
559 return true
560 }
561
562 func textViewDidChange(_ textView: UITextView) {
563 let text = textView.text
564 if textView == tvAboutMe {
565 if let lenghtText = text?.characters.count {
566 lettersCounter.text = "\(lenghtText)"
567
568 }
569 } else if textView == tvStatus {
570 statusLettersCounter.text = "\(45 - (text?.characters.count)!)"
571 }
572 }
573
574 func hideKeyboard() {
575 tvStatus.resignFirstResponder()
576 tvAboutMe.resignFirstResponder()
577 }
578
579 @IBAction func actionInputDone() {
580 hideKeyboard()
581 }
582
583 @IBAction func actionInputNext() {
584 if selectedTextView == tvStatus {
585 tvAboutMe.becomeFirstResponder()
586 } else {
587 hideKeyboard()
588 let bottomOffset: CGPoint = CGPoint(x: 0, y: scMain.contentSize.height - scMain.bounds.size.height)
589 scMain.setContentOffset(bottomOffset, animated: true)
590 }
591 }
592
593 func keyboardWillShow(_ sender: Notification) {
594 if animationAdded { scMain.setContentOffset(CGPoint(x: 0, y: scrollViewOffset), animated: true) }
595 animationAdded = true
596 // let keyboardHeight: CGFloat = (((sender as NSNotification).userInfo![UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue.size).height + 44
597
598 let keyboardHeight : CGFloat = ((sender as NSNotification).userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size.height + 44
599 let keyboardY = UIScreen.main.bounds.height - keyboardHeight
600 guard let textView = selectedTextView else { return }
601 let globalPoint = textView.superview?.convert(textView.frame.origin, to: UIApplication.shared.keyWindow?.rootViewController?.view)
602 if let point = globalPoint {
603 let textViewY: CGFloat = point.y + textView.frame.size.height
604 if textViewY > keyboardY {
605 let animationValue = textViewY - keyboardY + 10.0
606 scMain.setContentOffset(CGPoint(x: 0, y: scrollViewOffset + animationValue), animated: true)
607 }
608 }
609 }
610
611 func keyboardWillHide(_ sender: Notification) {
612 if animationAdded {
613 animationAdded = false
614 scMain.setContentOffset(CGPoint(x: 0, y: scrollViewOffset), animated: true)
615 }
616 }
617 }