alqindiirsyam 2 tahun lalu
induk
melakukan
d9dacc1615
20 mengubah file dengan 471 tambahan dan 220 penghapusan
  1. 22 22
      appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.pbxproj
  2. 6 6
      appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift
  3. 3 3
      appbuilder-ios/NexilisLite/NexilisLite.podspec
  4. 57 7
      appbuilder-ios/NexilisLite/NexilisLite/Source/APIS.swift
  5. 41 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/CoreMessage_TMessageBank.swift
  6. 1 0
      appbuilder-ios/NexilisLite/NexilisLite/Source/CoreMessage_TMessageCode.swift
  7. 75 2
      appbuilder-ios/NexilisLite/NexilisLite/Source/IncomingThread.swift
  8. 156 116
      appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift
  9. 4 3
      appbuilder-ios/NexilisLite/NexilisLite/Source/TMessage.swift
  10. 0 5
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraAudioConference.swift
  11. 47 18
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraAudioViewController.swift
  12. 20 18
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraVideoViewController.swift
  13. 5 2
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift
  14. 1 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangeDeviceViewController.swift
  15. 1 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangeNamePassswordViewController.swift
  16. 2 2
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangePasswordViewController.swift
  17. 19 2
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/HistoryCCViewController.swift
  18. 4 4
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ProfileViewController.swift
  19. 6 6
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SettingTableViewController.swift
  20. 1 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SignUpSignIn.swift

+ 22 - 22
appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.pbxproj

@@ -14,7 +14,7 @@
 		2401CEA1275490DB00B323BB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2401CE9F275490DB00B323BB /* Main.storyboard */; };
 		2401CEA1275490DB00B323BB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2401CE9F275490DB00B323BB /* Main.storyboard */; };
 		2401CEA3275490E600B323BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2401CEA2275490E600B323BB /* Assets.xcassets */; };
 		2401CEA3275490E600B323BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2401CEA2275490E600B323BB /* Assets.xcassets */; };
 		2401CEA6275490E600B323BB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2401CEA4275490E600B323BB /* LaunchScreen.storyboard */; };
 		2401CEA6275490E600B323BB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2401CEA4275490E600B323BB /* LaunchScreen.storyboard */; };
-		64C73E0D9E9CD36FD373F9D8 /* Pods_AppBuilder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F706066070D0174AE105C209 /* Pods_AppBuilder.framework */; };
+		8B68E76E8EC79CD0386179F7 /* Pods_AppBuilder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 286359D832B5EEB59F835E69 /* Pods_AppBuilder.framework */; };
 		A413B18727EACB20006D16EB /* PrefsUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = A413B18627EACB20006D16EB /* PrefsUtil.swift */; };
 		A413B18727EACB20006D16EB /* PrefsUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = A413B18627EACB20006D16EB /* PrefsUtil.swift */; };
 		A42ED92227F30BA200B0FAB7 /* FirstTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A42ED92127F30BA200B0FAB7 /* FirstTabViewController.swift */; };
 		A42ED92227F30BA200B0FAB7 /* FirstTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A42ED92127F30BA200B0FAB7 /* FirstTabViewController.swift */; };
 		A42ED92427F3FC2F00B0FAB7 /* SecondTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A42ED92327F3FC2F00B0FAB7 /* SecondTabViewController.swift */; };
 		A42ED92427F3FC2F00B0FAB7 /* SecondTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A42ED92327F3FC2F00B0FAB7 /* SecondTabViewController.swift */; };
@@ -74,7 +74,9 @@
 		2401CEA2275490E600B323BB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		2401CEA2275490E600B323BB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		2401CEA5275490E600B323BB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		2401CEA5275490E600B323BB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		2401CEA7275490E600B323BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		2401CEA7275490E600B323BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		65C757AC97A834D1917560B2 /* Pods-AppBuilder.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppBuilder.debug.xcconfig"; path = "Target Support Files/Pods-AppBuilder/Pods-AppBuilder.debug.xcconfig"; sourceTree = "<group>"; };
+		286359D832B5EEB59F835E69 /* Pods_AppBuilder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppBuilder.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		86F4F813DA81C40376134BE8 /* Pods-AppBuilder.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppBuilder.debug.xcconfig"; path = "Target Support Files/Pods-AppBuilder/Pods-AppBuilder.debug.xcconfig"; sourceTree = "<group>"; };
+		9CBF52872588FEC0649D8708 /* Pods-AppBuilder.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppBuilder.release.xcconfig"; path = "Target Support Files/Pods-AppBuilder/Pods-AppBuilder.release.xcconfig"; sourceTree = "<group>"; };
 		A413B18627EACB20006D16EB /* PrefsUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsUtil.swift; sourceTree = "<group>"; };
 		A413B18627EACB20006D16EB /* PrefsUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsUtil.swift; sourceTree = "<group>"; };
 		A42ED92127F30BA200B0FAB7 /* FirstTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstTabViewController.swift; sourceTree = "<group>"; };
 		A42ED92127F30BA200B0FAB7 /* FirstTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstTabViewController.swift; sourceTree = "<group>"; };
 		A42ED92327F3FC2F00B0FAB7 /* SecondTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondTabViewController.swift; sourceTree = "<group>"; };
 		A42ED92327F3FC2F00B0FAB7 /* SecondTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondTabViewController.swift; sourceTree = "<group>"; };
@@ -86,11 +88,9 @@
 		A4B5F03B27F193DC0089B871 /* Poppins-LightItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-LightItalic.ttf"; sourceTree = "<group>"; };
 		A4B5F03B27F193DC0089B871 /* Poppins-LightItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-LightItalic.ttf"; sourceTree = "<group>"; };
 		A4B5F03C27F193DC0089B871 /* Poppins-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-SemiBold.ttf"; sourceTree = "<group>"; };
 		A4B5F03C27F193DC0089B871 /* Poppins-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-SemiBold.ttf"; sourceTree = "<group>"; };
 		A4B5F03D27F193DC0089B871 /* Poppins-MediumItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-MediumItalic.ttf"; sourceTree = "<group>"; };
 		A4B5F03D27F193DC0089B871 /* Poppins-MediumItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-MediumItalic.ttf"; sourceTree = "<group>"; };
-		A8A4F2997036256E6F370DE3 /* Pods-AppBuilder.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppBuilder.release.xcconfig"; path = "Target Support Files/Pods-AppBuilder/Pods-AppBuilder.release.xcconfig"; sourceTree = "<group>"; };
 		CDEE3DC929B06E1E00B420E5 /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDEE3DC929B06E1E00B420E5 /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDEE3DCB29B06E1E00B420E5 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
 		CDEE3DCB29B06E1E00B420E5 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
 		CDEE3DCD29B06E1E00B420E5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		CDEE3DCD29B06E1E00B420E5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		F706066070D0174AE105C209 /* Pods_AppBuilder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppBuilder.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -98,7 +98,7 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				64C73E0D9E9CD36FD373F9D8 /* Pods_AppBuilder.framework in Frameworks */,
+				8B68E76E8EC79CD0386179F7 /* Pods_AppBuilder.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -119,7 +119,7 @@
 				CDEE3DCA29B06E1E00B420E5 /* NotificationService */,
 				CDEE3DCA29B06E1E00B420E5 /* NotificationService */,
 				2401CE97275490DB00B323BB /* Products */,
 				2401CE97275490DB00B323BB /* Products */,
 				6E32BCCF4DE50EE1A90E8AAE /* Pods */,
 				6E32BCCF4DE50EE1A90E8AAE /* Pods */,
-				EB9643D0C6F881AD1B5AFD88 /* Frameworks */,
+				2F89B8A584A02CBC3C334BD2 /* Frameworks */,
 			);
 			);
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
@@ -152,11 +152,19 @@
 			path = AppBuilder;
 			path = AppBuilder;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
+		2F89B8A584A02CBC3C334BD2 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				286359D832B5EEB59F835E69 /* Pods_AppBuilder.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 		6E32BCCF4DE50EE1A90E8AAE /* Pods */ = {
 		6E32BCCF4DE50EE1A90E8AAE /* Pods */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				65C757AC97A834D1917560B2 /* Pods-AppBuilder.debug.xcconfig */,
-				A8A4F2997036256E6F370DE3 /* Pods-AppBuilder.release.xcconfig */,
+				86F4F813DA81C40376134BE8 /* Pods-AppBuilder.debug.xcconfig */,
+				9CBF52872588FEC0649D8708 /* Pods-AppBuilder.release.xcconfig */,
 			);
 			);
 			path = Pods;
 			path = Pods;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -184,14 +192,6 @@
 			path = NotificationService;
 			path = NotificationService;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
-		EB9643D0C6F881AD1B5AFD88 /* Frameworks */ = {
-			isa = PBXGroup;
-			children = (
-				F706066070D0174AE105C209 /* Pods_AppBuilder.framework */,
-			);
-			name = Frameworks;
-			sourceTree = "<group>";
-		};
 /* End PBXGroup section */
 /* End PBXGroup section */
 
 
 /* Begin PBXNativeTarget section */
 /* Begin PBXNativeTarget section */
