Parcourir la source

fix bugs and new request

alqindiirsyam il y a 6 mois
Parent
commit
81acfa54b9

+ 9 - 7
NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -368,7 +368,6 @@ public class Nexilis: NSObject {
     private static func getPullGroupNoMember() {
         if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.pullGroupNoMember(), timeout: 30 * 1000), response.isOk() {
             let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
-            //print("KUACAU \(data)")
             if !data.isEmpty {
                 if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
@@ -3154,7 +3153,8 @@ extension Nexilis: MessageDelegate {
             let fPinContacCenter = message.getBody(key: CoreMessage_TMessageKey.F_PIN)
             let requester = message.getBody(key: CoreMessage_TMessageKey.UPLINE_PIN)
             let complaintId = message.getBody(key: CoreMessage_TMessageKey.DATA)
-            if !requester.isEmpty {
+            let onGoingCC: String = SecureUserDefaults.shared.value(forKey: "onGoingCC") ?? ""
+            if !requester.isEmpty && onGoingCC.isEmpty {
                 SecureUserDefaults.shared.set("\(requester),\(fPinContacCenter),\(complaintId)", forKey: "onGoingCC")
                 SecureUserDefaults.shared.set("\(fPinContacCenter)", forKey: "membersCC")
             }
@@ -3333,13 +3333,9 @@ extension Nexilis: MessageDelegate {
                                         var members = ""
                                         var user : [User] = []
                                         let idMe = User.getMyPin()!
+                                        
                                         for json in jsonArray {
                                             if "\(json)" != idMe {
-                                                if members.isEmpty {
-                                                    members = "\(json)"
-                                                } else {
-                                                    members += ",\(json)"
-                                                }
                                                 if let userData = User.getData(pin: "\(json)") {
                                                     user.append(userData)
                                                 } else {
@@ -3350,8 +3346,14 @@ extension Nexilis: MessageDelegate {
                                                         }
                                                     })
                                                 }
+                                                if members.isEmpty {
+                                                    members = "\(json)"
+                                                } else {
+                                                    members += ",\(json)"
+                                                }
                                             }
                                         }
+                                        print("HEHE0 \(members)")
                                         SecureUserDefaults.shared.set("\(members)", forKey: "membersCC")
                                         if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
                                             let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal

+ 0 - 1
NexilisLite/NexilisLite/Source/Utils.swift

@@ -1799,7 +1799,6 @@ public class DialogUnableAccess: UIViewController {
     }
     
     @objc func kycTapped() {
-        //print("kycTapped")
         APIS.openContactCenter()
         self.dismiss(animated: true)
     }

+ 20 - 23
NexilisLite/NexilisLite/Source/View/Call/QmeraAudioViewController.swift

@@ -824,6 +824,7 @@ class QmeraAudioViewController: UIViewController {
                                 }
                             }
                             SecureUserDefaults.shared.set(members, forKey: "inEditorPersonal")
+                            SecureUserDefaults.shared.set("\(members)", forKey: "membersCC")
                         }
                     }
                     self.users.append(User.getData(pin: dataMessage.getPIN())!)
@@ -887,23 +888,6 @@ class QmeraAudioViewController: UIViewController {
                 }
                 if (!isOutgoing || !firstCall), users.count >= 1, let user = User.getData(pin: String(arrayMessage[1])), !users.contains(user) {
                     self.users.append(user)
-                    let onGoingCC: String = SecureUserDefaults.shared.value(forKey: "onGoingCC") ?? ""
-                    if !onGoingCC.isEmpty {
-                        DispatchQueue.main.async {
-                            var members = ""
-                            for user in self.users {
-                                if members.isEmpty {
-                                    members = "\(user.pin)"
-                                } else {
-                                    members = ",\(user.pin)"
-                                }
-                            }
-                            SecureUserDefaults.shared.set("\(members)", forKey: "membersCC")
-                        }
-                    }
-                    if buttonWB.isEnabled {
-                        buttonWB.isEnabled = false
-                    }
                 }
             } else if state == Nexilis.AUDIO_CALL_END || (!ticketId.isEmpty && state == Nexilis.VIDEO_CALL_END) {
                 if isOutgoing {
@@ -919,6 +903,9 @@ class QmeraAudioViewController: UIViewController {
                         let officer = onGoingCC.isEmpty ? "" : onGoingCC.components(separatedBy: ",")[1]
                         if pin == requester || pin == officer {
                             DispatchQueue.main.async {
+                                if !self.end.isEnabled {
+                                    return
+                                }
                                 if self.buttonWB.isDescendant(of: self.view){
                                     self.buttonWB.removeFromSuperview()
                                 }
@@ -943,6 +930,9 @@ class QmeraAudioViewController: UIViewController {
                         }
                     } else if !onGoingCC.isEmpty && users.count == 0 {
                         DispatchQueue.main.async {
+                            if !self.end.isEnabled {
+                                return
+                            }
                             if self.buttonWB.isDescendant(of: self.view){
                                 self.buttonWB.removeFromSuperview()
                             }
@@ -982,8 +972,11 @@ class QmeraAudioViewController: UIViewController {
                             self.didEnd(sender: true)
                         }
                         return
-                    } else if users.count == 1 && !buttonWB.isEnabled {
-                        buttonWB.isEnabled = true
+                    }
+                    DispatchQueue.main.async{ [self] in
+                        if users.count == 1 && !buttonWB.isEnabled {
+                            buttonWB.isEnabled = true
+                        }
                     }
                 }
 //                if users.count == 0 {
@@ -1013,8 +1006,10 @@ class QmeraAudioViewController: UIViewController {
                             SecureUserDefaults.shared.set("\(members)", forKey: "membersCC")
                         }
                     }
-                    if users.count == 1 && !buttonWB.isEnabled {
-                        buttonWB.isEnabled = true
+                    DispatchQueue.main.async { [self] in
+                        if users.count == 1 && !buttonWB.isEnabled {
+                            buttonWB.isEnabled = true
+                        }
                     }
                 }
                 if users.count == 0 {
@@ -1048,8 +1043,10 @@ class QmeraAudioViewController: UIViewController {
                             SecureUserDefaults.shared.set("\(members)", forKey: "membersCC")
                         }
                     }
-                    if users.count == 1 && !buttonWB.isEnabled {
-                        buttonWB.isEnabled = true
+                    DispatchQueue.main.async { [self] in
+                        if users.count == 1 && !buttonWB.isEnabled {
+                            buttonWB.isEnabled = true
+                        }
                     }
                 }
                 if users.count == 0 {

+ 23 - 2
NexilisLite/NexilisLite/Source/View/Call/QmeraVideoViewController.swift

@@ -515,9 +515,11 @@ class QmeraVideoViewController: UIViewController {
                                     }
                                 }
                             }
+                            SecureUserDefaults.shared.set(members, forKey: "inEditorPersonal")
                             SecureUserDefaults.shared.set("\(members)", forKey: "membersCC")
                         }
                     }
