浏览代码

add action in view grouping image

alqindiirsyam 2 年之前
父节点
当前提交
76750085f5

+ 3 - 2
appbuilder-ios/DigiXLite/DigiXLite.podspec

@@ -8,7 +8,7 @@
 
 
 Pod::Spec.new do |spec|
 Pod::Spec.new do |spec|
   spec.name         = "DigiXLite"
   spec.name         = "DigiXLite"
-  spec.version      = "2.2.3"
+  spec.version      = "2.2.1"
   spec.summary      = "DigiXLite Framework"
   spec.summary      = "DigiXLite Framework"
   spec.description  = <<-DESC
   spec.description  = <<-DESC
   DigiXLite Framework, embed Contact Center, Live Streaming, Push Notifications, Instant Messaging, Video and VoIP Calling features into your mobile apps within minutes...
   DigiXLite Framework, embed Contact Center, Live Streaming, Push Notifications, Instant Messaging, Video and VoIP Calling features into your mobile apps within minutes...
@@ -18,7 +18,7 @@ Pod::Spec.new do |spec|
   spec.license      = "MIT"
   spec.license      = "MIT"
   spec.author       = { "Yayan D Wicaksono" => "ya2n.wicaksono@gmail.com" }
   spec.author       = { "Yayan D Wicaksono" => "ya2n.wicaksono@gmail.com" }
   spec.ios.deployment_target = "14.0"
   spec.ios.deployment_target = "14.0"
-#  spec.source       = { :http => 'https://newuniverse.io/UCPaaSiOS/releases/download/DigiXLite/v2.2.3/DigiXLite.zip' }
+#  spec.source       = { :http => 'https://newuniverse.io/UCPaaSiOS/releases/download/DigiXLite/v2.2.1/DigiXLite.zip' }
   spec.source       = { :path => '.' }
   spec.source       = { :path => '.' }
   spec.source_files = 'DigiXLite/Source/**/*'
   spec.source_files = 'DigiXLite/Source/**/*'
   spec.resource_bundles = { 'DigiXLite' => ['DigiXLite/Resource/**/*']}
   spec.resource_bundles = { 'DigiXLite' => ['DigiXLite/Resource/**/*']}
@@ -31,6 +31,7 @@ Pod::Spec.new do |spec|
   spec.dependency 'Toast-Swift', '~> 5.0.1'
   spec.dependency 'Toast-Swift', '~> 5.0.1'
   spec.dependency 'ZIPFoundation', '~> 0.9.16'
   spec.dependency 'ZIPFoundation', '~> 0.9.16'
   spec.dependency 'SwiftLinkPreview', '~> 3.4.0'
   spec.dependency 'SwiftLinkPreview', '~> 3.4.0'
+  spec.dependency 'Popover'
 # spec.dependency 'iOS-WebP'
 # spec.dependency 'iOS-WebP'
 #  spec.preserve_path = 'DigiXLite.framework'
 #  spec.preserve_path = 'DigiXLite.framework'
 #  spec.xcconfig = { 'OTHER_LDFLAGS' => '-framework DigiXLite' }
 #  spec.xcconfig = { 'OTHER_LDFLAGS' => '-framework DigiXLite' }

+ 1 - 1
appbuilder-ios/DigiXLite/DigiXLite.xcodeproj/xcuserdata/akhmadalqindiirsyam.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -12,7 +12,7 @@
 		<key>DigiXLiteResources.xcscheme_^#shared#^_</key>
 		<key>DigiXLiteResources.xcscheme_^#shared#^_</key>
 		<dict>
 		<dict>
 			<key>orderHint</key>
 			<key>orderHint</key>
-			<integer>14</integer>
+			<integer>15</integer>
 		</dict>
 		</dict>
 		<key>NexilisLiteResources.xcscheme_^#shared#^_</key>
 		<key>NexilisLiteResources.xcscheme_^#shared#^_</key>
 		<dict>
 		<dict>

二进制
appbuilder-ios/DigiXLite/DigiXLite.xcworkspace/xcuserdata/akhmadalqindiirsyam.xcuserdatad/UserInterfaceState.xcuserstate


+ 17 - 3
appbuilder-ios/DigiXLite/DigiXLite/Source/View/Chat/EditorPersonal.swift

@@ -1129,7 +1129,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         }
                         }
                     }
                     }
                     if row["image_id"] != nil && !(row["image_id"] as! String).isEmpty && (row["message_text"] as! String).isEmpty && (row["reff_id"] as! String).isEmpty && (row["credential"] as! String) != "1" && (row["read_receipts"] as! String) != "8" {
                     if row["image_id"] != nil && !(row["image_id"] as! String).isEmpty && (row["message_text"] as! String).isEmpty && (row["reff_id"] as! String).isEmpty && (row["credential"] as! String) != "1" && (row["read_receipts"] as! String) != "8" {
-                        tempImages.append(ImageGrouping(messageId: row["message_id"] as! String, thumbId: row["thumb_id"] as! String, imageId: row["image_id"] as! String, status: row["status"] as! String, time: row["server_date"] as! String, lPin: row["l_pin"] as! String))
+                        tempImages.append(ImageGrouping(messageId: row["message_id"] as! String, thumbId: row["thumb_id"] as! String, imageId: row["image_id"] as! String, status: row["status"] as! String, time: row["server_date"] as! String, lPin: row["l_pin"] as! String, dataMessage: row, dataPerson: dataPerson))
                     } else if tempImages.count >= 4 {
                     } else if tempImages.count >= 4 {
                         groupImages[tempImages[0].messageId] = tempImages
                         groupImages[tempImages[0].messageId] = tempImages
                         var tempDataOnGrouping: [[String: Any?]] =  []
                         var tempDataOnGrouping: [[String: Any?]] =  []
@@ -3789,11 +3789,20 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
             }
             }
             cancelAction()
             cancelAction()
         } else if forwardSession {
         } else if forwardSession {
-            let dataMessages = self.dataMessages.filter({ $0["isSelected"] as! Bool == true })
+            var dataMessages = self.dataMessages.filter({ $0["isSelected"] as! Bool == true })
             let countSelected = dataMessages.count
             let countSelected = dataMessages.count
             if countSelected == 0 {
             if countSelected == 0 {
                 return
                 return
             }
             }
+            for i in 0..<countSelected {
+                if let groupingImages = groupImages[dataMessages[i]["message_id"] as! String] {
+                    var tempData = dataMessages
+                    tempData.remove(at: i)
+                    tempData.insert(contentsOf: dataMessagesOnGrouping[dataMessages[i]["message_id"] as! String]!, at: i)
+                    tempData.insert(dataMessages[i], at: i)
+                    dataMessages = tempData
+                }
+            }
             contactChatNav.modalPresentationStyle = .custom
             contactChatNav.modalPresentationStyle = .custom
             contactChatNav.navigationBar.tintColor = .white
             contactChatNav.navigationBar.tintColor = .white
             contactChatNav.navigationBar.barTintColor = .mainColor
             contactChatNav.navigationBar.barTintColor = .mainColor
@@ -6315,13 +6324,18 @@ public class ImageGrouping {
     public var status = ""
     public var status = ""
     public var time = ""
     public var time = ""
     public var lPin = ""
     public var lPin = ""
+    public var dataMessage: [String: Any?] = [:]
+    public var dataPerson: [String: String?] = [:]
     
     
-    public init(messageId: String, thumbId: String, imageId: String, status: String, time: String, lPin: String) {
+    public init(messageId: String, thumbId: String, imageId: String, status: String, time: String, lPin: String, dataMessage: [String: Any?], dataPerson: [String: String?]) {
         self.messageId = messageId
         self.messageId = messageId
         self.thumbId = thumbId
         self.thumbId = thumbId
         self.imageId = imageId
         self.imageId = imageId
         self.status = status
         self.status = status
         self.time = time
         self.time = time
         self.lPin = lPin
         self.lPin = lPin
+        self.dataMessage = dataMessage
+        self.dataPerson = dataPerson
     }
     }
 }
 }