@@ -199,13 +199,13 @@
 			isa = PBXNativeTarget;
 			isa = PBXNativeTarget;
 			buildConfigurationList = 2401CEC0275490E600B323BB /* Build configuration list for PBXNativeTarget "AppBuilder" */;
 			buildConfigurationList = 2401CEC0275490E600B323BB /* Build configuration list for PBXNativeTarget "AppBuilder" */;
 			buildPhases = (
 			buildPhases = (
-				81EC0B8B73DF791FC5DE2676 /* [CP] Check Pods Manifest.lock */,
+				5C3F5CA54D12D5CEEA326725 /* [CP] Check Pods Manifest.lock */,
 				2401CE92275490DB00B323BB /* Sources */,
 				2401CE92275490DB00B323BB /* Sources */,
 				2401CE93275490DB00B323BB /* Frameworks */,
 				2401CE93275490DB00B323BB /* Frameworks */,
 				2401CE94275490DB00B323BB /* Resources */,
 				2401CE94275490DB00B323BB /* Resources */,
 				247E0A722796969200430E5F /* Embed Frameworks */,
 				247E0A722796969200430E5F /* Embed Frameworks */,
 				CDEE3DD129B06E1E00B420E5 /* Embed Foundation Extensions */,
 				CDEE3DD129B06E1E00B420E5 /* Embed Foundation Extensions */,
-				07199500606CD285677B26A8 /* [CP] Embed Pods Frameworks */,
+				3A1C735B8CDE2075245568C6 /* [CP] Embed Pods Frameworks */,
 			);
 			);
 			buildRules = (
 			buildRules = (
 			);
 			);
@@ -298,7 +298,7 @@
 /* End PBXResourcesBuildPhase section */
 /* End PBXResourcesBuildPhase section */
 
 
 /* Begin PBXShellScriptBuildPhase section */
 /* Begin PBXShellScriptBuildPhase section */
-		07199500606CD285677B26A8 /* [CP] Embed Pods Frameworks */ = {
+		3A1C735B8CDE2075245568C6 /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
@@ -315,7 +315,7 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AppBuilder/Pods-AppBuilder-frameworks.sh\"\n";
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AppBuilder/Pods-AppBuilder-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 			showEnvVarsInLog = 0;
 		};
 		};
