소스 검색

add max retry upload

alqindiirsyam 1 년 전
부모
커밋
2a29b8409b

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

@@ -1102,7 +1102,11 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                     } else {
                         let imageStatus = NSTextAttachment()
                         let status = getRealStatus(messageId: data.messageId)
-                        if (status == "1" || status == "2" ) {
+                        if status == "0" {
+                            imageStatus.image = UIImage(systemName: "xmark.circle")!.withTintColor(UIColor.red, renderingMode: .alwaysOriginal)
+                        } else if status == "1" {
+                            imageStatus.image = UIImage(systemName: "clock.arrow.circlepath")!.withTintColor(UIColor.lightGray, renderingMode: .alwaysOriginal)
+                        } else if status == "2" {
                             imageStatus.image = UIImage(named: "checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)
                         } else if (status == "3") {
                             imageStatus.image = UIImage(named: "double-checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)

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

@@ -2436,4 +2436,12 @@ public class CoreMessage_TMessageBank {
         return tmessage
     }
     
+    public static func getFeatureAccessAll() -> TMessage {
+        let tmessage = TMessage()
+        tmessage.mCode = CoreMessage_TMessageCode.FEATURE_ACCESS_ALL
+        tmessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tmessage.mPIN = User.getMyPin() ?? ""
+        return tmessage
+    }
+    
 }

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

@@ -767,4 +767,6 @@ public class CoreMessage_TMessageCode {
     public static let CALLING = "CALL";
     public static let NOTIFY_TO_CALLING = "NTC";
     public static let CANCEL_CALL_NOTIFICATION = "CCN";
+    
+    public static let FEATURE_ACCESS_ALL = "FA02";
 }

+ 6 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/InquiryThread.swift

@@ -27,6 +27,7 @@ class InquiryThread {
                 while cursor.next() {
                     let status = cursor.int(forColumnIndex: 0)
                     if status == 1 {
+                        delInquiry(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 2)!)
                         continue
                     }
                     if let cursorMessage = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(cursor.string(forColumnIndex: 2)!)'") {
@@ -35,7 +36,7 @@ class InquiryThread {
                                 addQueue(message: TMessage(data: message))
                             }
                         } else {
-                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "INQUIRY", _where: "id = '\(cursor.string(forColumnIndex: 2)!)'")
+                            delInquiry(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 2)!)
                         }
                         cursorMessage.close()
                     }
@@ -45,6 +46,10 @@ class InquiryThread {
         })
     }
     
+    private func delInquiry(fmdb: Any, messageId: String) {
+        _ = Database.shared.deleteRecord(fmdb: fmdb as! FMDatabase, table: "INQUIRY", _where: "id = '\(messageId)'")
+    }
+    
     func addQueue(message: TMessage) {
         //print("MASUK INQUIRY ADD")
         addInquiry(message: message)

+ 25 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -67,6 +67,7 @@ public class Nexilis: NSObject {
     public static let listenerTypingChat = "onTypingChatLibLite"
     public static let listenerStatusCall = "onStatusCallLibLite"
     public static let callFCM = "onCallFCM"
+    public static let failedSendMessage = "onFailedSendMessage"
     public static var showLibraryNotification = true
     
     public static let STREAMING_SEMINAR_ENDED = 88
@@ -223,6 +224,7 @@ public class Nexilis: NSObject {
                             }
                         })
                     }
+                    getFeatureAccess()
                     getServiceBank()
                     getPullWorkingArea()
                     getPullGroupNoMember()
@@ -349,6 +351,29 @@ public class Nexilis: NSObject {
         })
     }
     
+    private static func getFeatureAccess() {
+        DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
+            if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getFeatureAccessAll(), timeout: 10 * 1000), response.isOk() {
+                let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
+                if !data.isEmpty {
+                    if let jsonArray = try! JSONSerialization.jsonObject(with: data.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
+                            if umr != nil {
+                                Utils.setMaxRetryUpload(value: "\(umr ?? 0)")
+                            }
+                            if umt != nil {
+                                Utils.setMaxRetryTimeUpload(value: "\(umt ?? 0)")
+                            }
+                        } catch {
+                        }
+                    }
+                }
+            }
+        })
+    }
+    
     private static func getPullWorkingArea() {
         DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getWorkingAreaContactCenter(), timeout: 30 * 1000), response.isOk() {

+ 92 - 6
appbuilder-ios/NexilisLite/NexilisLite/Source/OutgoingThread.swift

@@ -25,10 +25,19 @@ class OutgoingThread {
     
     init() {
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message from OUTGOING") {
+            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message, id from OUTGOING") {
                 while cursor.next() {
                     if let message = cursor.string(forColumnIndex: 0) {
-                        addQueue(message: TMessage(data: message))
+                        if let cursorMessage = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(cursor.string(forColumnIndex: 1)!)'") {
+                            if cursorMessage.next() {
+                                addQueue(message: TMessage(data: message))
+                            } else {
+                                delOutgoing(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 1)!)
+                            }
+                            cursorMessage.close()
+                        } else {
+                            delOutgoing(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 1)!)
+                        }
                     }
                 }
                 cursor.close()