+

+ 120 - 1
appbuilder-ios/DigiXLite/DigiXLite/Source/View/Chat/ListGroupImages.swift

@@ -6,6 +6,7 @@
 //
 //
 
 
 import UIKit
 import UIKit
+import Popover
 
 
 class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDelegate {
 class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDelegate {
     var listGroupingImages: [ImageGrouping]!
     var listGroupingImages: [ImageGrouping]!
@@ -13,6 +14,14 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
     var titleName: String!
     var titleName: String!
     let tableViewImages = UITableView()
     let tableViewImages = UITableView()
     var isInitiator = false
     var isInitiator = false
+    var copySession = false
+    var forwardSession = false
+    var deleteSession = false
+    var tableViewPopOver = UITableView()
+    var popover: Popover!
+    var startYVisible: CGFloat!
+    var endYVisible: CGFloat!
+    var indexSelected = 0
 
 
     override func viewDidLoad() {
     override func viewDidLoad() {
         super.viewDidLoad()
         super.viewDidLoad()
@@ -31,7 +40,9 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
         self.view.addSubview(tableViewImages)
         self.view.addSubview(tableViewImages)
         tableViewImages.anchor(top: self.view.safeAreaLayoutGuide.topAnchor, left: self.view.safeAreaLayoutGuide.leftAnchor, bottom: self.view.safeAreaLayoutGuide.bottomAnchor, right: self.view.safeAreaLayoutGuide.rightAnchor)
         tableViewImages.anchor(top: self.view.safeAreaLayoutGuide.topAnchor, left: self.view.safeAreaLayoutGuide.leftAnchor, bottom: self.view.safeAreaLayoutGuide.bottomAnchor, right: self.view.safeAreaLayoutGuide.rightAnchor)
         
         
-        tableViewImages.scrollToRow(at: IndexPath(row: imageTapped, section: 0), at: .top, animated: false)
+        DispatchQueue.main.async {[self] in
+            tableViewImages.scrollToRow(at: IndexPath(row: imageTapped, section: 0), at: .top, animated: false)
+        }
         
         
         let center: NotificationCenter = NotificationCenter.default
         let center: NotificationCenter = NotificationCenter.default
         center.addObserver(self, selector: #selector(onStatusChat(notification:)), name: NSNotification.Name(rawValue: DigiX.listenerStatusChat), object: nil)
         center.addObserver(self, selector: #selector(onStatusChat(notification:)), name: NSNotification.Name(rawValue: DigiX.listenerStatusChat), object: nil)
@@ -52,10 +63,38 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
     }
     }
     
     
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        if tableView == tableViewPopOver {
+            return 5
+        }
         return listGroupingImages.count
         return listGroupingImages.count
     }
     }
     
     
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        if tableView == tableViewPopOver {
+            let cell = tableView.dequeueReusableCell(withIdentifier: "cellPopOver", for: indexPath as IndexPath)
+            var content = cell.defaultContentConfiguration()
+            content.textProperties.font = UIFont.systemFont(ofSize: 14)
+            content.imageProperties.tintColor = .black
+            switch indexPath.row {
+            case 0:
+                content.image = UIImage(systemName: "star.fill")
+                content.text = "Star".localized()
+            case 1:
+                content.image = UIImage(systemName: "arrowshape.turn.up.left.fill")
+                content.text = "Reply".localized()
+            case 2:
+                content.image = UIImage(systemName: "arrowshape.turn.up.right.fill")
+                content.text = "Forward".localized()
+            case 3:
+                content.image = UIImage(systemName: "info.circle.fill")
+                content.text = "Info".localized()
+            default:
+                content.image = UIImage(systemName: "trash.fill")
+                content.text = "Delete".localized()
+            }
+            cell.contentConfiguration = content
+            return cell
+        }
         let cell = tableView.dequeueReusableCell(withIdentifier: "cellGrupingImages", for: indexPath as IndexPath)
         let cell = tableView.dequeueReusableCell(withIdentifier: "cellGrupingImages", for: indexPath as IndexPath)
         cell.contentView.subviews.forEach({ $0.removeFromSuperview() })
         cell.contentView.subviews.forEach({ $0.removeFromSuperview() })
         cell.backgroundColor = .clear
         cell.backgroundColor = .clear
@@ -65,6 +104,14 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
         cell.contentView.addSubview(containerImages)
         cell.contentView.addSubview(containerImages)
         containerImages.anchor(top: cell.contentView.topAnchor, left: cell.contentView.leftAnchor, bottom: cell.contentView.bottomAnchor, right: cell.contentView.rightAnchor, paddingBottom: 15, height: UIScreen.main.bounds.height - 104)
         containerImages.anchor(top: cell.contentView.topAnchor, left: cell.contentView.leftAnchor, bottom: cell.contentView.bottomAnchor, right: cell.contentView.rightAnchor, paddingBottom: 15, height: UIScreen.main.bounds.height - 104)
         
         
+        if !copySession && !forwardSession && !deleteSession {
+            let longPressRecognizer = LongPressImageVIew(target: self, action: #selector(handleLongPress(_:)))
+            longPressRecognizer.imageView = containerImages
+            longPressRecognizer.index = indexPath.row
+            containerImages.isUserInteractionEnabled = true
+            containerImages.addGestureRecognizer(longPressRecognizer)
+        }
+        
         let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
         let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
         let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
         let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
         let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
         let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -118,6 +165,73 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
         }
         }
         return cell
         return cell
     }
     }