-		81EC0B8B73DF791FC5DE2676 /* [CP] Check Pods Manifest.lock */ = {
+		5C3F5CA54D12D5CEEA326725 /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
@@ -511,7 +511,7 @@
 		};
 		};
 		2401CEC1275490E600B323BB /* Debug */ = {
 		2401CEC1275490E600B323BB /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 65C757AC97A834D1917560B2 /* Pods-AppBuilder.debug.xcconfig */;
+			baseConfigurationReference = 86F4F813DA81C40376134BE8 /* Pods-AppBuilder.debug.xcconfig */;
 			buildSettings = {
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@@ -543,7 +543,7 @@
 		};
 		};
 		2401CEC2275490E600B323BB /* Release */ = {
 		2401CEC2275490E600B323BB /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = A8A4F2997036256E6F370DE3 /* Pods-AppBuilder.release.xcconfig */;
+			baseConfigurationReference = 9CBF52872588FEC0649D8708 /* Pods-AppBuilder.release.xcconfig */;
 			buildSettings = {
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;

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

@@ -864,7 +864,7 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
         DispatchQueue.global().async {
         DispatchQueue.global().async {
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let p_password = password
             let p_password = password
-            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = p_password
             var result: Bool = false
             var result: Bool = false
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiAdmin(p_name: idMe!, p_password: md5Hex)) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiAdmin(p_name: idMe!, p_password: md5Hex)) {
                 if response.isOk() {
                 if response.isOk() {
@@ -899,7 +899,7 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
         DispatchQueue.global().async {
         DispatchQueue.global().async {
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let p_password = password
             let p_password = password
-            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = p_password
             var result: Bool = false
             var result: Bool = false
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiInternal(p_name: idMe!, p_password: md5Hex)) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiInternal(p_name: idMe!, p_password: md5Hex)) {
                 if response.isOk() {
                 if response.isOk() {
@@ -935,8 +935,8 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let p_password = oldPassword
             let p_password = oldPassword
             let n_password = newPassword
             let n_password = newPassword
-            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
-            let md5HexNew = Utils.getMD5(string: n_password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = p_password
+            let md5HexNew = n_password
             var result: Bool = false
             var result: Bool = false
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordAdmin(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordAdmin(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
                 if response.isOk() {
                 if response.isOk() {
@@ -972,8 +972,8 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let p_password = oldPassword
             let p_password = oldPassword
             let n_password = newPassword
             let n_password = newPassword
-            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
-            let md5HexNew = Utils.getMD5(string: n_password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = p_password
+            let md5HexNew = n_password
             var result: Bool = false
             var result: Bool = false
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordInternal(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordInternal(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
                 if response.isOk() {
                 if response.isOk() {

+ 3 - 3
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      = "1.0.6"
+  spec.version      = "1.0.7"
   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,13 +18,13 @@ 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/v1.0.6/NexilisLite.zip' }
+#  spec.source       = { :http => 'https://newuniverse.io/UCPaaSiOS/releases/download/NexilisLiteiOS/v1.0.7/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/**/*']}
   spec.swift_version = '5.5.1'
   spec.swift_version = '5.5.1'
   spec.dependency 'FMDB', '~> 2.7.5'
   spec.dependency 'FMDB', '~> 2.7.5'
-  spec.dependency 'nuSDKService', '~> 0.0.9'
+  spec.dependency 'nuSDKService', '~> 1.0.0'
   spec.dependency 'NotificationBannerSwift', '~> 3.2.1'
   spec.dependency 'NotificationBannerSwift', '~> 3.2.1'
   spec.dependency 'Alamofire', '~> 5.7.0'
   spec.dependency 'Alamofire', '~> 5.7.0'
   spec.dependency 'SDWebImage', '~> 5.15.7'
   spec.dependency 'SDWebImage', '~> 5.15.7'

+ 57 - 7
appbuilder-ios/NexilisLite/NexilisLite/Source/APIS.swift

@@ -61,14 +61,64 @@ public class APIS: NSObject {
             banner.show()
             banner.show()
             return
             return
         }
         }
-        let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
-        controller.isContactCenter = true
-        let navigationController = UINavigationController(rootViewController: controller)
-        navigationController.defaultStyle()
-        if UIApplication.shared.visibleViewController?.navigationController != nil {
-            UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+        if User.isCallCenter(userType: (User.getData(pin: User.getMyPin())?.userType)!) {
+            let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "myHistoryCC") as! HistoryCCViewController
+            controller.isOfficer = true
+            controller.fromAPI = true
+            let navigationController = UINavigationController(rootViewController: controller)
+            navigationController.defaultStyle()
+            if UIApplication.shared.visibleViewController?.navigationController != nil {
+                UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+            } else {
+                UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+            }
         } else {
         } else {
-            UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+            let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
+            controller.isContactCenter = true
+            let navigationController = UINavigationController(rootViewController: controller)
+            navigationController.defaultStyle()
+            if UIApplication.shared.visibleViewController?.navigationController != nil {
+                UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+            } else {
+                UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+            }
+        }
+    }
+    
+    public static func callContactCenter(mode: String, speciality: String) {
+        let isChangeProfile = Utils.getSetProfile()
+        if !isChangeProfile {
+            APIS.showChangeProfile()
+            return
+        }
+        let isWaitingRequestCC = UserDefaults.standard.bool(forKey: "waitingRequestCC")
+        if isWaitingRequestCC {
+            let imageView = UIImageView(image: UIImage(systemName: "info.circle"))
+            imageView.tintColor = .white
+            let banner = FloatingNotificationBanner(title: "You have requested Call Center, please wait for response.".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .info, colors: nil, iconPosition: .center)
+            banner.show()
+            return
+        }
+        if User.isCallCenter(userType: (User.getData(pin: User.getMyPin())?.userType)!) {
+            let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "myHistoryCC") as! HistoryCCViewController
+            controller.isOfficer = true
+            let navigationController = UINavigationController(rootViewController: controller)
+            navigationController.defaultStyle()
+            if UIApplication.shared.visibleViewController?.navigationController != nil {
+                UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+            } else {
+                UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+            }
+        } else {
+            let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
+            controller.isContactCenter = true
+            let navigationController = UINavigationController(rootViewController: controller)
+            navigationController.defaultStyle()
+            if UIApplication.shared.visibleViewController?.navigationController != nil {
+                UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+            } else {
+                UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+            }
         }
         }
     }
     }
     
     

+ 41 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/CoreMessage_TMessageBank.swift

@@ -165,7 +165,11 @@ public class CoreMessage_TMessageBank {
         tmessage.mBodies[CoreMessage_TMessageKey.FORMAT] = ex_format
         tmessage.mBodies[CoreMessage_TMessageKey.FORMAT] = ex_format
         tmessage.mBodies[CoreMessage_TMessageKey.IS_CALL_CENTER] = is_call_center
         tmessage.mBodies[CoreMessage_TMessageKey.IS_CALL_CENTER] = is_call_center
         tmessage.mBodies[CoreMessage_TMessageKey.CALL_CENTER_ID] = call_center_id
         tmessage.mBodies[CoreMessage_TMessageKey.CALL_CENTER_ID] = call_center_id
-        tmessage.mBodies[CoreMessage_TMessageKey.OPPOSITE_PIN] = opposite_pin
+        tmessage.mBodies[CoreMessage_TMessageKey.F_USER_ID] = me
+        tmessage.mBodies[CoreMessage_TMessageKey.QUANTITY] = "1"
+        if !opposite_pin.isEmpty {
+            tmessage.mBodies[CoreMessage_TMessageKey.OPPOSITE_PIN] = opposite_pin
+        }
         
         
         if !image_id.isEmpty {
         if !image_id.isEmpty {
             tmessage.mBodies[CoreMessage_TMessageKey.IMAGE_ID] = image_id
             tmessage.mBodies[CoreMessage_TMessageKey.IMAGE_ID] = image_id
@@ -531,6 +535,15 @@ public class CoreMessage_TMessageBank {
         return tMessage
         return tMessage
     }
     }
     
     
+    public static func getAddFriendQRCodeSilent(fpin: String) -> TMessage {
+        let tMessage = TMessage()
+        tMessage.mCode = CoreMessage_TMessageCode.ADD_FRIEND_QR
+        tMessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tMessage.mBodies[CoreMessage_TMessageKey.FRIEND_FPIN] = fpin
+        tMessage.mBodies["is_silent"] = "1"
+        return tMessage
+    }
+    
     public static func removeFriend(lpin: String) -> TMessage {
     public static func removeFriend(lpin: String) -> TMessage {
         let tMessage = TMessage()
         let tMessage = TMessage()
         tMessage.mCode = CoreMessage_TMessageCode.REMOVE_FRIEND
         tMessage.mCode = CoreMessage_TMessageCode.REMOVE_FRIEND
@@ -2354,4 +2367,31 @@ public class CoreMessage_TMessageBank {
         return tmessage
         return tmessage
     }
     }
     
     
+    public static func getServiceBank() -> TMessage {
+        let tmessage = TMessage()
+        tmessage.mCode = CoreMessage_TMessageCode.GET_SERVICE_BNI
+        tmessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tmessage.mPIN = UserDefaults.standard.string(forKey: "me")!
+        tmessage.mBodies[CoreMessage_TMessageKey.PLATFORM] = "0"
+        return tmessage
+    }
+    
+    public static func getIncomingCallCS(f_pin_opposite: String) -> TMessage {
+        let tmessage = TMessage()
+        tmessage.mCode = CoreMessage_TMessageCode.INCOMING_CALL_CC
+        tmessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tmessage.mPIN = UserDefaults.standard.string(forKey: "me")!
+        tmessage.mBodies[CoreMessage_TMessageKey.F_PIN] = f_pin_opposite
+        return tmessage
+    }
+
+    public static func getEndCall(f_pin_opposite: String) -> TMessage {
+        let tmessage = TMessage()
+        tmessage.mCode = CoreMessage_TMessageCode.END_CALL
+        tmessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tmessage.mPIN = UserDefaults.standard.string(forKey: "me")!
+        tmessage.mBodies[CoreMessage_TMessageKey.F_PIN] = f_pin_opposite
+        return tmessage;
+    }
+    
 }
 }

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

@@ -584,6 +584,7 @@ public class CoreMessage_TMessageCode {
     public static let ASKING_FOR_END_CALL = "ASKE";
     public static let ASKING_FOR_END_CALL = "ASKE";
     
     
     public static let END_CALL = "ENCL";
     public static let END_CALL = "ENCL";
+    public static let INCOMING_CALL_CC = "ICS";
     
     
     public static let POST_RETRIEVE_PROFILE = "PIP";
     public static let POST_RETRIEVE_PROFILE = "PIP";
     public static let POST_RETRIEVE_TIMELINE = "PIT";
     public static let POST_RETRIEVE_TIMELINE = "PIT";

+ 75 - 2
appbuilder-ios/NexilisLite/NexilisLite/Source/IncomingThread.swift

@@ -54,10 +54,10 @@ class IncomingThread {
         } else if message.getCode() == CoreMessage_TMessageCode.PUSH_MYSELF || message.getCode() == CoreMessage_TMessageCode.PUSH_MYSELF_ACK || message.getCode() == CoreMessage_TMessageCode.PULL_MYSELF {
         } else if message.getCode() == CoreMessage_TMessageCode.PUSH_MYSELF || message.getCode() == CoreMessage_TMessageCode.PUSH_MYSELF_ACK || message.getCode() == CoreMessage_TMessageCode.PULL_MYSELF {
             pushMyself(message: message)
             pushMyself(message: message)
         } else if message.getCode() == CoreMessage_TMessageCode.PUSH_BUDDY {
         } else if message.getCode() == CoreMessage_TMessageCode.PUSH_BUDDY {
-            makeNotifAddFriend(message: message)
             DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
             DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
                 self.initBatchBuddy(message: message)
                 self.initBatchBuddy(message: message)
             })
             })
+            makeNotifAddFriend(message: message)
         } else if message.getCode() == CoreMessage_TMessageCode.INIT_BATCH_BUDDY {
         } else if message.getCode() == CoreMessage_TMessageCode.INIT_BATCH_BUDDY {
             initBatchBuddy(message: message)
             initBatchBuddy(message: message)
         } else if message.getCode() == CoreMessage_TMessageCode.CHANGE_BATCH_PERSON_INFO {
         } else if message.getCode() == CoreMessage_TMessageCode.CHANGE_BATCH_PERSON_INFO {
@@ -140,7 +140,7 @@ class IncomingThread {
             verifyOTP(message: message)
             verifyOTP(message: message)
         } else if message.getCode() == CoreMessage_TMessageCode.REMOVE_FRIEND {
         } else if message.getCode() == CoreMessage_TMessageCode.REMOVE_FRIEND {
             deleteBuddy(message: message)
             deleteBuddy(message: message)
-        } else if message.getCode() == CoreMessage_TMessageCode.PUSH_CALL_CENTER || message.getCode() == CoreMessage_TMessageCode.ACCEPT_CALL_CENTER || message.getCode() == CoreMessage_TMessageCode.END_CALL_CENTER || message.getCode() == CoreMessage_TMessageCode.TIMEOUT_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.INVITE_TO_ROOM_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.ACCEPT_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.PUSH_MEMBER_ROOM_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.INVITE_END_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.INVITE_EXIT_CONTACT_CENTER {
+        } else if message.getCode() == CoreMessage_TMessageCode.PUSH_CALL_CENTER || message.getCode() == CoreMessage_TMessageCode.ACCEPT_CALL_CENTER || message.getCode() == CoreMessage_TMessageCode.END_CALL_CENTER || message.getCode() == CoreMessage_TMessageCode.TIMEOUT_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.INVITE_TO_ROOM_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.ACCEPT_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.PUSH_MEMBER_ROOM_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.INVITE_END_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.INVITE_EXIT_CONTACT_CENTER || message.getCode() == CoreMessage_TMessageCode.PUSH_SECOND_CONTACT_CENTER {
             handleCallCenter(message: message)
             handleCallCenter(message: message)
         } else if message.getCode() == CoreMessage_TMessageCode.PUSH_DISCUSSION_COMMENT {
         } else if message.getCode() == CoreMessage_TMessageCode.PUSH_DISCUSSION_COMMENT {
             if let delegate = Nexilis.shared.messageDelegate {
             if let delegate = Nexilis.shared.messageDelegate {
@@ -161,6 +161,8 @@ class IncomingThread {
             backupAvailability(message: message)
             backupAvailability(message: message)
         } else if message.getCode() == CoreMessage_TMessageCode.FORWARD_MESSAGE {
         } else if message.getCode() == CoreMessage_TMessageCode.FORWARD_MESSAGE {
             incomingWBSS(message: message)
             incomingWBSS(message: message)
+        } else if message.getCode() == CoreMessage_TMessageCode.INCOMING_CALL_CC {
+            incomingCallCC(message: message)
         } else {
         } else {
             print("unprocessed code", message.getCode())
             print("unprocessed code", message.getCode())
             ack(message: message)
             ack(message: message)
@@ -173,6 +175,71 @@ class IncomingThread {
     /**
     /**
      *
      *
      */
      */
+    private func incomingCallCC(message: TMessage) {
+        if let packetId = message.mBodies[CoreMessage_TMessageKey.PACKET_ID] {
+            _ = Nexilis.responseString(packetId: packetId, message: "01")
+        }
+        ack(message: message)
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
+            let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
+            let channelCC = UserDefaults.standard.string(forKey: "channelCC") ?? ""
+            let complaintId = onGoingCC.components(separatedBy: ",")[2]
+            let fPinCC = onGoingCC.isEmpty ? "" : onGoingCC.components(separatedBy: ",")[1]
+            if fPinCC == User.getMyPin() {
+                return
+            }
+            if channelCC == "1" {
+                let controller = QmeraAudioViewController()
+                controller.isOutgoing = false
+                controller.user = User.getData(pin: fPinCC)
+                controller.ticketId = complaintId
+                controller.modalPresentationStyle = .overCurrentContext
+                if UIApplication.shared.visibleViewController is UIAlertController {
+                    let vc = UIApplication.shared.visibleViewController as! UIAlertController
+                    vc.dismiss(animated: true, completion: {
+                        if UIApplication.shared.visibleViewController?.navigationController != nil {
+                            UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
+                        } else {
+                            UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
+                        }
+                    })
+                    return
+                }
+                if UIApplication.shared.visibleViewController?.navigationController != nil {
+                    UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
+                } else {
+                    UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
+                }
+            } else if channelCC == "2" {
+                let videoController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
+                let user = User.getData(pin: fPinCC)
+                videoController.fPin = user!.pin
+                videoController.isInisiator = false
+                videoController.users.append(user!)
+                videoController.isAutoAccept = true
+                videoController.ticketId = complaintId
+                let navigationController = UINavigationController(rootViewController: videoController)
+                navigationController.modalPresentationStyle = .fullScreen
+                if UIApplication.shared.visibleViewController is UIAlertController {
+                    let vc = UIApplication.shared.visibleViewController as! UIAlertController
+                    vc.dismiss(animated: true, completion: {
+                        if UIApplication.shared.visibleViewController?.navigationController != nil {
+                            UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+                        } else {
+                            UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+                        }
+                    })
+                    return
+                }
+                if UIApplication.shared.visibleViewController?.navigationController != nil {
+                    UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+                } else {
+                    UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+                }
+            }
+        })
+    }
+    
     private func incomingWBSS(message: TMessage) {
     private func incomingWBSS(message: TMessage) {
         let type = message.getBody(key: CoreMessage_TMessageKey.TYPE, default_value: "")
         let type = message.getBody(key: CoreMessage_TMessageKey.TYPE, default_value: "")
         let status = message.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "")
         let status = message.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "")
@@ -244,6 +311,9 @@ class IncomingThread {
                         if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin FROM BUDDY where f_pin='\(f_pin)'"), cursorUser.next() {
                         if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin FROM BUDDY where f_pin='\(f_pin)'"), cursorUser.next() {
                             return
                             return
                         }
                         }
+                        if message.getBody(key: "is_silent") == "1" {
+                            return
+                        }
                         let firstname = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.FIRST_NAME)
                         let firstname = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.FIRST_NAME)
                         let lastname = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LAST_NAME)
                         let lastname = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LAST_NAME)
                         let f_pin = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.F_PIN)
                         let f_pin = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.F_PIN)
@@ -400,6 +470,9 @@ class IncomingThread {
         if let delegate = Nexilis.shared.messageDelegate {
         if let delegate = Nexilis.shared.messageDelegate {
             delegate.onReceive(message: message)
             delegate.onReceive(message: message)
         }
         }
+        if let packetId = message.mBodies[CoreMessage_TMessageKey.PACKET_ID], (message.getCode() == CoreMessage_TMessageCode.PUSH_CALL_CENTER || message.getCode() == CoreMessage_TMessageCode.PUSH_SECOND_CONTACT_CENTER) {
+            _ = Nexilis.responseString(packetId: packetId, message: "00")
+        }
         ack(message: message)
         ack(message: message)
         // TODO: notif call center
         // TODO: notif call center
     }
     }

+ 156 - 116
appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -157,6 +157,8 @@ public class Nexilis: NSObject {
                         })
                         })
                     })
                     })
                 }
                 }
