Bläddra i källkod

update fix bugs for 5.0.32

alqindiirsyam 3 månader sedan
förälder
incheckning
b65f52498e

+ 2 - 8
AppBuilder/AppBuilder/SecondTabViewController.swift

@@ -1780,13 +1780,7 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                 imageView.heightAnchor.constraint(equalToConstant: 55.0)
             ])
             var leadingAnchor = imageView.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 10.0)
-            if data.profile.isEmpty && data.pin != "-999" && data.pin != "-997" {
-                if data.messageScope == MessageScope.WHISPER || data.messageScope == MessageScope.CALL || data.messageScope == MessageScope.MISSED_CALL {
-                    imageView.image = UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
-                } else {
-                    imageView.image = UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
-                }
-            } else if data.pin == "-997" {
+            if data.pin == "-997" {
                 imageView.frame = CGRect(x: 0, y: 0, width: 55.0, height: 55.0)
                 imageView.circle()
                 if let urlGif = Bundle.resourceBundle(for: Nexilis.self).url(forResource: "pb_gpt_bot", withExtension: "gif") {
@@ -1809,7 +1803,7 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                     }
                 }
             } else {
-                if !Utils.getIconDock().isEmpty && data.profile.isEmpty {
+                if !Utils.getIconDock().isEmpty && data.official == "1" {
                     let urlString = Utils.getUrlDock()!
                     if let cachedImage = ImageCache.shared.image(forKey: urlString) {
                         let imageData = cachedImage

+ 26 - 0
NexilisLite/NexilisLite/Source/APIS.swift

@@ -1601,6 +1601,32 @@ public class APIS: NSObject {
         }
     }
     
+    public static func showExpiredVersion() {
+        guard !isAlertPresented else { return }
+        isAlertPresented = true
+        let alertController = LibAlertController(
+            title: "Update Available".localized(),
+            message: "A new version is now available. Please update to the latest version to enjoy new features and important improvements.".localized(),
+            preferredStyle: .alert
+        )
+        
+        alertController.addAction(UIAlertAction(title: "OK".localized(), style: .default, handler: { _ in
+            if APIS.appNm == "OneApp" {
+                let appStoreURL = URL(string: "https://apps.apple.com/app/id6741251571")!
+                UIApplication.shared.open(appStoreURL)
+            } else {
+                let appStoreURL = URL(string: "https://apps.apple.com/app/")!
+                UIApplication.shared.open(appStoreURL)
+            }
+        }))
+        
+        if UIApplication.shared.visibleViewController?.navigationController != nil {
+            UIApplication.shared.visibleViewController?.navigationController?.present(alertController, animated: true, completion: nil)
+        } else {
+            UIApplication.shared.visibleViewController?.present(alertController, animated: true, completion: nil)
+        }
+    }
+    
     private static func openAppSettings() {
         if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
             if UIApplication.shared.canOpenURL(settingsURL) {

+ 11 - 0
NexilisLite/NexilisLite/Source/CoreMessage_TMessageBank.swift

@@ -2690,4 +2690,15 @@ public class CoreMessage_TMessageBank {
         return tMessage
     }
     
+    public static func checkVersion() -> TMessage {
+        let tMessage = NexilisLite.TMessage()
+        let me = User.getMyPin() ?? ""
+        tMessage.mPIN = me
+        tMessage.mCode = CoreMessage_TMessageCode.VERSION_CHECK
+        tMessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tMessage.mBodies[CoreMessage_TMessageKey.VERSION] = UIApplication.appVersion
+        tMessage.mBodies[CoreMessage_TMessageKey.CPAAS_VERSION] = Nexilis.cpaasVersion
+        return tMessage
+    }
+    
 }

+ 15 - 10
NexilisLite/NexilisLite/Source/Extension.swift

@@ -577,7 +577,7 @@ extension UIColor {
     }
     
     public static var mentionColor: UIColor {
-        return UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? renderColor(hex: "#f6fcae") : renderColor(hex: "#53bdea")
+        return UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? renderColor(hex: "#f6fcae") : renderColor(hex: "#25D366")
     }
     
     public static var blueBubbleColor: UIColor {
@@ -815,7 +815,7 @@ extension String {
             applyTextFormatting(to: finalText, sign: sign, attributes: attributes, isEditing: isEditing)
         }
         
-        processMentions(in: finalText, groupID: group_id, isEditing: isEditing)
+        processMentions(in: finalText, groupID: group_id, isEditing: isEditing, listMentionInTextField: listMentionInTextField)
         
         if isSearching {
             highlightSearchText(in: finalText, searchText: textSearch)
@@ -859,20 +859,25 @@ extension String {
         }
     }
 
-    private func processMentions(in text: NSMutableAttributedString, groupID: String, isEditing: Bool) {
+    private func processMentions(in text: NSMutableAttributedString, groupID: String, isEditing: Bool, listMentionInTextField: [User] = []) {
         let regex = try? NSRegularExpression(pattern: "@(\\w+)", options: [])
         let matches = regex?.matches(in: text.string, options: [], range: NSRange(location: 0, length: text.length)) ?? []
 
         for match in matches.reversed() {
             let range = match.range(at: 1)
             let username = (text.string as NSString).substring(with: range)
-            
-            if let member = Member.getMember(f_pin: username) {
-                let fullName = "\(member.firstName) \(member.lastName)".trimmingCharacters(in: .whitespaces)
-                text.replaceCharacters(in: range, with: fullName)
-                if !groupID.isEmpty, Member.getMemberInGroup(f_pin: username, group_id: groupID) != nil {
-                    let newRange = (text.string as NSString).range(of: "@\(fullName)")
-                    text.addAttribute(.foregroundColor, value: UIColor.mentionColor, range: newRange)
+            if isEditing {
+                if let _ = listMentionInTextField.firstIndex(where: { $0.fullName == username }) {
+                    text.addAttribute(.foregroundColor, value: UIColor.mentionColor, range: match.range(at: 0))
+                }
+            } else {
+                if let member = Member.getMember(f_pin: username) {
+                    let fullName = "\(member.firstName) \(member.lastName)".trimmingCharacters(in: .whitespaces)
+                    text.replaceCharacters(in: range, with: fullName)
+                    if !groupID.isEmpty, Member.getMemberInGroup(f_pin: username, group_id: groupID) != nil {
+                        let newRange = (text.string as NSString).range(of: "@\(fullName)")
+                        text.addAttribute(.foregroundColor, value: UIColor.mentionColor, range: newRange)
+                    }
                 }
             }
         }

+ 0 - 9
NexilisLite/NexilisLite/Source/IncomingThread.swift

@@ -1476,15 +1476,6 @@ class IncomingThread {
                             "f_display_name" : (CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.FIRST_NAME) + " " + CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LAST_NAME)).trimmingCharacters(in: .whitespaces)
                         ], _where: "f_pin = '\(CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.F_PIN))'")
                     }
-                    let device_id: String = SecureUserDefaults.shared.value(forKey: "device_id") ?? ""
-                    if !device_id.isEmpty, let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin FROM BUDDY where device_id='\(device_id)'"), cursorUser.next() {
-                        if User.getMyPin() != cursorUser.string(forColumnIndex: 0) {
-                            SecureUserDefaults.shared.set(cursorUser.string(forColumnIndex: 0), forKey: "me")
-                            APIS.sendPushToken(Utils.getTokenAPN(), isResend: true)
-                            Nexilis.sendVersionToBE()
-                        }
-                        cursorUser.close()
-                    }
                     if let delegate = Nexilis.shared.personInfoDelegate {
                         delegate.onUpdatePersonInfo(state: 99, message: "update_buddy")
                     }

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

@@ -18,6 +18,7 @@ import SDWebImage
 import CryptoKit
 
 public class Nexilis: NSObject {
+    public static var cpaasVersion = "5.0.32"
     public static var sAPIKey = ""
     
     public static var ADDRESS = ""
@@ -285,6 +286,14 @@ public class Nexilis: NSObject {
                         dialog.modalPresentationStyle = .overCurrentContext
                         UIApplication.shared.visibleViewController?.present(dialog, animated: true)
                     }
+                    DispatchQueue.global().async {
+                        if let vers = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.checkVersion()) {
+                            let dataVersion = vers.getBody(key: CoreMessage_TMessageKey.DATA)
+                            if dataVersion == "1" {
+                                APIS.showExpiredVersion()
+                            }
+                        }
+                    }
                 }
             } catch {
                 delegate.onFailed(error: "99:Something went wrong")

+ 5 - 3
NexilisLite/NexilisLite/Source/View/Call/QmeraVideoViewController.swift

@@ -1287,8 +1287,10 @@ class QmeraVideoViewController: UIViewController {
             }
         } else if (state == Nexilis.VIDEO_CALL_ZOOM) && self.dataPerson.count > 1 {
             DispatchQueue.main.async {
-                self.zoomView.transform   = CGAffineTransform.init(scaleX: 1.9, y: 2.0).rotated(by: (-CGFloat.pi)/2)
-                self.zoomView.contentMode = .scaleAspectFit
+                if arrayMessage[0] != arrayMessage[3] {
+                    self.zoomView.transform   = CGAffineTransform.init(scaleX: 1.9, y: 2.0).rotated(by: (CGFloat.pi)/2)
+                    self.zoomView.contentMode = .scaleAspectFit
+                }
             }
         } else if (state == Nexilis.VIDEO_CAMERA_PARAMS_CHANED){
             if(arrayMessage[3] == "0"){
@@ -1621,7 +1623,7 @@ class QmeraVideoViewController: UIViewController {
                     
                     if self.dataPerson.count == 1 {
                         self.transformZoomAfterNewUserMore2 = false
-                        self.zoomView.transform   = CGAffineTransform.init(scaleX: 1.9, y: 2.0).rotated(by: (CGFloat.pi)/2)
+//                        self.zoomView.transform   = CGAffineTransform.init(scaleX: 1.9, y: 2.0).rotated(by: (CGFloat.pi)/2)
                         
                         if !self.users[0].isConnected {
                             self.resetViewToOutgoing()

+ 2 - 8
NexilisLite/NexilisLite/Source/View/Chat/ChatWALikeVC.swift

@@ -673,13 +673,7 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
             imageView.heightAnchor.constraint(equalToConstant: 55.0)
         ])
         var leadingAnchor = imageView.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 20.0)
-        if data.profile.isEmpty && data.pin != "-999" && data.pin != "-997" {
-            if data.messageScope == MessageScope.WHISPER || data.messageScope == MessageScope.CALL || data.messageScope == MessageScope.MISSED_CALL {
-                imageView.image = UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
-            } else {
-                imageView.image = UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
-            }
-        } else if data.pin == "-997" {
+        if data.pin == "-997" {
             imageView.frame = CGRect(x: 0, y: 0, width: 55.0, height: 55.0)
             imageView.circle()
             if let urlGif = Bundle.resourceBundle(for: Nexilis.self).url(forResource: "pb_gpt_bot", withExtension: "gif") {
@@ -702,7 +696,7 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
                 }
             }
         } else {
-            if !Utils.getIconDock().isEmpty && data.profile.isEmpty {
+            if !Utils.getIconDock().isEmpty && data.official == "1" {
                 let urlString = Utils.getUrlDock()!
                 if let cachedImage = ImageCache.shared.image(forKey: urlString) {
                     let imageData = cachedImage

+ 77 - 66
NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift

@@ -122,6 +122,7 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
     var timerSearch: Timer?
     
     var tableMentionEdit = UITableView()
+    var heightTableEditMention: NSLayoutConstraint!
     
     func offset() -> CGFloat{
         guard let fontSize = Int(SecureUserDefaults.shared.value(forKey: "font_size") ?? "0") else { return 0 }
@@ -1677,7 +1678,7 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
             
             let duration: CGFloat = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat
             
-            if self.constraintViewTextField.constant != keyboardHeight - 60 {
+            if self.constraintBottomAttachment.constant != keyboardHeight || self.constraintViewTextField.constant != keyboardHeight - 60 {
 //                self.constraintViewTextField.constant = keyboardHeight - 60
                 self.constraintBottomAttachment.constant = keyboardHeight
                 if self.contraintBottomMention.constant > 0 {
@@ -1718,7 +1719,7 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
             let info:NSDictionary = notification.userInfo! as NSDictionary
             let duration: CGFloat = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat
             
-//            self.constraintViewTextField.constant = 0
+            self.constraintViewTextField.constant = 0
             self.constraintBottomAttachment.constant = 0
             self.constraintBottomContainerMultpileSelectSession.constant = 0
             if self.contraintBottomMention.constant > 0 {
@@ -1941,10 +1942,10 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
             })
             self.timerCredential[messageId] = timer
         }
-        if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintViewTextField.constant == 0 {
+        if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintBottomAttachment.constant == 0 {
             textFieldSend.text = "Send message".localized()
             textFieldSend.textColor = UIColor.lightGray
-        } else if constraintViewTextField.constant != 0 {
+        } else if constraintBottomAttachment.constant != 0 {
             textFieldSend.text = ""
             heightTextFieldSend.constant = 40
         }
@@ -2449,18 +2450,19 @@ extension EditorGroup: UIDocumentPickerDelegate, DocumentPickerDelegate, QLPrevi
             navController.navigationBar.barTintColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
             navController.navigationBar.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
             navController.navigationBar.isTranslucent = false
+            let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 16)]
+            let appearance = UINavigationBarAppearance()
+            appearance.configureWithDefaultBackground()
+            appearance.titleTextAttributes = attributes
+            appearance.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
+            navController.navigationBar.standardAppearance = appearance
+            navController.navigationBar.scrollEdgeAppearance = appearance
             let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
             UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
-            let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
-            navController.navigationBar.titleTextAttributes = textAttributes
             let leftBarButton = navigationQLPreviewDocument(title: "Cancel".localized(), style: .plain, target: self, action: #selector(cancelDocumentPreview))
             let rightBarButton = navigationQLPreviewDocument(title: "Send".localized(), style: .done, target: self, action: #selector(sendDocument))
-//            leftBarButton.tintColor = .white
-//            rightBarButton.tintColor = .white
             leftBarButton.navigation = navController
             rightBarButton.navigation = navController
-//            navController.navigationBar.barTintColor = .mainColor
-            navController.navigationBar.isTranslucent = false
             previewController.navigationItem.leftBarButtonItem = leftBarButton
             previewController.navigationItem.rightBarButtonItem = rightBarButton
             previewController.dataSource = self
@@ -2574,25 +2576,15 @@ extension EditorGroup: UITextViewDelegate, CustomTextViewPasteDelegate {
             }
             
             if continueCheckMention {
-                if let indexLastBreak = fulltextForMention.split(separator: "\n").lastIndex(where: { $0.contains("@") }) {
-                    let splitSpace = fulltextForMention.split(separator: "\n")[indexLastBreak].split(separator: " ")
-                    if let indexLastMention = splitSpace.lastIndex(where: { $0.hasPrefix("@") }),
-                       let lastChar = fulltextForMention.last,
-                       lastChar != " " && lastChar != "\n" {
-                        let textM = String(splitSpace[indexLastMention].dropFirst())
-                        if lastPositionCursorMention == textM.count + 1 {
-                            showMention(text: textM)
-                            isShowMention = true
-                        }
-                    }
-                } else if fulltextForMention.count >= 3 && self.textFieldSend.textColor != UIColor.lightGray {
-                    if let indexLastBreak = fulltextForMention.split(separator: "\n").lastIndex(where: { $0.count >= 3 }) {
-                        let splitSpace = fulltextForMention.split(separator: "\n")[indexLastBreak].split(separator: " ")
-                        if let indexLastMention = splitSpace.lastIndex(of: splitSpace.last ?? ""),
-                           let lastChar = fulltextForMention.last,
-                           lastChar != " " && lastChar != "\n" {
-                            if String(splitSpace[indexLastMention]).count >= 3 {
-                                showMention(text: String(splitSpace[indexLastMention]))
+                let lines = fulltextForMention.split(separator: "\n")
+                if let lastLineIndex = lines.lastIndex(where: { !$0.isEmpty }) {
+                    let words = lines[lastLineIndex].split(separator: " ")
+                    if let lastWordIndex = words.lastIndex(where: { !$0.isEmpty }) {
+                        let mentionText = words[lastWordIndex]
+                        let lastChar = fulltextForMention.last
+                        if lastChar != "\n" && lastChar != " " {
+                            if mentionText.starts(with: "@") || (mentionText.count >= 2 && (self.textFieldSend.textColor != UIColor.lightGray || heightTableEditMention != nil)) {
+                                showMention(text: mentionText.starts(with: "@") ? String(mentionText.dropFirst()) : String(mentionText))
                                 isShowMention = true
                             }
                         }
@@ -2757,12 +2749,6 @@ extension EditorGroup: UITextViewDelegate, CustomTextViewPasteDelegate {
         if self.contraintBottomMention.constant < 0 {
             if !isEditingMessage {
                 self.contraintBottomMention.constant = 25 + constraintBottomAttachment.constant + self.heightTextFieldSend.constant + self.viewTextfield.bounds.height
-                if self.viewTextfield.subviews.contains(self.containerLink) {
-                    self.contraintBottomMention.constant = self.contraintBottomMention.constant + 80
-                }
-                if self.viewTextfield.subviews.contains(self.containerPreviewReply) {
-                    self.contraintBottomMention.constant = self.contraintBottomMention.constant + 50
-                }
                 UIView.animate(withDuration: 0.5, animations: {
                     self.view.layoutIfNeeded()
                 })
@@ -2789,18 +2775,22 @@ extension EditorGroup: UITextViewDelegate, CustomTextViewPasteDelegate {
                     cursor.close()
                 }
                 listMentionWithText.removeAll(where: { listMentionInTextField.contains($0) })
-                if !isEditingMessage {
-                    if listMentionWithText.count > 0 {
-                        if listMentionWithText.count < 5 {
-                            self.heightTableMention.constant = CGFloat(44 * listMentionWithText.count)
-                        } else {
-                            self.heightTableMention.constant = 44 * 4
-                        }
-                        tableMention.reloadData()
+                var nowTableMention = tableMention!
+                var nowHeightTableMention = heightTableMention!
+                if isEditingMessage {
+                    nowTableMention = tableMentionEdit
+                    nowHeightTableMention = heightTableEditMention
+                }
+                if listMentionWithText.count > 0 {
+                    if listMentionWithText.count < 5 {
+                        nowHeightTableMention.constant = CGFloat(44 * listMentionWithText.count)
                     } else {
-                        self.heightTableMention.constant = 44
-                        self.hideMention()
+                        nowHeightTableMention.constant = 44 * 4
                     }
+                    nowTableMention.reloadData()
+                } else {
+                    nowHeightTableMention.constant = 44
+                    self.hideMention()
                 }
             } catch {
                 rollback.pointee = true
@@ -2817,6 +2807,10 @@ extension EditorGroup: UITextViewDelegate, CustomTextViewPasteDelegate {
             UIView.animate(withDuration: 0.5, animations: {
                 self.view.layoutIfNeeded()
             })
+        } else if self.heightTableEditMention != nil && self.heightTableEditMention.constant != 0 {
+            listMentionWithText.removeAll()
+            tableMentionEdit.reloadData()
+            self.heightTableEditMention.constant = 0
         }
     }
     
@@ -3137,7 +3131,7 @@ extension EditorGroup: UITextViewDelegate, CustomTextViewPasteDelegate {
     
     private func handleRichText(_ textView: UITextView) {
         textView.preserveCursorPosition(withChanges: { _ in
-            textView.attributedText = textView.text.richText(isEditing: true, group_id: self.dataGroup["group_id"]  as? String ?? "")
+            textView.attributedText = textView.text.richText(isEditing: true, group_id: self.dataGroup["group_id"]  as? String ?? "", listMentionInTextField: self.listMentionInTextField)
             return .preserveCursor
         })
     }
@@ -3602,6 +3596,10 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
         }
         editVC = UIViewController()
         if let view = editVC.view {
+//            let tapGesture = ObjectGesture(target: self, action: #selector(dismissEditVC))
+//            tapGesture.message_id = oldTextForTextview
+//            view.addGestureRecognizer(tapGesture)
+            
             view.backgroundColor = .clear
             let blurView = UIView()
             let blurEffect = UIBlurEffect(style: .systemUltraThinMaterialLight)
@@ -3615,7 +3613,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
             
             let tapGesture = ObjectGesture(target: self, action: #selector(dismissEditVC))
             tapGesture.message_id = oldTextForTextview
-            view.addGestureRecognizer(tapGesture)
+            blurView.addGestureRecognizer(tapGesture)
             
             editTextView = CustomTextView()
             editTextView.layer.cornerRadius = textFieldSend.maxCornerRadius()
@@ -3637,11 +3635,6 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
             editTextView.attributedText = oldTextForTextview.richText(isEditing: true, group_id: self.dataGroup["group_id"]  as? String ?? "")
             editTextView.becomeFirstResponder()
             
-//            tableMentionEdit = UITableView()
-//            view.addSubview(tableMentionEdit)
-//            tableMentionEdit.anchor(left: view.leftAnchor, right: view.rightAnchor, height: 44)
-            
-            
             buttonSendEdit.setImage(resizeImage(image: self.traitCollection.userInterfaceStyle == .dark ? UIImage(named: "Send-(White)", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(.blackDarkMode) : UIImage(named: "Send-(White)", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, targetSize: CGSize(width: 30, height: 30)).withRenderingMode(.alwaysOriginal), for: .normal)
             buttonSendEdit.circle()
             buttonSendEdit.isEnabled = true
@@ -3707,6 +3700,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                 self.isEditingMessage = false
                 self.listMentionWithText = self.tempListMentionWithText
                 self.listMentionInTextField = self.tempListMentionWithText
+                self.heightTableEditMention = nil
                 self.editVC.dismiss(animated: true)
              })
             buttonSendEdit.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .white : .mainColor
@@ -3747,6 +3741,17 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
             messageText.textColor = self.traitCollection.userInterfaceStyle == .dark ? .white : .black
             messageText.font = .systemFont(ofSize: 12 + offset())
             messageText.attributedText = oldText.richText(group_id: self.dataGroup["group_id"]  as? String ?? "")
+            
+            tableMentionEdit = UITableView()
+            tableMentionEdit.register(UITableViewCell.self, forCellReuseIdentifier: "cellEditMention")
+            tableMentionEdit.dataSource = self
+            tableMentionEdit.delegate = self
+            tableMentionEdit.contentInset = UIEdgeInsets(top: -25, left: 0, bottom: 0, right: 0)
+            tableMentionEdit.backgroundColor = .white
+            view.addSubview(tableMentionEdit)
+            tableMentionEdit.anchor(left: view.leftAnchor, bottom: editTextView.topAnchor, right: view.rightAnchor)
+            heightTableEditMention = tableMentionEdit.heightAnchor.constraint(equalToConstant: 0)
+            self.heightTableEditMention.isActive = true
         }
         editVC.modalTransitionStyle = .crossDissolve
         editVC.modalPresentationStyle = .overFullScreen
@@ -3763,6 +3768,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
             self.isEditingMessage = false
             self.listMentionWithText = self.tempListMentionWithText
             self.listMentionInTextField = self.tempListMentionWithText
+            self.heightTableEditMention = nil
             editVC.dismiss(animated: true)
         } else if self.isEditingMessage {
             let alert = LibAlertController(title: "".localized(), message: "Discard edit?".localized(), preferredStyle: .alert)
@@ -3771,6 +3777,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                 self.isEditingMessage = false
                 self.listMentionWithText = self.tempListMentionWithText
                 self.listMentionInTextField = self.tempListMentionWithText
+                self.heightTableEditMention = nil
                 self.editVC.dismiss(animated: true)
             }))
             editVC.present(alert, animated: true, completion: nil)
@@ -4385,14 +4392,14 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
     }
     
     public func numberOfSections(in tableView: UITableView) -> Int {
-        if tableView == tableMention {
+        if tableView == tableMention || tableView == tableMentionEdit {
             return 1
         }
         return dataDates.count
     }
     
     public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        if tableView == tableMention {
+        if tableView == tableMention || tableView == tableMentionEdit {
             return listMentionWithText.count
         }
         let count = dataMessages.filter({ $0["chat_date"]  as? String ?? "" == dataDates[section] }).count
@@ -4400,7 +4407,7 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
     }
     
     public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
-        if tableView == tableMention {
+        if tableView == tableMention || tableView == tableMentionEdit {
             return .none
         }
         let containerView = UIView()
@@ -4439,17 +4446,21 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
     }
     
     public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if tableView == tableMention {
+        if tableView == tableMention || tableView == tableMentionEdit {
             return 0
         }
         return 50
     }
     
     public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        if tableView == tableMention {
+        if tableView == tableMention || tableView == tableMentionEdit {
             tableView.deselectRow(at: indexPath, animated: true)
-            let fulltextForMention = textFieldSend.text.substring(from: 0, to: lastPositionCursorMention - 1)
-            let diff = textFieldSend.text.count - fulltextForMention.count
+            var nowTextField = textFieldSend!
+            if tableView == tableMentionEdit {
+                nowTextField = editTextView
+            }
+            let fulltextForMention = nowTextField.text.substring(from: 0, to: lastPositionCursorMention - 1)
+            let diff = nowTextField.text.count - fulltextForMention.count
             var indexLastMention = fulltextForMention.lastIndex(of: "@")
             if indexLastMention == nil {
                 if let spaceIndex = fulltextForMention.lastIndex(of: " ") {
@@ -4470,7 +4481,7 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                     addSpaceAfterReplacement = " "
                 }
                 
-                var text = textFieldSend.text ?? ""
+                var text = nowTextField.text ?? ""
                 let nameMention = (listMentionWithText[indexPath.row].firstName + " " + listMentionWithText[indexPath.row].lastName).trimmingCharacters(in: .whitespaces)
                 let replacementText = "@\(nameMention)"
                 
@@ -4480,12 +4491,12 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                     text.replaceSubrange(startIndex..<endIndex, with: replacementText + addSpaceAfterReplacement)
                 }
                 
-                textFieldSend.attributedText = text.richText(isEditing: true, group_id: self.dataGroup["group_id"]  as? String ?? "", listMentionInTextField: listMentionInTextField)
+                nowTextField.attributedText = text.richText(isEditing: true, group_id: self.dataGroup["group_id"]  as? String ?? "", listMentionInTextField: listMentionInTextField)
                 
-                let newPosition = textFieldSend.position(from: textFieldSend.beginningOfDocument, offset: textFieldSend.text.count - diff)
-                textFieldSend.selectedTextRange = textFieldSend.textRange(from: newPosition!, to: newPosition!)
+                let newPosition = nowTextField.position(from: nowTextField.beginningOfDocument, offset: nowTextField.text.count - diff)
+                nowTextField.selectedTextRange = nowTextField.textRange(from: newPosition!, to: newPosition!)
                 
-                listMentionInTextField.last?.ex_block = "\(textFieldSend.text.count - diff - addSpaceAfterReplacement.count)" //upperBound
+                listMentionInTextField.last?.ex_block = "\(nowTextField.text.count - diff - addSpaceAfterReplacement.count)" //upperBound
                 
                 hideMention()
             }
@@ -4570,8 +4581,8 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
     
     
     public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        if tableView == tableMention {
-            let cellMention = tableView.dequeueReusableCell(withIdentifier: "cellMention", for: indexPath as IndexPath)
+        if tableView == tableMention || tableView == tableMentionEdit {
+            let cellMention = tableView.dequeueReusableCell(withIdentifier: tableView == tableMention ? "cellMention" : "cellEditMention", for: indexPath as IndexPath)
             var content = cellMention.defaultContentConfiguration()
             content.textProperties.font = UIFont.systemFont(ofSize: 11 + offset())
             content.imageProperties.tintColor = .black

+ 13 - 12
NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -2575,7 +2575,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
             let info:NSDictionary = notification.userInfo! as NSDictionary
             let duration: CGFloat = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat
             
-//            self.constraintViewTextField.constant = 0
+            self.constraintViewTextField.constant = 0
             self.constraintBottomAttachment.constant = 0
             self.constraintBottomContainerMultpileSelectSession.constant = 0
             UIView.animate(withDuration: TimeInterval(duration), animations: {
@@ -2598,7 +2598,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
             
             let duration: CGFloat = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat
             
-            if self.constraintViewTextField.constant != keyboardHeight - 60 {
+            if self.constraintBottomAttachment.constant != keyboardHeight || self.constraintViewTextField.constant != keyboardHeight - 60 {
 //                self.constraintViewTextField.constant = keyboardHeight - 60
                 self.constraintBottomAttachment.constant = keyboardHeight
                 if isSearching {
@@ -2660,10 +2660,10 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         
         if (isContactCenter) {
             if fPinContacCenter.isEmpty && isRequestContactCenter {
-                if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintViewTextField.constant == 0 {
+                if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintBottomAttachment.constant == 0 {
                     textFieldSend.text = "Send message".localized()
                     textFieldSend.textColor = UIColor.lightGray
-                } else if constraintViewTextField.constant != 0 {
+                } else if constraintBottomAttachment.constant != 0 {
                     textFieldSend.text = ""
                 }
                 dismissKeyboard()
@@ -2792,10 +2792,10 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
             })
             self.timerCredential[messageId] = timer
         }
-        if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintViewTextField.constant == 0 {
+        if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintBottomAttachment.constant == 0 {
             textFieldSend.text = "Send message".localized()
             textFieldSend.textColor = UIColor.lightGray
-        } else if constraintViewTextField.constant != 0 {
+        } else if constraintBottomAttachment.constant != 0 {
             textFieldSend.text = ""
             heightTextFieldSend.constant = 40
         }
@@ -3766,18 +3766,19 @@ extension EditorPersonal: UIDocumentPickerDelegate, DocumentPickerDelegate, QLPr
             navController.navigationBar.barTintColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
             navController.navigationBar.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
             navController.navigationBar.isTranslucent = false
+            let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 16)]
+            let appearance = UINavigationBarAppearance()
+            appearance.configureWithDefaultBackground()
+            appearance.titleTextAttributes = attributes
+            appearance.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
+            navController.navigationBar.standardAppearance = appearance
+            navController.navigationBar.scrollEdgeAppearance = appearance
             let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
             UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
-            let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
-            navController.navigationBar.titleTextAttributes = textAttributes
             let leftBarButton = navigationQLPreviewDocument(title: "Cancel".localized(), style: .plain, target: self, action: #selector(cancelDocumentPreview))
             let rightBarButton = navigationQLPreviewDocument(title: "Send".localized(), style: .done, target: self, action: #selector(sendDocument))
-//            leftBarButton.tintColor = .white
-//            rightBarButton.tintColor = .white
             leftBarButton.navigation = navController
             rightBarButton.navigation = navController
-//            navController.navigationBar.barTintColor = .mainColor
-            navController.navigationBar.isTranslucent = false
             previewController.navigationItem.leftBarButtonItem = leftBarButton
             previewController.navigationItem.rightBarButtonItem = rightBarButton
             previewController.dataSource = self

+ 31 - 6
NexilisLite/NexilisLite/Source/View/Control/BackupRestoreView.swift

@@ -245,7 +245,23 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
             let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
             if let dirPath = paths.first {
                 let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(getFileName(option: optionBackup, fileId: fileIdBackup))
-                if !FileManager.default.fileExists(atPath: fileURL.path) {
+                if FileManager.default.fileExists(atPath: fileURL.path) {
+                    labelRestoring.text = "Restoring...".localized()
+                    restoreData(file: fileURL, dirPath: dirPath, indexPath: indexPath)
+                } else if FileEncryption.shared.isSecureExists(filename: getFileName(option: optionBackup, fileId: fileIdBackup)) {
+                    do {
+                        if var data = try FileEncryption.shared.readSecure(filename: getFileName(option: optionBackup, fileId: fileIdBackup)) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                            if dataDecrypt != nil {
+                                data = dataDecrypt!
+                            }
+                            try data.write(to: fileURL)
+                            restoreData(file: fileURL, dirPath: dirPath, indexPath: indexPath)
+                        }
+                    } catch {
+                        
+                    }
+                } else {
                     Download().startHTTP(forKey: getFileName(option: optionBackup, fileId: fileIdBackup), isImage: false) { (name, progress) in
                         DispatchQueue.main.async { [self] in
                             guard progress == 100 else {
@@ -253,12 +269,22 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
                                 return
                             }
                             labelRestoring.text = "Restoring...".localized()
-                            restoreData(file: fileURL, dirPath: dirPath, indexPath: indexPath)
+                            if FileEncryption.shared.isSecureExists(filename: getFileName(option: optionBackup, fileId: fileIdBackup)) {
+                                do {
+                                    if var data = try FileEncryption.shared.readSecure(filename: getFileName(option: optionBackup, fileId: fileIdBackup)) {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                                        if dataDecrypt != nil {
+                                            data = dataDecrypt!
+                                        }
+                                        try data.write(to: fileURL)
+                                        restoreData(file: fileURL, dirPath: dirPath, indexPath: indexPath)
+                                    }
+                                } catch {
+                                    
+                                }
+                            }
                         }
                     }
-                } else {
-                    labelRestoring.text = "Restoring...".localized()
-                    restoreData(file: fileURL, dirPath: dirPath, indexPath: indexPath)
                 }
             }
         }
@@ -581,7 +607,6 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
         destinationURL.appendPathComponent("unzipItem\(Date().currentTimeMillis())")
         do {
             try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)
-//            try Zip.unzipFile(file, destination: destinationURL, overwrite: true, password: nil)
             try fileManager.unzipItem(at: file, to: destinationURL)
             
             let files = try FileManager.default.contentsOfDirectory(atPath: destinationURL.path)

+ 3 - 9
NexilisLite/NexilisLite/Source/View/Control/ContactChatViewController.swift

@@ -208,7 +208,7 @@ class ContactChatViewController: UITableViewController {
         tableView.tableFooterView = UIView()
         
         pullBuddy()
-        getData()
+//        getData()
     }
     
     override func viewWillAppear(_ animated: Bool) {
@@ -1181,13 +1181,7 @@ extension ContactChatViewController {
                     imageView.heightAnchor.constraint(equalToConstant: 55.0)
                 ])
                 var leadingAnchor = imageView.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 10.0)
-                if data.profile.isEmpty && data.pin != "-999" && data.pin != "-997" {
-                    if data.messageScope == MessageScope.WHISPER || data.messageScope == MessageScope.CALL || data.messageScope == MessageScope.MISSED_CALL {
-                        imageView.image = UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
-                    } else {
-                        imageView.image = UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
-                    }
-                } else if data.pin == "-997" {
+                if data.pin == "-997" {
                     imageView.frame = CGRect(x: 0, y: 0, width: 55.0, height: 55.0)
                     imageView.circle()
                     if let urlGif = Bundle.resourceBundle(for: Nexilis.self).url(forResource: "pb_gpt_bot", withExtension: "gif") {
@@ -1210,7 +1204,7 @@ extension ContactChatViewController {
                         }
                     }
                 } else {
-                    if !Utils.getIconDock().isEmpty && data.profile.isEmpty {
+                    if !Utils.getIconDock().isEmpty && data.official == "1" {
                         let urlString = Utils.getUrlDock()!
                         if let cachedImage = ImageCache.shared.image(forKey: urlString) {
                             let imageData = cachedImage