+    
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        if tableView == tableViewPopOver {
+            popover.dismiss()
+            switch indexPath.row {
+            case 0:
+                popover.dismiss()
+            case 1:
+                popover.dismiss()
+            case 2:
+                popover.dismiss()
+            case 3:
+                popover.dismiss()
+                let messageInfoVC = MessageInfo()
+                messageInfoVC.data = listGroupingImages[indexSelected].dataMessage
+                messageInfoVC.dataPerson = listGroupingImages[indexPath.row].dataPerson
+                self.navigationController?.pushViewController(messageInfoVC, animated: true)
+            default :
+                popover.dismiss()
+            }
+        }
+    }
+    
+    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        let visibleRect = CGRect(origin: scrollView.contentOffset, size: scrollView.bounds.size)
+        let visibleTableViewRect = tableViewImages.convert(visibleRect, from: tableViewImages)
+
+        let startY = visibleTableViewRect.origin.y
+        let endY = startY + visibleTableViewRect.size.height
+        startYVisible = startY
+        endYVisible = endY
+    }
+    
+    @objc func handleLongPress(_ gestureRecognizer: LongPressImageVIew) {
+        if gestureRecognizer.state == .began {
+            indexSelected = gestureRecognizer.index
+            let contentOffset = tableViewImages.contentOffset
+            let location = gestureRecognizer.location(in: tableViewImages)
+            let xTouch = location.x - contentOffset.x
+            var yTouch = location.y - contentOffset.y + 100
+            
+            let boundary = startYVisible != nil ? (endYVisible - startYVisible) / 2 - 50 : (UIScreen.main.bounds.height - 64) / 2 - 50
+            let yTouchDiff = startYVisible != nil ? location.y - startYVisible : location.y - 0.0
+            
+            tableViewPopOver = UITableView(frame: CGRect(x: 0, y: 10, width: 140, height: 220))
+            popover = Popover()
+            if yTouchDiff >= boundary {
+                yTouch = location.y - contentOffset.y + 20
+                tableViewPopOver = UITableView(frame: CGRect(x: 0, y: 0, width: 140, height: 220))
+                popover.popoverType = .up
+            }
+            
+            tableViewPopOver.register(UITableViewCell.self, forCellReuseIdentifier: "cellPopOver")
+            tableViewPopOver.dataSource = self
+            tableViewPopOver.delegate = self
+            tableViewPopOver.layoutMargins = UIEdgeInsets.zero
+            tableViewPopOver.separatorInset = UIEdgeInsets.zero
+            tableViewPopOver.isScrollEnabled = false
+            
+            let viewTable = UITableView(frame: CGRect(x: 0, y: 0, width: 140, height: 220))
+            viewTable.addSubview(tableViewPopOver)
+            
+            let touchPoint = CGPoint( x: xTouch, y: yTouch)
+            popover.show(viewTable, point: touchPoint)
+            UINotificationFeedbackGenerator().notificationOccurred(.success)
+        }
+    }
 }
 }
 
 
 class CenteredTitleSubtitleView: UIView {
 class CenteredTitleSubtitleView: UIView {
@@ -162,3 +276,8 @@ class CenteredTitleSubtitleView: UIView {
         subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor).isActive = true
         subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor).isActive = true
     }
     }
 }
 }
+
+class LongPressImageVIew: UILongPressGestureRecognizer {
+    var imageView = UIImageView()
+    var index = 0
+}

+ 2 - 1
appbuilder-ios/DigiXLite/DigiXLite/Source/View/Chat/MessageInfo.swift

@@ -700,7 +700,8 @@ class MessageInfo: UIViewController, UITableViewDelegate, UITableViewDataSource
                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                 if let dirPath = paths.first {
                 if let dirPath = paths.first {
                     let thumbURL = URL(fileURLWithPath: dirPath).appendingPathComponent(thumbChat)
                     let thumbURL = URL(fileURLWithPath: dirPath).appendingPathComponent(thumbChat)
-                    let image    = UIImage(contentsOfFile: thumbURL.path)
+//                    let image    = UIImage(contentsOfFile: thumbURL.path)
+                    let image = UIGraphicsRenderer.renderImageAt(url: thumbURL as NSURL, size: CGSize(width: 250, height: 250))
                     imageThumb.image = image
                     imageThumb.image = image
                     
                     
                     let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(videoChat)
                     let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(videoChat)

+ 1 - 0
appbuilder-ios/DigiXLite/Podfile

@@ -15,6 +15,7 @@ target 'DigiXLite' do
   pod 'Toast-Swift', '~> 5.0.1'
   pod 'Toast-Swift', '~> 5.0.1'
   pod 'ZIPFoundation', '~> 0.9.16'
   pod 'ZIPFoundation', '~> 0.9.16'
   pod 'SwiftLinkPreview', '~> 3.4.0'
   pod 'SwiftLinkPreview', '~> 3.4.0'
+  pod 'Popover'
 
 
   target 'DigiXLiteTests' do
   target 'DigiXLiteTests' do
     # Pods for testing
     # Pods for testing

+ 3 - 2
appbuilder-ios/NexilisLite/NexilisLite.podspec

@@ -8,7 +8,7 @@
 
 
 Pod::Spec.new do |spec|
 Pod::Spec.new do |spec|
   spec.name         = "NexilisLite"
   spec.name         = "NexilisLite"
-  spec.version      = "2.2.3"
+  spec.version      = "2.2.1"
   spec.summary      = "NexilisLite Framework"
   spec.summary      = "NexilisLite Framework"
   spec.description  = <<-DESC
   spec.description  = <<-DESC
   NexilisLite Framework, embed Contact Center, Live Streaming, Push Notifications, Instant Messaging, Video and VoIP Calling features into your mobile apps within minutes...
   NexilisLite Framework, embed Contact Center, Live Streaming, Push Notifications, Instant Messaging, Video and VoIP Calling features into your mobile apps within minutes...
@@ -18,7 +18,7 @@ Pod::Spec.new do |spec|
   spec.license      = "MIT"
   spec.license      = "MIT"
   spec.author       = { "Yayan D Wicaksono" => "ya2n.wicaksono@gmail.com" }
   spec.author       = { "Yayan D Wicaksono" => "ya2n.wicaksono@gmail.com" }
   spec.ios.deployment_target = "14.0"
   spec.ios.deployment_target = "14.0"
-#  spec.source       = { :http => 'https://newuniverse.io/UCPaaSiOS/releases/download/NexilisLiteiOS/v2.2.3/NexilisLite.zip' }
+#  spec.source       = { :http => 'https://newuniverse.io/UCPaaSiOS/releases/download/NexilisLite/v2.2.1/NexilisLite.zip' }
   spec.source       = { :path => '.' }
   spec.source       = { :path => '.' }
   spec.source_files = 'NexilisLite/Source/**/*'
   spec.source_files = 'NexilisLite/Source/**/*'
   spec.resource_bundles = { 'NexilisLite' => ['NexilisLite/Resource/**/*']}
   spec.resource_bundles = { 'NexilisLite' => ['NexilisLite/Resource/**/*']}
@@ -31,6 +31,7 @@ Pod::Spec.new do |spec|
   spec.dependency 'Toast-Swift', '~> 5.0.1'
   spec.dependency 'Toast-Swift', '~> 5.0.1'
   spec.dependency 'ZIPFoundation', '~> 0.9.16'
   spec.dependency 'ZIPFoundation', '~> 0.9.16'
   spec.dependency 'SwiftLinkPreview', '~> 3.4.0'
   spec.dependency 'SwiftLinkPreview', '~> 3.4.0'
+  spec.dependency 'Popover'
 # spec.dependency 'iOS-WebP'
 # spec.dependency 'iOS-WebP'
 #  spec.preserve_path = 'NexilisLite.framework'
 #  spec.preserve_path = 'NexilisLite.framework'
 #  spec.xcconfig = { 'OTHER_LDFLAGS' => '-framework NexilisLite' }
 #  spec.xcconfig = { 'OTHER_LDFLAGS' => '-framework NexilisLite' }

+ 37 - 33
appbuilder-ios/NexilisLite/NexilisLite.xcodeproj/project.pbxproj

@@ -85,7 +85,6 @@
 		CD1E724E2A0BA86100BF871F /* VerifyEmail.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A02A0BA86100BF871F /* VerifyEmail.swift */; };
 		CD1E724E2A0BA86100BF871F /* VerifyEmail.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A02A0BA86100BF871F /* VerifyEmail.swift */; };
 		CD1E724F2A0BA86100BF871F /* SetInternalCSAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A12A0BA86100BF871F /* SetInternalCSAccount.swift */; };
 		CD1E724F2A0BA86100BF871F /* SetInternalCSAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A12A0BA86100BF871F /* SetInternalCSAccount.swift */; };
 		CD1E72502A0BA86100BF871F /* BroadcastVariantViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A22A0BA86100BF871F /* BroadcastVariantViewController.swift */; };
 		CD1E72502A0BA86100BF871F /* BroadcastVariantViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A22A0BA86100BF871F /* BroadcastVariantViewController.swift */; };