+                getServiceBank()
+                getPullWorkingArea()
                 delegate.onSuccess(userId: me)
                 delegate.onSuccess(userId: me)
                 if showButton {
                 if showButton {
                     DispatchQueue.main.async {
                     DispatchQueue.main.async {
@@ -193,6 +195,44 @@ public class Nexilis: NSObject {
         }
         }
     }
     }
     
     
+    private static func getServiceBank() {
+        DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
+            _ = Nexilis.write(message: CoreMessage_TMessageBank.getServiceBank())
+        })
+    }
+    
+    private static func getPullWorkingArea() {
+        DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
+            if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getWorkingAreaContactCenter(), timeout: 30 * 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] {
+                        Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                            do {
+                                for json in jsonArray {
+                                    var parent = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.PARENT_ID)
+                                    if parent.isEmpty {
+                                        parent = "-99"
+                                    }
+                                    _ = try Database.shared.insertRecord(fmdb: fmdb, table: "SERVICE_BANK", cvalues: [
+                                        "service_id" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.CATEGORY_ID),
+                                        "service_name" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.NAME),
+                                        "description" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.DESCRIPTION),
+                                        "parent" : parent,
+                                        "is_tablet" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.PLATFORM)
+                                    ], replace: true)
+                                }
+                            } catch {
+                                rollback.pointee = true
+                                print(error)
+                            }
+                        })
+                    }
+                }
+            }
+        })
+    }
+    
     public static func destroyAll() {
     public static func destroyAll() {
         let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
         let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
         if !onGoingCC.isEmpty {
         if !onGoingCC.isEmpty {
@@ -263,7 +303,7 @@ public class Nexilis: NSObject {
             Nexilis.dispatch?.wait()
             Nexilis.dispatch?.wait()
             Nexilis.dispatch = nil
             Nexilis.dispatch = nil
             print("success change user to fpin")
             print("success change user to fpin")
-            _ = Nexilis.write(message: CoreMessage_TMessageBank.getChangeConnectionID(p_pin: f_pin))
+//            _ = Nexilis.write(message: CoreMessage_TMessageBank.getChangeConnectionID(p_pin: f_pin))
         } catch{
         } catch{
             print(error)
             print(error)
         }
         }
@@ -422,6 +462,20 @@ public class Nexilis: NSObject {
         }
         }
         return result
         return result
     }
     }
+    
+    public static func responseString(packetId: String, message: String, timeout: Int = 15 * 1000) -> String? {
+        var result: String? = nil
+        do {
+            if !API.bInetConnAvailable() {
+                return nil
+            }
+            print(">> RESPONSE >> " + packetId + " " + message);
+            result = try API.sSendResponse(sRequestID: packetId, sResponse: message, lTimeout: timeout)
+        } catch {
+            print(error)
+        }
+        return result
+    }
 
 
     public static func setSpeaker(_ isEnabled: Bool) {
     public static func setSpeaker(_ isEnabled: Bool) {
         do {
         do {
@@ -1390,6 +1444,9 @@ extension Nexilis: CallDelegate {
             let idMe = UserDefaults.standard.string(forKey: "me")!
             let idMe = UserDefaults.standard.string(forKey: "me")!
             let myData = User.getData(pin: idMe)
             let myData = User.getData(pin: idMe)
             let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
             let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
+            if !onGoingCC.isEmpty {
+                return
+            }
             let deviceId = message.split(separator: ",")[0]
             let deviceId = message.split(separator: ",")[0]
             if myData?.offline_mode == "1" || self.stateUnfriend == deviceId {
             if myData?.offline_mode == "1" || self.stateUnfriend == deviceId {
                 DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
                 DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
@@ -1418,55 +1475,39 @@ extension Nexilis: CallDelegate {
                 }
                 }
             }
             }
             if (state == 21 && message.split(separator: ",")[1] != "joining Ac.room on channel 0") {
             if (state == 21 && message.split(separator: ",")[1] != "joining Ac.room on channel 0") {
-                if onGoingCC.isEmpty {
-                    let data = User.getDataCanNil(pin: String(deviceId))
-                    if data == nil {
-                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
-                            API.terminateCall(sParty: nil)
-                        })
-                        return
-                    }
+                let data = User.getDataCanNil(pin: String(deviceId))
+                if data == nil {
+                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
+                        API.terminateCall(sParty: nil)
+                    })
+                    return
+                }
 //                    let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
 //                    let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
 //                    uuidOngoing = UUID()
 //                    uuidOngoing = UUID()
 //                    self.displayIncomingCall(uuid: uuidOngoing, handle: String(deviceId), hasVideo: false) { error in
 //                    self.displayIncomingCall(uuid: uuidOngoing, handle: String(deviceId), hasVideo: false) { error in
 //                        UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
 //                        UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
 //                    }
 //                    }
-                    let controller = QmeraAudioViewController()
-                    controller.user = User.getData(pin: String(deviceId))
-                    controller.isOutgoing = false
-                    controller.modalPresentationStyle = .overCurrentContext
-                    if UIApplication.shared.visibleViewController is UIAlertController {
-                        let vc = UIApplication.shared.visibleViewController as! UIAlertController
-                        vc.dismiss(animated: true, completion: {
-                            if UIApplication.shared.visibleViewController?.navigationController != nil {
-                                UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
-                            } else {
-                                UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
-                            }
-                        })
-                        return
-                    }
-                    if UIApplication.shared.visibleViewController?.navigationController != nil {
-                        UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
-                    } else {
-                        UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
-                    }
-//                    API.receiveCCall(sParty: String(deviceId))
-                } else {
-                    DispatchQueue.main.asyncAfter(deadline: .now() + isShowAlert!, execute: {
-                        let controller = QmeraAudioViewController()
-                        controller.user = User.getData(pin: String(deviceId))
-                        controller.isOnGoing = true
-                        controller.isOutgoing = false
-                        controller.modalPresentationStyle = .overCurrentContext
+                let controller = QmeraAudioViewController()
+                controller.user = User.getData(pin: String(deviceId))
+                controller.isOutgoing = false
+                controller.modalPresentationStyle = .overCurrentContext
+                if UIApplication.shared.visibleViewController is UIAlertController {
+                    let vc = UIApplication.shared.visibleViewController as! UIAlertController
+                    vc.dismiss(animated: true, completion: {
                         if UIApplication.shared.visibleViewController?.navigationController != nil {
                         if UIApplication.shared.visibleViewController?.navigationController != nil {
                             UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
                             UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
                         } else {
                         } else {
                             UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
                             UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
                         }
                         }
-                        API.receiveCCall(sParty: String(deviceId))
                     })
                     })
+                    return
+                }
+                if UIApplication.shared.visibleViewController?.navigationController != nil {
+                    UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
+                } else {
+                    UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
                 }
                 }
+//                    API.receiveCCall(sParty: String(deviceId))
             } else if state == 31 {
             } else if state == 31 {
                 let dataUser = User.getDataCanNil(pin: String(deviceId))
                 let dataUser = User.getDataCanNil(pin: String(deviceId))
                 if dataUser == nil {
                 if dataUser == nil {
@@ -1475,74 +1516,27 @@ extension Nexilis: CallDelegate {
                     })
                     })
                     return
                     return
                 }
                 }