@@ -121,6 +130,9 @@ class OutgoingThread {
      *
      */
     
+    private var maxRetryUpload: [String: Int] = [:]
+    private var maxRetryUploadTime: [String: Int] = [:]
+    
     private func sendChat(message: TMessage) {
         // if media exist upload first
         var fileName = message.getBody(key: CoreMessage_TMessageKey.IMAGE_ID, default_value: "")
@@ -135,6 +147,10 @@ class OutgoingThread {
         }
         let isMedia = !fileName.isEmpty
         if isMedia {
+            if maxRetryUpload[message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)] == nil {
+                maxRetryUpload[message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)] = 0
+                maxRetryUploadTime[message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)] = Date().currentTimeMillis()
+            }
             if (!message.getBody(key: CoreMessage_TMessageKey.THUMB_ID).isEmpty) {
                 Network().uploadHTTP(name: message.getBody(key: CoreMessage_TMessageKey.THUMB_ID)) { (result, progress, response) in
                     if result, progress == 100 {
@@ -164,13 +180,15 @@ class OutgoingThread {
                                             self.delOutgoing(fmdb: fmdb, messageId: messageId)
                                         })
                                     } else {
-                                        InquiryThread.default.addQueue(message: message)
+                                        self.retryUpload(message: message, fileName: fileName)
                                     }
                                 }
                             } else {
-                                InquiryThread.default.addQueue(message: message)
+                                self.retryUpload(message: message, fileName: fileName)
                             }
                         }
+                    } else {
+                        self.retryUpload(message: message, fileName: fileName)
                     }
                 }
             } else {
@@ -190,11 +208,11 @@ class OutgoingThread {
                                     self.delOutgoing(fmdb: fmdb, messageId: messageId)
                                 })
                             } else {
-                                InquiryThread.default.addQueue(message: message)
+                                self.retryUpload(message: message, fileName: fileName)
                             }
                         }
                     } else {
-                        InquiryThread.default.addQueue(message: message)
+                        self.retryUpload(message: message, fileName: fileName)
                     }
                 }
             }
@@ -214,6 +232,74 @@ class OutgoingThread {
         }
     }
     