-		CD1E72512A0BA86100BF871F /* MessageInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A32A0BA86100BF871F /* MessageInfo.swift */; };
 		CD1E72522A0BA86100BF871F /* ImageVideoPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A42A0BA86100BF871F /* ImageVideoPicker.swift */; };
 		CD1E72522A0BA86100BF871F /* ImageVideoPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A42A0BA86100BF871F /* ImageVideoPicker.swift */; };
 		CD1E72532A0BA86100BF871F /* BackupRestoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A52A0BA86100BF871F /* BackupRestoreView.swift */; };
 		CD1E72532A0BA86100BF871F /* BackupRestoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A52A0BA86100BF871F /* BackupRestoreView.swift */; };
 		CD1E72542A0BA86100BF871F /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A62A0BA86100BF871F /* ProfileViewController.swift */; };
 		CD1E72542A0BA86100BF871F /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E71A62A0BA86100BF871F /* ProfileViewController.swift */; };
@@ -187,6 +186,8 @@
 		CD46A0BB2A0CE320009E4C87 /* sticker_10000000_8.png in Resources */ = {isa = PBXBuildFile; fileRef = CD46A0162A0CE2DE009E4C87 /* sticker_10000000_8.png */; };
 		CD46A0BB2A0CE320009E4C87 /* sticker_10000000_8.png in Resources */ = {isa = PBXBuildFile; fileRef = CD46A0162A0CE2DE009E4C87 /* sticker_10000000_8.png */; };
 		CD46A0BF2A0CE4FD009E4C87 /* NexilisLite.podspec in Resources */ = {isa = PBXBuildFile; fileRef = CD46A0BE2A0CE4FD009E4C87 /* NexilisLite.podspec */; };
 		CD46A0BF2A0CE4FD009E4C87 /* NexilisLite.podspec in Resources */ = {isa = PBXBuildFile; fileRef = CD46A0BE2A0CE4FD009E4C87 /* NexilisLite.podspec */; };
 		CD46A0C52A0D0D5D009E4C87 /* MyArchive.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD46A0C42A0D0D5D009E4C87 /* MyArchive.swift */; };
 		CD46A0C52A0D0D5D009E4C87 /* MyArchive.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD46A0C42A0D0D5D009E4C87 /* MyArchive.swift */; };
+		CD5A73AE2A77642D000541A5 /* MessageInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD5A73AC2A77642D000541A5 /* MessageInfo.swift */; };
+		CD5A73AF2A77642D000541A5 /* ListGroupImages.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD5A73AD2A77642D000541A5 /* ListGroupImages.swift */; };
 		CD9551592A664BDA00AF6476 /* Poppins-LightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD9551402A664BD400AF6476 /* Poppins-LightItalic.otf */; };
 		CD9551592A664BDA00AF6476 /* Poppins-LightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD9551402A664BD400AF6476 /* Poppins-LightItalic.otf */; };
 		CD95515A2A664BDA00AF6476 /* Poppins-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD95513F2A664BD400AF6476 /* Poppins-MediumItalic.otf */; };
 		CD95515A2A664BDA00AF6476 /* Poppins-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD95513F2A664BD400AF6476 /* Poppins-MediumItalic.otf */; };
 		CD95515B2A664BDA00AF6476 /* Poppins-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD9551412A664BD400AF6476 /* Poppins-Bold.otf */; };
 		CD95515B2A664BDA00AF6476 /* Poppins-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD9551412A664BD400AF6476 /* Poppins-Bold.otf */; };