-                let fpin = deviceId
-                var data: [String: String?] = [:]
-                Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, official_account, image_id, device_id, offline_mode, user_type FROM BUDDY where f_pin = '\(fpin)'"), cursorData.next() {
-                        data["f_pin"] = cursorData.string(forColumnIndex: 0)
-                        var name = ""
-                        if let firstname = cursorData.string(forColumnIndex: 1) {
-                            name = firstname
-                        }
-                        if let lastname = cursorData.string(forColumnIndex: 2) {
-                            name = name + " " + lastname
-                        }
-                        data["name"] = name
-                        data["picture"] = cursorData.string(forColumnIndex: 4)
-                        data["isOfficial"] = cursorData.string(forColumnIndex: 3)
-                        data["deviceId"] = cursorData.string(forColumnIndex: 5)
-                        data["isOffline"] = cursorData.string(forColumnIndex: 6)
-                        data["user_type"] = cursorData.string(forColumnIndex: 7)
-                        cursorData.close()
-                        
-                        let videoController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
-                        videoController.dataPerson.append(data)
-                        videoController.isInisiator = false
-                        if !onGoingCC.isEmpty {
-                            videoController.users.append(User.getData(pin: data["f_pin"]!!, fmdb: fmdb)!)
-                        }
-                        let navigationController = UINavigationController(rootViewController: videoController)
-                        navigationController.modalPresentationStyle = .fullScreen
-                        if !onGoingCC.isEmpty {
-                            videoController.isAutoAccept = true
-                            DispatchQueue.main.asyncAfter(deadline: .now() + isShowAlert!, execute: {
-                                if UIApplication.shared.visibleViewController is UIAlertController {
-                                    let vc = UIApplication.shared.visibleViewController as! UIAlertController
-                                    vc.dismiss(animated: true, completion: {
-                                        if UIApplication.shared.visibleViewController?.navigationController != nil {
-                                            UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
-                                        } else {
-                                            UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
-                                        }
-                                    })
-                                    return
-                                }
-                                if UIApplication.shared.visibleViewController?.navigationController != nil {
-                                    UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
-                                } else {
-                                    UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
-                                }
-                            })
+                let videoController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
+                videoController.fPin = String(deviceId)
+                videoController.isInisiator = false
+                let navigationController = UINavigationController(rootViewController: videoController)
+                navigationController.modalPresentationStyle = .fullScreen
+                if UIApplication.shared.visibleViewController is UIAlertController {
+                    let vc = UIApplication.shared.visibleViewController as! UIAlertController
+                    vc.dismiss(animated: true, completion: {
+                        if UIApplication.shared.visibleViewController?.navigationController != nil {
+                            UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
                         } else {
                         } else {
-                            if UIApplication.shared.visibleViewController is UIAlertController {
-                                let vc = UIApplication.shared.visibleViewController as! UIAlertController
-                                vc.dismiss(animated: true, completion: {
-                                    if UIApplication.shared.visibleViewController?.navigationController != nil {
-                                        UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
-                                    } else {
-                                        UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
-                                    }
-                                })
-                                return
-                            }
-                            if UIApplication.shared.visibleViewController?.navigationController != nil {
-                                UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
-                            } else {
-                                UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
-                            }
+                            UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
                         }
                         }
-                    }
-                })
+                    })
+                    return
+                }
+                if UIApplication.shared.visibleViewController?.navigationController != nil {
+                    UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+                } else {
+                    UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+                }
             }
             }
         }
         }
     }
     }
@@ -1579,6 +1573,7 @@ extension Nexilis: CallDelegate {
 }
 }
 
 
 var previewItem : NSURL?
 var previewItem : NSURL?
+var listCCIdInv: [String] = []
 
 
 extension Nexilis: MessageDelegate {
 extension Nexilis: MessageDelegate {
     public func onReceiveComment(message: TMessage) {
     public func onReceiveComment(message: TMessage) {
@@ -1847,6 +1842,10 @@ extension Nexilis: MessageDelegate {
         dataMessage["message"] = message
         dataMessage["message"] = message
         NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onReceiveChat"), object: nil, userInfo: dataMessage)
         NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onReceiveChat"), object: nil, userInfo: dataMessage)
         if message.getCode() == CoreMessage_TMessageCode.PUSH_CALL_CENTER {
         if message.getCode() == CoreMessage_TMessageCode.PUSH_CALL_CENTER {
+            if User.getDataCanNil(pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)) == nil {
+                Nexilis.addFriendSilent(fpin: message.getBody(key: CoreMessage_TMessageKey.L_PIN))
+                sleep(1)
+            }
             DispatchQueue.main.async {
             DispatchQueue.main.async {
                 if Nexilis.onGoingPushCC.isEmpty {
                 if Nexilis.onGoingPushCC.isEmpty {
                     var data: [String: String] = [:]
                     var data: [String: String] = [:]
@@ -1896,6 +1895,7 @@ extension Nexilis: MessageDelegate {
                         DispatchQueue.global().async {
                         DispatchQueue.global().async {
                             DispatchQueue.global().async {
                             DispatchQueue.global().async {
                                 _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
                                 _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
+                                
                             }
                             }
                         }
                         }
                         Nexilis.onGoingPushCC.removeAll()
                         Nexilis.onGoingPushCC.removeAll()
@@ -2041,6 +2041,7 @@ extension Nexilis: MessageDelegate {
                                                 let controller = QmeraAudioViewController()
                                                 let controller = QmeraAudioViewController()
                                                 controller.user = User.getData(pin: pin)
                                                 controller.user = User.getData(pin: pin)
                                                 controller.isOutgoing = true
                                                 controller.isOutgoing = true
+                                                controller.ticketId = complaintId
                                                 controller.modalPresentationStyle = .overCurrentContext
                                                 controller.modalPresentationStyle = .overCurrentContext
                                                 let navigationController = UINavigationController(rootViewController: controller)
                                                 let navigationController = UINavigationController(rootViewController: controller)
                                                 navigationController.modalPresentationStyle = .fullScreen
                                                 navigationController.modalPresentationStyle = .fullScreen
@@ -2053,6 +2054,7 @@ extension Nexilis: MessageDelegate {
                                                 let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
                                                 let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
                                                 videoVC.fPin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
                                                 videoVC.fPin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
                                                 videoVC.users.append(User.getData(pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN))!)
                                                 videoVC.users.append(User.getData(pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN))!)
+                                                videoVC.ticketId = complaintId
                                                 let navigationController = UINavigationController(rootViewController: videoVC)
                                                 let navigationController = UINavigationController(rootViewController: videoVC)
                                                 navigationController.modalPresentationStyle = .fullScreen
                                                 navigationController.modalPresentationStyle = .fullScreen
                                                 if UIApplication.shared.visibleViewController?.navigationController != nil {
                                                 if UIApplication.shared.visibleViewController?.navigationController != nil {
@@ -2209,6 +2211,10 @@ extension Nexilis: MessageDelegate {
                 UserDefaults.standard.set("\(fPinContacCenter)", forKey: "membersCC")
                 UserDefaults.standard.set("\(fPinContacCenter)", forKey: "membersCC")
             }
             }
         } else if message.getCode() == CoreMessage_TMessageCode.INVITE_TO_ROOM_CONTACT_CENTER {
         } else if message.getCode() == CoreMessage_TMessageCode.INVITE_TO_ROOM_CONTACT_CENTER {
+            if listCCIdInv.contains(message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)) {
+                return
+            }
+            listCCIdInv.append(message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))
             DispatchQueue.main.async {
             DispatchQueue.main.async {
                 let alert = UIAlertController(title: "", message: "\n\n\n\n\n\n\n\n\n\n".localized(), preferredStyle: .alert)
                 let alert = UIAlertController(title: "", message: "\n\n\n\n\n\n\n\n\n\n".localized(), preferredStyle: .alert)
                 let newWidth = UIScreen.main.bounds.width * 0.90 - 270
                 let newWidth = UIScreen.main.bounds.width * 0.90 - 270
@@ -2226,6 +2232,7 @@ extension Nexilis: MessageDelegate {
                 alert.view.subviews.first?.subviews.first?.subviews.first?.backgroundColor = .lightGray
                 alert.view.subviews.first?.subviews.first?.subviews.first?.backgroundColor = .lightGray
                 alert.view.tintColor = .black
                 alert.view.tintColor = .black
                 let rejectAction = UIAlertAction(title: "Reject".localized(), style: .destructive, handler: {(_) in
                 let rejectAction = UIAlertAction(title: "Reject".localized(), style: .destructive, handler: {(_) in
+                    listCCIdInv.removeAll(where: {$0 == message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)})
                     DispatchQueue.global().async {
                     DispatchQueue.global().async {
                         if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptCCRoomInvite(l_pin: message.getPIN(), type: 0, ticket_id: message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))) {
                         if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptCCRoomInvite(l_pin: message.getPIN(), type: 0, ticket_id: message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))) {
                             if result.isOk() {
                             if result.isOk() {
@@ -2236,6 +2243,7 @@ extension Nexilis: MessageDelegate {
                     alert.dismiss(animated: true, completion: nil)
                     alert.dismiss(animated: true, completion: nil)
                 })
                 })
                 let acceptAction = UIAlertAction(title: "Accept".localized(), style: .default, handler: {(_) in
                 let acceptAction = UIAlertAction(title: "Accept".localized(), style: .default, handler: {(_) in
+                    listCCIdInv.removeAll(where: {$0 == message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)})
                     let goAudioCall = Nexilis.checkMicPermission()
                     let goAudioCall = Nexilis.checkMicPermission()
                     if !goAudioCall && message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
                     if !goAudioCall && message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
                         let alert = UIAlertController(title: "Attention!".localized(), message: "Please allow microphone permission in your settings".localized(), preferredStyle: .alert)
                         let alert = UIAlertController(title: "Attention!".localized(), message: "Please allow microphone permission in your settings".localized(), preferredStyle: .alert)
@@ -2384,19 +2392,12 @@ extension Nexilis: MessageDelegate {
                                                 if let userData = User.getData(pin: "\(json)") {
                                                 if let userData = User.getData(pin: "\(json)") {
                                                     user.append(userData)
                                                     user.append(userData)
                                                 } else {
                                                 } else {
-                                                    Nexilis.addFriend (fpin: "\(json)") { result in
-                                                        DispatchQueue.main.async {
-                                                            if result {
-                                                                let userData = User.getData(pin: "\(json)")!
-                                                                user.append(userData)
-                                                            } else {
-                                                                let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
-                                                                imageView.tintColor = .white
-                                                                let banner = FloatingNotificationBanner(title: "Server busy, please try again later".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
-                                                                banner.show()
-                                                            }
+                                                    Nexilis.addFriendSilent(fpin: "\(json)")
+                                                    DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
+                                                        if let userData = User.getData(pin: "\(json)") {
+                                                            user.append(userData)
                                                         }
                                                         }
-                                                    }
+                                                    })
                                                 }
                                                 }
                                             }
                                             }
                                         }
                                         }
@@ -2429,6 +2430,39 @@ extension Nexilis: MessageDelegate {
                                             } else {
                                             } else {
                                                 UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
                                                 UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
                                             }
                                             }
+                                        } else {
+                                            UserDefaults.standard.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
+                                            DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
+                                                if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
+                                                    let pin = officer
+                                                    let controller = QmeraAudioViewController()
+                                                    controller.user = User.getData(pin: pin)
+                                                    controller.isOutgoing = false
+                                                    controller.ticketId = complaintId
+                                                    controller.modalPresentationStyle = .overCurrentContext
+                                                    let navigationController = UINavigationController(rootViewController: controller)
+                                                    navigationController.modalPresentationStyle = .fullScreen
+                                                    if UIApplication.shared.visibleViewController?.navigationController != nil {
+                                                        UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+                                                    } else {
+                                                        UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+                                                    }
+                                                } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
+                                                    let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
+                                                    videoVC.fPin = officer
+                                                    videoVC.users.append(User.getData(pin: officer)!)
+                                                    videoVC.ticketId = complaintId
+                                                    videoVC.isInisiator = false
+                                                    videoVC.isAutoAccept = true
+                                                    let navigationController = UINavigationController(rootViewController: videoVC)
+                                                    navigationController.modalPresentationStyle = .fullScreen
+                                                    if UIApplication.shared.visibleViewController?.navigationController != nil {
+                                                        UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+                                                    } else {
+                                                        UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+                                                    }
+                                                }
+                                            })
                                         }
                                         }
                                     }
                                     }
                                 }
                                 }
@@ -3060,6 +3094,12 @@ extension Nexilis: MessageDelegate {
         }
         }
     }
     }
     
     