+                    self.users.append(User.getData(pin: dataMessage.getPIN())!)
                 }
             }
         }
@@ -666,7 +668,7 @@ class QmeraVideoViewController: UIViewController {
         let navigationController = CustomNavigationController(rootViewController: editorPersonalVC)
         navigationController.modalPresentationStyle = .overCurrentContext
         navigationController.navigationBar.tintColor = .white
-//        navigationController.navigationBar.barTintColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
+        navigationController.navigationBar.barTintColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
         navigationController.navigationBar.isTranslucent = false
         navigationController.navigationBar.overrideUserInterfaceStyle = .dark
         navigationController.navigationBar.barStyle = .black
@@ -1125,6 +1127,20 @@ class QmeraVideoViewController: UIViewController {
                         labelName.textColor = .white
                     }
                     self.scrollRemoteView.contentSize.height = CGFloat(170 * 2)
+                    if self.buttonWB.isEnabled {
+                        self.buttonWB.isEnabled = false
+                    }
+                    if self.buttonRotate.isEnabled {
+                        self.buttonRotate.isEnabled = false
+                        if self.wbVC != nil && self.wbVC!.view.isDescendant(of: self.view){
+                            self.wbVC!.view.removeFromSuperview()
+                            self.buttonDecline.isHidden = false
+                            self.buttonSpeaker.isHidden = false
+                            self.buttonAddParticipant.isHidden = false
+                            self.buttonRotate.isHidden = false
+                            self.buttonMuted.isHidden = false
+                        }
+                    }
                 } else if self.dataPerson.count > 1 {
                     if self.dataPerson.firstIndex(where: {$0["f_pin"]!! == arrayMessage[1]}) != nil {
                         return
@@ -1163,6 +1179,9 @@ class QmeraVideoViewController: UIViewController {
                     labelName.textColor = .white
                 }
             }
+            if users.count >= 1, let user = User.getData(pin: String(arrayMessage[1])), !users.contains(user) {
+                self.users.append(user)
+            }
             if arrayMessage[5] == "2" && self.dataPerson.count == 1 {
                 DispatchQueue.main.async {
                     self.zoomView.transform   = CGAffineTransform.init(scaleX: -1.9, y: 2.2).rotated(by: (CGFloat.pi)/2)
@@ -1618,9 +1637,11 @@ extension QmeraVideoViewController : WhiteboardReceiver {
     
     @objc func runTimer(){
         DispatchQueue.main.async {
+            if !self.buttonWB.isEnabled {
+                return
+            }
             self.wbBlink = !self.wbBlink
             if(self.wbBlink){
-                //print("set wb blink on")
                 self.buttonWB.backgroundColor = .green
             }
             else {

+ 0 - 1
NexilisLite/NexilisLite/Source/View/Call/WhiteboardViewController.swift

@@ -300,7 +300,6 @@ class WhiteboardViewController: UIViewController, WhiteboardDelegate {
     
     func sendInit(){
         let d = destinations.joined(separator: ",")
-        //print("KOCAK \(d)")
 //            roomId = "\(me)\(tid)"
         wb?.setRoomId(roomId: roomId)
         wb!.sendInit(destinations: d)

+ 0 - 1
NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift

@@ -264,7 +264,6 @@ public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
 //            }
 //            self.timeoutCC.invalidate()
 //            NotificationCenter.default.removeObserver(self)
-//            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshView"), object: nil, userInfo: nil)
 //            self.dismiss(animated: true, completion: nil)
 //        } else if !complaintId.isEmpty {
 //            let alert = LibAlertController(title: "Interaction with Call Center is in progress".localized(), message: "Are you sure you want to end the Call Center?".localized(), preferredStyle: .alert)

+ 30 - 5
NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift

@@ -50,6 +50,8 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
     var stickers = [String]()
     public var unique_l_pin = ""
     public var fromNotification = false
+    public var referenceMessageId = ""
+    public var referenceChatDate = ""
     var isHistoryCC = false
     var complaintId = ""
     var counter = 0
@@ -407,7 +409,20 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
         tableChatView.delegate = self
         tableChatView.dataSource = self
         tableChatView.reloadData()
-        if counter != 0 {
+        if !referenceMessageId.isEmpty {
+            if dataMessages.firstIndex(where: {$0["message_id"] as? String == referenceMessageId} ) != 0 {
+                DispatchQueue.main.async {
+                    let section = self.dataDates.firstIndex(of: self.referenceChatDate)
+                    let row = self.dataMessages.filter({$0["chat_date"] as! String == self.referenceChatDate}).firstIndex(where: { $0["message_id"] as? String == self.referenceMessageId})
+                    let indexPath = IndexPath(row: row!, section: section!)
+                    self.tableChatView.scrollToRow(at: indexPath, at: .middle, animated: false)
+                    self.tableChatView.cellForRow(at: indexPath)?.contentView.backgroundColor = .yellow
+                    DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
+                        self.tableChatView.cellForRow(at: indexPath)?.contentView.backgroundColor = .clear
+                    })
+                }
+            }
+        } else if counter != 0 {
             if dataMessages.firstIndex(where: {$0["message_id"] as? String == markerCounter} ) != 0 {
                 DispatchQueue.main.async {
                     let data = self.dataMessages.filter({ $0["message_id"] as? String == self.markerCounter })
@@ -1092,7 +1107,12 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
                                     })
                                 }
                             }
-                            self.tableChatView.reloadRows(at: [IndexPath(row: self.dataMessages.filter({ $0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).count - 1, section: self.dataDates.count - 1)], with: .none)
+                            let section = self.dataDates.firstIndex(of: self.dataDates[self.dataDates.count - 1])
+                            let row = self.dataMessages.filter({$0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).firstIndex(where: { $0["message_id"] as? String == row["message_id"] as? String})
+                            let indexPath = IndexPath(row: row!, section: section!)
+                            if row != nil && section != nil{
+                                self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+                            }
                         })
                     }
                     if  self.currentIndexpath?.row == (self.dataMessages.count - 2) {
@@ -1497,7 +1517,6 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
     @objc func didTapExit() {
         SecureUserDefaults.shared.removeValue(forKey: "inEditorGroup")
         NotificationCenter.default.removeObserver(self)
-        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshView"), object: nil, userInfo: nil)
         self.dismiss(animated: true, completion: nil)
     }
     
@@ -1801,7 +1820,6 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
         if credential == "1" {
             var timer = Timer()
             var minute = 60
-            self.timerCredential[messageId] = timer
             timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: {_ in
                 minute -= 1
                 self.listTimerCredential[messageId] = minute
@@ -1827,8 +1845,13 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
                         })
                     }
                 }
-                self.tableChatView.reloadRows(at: [IndexPath(row: self.dataMessages.filter({ $0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).count - 1, section: self.dataDates.count - 1)], with: .none)
+                let section = self.dataDates.firstIndex(of: self.dataDates[self.dataDates.count - 1])
+                let row = self.dataMessages.filter({$0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).firstIndex(where: { $0["message_id"] as? String == messageId})
+                if row != nil && section != nil{
+                    self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+                }
             })
+            self.timerCredential[messageId] = timer
         }
         if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintViewTextField.constant == 0 {
             textFieldSend.text = "Send message".localized()
@@ -2888,6 +2911,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                     self.dataMessages[idx!]["is_stared"] = "1"
                 }
                 self.tableChatView.reloadRows(at: [indexPath!], with: .none)
+                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "listenerStarMessage"), object: nil, userInfo: nil)
             })
         } else {
             star = UIAction(title: "Unstar".localized(), image: UIImage(systemName: "star.slash"), handler: {(_) in
@@ -2911,6 +2935,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                     self.dataMessages[idx!]["is_stared"] = "0"
                 }
                 self.tableChatView.reloadRows(at: [indexPath!], with: .none)
+                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "listenerStarMessage"), object: nil, userInfo: nil)
             })
         }
         

