alqindiirsyam 1 rok temu
rodzic
commit
281cb41339

+ 3 - 12
appbuilder-ios/AppBuilder/AppBuilder/SecondTabViewController.swift

@@ -1128,18 +1128,9 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                     imageView.image = UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
                 }
             } else {
-                if !PrefsUtil.getIconDock().isEmpty {
-                    let dataImage = try? Data(contentsOf: URL(string: PrefsUtil.getUrlDock()!)!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
-                    if dataImage != nil {
-                        getImage(name: data.profile, placeholderImage: UIImage(data: dataImage!), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
-                            imageView.image = image
-                        })
-                    }
-                } else {
-                    getImage(name: data.profile, placeholderImage: UIImage(named: data.pin == "-999" ? "pb_button" : data.messageScope == "3" ? "Profile---Purple" : "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
-                        imageView.image = image
-                    })
-                }
+                getImage(name: data.profile, placeholderImage: UIImage(named: data.pin == "-999" ? "pb_button" : data.messageScope == "3" ? "Profile---Purple" : "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
+                    imageView.image = image
+                })
             }
             let titleView = UILabel()
             content.addSubview(titleView)

+ 4 - 0
appbuilder-ios/NexilisLite/NexilisLite/Resource/id.lproj/Localizable.strings

@@ -360,3 +360,7 @@
 "Back to Company App" = "Kembali ke Aplikasi Awal";
 "Are you sure want to back to company app?" = "Apakah kamu yakin ingin kembali ke aplikasi awal?";
 "Failed to back to Company App" = "Gagal kembali ke Aplikasi Awal";
+"Profile" = "Profil";
+"Contact Center" = "Pusat Kontak";
+"Notification Center" = "Pusat Notifikasi";
+"Call" = "Panggilan";

+ 9 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/CoreMessage_TMessageBank.swift

@@ -2494,4 +2494,13 @@ public class CoreMessage_TMessageBank {
         return tmessage
     }
     
+    public static func requestGPTBot(message: String) -> TMessage {
+        let tmessage = TMessage()
+        tmessage.mCode = CoreMessage_TMessageCode.GPT
+        tmessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tmessage.mPIN = User.getMyPin() ?? ""
+        tmessage.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message
+        return tmessage
+    }
+    
 }

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

@@ -780,4 +780,5 @@ public class CoreMessage_TMessageCode {
     public static let BLOCK_ACCESS = "BLK";
     
     public static let RESET_SUPER_APP = "RSA";
+    public static let GPT = "GPT";
 }

+ 4 - 2
appbuilder-ios/NexilisLite/NexilisLite/Source/Download.swift