@@ -330,7 +331,6 @@
 		CD1E71A02A0BA86100BF871F /* VerifyEmail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerifyEmail.swift; sourceTree = "<group>"; };
 		CD1E71A02A0BA86100BF871F /* VerifyEmail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerifyEmail.swift; sourceTree = "<group>"; };
 		CD1E71A12A0BA86100BF871F /* SetInternalCSAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetInternalCSAccount.swift; sourceTree = "<group>"; };
 		CD1E71A12A0BA86100BF871F /* SetInternalCSAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetInternalCSAccount.swift; sourceTree = "<group>"; };
 		CD1E71A22A0BA86100BF871F /* BroadcastVariantViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BroadcastVariantViewController.swift; sourceTree = "<group>"; };
 		CD1E71A22A0BA86100BF871F /* BroadcastVariantViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BroadcastVariantViewController.swift; sourceTree = "<group>"; };
-		CD1E71A32A0BA86100BF871F /* MessageInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageInfo.swift; sourceTree = "<group>"; };
 		CD1E71A42A0BA86100BF871F /* ImageVideoPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageVideoPicker.swift; sourceTree = "<group>"; };
 		CD1E71A42A0BA86100BF871F /* ImageVideoPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageVideoPicker.swift; sourceTree = "<group>"; };
 		CD1E71A52A0BA86100BF871F /* BackupRestoreView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackupRestoreView.swift; sourceTree = "<group>"; };
 		CD1E71A52A0BA86100BF871F /* BackupRestoreView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackupRestoreView.swift; sourceTree = "<group>"; };
 		CD1E71A62A0BA86100BF871F /* ProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
 		CD1E71A62A0BA86100BF871F /* ProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
@@ -440,6 +440,8 @@
 		CD46A01A2A0CE2DE009E4C87 /* Palio.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Palio.storyboard; sourceTree = "<group>"; };
 		CD46A01A2A0CE2DE009E4C87 /* Palio.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Palio.storyboard; sourceTree = "<group>"; };
 		CD46A0BE2A0CE4FD009E4C87 /* NexilisLite.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = NexilisLite.podspec; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
 		CD46A0BE2A0CE4FD009E4C87 /* NexilisLite.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = NexilisLite.podspec; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
 		CD46A0C42A0D0D5D009E4C87 /* MyArchive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyArchive.swift; sourceTree = "<group>"; };
 		CD46A0C42A0D0D5D009E4C87 /* MyArchive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyArchive.swift; sourceTree = "<group>"; };
+		CD5A73AC2A77642D000541A5 /* MessageInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageInfo.swift; sourceTree = "<group>"; };
+		CD5A73AD2A77642D000541A5 /* ListGroupImages.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListGroupImages.swift; sourceTree = "<group>"; };
 		CD9551332A664BD400AF6476 /* Poppins-SemiBoldItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-SemiBoldItalic.otf"; sourceTree = "<group>"; };
 		CD9551332A664BD400AF6476 /* Poppins-SemiBoldItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-SemiBoldItalic.otf"; sourceTree = "<group>"; };
 		CD9551342A664BD400AF6476 /* Poppins-ExtraBoldItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-ExtraBoldItalic.otf"; sourceTree = "<group>"; };
 		CD9551342A664BD400AF6476 /* Poppins-ExtraBoldItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-ExtraBoldItalic.otf"; sourceTree = "<group>"; };
 		CD9551352A664BD400AF6476 /* SIL Open Font License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "SIL Open Font License.txt"; sourceTree = "<group>"; };
 		CD9551352A664BD400AF6476 /* SIL Open Font License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "SIL Open Font License.txt"; sourceTree = "<group>"; };
@@ -649,13 +651,15 @@
 		CD1E716D2A0BA86100BF871F /* Chat */ = {
 		CD1E716D2A0BA86100BF871F /* Chat */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				CD1E716E2A0BA86100BF871F /* EditorStarMessages.swift */,
-				CD1E716F2A0BA86100BF871F /* PreviewAttachmentImageVideo.xib */,
+				CD1E71742A0BA86100BF871F /* CustomTextView.swift */,
+				CD1E71722A0BA86100BF871F /* EditorGroup.swift */,
 				CD1E71702A0BA86100BF871F /* EditorPersonal.swift */,
 				CD1E71702A0BA86100BF871F /* EditorPersonal.swift */,
+				CD1E716E2A0BA86100BF871F /* EditorStarMessages.swift */,
 				CD1E71712A0BA86100BF871F /* FormEditor.swift */,
 				CD1E71712A0BA86100BF871F /* FormEditor.swift */,
-				CD1E71722A0BA86100BF871F /* EditorGroup.swift */,
+				CD5A73AD2A77642D000541A5 /* ListGroupImages.swift */,
+				CD5A73AC2A77642D000541A5 /* MessageInfo.swift */,
 				CD1E71732A0BA86100BF871F /* PreviewAttachmentImageVideo.swift */,
 				CD1E71732A0BA86100BF871F /* PreviewAttachmentImageVideo.swift */,
-				CD1E71742A0BA86100BF871F /* CustomTextView.swift */,
+				CD1E716F2A0BA86100BF871F /* PreviewAttachmentImageVideo.xib */,
 			);
 			);
 			path = Chat;
 			path = Chat;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -699,42 +703,41 @@
 		CD1E71892A0BA86100BF871F /* Control */ = {
 		CD1E71892A0BA86100BF871F /* Control */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				CD1E718A2A0BA86100BF871F /* GroupCreateViewController.swift */,
+				CD1E71AB2A0BA86100BF871F /* AddFriendTableViewController.swift */,
+				CD1E71AD2A0BA86100BF871F /* AudienceViewController.swift */,
+				CD1E719B2A0BA86100BF871F /* BackupRestoreOption.swift */,
+				CD1E71A52A0BA86100BF871F /* BackupRestoreView.swift */,
 				CD1E718B2A0BA86100BF871F /* BroadcastMembersTableViewCell.swift */,
 				CD1E718B2A0BA86100BF871F /* BroadcastMembersTableViewCell.swift */,
-				CD1E718C2A0BA86100BF871F /* QRScannerView.swift */,
-				CD1E718D2A0BA86100BF871F /* GroupDescViewController.swift */,
-				CD1E718E2A0BA86100BF871F /* HistoryBroadcastViewController.swift */,
-				CD1E718F2A0BA86100BF871F /* CheckConnection.swift */,
-				CD1E71902A0BA86100BF871F /* SignUpSignIn.swift */,
-				CD1E71912A0BA86100BF871F /* GroupDetailViewController.swift */,
+				CD1E71A72A0BA86100BF871F /* BroadcastMembersTableViewController.swift */,
+				CD1E719A2A0BA86100BF871F /* BroadcastModeViewController.swift */,
+				CD1E71A22A0BA86100BF871F /* BroadcastVariantViewController.swift */,
+				CD1E71A82A0BA86100BF871F /* BroadcastViewController.swift */,
+				CD1E71942A0BA86100BF871F /* ChangeDeviceViewController.swift */,
 				CD1E71922A0BA86100BF871F /* ChangeNamePassswordViewController.swift */,
 				CD1E71922A0BA86100BF871F /* ChangeNamePassswordViewController.swift */,
+				CD1E719D2A0BA86100BF871F /* ChangeNameTableViewController.swift */,
+				CD1E71962A0BA86100BF871F /* ChangePasswordViewController.swift */,
+				CD1E718F2A0BA86100BF871F /* CheckConnection.swift */,
 				CD1E71932A0BA86100BF871F /* ContactChatViewController.swift */,
 				CD1E71932A0BA86100BF871F /* ContactChatViewController.swift */,
-				CD1E71942A0BA86100BF871F /* ChangeDeviceViewController.swift */,
 				CD1E71952A0BA86100BF871F /* DocumentPicker.swift */,
 				CD1E71952A0BA86100BF871F /* DocumentPicker.swift */,
-				CD1E71962A0BA86100BF871F /* ChangePasswordViewController.swift */,
+				CD1E718A2A0BA86100BF871F /* GroupCreateViewController.swift */,
+				CD1E718D2A0BA86100BF871F /* GroupDescViewController.swift */,
+				CD1E71912A0BA86100BF871F /* GroupDetailViewController.swift */,
+				CD1E71A92A0BA86100BF871F /* GroupMemberViewController.swift */,
 				CD1E71972A0BA86100BF871F /* GroupNameViewController.swift */,
 				CD1E71972A0BA86100BF871F /* GroupNameViewController.swift */,
 				CD1E71982A0BA86100BF871F /* GroupTopicViewController.swift */,
 				CD1E71982A0BA86100BF871F /* GroupTopicViewController.swift */,
-				CD1E71992A0BA86100BF871F /* SettingTableViewController.swift */,
-				CD1E719A2A0BA86100BF871F /* BroadcastModeViewController.swift */,
-				CD1E719B2A0BA86100BF871F /* BackupRestoreOption.swift */,
+				CD1E718E2A0BA86100BF871F /* HistoryBroadcastViewController.swift */,
 				CD1E719C2A0BA86100BF871F /* HistoryCCViewController.swift */,
 				CD1E719C2A0BA86100BF871F /* HistoryCCViewController.swift */,
-				CD1E719D2A0BA86100BF871F /* ChangeNameTableViewController.swift */,
-				CD1E719E2A0BA86100BF871F /* NotificationSound.swift */,
-				CD1E719F2A0BA86100BF871F /* TypeViewController.swift */,
-				CD1E71A02A0BA86100BF871F /* VerifyEmail.swift */,
-				CD1E71A12A0BA86100BF871F /* SetInternalCSAccount.swift */,
-				CD1E71A22A0BA86100BF871F /* BroadcastVariantViewController.swift */,
-				CD1E71A32A0BA86100BF871F /* MessageInfo.swift */,
 				CD1E71A42A0BA86100BF871F /* ImageVideoPicker.swift */,
 				CD1E71A42A0BA86100BF871F /* ImageVideoPicker.swift */,
-				CD1E71A52A0BA86100BF871F /* BackupRestoreView.swift */,
+				CD1E719E2A0BA86100BF871F /* NotificationSound.swift */,
 				CD1E71A62A0BA86100BF871F /* ProfileViewController.swift */,
 				CD1E71A62A0BA86100BF871F /* ProfileViewController.swift */,
-				CD1E71A72A0BA86100BF871F /* BroadcastMembersTableViewController.swift */,
-				CD1E71A82A0BA86100BF871F /* BroadcastViewController.swift */,
-				CD1E71A92A0BA86100BF871F /* GroupMemberViewController.swift */,
-				CD1E71AA2A0BA86100BF871F /* SetOfficerBNI.swift */,
-				CD1E71AB2A0BA86100BF871F /* AddFriendTableViewController.swift */,
+				CD1E718C2A0BA86100BF871F /* QRScannerView.swift */,
 				CD1E71AC2A0BA86100BF871F /* ScannerViewController.swift */,
 				CD1E71AC2A0BA86100BF871F /* ScannerViewController.swift */,
-				CD1E71AD2A0BA86100BF871F /* AudienceViewController.swift */,
+				CD1E71A12A0BA86100BF871F /* SetInternalCSAccount.swift */,
+				CD1E71AA2A0BA86100BF871F /* SetOfficerBNI.swift */,
+				CD1E71992A0BA86100BF871F /* SettingTableViewController.swift */,
+				CD1E71902A0BA86100BF871F /* SignUpSignIn.swift */,
+				CD1E719F2A0BA86100BF871F /* TypeViewController.swift */,
+				CD1E71A02A0BA86100BF871F /* VerifyEmail.swift */,
 			);
 			);
 			path = Control;
 			path = Control;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -1171,12 +1174,12 @@
 			files = (
 			files = (
 				CD1E72272A0BA86100BF871F /* QmeraStreamingViewController.swift in Sources */,
 				CD1E72272A0BA86100BF871F /* QmeraStreamingViewController.swift in Sources */,
 				CD1E72522A0BA86100BF871F /* ImageVideoPicker.swift in Sources */,
 				CD1E72522A0BA86100BF871F /* ImageVideoPicker.swift in Sources */,
-				CD1E72512A0BA86100BF871F /* MessageInfo.swift in Sources */,
 				CD1E724E2A0BA86100BF871F /* VerifyEmail.swift in Sources */,
 				CD1E724E2A0BA86100BF871F /* VerifyEmail.swift in Sources */,
 				CDDF46762A2DD81300049A19 /* SeminarViewController.swift in Sources */,
 				CDDF46762A2DD81300049A19 /* SeminarViewController.swift in Sources */,
 				CD1E721A2A0BA86100BF871F /* NotifSound.swift in Sources */,
 				CD1E721A2A0BA86100BF871F /* NotifSound.swift in Sources */,
 				CD1E724F2A0BA86100BF871F /* SetInternalCSAccount.swift in Sources */,
 				CD1E724F2A0BA86100BF871F /* SetInternalCSAccount.swift in Sources */,
 				CD1E721C2A0BA86100BF871F /* ContactCallViewController.swift in Sources */,
 				CD1E721C2A0BA86100BF871F /* ContactCallViewController.swift in Sources */,
+				CD5A73AE2A77642D000541A5 /* MessageInfo.swift in Sources */,
 				CD1E723B2A0BA86100BF871F /* GroupDescViewController.swift in Sources */,
 				CD1E723B2A0BA86100BF871F /* GroupDescViewController.swift in Sources */,
 				CD1E725C2A0BA86100BF871F /* Utils.swift in Sources */,
 				CD1E725C2A0BA86100BF871F /* Utils.swift in Sources */,
 				CD1E72232A0BA86100BF871F /* EditorGroup.swift in Sources */,
 				CD1E72232A0BA86100BF871F /* EditorGroup.swift in Sources */,
@@ -1211,6 +1214,7 @@
 				CD1E724A2A0BA86100BF871F /* HistoryCCViewController.swift in Sources */,
 				CD1E724A2A0BA86100BF871F /* HistoryCCViewController.swift in Sources */,
 				CD1E722A2A0BA86100BF871F /* StreamingViewController.swift in Sources */,
 				CD1E722A2A0BA86100BF871F /* StreamingViewController.swift in Sources */,
 				CD1E72132A0BA86100BF871F /* Database.swift in Sources */,
 				CD1E72132A0BA86100BF871F /* Database.swift in Sources */,
+				CD5A73AF2A77642D000541A5 /* ListGroupImages.swift in Sources */,
 				CD1E720F2A0BA86100BF871F /* Download.swift in Sources */,
 				CD1E720F2A0BA86100BF871F /* Download.swift in Sources */,
 				CD1E725D2A0BA86100BF871F /* WhiteboardDelegate.swift in Sources */,
 				CD1E725D2A0BA86100BF871F /* WhiteboardDelegate.swift in Sources */,
 				CD1E721B2A0BA86100BF871F /* Nexilis.swift in Sources */,
 				CD1E721B2A0BA86100BF871F /* Nexilis.swift in Sources */,

+ 16 - 3
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -1130,7 +1130,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         }
                         }
                     }
                     }
                     if row["image_id"] != nil && !(row["image_id"] as! String).isEmpty && (row["message_text"] as! String).isEmpty && (row["reff_id"] as! String).isEmpty && (row["credential"] as! String) != "1" && (row["read_receipts"] as! String) != "8" {
                     if row["image_id"] != nil && !(row["image_id"] as! String).isEmpty && (row["message_text"] as! String).isEmpty && (row["reff_id"] as! String).isEmpty && (row["credential"] as! String) != "1" && (row["read_receipts"] as! String) != "8" {
-                        tempImages.append(ImageGrouping(messageId: row["message_id"] as! String, thumbId: row["thumb_id"] as! String, imageId: row["image_id"] as! String, status: row["status"] as! String, time: row["server_date"] as! String, lPin: row["l_pin"] as! String))
+                        tempImages.append(ImageGrouping(messageId: row["message_id"] as! String, thumbId: row["thumb_id"] as! String, imageId: row["image_id"] as! String, status: row["status"] as! String, time: row["server_date"] as! String, lPin: row["l_pin"] as! String, dataMessage: row, dataPerson: dataPerson))
                     } else if tempImages.count >= 4 {
                     } else if tempImages.count >= 4 {
                         groupImages[tempImages[0].messageId] = tempImages
                         groupImages[tempImages[0].messageId] = tempImages
                         var tempDataOnGrouping: [[String: Any?]] =  []
                         var tempDataOnGrouping: [[String: Any?]] =  []
@@ -3800,11 +3800,20 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
             }
             }
             cancelAction()
             cancelAction()
         } else if forwardSession {
         } else if forwardSession {
-            let dataMessages = self.dataMessages.filter({ $0["isSelected"] as! Bool == true })
+            var dataMessages = self.dataMessages.filter({ $0["isSelected"] as! Bool == true })
             let countSelected = dataMessages.count
             let countSelected = dataMessages.count
             if countSelected == 0 {
             if countSelected == 0 {
                 return
                 return
             }
             }
+            for i in 0..<countSelected {
+                if let groupingImages = groupImages[dataMessages[i]["message_id"] as! String] {
+                    var tempData = dataMessages
+                    tempData.remove(at: i)
+                    tempData.insert(contentsOf: dataMessagesOnGrouping[dataMessages[i]["message_id"] as! String]!, at: i)
+                    tempData.insert(dataMessages[i], at: i)
+                    dataMessages = tempData
+                }
+            }
             contactChatNav.modalPresentationStyle = .custom
             contactChatNav.modalPresentationStyle = .custom
             contactChatNav.navigationBar.tintColor = .white
             contactChatNav.navigationBar.tintColor = .white
             contactChatNav.navigationBar.barTintColor = .mainColor
             contactChatNav.navigationBar.barTintColor = .mainColor
@@ -6327,13 +6336,17 @@ public class ImageGrouping {
     public var status = ""
     public var status = ""
     public var time = ""
     public var time = ""
     public var lPin = ""
     public var lPin = ""
+    public var dataMessage: [String: Any?] = [:]
+    public var dataPerson: [String: String?] = [:]
     
     
-    public init(messageId: String, thumbId: String, imageId: String, status: String, time: String, lPin: String) {
+    public init(messageId: String, thumbId: String, imageId: String, status: String, time: String, lPin: String, dataMessage: [String: Any?], dataPerson: [String: String?]) {
         self.messageId = messageId
         self.messageId = messageId
         self.thumbId = thumbId
         self.thumbId = thumbId
         self.imageId = imageId
         self.imageId = imageId
         self.status = status
         self.status = status
         self.time = time
         self.time = time
         self.lPin = lPin
         self.lPin = lPin
+        self.dataMessage = dataMessage
+        self.dataPerson = dataPerson
     }
     }
 }
 }