+ 59 - 29
NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -53,6 +53,8 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
     public var onGoingCC = false
     public var fPinContacCenter = ""
     public var complaintId = ""
+    public var referenceMessageId = ""
+    public var referenceChatDate = ""
     var channelContactCenter = ""
     var counter = 0
     var dateStartCC = ""
@@ -124,19 +126,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
     
     public override func viewDidDisappear(_ animated: Bool) {
         if self.isMovingFromParent {
-            for timer in self.timerCredential.values {
-                timer.invalidate()
-            }
-            self.timeoutCC.invalidate()
-            SecureUserDefaults.shared.removeValue(forKey: "inEditorPersonal")
-            NotificationCenter.default.removeObserver(self)
-            super.viewDidDisappear(true)
-            self.removeFromParent()
-            self.dismiss(animated: true, completion: nil)
-            if !isContactCenter {
-                let l_pin = self.dataPerson["f_pin"]!!
-                SecureUserDefaults.shared.set("\(textFieldSend.textColor != UIColor.lightGray ? textFieldSend.text! : ""),\(reffId ?? "")", forKey: "saved_\(l_pin)")
-            }
+            removeAllObjectBeforeDismissVC()
         }
     }
     
@@ -562,7 +552,20 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
             }
             
             tableChatView.alpha = 0