+    private func retryUpload(message: TMessage, fileName: String) {
+        //print("masuk Retry")
+        var maxRetry = Utils.getMaxRetryUpload()
+        var maxRetryTime = Utils.getMaxRetryTimeUpload()
+        
+        if maxRetry == "0" {
+            maxRetry = "5"
+        }
+        if maxRetryTime == "0" {
+            maxRetryTime = "60000"
+        }
+        
+        var countRetry = 0
+        do {
+            countRetry = maxRetryUpload[message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)]!
+            countRetry += 1
+            //print("masuk Retry1 = \(countRetry)")
+            maxRetryUpload.updateValue(countRetry, forKey: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+        } catch {}
+        if countRetry >= Int(maxRetry)! {
+            Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                    "status" : "0"
+                ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
+                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                    "status" : "0"
+                ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
+                self.delOutgoing(fmdb: fmdb, messageId: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+            })
+            var dataMessage: [AnyHashable : Any] = [:]
+            dataMessage["message_id"] = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
+            dataMessage["status"] = "0"
+            NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.failedSendMessage), object: nil, userInfo: dataMessage)
+            maxRetryUpload.removeValue(forKey: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+            maxRetryUploadTime.removeValue(forKey: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+            if let delegate = Nexilis.shared.messageDelegate {
+                delegate.onUpload(name: fileName, progress: 100)
+            }
+        } else {
+            let timeRetry = maxRetryUploadTime[message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)]!
+            if timeRetry != 0 {
+                if (timeRetry + Int(maxRetryTime)!) <= Date().currentTimeMillis() {
+                    Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                            "status" : "0"
+                        ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                            "status" : "0"
+                        ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
+                        self.delOutgoing(fmdb: fmdb, messageId: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+                    })
+                    var dataMessage: [AnyHashable : Any] = [:]
+                    dataMessage["message_id"] = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
+                    dataMessage["status"] = "0"
+                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.failedSendMessage), object: nil, userInfo: dataMessage)
+                    maxRetryUpload.removeValue(forKey: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+                    maxRetryUploadTime.removeValue(forKey: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+                    if let delegate = Nexilis.shared.messageDelegate {
+                        delegate.onUpload(name: fileName, progress: 100)
+                    }
+                    return
+                }
+            }
+            //print("retry sukses")
+            sendChat(message: message)
+        }
+    }
+    
     private func deleteMessage(message: TMessage) {
         let messageId = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
         let type = message.getBody(key: CoreMessage_TMessageKey.DELETE_MESSAGE_FLAG)

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

@@ -182,6 +182,22 @@ public final class Utils {
         UserDefaults.standard.string(forKey: "app_builder_background_dark") ?? ""
     }
     
+    static func setMaxRetryUpload(value: String) {
+        UserDefaults.standard.set(value, forKey: "max_retry_upload")
+    }
+
+    static func getMaxRetryUpload() -> String {
+        UserDefaults.standard.string(forKey: "max_retry_upload") ?? "5"
+    }
+    
+    static func setMaxRetryTimeUpload(value: String) {
+        UserDefaults.standard.set(value, forKey: "max_retry_time_upload")
+    }
+
+    static func getMaxRetryTimeUpload() -> String {
+        UserDefaults.standard.string(forKey: "max_retry_time_upload") ?? "60000"
+    }
+    
     
     public static func sGetCurrentDateTime(sFormat: String!) -> String! {
         let todaysDate = NSDate()

+ 30 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift

@@ -201,6 +201,7 @@ public class EditorGroup: UIViewController {
         center.addObserver(self, selector: #selector(onMemberTopic(notification:)), name: NSNotification.Name(rawValue: "onMember"), object: nil)
         center.addObserver(self, selector: #selector(onGroup(notification:)), name: NSNotification.Name(rawValue: "onGroup"), object: nil)
         center.addObserver(self, selector: #selector(onMemberTopic(notification:)), name: NSNotification.Name(rawValue: "onTopic"), object: nil)
+        center.addObserver(self, selector: #selector(onFailedSendMessage(notification:)), name: NSNotification.Name(rawValue: Nexilis.failedSendMessage), object: nil)
         
         if dataMessageForward != nil {
             for i in 0..<dataMessageForward!.count {
@@ -967,6 +968,35 @@ public class EditorGroup: UIViewController {
         }
     }
     
+    @objc func onFailedSendMessage(notification: NSNotification) {
+        DispatchQueue.main.async {
+            let data:[AnyHashable : Any] = notification.userInfo!
+            let messageId = data["message_id"] as! String
+            let status = data["status"] as! String
+            
+            var idx = self.dataMessages.firstIndex(where: { $0["message_id"] as? String ?? "" == messageId })
+            if let idxMessageIdParent = self.groupImages.firstIndex(where: { $0.value.contains(where: { $0.messageId == messageId }) }) {
+                if let idxInImages = self.groupImages[idxMessageIdParent].value.firstIndex(where: { $0.messageId == messageId }) {
+                    self.groupImages[idxMessageIdParent].value[idxInImages].status = status
+                    self.groupImages[idxMessageIdParent].value[idxInImages].dataMessage["status"] = status
+                }
+                idx = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == self.groupImages[idxMessageIdParent].key })
+            }
+            
+            if (idx != nil) {
+                do {
+                    self.dataMessages[idx!]["status"] = status
+                    let section = self.dataDates.firstIndex(of: self.dataMessages[idx!]["chat_date"] as! String)
+                    let row = self.dataMessages.filter({ $0["chat_date"] as! String == self.dataMessages[idx!]["chat_date"] as! String}).firstIndex(where: { $0["message_id"] as? String == self.dataMessages[idx!]["message_id"] as? String })
+                    if row != nil && section != nil  {
+                        self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+                    }
+                } catch {
+                }
+            }
+        }
+    }
+    
     private func updateStatusDelete(idx: Int?, chatData: [String: String]) {
         do {
             if self.dataMessages[idx!]["lock"] as! String == "1" {

+ 36 - 2
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -225,6 +225,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         center.addObserver(self, selector: #selector(onUploadChat(notification:)), name: NSNotification.Name(rawValue: "onUploadChat"), object: nil)
         center.addObserver(self, selector: #selector(onUnfriend(notification:)), name: NSNotification.Name(rawValue: "onUpdatePersonInfo"), object: nil)
         center.addObserver(self, selector: #selector(onTyping(notification:)), name: NSNotification.Name(rawValue: Nexilis.listenerTypingChat), object: nil)
+        center.addObserver(self, selector: #selector(onFailedSendMessage(notification:)), name: NSNotification.Name(rawValue: Nexilis.failedSendMessage), object: nil)
         
         if dataMessageForward != nil {
             for i in 0..<dataMessageForward!.count {
@@ -1654,6 +1655,35 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         }
     }
     
+    @objc func onFailedSendMessage(notification: NSNotification) {
+        DispatchQueue.main.async {
+            let data:[AnyHashable : Any] = notification.userInfo!
+            let messageId = data["message_id"] as! String
+            let status = data["status"] as! String
+            
+            var idx = self.dataMessages.firstIndex(where: { $0["message_id"] as? String ?? "" == messageId })
+            if let idxMessageIdParent = self.groupImages.firstIndex(where: { $0.value.contains(where: { $0.messageId == messageId }) }) {
+                if let idxInImages = self.groupImages[idxMessageIdParent].value.firstIndex(where: { $0.messageId == messageId }) {
+                    self.groupImages[idxMessageIdParent].value[idxInImages].status = status
+                    self.groupImages[idxMessageIdParent].value[idxInImages].dataMessage["status"] = status
+                }
+                idx = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == self.groupImages[idxMessageIdParent].key })
+            }
+            
+            if (idx != nil) {
+                do {
+                    self.dataMessages[idx!]["status"] = status
+                    let section = self.dataDates.firstIndex(of: self.dataMessages[idx!]["chat_date"] as! String)
+                    let row = self.dataMessages.filter({ $0["chat_date"] as! String == self.dataMessages[idx!]["chat_date"] as! String}).firstIndex(where: { $0["message_id"] as? String == self.dataMessages[idx!]["message_id"] as? String })
+                    if row != nil && section != nil  {
+                        self.tableChatView.reloadRows(at: [IndexPath(row: row!, section: section!)], with: .none)
+                    }
+                } catch {
+                }
+            }
+        }
+    }
+    
     private func updateStatusDelete(idx: Int?, chatData: [String: String]) {
         do {
             if self.dataMessages[idx!]["lock"] as! String == "1" {
@@ -4657,7 +4687,9 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                 statusMessage.trailingAnchor.constraint(equalTo: containerMessage.leadingAnchor, constant: -8).isActive = true
                 statusMessage.widthAnchor.constraint(equalToConstant: 15).isActive = true
                 statusMessage.heightAnchor.constraint(equalToConstant: 15).isActive = true
-                if dataMessages[indexPath.row]["status"]! as! String == "1" {
+                if dataMessages[indexPath.row]["status"]! as! String == "0" {
+                    statusMessage.image = UIImage(systemName: "xmark.circle")!.withTintColor(UIColor.red, renderingMode: .alwaysOriginal)
+                } else if dataMessages[indexPath.row]["status"]! as! String == "1" {
                     statusMessage.image = UIImage(systemName: "clock.arrow.circlepath")!.withTintColor(UIColor.lightGray, renderingMode: .alwaysOriginal)
                 } else if (dataMessages[indexPath.row]["status"]! as! String == "2" ) {
                     statusMessage.image = UIImage(named: "checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)
@@ -5062,7 +5094,9 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                         let statusInImage = UIImageView()
                         containerTimeStatus.addSubview(statusInImage)
                         statusInImage.anchor(right: containerTimeStatus.rightAnchor, centerY: containerTimeStatus.centerYAnchor, width: 15, height: 15)
-                        if listImages[i].status == "1" {
+                        if listImages[i].status == "0" {
+                            statusMessage.image = UIImage(systemName: "xmark.circle")!.withTintColor(UIColor.red, renderingMode: .alwaysOriginal)
+                        } else if listImages[i].status == "1" {
                             statusInImage.image = UIImage(systemName: "clock.arrow.circlepath")!.withTintColor(UIColor.white, renderingMode: .alwaysOriginal)
                         } else if listImages[i].status == "2"  {
                             statusInImage.image = UIImage(named: "checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.white)

+ 5 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ContactChatViewController.swift

@@ -1074,7 +1074,11 @@ extension ContactChatViewController {
                         } else {
                             let imageStatus = NSTextAttachment()
                             let status = getRealStatus(messageId: data.messageId)
-                            if (status == "1" || status == "2" ) {
+                            if status == "0" {
+                                imageStatus.image = UIImage(systemName: "xmark.circle")!.withTintColor(UIColor.red, renderingMode: .alwaysOriginal)
+                            } else if status == "1" {
+                                imageStatus.image = UIImage(systemName: "clock.arrow.circlepath")!.withTintColor(UIColor.lightGray, renderingMode: .alwaysOriginal)
+                            } else if status == "2" {
                                 imageStatus.image = UIImage(named: "checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)
                             } else if (status == "3") {
                                 imageStatus.image = UIImage(named: "double-checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)