alqindiirsyam 1 år sedan
förälder
incheckning
8377a4cd0e

+ 2 - 2
appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift

@@ -544,7 +544,7 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
     
     public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
         let headerView = UIView()
-        if (section == 2 && Item.menus["Config"]!.count > 0) || section == 3 {
+        if (section == 2 && Item.menus["Config"]!.count > 0) || section == 3 || (section == 1 && Item.menus["Config"]!.count > 0) {
             headerView.backgroundColor = .clear
             
             let lineView = UIView()
@@ -563,7 +563,7 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
     }
     
     public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 2 || section == 3 {
+        if section == 2 || section == 3 || section == 1 {
             return 6
         }
         return 1

+ 1 - 0
appbuilder-ios/AppBuilder/AppBuilder/SecondTabViewController.swift

@@ -175,6 +175,7 @@ class SecondTabViewController: UIViewController, UIScrollViewDelegate, UIGesture
     
     @objc func startConversation(){
         let navigationController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactChatNav") as! UINavigationController
+        navigationController.view.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .black : .white
         Utils.addBackground(view: navigationController.view)
         navigationController.modalPresentationStyle = .fullScreen
         navigationController.navigationBar.tintColor = .white

+ 2 - 0
appbuilder-ios/AppBuilder/AppBuilder/ViewController.swift

@@ -662,6 +662,8 @@ class ViewController: UITabBarController, UITabBarControllerDelegate, SettingMAB
     
     func showWelocomeView() {
         if let viewWelcome = welcomeVC.view {
+            viewWelcome.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .black : .white
+            Utils.addBackground(view: viewWelcome)
             let bgImage = UIImageView()
             viewWelcome.addSubview(bgImage)
             bgImage.anchor(top: viewWelcome.topAnchor, left: viewWelcome.leftAnchor, bottom: viewWelcome.bottomAnchor, right: viewWelcome.rightAnchor)

+ 1 - 2
appbuilder-ios/NexilisLite/NexilisLite/Resource/Palio.storyboard

@@ -1734,7 +1734,7 @@
                     <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="8aL-ZR-t6m">
                         <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                         <prototypes>
                             <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="reuseIdentifierChat" id="zd4-bn-4R1">
                                 <rect key="frame" x="0.0" y="50" width="414" height="43.5"/>
@@ -2476,7 +2476,6 @@
                                 <subviews>
                                     <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="Zwh-BN-IXY" customClass="CustomTextView" customModule="NexilisLite" customModuleProvider="target">
                                         <rect key="frame" x="65" y="0.0" width="329" height="40"/>
-                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                         <constraints>
                                             <constraint firstAttribute="height" constant="40" id="BM5-gS-VIN"/>
                                         </constraints>

+ 3 - 2
appbuilder-ios/NexilisLite/NexilisLite/Resource/id.lproj/Localizable.strings

@@ -12,7 +12,7 @@
 "Search chats & messages" = "Cari obrolan & pesan";
 "There are no conversations" = "Belum ada obrolan";
 "Start Recording" = "Mulai merekam";
-"Say something, I'm listening!" = "Katakan sesuatu, saya dengar!";
+"Say something, I'm listening!" = "Katakan sesuatu, aku akan dengarkan!";
 "Stop Recording" = "Hentikan perekaman";
 "Search" = "Cari";
 "View Replies" = "Lihat Balasan";
@@ -117,7 +117,7 @@
 "Unblock" = "Buka Blokir";
 "You blocked this user" = "Kamu memblokir pengguna ini";
 "You have been blocked by this user" = "Kamu telah diblokir oleh pengguna ini";
-"For Me" = "untuk saya";
+"For Me" = "untukku";
 "For Everyone" = "untuk semua orang";
 "You were deleted this message" = "Kamu telah menghapus pesan ini";
 "This message was deleted" = "Pesan ini telah dihapus";
@@ -375,4 +375,5 @@
 "Failed" = "Gagal";
 "Failed, unknown user" = "Gagal, pengguna tidak dikenal";
 "Failed, blocked user" = "Gagal, pengguna telah diblokir";
+"Feature disabled.." = "Fitur dinonaktifkan..";
 

+ 1 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/APIS.swift

@@ -759,6 +759,7 @@ public class APIS: NSObject {
 
 extension UINavigationController {
     func defaultStyle() {
+        self.view.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .black : .white
         self.modalPresentationStyle = .fullScreen
         self.navigationBar.tintColor = .white
         self.navigationBar.barTintColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor

+ 168 - 34
appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -516,34 +516,161 @@ public class Nexilis: NSObject {
     
     private static func getFeatureAccess() {
         DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
-            Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "get_feature_access")!) { data, response, error in
+            Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "get_feature_access_new")!) { data, response, error in
                 if let data = data, let responseString = String(data: data, encoding: .utf8) {
-                    Utils.setFeatureAccess(value: responseString)
                     if let jsonArray = try? JSONSerialization.jsonObject(with: responseString.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
                         do {
-                            let umr = jsonArray[0]["upload_max_retry"] as? Int
-                            let umt = jsonArray[0]["upload_max_time"] as? Int64
-                            let checkEmu = jsonArray[0]["check_emulator"] as? String
-                            let checkRooted = jsonArray[0]["check_rooted_device"] as? String
-                            let checkScreenCapt = jsonArray[0]["check_screen_capture"] as? String
-                            let checkDebug = jsonArray[0]["check_usb_debugging"] as? String
-                            if umr != nil {
-                                Utils.setMaxRetryUpload(value: "\(umr ?? 0)")
-                            }
-                            if umt != nil {
-                                Utils.setMaxRetryTimeUpload(value: "\(umt ?? 0)")
-                            }
-                            if checkEmu != nil {
-                                Utils.setCheckEmulator(b: checkEmu == "1")
-                            }
-                            if checkRooted != nil {
-                                Utils.setCheckRooted(b: checkRooted == "1")
-                            }
-                            if checkScreenCapt != nil {
-                                Utils.setCheckScreenCapture(b: checkScreenCapt == "1")
+                            var jsonFA: [String: Any] = [:]
+                            for jsonData in jsonArray {
+                                if jsonData["admin_features"]! != nil {
+                                    jsonFA["admin_features"] = jsonData["admin_features"]!
+                                }
+                                if jsonData["audio_call"]! != nil {
+                                    jsonFA["audio_call"] = jsonData["audio_call"]!
+                                }
+                                if jsonData["audio_call_add"]! != nil {
+                                    jsonFA["audio_call_add"] = jsonData["audio_call_add"]!
+                                }
+                                if jsonData["backup_restore"]! != nil {
+                                    jsonFA["backup_restore"] = jsonData["backup_restore"]!
+                                }
+                                if jsonData["backup_restore"]! != nil {
+                                    jsonFA["backup_restore"] = jsonData["backup_restore"]!
+                                }
+                                if jsonData["battery_optimization"]! != nil {
+                                    jsonFA["battery_optimization"] = jsonData["battery_optimization"]!
+                                }
+                                if jsonData["call_center"]! != nil {
+                                    jsonFA["call_center"] = jsonData["call_center"]!
+                                }
+                                if jsonData["email"]! != nil {
+                                    jsonFA["email"] = jsonData["email"]!
+                                }
+                                if jsonData["live_streaming"]! != nil {
+                                    jsonFA["live_streaming"] = jsonData["live_streaming"]!
+                                }
+                                if jsonData["live_streaming_view"]! != nil {
+                                    jsonFA["live_streaming_view"] = jsonData["live_streaming_view"]!
+                                }
+                                if jsonData["logout"]! != nil {
+                                    jsonFA["logout"] = jsonData["logout"]!
+                                }
+                                if jsonData["multiple_login"]! != nil {
+                                    jsonFA["multiple_login"] = jsonData["multiple_login"]!
+                                }
+                                if jsonData["online_seminar"]! != nil {
+                                    jsonFA["online_seminar"] = jsonData["online_seminar"]!
+                                }
+                                if jsonData["sms"]! != nil {
+                                    jsonFA["sms"] = jsonData["sms"]!
+                                }
+                                if jsonData["video_call"]! != nil {
+                                    jsonFA["video_call"] = jsonData["video_call"]!
+                                }
+                                if jsonData["video_call_add"]! != nil {
+                                    jsonFA["video_call_add"] = jsonData["video_call_add"]!
+                                }
+                                if jsonData["web"]! != nil {
+                                    jsonFA["web"] = jsonData["web"]!
+                                }
+                                if jsonData["change_profile_name"]! != nil {
+                                    jsonFA["change_profile_name"] = jsonData["change_profile_name"]!
+                                }
+                                if jsonData["change_profile_photo"]! != nil {
+                                    jsonFA["change_profile_photo"] = jsonData["change_profile_photo"]!
+                                }
+                                if jsonData["behaviour_analysis"]! != nil {
+                                    jsonFA["behaviour_analysis"] = jsonData["behaviour_analysis"]!
+                                }
+                                if jsonData["instant_messaging"]! != nil {
+                                    jsonFA["instant_messaging"] = jsonData["instant_messaging"]!
+                                }
+                                if jsonData["battery_optimization_force"]! != nil {
+                                    jsonFA["battery_optimization_force"] = jsonData["battery_optimization_force"]!
+                                }
+                                if jsonData["upload_max_retry"]! != nil {
+                                    let umr = jsonData["upload_max_retry"] as? Int
+                                    Utils.setMaxRetryUpload(value: "\(umr ?? 0)")
+                                    jsonFA["upload_max_retry"] = jsonData["upload_max_retry"]!
+                                }
+                                if jsonData["upload_max_time"]! != nil {
+                                    let umt = jsonData["upload_max_time"] as? Int64
+                                    Utils.setMaxRetryTimeUpload(value: "\(umt ?? 0)")
+                                    jsonFA["upload_max_time"] = jsonData["upload_max_time"]!
+                                }
+                                if jsonData["check_rooted_device"]! != nil {
+                                    let checkRooted = jsonData["check_rooted_device"] as? String
+                                    Utils.setCheckRooted(b: checkRooted == "1")
+                                    jsonFA["check_rooted_device"] = jsonData["check_rooted_device"]!
+                                }
+                                if jsonData["check_emulator"]! != nil {
+                                    let checkEmu = jsonData["check_emulator"] as? String
+                                    Utils.setCheckEmulator(b: checkEmu == "1")
+                                    jsonFA["check_emulator"] = jsonData["check_emulator"]!
+                                }
+                                if jsonData["check_malware"]! != nil {
+                                    jsonFA["check_malware"] = jsonData["check_malware"]!
+                                }
+                                if jsonData["check_usb_debugging"]! != nil {
+                                    let checkDebug = jsonData["check_usb_debugging"] as? String
+                                    Utils.setCheckDebugger(b: checkDebug == "1")
+                                    jsonFA["check_usb_debugging"] = jsonData["check_usb_debugging"]!
+                                }
+                                if jsonData["check_screen_capture"]! != nil {
+                                    let checkScreenCapt = jsonData["check_screen_capture"] as? String
+                                    Utils.setCheckScreenCapture(b: checkScreenCapt == "1")
+                                    jsonFA["check_screen_capture"] = jsonData["check_screen_capture"]!
+                                }
+                                if jsonData["check_cloned_app"]! != nil {
+                                    jsonFA["check_cloned_app"] = jsonData["check_cloned_app"]!
+                                }
+                                if jsonData["check_call_forwarding"]! != nil {
+                                    jsonFA["check_call_forwarding"] = jsonData["check_call_forwarding"]!
+                                }
+                                if jsonData["show_security_shield_dialog"]! != nil {
+                                    jsonFA["show_security_shield_dialog"] = jsonData["show_security_shield_dialog"]!
+                                }
+                                if jsonData["logging_state"]! != nil {
+                                    jsonFA["logging_state"] = jsonData["logging_state"]!
+                                }
+                                if jsonData["smartbot"]! != nil {
+                                    jsonFA["smartbot"] = jsonData["smartbot"]!
+                                }
+                                if jsonData["message_counter"]! != nil {
+                                    jsonFA["message_counter"] = jsonData["message_counter"]!
+                                }
+                                if jsonData["secure_folder"]! != nil {
+                                    jsonFA["secure_folder"] = jsonData["secure_folder"]!
+                                }
+                                if jsonData["check_sim_swap"]! != nil {
+                                    jsonFA["check_sim_swap"] = jsonData["check_sim_swap"]!
+                                }
+                                if jsonData["check_screen_casting"]! != nil {
+                                    jsonFA["check_screen_casting"] = jsonData["check_screen_casting"]!
+                                }
+                                if jsonData["check_keylogger"]! != nil {
+                                    jsonFA["check_keylogger"] = jsonData["check_keylogger"]!
+                                }
+                                if jsonData["check_sideloaded_app"]! != nil {
+                                    jsonFA["check_sideloaded_app"] = jsonData["check_sideloaded_app"]!
+                                }
+                                if jsonData["check_outdated_os"]! != nil {
+                                    jsonFA["check_outdated_os"] = jsonData["check_outdated_os"]!
+                                }
+                                if jsonData["minimum_android_version"]! != nil {
+                                    jsonFA["minimum_android_version"] = jsonData["minimum_android_version"]!
+                                }
+                                if jsonData["application_backup_detection"]! != nil {
+                                    jsonFA["application_backup_detection"] = jsonData["application_backup_detection"]!
+                                }
+                                if jsonData["ls_broadcast_type"]! != nil {
+                                    jsonFA["ls_broadcast_type"] = jsonData["ls_broadcast_type"]!
+                                }
                             }
-                            if checkDebug != nil {
-                                Utils.setCheckDebugger(b: checkDebug == "1")
+                            if let convertJsonFA = try? JSONSerialization.data(withJSONObject: jsonFA, options: .prettyPrinted) {
+                                if let jsonFAString = String(data: convertJsonFA, encoding: .utf8) {
+                                    Utils.setFeatureAccess(value: jsonFAString)
+                                }
                             }
                         } catch {
                         }
@@ -574,14 +701,21 @@ public class Nexilis: NSObject {
     
     public static func checkingAccess(key: String) -> Bool {
         let dataAccess = Utils.getFeatureAccess()
-        if let jsonArray = try? JSONSerialization.jsonObject(with: dataAccess.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
-            let backupRest = jsonArray[0]["backup_restore"] as? Int
-            let logout = jsonArray[0]["logout"] as? Int
-            if backupRest != nil && backupRest == 1 {
+        if dataAccess.isEmpty {
+            if key == "battery_optimization_force" || key == "backup_restore" || key == "check_sim_swap" || key == "admin_features" {
+                return false
+            } else {
                 return true
             }
-            if logout != nil && logout == 1 {
-                return true
+        } else if let jsonArray = try? JSONSerialization.jsonObject(with: dataAccess.data(using: String.Encoding.utf8)!, options: []) as? [String: Any] {
+            if jsonArray[key] != nil {
+                return jsonArray[key] as! String == "1"
+            } else {
+                if key == "sms" || key == "email" || key == "whatsapp" || key == "battery_optimization_force" || key == "backup_restore" || key == "check_sim_swap" || key == "admin_features" {
+                    return false
+                } else {
+                    return true
+                }
             }
         }
         return false
@@ -864,12 +998,12 @@ public class Nexilis: NSObject {
             }
 
             let dataEncode = String(data: data, encoding: .utf8)!
-//            print("dataEncode \(dataEncode.trimmingCharacters(in: .whitespacesAndNewlines))")
+            print("dataEncode \(dataEncode.trimmingCharacters(in: .whitespacesAndNewlines))")
 //            //print("decrypt \(Utils.decrypt(str: "4=sm<wmpm1ir==>wtxxl"))")
             if !dataEncode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                 let dataDecodeBase64 = String(data: Data(base64Encoded: dataEncode)!, encoding: .utf8)!
                 let dataRealDecode = Utils.decrypt(str: dataDecodeBase64)
-//                print("dataRealDecode \(dataRealDecode)")
+                print("dataRealDecode \(dataRealDecode)")
                 do {
                     if let jsonData = dataRealDecode.data(using: .utf8), let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
                         var newDomain = jsonObject["domain"] as! String
@@ -1022,9 +1156,9 @@ public class Nexilis: NSObject {
         return result
     }
 
-    public static func setSpeaker(_ isEnabled: Bool) {
+    public static func setSpeaker(_ isEnabled: Bool, isVideo: Bool = false) {
         do {
-            API.adjustVolume(fValue: isEnabled ? 10.0: 3.0)
+            API.adjustVolume(fValue: isEnabled ? 10.0: isVideo ? 0.0 : 3.0)
         } catch {
         }
     }

+ 10 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/Utils.swift

@@ -245,6 +245,13 @@ public final class Utils {
     static func getFeatureAccess() -> String {
         UserDefaults.standard.string(forKey: "pb_feature_access") ?? ""
     }
+    static func setChatbotGreetings(value: String) {
+        UserDefaults.standard.set(value, forKey: "chatbot_greetings")
+    }
+
+    static func getChatbotGreetings() -> String {
+        UserDefaults.standard.string(forKey: "chatbot_greetings") ?? "Welcome..."
+    }
     
     
     public static func sGetCurrentDateTime(sFormat: String!) -> String! {
@@ -555,6 +562,9 @@ public final class Utils {
                     if json[CoreMessage_TMessageKey.KEY] as! String == "enable_valid_trans" {
                         Utils.setValidTrans(value: json[CoreMessage_TMessageKey.VALUE] as! String)
                     }
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "chatbot_greetings" {
+                        Utils.setValidTrans(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    }
                 }
             } catch {
             }

+ 1 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraVideoViewController.swift

@@ -903,7 +903,7 @@ class QmeraVideoViewController: UIViewController {
             }
             self.isSpeaker = isSpeaker
         }
-        Nexilis.setSpeaker(isSpeaker)
+        Nexilis.setSpeaker(isSpeaker, isVideo: true)
     }
     
     @objc func didTapSpeakerButton(sender: AnyObject){

+ 113 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift

@@ -139,6 +139,8 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
         loadData()
         setRightButtonItem()
         
+        addGreeting()
+        
         let center: NotificationCenter = NotificationCenter.default
         center.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
         center.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
@@ -149,6 +151,117 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
         
     }
     
+    private func addGreeting() {
+        guard let me = UserDefaults.standard.string(forKey: "me") else {
+            return
+        }
+        var user_id:String? = ""
+        let message_id = me + CoreMessage_TMessageUtil.getTID()
+        let server_date = String(Date().currentTimeMillis())
+        
+        var gptRow : [String: String] = [:]
+        gptRow["role"] = "assistant"
+        gptRow["content"] = Utils.getChatbotGreetings()
+        chatGPTMessages.append(gptRow)
+        
+        Database.shared.database?.inTransaction({ (fmdb, rollback) in
+            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
+                user_id = cursor.string(forColumnIndex: 0)
+                cursor.close()
+            }
+        })
+        Database.shared.database?.inTransaction({ (fmdb, rollback) in
+            do {
+                _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                    "message_id" : message_id ,
+                    "f_pin" : "-997",
+                    "f_display_name" : "GPT SmartBot",
+                    "l_pin" : me,
+                    "l_user_id" : String(user_id!),
+                    "message_scope_id" : "31",
+                    "server_date" : server_date,
+                    "status" : "3",
+                    "message_text" : gptRow["content"],
+                    "audio_id" : "",
+                    "video_id" : "",
+                    "image_id" : "",
+                    "file_id" : "",
+                    "thumb_id" : "",
+                    "opposite_pin" : "",
+                    "format" : "",
+                    "blog_id" : "",
+                    "read_receipts" : "0",
+                    "chat_id" : "",
+                    "account_type" : "1",
+                    "credential" :"",
+                    "reff_id" : "",
+                    "message_large_text" : "",
+                    "attachment_flag" : "0",
+                    "local_timestamp" : String(Date().currentTimeMillis())
+                ], replace: true)
+            } catch {
+                rollback.pointee = true
+                //print(error)
+            }
+        })
+        let pin = "-997"
+        var counter : Int? = nil
+        Database.shared.database?.inTransaction({ (fmdb, rollback) in
+            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
+                counter = Int(cursor.int(forColumnIndex: 0))
+                counter! += 0
+                cursor.close()
+                //print("select db message summary")
+            }
+        })
+        if counter == nil {
+            counter = 0
+            //print("set counter message summary")
+        }
+        Database.shared.database?.inTransaction({ (fmdb, rollback) in
+            do {
+                _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
+                    "l_pin" : pin,
+                    "message_id" : message_id,
+                    "counter" : counter!
+                ], replace: true)
+            } catch {
+                rollback.pointee = true
+                //print(error)
+            }
+        })
+        var row: [String: Any?] = [:]
+        row["message_id"] = message_id
+        row["f_pin"] = "-997"
+        row["l_pin"] = me
+        row["message_scope_id"] = "31"
+        row["server_date"] = server_date
+        row["status"] = "3"
+        row["message_text"] = gptRow["content"]
+        row["audio_id"] = ""
+        row["video_id"] = ""
+        row["image_id"] = ""
+        row["thumb_id"] = ""
+        row["read_receipts"] = "0"
+        row["credential"] = ""
+        row["file_id"] = ""
+        row["reff_id"] = ""
+        row["progress"] = 100.0
+        row["attachment_flag"] = "0"
+        row["lock"] = ""
+        row["is_stared"] = "0"
+        row["isSelected"] = false
+        if !self.dataDates.contains("Today".localized()) {
+            self.dataDates.append("Today".localized())
+            self.tableChatView.insertSections(IndexSet(integer: self.dataDates.count - 1), with: .none)
+        }
+        row["chat_date"] = "Today".localized()
+        row["blog_id"] = "0"
+        self.dataMessages.append(row)
+        self.tableChatView.insertRows(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)
+        self.tableChatView.scrollToBottom()
+    }
+    
     @objc func sendTapped() {
         sendChat(message_text: textFieldSend.text!, viewController: self)
     }

+ 19 - 7
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift

@@ -922,13 +922,21 @@ public class EditorGroup: UIViewController {
                     } else {
                         row["thumb_id"] = ""
                     }
-                    row["read_receipts"] = 0
-                    row["chat_id"] = ""
+                    if (chatData.keys.contains(CoreMessage_TMessageKey.CHAT_ID)) {
+                        row["chat_id"] = chatData[CoreMessage_TMessageKey.CHAT_ID]
+                    } else {
+                        row["chat_id"] = ""
+                    }
                     if (chatData.keys.contains(CoreMessage_TMessageKey.FILE_ID)) {
                         row["file_id"] = chatData[CoreMessage_TMessageKey.FILE_ID]
                     } else {
                         row["file_id"] = ""
                     }
+                    if (chatData.keys.contains(CoreMessage_TMessageKey.READ_RECEIPTS)) {
+                        row["read_receipts"] = chatData[CoreMessage_TMessageKey.READ_RECEIPTS]
+                    } else {
+                        row["read_receipts"] = ""
+                    }
                     if (chatData.keys.contains(CoreMessage_TMessageKey.CREDENTIAL)) {
                         row["credential"] = chatData[CoreMessage_TMessageKey.CREDENTIAL]
                     } else {
@@ -1585,16 +1593,20 @@ public class EditorGroup: UIViewController {
             read_receipts = "8"
         }
         if message_text.contains("@") && listMentionInTextField.count > 0 {
+            var diff: Int = 0
             for i in 0..<listMentionInTextField.count {
                 let nameWithMention = ("@" + listMentionInTextField[i].firstName + " " + listMentionInTextField[i].lastName).trimmingCharacters(in: .whitespaces)
-                let upperBound = Int(listMentionInTextField[i].ex_block!)! - 1
-                let lowerBound = Int(listMentionInTextField[i].ex_block!)! - nameWithMention.count
+                let upperBound = Int(listMentionInTextField[i].ex_block!)! + diff - 1
+                let lowerBound = Int(listMentionInTextField[i].ex_block!)! + diff - nameWithMention.count
                 var afterMention = ""
                 if upperBound + 1 != message_text.count && message_text.substring(from: upperBound + 1, to: upperBound + 1) != "\n" && message_text.substring(from: upperBound + 1, to: upperBound + 1) != " " && message_text.substring(from: upperBound + 1, to: upperBound + 1) != "" {
                     afterMention = " "
                 }
-                let stringRange = message_text.index(message_text.startIndex, offsetBy: lowerBound)..<message_text.index(message_text.startIndex, offsetBy: upperBound + 1)
-                message_text = message_text.replacingOccurrences(of: nameWithMention, with: "@\(listMentionInTextField[i].pin)" + afterMention, range: stringRange)
+                let startIndex = message_text.index(message_text.startIndex, offsetBy: lowerBound)
+                let endIndex = message_text.index(message_text.startIndex, offsetBy: upperBound + 1)
+                let range = startIndex..<endIndex
+                message_text = message_text.replacingOccurrences(of: nameWithMention, with: "@\(listMentionInTextField[i].pin)" + afterMention, range: range)
+                diff += "@\(listMentionInTextField[i].pin)".count - nameWithMention.count
             }
         }
         let message = CoreMessage_TMessageBank.sendMessage(l_pin: dataGroup["group_id"] as! String, message_scope_id: message_scope_id, status: status, message_text: message_text, credential: credential, attachment_flag: attachment_flag, ex_blog_id: ex_blog_id, message_large_text: message_large_text, ex_format: ex_format, image_id: image_id, audio_id: audio_id, video_id: video_id, file_id: file_id, thumb_id: thumb_id, reff_id: reff_id, read_receipts: read_receipts, chat_id: dataTopic["chat_id"] as! String, is_call_center: is_call_center, call_center_id: call_center_id, opposite_pin: opposite_pin)
@@ -2113,7 +2125,7 @@ extension EditorGroup: UITextViewDelegate {
                     }
                 }
             }
-            listMentionInTextField.removeAll(where: { listHaveToRemoved.contains($0) })
+//            listMentionInTextField.removeAll(where: { listHaveToRemoved.contains($0) })
             if continueCheckMention {
                 let splitBreak = fulltextForMention.components(separatedBy: "\n")
                 let indexLastBreak = splitBreak.lastIndex(where: { $0.contains("@") })

+ 13 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -941,6 +941,8 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                 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 FROM MESSAGE where message_scope_id = '5' AND broadcast_flag = 0 AND is_call_center = 1 AND call_center_id = '\(complaintId)' order by server_date asc"
             }
             if isRequestContactCenter && !isDirectCC {
+                viewButton.isHidden = true
+                viewTextfield.isHidden = true
                 var row: [String: Any?] = [:]
                 row["f_pin"] = nil
                 row["message_id"] = ""
@@ -1344,6 +1346,9 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
                             self.dismiss(animated: true, completion: nil)
                         })
+                    } else {
+                        viewButton.isHidden = false
+                        viewTextfield.isHidden = false
                     }
                 } else if (dataMessage.getCode() == CoreMessage_TMessageCode.INVITE_END_CONTACT_CENTER || dataMessage.getCode() == CoreMessage_TMessageCode.END_CALL_CENTER || dataMessage.getCode() == CoreMessage_TMessageCode.INVITE_EXIT_CONTACT_CENTER) && !fromVCAC {
                     let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
@@ -2077,6 +2082,10 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
     
     @objc func audioVideoCall(sender: UIBarButtonItem) {
         if sender.tag == 0 {
+            if !Nexilis.checkingAccess(key: "audio_call") {
+                showToast(message: "Feature disabled..".localized(), font: UIFont.systemFont(ofSize: 12), controller: self)
+                return
+            }
             let goAudioCall = Nexilis.checkMicPermission()
             if !goAudioCall{
                 let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow microphone permission in your settings".localized(), preferredStyle: .alert)
@@ -2103,6 +2112,10 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                 present(controller, animated: true, completion: nil)
             }
         } else {
+            if !Nexilis.checkingAccess(key: "video_call") {
+                showToast(message: "Feature disabled..".localized(), font: UIFont.systemFont(ofSize: 12), controller: self)
+                return
+            }
             let goAudioCall = Nexilis.checkMicPermission()
             let goVideoCall = Nexilis.checkCameraPermission()
             if goVideoCall == 0 {

+ 12 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Contact/ContactCallViewController.swift

@@ -33,6 +33,10 @@ class ContactCallViewController: UIViewController {
     
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
         if (segue.identifier == "videoVC") {
+            if !Nexilis.checkingAccess(key: "video_call") {
+                showToast(message: "Feature disabled..".localized(), font: UIFont.systemFont(ofSize: 12), controller: self)
+                return
+            }
             if !CheckConnection.isConnectedToNetwork() {
                 let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
                 imageView.tintColor = .white
@@ -311,6 +315,10 @@ extension ContactCallViewController: UITableViewDataSource {
     }
     
     @objc func call(sender: Any) {
+        if !Nexilis.checkingAccess(key: "audio_call") {
+            showToast(message: "Feature disabled..".localized(), font: UIFont.systemFont(ofSize: 12), controller: self)
+            return
+        }
         let index = sender as! UIButton
         if let pin = dataPerson[index.tag]["f_pin"] {
             if !CheckConnection.isConnectedToNetwork() {
@@ -329,6 +337,10 @@ extension ContactCallViewController: UITableViewDataSource {
     }
     
     @objc func videoCall(sender: Any) {
+        if !Nexilis.checkingAccess(key: "video_call") {
+            showToast(message: "Feature disabled..".localized(), font: UIFont.systemFont(ofSize: 12), controller: self)
+            return
+        }
         let index = sender as! UIButton
         if !CheckConnection.isConnectedToNetwork() {
             let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))

+ 0 - 2
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/HistoryCCViewController.swift

@@ -21,8 +21,6 @@ public class HistoryCCViewController: UITableViewController, QLPreviewController
         super.viewDidLoad()
         self.title = "Call Center History".localized()
         
-        self.view.backgroundColor = .white
-        
         if fromAPI {
             let imageButton = UIImageView(frame: CGRect(x: -16, y: 0, width: 20, height: 44))
             imageButton.image = UIImage(systemName: "chevron.backward", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular, scale: .default))?.withTintColor(.white)

+ 100 - 83
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ProfileViewController.swift

@@ -67,6 +67,8 @@ public class ProfileViewController: UITableViewController {
     var publicBanner = FloatingNotificationBanner()
     
     var fromAPI = false
+    var timerSwitchPA = Timer()
+    var timerSwitchAC = Timer()
     
     private func reload() {
         if let user = self.user {
@@ -160,15 +162,15 @@ public class ProfileViewController: UITableViewController {
     }
     
     public override func viewWillAppear(_ animated: Bool) {
-        if navigationController?.navigationBar.backgroundColor != .clear || self.traitCollection.userInterfaceStyle == .dark {
+//        if navigationController?.navigationBar.backgroundColor != .clear || self.traitCollection.userInterfaceStyle == .dark {
             navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
             navigationController?.navigationBar.tintColor = .white
             navigationItem.rightBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .normal)
-        } else {
-            navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black]
-            navigationController?.navigationBar.tintColor = .black
-            navigationItem.rightBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: .normal)
-        }
+//        } else {
+//            navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black]
+//            navigationController?.navigationBar.tintColor = .black
+//            navigationItem.rightBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: .normal)
+//        }
         if fromListFriend {
             if let me = UserDefaults.standard.string(forKey: "me"), me == self.data || self.flag == Flag.me {
                 Database.shared.database?.inTransaction({ fmdb, rollback in
@@ -204,14 +206,15 @@ public class ProfileViewController: UITableViewController {
         profile.isUserInteractionEnabled = true
         profile.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(profileTapped)))
         
+        let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16.0), NSAttributedString.Key.foregroundColor: UIColor.white]
+        let navBarAppearance = UINavigationBarAppearance()
+        navBarAppearance.configureWithOpaqueBackground()
+        navBarAppearance.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : UIColor.mainColor
+        navBarAppearance.titleTextAttributes = attributes
+        navigationController?.navigationBar.standardAppearance = navBarAppearance
+        navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
+        
         if fromAPI {
-            let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16.0), NSAttributedString.Key.foregroundColor: UIColor.white]
-            let navBarAppearance = UINavigationBarAppearance()
-            navBarAppearance.configureWithOpaqueBackground()
-            navBarAppearance.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : UIColor.mainColor
-            navBarAppearance.titleTextAttributes = attributes
-            navigationController?.navigationBar.standardAppearance = navBarAppearance
-            navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
             let backButton = UIBarButtonItem(image: UIImage(systemName: "chevron.backward"), style: .plain, target: self, action: #selector(self.didTapExit))
             self.navigationItem.leftBarButtonItem = backButton
         }
@@ -273,41 +276,44 @@ public class ProfileViewController: UITableViewController {
     }
     
     @objc func acceptCallSwitch(mySwitch: UISwitch) {
-        let value = mySwitch.isOn
-        if !CheckConnection.isConnectedToNetwork()  || API.nGetCLXConnState() == 0 {
-            let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
-            imageView.tintColor = .white
-            publicBanner.dismiss()
-            publicBanner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
-            publicBanner.show()
-            self.switchPrivateAccount.setOn(!value, animated: true)
-            return
-        }
-        DispatchQueue.global().async {
-            let tMessage = CoreMessage_TMessageBank.getChangePersonInfo_New(p_f_pin: self.data)
-            tMessage.mBodies[CoreMessage_TMessageKey.OFFLINE_MODE] = value ? "0" : "1"
-            if let resp = Nexilis.writeAndWait(message: tMessage) {
-                if resp.isOk() {
-                    Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                            "offline_mode" : value ? "0" : "1"
-                        ], _where: "f_pin = '\(self.data)'")
-                    })
-                    DispatchQueue.main.async { [self] in
-                        let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
-                        imageView.tintColor = .white
-                        publicBanner.dismiss()
-                        publicBanner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
-                        publicBanner.show()
-                    }
-                } else {
-                    DispatchQueue.main.async { [self] in
-                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
-                        imageView.tintColor = .white
-                        publicBanner.dismiss()
-                        publicBanner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
-                        publicBanner.show()
-                        self.switchPrivateAccount.setOn(!value, animated: true)
+        timerSwitchAC.invalidate()
+        timerSwitchAC = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { [self] _ in
+            let value = mySwitch.isOn
+            if !CheckConnection.isConnectedToNetwork()  || API.nGetCLXConnState() == 0 {
+                let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                imageView.tintColor = .white
+                publicBanner.dismiss()
+                publicBanner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
+                publicBanner.show()
+                self.switchPrivateAccount.setOn(!value, animated: true)
+                return
+            }
+            DispatchQueue.global().async {
+                let tMessage = CoreMessage_TMessageBank.getChangePersonInfo_New(p_f_pin: self.data)
+                tMessage.mBodies[CoreMessage_TMessageKey.OFFLINE_MODE] = value ? "0" : "1"
+                if let resp = Nexilis.writeAndWait(message: tMessage) {
+                    if resp.isOk() {
+                        Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                "offline_mode" : value ? "0" : "1"
+                            ], _where: "f_pin = '\(self.data)'")
+                        })
+                        DispatchQueue.main.async { [self] in
+                            let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                            imageView.tintColor = .white
+                            publicBanner.dismiss()
+                            publicBanner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
+                            publicBanner.show()
+                        }
+                    } else {
+                        DispatchQueue.main.async { [self] in
+                            let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                            imageView.tintColor = .white
+                            publicBanner.dismiss()
+                            publicBanner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
+                            publicBanner.show()
+                            self.switchPrivateAccount.setOn(!value, animated: true)
+                        }
                     }
                 }
             }
@@ -315,41 +321,44 @@ public class ProfileViewController: UITableViewController {
     }
     
     @objc func privateAccountSwitch(mySwitch: UISwitch) {
-        let value = mySwitch.isOn
-        if !CheckConnection.isConnectedToNetwork()  || API.nGetCLXConnState() == 0 {
-            let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
-            imageView.tintColor = .white
-            publicBanner.dismiss()
-            publicBanner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
-            publicBanner.show()
-            self.switchPrivateAccount.setOn(!value, animated: true)
-            return
-        }
-        DispatchQueue.global().async {
-            let tMessage = CoreMessage_TMessageBank.getChangePersonInfo_New(p_f_pin: self.data)
-            tMessage.mBodies[CoreMessage_TMessageKey.PRIVACY_FLAG] = value ? "1" : "0"
-            if let resp = Nexilis.writeAndWait(message: tMessage) {
-                if resp.isOk() {
-                    Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                            "privacy_flag" : value ? "1" : "0"
-                        ], _where: "f_pin = '\(self.data)'")
-                    })
-                    DispatchQueue.main.async { [self] in
-                        let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
-                        imageView.tintColor = .white
-                        publicBanner.dismiss()
-                        publicBanner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
-                        publicBanner.show()
-                    }
-                } else {
-                    DispatchQueue.main.async { [self] in
-                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
-                        imageView.tintColor = .white
-                        publicBanner.dismiss()
-                        publicBanner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
-                        publicBanner.show()
-                        self.switchPrivateAccount.setOn(!value, animated: true)
+        timerSwitchPA.invalidate()
+        timerSwitchPA = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { [self] _ in
+            let value = mySwitch.isOn
+            if !CheckConnection.isConnectedToNetwork()  || API.nGetCLXConnState() == 0 {
+                let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                imageView.tintColor = .white
+                publicBanner.dismiss()
+                publicBanner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
+                publicBanner.show()
+                self.switchPrivateAccount.setOn(!value, animated: true)
+                return
+            }
+            DispatchQueue.global().async {
+                let tMessage = CoreMessage_TMessageBank.getChangePersonInfo_New(p_f_pin: self.data)
+                tMessage.mBodies[CoreMessage_TMessageKey.PRIVACY_FLAG] = value ? "1" : "0"
+                if let resp = Nexilis.writeAndWait(message: tMessage) {
+                    if resp.isOk() {
+                        Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                "privacy_flag" : value ? "1" : "0"
+                            ], _where: "f_pin = '\(self.data)'")
+                        })
+                        DispatchQueue.main.async { [self] in
+                            let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                            imageView.tintColor = .white
+                            publicBanner.dismiss()
+                            publicBanner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
+                            publicBanner.show()
+                        }
+                    } else {
+                        DispatchQueue.main.async { [self] in
+                            let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                            imageView.tintColor = .white
+                            publicBanner.dismiss()
+                            publicBanner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
+                            publicBanner.show()
+                            self.switchPrivateAccount.setOn(!value, animated: true)
+                        }
                     }
                 }
             }
@@ -372,6 +381,10 @@ public class ProfileViewController: UITableViewController {
     }
     
     @objc func call(sender: Any) {
+        if !Nexilis.checkingAccess(key: "audio_call") {
+            showToast(message: "Feature disabled..".localized(), font: UIFont.systemFont(ofSize: 12), controller: self)
+            return
+        }
         let myData = User.getData(pin: self.data)
         if myData?.ex_block == "1" || myData?.ex_block == "-1" {
             var title = "You blocked this user".localized()
@@ -401,6 +414,10 @@ public class ProfileViewController: UITableViewController {
     }
     
     @objc func video(sender: Any) {
+        if !Nexilis.checkingAccess(key: "video_call") {
+            showToast(message: "Feature disabled..".localized(), font: UIFont.systemFont(ofSize: 12), controller: self)
+            return
+        }
         let myData = User.getData(pin: self.data)
         if myData?.ex_block == "1" || myData?.ex_block == "-1" {
             var title = "You blocked this user".localized()