+    public static func addFriendSilent(fpin: String) {
+        DispatchQueue.global().async {
+            _ = Nexilis.write(message: CoreMessage_TMessageBank.getAddFriendQRCodeSilent(fpin: fpin))
+        }
+    }
+    
     public func onReceive(message: [AnyHashable : Any?]) {
     public func onReceive(message: [AnyHashable : Any?]) {
         var dataMessage: [AnyHashable : Any] = [:]
         var dataMessage: [AnyHashable : Any] = [:]
         dataMessage["message"] = message
         dataMessage["message"] = message

+ 4 - 3
appbuilder-ios/NexilisLite/NexilisLite/Source/TMessage.swift

@@ -34,16 +34,17 @@ public class TMessage {
     public static let TYPE_NEED_ACK    =  "3"
     public static let TYPE_NEED_ACK    =  "3"
     
     
     public init() {
     public init() {
+        mVersion = "1.0.107"
         mBodies[CoreMessage_TMessageKey.IMEI] = Nexilis.getCLMUserId()
         mBodies[CoreMessage_TMessageKey.IMEI] = Nexilis.getCLMUserId()
 //        mBodies[CoreMessage_TMessageKey.VERCOD] = UIApplication.appVersion
 //        mBodies[CoreMessage_TMessageKey.VERCOD] = UIApplication.appVersion
-        mBodies[CoreMessage_TMessageKey.VERCOD] = "1.8.5.24"
+        mBodies[CoreMessage_TMessageKey.VERCOD] = "1.0.220216"
     }
     }
     
     
     public init(data : String) {
     public init(data : String) {
         _ = unpack(data: data)
         _ = unpack(data: data)
     }
     }
     
     
-    init(type: String, version: String = "1.0.106", code: String,status: String, pin: String, l_pin: String, bodies:[String: String], media:  [UInt8]) {
+    init(type: String, version: String, code: String,status: String, pin: String, l_pin: String, bodies:[String: String], media:  [UInt8]) {
         mType = type
         mType = type
         mVersion = version
         mVersion = version
         mCode = code
         mCode = code
@@ -54,7 +55,7 @@ public class TMessage {
         mMedia = media
         mMedia = media
         mBodies[CoreMessage_TMessageKey.IMEI] = Nexilis.getCLMUserId()
         mBodies[CoreMessage_TMessageKey.IMEI] = Nexilis.getCLMUserId()
 //        mBodies[CoreMessage_TMessageKey.VERCOD] = UIApplication.appVersion
 //        mBodies[CoreMessage_TMessageKey.VERCOD] = UIApplication.appVersion
-        mBodies[CoreMessage_TMessageKey.VERCOD] = "1.8.5.24"
+        mBodies[CoreMessage_TMessageKey.VERCOD] = "1.0.220216"
     }
     }
     
     
     public func clone(p_tmessage:TMessage) -> TMessage {
     public func clone(p_tmessage:TMessage) -> TMessage {

+ 0 - 5
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraAudioConference.swift

@@ -436,11 +436,6 @@ class QmeraAudioConference: UIViewController {
                         }
                         }
                     }
                     }
                     self.users.append(User.getData(pin: dataMessage.getPIN())!)
                     self.users.append(User.getData(pin: dataMessage.getPIN())!)
-                    // Start Calling
-                    if !self.isAddCall.isEmpty && self.isAddCall == dataMessage.getPIN(){
-//                        Nexilis.shared.callManager.startCall(handle: dataMessage.getPIN())
-                        API.initiateCCall(sParty: dataMessage.getPIN())
-                    }
                 }
                 }
             }
             }
         }
         }

+ 47 - 18
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraAudioViewController.swift

@@ -58,12 +58,25 @@ class QmeraAudioViewController: UIViewController {
     
     
     var isOnGoing: Bool = false
     var isOnGoing: Bool = false
     
     
+    var ticketId: String = ""
+    
     private var timer: Timer?
     private var timer: Timer?
     
     
     private var firstCall: Bool = true
     private var firstCall: Bool = true
     
     
     private var isSpeaker: Bool = false
     private var isSpeaker: Bool = false
     
     
+    var listRemoteViewFix: [UIImageView] = [
+        UIImageView(),
+        UIImageView(),
+        UIImageView(),
+        UIImageView(),
+        UIImageView()
+    ]
+    
+    let zoomView = UIImageView()
+    let cameraView = UIImageView()
+    
     let status: UILabel = {
     let status: UILabel = {
         let label = UILabel()
         let label = UILabel()
         label.text = "Calling..."
         label.text = "Calling..."
@@ -236,29 +249,41 @@ class QmeraAudioViewController: UIViewController {
         name.anchor(top: profiles.bottomAnchor, left: view.leftAnchor, right: view.rightAnchor, paddingTop: 5, paddingLeft: 20, paddingRight: 20, centerX: view.centerXAnchor)
         name.anchor(top: profiles.bottomAnchor, left: view.leftAnchor, right: view.rightAnchor, paddingTop: 5, paddingLeft: 20, paddingRight: 20, centerX: view.centerXAnchor)
         definesPresentationContext = true
         definesPresentationContext = true
         
         
+        if isOutgoing {
+            outgoingView()
+        } else if isOnGoing {
+            ongoingView()
+        } else {
+            incomingView()
+        }
+        
+        UIDevice.current.isProximityMonitoringEnabled = true
+        
         NotificationCenter.default.addObserver(self, selector: #selector(onStatusCall(_:)), name: NSNotification.Name(rawValue: "onStatusCall"), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(onStatusCall(_:)), name: NSNotification.Name(rawValue: "onStatusCall"), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(onReceiveMessage(notification:)), name: NSNotification.Name(rawValue: "onReceiveChat"), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(onReceiveMessage(notification:)), name: NSNotification.Name(rawValue: "onReceiveChat"), object: nil)
         
         
         if let u = self.user {
         if let u = self.user {
             self.users.append(u)
             self.users.append(u)
-            if isOutgoing {
+            if isOutgoing && ticketId.isEmpty {
 //                let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
 //                let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
 //                if onGoingCC.isEmpty {
 //                if onGoingCC.isEmpty {
 //                    Nexilis.shared.callManager.startCall(handle: u.pin)
 //                    Nexilis.shared.callManager.startCall(handle: u.pin)
 //                } else {
 //                } else {
                     API.initiateCCall(sParty: u.pin)
                     API.initiateCCall(sParty: u.pin)
 //                }
 //                }
+            } else if !ticketId.isEmpty {
+                if isOutgoing {
+                    API.ccs(sTicketID: ticketId, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViewFix, ivLocalView: cameraView, ivRemoteZ: zoomView, bCameraOn: false)
+                    if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getIncomingCallCS(f_pin_opposite: u.pin), timeout: 30 * 1000){
+                        if response.mBodies[CoreMessage_TMessageKey.ERRCOD] != "01" {
+                            self.didEnd(sender: true)
+                        }
+                    }
+                } else {
+                    API.csa(sTicketID: ticketId, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViewFix, ivLocalView: cameraView, ivRemoteZ: zoomView, bCameraOn: false)
+                }
             }
             }
         }
         }
-        
-        if isOutgoing {
-            outgoingView()
-        } else if isOnGoing {
-            ongoingView()
-        } else {
-            incomingView()
-        }
-        UIDevice.current.isProximityMonitoringEnabled = true
     }
     }
     
     
     override func viewWillLayoutSubviews() {
     override func viewWillLayoutSubviews() {
@@ -558,11 +583,6 @@ class QmeraAudioViewController: UIViewController {
                         }
                         }
                     }
                     }
                     self.users.append(User.getData(pin: dataMessage.getPIN())!)
                     self.users.append(User.getData(pin: dataMessage.getPIN())!)
-                    // Start Calling
-                    if !self.isAddCall.isEmpty && self.isAddCall == dataMessage.getPIN() {
-//                        Nexilis.shared.callManager.startCall(handle: dataMessage.getPIN())
-                        API.initiateCCall(sParty: dataMessage.getPIN())
-                    }
                 }
                 }
             }
             }
         }
         }