@@ -57,8 +57,10 @@ public class Download {
             if baseURL.last != "/" {
                 sep = "/"
             }
-            let fullURL = "\(baseURL)\(sep)\(filename)"
-            //print("FULL URL: \(fullURL)")
+            var fullURL = "\(baseURL)\(sep)\(filename)"
+            if let encodedUrlString = fullURL.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
+                fullURL = encodedUrlString
+            }
             let BOUNDARY = "esuploader-" + "\(Date().currentTimeMillis())"
             let MIME_TYPE = "multipart/form-data; boundary=" + BOUNDARY
             let headers: HTTPHeaders = [

+ 4 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/Network.swift

@@ -214,6 +214,10 @@ public class Network {
         }
         
         //print("FULL URL: \(endUrl)")
+        var endUrl = endUrl
+        if let encodedUrlString = endUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
+            endUrl = encodedUrlString
+        }
         let BOUNDARY = "esuploader-" + "\(Date().currentTimeMillis())"
         let MIME_TYPE = "multipart/form-data; boundary=" + BOUNDARY
         let headers: HTTPHeaders = [

+ 2 - 2
appbuilder-ios/NexilisLite/NexilisLite/Source/TMessage.swift

@@ -37,7 +37,7 @@ public class TMessage {
         mVersion = "1.0.111"
         mBodies[CoreMessage_TMessageKey.IMEI] = Nexilis.getCLMUserId()
 //        mBodies[CoreMessage_TMessageKey.VERCOD] = UIApplication.appVersion
-        mBodies[CoreMessage_TMessageKey.VERCOD] = "2.2.157"
+        mBodies[CoreMessage_TMessageKey.VERCOD] = "2.2.177"
     }
     
     public init(data : String) {
@@ -55,7 +55,7 @@ public class TMessage {
         mMedia = media
         mBodies[CoreMessage_TMessageKey.IMEI] = Nexilis.getCLMUserId()
 //        mBodies[CoreMessage_TMessageKey.VERCOD] = UIApplication.appVersion
-        mBodies[CoreMessage_TMessageKey.VERCOD] = "2.2.157"
+        mBodies[CoreMessage_TMessageKey.VERCOD] = "2.2.177"
     }
     
     public func clone(p_tmessage:TMessage) -> TMessage {

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

@@ -204,6 +204,30 @@ public final class Utils {
         UserDefaults.standard.string(forKey: "max_retry_time_upload") ?? "60000"
     }
     
+    static func setWhatsappCenter(value: String) {
+        UserDefaults.standard.set(value, forKey: "whatsapp_center")
+    }
+
+    static func getWhatsappCenter() -> String {
+        UserDefaults.standard.string(forKey: "whatsapp_center") ?? "08115881946"
+    }
+    
+    static func setSMSCenter(value: String) {
+        UserDefaults.standard.set(value, forKey: "sms_center")
+    }
+
+    static func getSMSCenter() -> String {
+        UserDefaults.standard.string(forKey: "sms_center") ?? "081290009799"
+    }
+    
+    static func setCallCenter(value: String) {
+        UserDefaults.standard.set(value, forKey: "call_center")
+    }
+
+    static func getCallCenter() -> String {
+        UserDefaults.standard.string(forKey: "call_center") ?? "1500046"
+    }
+    
     
     public static func sGetCurrentDateTime(sFormat: String!) -> String! {
         let todaysDate = NSDate()
@@ -501,6 +525,15 @@ public final class Utils {
                     if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_background_dark" {
                         Utils.setBackgroundDark(value: json[CoreMessage_TMessageKey.VALUE] as! String)
                     }
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "sms_center" {
+                        Utils.setSMSCenter(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    }
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "whatsapp_center" {
+                        Utils.setWhatsappCenter(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    }
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "call_center" {
+                        Utils.setCallCenter(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    }
                 }
             } catch {
             }
@@ -1349,6 +1382,7 @@ public class DialogUnableAccess: UIViewController {
     
     @objc func kycTapped() {
         //print("kycTapped")
+        APIS.openContactCenter()
         self.dismiss(animated: true)
     }
     
@@ -1504,6 +1538,7 @@ public class DialogVerifyYou: UIViewController {
                     self.deleteAllRecordDatabase()
                     if(!fPin.isEmpty) {
 //                            Nexilis.changeUser(f_pin: device_id)
+                        Utils.setLoginMultipleFPin(value: "")
                         UserDefaults.standard.setValue(device_id, forKey: "device_id")
                         Utils.setProfile(value: true)
                         UserDefaults.standard.synchronize()
@@ -1675,6 +1710,7 @@ public class DialogSignIn: UIViewController {
     
     @objc func ccTapped() {
         //print("ccTapped")
+        APIS.openContactCenter()
         self.dismiss(animated: true)
     }
     
@@ -1894,6 +1930,7 @@ public class DialogSecurityShield: UIViewController {
     
     @objc func ccTapped() {
         //print("ccTapped")
+        APIS.openContactCenter()
         self.dismiss(animated: true)
     }
     
@@ -2006,6 +2043,7 @@ public class DialogTransactionApproval: UIViewController {
     
     @objc func ccTapped() {
         //print("ccTapped")
+        APIS.openContactCenter()
         self.dismiss(animated: true)
     }
     

+ 182 - 160
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift

@@ -117,13 +117,15 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
         super.viewDidLoad()
         navigationController?.navigationBar.topItem?.title = "GPT SmartBot"
         
+        buttonSendChat.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)
         buttonSendChat.circle()
         buttonSendChat.addTarget(self, action: #selector(sendTapped), for: .touchUpInside)
-        buttonSendChat.backgroundColor = .mainColor
+        buttonSendChat.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .white : .mainColor
         textFieldSend.layer.cornerRadius = textFieldSend.maxCornerRadius()
         textFieldSend.layer.borderWidth = 1.0
         textFieldSend.text = "Send message".localized()
         textFieldSend.textColor = UIColor.lightGray
+        textFieldSend.tintColor = self.traitCollection.userInterfaceStyle == .dark ? .white : .black
         textFieldSend.textContainerInset = UIEdgeInsets(top: 12, left: 20, bottom: 11, right: 40)
         textFieldSend.layer.borderColor = UIColor.lightGray.withAlphaComponent(0.5).cgColor
         textFieldSend.font = UIFont.systemFont(ofSize: 12)
@@ -172,7 +174,7 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
 //        }
     }
     
-    private func sendChat(message_scope_id:String =  "31", status:String =  "2", message_text:String =  "", credential:String = "0", attachment_flag: String = "0", ex_blog_id: String = "", message_large_text: String = "", ex_format: String = "", image_id: String = "", audio_id: String = "", video_id: String = "", file_id: String = "", thumb_id: String = "", reff_id: String = "", read_receipts: String = "4", chat_id: String = "", is_call_center: String = "0", call_center_id: String = "", viewController: UIViewController) {
+    private func sendChat(message_scope_id:String =  "31", status:String =  "4", message_text:String =  "", credential:String = "0", attachment_flag: String = "0", ex_blog_id: String = "", message_large_text: String = "", ex_format: String = "", image_id: String = "", audio_id: String = "", video_id: String = "", file_id: String = "", thumb_id: String = "", reff_id: String = "", read_receipts: String = "4", chat_id: String = "", is_call_center: String = "0", call_center_id: String = "", viewController: UIViewController) {
         if viewController is ChatGPTBotView {
             if ((textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) == "Send message".localized() && textFieldSend.textColor == UIColor.lightGray && attachment_flag != "11") || textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ) {
                 dismissKeyboard()
@@ -195,7 +197,7 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
         var opposite_pin = idMe ?? ""
         sendTyping(l_pin: l_pin, isTyping: true)
         let message = CoreMessage_TMessageBank.sendMessage(l_pin: l_pin, 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: chat_id, is_call_center: is_call_center, call_center_id: call_center_id, opposite_pin: opposite_pin)
-        Nexilis.addQueueMessage(message: message)
+        Nexilis.saveMessage(message: message)
         let messageId = String(message.mBodies[CoreMessage_TMessageKey.MESSAGE_ID]!)
         var row: [String: Any?] = [:]
         row["message_id"] = messageId
@@ -230,7 +232,7 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
         gptRow["content"] = row["message_text"] as! String
         chatGPTMessages.append(gptRow)
         let jsonBody = Payload(use_video: "0", payload: chatGPTMessages)
-        request(data: jsonBody)
+        request(mesage: row["message_text"] as! String)
         tableChatView.insertRows(at: [IndexPath(row: dataMessages.filter({ $0["chat_date"] as! String == dataDates[dataDates.count - 1]}).count - 1, section: dataDates.count - 1)], with: .none)
         if textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "Send message".localized() && textFieldSend.textColor != UIColor.lightGray && constraintViewTextField.constant == 0 {
             textFieldSend.text = "Send message".localized()
@@ -268,167 +270,187 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
 //        }
     }
     
-    private func request(data: Payload) {
-        AF.request(CHATGPT_URL, method: .post, parameters: data, encoder: JSONParameterEncoder.default)
-            .responseJSON{ response in
-                if let result = response.value as? [String: Any], let message = result["message"] as? [String: String] {
-                    self.chatGPTMessages.append(message)
-                    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())
-                    
-                    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" : message["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! += 1
-                            cursor.close()
-                            //print("select db message summary")
-                        }
-                    })
-                    if counter == nil {
-                        counter = 1
-                        //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)
-                        }
-                    })
-                    //print("insert db message summary \(message_id)")
-                    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"] = message["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.counter += 1
-                    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)
-                    if self.currentIndexpath?.row == (self.dataMessages.count - 2) {
-                        if (self.viewIfLoaded?.window != nil) {
-                            self.sendReadMessageStatus(chat_id: "", f_pin: row["f_pin"] as! String, message_scope_id: row["message_scope_id"] as! String, message_id: message_id)
-                        }
-                        self.tableChatView.scrollToBottom()
-                        if ( self.currentIndexpath!.section <= self.dataDates.count - 1 && self.currentIndexpath!.row <= self.dataMessages.filter({ $0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).count - 1)  {
-                            self.counter = 0
-                            self.updateCounter(counter: self.counter)
-                        }
-                        let lastMarkerCounter = self.markerCounter
-                        if self.markerCounter != nil {
-                            self.markerCounter = nil
-                        }
-                        self.tableChatView.beginUpdates()
-                        let indexMessage = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == lastMarkerCounter })
-                        if indexMessage != nil {
-                            let section = self.dataDates.firstIndex(of: self.dataMessages[indexMessage!]["chat_date"] as! String)
-                            let row = self.dataMessages.filter({ $0["chat_date"] as! String == self.dataMessages[indexMessage!]["chat_date"] as! String}).firstIndex(where: { $0["message_id"] as? String == self.dataMessages[indexMessage!]["message_id"] as? String })
-                            if row != nil && section != nil  {
-                                self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
-                            }
-                        }
-                        self.tableChatView.endUpdates()
-                    }
-                    else if self.currentIndexpath == nil {
-                        self.counter = 0
-                        self.updateCounter(counter: self.counter)
-                        if (self.viewIfLoaded?.window != nil) {
-                            self.sendReadMessageStatus(chat_id: "", f_pin: row["f_pin"] as! String, message_scope_id: row["message_scope_id"] as! String, message_id: message_id)
-                        }
-                    }
-                    else if self.counter != 0 {
-                        if !self.indicatorCounterBSTB.isDescendant(of: self.view) && self.buttonScrollToBottom.isDescendant(of: self.view) {
-                            self.markerCounter = row["message_id"] as? String
-                            self.addCounterAtButttonScrollToBottom()
-                            self.tableChatView.beginUpdates()
-                            let indexMessage = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == self.markerCounter })
-                            if indexMessage != nil {
-                                let section = self.dataDates.firstIndex(of: self.dataMessages[indexMessage!]["chat_date"] as! String)
-                                let row = self.dataMessages.filter({ $0["chat_date"] as! String == self.dataMessages[indexMessage!]["chat_date"] as! String}).firstIndex(where: { $0["message_id"] as? String == self.dataMessages[indexMessage!]["message_id"] as? String })
-                                if row != nil && section != nil  {
-                                    self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+    private func request(mesage: String) {
+        DispatchQueue.global().async {
+            do {
+                if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.requestGPTBot(message: mesage)) {
+                    if response.isOk() {
+                        let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
+                        if let json = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: []) as? [String: Any?] {
+                            print("HMM \(json)")
+                            DispatchQueue.main.async {
+                                var gptRow : [String: String] = [:]
+                                gptRow["role"] = json["role"] as? String
+                                gptRow["content"] = json["content"] as? String
+                                self.chatGPTMessages.append(gptRow)
+                                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())
+                                
+                                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! += 1
+                                        cursor.close()
+                                        //print("select db message summary")
+                                    }
+                                })
+                                if counter == nil {
+                                    counter = 1
+                                    //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)
+                                    }
+                                })
+                                //print("insert db message summary \(message_id)")
+                                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.counter += 1
+                                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)
+                                if self.currentIndexpath?.row == (self.dataMessages.count - 2) {
+                                    if (self.viewIfLoaded?.window != nil) {
+                                        self.sendReadMessageStatus(chat_id: "", f_pin: row["f_pin"] as! String, message_scope_id: row["message_scope_id"] as! String, message_id: message_id)
+                                    }
+                                    self.tableChatView.scrollToBottom()
+                                    if ( self.currentIndexpath!.section <= self.dataDates.count - 1 && self.currentIndexpath!.row <= self.dataMessages.filter({ $0["chat_date"] as! String == self.dataDates[self.dataDates.count - 1]}).count - 1)  {
+                                        self.counter = 0
+                                        self.updateCounter(counter: self.counter)
+                                    }
+                                    let lastMarkerCounter = self.markerCounter
+                                    if self.markerCounter != nil {
+                                        self.markerCounter = nil
+                                    }
+                                    self.tableChatView.beginUpdates()
+                                    let indexMessage = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == lastMarkerCounter })
+                                    if indexMessage != nil {
+                                        let section = self.dataDates.firstIndex(of: self.dataMessages[indexMessage!]["chat_date"] as! String)
+                                        let row = self.dataMessages.filter({ $0["chat_date"] as! String == self.dataMessages[indexMessage!]["chat_date"] as! String}).firstIndex(where: { $0["message_id"] as? String == self.dataMessages[indexMessage!]["message_id"] as? String })
+                                        if row != nil && section != nil  {
+                                            self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+                                        }
+                                    }
+                                    self.tableChatView.endUpdates()
+                                }
+                                else if self.currentIndexpath == nil {
+                                    self.counter = 0
+                                    self.updateCounter(counter: self.counter)
+                                    if (self.viewIfLoaded?.window != nil) {
+                                        self.sendReadMessageStatus(chat_id: "", f_pin: row["f_pin"] as! String, message_scope_id: row["message_scope_id"] as! String, message_id: message_id)
+                                    }
+                                }
+                                else if self.counter != 0 {
+                                    if !self.indicatorCounterBSTB.isDescendant(of: self.view) && self.buttonScrollToBottom.isDescendant(of: self.view) {
+                                        self.markerCounter = row["message_id"] as? String
+                                        self.addCounterAtButttonScrollToBottom()
+                                        self.tableChatView.beginUpdates()
+                                        let indexMessage = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == self.markerCounter })
+                                        if indexMessage != nil {
+                                            let section = self.dataDates.firstIndex(of: self.dataMessages[indexMessage!]["chat_date"] as! String)
+                                            let row = self.dataMessages.filter({ $0["chat_date"] as! String == self.dataMessages[indexMessage!]["chat_date"] as! String}).firstIndex(where: { $0["message_id"] as? String == self.dataMessages[indexMessage!]["message_id"] as? String })
+                                            if row != nil && section != nil  {
+                                                self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+                                            }
+                                        }
+                                        self.tableChatView.endUpdates()
+                                    } else if self.indicatorCounterBSTB.isDescendant(of: self.view) {
+                                        self.labelCounter.text = "\(self.counter)"
+                                    }
                                 }
                             }
-                            self.tableChatView.endUpdates()
-                        } else if self.indicatorCounterBSTB.isDescendant(of: self.view) {
-                            self.labelCounter.text = "\(self.counter)"
                         }
                     }
                 }