+ 119 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/ListGroupImages.swift

@@ -6,6 +6,7 @@
 //
 //
 
 
 import UIKit
 import UIKit
+import Popover
 
 
 class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDelegate {
 class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDelegate {
     var listGroupingImages: [ImageGrouping]!
     var listGroupingImages: [ImageGrouping]!
@@ -13,6 +14,14 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
     var titleName: String!
     var titleName: String!
     let tableViewImages = UITableView()
     let tableViewImages = UITableView()
     var isInitiator = false
     var isInitiator = false
+    var copySession = false
+    var forwardSession = false
+    var deleteSession = false
+    var tableViewPopOver = UITableView()
+    var popover: Popover!
+    var startYVisible: CGFloat!
+    var endYVisible: CGFloat!
+    var indexSelected = 0
 
 
     override func viewDidLoad() {
     override func viewDidLoad() {
         super.viewDidLoad()
         super.viewDidLoad()
@@ -31,7 +40,9 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
         self.view.addSubview(tableViewImages)
         self.view.addSubview(tableViewImages)
         tableViewImages.anchor(top: self.view.safeAreaLayoutGuide.topAnchor, left: self.view.safeAreaLayoutGuide.leftAnchor, bottom: self.view.safeAreaLayoutGuide.bottomAnchor, right: self.view.safeAreaLayoutGuide.rightAnchor)
         tableViewImages.anchor(top: self.view.safeAreaLayoutGuide.topAnchor, left: self.view.safeAreaLayoutGuide.leftAnchor, bottom: self.view.safeAreaLayoutGuide.bottomAnchor, right: self.view.safeAreaLayoutGuide.rightAnchor)
         
         
-        tableViewImages.scrollToRow(at: IndexPath(row: imageTapped, section: 0), at: .top, animated: false)
+        DispatchQueue.main.async {[self] in
+            tableViewImages.scrollToRow(at: IndexPath(row: imageTapped, section: 0), at: .top, animated: false)
+        }
         
         
         let center: NotificationCenter = NotificationCenter.default
         let center: NotificationCenter = NotificationCenter.default
         center.addObserver(self, selector: #selector(onStatusChat(notification:)), name: NSNotification.Name(rawValue: Nexilis.listenerStatusChat), object: nil)
         center.addObserver(self, selector: #selector(onStatusChat(notification:)), name: NSNotification.Name(rawValue: Nexilis.listenerStatusChat), object: nil)
@@ -52,10 +63,38 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
     }
     }
     
     
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        if tableView == tableViewPopOver {
+            return 5
+        }
         return listGroupingImages.count
         return listGroupingImages.count
     }
     }
     
     
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        if tableView == tableViewPopOver {
+            let cell = tableView.dequeueReusableCell(withIdentifier: "cellPopOver", for: indexPath as IndexPath)
+            var content = cell.defaultContentConfiguration()
+            content.textProperties.font = UIFont.systemFont(ofSize: 14)
+            content.imageProperties.tintColor = .black
+            switch indexPath.row {
+            case 0:
+                content.image = UIImage(systemName: "star.fill")
+                content.text = "Star".localized()
+            case 1:
+                content.image = UIImage(systemName: "arrowshape.turn.up.left.fill")
+                content.text = "Reply".localized()
+            case 2:
+                content.image = UIImage(systemName: "arrowshape.turn.up.right.fill")
+                content.text = "Forward".localized()
+            case 3:
+                content.image = UIImage(systemName: "info.circle.fill")
+                content.text = "Info".localized()
+            default:
+                content.image = UIImage(systemName: "trash.fill")
+                content.text = "Delete".localized()
+            }
+            cell.contentConfiguration = content
+            return cell
+        }
         let cell = tableView.dequeueReusableCell(withIdentifier: "cellGrupingImages", for: indexPath as IndexPath)
         let cell = tableView.dequeueReusableCell(withIdentifier: "cellGrupingImages", for: indexPath as IndexPath)
         cell.contentView.subviews.forEach({ $0.removeFromSuperview() })
         cell.contentView.subviews.forEach({ $0.removeFromSuperview() })
         cell.backgroundColor = .clear
         cell.backgroundColor = .clear
@@ -65,6 +104,14 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
         cell.contentView.addSubview(containerImages)
         cell.contentView.addSubview(containerImages)
         containerImages.anchor(top: cell.contentView.topAnchor, left: cell.contentView.leftAnchor, bottom: cell.contentView.bottomAnchor, right: cell.contentView.rightAnchor, paddingBottom: 15, height: UIScreen.main.bounds.height - 104)
         containerImages.anchor(top: cell.contentView.topAnchor, left: cell.contentView.leftAnchor, bottom: cell.contentView.bottomAnchor, right: cell.contentView.rightAnchor, paddingBottom: 15, height: UIScreen.main.bounds.height - 104)
         
         
+        if !copySession && !forwardSession && !deleteSession {
+            let longPressRecognizer = LongPressImageVIew(target: self, action: #selector(handleLongPress(_:)))
+            longPressRecognizer.imageView = containerImages
+            longPressRecognizer.index = indexPath.row
+            containerImages.isUserInteractionEnabled = true
+            containerImages.addGestureRecognizer(longPressRecognizer)
+        }
+        
         let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
         let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
         let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
         let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
         let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
         let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -119,7 +166,73 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
         }
         }
         return cell
         return cell
     }
     }