@@ -574,15 +594,24 @@ class QmeraAudioViewController: UIViewController {
            let message = data["message"] as? String
            let message = data["message"] as? String
         {
         {
             let arrayMessage = message.split(separator: ",")
             let arrayMessage = message.split(separator: ",")
-            if state == 23 {
+            if state == 23 || (!ticketId.isEmpty && state == 33) {
                 if users.count == 1 {
                 if users.count == 1 {
                     DispatchQueue.main.async {
                     DispatchQueue.main.async {
                         self.status.text = "Ringing..."
                         self.status.text = "Ringing..."
                     }
                     }
                 }
                 }
-            } else if state == 22 {
+            } else if state == 22 || (!ticketId.isEmpty && state == 32) {
                 if users.count == 1 && firstCall {
                 if users.count == 1 && firstCall {
                     DispatchQueue.main.async {
                     DispatchQueue.main.async {
+                        if !self.ticketId.isEmpty {
+                            NSLayoutConstraint.deactivate(self.stack.constraints)
+                            self.stack.subviews.forEach { subview in
+                                subview.removeFromSuperview()
+                            }
+                            UIView.animate(withDuration: 0.3, animations: {
+                                self.view.layoutIfNeeded()
+                            })
+                        }
                         self.ongoingView()
                         self.ongoingView()
                         let connectDate = Date()
                         let connectDate = Date()
                         self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
                         self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
@@ -613,7 +642,7 @@ class QmeraAudioViewController: UIViewController {
                         }
                         }
                     }
                     }
                 }
                 }
-            } else if state == 28 {
+            } else if state == 28 || (!ticketId.isEmpty && state == 38) {
                 let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
                 let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
                 if let pin = arrayMessage.first, let index = users.firstIndex(of: User(pin: String(pin))) {
                 if let pin = arrayMessage.first, let index = users.firstIndex(of: User(pin: String(pin))) {
                     users.remove(at: index)
                     users.remove(at: index)

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

@@ -64,6 +64,7 @@ class QmeraVideoViewController: UIViewController {
     var showNotifCCEnd = false
     var showNotifCCEnd = false
     var transformZoomAfterNewUserMore2 = false
     var transformZoomAfterNewUserMore2 = false
     var isAddCall = ""
     var isAddCall = ""
+    var ticketId = ""
     private var frontCamera = true
     private var frontCamera = true
     var users: [User] = []
     var users: [User] = []
     let poweredByView: UIStackView = {
     let poweredByView: UIStackView = {
@@ -189,7 +190,9 @@ class QmeraVideoViewController: UIViewController {
                     row["deviceId"] = cursorData.string(forColumnIndex: 5)
                     row["deviceId"] = cursorData.string(forColumnIndex: 5)
                     row["isOffline"] = cursorData.string(forColumnIndex: 6)
                     row["isOffline"] = cursorData.string(forColumnIndex: 6)
                     row["user_type"] = cursorData.string(forColumnIndex: 7)
                     row["user_type"] = cursorData.string(forColumnIndex: 7)
-                    dataPerson.append(row)
+                    if fPin != User.getMyPin() {
+                        dataPerson.append(row)
+                    }
                 } else {
                 } else {
                     var row: [String: String?] = [:]
                     var row: [String: String?] = [:]
                     row["f_pin"] = fPin
                     row["f_pin"] = fPin
@@ -367,7 +370,16 @@ class QmeraVideoViewController: UIViewController {
         if isInisiator {
         if isInisiator {
             labelIncomingOutgoing.text = "Outgoing video call".localized() + "..."
             labelIncomingOutgoing.text = "Outgoing video call".localized() + "..."
 //            Nexilis.startAudio()
 //            Nexilis.startAudio()
-            API.initiateCCall(sParty: dataPerson[0]["f_pin"]!, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViewFix, ivLocalView: cameraView, ivRemoteZ: zoomView)
+            if ticketId.isEmpty {
+                API.initiateCCall(sParty: dataPerson[0]["f_pin"]!, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViewFix, ivLocalView: cameraView, ivRemoteZ: zoomView)
+            } else {
+                API.ccs(sTicketID: ticketId, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViewFix, ivLocalView: cameraView, ivRemoteZ: zoomView, bCameraOn: true)
+                if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getIncomingCallCS(f_pin_opposite: users[0].pin), timeout: 30 * 1000){
+                    if response.mBodies[CoreMessage_TMessageKey.ERRCOD] != "01" {
+                        endAllCall()
+                    }
+                }
+            }
         } else {
         } else {
             let systemSoundID: SystemSoundID = 1254
             let systemSoundID: SystemSoundID = 1254
             AudioServicesPlaySystemSound(systemSoundID)
             AudioServicesPlaySystemSound(systemSoundID)
@@ -442,21 +454,6 @@ class QmeraVideoViewController: UIViewController {
                             UserDefaults.standard.set("\(members)", forKey: "membersCC")
                             UserDefaults.standard.set("\(members)", forKey: "membersCC")
                         }
                         }
                     }
                     }
-                    // Start Calling
-                    if !self.isAddCall.isEmpty && self.isAddCall == dataMessage.getPIN(){
-                        let user = User.getData(pin: dataMessage.getPIN())!
-                        var dataPerson: [String: String?] = [:]
-                        dataPerson["f_pin"] = user.pin
-                        dataPerson["name"] = user.fullName
-                        dataPerson["picture"] = user.thumb
-                        dataPerson["isOfficial"] = user.official
-                        dataPerson["deviceId"] = user.pin
-                        dataPerson["isOffline"] = ""
-                        dataPerson["user_type"] = user.userType
-                        self.dataPerson.append(dataPerson)
-                        self.users.append(user)
-                        API.initiateCCall(sParty: dataMessage.getPIN(), nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: self.listRemoteViewFix, ivLocalView: self.cameraView, ivRemoteZ: self.zoomView)
-                    }
                 }
                 }
             }
             }
         }
         }
@@ -539,7 +536,11 @@ class QmeraVideoViewController: UIViewController {
                 return
                 return
             }
             }
 //            Nexilis.startAudio()
 //            Nexilis.startAudio()
-            API.receiveCCall(sParty: dataPerson[0]["f_pin"]!, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViewFix, ivLocalView: cameraView,ivRemoteZ: zoomView)
+            if ticketId.isEmpty {
+                API.receiveCCall(sParty: dataPerson[0]["f_pin"]!, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViewFix, ivLocalView: cameraView,ivRemoteZ: zoomView)
+            } else {
+                API.csa(sTicketID: ticketId, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViewFix, ivLocalView: cameraView, ivRemoteZ: zoomView, bCameraOn: true)
+            }
         }
         }
         DispatchQueue.main.async {
         DispatchQueue.main.async {
             self.myImage.removeFromSuperview()
             self.myImage.removeFromSuperview()
@@ -793,6 +794,7 @@ class QmeraVideoViewController: UIViewController {
         cameraView.image = nil
         cameraView.image = nil
         zoomView.image = nil
         zoomView.image = nil
         listRemoteViewFix.removeAll()
         listRemoteViewFix.removeAll()
+        dataPerson.removeAll()
     }
     }
     
     
     func setSpeaker(isSpeaker: Bool) {
     func setSpeaker(isSpeaker: Bool) {

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

@@ -1308,6 +1308,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                     UserDefaults.standard.removeObject(forKey: "waitingRequestCC")
                     UserDefaults.standard.removeObject(forKey: "waitingRequestCC")
                     if dataMessage.getBody(key: CoreMessage_TMessageKey.CHANNEL) != "0" {
                     if dataMessage.getBody(key: CoreMessage_TMessageKey.CHANNEL) != "0" {
                         UserDefaults.standard.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
                         UserDefaults.standard.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
+                        UserDefaults.standard.set(dataMessage.getBody(key: CoreMessage_TMessageKey.CHANNEL), forKey: "channelCC")
                         DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
                         DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
                             self.dismiss(animated: true, completion: nil)
                             self.dismiss(animated: true, completion: nil)
                         })
                         })
@@ -2175,7 +2176,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         }
         }
     }
     }
     
     