+            } catch {
+                print("Error encoding data: \(error.localizedDescription)")
             }
+        }
+//        AF.request(CHATGPT_URL, method: .post, parameters: data, encoder: JSONParameterEncoder.default)
+//            .responseJSON{ response in
+//                if let result = response.value as? [String: Any], let message = result["message"] as? [String: String] {
+//                    
+//                }
+//            }
     }
     
     func loadData(){
@@ -2327,7 +2349,7 @@ extension ChatGPTBotView: UITextViewDelegate {
     public func textViewDidBeginEditing(_ textView: UITextView) {
         if textView.textColor == UIColor.lightGray {
             textView.text = nil
-            textView.textColor = UIColor.black
+            textView.textColor = self.traitCollection.userInterfaceStyle == .dark ? .white : UIColor.black
         }
     }
     

+ 20 - 14
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -947,7 +947,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                 row["chat_date"] = "Today".localized()
                 let listStringName: [String] = ["Messaging".localized(), "Secure SMS".localized(), "VoIP Call".localized(), "Email".localized(), "Video Call".localized(), "GSM Call".localized(), "GPT Chatbot".localized(), "WhatsApp"]
                 var data : [CategoryCC] = []
-                let channels : [String] = ["0", "4", "2", "3", "1", "5", "7", "6"]
+                let channels : [String] = ["0", "4", "1", "3", "2", "5", "7", "6"]
                 if Utils.getDefaultCC() == "No" {
                     let category = CategoryCC.getDatafromParent(parent: CategoryCC.default_parent)
                     for i in 0..<category.count {
@@ -2478,7 +2478,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                     let listStringName: [String] = ["Messaging".localized(), "Secure SMS".localized(), "VoIP Call".localized(), "Email".localized(), "Video Call".localized(), "GSM Call".localized(), "GPT Chatbot".localized(), "WhatsApp"]
 //                    let listStringName: [String] = ["Chat with a Representative".localized(), "Video Call a Representative".localized(), "Call a Representative".localized()]
                     var data : [CategoryCC] = []
-                    let channels : [String] = ["0", "4", "2", "3", "1", "5", "7", "6"]
+                    let channels : [String] = ["0", "4", "1", "3", "2", "5", "7", "6"]
                     for i in 0..<listStringName.count {
                         data.append(CategoryCC(id: "level\(Int(level)! + 1)_\(channels[i])", service_id: service_id!, service_name: listStringName[i], parent: id!, description: "", is_tablet: "0"))
                     }
@@ -2679,15 +2679,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
     }
     
     func requestSMSContactCenter(_ channel: Int){
-        let idMe = UserDefaults.standard.string(forKey: "me")!
-        let complaintId = "CMP_\(idMe)_\(String(Date().currentTimeMillis()))SMS"
-        isRequestContactCenter = true
-        if let phoneNum = UserDefaults.standard.string(forKey: "whatsapp_center") {
-            APIS.sendSMS(phoneNumber: phoneNum)
-        }
-        else {
-            APIS.sendSMS(phoneNumber: "+628115881946")
-        }
+//        let idMe = UserDefaults.standard.string(forKey: "me")!
+//        let complaintId = "CMP_\(idMe)_\(String(Date().currentTimeMillis()))SMS"
+//        isRequestContactCenter = true
+        var phone = Utils.getSMSCenter()
+        if phone.substring(from: 0, to: 0) == "0" {
+            phone = "+62" + phone.substring(from: 1, to: phone.count)
+        }
+        APIS.sendSMS(phoneNumber: phone)
 //        let tmessage = TMessage()
 //        tmessage.mCode = CoreMessage_TMessageCode.ACCEPT_CALL_CENTER
 //        tmessage.mStatus = CoreMessage_TMessageUtil.getTID()
@@ -2699,13 +2698,20 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
     }
     
     func requestGSMCallContactCenter(_ channel: Int){
-        if let url = URL(string: "tel://1500046") {
+        var phone = Utils.getCallCenter()
+        if phone.substring(from: 0, to: 0) == "0" {
+            phone = "+62" + phone.substring(from: 1, to: phone.count)
+        }
+        if let url = URL(string: "tel://\(phone)") {
             UIApplication.shared.open(url)
         }
     }
     
     func requestWhatsappContactCenter(_ channel: Int){
-        let phone = UserDefaults.standard.string(forKey: "whatsapp_center") ?? "628115881946";
+        var phone = Utils.getWhatsappCenter()
+        if phone.substring(from: 0, to: 0) == "0" {
+            phone = "+62" + phone.substring(from: 1, to: phone.count)
+        }
         APIS.sendWhatsapp(phoneNumber: phone)
     }
     
@@ -3158,7 +3164,7 @@ extension EditorPersonal: UIDocumentPickerDelegate, DocumentPickerDelegate, QLPr
     }
     
     public func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
-        1
+        return self.previewItem != nil ? 1 : 0
     }
     
     public func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {

+ 12 - 19
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ContactChatViewController.swift

@@ -144,13 +144,15 @@ class ContactChatViewController: UITableViewController {
 //            }))
 //        }
         
-        if noUCList {
-            let buttonAddFriend = UIBarButtonItem(image: UIImage(systemName: "person.badge.plus", withConfiguration: UIImage.SymbolConfiguration(pointSize: 18, weight: .regular, scale: .default))?.withTintColor(.white), style: .plain, target: self, action: #selector(addFriend(sender:)))
-            navigationItem.rightBarButtonItem = buttonAddFriend
-        } else {
-            let menu = UIMenu(title: "", children: childrenMenu)
-            navigationItem.rightBarButtonItem = UIBarButtonItem(title: nil, image: UIImage(systemName: "ellipsis"), primaryAction: .none, menu: menu)
-        }
+//        if noUCList {
+//            let buttonAddFriend = UIBarButtonItem(image: UIImage(systemName: "person.badge.plus", withConfiguration: UIImage.SymbolConfiguration(pointSize: 18, weight: .regular, scale: .default))?.withTintColor(.white), style: .plain, target: self, action: #selector(addFriend(sender:)))
+//            navigationItem.rightBarButtonItem = buttonAddFriend
+//        } else {
+//            let menu = UIMenu(title: "", children: childrenMenu)
+//            navigationItem.rightBarButtonItem = UIBarButtonItem(title: nil, image: UIImage(systemName: "ellipsis"), primaryAction: .none, menu: menu)
+//        }
+        let menu = UIMenu(title: "", children: childrenMenu)
+        navigationItem.rightBarButtonItem = UIBarButtonItem(title: nil, image: UIImage(systemName: "ellipsis"), primaryAction: .none, menu: menu)
         
         searchController = UISearchController(searchResultsController: nil)
         searchController.delegate = self
@@ -1054,18 +1056,9 @@ extension ContactChatViewController {
                         imageView.image = UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
                     }
                 } else {
-                    if !Utils.getIconDock().isEmpty {
-                        let dataImage = try? Data(contentsOf: URL(string: Utils.getUrlDock()!)!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
-                        if dataImage != nil {
-                            getImage(name: data.profile, placeholderImage: UIImage(data: dataImage!), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
-                                imageView.image = image
-                            })
-                        }
-                    } else {
-                        getImage(name: data.profile, placeholderImage: UIImage(named: data.pin == "-999" ? "pb_button" : data.messageScope == "3" ? "Profile---Purple" : "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
-                            imageView.image = image
-                        })
-                    }
+                    getImage(name: data.profile, placeholderImage: UIImage(named: data.pin == "-999" ? "pb_button" : data.messageScope == "3" ? "Profile---Purple" : "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
+                        imageView.image = image
+                    })
                 }
                 let titleView = UILabel()
                 content.addSubview(titleView)