-            if counter != 0 && dataMessages.count >= counter {
+            if !referenceMessageId.isEmpty {
+                if dataMessages.firstIndex(where: {$0["message_id"] as? String == referenceMessageId} ) != 0 {
+                    DispatchQueue.main.async {
+                        let section = self.dataDates.firstIndex(of: self.referenceChatDate)
+                        let row = self.dataMessages.filter({$0["chat_date"] as! String == self.referenceChatDate}).firstIndex(where: { $0["message_id"] as? String == self.referenceMessageId})
+                        let indexPath = IndexPath(row: row!, section: section!)
+                        self.tableChatView.scrollToRow(at: indexPath, at: .middle, animated: false)
+                        self.tableChatView.cellForRow(at: indexPath)?.contentView.backgroundColor = .yellow
+                        DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
+                            self.tableChatView.cellForRow(at: indexPath)?.contentView.backgroundColor = .clear
+                        })
+                    }
+                }
+            } else if counter != 0 && dataMessages.count >= counter {
                 if dataMessages.firstIndex(where: {$0["message_id"] as? String == markerCounter} ) != 0 {
                     DispatchQueue.main.async {
                         let data = self.dataMessages.filter({ $0["message_id"] as? String == self.markerCounter })
@@ -1469,7 +1472,9 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
                         SecureUserDefaults.shared.set(dataMessage.getBody(key: CoreMessage_TMessageKey.CHANNEL), forKey: "channelCC")
                         DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
-                            self.dismiss(animated: true, completion: nil)
+                            self.dismiss(animated: true, completion: {
+                                self.removeAllObjectBeforeDismissVC()
+                            })
                         })
                     } else {
                         viewButton.isHidden = false
@@ -1519,10 +1524,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         timeoutCC.invalidate()
                         DispatchQueue.main.asyncAfter(deadline: .now() + 1.5, execute: {
                             if !(self.presentedViewController is EditorPersonal) {
-                                self.dismiss(animated: true, completion: nil)
+                                self.dismiss(animated: true, completion: {
+                                    self.removeAllObjectBeforeDismissVC()
+                                })
                             }
                             DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
-                                self.dismiss(animated: true, completion: nil)
+                                self.dismiss(animated: true, completion: {
+                                    self.removeAllObjectBeforeDismissVC()
+                                })
                             }
                         })
                     } else {
@@ -1655,7 +1664,11 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                     })
                                 }
                             }
-                            self.tableChatView.reloadRows(at: [IndexPath(row: self.dataMessages.filter({ $0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).count - 1, section: self.dataDates.count - 1)], with: .none)
+                            let section = self.dataDates.firstIndex(of: self.dataDates[self.dataDates.count - 1])
+                            let row = self.dataMessages.filter({$0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).firstIndex(where: { $0["message_id"] as? String == row["message_id"] as? String})
+                            if row != nil && section != nil{
+                                self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+                            }
                         })
                     }
                     if self.isContactCenter {
@@ -2360,14 +2373,9 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
     
     @objc func didTapExit() {
         if complaintId.isEmpty || fromVCAC {
-            for timer in self.timerCredential.values {
-                timer.invalidate()
-            }
-            self.timeoutCC.invalidate()
-            SecureUserDefaults.shared.removeValue(forKey: "inEditorPersonal")
-            NotificationCenter.default.removeObserver(self)
-            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshView"), object: nil, userInfo: nil)
-            self.dismiss(animated: true, completion: nil)
+            self.dismiss(animated: true, completion: {
+                self.removeAllObjectBeforeDismissVC()
+            })
         } else if !complaintId.isEmpty {
             let alert = LibAlertController(title: "Interaction with Call Center is in progress".localized(), message: "Are you sure you want to end the Call Center?".localized(), preferredStyle: .alert)
             alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: nil))
@@ -2378,6 +2386,20 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         }
     }
     