+    
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        if tableView == tableViewPopOver {
+            popover.dismiss()
+            switch indexPath.row {
+            case 0:
+                popover.dismiss()
+            case 1:
+                popover.dismiss()
+            case 2:
+                popover.dismiss()
+            case 3:
+                popover.dismiss()
+                let messageInfoVC = MessageInfo()
+                messageInfoVC.data = listGroupingImages[indexSelected].dataMessage
+                messageInfoVC.dataPerson = listGroupingImages[indexPath.row].dataPerson
+                self.navigationController?.pushViewController(messageInfoVC, animated: true)
+            default :
+                popover.dismiss()
+            }
+        }
+    }
+    
+    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        let visibleRect = CGRect(origin: scrollView.contentOffset, size: scrollView.bounds.size)
+        let visibleTableViewRect = tableViewImages.convert(visibleRect, from: tableViewImages)
 
 
+        let startY = visibleTableViewRect.origin.y
+        let endY = startY + visibleTableViewRect.size.height
+        startYVisible = startY
+        endYVisible = endY
+    }
+    
+    @objc func handleLongPress(_ gestureRecognizer: LongPressImageVIew) {
+        if gestureRecognizer.state == .began {
+            indexSelected = gestureRecognizer.index
+            let contentOffset = tableViewImages.contentOffset
+            let location = gestureRecognizer.location(in: tableViewImages)
+            let xTouch = location.x - contentOffset.x
+            var yTouch = location.y - contentOffset.y + 100
+            
+            let boundary = startYVisible != nil ? (endYVisible - startYVisible) / 2 - 50 : (UIScreen.main.bounds.height - 64) / 2 - 50
+            let yTouchDiff = startYVisible != nil ? location.y - startYVisible : location.y - 0.0
+            
+            tableViewPopOver = UITableView(frame: CGRect(x: 0, y: 10, width: 140, height: 220))
+            popover = Popover()
+            if yTouchDiff >= boundary {
+                yTouch = location.y - contentOffset.y + 20
+                tableViewPopOver = UITableView(frame: CGRect(x: 0, y: 0, width: 140, height: 220))
+                popover.popoverType = .up
+            }
+            
+            tableViewPopOver.register(UITableViewCell.self, forCellReuseIdentifier: "cellPopOver")
+            tableViewPopOver.dataSource = self
+            tableViewPopOver.delegate = self
+            tableViewPopOver.layoutMargins = UIEdgeInsets.zero
+            tableViewPopOver.separatorInset = UIEdgeInsets.zero
+            tableViewPopOver.isScrollEnabled = false
+            
+            let viewTable = UITableView(frame: CGRect(x: 0, y: 0, width: 140, height: 220))
+            viewTable.addSubview(tableViewPopOver)
+            
+            let touchPoint = CGPoint( x: xTouch, y: yTouch)
+            popover.show(viewTable, point: touchPoint)
+            UINotificationFeedbackGenerator().notificationOccurred(.success)
+        }
+    }
 }
 }
 
 
 class CenteredTitleSubtitleView: UIView {
 class CenteredTitleSubtitleView: UIView {
@@ -164,3 +277,8 @@ class CenteredTitleSubtitleView: UIView {
         subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor).isActive = true
         subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor).isActive = true
     }
     }
 }
 }