-    private func sendChat(message_scope_id:String =  "3", 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 = "", chat_id: String = "", is_call_center: String = "0", call_center_id: String = "", viewController: UIViewController, isAutoSendCC : Bool = false) {
+    private func sendChat(message_scope_id:String =  "3", status:String =  "3", 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, isAutoSendCC : Bool = false) {
         if viewController is EditorPersonal && file_id == "" && dataMessageForward == nil && !isAutoSendCC{
         if viewController is EditorPersonal && file_id == "" && dataMessageForward == nil && !isAutoSendCC{
             if ((textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) == "Send message".localized() && textFieldSend.textColor == UIColor.lightGray && attachment_flag != "11") || textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ) {
             if ((textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines) == "Send message".localized() && textFieldSend.textColor == UIColor.lightGray && attachment_flag != "11") || textFieldSend.text!.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ) {
                 dismissKeyboard()
                 dismissKeyboard()
@@ -2197,6 +2198,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         var call_center_id = call_center_id
         var call_center_id = call_center_id
         var l_pin = dataPerson["f_pin"]!!
         var l_pin = dataPerson["f_pin"]!!
         var message_scope_id = message_scope_id
         var message_scope_id = message_scope_id
+        var chat_id = chat_id
         
         
         if (isContactCenter) {
         if (isContactCenter) {
             if fPinContacCenter.isEmpty && isRequestContactCenter {
             if fPinContacCenter.isEmpty && isRequestContactCenter {
@@ -2214,6 +2216,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
             call_center_id = complaintId
             call_center_id = complaintId
             l_pin = fPinContacCenter
             l_pin = fPinContacCenter
             message_scope_id = "5"
             message_scope_id = "5"
+            chat_id = complaintId
             if isAutoSendCC {
             if isAutoSendCC {
                 timeoutCC = Timer.scheduledTimer(withTimeInterval: 30.0, repeats: false, block: {_ in
                 timeoutCC = Timer.scheduledTimer(withTimeInterval: 30.0, repeats: false, block: {_ in
                     let imageView = UIImageView(image: UIImage(systemName: "info.circle"))
                     let imageView = UIImageView(image: UIImage(systemName: "info.circle"))
@@ -2229,7 +2232,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         let idMe = UserDefaults.standard.string(forKey: "me") as String?
         let idMe = UserDefaults.standard.string(forKey: "me") as String?
         var opposite_pin = ""
         var opposite_pin = ""
         if isContactCenter {
         if isContactCenter {
-            opposite_pin = fPinContacCenter
+            opposite_pin = ""
         } else {
         } else {
             opposite_pin = idMe ?? ""
             opposite_pin = idMe ?? ""
         }
         }

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

@@ -221,7 +221,7 @@ public class ChangeDeviceViewController: UIViewController {
         }
         }
         Nexilis.showLoader()
         Nexilis.showLoader()
         DispatchQueue.global().async {
         DispatchQueue.global().async {
-            let md5Hex = Utils.getMD5(string: password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = password
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignIn(p_name: name, p_password: md5Hex), timeout: 30 * 1000) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignIn(p_name: name, p_password: md5Hex), timeout: 30 * 1000) {
                 if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "11" {
                 if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "11" {
                     DispatchQueue.main.async {
                     DispatchQueue.main.async {

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

@@ -147,7 +147,7 @@ public class ChangeNamePassswordViewController: UIViewController {
                         })
                         })
                     }
                     }
                 } else if resp.isOk() {
                 } else if resp.isOk() {
-                    let md5Hex = Utils.getMD5(string: password).map { String(format: "%02hhx", $0) }.joined()
+                    let md5Hex = password
                     let tMessage = CoreMessage_TMessageBank.getChangePersonInfo_New(p_f_pin: idMe)
                     let tMessage = CoreMessage_TMessageBank.getChangePersonInfo_New(p_f_pin: idMe)
                     tMessage.mBodies[CoreMessage_TMessageKey.FIRST_NAME] = first
                     tMessage.mBodies[CoreMessage_TMessageKey.FIRST_NAME] = first
                     tMessage.mBodies[CoreMessage_TMessageKey.LAST_NAME] = last
                     tMessage.mBodies[CoreMessage_TMessageKey.LAST_NAME] = last

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

@@ -84,8 +84,8 @@ class ChangePasswordViewController: UIViewController {
         let idMe = UserDefaults.standard.string(forKey: "me")!
         let idMe = UserDefaults.standard.string(forKey: "me")!
         DispatchQueue.global().async {
         DispatchQueue.global().async {
             let tMessage = CoreMessage_TMessageBank.getChangePersonInfo_New(p_f_pin: idMe)
             let tMessage = CoreMessage_TMessageBank.getChangePersonInfo_New(p_f_pin: idMe)
-            let md5HexOld = Utils.getMD5(string: oldPassword).map { String(format: "%02hhx", $0) }.joined()
-            let md5HexNew = Utils.getMD5(string: newPassword).map { String(format: "%02hhx", $0) }.joined()
+            let md5HexOld = oldPassword
+            let md5HexNew = newPassword
             tMessage.mBodies[CoreMessage_TMessageKey.PASSWORD] = md5HexNew
             tMessage.mBodies[CoreMessage_TMessageKey.PASSWORD] = md5HexNew
             tMessage.mBodies[CoreMessage_TMessageKey.PASSWORD_OLD] = md5HexOld
             tMessage.mBodies[CoreMessage_TMessageKey.PASSWORD_OLD] = md5HexOld
             if let resp = Nexilis.writeAndWait(message: tMessage){
             if let resp = Nexilis.writeAndWait(message: tMessage){

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

@@ -14,6 +14,8 @@ public class HistoryCCViewController: UITableViewController, QLPreviewController
     public var isOfficer = false
     public var isOfficer = false
     
     
     var previewItem: NSURL?
     var previewItem: NSURL?
+    
+    var fromAPI = false
 
 
     public override func viewDidLoad() {
     public override func viewDidLoad() {
         super.viewDidLoad()
         super.viewDidLoad()
@@ -21,6 +23,21 @@ public class HistoryCCViewController: UITableViewController, QLPreviewController
         
         
         self.view.backgroundColor = .white
         self.view.backgroundColor = .white
         
         
+        if fromAPI {
+            let imageButton = UIImageView(frame: CGRect(x: -16, y: 0, width: 20, height: 44))
+            imageButton.image = UIImage(systemName: "chevron.backward", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular, scale: .default))?.withTintColor(.white)
+            imageButton.contentMode = .left
+            let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapExit))
+            imageButton.isUserInteractionEnabled = true
+            imageButton.addGestureRecognizer(tapGestureRecognizer)
+            let leftItem = UIBarButtonItem(customView: imageButton)
+            self.navigationItem.leftBarButtonItem = leftItem
+        }
+        
+    }
+    
+    @objc func didTapExit() {
+        self.dismiss(animated: true, completion: nil)
     }
     }
     
     
     public override func viewWillAppear(_ animated: Bool) {
     public override func viewWillAppear(_ animated: Bool) {
@@ -58,11 +75,11 @@ public class HistoryCCViewController: UITableViewController, QLPreviewController
         cell.imageOfficer.image = nil
         cell.imageOfficer.image = nil
         if dataOfficer.count > 0 {
         if dataOfficer.count > 0 {
             if isOfficer {
             if isOfficer {
-                cell.labelOfficer.text = dataRequester["name"]!
+                cell.labelOfficer.text = dataRequester["name"] ?? ""
             } else {
             } else {
                 cell.labelOfficer.text = "Officer".localized() + " : " + dataOfficer["name"]!
                 cell.labelOfficer.text = "Officer".localized() + " : " + dataOfficer["name"]!
             }
             }
-            if !(dataOfficer["image"]!).isEmpty || !(dataRequester["image"]!).isEmpty {
+            if !(dataOfficer["image"] ?? "").isEmpty || !(dataRequester["image"] ?? "").isEmpty {
                 if isOfficer {
                 if isOfficer {
                     getImage(name: dataRequester["image"]!, placeholderImage: UIImage(systemName: "person.circle.fill")!, isCircle: true, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
                     getImage(name: dataRequester["image"]!, placeholderImage: UIImage(systemName: "person.circle.fill")!, isCircle: true, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
                         cell.imageOfficer.image = image
                         cell.imageOfficer.image = image

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

@@ -110,11 +110,11 @@ public class ProfileViewController: UITableViewController {
                         } else if User.isCallCenter(userType: user.userType ?? "") {
                         } else if User.isCallCenter(userType: user.userType ?? "") {
                             let dataCategory = CategoryCC.getDataFromServiceId(service_id: user.ex_offmp!)
                             let dataCategory = CategoryCC.getDataFromServiceId(service_id: user.ex_offmp!)
                             self.imageUserType.image = UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
                             self.imageUserType.image = UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
-                            if dataCategory != nil {
-                                self.labelUserType.text = "Call Center (\(dataCategory!.service_name))".localized()
-                            } else {
+//                            if dataCategory != nil {
+//                                self.labelUserType.text = "Call Center (\(dataCategory!.service_name))".localized()
+//                            } else {
                                 self.labelUserType.text = "Call Center".localized()
                                 self.labelUserType.text = "Call Center".localized()
-                            }
+//                            }
 //                            self.buttonHistoryCC.isHidden = true
 //                            self.buttonHistoryCC.isHidden = true
                         }
                         }
                     }
                     }

+ 6 - 6
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SettingTableViewController.swift

@@ -770,7 +770,7 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
         DispatchQueue.global().async {
         DispatchQueue.global().async {
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let p_password = password
             let p_password = password
-            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = p_password
             var result: Bool = false
             var result: Bool = false
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiAdmin(p_name: idMe!, p_password: md5Hex)) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiAdmin(p_name: idMe!, p_password: md5Hex)) {
                 if response.isOk() {
                 if response.isOk() {
@@ -805,7 +805,7 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
         DispatchQueue.global().async {
         DispatchQueue.global().async {
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let p_password = password
             let p_password = password
-            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = p_password
             var result: Bool = false
             var result: Bool = false
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiInternal(p_name: idMe!, p_password: md5Hex)) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiInternal(p_name: idMe!, p_password: md5Hex)) {
                 if response.isOk() {
                 if response.isOk() {
@@ -841,8 +841,8 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let p_password = oldPassword
             let p_password = oldPassword
             let n_password = newPassword
             let n_password = newPassword
-            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
-            let md5HexNew = Utils.getMD5(string: n_password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = p_password
+            let md5HexNew = n_password
             var result: Bool = false
             var result: Bool = false
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordAdmin(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordAdmin(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
                 if response.isOk() {
                 if response.isOk() {
@@ -878,8 +878,8 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let idMe = UserDefaults.standard.string(forKey: "me") as String?
             let p_password = oldPassword
             let p_password = oldPassword
             let n_password = newPassword
             let n_password = newPassword
-            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
-            let md5HexNew = Utils.getMD5(string: n_password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = p_password
+            let md5HexNew = n_password
             var result: Bool = false
             var result: Bool = false
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordInternal(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordInternal(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
                 if response.isOk() {
                 if response.isOk() {

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

@@ -251,7 +251,7 @@ public class SignUpSignIn: UIViewController {
         }
         }
         Nexilis.showLoader()
         Nexilis.showLoader()
         DispatchQueue.global().async {
         DispatchQueue.global().async {
-            let md5Hex = Utils.getMD5(string: password).map { String(format: "%02hhx", $0) }.joined()
+            let md5Hex = password
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignUpSignInAPI(p_name: name, p_password: md5Hex), timeout: 30 * 1000) {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignUpSignInAPI(p_name: name, p_password: md5Hex), timeout: 30 * 1000) {
                 if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "20" {
                 if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "20" {
                     DispatchQueue.main.async {
                     DispatchQueue.main.async {