+    private func removeAllObjectBeforeDismissVC() {
+        for timer in self.timerCredential.values {
+            timer.invalidate()
+        }
+        self.timeoutCC.invalidate()
+        SecureUserDefaults.shared.removeValue(forKey: "inEditorPersonal")
+        NotificationCenter.default.removeObserver(self)
+        self.removeFromParent()
+        if !self.isContactCenter {
+            let l_pin = self.dataPerson["f_pin"]!!
+            SecureUserDefaults.shared.set("\(self.textFieldSend.textColor != UIColor.lightGray ? self.textFieldSend.text! : ""),\(self.reffId ?? "")", forKey: "saved_\(l_pin)")
+        }
+    }
+    
     public func endCallCenter() {
         timeoutCC.invalidate()
         let complaintId = self.complaintId
@@ -2418,7 +2440,9 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
             SecureUserDefaults.shared.removeValue(forKey: "membersCC")
             SecureUserDefaults.shared.removeValue(forKey: "waitingRequestCC")
         }
-        self.dismiss(animated: true, completion: nil)
+        self.dismiss(animated: true, completion: {
+            self.removeAllObjectBeforeDismissVC()
+        })
     }
     
     @objc func keyboardWillHide(notification: NSNotification) {
@@ -2600,7 +2624,6 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         if credential == "1" {
             var timer = Timer()
             var minute = 60
-            self.timerCredential[messageId] = timer
             timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: {_ in
                 minute -= 1
                 self.listTimerCredential[messageId] = minute
@@ -2626,8 +2649,13 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         })
                     }
                 }
-                self.tableChatView.reloadRows(at: [IndexPath(row: self.dataMessages.filter({ $0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).count - 1, section: self.dataDates.count - 1)], with: .none)
+                let section = self.dataDates.firstIndex(of: self.dataDates[self.dataDates.count - 1])
+                let row = self.dataMessages.filter({$0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).firstIndex(where: { $0["message_id"] as? String == messageId})
+                if row != nil && section != nil{
+                    self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+                }
             })
+            self.timerCredential[messageId] = timer
         }
         if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintViewTextField.constant == 0 {
             textFieldSend.text = "Send message".localized()
@@ -3923,6 +3951,7 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                     self.dataMessages[idx!]["is_stared"] = "1"
                 }
                 self.tableChatView.reloadRows(at: [indexPath!], with: .none)
+                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "listenerStarMessage"), object: nil, userInfo: nil)
             })
         } else {
             star = UIAction(title: "Unstar".localized(), image: UIImage(systemName: "star.slash"), handler: {(_) in
@@ -3946,6 +3975,7 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                     self.dataMessages[idx!]["is_stared"] = "0"
                 }
                 self.tableChatView.reloadRows(at: [indexPath!], with: .none)
+                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "listenerStarMessage"), object: nil, userInfo: nil)
             })
         }
         

+ 90 - 133
NexilisLite/NexilisLite/Source/View/Chat/EditorStarMessages.swift

@@ -12,7 +12,7 @@ import QuickLook
 import Photos
 import SwiftLinkPreview
 