+
+class LongPressImageVIew: UILongPressGestureRecognizer {
+    var imageView = UIImageView()
+    var index = 0
+}

+ 5 - 2
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/MessageInfo.swift

@@ -700,7 +700,8 @@ class MessageInfo: UIViewController, UITableViewDelegate, UITableViewDataSource
                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                 if let dirPath = paths.first {
                 if let dirPath = paths.first {
                     let thumbURL = URL(fileURLWithPath: dirPath).appendingPathComponent(thumbChat)
                     let thumbURL = URL(fileURLWithPath: dirPath).appendingPathComponent(thumbChat)
-                    let image    = UIImage(contentsOfFile: thumbURL.path)
+//                    let image    = UIImage(contentsOfFile: thumbURL.path)
+                    let image = UIGraphicsRenderer.renderImageAt(url: thumbURL as NSURL, size: CGSize(width: 250, height: 250))
                     imageThumb.image = image
                     imageThumb.image = image
                     
                     
                     let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(videoChat)
                     let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(videoChat)
@@ -1030,9 +1031,11 @@ class MessageInfo: UIViewController, UITableViewDelegate, UITableViewDataSource
             let day = -(components.day!)
             let day = -(components.day!)
             if day == 1 {
             if day == 1 {
                 return "Yesterday".localized()
                 return "Yesterday".localized()
+            } else if day < 7 {
+                return "\(day) " + "days".localized() + " " + "ago".localized()
             } else {
             } else {
                 let formatter = DateFormatter()
                 let formatter = DateFormatter()
-                formatter.dateFormat = "dd/MM/yy"
+                formatter.dateFormat = "dd MMMM yyyy"
                 formatter.locale = NSLocale(localeIdentifier: "id") as Locale?
                 formatter.locale = NSLocale(localeIdentifier: "id") as Locale?
                 let stringFormat = formatter.string(from: date as Date)
                 let stringFormat = formatter.string(from: date as Date)
                 return stringFormat
                 return stringFormat

+ 1 - 0
appbuilder-ios/NexilisLite/Podfile

@@ -15,6 +15,7 @@ target 'NexilisLite' do
   pod 'Toast-Swift', '~> 5.0.1'
   pod 'Toast-Swift', '~> 5.0.1'
   pod 'ZIPFoundation', '~> 0.9.16'
   pod 'ZIPFoundation', '~> 0.9.16'
   pod 'SwiftLinkPreview', '~> 3.4.0'
   pod 'SwiftLinkPreview', '~> 3.4.0'
+  pod 'Popover'
 
 
   target 'NexilisLiteTests' do
   target 'NexilisLiteTests' do
     # Pods for testing
     # Pods for testing

+ 5 - 1
appbuilder-ios/NexilisLite/Podfile.lock

@@ -8,6 +8,7 @@ PODS:
     - MarqueeLabel (~> 4.3.0)
     - MarqueeLabel (~> 4.3.0)
     - SnapKit (~> 5.6.0)
     - SnapKit (~> 5.6.0)
   - nuSDKService (1.0.0)
   - nuSDKService (1.0.0)
+  - Popover (1.3.0)
   - SDWebImage (5.15.8):
   - SDWebImage (5.15.8):
     - SDWebImage/Core (= 5.15.8)
     - SDWebImage/Core (= 5.15.8)
   - SDWebImage/Core (5.15.8)
   - SDWebImage/Core (5.15.8)
@@ -21,6 +22,7 @@ DEPENDENCIES:
   - FMDB (~> 2.7.5)
   - FMDB (~> 2.7.5)
   - NotificationBannerSwift (~> 3.2.1)
   - NotificationBannerSwift (~> 3.2.1)
   - nuSDKService (~> 1.0.0)
   - nuSDKService (~> 1.0.0)
+  - Popover
   - SDWebImage (~> 5.15.7)
   - SDWebImage (~> 5.15.7)
   - SwiftLinkPreview (~> 3.4.0)
   - SwiftLinkPreview (~> 3.4.0)
   - Toast-Swift (~> 5.0.1)
   - Toast-Swift (~> 5.0.1)
@@ -33,6 +35,7 @@ SPEC REPOS:
     - MarqueeLabel
     - MarqueeLabel
     - NotificationBannerSwift
     - NotificationBannerSwift
     - nuSDKService
     - nuSDKService
+    - Popover
     - SDWebImage
     - SDWebImage
     - SnapKit
     - SnapKit
     - SwiftLinkPreview
     - SwiftLinkPreview
@@ -45,12 +48,13 @@ SPEC CHECKSUMS:
   MarqueeLabel: da4b9cf619fe70c75d7bab4580b0b4a0b868aa6b
   MarqueeLabel: da4b9cf619fe70c75d7bab4580b0b4a0b868aa6b
   NotificationBannerSwift: dce54ded532b26e30cd8e7f4d80e124a0f2ba7d1
   NotificationBannerSwift: dce54ded532b26e30cd8e7f4d80e124a0f2ba7d1
   nuSDKService: b92c0f1c47f502f808e4f4134881fcde687e46e9
   nuSDKService: b92c0f1c47f502f808e4f4134881fcde687e46e9
+  Popover: 10e1d9528f81d9504df984b7b3f491292bc1822d
   SDWebImage: cb032eba469c54e0000e78bcb0a13cdde0a52798
   SDWebImage: cb032eba469c54e0000e78bcb0a13cdde0a52798
   SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25
   SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25
   SwiftLinkPreview: c1bc5b2cb3cd42f2865137c1a61f5d788dcf5c9c
   SwiftLinkPreview: c1bc5b2cb3cd42f2865137c1a61f5d788dcf5c9c
   Toast-Swift: 9b6a70f28b3bf0b96c40d46c0c4b9d6639846711
   Toast-Swift: 9b6a70f28b3bf0b96c40d46c0c4b9d6639846711
   ZIPFoundation: d170fa8e270b2a32bef9dcdcabff5b8f1a5deced
   ZIPFoundation: d170fa8e270b2a32bef9dcdcabff5b8f1a5deced
 
 
-PODFILE CHECKSUM: 3f56ca150f6ffc0bfb86b363d4183eb6c9e68195
+PODFILE CHECKSUM: 0b7b9265bedca3b4485f2678aa8f7bbb907ceaa2
 
 
 COCOAPODS: 1.12.1
 COCOAPODS: 1.12.1