-public class EditorStarMessages: UIViewController, UITableViewDataSource, UITableViewDelegate, UIContextMenuInteractionDelegate, QLPreviewControllerDataSource {
+public class EditorStarMessages: UIViewController, UITableViewDataSource, UITableViewDelegate, UIContextMenuInteractionDelegate, QLPreviewControllerDataSource, UITextViewDelegate {
     @IBOutlet var tableChatView: UITableView!
     var dataMessages: [[String: Any?]] = []
     var dataDates: [String] = []
@@ -74,9 +74,15 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
         
         let center: NotificationCenter = NotificationCenter.default
         center.addObserver(self, selector: #selector(onStatusChat(notification:)), name: NSNotification.Name(rawValue: Nexilis.listenerStatusChat), object: nil)
+        center.addObserver(self, selector: #selector(onRefreshData(notification:)), name: NSNotification.Name(rawValue: "listenerStarMessage"), object: nil)
 
     }
     
+    @objc func onRefreshData(notification: NSNotification) {
+        getData()
+        tableChatView.reloadData()
+    }
+    
     @objc func didTapExit() {
         self.dismiss(animated: true, completion: nil)
     }
@@ -200,7 +206,15 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
         timeMessage.translatesAutoresizingMaskIntoConstraints = false
         timeMessage.bottomAnchor.constraint(equalTo: cellMessage.contentView.bottomAnchor, constant: -5).isActive = true
         
-        let messageText = UILabel()
+        let messageText = UITextView()
+        messageText.isEditable = false
+        messageText.isSelectable = true
+        messageText.dataDetectorTypes = []
+        messageText.backgroundColor = .clear
+        messageText.isScrollEnabled = false
+        messageText.textContainerInset = UIEdgeInsets.zero
+        messageText.contentInset = UIEdgeInsets.zero
+        messageText.textDragInteraction?.isEnabled = false
         containerMessage.addSubview(messageText)
         messageText.translatesAutoresizingMaskIntoConstraints = false
         let topMarginText = messageText.topAnchor.constraint(equalTo: containerMessage.topAnchor, constant: 32)
@@ -348,10 +362,6 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
             imageStared.backgroundColor = .clear
             imageStared.tintColor = .systemYellow
         }
-        
-        messageText.numberOfLines = 0
-        messageText.lineBreakMode = .byWordWrapping
-        containerMessage.addSubview(messageText)
         topMarginText.isActive = true
         if dataMessages[indexPath.row]["attachment_flag"] as! String == "27" || dataMessages[indexPath.row]["attachment_flag"] as! String == "26" {
             messageText.leadingAnchor.constraint(equalTo: containerMessage.leadingAnchor, constant: 85).isActive = true
@@ -419,36 +429,37 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                 imageSticker.contentMode = .scaleAspectFit
             }
             else {
-                messageText.attributedText = textChat!.richText()
+                modifyText()
             }
         } else {
-            messageText.attributedText = textChat!.richText()
+            modifyText()
         }
         messageText.font = UIFont.systemFont(ofSize: 12)
         
-        messageText.isUserInteractionEnabled = false
-        if !textChat!.isEmpty {
-            if textChat!.contains("■"){
-                textChat = textChat?.components(separatedBy: "■")[0]
-                textChat = textChat?.trimmingCharacters(in: .whitespacesAndNewlines)
-            }
-            let listTextEnter = textChat!.split(separator: "\n")
-            for j in 0...listTextEnter.count - 1 {
-                let listText = listTextEnter[j].split(separator: " ")
-                if listText.count > 0 {
-                    for i in 0...listText.count - 1 {
-                        if listText[i].lowercased().checkStartWithLink() {
-                            let attributedString = textChat!.richText()
-                            let rangeTapLink = (attributedString.string as NSString).range(of: String(listText[i]))
-                            attributedString.addAttributes([.foregroundColor: UIColor.blue, .underlineStyle: NSUnderlineStyle.single.rawValue], range: rangeTapLink)
-                            messageText.attributedText = attributedString
-                            messageText.isUserInteractionEnabled = true
-                            let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressLink(_:)))
-                            longPress.minimumPressDuration = 0.1
-                            containerMessage.addGestureRecognizer(longPress)
+        func modifyText() {
+            if !textChat!.isEmpty {
+                if textChat!.contains("■"){
+                    textChat = textChat!.components(separatedBy: "■")[0]
+                    textChat = textChat!.trimmingCharacters(in: .whitespacesAndNewlines)
+                }
+                let finalAtribute = textChat!.richText()
+                textChat = finalAtribute.string
+                let urlPattern = "(https?://|www\\.)\\S+"
+                if let regex = try? NSRegularExpression(pattern: urlPattern, options: []) {
+                    let matches = regex.matches(in: textChat!, options: [], range: NSRange(textChat!.startIndex..., in: textChat!))
+                    
+                    for match in matches {
+                        if let range = Range(match.range, in: textChat!) {
+                            let linkText = String(textChat![range])
+                            let nsRange = NSRange(range, in: textChat!)
+                            finalAtribute.addAttribute(.link, value: linkText, range: nsRange)
+                            finalAtribute.addAttribute(.foregroundColor, value: UIColor.blue, range: nsRange)
+                            finalAtribute.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: nsRange)
                         }
                     }
                 }
+                messageText.attributedText = finalAtribute
+                messageText.delegate = self
             }
         }
         
@@ -854,120 +865,22 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
         
         return cellMessage
     }
-    
-    @objc func handleLongPressLink(_ gestureRecognizer: UILongPressGestureRecognizer) {
-        func showMenuContext() {
-            if gestureRecognizer.state == .cancelled || gestureRecognizer.state == .ended{
-                timerCheckLink?.invalidate()
-            } else if gestureRecognizer.state == .began {
-                timerCheckLink = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false, block: {_ in
-                    let interaction = UIContextMenuInteraction(delegate: self)
-                    gestureRecognizer.view!.addInteraction(interaction)
-                    guard let interaction = gestureRecognizer.view!.interactions.first,
-                          let data = Data(base64Encoded: "X3ByZXNlbnRNZW51QXRMb2NhdGlvbjo="),
-                          let str = String(data: data, encoding: .utf8)
-                    else {
-                        return
-                    }
-                    let selector = NSSelectorFromString(str)
-                    guard interaction.responds(to: selector) else {
-                        return
-                    }
-                    let impactHeavy = UIImpactFeedbackGenerator(style: .heavy)
-                    impactHeavy.impactOccurred()
-                    interaction.perform(selector, with: self.view)
-                    self.showMenuContext = true
-                })
-            }
-        }
-        if gestureRecognizer.state == .began {
-            let touchPoint = gestureRecognizer.location(in: self.view)
-            touchedSubview = self.view.hitTest(touchPoint, with: nil) ?? UIView()
-            if !(touchedSubview is UILabel) {
-                showMenuContext()
-            }
-        }
-        guard let label = touchedSubview as? UILabel else { return }
-        let touchPointLabel = gestureRecognizer.location(in: label)
-
-        if let text = label.text, let range = getWordRange(at: touchPointLabel, in: label) {
-            let word = String(text[range])
-            if word.starts(with: "www.") || word.starts(with: "https://") || word.starts(with: "http://") {
-                if gestureRecognizer.state == .cancelled || gestureRecognizer.state == .ended {
-                    timerCheckLink?.invalidate()
-                    if label.isHighlighted {
-                        var stringURl = word
-                        if stringURl.starts(with: "www.") {
-                            stringURl = "https://" + stringURl.replacingOccurrences(of: "www.", with: "")
-                        }
-                        guard let url = URL(string: stringURl) else { return }
-                        UIApplication.shared.open(url)
-                        label.attributedText = removeHighlightedText(for: text, in: range, label: label)
-                    }
-                } else if gestureRecognizer.state == .began {
-                    label.attributedText = highlightedText(for: text, in: range, label: label)
-                    timerCheckLink = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: {_ in
-                        UIPasteboard.general.string = word
-                        self.view.makeToast("Link Copied".localized(), duration: 3)
-                        label.attributedText = self.removeHighlightedText(for: text, in: range, label: label)
-                    })
-                }
-            } else {
-                showMenuContext()
-            }
-        } else {
-            showMenuContext()
-        }
-    }
-    
-    func getWordRange(at point: CGPoint, in label: UILabel) -> Range<String.Index>? {
-        guard let text = label.text else { return nil }
-        
-        let layoutManager = NSLayoutManager()
-        let textContainer = NSTextContainer(size: label.frame.size)
-        let textStorage = NSTextStorage(attributedString: NSAttributedString(string: text))
-        
-        layoutManager.addTextContainer(textContainer)
-        textStorage.addLayoutManager(layoutManager)
-        textContainer.lineFragmentPadding = 0
-        textContainer.maximumNumberOfLines = label.numberOfLines
-        
-        lastTouchPoint = point
-        let characterIndex = layoutManager.characterIndex(for: point, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
-        
-        if characterIndex == text.count - 1 {
-            return nil
-        }
-        var wordStartIndex = characterIndex
-        while wordStartIndex > 0 && text[text.index(text.startIndex, offsetBy: wordStartIndex - 1)] != " " && text[text.index(text.startIndex, offsetBy: wordStartIndex - 1)] != "\n" {
-            wordStartIndex -= 1
-        }
-        
-        var wordEndIndex = characterIndex
-        while wordEndIndex < text.count && text[text.index(text.startIndex, offsetBy: wordEndIndex)] != " " && text[text.index(text.startIndex, offsetBy: wordEndIndex)] != "\n" {
-            wordEndIndex += 1
-        }
-        
-        return text.index(text.startIndex, offsetBy: wordStartIndex)..<text.index(text.startIndex, offsetBy: wordEndIndex)
-    }
 
-    func highlightedText(for text: String, in range: Range<String.Index>, label: UILabel) -> NSAttributedString {
-        let mutableAttributedString = label.attributedText!.mutableCopy() as! NSMutableAttributedString
+    func highlightedText(for text: String, in range: Range<String.Index>, textView: UITextView) -> NSAttributedString {
+        let mutableAttributedString = textView.attributedText!.mutableCopy() as! NSMutableAttributedString
         mutableAttributedString.addAttribute(.backgroundColor, value: UIColor.lightGray.withAlphaComponent(0.5), range: NSRange(range, in: text))
-        label.isHighlighted = true
         return mutableAttributedString
     }
     
-    func removeHighlightedText(for text: String, in range: Range<String.Index>, label: UILabel) -> NSAttributedString {
-        let mutableAttributedString = label.attributedText!.mutableCopy() as! NSMutableAttributedString
+    func removeHighlightedText(for text: String, in range: Range<String.Index>, textView: UITextView) -> NSAttributedString {
+        let mutableAttributedString = textView.attributedText!.mutableCopy() as! NSMutableAttributedString
         mutableAttributedString.removeAttribute(.backgroundColor, range: NSRange(range, in: text))
-        label.isHighlighted = false
         return mutableAttributedString
     }
-    
+        
     @objc func tapMessageText(_ sender: ObjectGesture) {
-        var stringURl = sender.message_id.lowercased()
-        if stringURl.starts(with: "www.") {
+        var stringURl = sender.message_id
+        if stringURl.lowercased().starts(with: "www.") {
             stringURl = "https://" + stringURl.replacingOccurrences(of: "www.", with: "")
         }
         guard let url = URL(string: stringURl) else { return }
@@ -975,6 +888,9 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
     }
     
     func getData() {
+        if !dataMessages.isEmpty {
+            dataMessages.removeAll()
+        }
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
             do {
                 if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared, blog_id FROM MESSAGE where is_stared=1 order by server_date asc") {
@@ -1659,5 +1575,46 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                 navigationController?.present(streamingNav, animated: true, completion: nil)
             }
         }
+        if message[TypeDataMessage.message_scope_id] as? String == "3" {
+            var pin = message[TypeDataMessage.l_pin] as? String ?? ""
+            if pin == (User.getMyPin() ?? "") {
+                pin = message[TypeDataMessage.f_pin] as? String ?? ""
+            }
+            let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
+            editorPersonalVC.hidesBottomBarWhenPushed = true
+            editorPersonalVC.unique_l_pin = pin
+            editorPersonalVC.referenceMessageId = message[TypeDataMessage.message_id] as? String ?? ""
+            editorPersonalVC.referenceChatDate = message[TypeDataMessage.chat_date] as? String ?? ""
+            navigationController?.show(editorPersonalVC, sender: nil)
+        } else {
+            var pin = message[TypeDataMessage.chat_id] as? String ?? ""
+            if pin.isEmpty {
+                pin = message[TypeDataMessage.l_pin] as? String ?? ""
+            }
+            let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
+            editorGroupVC.hidesBottomBarWhenPushed = true
+            editorGroupVC.unique_l_pin = pin
+            editorGroupVC.referenceMessageId = message[TypeDataMessage.message_id] as? String ?? ""
+            editorGroupVC.referenceChatDate = message[TypeDataMessage.chat_date] as? String ?? ""
+            navigationController?.show(editorGroupVC, sender: nil)
+        }
     }
+    
+    public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
+            switch interaction {
+            case .invokeDefaultAction:
+                let gesture = ObjectGesture()
+                gesture.message_id = URL.absoluteString
+                tapMessageText(gesture)
+                return false
+            case .presentActions:
+                UIPasteboard.general.string = URL.absoluteString
+                self.view.makeToast("Link Copied".localized(), duration: 3)
+                return false
+            case .preview:
+                return true
+            @unknown default:
+                return true
+            }
+        }
 }

+ 7 - 2
NexilisLite/NexilisLite/Source/View/Chat/MessageInfo.swift

@@ -84,8 +84,13 @@ class MessageInfo: UIViewController, UITableViewDelegate, UITableViewDataSource,
     
     func getAllLocationDesc() {
         for data in dataStatus {
-            let latitude = CLLocationDegrees(data["latitude"] as? String ?? "")!
-            let longitude = CLLocationDegrees(data["longitude"] as? String ?? "")!
+            let latitudeString = data["latitude"] as? String ?? ""
+            let longitudeString = data["longitude"] as? String ?? ""
+            if latitudeString == "" || longitudeString == "" {
+                continue
+            }
+            let latitude = CLLocationDegrees(latitudeString)!
+            let longitude = CLLocationDegrees(longitudeString)!
             guard (-90...90).contains(latitude), (-180...180).contains(longitude) else {
                 print("Invalid coordinates!")
                 continue

+ 0 - 1
NexilisLite/NexilisLite/Source/View/Contact/ContactCallViewController.swift

@@ -52,7 +52,6 @@ class ContactCallViewController: UIViewController {
     
     override func viewDidDisappear(_ animated: Bool) {
         NotificationCenter.default.removeObserver(self)
-        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshView"), object: nil, userInfo: nil)
     }
     
     override func viewDidLoad() {

+ 0 - 4
NexilisLite/NexilisLite/Source/View/Control/ChangeNamePassswordViewController.swift

@@ -20,10 +20,6 @@ public class ChangeNamePassswordViewController: UIViewController {
     public var fromSetting = false
     public var isSuccess: (() -> ())?
     
-    public override func viewWillDisappear(_ animated: Bool) {
-        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshView"), object: nil, userInfo: nil)
-    }
-    
     public override func viewDidLoad() {
         super.viewDidLoad()
         

+ 0 - 1
NexilisLite/NexilisLite/Source/View/Streaming/CreateSeminarViewController.swift

@@ -75,7 +75,6 @@ public class CreateSeminarViewController: UITableViewController {
     deinit {
         //print(#function, ">>>> TADAA1")
         NotificationCenter.default.removeObserver(self)
-        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshView"), object: nil, userInfo: nil)
     }
     
     public override func viewDidLoad() {

+ 0 - 1
NexilisLite/NexilisLite/Source/View/Streaming/QmeraCreateStreamingViewController.swift

@@ -84,7 +84,6 @@ public class QmeraCreateStreamingViewController: UITableViewController {
     deinit {
         //print(#function, ">>>> TADAA1")
         NotificationCenter.default.removeObserver(self)
-        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshView"), object: nil, userInfo: nil)
     }
     
     public override func viewDidLoad() {