Bläddra i källkod

commit appbuilder

kevin 3 år sedan
förälder
incheckning
5564a04eb1
67 ändrade filer med 4571 tillägg och 0 borttagningar
  1. BIN
      .DS_Store
  2. 5 0
      .gitignore
  3. BIN
      appbuilder-ios/.DS_Store
  4. BIN
      appbuilder-ios/AppBuilder/.DS_Store
  5. 508 0
      appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.pbxproj
  6. 7 0
      appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  7. 8 0
      appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  8. BIN
      appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.xcworkspace/xcuserdata/easysoft.xcuserdatad/UserInterfaceState.xcuserstate
  9. BIN
      appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.xcworkspace/xcuserdata/qindi.xcuserdatad/UserInterfaceState.xcuserstate
  10. 98 0
      appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/xcshareddata/xcschemes/AppBuilder.xcscheme
  11. 14 0
      appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/xcuserdata/easysoft.xcuserdatad/xcschemes/xcschememanagement.plist
  12. 10 0
      appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/contents.xcworkspacedata
  13. 8 0
      appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  14. 5 0
      appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/easysoft.xcuserdatad/IDEFindNavigatorScopes.plist
  15. BIN
      appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/easysoft.xcuserdatad/UserInterfaceState.xcuserstate
  16. 6 0
      appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/easysoft.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  17. BIN
      appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/maronakins.xcuserdatad/UserInterfaceState.xcuserstate
  18. 200 0
      appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/maronakins.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  19. BIN
      appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/qindi.xcuserdatad/UserInterfaceState.xcuserstate
  20. 174 0
      appbuilder-ios/AppBuilder/AppBuilder/AppDelegate.swift
  21. 11 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AccentColor.colorset/Contents.json
  22. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/1024.png
  23. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/114.png
  24. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/120.png
  25. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/180.png
  26. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/29.png
  27. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/40.png
  28. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/57.png
  29. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/58.png
  30. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/60.png
  31. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/80.png
  32. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/87.png
  33. 80 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/Contents.json
  34. 6 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/Contents.json
  35. 21 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_icon.imageset/Contents.json
  36. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_icon.imageset/nexilis_icon.png
  37. 21 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_lbackground_1.imageset/Contents.json
  38. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_lbackground_1.imageset/pb_lbackground_1.png
  39. 21 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_powered_button.imageset/Contents.json
  40. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_powered_button.imageset/pb_powered_button.png
  41. 21 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_1_icon.imageset/Contents.json
  42. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_1_icon.imageset/tab_1_nexilis.png
  43. 21 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_2_icon.imageset/Contents.json
  44. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_2_icon.imageset/tab_2_nexilis.png
  45. 21 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_3_icon.imageset/Contents.json
  46. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_3_icon.imageset/tab_3_nexilis.png
  47. 21 0
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_4_icon.imageset/Contents.json
  48. BIN
      appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_4_icon.imageset/tab_4_nexilis.png
  49. 48 0
      appbuilder-ios/AppBuilder/AppBuilder/Base.lproj/LaunchScreen.storyboard
  50. 342 0
      appbuilder-ios/AppBuilder/AppBuilder/Base.lproj/Main.storyboard
  51. 145 0
      appbuilder-ios/AppBuilder/AppBuilder/FirstTabViewController.swift
  52. 724 0
      appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift
  53. 102 0
      appbuilder-ios/AppBuilder/AppBuilder/Info.plist
  54. 185 0
      appbuilder-ios/AppBuilder/AppBuilder/PrefsUtil.swift
  55. 52 0
      appbuilder-ios/AppBuilder/AppBuilder/SceneDelegate.swift
  56. 919 0
      appbuilder-ios/AppBuilder/AppBuilder/SecondTabViewController.swift
  57. 141 0
      appbuilder-ios/AppBuilder/AppBuilder/ThirdTabViewController.swift
  58. 595 0
      appbuilder-ios/AppBuilder/AppBuilder/ViewController.swift
  59. BIN
      appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-Light.ttf
  60. BIN
      appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-LightItalic.ttf
  61. BIN
      appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-Medium.ttf
  62. BIN
      appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-MediumItalic.ttf
  63. BIN
      appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-Regular.ttf
  64. BIN
      appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-SemiBold.ttf
  65. BIN
      appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-SemiBoldItalic.ttf
  66. 31 0
      appbuilder-ios/AppBuilder/Podfile
  67. BIN
      appbuilder-ios/NexilisLite/.DS_Store

BIN
.DS_Store


+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+AppBuilder.xcodeproj/xcuserdata/
+AppBuilder.xcworkspace/xcuserdata/
+Pods/
+.DS_Store
+Podfile.lock

BIN
appbuilder-ios/.DS_Store


BIN
appbuilder-ios/AppBuilder/.DS_Store


+ 508 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.pbxproj

@@ -0,0 +1,508 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 51;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		12960AE02892361000A467DD /* FourthTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12960ADF2892361000A467DD /* FourthTabViewController.swift */; };
+		2401CE9A275490DB00B323BB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2401CE99275490DB00B323BB /* AppDelegate.swift */; };
+		2401CE9C275490DB00B323BB /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2401CE9B275490DB00B323BB /* SceneDelegate.swift */; };
+		2401CE9E275490DB00B323BB /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2401CE9D275490DB00B323BB /* ViewController.swift */; };
+		2401CEA1275490DB00B323BB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2401CE9F275490DB00B323BB /* Main.storyboard */; };
+		2401CEA3275490E600B323BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2401CEA2275490E600B323BB /* Assets.xcassets */; };
+		2401CEA6275490E600B323BB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2401CEA4275490E600B323BB /* LaunchScreen.storyboard */; };
+		A413B18727EACB20006D16EB /* PrefsUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = A413B18627EACB20006D16EB /* PrefsUtil.swift */; };
+		A42ED92227F30BA200B0FAB7 /* FirstTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A42ED92127F30BA200B0FAB7 /* FirstTabViewController.swift */; };
+		A42ED92427F3FC2F00B0FAB7 /* SecondTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A42ED92327F3FC2F00B0FAB7 /* SecondTabViewController.swift */; };
+		A42ED92627F439A200B0FAB7 /* ThirdTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A42ED92527F439A200B0FAB7 /* ThirdTabViewController.swift */; };
+		A4B5F03E27F193DD0089B871 /* Poppins-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A4B5F03727F193DC0089B871 /* Poppins-Light.ttf */; };
+		A4B5F03F27F193DD0089B871 /* Poppins-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A4B5F03827F193DC0089B871 /* Poppins-Medium.ttf */; };
+		A4B5F04027F193DD0089B871 /* Poppins-SemiBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A4B5F03927F193DC0089B871 /* Poppins-SemiBoldItalic.ttf */; };
+		A4B5F04127F193DD0089B871 /* Poppins-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A4B5F03A27F193DC0089B871 /* Poppins-Regular.ttf */; };
+		A4B5F04227F193DD0089B871 /* Poppins-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A4B5F03B27F193DC0089B871 /* Poppins-LightItalic.ttf */; };
+		A4B5F04327F193DD0089B871 /* Poppins-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A4B5F03C27F193DC0089B871 /* Poppins-SemiBold.ttf */; };
+		A4B5F04427F193DD0089B871 /* Poppins-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A4B5F03D27F193DC0089B871 /* Poppins-MediumItalic.ttf */; };
+		D97787F5841788DD7CA5D22E /* Pods_AppBuilder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9E4106B3479B94418329D80 /* Pods_AppBuilder.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		247E0A722796969200430E5F /* Embed Frameworks */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 10;
+			files = (
+			);
+			name = "Embed Frameworks";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		0DA67759833E5D05CCC5F918 /* Pods_AppBuilder_AppBuilderTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppBuilder_AppBuilderTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		12960ADF2892361000A467DD /* FourthTabViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FourthTabViewController.swift; sourceTree = "<group>"; };
+		17C212CC198CF15351DAB5D9 /* 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>"; };
+		1AFA5DE79F538A842695875B /* 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>"; };
+		2401CE96275490DB00B323BB /* AppBuilder.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppBuilder.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		2401CE99275490DB00B323BB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+		2401CE9B275490DB00B323BB /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
+		2401CE9D275490DB00B323BB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
+		2401CEA0275490DB00B323BB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; 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>"; };
+		2401CEA7275490E600B323BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		64D75EB30B05A0FFB0CD4A15 /* Pods_AppBuilder_AppBuilderUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppBuilder_AppBuilderUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		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>"; };
+		A42ED92327F3FC2F00B0FAB7 /* SecondTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondTabViewController.swift; sourceTree = "<group>"; };
+		A42ED92527F439A200B0FAB7 /* ThirdTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdTabViewController.swift; sourceTree = "<group>"; };
+		A4B5F03727F193DC0089B871 /* Poppins-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-Light.ttf"; sourceTree = "<group>"; };
+		A4B5F03827F193DC0089B871 /* Poppins-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-Medium.ttf"; sourceTree = "<group>"; };
+		A4B5F03927F193DC0089B871 /* Poppins-SemiBoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-SemiBoldItalic.ttf"; sourceTree = "<group>"; };
+		A4B5F03A27F193DC0089B871 /* Poppins-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-Regular.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>"; };
+		A4B5F03D27F193DC0089B871 /* Poppins-MediumItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-MediumItalic.ttf"; sourceTree = "<group>"; };
+		F9E4106B3479B94418329D80 /* Pods_AppBuilder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppBuilder.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		2401CE93275490DB00B323BB /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D97787F5841788DD7CA5D22E /* Pods_AppBuilder.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		2401CE8D275490DB00B323BB = {
+			isa = PBXGroup;
+			children = (
+				2401CE98275490DB00B323BB /* AppBuilder */,
+				2401CE97275490DB00B323BB /* Products */,
+				6E32BCCF4DE50EE1A90E8AAE /* Pods */,
+				EC8D46330C460C606FF6529D /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		2401CE97275490DB00B323BB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				2401CE96275490DB00B323BB /* AppBuilder.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		2401CE98275490DB00B323BB /* AppBuilder */ = {
+			isa = PBXGroup;
+			children = (
+				A4B5F03627F193DC0089B871 /* fonts */,
+				2401CE99275490DB00B323BB /* AppDelegate.swift */,
+				2401CE9B275490DB00B323BB /* SceneDelegate.swift */,
+				2401CE9D275490DB00B323BB /* ViewController.swift */,
+				2401CE9F275490DB00B323BB /* Main.storyboard */,
+				2401CEA2275490E600B323BB /* Assets.xcassets */,
+				2401CEA4275490E600B323BB /* LaunchScreen.storyboard */,
+				2401CEA7275490E600B323BB /* Info.plist */,
+				A413B18627EACB20006D16EB /* PrefsUtil.swift */,
+				A42ED92127F30BA200B0FAB7 /* FirstTabViewController.swift */,
+				A42ED92327F3FC2F00B0FAB7 /* SecondTabViewController.swift */,
+				A42ED92527F439A200B0FAB7 /* ThirdTabViewController.swift */,
+				12960ADF2892361000A467DD /* FourthTabViewController.swift */,
+			);
+			path = AppBuilder;
+			sourceTree = "<group>";
+		};
+		6E32BCCF4DE50EE1A90E8AAE /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				1AFA5DE79F538A842695875B /* Pods-AppBuilder.debug.xcconfig */,
+				17C212CC198CF15351DAB5D9 /* Pods-AppBuilder.release.xcconfig */,
+			);
+			path = Pods;
+			sourceTree = "<group>";
+		};
+		A4B5F03627F193DC0089B871 /* fonts */ = {
+			isa = PBXGroup;
+			children = (
+				A4B5F03727F193DC0089B871 /* Poppins-Light.ttf */,
+				A4B5F03827F193DC0089B871 /* Poppins-Medium.ttf */,
+				A4B5F03927F193DC0089B871 /* Poppins-SemiBoldItalic.ttf */,
+				A4B5F03A27F193DC0089B871 /* Poppins-Regular.ttf */,
+				A4B5F03B27F193DC0089B871 /* Poppins-LightItalic.ttf */,
+				A4B5F03C27F193DC0089B871 /* Poppins-SemiBold.ttf */,
+				A4B5F03D27F193DC0089B871 /* Poppins-MediumItalic.ttf */,
+			);
+			path = fonts;
+			sourceTree = "<group>";
+		};
+		EC8D46330C460C606FF6529D /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				F9E4106B3479B94418329D80 /* Pods_AppBuilder.framework */,
+				0DA67759833E5D05CCC5F918 /* Pods_AppBuilder_AppBuilderTests.framework */,
+				64D75EB30B05A0FFB0CD4A15 /* Pods_AppBuilder_AppBuilderUITests.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		2401CE95275490DB00B323BB /* AppBuilder */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2401CEC0275490E600B323BB /* Build configuration list for PBXNativeTarget "AppBuilder" */;
+			buildPhases = (
+				0F7EEEDCC8B3DA357207C77A /* [CP] Check Pods Manifest.lock */,
+				2401CE92275490DB00B323BB /* Sources */,
+				2401CE93275490DB00B323BB /* Frameworks */,
+				2401CE94275490DB00B323BB /* Resources */,
+				66DF055B3D0DA2B0E04E06CA /* [CP] Embed Pods Frameworks */,
+				247E0A722796969200430E5F /* Embed Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = AppBuilder;
+			productName = TestQmeraLite;
+			productReference = 2401CE96275490DB00B323BB /* AppBuilder.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		2401CE8E275490DB00B323BB /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 1250;
+				LastUpgradeCheck = 1250;
+				TargetAttributes = {
+					2401CE95275490DB00B323BB = {
+						CreatedOnToolsVersion = 12.5.1;
+					};
+				};
+			};
+			buildConfigurationList = 2401CE91275490DB00B323BB /* Build configuration list for PBXProject "AppBuilder" */;
+			compatibilityVersion = "Xcode 9.3";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 2401CE8D275490DB00B323BB;
+			productRefGroup = 2401CE97275490DB00B323BB /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				2401CE95275490DB00B323BB /* AppBuilder */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		2401CE94275490DB00B323BB /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A4B5F04427F193DD0089B871 /* Poppins-MediumItalic.ttf in Resources */,
+				A4B5F03E27F193DD0089B871 /* Poppins-Light.ttf in Resources */,
+				2401CEA6275490E600B323BB /* LaunchScreen.storyboard in Resources */,
+				A4B5F04027F193DD0089B871 /* Poppins-SemiBoldItalic.ttf in Resources */,
+				A4B5F03F27F193DD0089B871 /* Poppins-Medium.ttf in Resources */,
+				A4B5F04327F193DD0089B871 /* Poppins-SemiBold.ttf in Resources */,
+				2401CEA3275490E600B323BB /* Assets.xcassets in Resources */,
+				2401CEA1275490DB00B323BB /* Main.storyboard in Resources */,
+				A4B5F04227F193DD0089B871 /* Poppins-LightItalic.ttf in Resources */,
+				A4B5F04127F193DD0089B871 /* Poppins-Regular.ttf in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		0F7EEEDCC8B3DA357207C77A /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-AppBuilder-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		66DF055B3D0DA2B0E04E06CA /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-AppBuilder/Pods-AppBuilder-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-AppBuilder/Pods-AppBuilder-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AppBuilder/Pods-AppBuilder-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		2401CE92275490DB00B323BB /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A42ED92427F3FC2F00B0FAB7 /* SecondTabViewController.swift in Sources */,
+				A413B18727EACB20006D16EB /* PrefsUtil.swift in Sources */,
+				A42ED92227F30BA200B0FAB7 /* FirstTabViewController.swift in Sources */,
+				A42ED92627F439A200B0FAB7 /* ThirdTabViewController.swift in Sources */,
+				2401CE9E275490DB00B323BB /* ViewController.swift in Sources */,
+				2401CE9A275490DB00B323BB /* AppDelegate.swift in Sources */,
+				12960AE02892361000A467DD /* FourthTabViewController.swift in Sources */,
+				2401CE9C275490DB00B323BB /* SceneDelegate.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		2401CE9F275490DB00B323BB /* Main.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				2401CEA0275490DB00B323BB /* Base */,
+			);
+			name = Main.storyboard;
+			sourceTree = "<group>";
+		};
+		2401CEA4275490E600B323BB /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				2401CEA5275490E600B323BB /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		2401CEBE275490E600B323BB /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 14.5;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+			};
+			name = Debug;
+		};
+		2401CEBF275490E600B323BB /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 14.5;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_COMPILATION_MODE = wholemodule;
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		2401CEC1275490E600B323BB /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 1AFA5DE79F538A842695875B /* Pods-AppBuilder.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
+				CODE_SIGN_IDENTITY = "Apple Development";
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = WM6NB9V368;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/Frameworks",
+				);
+				INFOPLIST_FILE = AppBuilder/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0.0;
+				PRODUCT_BUNDLE_IDENTIFIER = io.newuniverse.AppBuilder420;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "";
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = 1;
+			};
+			name = Debug;
+		};
+		2401CEC2275490E600B323BB /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 17C212CC198CF15351DAB5D9 /* Pods-AppBuilder.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
+				CODE_SIGN_IDENTITY = "Apple Development";
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = WM6NB9V368;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/Frameworks",
+				);
+				INFOPLIST_FILE = AppBuilder/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0.0;
+				PRODUCT_BUNDLE_IDENTIFIER = io.newuniverse.AppBuilder420;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "";
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = 1;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		2401CE91275490DB00B323BB /* Build configuration list for PBXProject "AppBuilder" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2401CEBE275490E600B323BB /* Debug */,
+				2401CEBF275490E600B323BB /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		2401CEC0275490E600B323BB /* Build configuration list for PBXNativeTarget "AppBuilder" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2401CEC1275490E600B323BB /* Debug */,
+				2401CEC2275490E600B323BB /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 2401CE8E275490DB00B323BB /* Project object */;
+}

+ 7 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>

+ 8 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>

BIN
appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.xcworkspace/xcuserdata/easysoft.xcuserdatad/UserInterfaceState.xcuserstate


BIN
appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/project.xcworkspace/xcuserdata/qindi.xcuserdatad/UserInterfaceState.xcuserstate


+ 98 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/xcshareddata/xcschemes/AppBuilder.xcscheme

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1250"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2401CE95275490DB00B323BB"
+               BuildableName = "AppBuilder.app"
+               BlueprintName = "AppBuilder"
+               ReferencedContainer = "container:AppBuilder.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2401CEAB275490E600B323BB"
+               BuildableName = "AppBuilderTests.xctest"
+               BlueprintName = "AppBuilderTests"
+               ReferencedContainer = "container:AppBuilder.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2401CEB6275490E600B323BB"
+               BuildableName = "AppBuilderUITests.xctest"
+               BlueprintName = "AppBuilderUITests"
+               ReferencedContainer = "container:AppBuilder.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "2401CE95275490DB00B323BB"
+            BuildableName = "AppBuilder.app"
+            BlueprintName = "AppBuilder"
+            ReferencedContainer = "container:AppBuilder.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "2401CE95275490DB00B323BB"
+            BuildableName = "AppBuilder.app"
+            BlueprintName = "AppBuilder"
+            ReferencedContainer = "container:AppBuilder.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Debug"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 14 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcodeproj/xcuserdata/easysoft.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>AppBuilder.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 10 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:AppBuilder.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+</Workspace>

+ 8 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>

+ 5 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/easysoft.xcuserdatad/IDEFindNavigatorScopes.plist

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array/>
+</plist>

BIN
appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/easysoft.xcuserdatad/UserInterfaceState.xcuserstate


+ 6 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/easysoft.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Bucket
+   uuid = "B78A7D79-B865-4E03-BFF3-7C45906BC9CA"
+   type = "0"
+   version = "2.0">
+</Bucket>

BIN
appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/maronakins.xcuserdatad/UserInterfaceState.xcuserstate


+ 200 - 0
appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/maronakins.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Bucket
+   uuid = "0C8145CA-38F4-45EE-830B-81836B7942D4"
+   type = "0"
+   version = "2.0">
+   <Breakpoints>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "A6B12BB7-8FA2-41BF-901D-ED6E7EB24E9B"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/ViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "79"
+            endingLineNumber = "79"
+            landmarkName = "viewDidLoad()"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "79E77E68-3240-4C22-8D9F-A32DBDFB08A5"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/ViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "81"
+            endingLineNumber = "81"
+            landmarkName = "viewDidLoad()"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "8A53EC4B-F44F-405F-8950-A31687F0A496"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/ViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "83"
+            endingLineNumber = "83"
+            landmarkName = "viewDidLoad()"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "9DEDC0FC-980A-41BD-AD40-7CB7BCC79DED"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/ViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "85"
+            endingLineNumber = "85"
+            landmarkName = "viewDidLoad()"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "E891BDAB-FAA5-42DA-8B02-95CF81109783"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/ViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "74"
+            endingLineNumber = "74"
+            landmarkName = "viewDidLoad()"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "4CB4CE68-9070-45D4-823C-3B5DC98F0BC5"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/FourthTabViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "131"
+            endingLineNumber = "131"
+            landmarkName = "viewWillAppear(_:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "B7B4DF8D-8898-4BA5-A08D-FC3232FA6A62"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/FourthTabViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "132"
+            endingLineNumber = "132"
+            landmarkName = "viewWillAppear(_:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "BF47E607-BBE1-48E6-8934-C0B74B7C8765"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/FourthTabViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "75"
+            endingLineNumber = "75"
+            landmarkName = "makeMenu()"
+            landmarkType = "7">
+            <Locations>
+               <Location
+                  uuid = "BF47E607-BBE1-48E6-8934-C0B74B7C8765 - c14ec7cf25500f46"
+                  shouldBeEnabled = "Yes"
+                  ignoreCount = "0"
+                  continueAfterRunningActions = "No"
+                  symbolName = "closure #1 (__C.FMDatabase, Swift.UnsafeMutablePointer&lt;ObjectiveC.ObjCBool&gt;) -&gt; () in AppBuilder.FourthTabViewController.makeMenu() -&gt; ()"
+                  moduleName = "AppBuilder"
+                  usesParentBreakpointCondition = "Yes"
+                  urlString = "file:///Users/maronakins/appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift"
+                  startingColumnNumber = "9223372036854775807"
+                  endingColumnNumber = "9223372036854775807"
+                  startingLineNumber = "75"
+                  endingLineNumber = "75"
+                  offsetFromSymbolStart = "5516">
+               </Location>
+               <Location
+                  uuid = "BF47E607-BBE1-48E6-8934-C0B74B7C8765 - c14ec7cf25500f46"
+                  shouldBeEnabled = "Yes"
+                  ignoreCount = "0"
+                  continueAfterRunningActions = "No"
+                  symbolName = "closure #1 (__C.FMDatabase, Swift.UnsafeMutablePointer&lt;ObjectiveC.ObjCBool&gt;) -&gt; () in AppBuilder.FourthTabViewController.makeMenu() -&gt; ()"
+                  moduleName = "AppBuilder"
+                  usesParentBreakpointCondition = "Yes"
+                  urlString = "file:///Users/maronakins/appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift"
+                  startingColumnNumber = "9223372036854775807"
+                  endingColumnNumber = "9223372036854775807"
+                  startingLineNumber = "75"
+                  endingLineNumber = "75"
+                  offsetFromSymbolStart = "5568">
+               </Location>
+            </Locations>
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "A4F552A5-D0F3-43BE-8275-D417858C7336"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/FourthTabViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "266"
+            endingLineNumber = "266"
+            landmarkName = "tableView(_:didSelectRowAt:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            uuid = "6A9CD5E2-73CC-4648-94E1-EEDC8E0BF4AF"
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "AppBuilder/FourthTabViewController.swift"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "267"
+            endingLineNumber = "267"
+            landmarkName = "tableView(_:didSelectRowAt:)"
+            landmarkType = "7">
+         </BreakpointContent>
+      </BreakpointProxy>
+   </Breakpoints>
+</Bucket>

BIN
appbuilder-ios/AppBuilder/AppBuilder.xcworkspace/xcuserdata/qindi.xcuserdatad/UserInterfaceState.xcuserstate


+ 174 - 0
appbuilder-ios/AppBuilder/AppBuilder/AppDelegate.swift

@@ -0,0 +1,174 @@
+//
+//  AppDelegate.swift
+//  TestQmeraLite
+//
+//  Created by Qindi on 29/11/21.
+//
+
+import UIKit
+import NexilisLite
+
+struct AppFontName {
+    static let regular = "Poppins-Regular"
+    static let bold = "Poppins-SemiBold"
+    static let italic = "Poppins-MediumItalic"
+}
+
+extension UIFontDescriptor.AttributeName {
+    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
+}
+
+extension UIFont {
+    static var isOverrided: Bool = false
+    static let FONT_SELECT = 0
+
+    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont {
+        return UIFont(name: AppFontName.regular, size: size)!
+    }
+
+    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont {
+        return UIFont(name: AppFontName.bold, size: size)!
+    }
+
+    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont {
+        return UIFont(name: AppFontName.italic, size: size)!
+    }
+
+    @objc convenience init(myCoder aDecoder: NSCoder) {
+        guard
+            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
+            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
+                self.init(myCoder: aDecoder)
+                return
+        }
+        var fontName = ""
+        switch fontAttribute {
+        case "CTFontRegularUsage":
+            fontName = AppFontName.regular
+        case "CTFontEmphasizedUsage", "CTFontBoldUsage":
+            fontName = AppFontName.bold
+        case "CTFontObliqueUsage":
+            fontName = AppFontName.italic
+        default:
+            fontName = AppFontName.regular
+        }
+        self.init(name: fontName, size: fontDescriptor.pointSize)!
+    }
+
+    class func overrideInitialize() {
+        guard self == UIFont.self, !isOverrided, FONT_SELECT == 0 else { return }
+
+        // Avoid method swizzling run twice and revert to original initialize function
+        isOverrided = true
+
+        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
+            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) {
+            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
+        }
+
+        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
+            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) {
+            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
+        }
+
+        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
+            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) {
+            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
+        }
+
+        if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))), // Trick to get over the lack of UIFont.init(coder:))
+            let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
+            method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
+        }
+    }
+}
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+    override init() {
+        super.init()
+        UIFont.overrideInitialize()
+    }
+    
+    func transparentNavbar(){
+        // Sets background to a blank/empty image
+            UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
+            // Sets shadow (line below the bar) to a blank image
+            UINavigationBar.appearance().shadowImage = UIImage()
+            // Sets the translucent background color
+            UINavigationBar.appearance().backgroundColor = .clear
+            // Set translucent. (Default value is already true, so this can be removed if desired.)
+            UINavigationBar.appearance().isTranslucent = true
+    }
+
+    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+        // Override point for customization after application launch.
+//        Nexilis.connect(apiKey: "09ED34439CFE435E5D528E73F2D3DC1B23307B56EAB28A4883700D47BB5ADE07", delegate: self)
+//        Nexilis.connect(apiKey: "E6FF534BDA45A78619488E44AC90592327DDF33ACF6213A58DB55B78300BA8EE", delegate: self)
+        Nexilis.connect(apiKey: "***REPLACE***WITH***YOUR***ACCOUNT***", delegate: self)
+        if let response = Nexilis.writeSync(message: getPrefs(key: ""), timeout: 5000) {
+            if response.mBodies[CoreMessage_TMessageKey.ERRCOD] == "00" {
+                let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
+                if let json = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: []) as? [[String: Any?]] {
+                    for j in json {
+                        if let firstTab = j["app_builder_url_first_tab"] as? String {
+                            print("first tab: \(firstTab)")
+                            PrefsUtil.setURLFirstTab(value: firstTab)
+                            ViewController.sURL = firstTab
+                        }
+                        if let thirdTab = j["app_builder_url_third_tab"] as? String {
+                            print("third tab: \(thirdTab)")
+                            PrefsUtil.setURLThirdTab(value: thirdTab)
+                            ViewController.tab3 = thirdTab
+                        }
+                        if let customTab = j["app_builder_custom_tab"] as? String {
+                            print("custom tab: \(customTab)")
+                            PrefsUtil.setCustomTab(cust: customTab)
+                        }
+                    }
+                }
+            }
+        }
+        return true
+    }
+
+    // MARK: UISceneSession Lifecycle
+
+    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+        // Called when a new scene session is being created.
+        // Use this method to select a configuration to create the new scene with.
+        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+    }
+
+    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
+        // Called when the user discards a scene session.
+        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+    }
+    
+    func getPrefs(key: String) -> TMessage {
+        let tMessage = NexilisLite.TMessage()
+        let me = UserDefaults.standard.string(forKey: "me")
+        tMessage.mCode = "PPR"
+        tMessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tMessage.mBodies[CoreMessage_TMessageKey.F_PIN] = me
+        tMessage.mBodies[CoreMessage_TMessageKey.KEY] = key
+        return tMessage
+    }
+
+
+}
+
+extension AppDelegate: ConnectDelegate {
+    
+    func onSuccess(userId: String) {
+        print(#function, "userId: \(userId)")
+    }
+    
+    func onFailed(error: String) {
+        print(#function, "error: \(error)")
+    }
+    
+}
+

+ 11 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AccentColor.colorset/Contents.json

@@ -0,0 +1,11 @@
+{
+  "colors" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/1024.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/114.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/120.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/180.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/29.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/40.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/57.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/58.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/60.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/80.png


BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/87.png


+ 80 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -0,0 +1,80 @@
+{
+  "images" : [
+    {
+      "filename" : "40.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "60.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "29.png",
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "58.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "87.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "80.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "120.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "57.png",
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "size" : "57x57"
+    },
+    {
+      "filename" : "114.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "57x57"
+    },
+    {
+      "filename" : "120.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "60x60"
+    },
+    {
+      "filename" : "180.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "60x60"
+    },
+    {
+      "filename" : "1024.png",
+      "idiom" : "ios-marketing",
+      "scale" : "1x",
+      "size" : "1024x1024"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 6 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 21 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_icon.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "nexilis_icon.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_icon.imageset/nexilis_icon.png


+ 21 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_lbackground_1.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "pb_lbackground_1.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_lbackground_1.imageset/pb_lbackground_1.png


+ 21 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_powered_button.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "pb_powered_button.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/pb_powered_button.imageset/pb_powered_button.png


+ 21 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_1_icon.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "tab_1_nexilis.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_1_icon.imageset/tab_1_nexilis.png


+ 21 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_2_icon.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "tab_2_nexilis.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_2_icon.imageset/tab_2_nexilis.png


+ 21 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_3_icon.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "tab_3_nexilis.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_3_icon.imageset/tab_3_nexilis.png


+ 21 - 0
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_4_icon.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "tab_4_nexilis.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/Assets.xcassets/tab_4_icon.imageset/tab_4_nexilis.png


+ 48 - 0
appbuilder-ios/AppBuilder/AppBuilder/Base.lproj/LaunchScreen.storyboard

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="pb_icon" translatesAutoresizingMaskIntoConstraints="NO" id="Dki-8X-fvw">
+                                <rect key="frame" x="82" y="323" width="250" height="250"/>
+                                <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="250" id="Kvz-Gz-JlQ"/>
+                                    <constraint firstAttribute="width" constant="250" id="YUt-RC-lbI"/>
+                                </constraints>
+                            </imageView>
+                        </subviews>
+                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstItem="Dki-8X-fvw" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="P1E-dg-6gJ"/>
+                            <constraint firstItem="Dki-8X-fvw" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="ZXk-uU-Old"/>
+                        </constraints>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="pb_icon" width="169" height="168"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 342 - 0
appbuilder-ios/AppBuilder/AppBuilder/Base.lproj/Main.storyboard

@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="nD6-T3-59p">
+    <device id="retina6_7" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--Item 2-->
+        <scene sceneID="3Wf-gK-qyG">
+            <objects>
+                <viewController id="yL2-sh-r2b" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Cwo-Ej-asl">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <viewLayoutGuide key="safeArea" id="NCr-Sf-zM1"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </view>
+                    <tabBarItem key="tabBarItem" title="Item 2" id="3tr-an-hLR"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Fum-Sw-dKP" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-94" y="525"/>
+        </scene>
+        <!--First Tab View Controller-->
+        <scene sceneID="bNR-du-k4c">
+            <objects>
+                <viewController storyboardIdentifier="firstTabVC" useStoryboardIdentifierAsRestorationIdentifier="YES" id="iKy-YH-N88" customClass="FirstTabViewController" customModule="AppBuilder" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="OUO-5T-AtV">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <wkWebView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zT9-mO-2xu">
+                                <rect key="frame" x="0.0" y="44" width="428" height="848"/>
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <wkWebViewConfiguration key="configuration">
+                                    <audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
+                                    <wkPreferences key="preferences"/>
+                                </wkWebViewConfiguration>
+                            </wkWebView>
+                        </subviews>
+                        <viewLayoutGuide key="safeArea" id="f2x-TV-t0G"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="zT9-mO-2xu" firstAttribute="leading" secondItem="f2x-TV-t0G" secondAttribute="leading" id="IO4-cU-dmV"/>
+                            <constraint firstItem="zT9-mO-2xu" firstAttribute="top" secondItem="f2x-TV-t0G" secondAttribute="top" id="NUS-DV-p70"/>
+                            <constraint firstItem="f2x-TV-t0G" firstAttribute="trailing" secondItem="zT9-mO-2xu" secondAttribute="trailing" id="OHq-JX-jnE"/>
+                            <constraint firstItem="f2x-TV-t0G" firstAttribute="bottom" secondItem="zT9-mO-2xu" secondAttribute="bottom" id="OUP-JZ-QoH"/>
+                        </constraints>
+                    </view>
+                    <connections>
+                        <outlet property="webView" destination="zT9-mO-2xu" id="9yf-9r-PmW"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="1UN-B6-dct" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-772" y="1185"/>
+        </scene>
+        <!--Second Tab View Controller-->
+        <scene sceneID="JH2-j3-Jce">
+            <objects>
+                <viewController storyboardIdentifier="secondTabVC" useStoryboardIdentifierAsRestorationIdentifier="YES" id="z6f-Hz-Xwh" customClass="SecondTabViewController" customModule="AppBuilder" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="T1X-gt-fSN">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="pb_lbackground_1" translatesAutoresizingMaskIntoConstraints="NO" id="BU2-P5-16y">
+                                <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                            </imageView>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oT8-Uw-cgS">
+                                <rect key="frame" x="0.0" y="44" width="428" height="848"/>
+                                <subviews>
+                                    <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="4Jc-b8-aeF">
+                                        <rect key="frame" x="0.0" y="0.0" width="428" height="848"/>
+                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                        <prototypes>
+                                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="reuseIdentifierChat" id="Tz5-0s-zFj">
+                                                <rect key="frame" x="0.0" y="44.666666030883789" width="428" height="43.666667938232422"/>
+                                                <autoresizingMask key="autoresizingMask"/>
+                                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Tz5-0s-zFj" id="4MW-eb-afV">
+                                                    <rect key="frame" x="0.0" y="0.0" width="428" height="43.666667938232422"/>
+                                                    <autoresizingMask key="autoresizingMask"/>
+                                                </tableViewCellContentView>
+                                            </tableViewCell>
+                                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="reuseIdentifierGroup" id="im7-ks-lTd">
+                                                <rect key="frame" x="0.0" y="88.333333969116211" width="428" height="43.666667938232422"/>
+                                                <autoresizingMask key="autoresizingMask"/>
+                                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="im7-ks-lTd" id="lNo-4T-eyr">
+                                                    <rect key="frame" x="0.0" y="0.0" width="428" height="43.666667938232422"/>
+                                                    <autoresizingMask key="autoresizingMask"/>
+                                                </tableViewCellContentView>
+                                            </tableViewCell>
+                                        </prototypes>
+                                        <connections>
+                                            <outlet property="dataSource" destination="z6f-Hz-Xwh" id="AOZ-F1-Rhe"/>
+                                            <outlet property="delegate" destination="z6f-Hz-Xwh" id="rwB-hc-wXw"/>
+                                        </connections>
+                                    </tableView>
+                                </subviews>
+                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <constraints>
+                                    <constraint firstAttribute="bottom" secondItem="4Jc-b8-aeF" secondAttribute="bottom" id="AJg-3y-ycq"/>
+                                    <constraint firstAttribute="trailing" secondItem="4Jc-b8-aeF" secondAttribute="trailing" id="MQg-wg-wJC"/>
+                                    <constraint firstItem="4Jc-b8-aeF" firstAttribute="leading" secondItem="oT8-Uw-cgS" secondAttribute="leading" id="gr8-uB-Kjv"/>
+                                    <constraint firstItem="4Jc-b8-aeF" firstAttribute="top" secondItem="oT8-Uw-cgS" secondAttribute="top" id="tgW-8t-y1Q"/>
+                                </constraints>
+                            </view>
+                        </subviews>
+                        <viewLayoutGuide key="safeArea" id="Exo-M2-oVn"/>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstItem="BU2-P5-16y" firstAttribute="top" secondItem="T1X-gt-fSN" secondAttribute="top" id="6kj-QA-eHg"/>
+                            <constraint firstItem="oT8-Uw-cgS" firstAttribute="leading" secondItem="Exo-M2-oVn" secondAttribute="leading" id="9FF-6z-ROG"/>
+                            <constraint firstItem="oT8-Uw-cgS" firstAttribute="top" secondItem="Exo-M2-oVn" secondAttribute="top" id="CvI-hv-hNw"/>
+                            <constraint firstItem="Exo-M2-oVn" firstAttribute="bottom" secondItem="oT8-Uw-cgS" secondAttribute="bottom" id="Imt-VX-VR1"/>
+                            <constraint firstItem="BU2-P5-16y" firstAttribute="leading" secondItem="Exo-M2-oVn" secondAttribute="leading" id="L9z-Na-Kbb"/>
+                            <constraint firstItem="Exo-M2-oVn" firstAttribute="trailing" secondItem="BU2-P5-16y" secondAttribute="trailing" id="Udn-OO-sE2"/>
+                            <constraint firstItem="oT8-Uw-cgS" firstAttribute="trailing" secondItem="Exo-M2-oVn" secondAttribute="trailing" id="Vck-XN-acd"/>
+                            <constraint firstAttribute="bottom" secondItem="BU2-P5-16y" secondAttribute="bottom" id="jai-lq-WbQ"/>
+                        </constraints>
+                    </view>
+                    <connections>
+                        <outlet property="backgroundImage" destination="BU2-P5-16y" id="gud-Yi-EyH"/>
+                        <outlet property="tableView" destination="4Jc-b8-aeF" id="kie-X3-tsw"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iEb-Pf-p13" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-94.20289855072464" y="1184.5982142857142"/>
+        </scene>
+        <!--Item 1-->
+        <scene sceneID="N8z-aZ-R0C">
+            <objects>
+                <viewController id="shx-A0-Rpw" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="0VY-c7-1YL">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <viewLayoutGuide key="safeArea" id="cTG-dq-upN"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </view>
+                    <tabBarItem key="tabBarItem" title="Item 1" id="p7E-Es-Ytv"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="ea8-TI-6Jg" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-772" y="525"/>
+        </scene>
+        <!--test-->
+        <scene sceneID="P0z-HA-ArT">
+            <objects>
+                <navigationController title="test" id="nD6-T3-59p" sceneMemberID="viewController">
+                    <navigationBar key="navigationBar" opaque="NO" contentMode="scaleToFill" id="mEs-FV-nQc">
+                        <rect key="frame" x="0.0" y="44" width="428" height="44"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <color key="tintColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <color key="barTintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <textAttributes key="titleTextAttributes">
+                            <color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        </textAttributes>
+                        <textAttributes key="largeTitleTextAttributes">
+                            <color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        </textAttributes>
+                    </navigationBar>
+                    <toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="7Tu-EZ-US7">
+                        <autoresizingMask key="autoresizingMask"/>
+                    </toolbar>
+                    <connections>
+                        <segue destination="303-e4-dlv" kind="relationship" relationship="rootViewController" id="ax7-Vc-WBo"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="2PQ-0V-IE2" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-145" y="-202"/>
+        </scene>
+        <!--mainVC-->
+        <scene sceneID="acr-UY-sCb">
+            <objects>
+                <tabBarController title="mainVC" id="303-e4-dlv" customClass="ViewController" customModule="AppBuilder" customModuleProvider="target" sceneMemberID="viewController">
+                    <navigationItem key="navigationItem" id="sH1-Nb-Vna"/>
+                    <tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="aG7-6Q-gSS">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="49"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                        <color key="barTintColor" white="0.91082411545973563" alpha="1" colorSpace="calibratedWhite"/>
+                    </tabBar>
+                    <connections>
+                        <segue destination="shx-A0-Rpw" kind="relationship" relationship="viewControllers" id="InU-1A-5CF"/>
+                        <segue destination="yL2-sh-r2b" kind="relationship" relationship="viewControllers" id="2uQ-yM-Uwx"/>
+                        <segue destination="BQG-BK-XdT" kind="relationship" relationship="viewControllers" id="xa0-0l-EhV"/>
+                        <segue destination="HRs-yQ-che" kind="relationship" relationship="viewControllers" id="H7y-1o-pCn"/>
+                        <segue destination="doo-wB-Xef" kind="relationship" relationship="viewControllers" id="XZ7-g3-417"/>
+                    </connections>
+                </tabBarController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="xVj-nd-1u2" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="619" y="-202"/>
+        </scene>
+        <!--Item 3-->
+        <scene sceneID="akE-9q-KIu">
+            <objects>
+                <viewController id="BQG-BK-XdT" userLabel="Item 3" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="tfu-1X-nbl">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <viewLayoutGuide key="safeArea" id="5ym-td-Khs"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </view>
+                    <tabBarItem key="tabBarItem" title="Item 3" id="fhU-xt-rD1" userLabel="Item 3"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dEh-1z-WOg" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="619" y="525"/>
+        </scene>
+        <!--Item 4-->
+        <scene sceneID="ayN-8g-7Qb">
+            <objects>
+                <viewController id="HRs-yQ-che" userLabel="Item 4" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="CpP-4M-jQO">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <viewLayoutGuide key="safeArea" id="FW7-Pt-spm"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </view>
+                    <tabBarItem key="tabBarItem" title="Item 4" id="9HE-z6-qW3" userLabel="Item 4"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="kTc-lt-5jQ" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1293" y="525"/>
+        </scene>
+        <!--Item 5-->
+        <scene sceneID="1OZ-lX-QwV">
+            <objects>
+                <viewController id="doo-wB-Xef" userLabel="Item 5" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="gva-IL-Ua7">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <viewLayoutGuide key="safeArea" id="b9A-7D-aDQ"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </view>
+                    <tabBarItem key="tabBarItem" title="Item 5" id="aDp-Df-R88" userLabel="Item 5"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="pku-2n-PfH" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="2017" y="525"/>
+        </scene>
+        <!--Third Tab View Controller-->
+        <scene sceneID="2tv-T7-3Gz">
+            <objects>
+                <viewController storyboardIdentifier="thirdTabVC" useStoryboardIdentifierAsRestorationIdentifier="YES" id="sim-nJ-liW" customClass="ThirdTabViewController" customModule="AppBuilder" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="zlx-Nr-4qk">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <wkWebView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bvD-XN-Tvh">
+                                <rect key="frame" x="0.0" y="44" width="428" height="848"/>
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <wkWebViewConfiguration key="configuration">
+                                    <audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
+                                    <wkPreferences key="preferences"/>
+                                </wkWebViewConfiguration>
+                            </wkWebView>
+                        </subviews>
+                        <viewLayoutGuide key="safeArea" id="gQh-2u-SN6"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="gQh-2u-SN6" firstAttribute="bottom" secondItem="bvD-XN-Tvh" secondAttribute="bottom" id="7Q0-Pz-a2B"/>
+                            <constraint firstItem="bvD-XN-Tvh" firstAttribute="leading" secondItem="gQh-2u-SN6" secondAttribute="leading" id="Xt6-nC-kXW"/>
+                            <constraint firstItem="gQh-2u-SN6" firstAttribute="trailing" secondItem="bvD-XN-Tvh" secondAttribute="trailing" id="d1o-4Y-rDd"/>
+                            <constraint firstItem="bvD-XN-Tvh" firstAttribute="top" secondItem="gQh-2u-SN6" secondAttribute="top" id="wKy-eu-cvh"/>
+                        </constraints>
+                    </view>
+                    <connections>
+                        <outlet property="webView" destination="bvD-XN-Tvh" id="4YE-s2-y3Z"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="crD-Us-xmX" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="619" y="1185"/>
+        </scene>
+        <!--Fourth Tab View Controller-->
+        <scene sceneID="ZzT-E6-umc">
+            <objects>
+                <viewController storyboardIdentifier="fourthTabVC" useStoryboardIdentifierAsRestorationIdentifier="YES" id="ruc-qb-tdV" customClass="FourthTabViewController" customModule="AppBuilder" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="9o3-Cd-xmC">
+                        <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="pb_lbackground_1" translatesAutoresizingMaskIntoConstraints="NO" id="rdi-Bn-gaF">
+                                <rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
+                            </imageView>
+                            <tableView opaque="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" bouncesZoom="NO" dataMode="prototypes" style="insetGrouped" separatorStyle="default" separatorInsetReference="fromAutomaticInsets" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="5" sectionFooterHeight="5" translatesAutoresizingMaskIntoConstraints="NO" id="gUO-Ws-n00">
+                                <rect key="frame" x="0.0" y="80" width="428" height="807"/>
+                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <inset key="separatorInset" minX="3" minY="0.0" maxX="0.0" maxY="0.0"/>
+                                <color key="sectionIndexBackgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <prototypes>
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="2" reuseIdentifier="reuseIdentifier" id="IEo-SX-4um">
+                                        <rect key="frame" x="20" y="49" width="388" height="43.666667938232422"/>
+                                        <autoresizingMask key="autoresizingMask"/>
+                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="IEo-SX-4um" id="je4-kr-tvF">
+                                            <rect key="frame" x="0.0" y="0.0" width="388" height="43.666667938232422"/>
+                                            <autoresizingMask key="autoresizingMask"/>
+                                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                            <edgeInsets key="layoutMargins" top="0.0" left="0.0" bottom="0.0" right="0.0"/>
+                                        </tableViewCellContentView>
+                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    </tableViewCell>
+                                </prototypes>
+                            </tableView>
+                        </subviews>
+                        <viewLayoutGuide key="safeArea" id="SgQ-c4-v3h"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="rdi-Bn-gaF" firstAttribute="top" secondItem="9o3-Cd-xmC" secondAttribute="top" id="3iG-Qg-ugF"/>
+                            <constraint firstItem="SgQ-c4-v3h" firstAttribute="bottom" secondItem="gUO-Ws-n00" secondAttribute="bottom" constant="5" id="cJW-F2-vbP"/>
+                            <constraint firstItem="gUO-Ws-n00" firstAttribute="top" secondItem="9o3-Cd-xmC" secondAttribute="top" constant="80" id="dgB-Kt-3hN"/>
+                            <constraint firstAttribute="bottom" secondItem="rdi-Bn-gaF" secondAttribute="bottom" id="i6c-Au-25J"/>
+                            <constraint firstItem="SgQ-c4-v3h" firstAttribute="trailing" secondItem="rdi-Bn-gaF" secondAttribute="trailing" id="ka4-Ak-VDR"/>
+                            <constraint firstItem="gUO-Ws-n00" firstAttribute="trailing" secondItem="SgQ-c4-v3h" secondAttribute="trailing" id="suE-CO-UTB"/>
+                            <constraint firstItem="rdi-Bn-gaF" firstAttribute="leading" secondItem="SgQ-c4-v3h" secondAttribute="leading" id="wzr-gR-Yrs"/>
+                            <constraint firstItem="gUO-Ws-n00" firstAttribute="leading" secondItem="SgQ-c4-v3h" secondAttribute="leading" id="xiY-lp-lrd"/>
+                        </constraints>
+                    </view>
+                    <connections>
+                        <outlet property="backgroundImage" destination="rdi-Bn-gaF" id="MAO-jC-VP5"/>
+                        <outlet property="tableView" destination="gUO-Ws-n00" id="8ZB-Pu-MLW"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="R3B-ld-vod" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1293" y="1184"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="pb_lbackground_1" width="1204" height="2475"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 145 - 0
appbuilder-ios/AppBuilder/AppBuilder/FirstTabViewController.swift

@@ -0,0 +1,145 @@
+//
+//  FirstTabViewController.swift
+//  AppBuilder
+//
+//  Created by Kevin Maulana on 29/03/22.
+//
+
+import UIKit
+import WebKit
+
+class FirstTabViewController: UIViewController, WKUIDelegate, UIScrollViewDelegate, UIGestureRecognizerDelegate {
+    
+    @IBOutlet weak var webView: WKWebView!
+    var address = ""
+    private var lastContentOffset: CGFloat = 0
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        let isBurger = cpaasMode == PrefsUtil.CPAAS_MODE_BURGER
+        navigationController?.navigationBar.backgroundColor = .white
+        navigationController?.setNavigationBarHidden(!isBurger, animated: false)
+        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(collapseDocked))
+        tapGesture.cancelsTouchesInView = false
+        tapGesture.delegate = self
+        webView.scrollView.addGestureRecognizer(tapGesture)
+        let refreshControl = UIRefreshControl()
+        refreshControl.addTarget(self, action: #selector(reloadWebView(_:)), for: .valueChanged)
+        webView.scrollView.addSubview(refreshControl)
+        webView.scrollView.delegate = self
+    }
+    
+    override func viewWillAppear(_ animated: Bool) {
+        let me = UserDefaults.standard.string(forKey: "me")
+        
+        var myURL : URL?
+        switch(ViewController.sURL){
+        case "0":
+            address = "https://qmera.io/nexilis/pages/tab1-main-only?f_pin=\(me ?? "")"
+            myURL = URL(string: address)
+        case "1":
+            address = "https://qmera.io/nexilis/pages/tab3-main-only?f_pin=\(me ?? "")"
+            myURL = URL(string: address)
+        case "2":
+            address = "https://qmera.io/nexilis/pages/tab1-main?f_pin=\(me ?? "")"
+            myURL = URL(string: address)
+        case "3":
+            address = "https://qmera.io/nexilis/pages/tab3-commerce?f_pin=\(me ?? "")"
+            myURL = URL(string: address)
+        default:
+            if(!ViewController.sURL.isEmpty){
+                if(ViewController.sURL.lowercased().contains("https://")){
+                    address = ViewController.sURL
+                    myURL = URL(string: address)
+                }
+                else {
+                    address = "https://\(ViewController.sURL)"
+                    myURL = URL(string: address)
+                }
+            }
+        }
+        print(address)
+        if let u = myURL{
+            let myRequest = URLRequest(url: u)
+            webView.load(myRequest)
+        }
+        self.navigationController?.navigationBar.topItem?.title = Bundle.main.displayName
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        let isBurger = cpaasMode == PrefsUtil.CPAAS_MODE_BURGER
+        navigationController?.setNavigationBarHidden(!isBurger, animated: false)
+    }
+    
+    override func viewDidAppear(_ animated: Bool) {
+        
+    }
+    
+    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        if (self.lastContentOffset > scrollView.contentOffset.y && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)) {
+            showTabBar();
+        }
+        else if (self.lastContentOffset != 0 && self.lastContentOffset < scrollView.contentOffset.y && self.lastContentOffset >= 0) {
+            hideTabBar();
+        }
+        self.lastContentOffset = scrollView.contentOffset.y
+        self.collapseDocked()
+    }
+    
+    @objc func collapseDocked() {
+        if ViewController.isExpandButton {
+            ViewController.expandButton()
+        }
+    }
+
+    @objc func reloadWebView(_ sender: UIRefreshControl) {
+        webView.reload()
+        sender.endRefreshing()
+    }
+    
+    func hideTabBar() {
+        var viewController = UIApplication.shared.windows.first!.rootViewController
+        if !(viewController is ViewController) {
+            viewController = self.parent
+        }
+        if ViewController.middleButton.isDescendant(of: viewController!.view) {
+            DispatchQueue.main.async {
+                if let viewController = viewController as? ViewController {
+                    viewController.tabBar.isHidden = true
+                }
+                ViewController.removeMiddleButton()
+            }
+        }
+    }
+
+    func showTabBar() {
+        if(ViewController.alwaysHideButton){
+            return
+        }
+        var viewController = UIApplication.shared.windows.first!.rootViewController
+        if !(viewController is ViewController) {
+            viewController = self.parent
+        }
+        if !ViewController.middleButton.isDescendant(of: viewController!.view) {
+            ViewController.isExpandButton = false
+            if let viewController = viewController as? ViewController {
+                viewController.tabBar.isHidden = false
+                viewController.createMidFloatingButton()
+            }
+        }
+    }
+
+    func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
+        scrollView.pinchGestureRecognizer?.isEnabled = false
+    }
+
+    /*
+    // MARK: - Navigation
+
+    // In a storyboard-based application, you will often want to do a little preparation before navigation
+    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
+        // Get the new view controller using segue.destination.
+        // Pass the selected object to the new view controller.
+    }
+    */
+
+}

+ 724 - 0
appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift

@@ -0,0 +1,724 @@
+//
+//  SettingTableViewController.swift
+//  Qmera
+//
+//  Created by Yayan Dwi on 16/09/21.
+//
+
+import UIKit
+import NotificationBannerSwift
+import nuSDKService
+import NexilisLite
+
+public class FourthTabViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate {
+    
+    var language: [[String: String]] = [["English": "en"],["Indonesia": "id"]]
+    var alert: UIAlertController?
+    var textFields = [UITextField]()
+    
+    @IBOutlet weak var tableView: UITableView!
+    @IBOutlet weak var backgroundImage: UIImageView!
+    
+    public override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        var isNCNil = navigationController == nil
+        print("isNCNil: \(isNCNil)")
+        
+        tableView.delegate = self
+        tableView.dataSource = self
+        
+        self.navigationController?.navigationBar.topItem?.title = "Settings".localized();
+        view.backgroundColor = .white
+        
+        makeMenu()
+        
+//        navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(didTapCancel))
+    }
+    
+    func makeMenu(){
+        let isChangeProfile = UserDefaults.standard.bool(forKey: "is_change_profile")
+        Database.shared.database?.inTransaction({ fmdb, rollback in
+            let idMe = UserDefaults.standard.string(forKey: "me") as String?
+            if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type, image_id FROM BUDDY where f_pin='\(idMe!)'"), cursorUser.next() {
+                var groupId = ""
+                if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorGroup.next() {
+                    groupId = cursorGroup.string(forColumnIndex: 0) ?? ""
+                    cursorGroup.close()
+                }
+                var position = ""
+                if let cursorIsAdmin = Database.shared.getRecords(fmdb: fmdb, query: "SELECT position FROM GROUPZ_MEMBER where group_id = '\(groupId)' AND f_pin = '\(idMe!)'"), cursorIsAdmin.next() {
+                    position = cursorIsAdmin.string(forColumnIndex: 0) ?? ""
+                    cursorIsAdmin.close()
+                }
+                if cursorUser.string(forColumnIndex: 0) == "23" && position == "1" {
+                    Item.menus["Personal"] = [
+                        Item(icon: UIImage(systemName: "person.fill"), title: "Personal Information".localized()),
+                        Item(icon: UIImage(systemName: "person.crop.rectangle"), title: "Change Admin / Internal Password".localized()),
+                        Item(icon: UIImage(systemName: "laptopcomputer.and.iphone"), title: "Login to Nexilis Web".localized()),
+                        Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
+                    ]
+                } else if cursorUser.string(forColumnIndex: 0) == "23" || cursorUser.string(forColumnIndex: 0) == "24" {
+                    Item.menus["Personal"] = [
+                        Item(icon: UIImage(systemName: "person.fill"), title: "Personal Information".localized()),
+                        Item(icon: UIImage(systemName: "laptopcomputer.and.iphone"), title: "Login to Nexilis Web".localized()),
+                            Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
+                    ]
+                } else {
+                    Item.menus["Personal"] = [
+                        Item(icon: UIImage(systemName: "person.fill"), title: "Personal Information".localized()),
+                        Item(icon: UIImage(systemName: "person.crop.rectangle"), title: "Sign In Admin / Internal".localized()),
+                        Item(icon: UIImage(systemName: "laptopcomputer.and.iphone"), title: "Login to Nexilis Web".localized()),
+                            Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
+                    ]
+                }
+                let image = cursorUser.string(forColumnIndex: 1) ?? ""
+                if !image.isEmpty {
+                    do {
+                        let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
+                        let file = documentDir.appendingPathComponent(image)
+                        if FileManager().fileExists(atPath: file.path) {
+                            let image = UIImage(contentsOfFile: file.path)
+                            Item.menus["Personal"]?[0].icon = image?.circleMasked
+                        } else {
+                            Download().start(forKey: image) { (name, progress) in
+                                guard progress == 100 else {
+                                    return
+                                }
+
+                                DispatchQueue.main.async {
+                                    let image = UIImage(contentsOfFile: file.path)
+                                    Item.menus["Personal"]?[0].icon = image?.circleMasked
+                                    self.tableView.reloadData()
+                                }
+                            }
+                        }
+                    } catch {}
+                }
+                cursorUser.close()
+            }
+            if !isChangeProfile {
+                Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Change Device".localized()))
+            }
+        })
+        
+        Item.menus["Call"] = [
+            Item(icon: UIImage(systemName: "message"), title: "Incoming Message(s)".localized()),
+            Item(icon: UIImage(systemName: "phone"), title: "Incoming Call(s)".localized()),
+            Item(icon: UIImage(systemName: "iphone.homebutton.radiowaves.left.and.right"), title: "Vibrate Mode".localized()),
+        ]
+        Item.menus["Etc"] = [
+            Item(icon: UIImage(systemName: "photo.on.rectangle.angled"), title: "Save to Gallery".localized()),
+            Item(icon: UIImage(systemName: "arrow.down.square"), title: "Auto Download".localized()),
+//            Item(icon: UIImage(systemName: "mail"), title: "Email".localized()),
+        ]
+        Item.menus["Version"] = [
+            Item(icon: UIImage(systemName: "gear"), title: "Version".localized()),
+        ]
+        if isChangeProfile {
+            Item.menus["Version"]?.append(Item(icon: UIImage(systemName: "rectangle.portrait.and.arrow.right"), title: "Logout".localized()))
+        }
+        Item.menus["Powered"] = [
+            Item(icon: UIImage(named: "pb_powered_button"), title: "Powered by Nexilis".localized()),
+        ]
+    }
+    
+    override public func viewWillAppear(_ animated: Bool) {
+        let randomInt = Int.random(in: 1..<2)
+        backgroundImage.image = UIImage(named: "pb_lbackground_\(randomInt)")
+        self.navigationController?.navigationBar.topItem?.title = "Settings".localized();
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        let isBurger = cpaasMode == PrefsUtil.CPAAS_MODE_BURGER
+        navigationController?.setNavigationBarHidden(false, animated: false)
+        navigationController?.navigationBar.backgroundColor = .clear
+        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
+        navigationController?.navigationBar.shadowImage = UIImage()
+        navigationController?.navigationBar.isTranslucent = true
+    }
+    
+//    @objc func didTapCancel(sender: AnyObject) {
+//        navigationController?.dismiss(animated: true, completion: nil)
+//    }
+    
+    // MARK: - Table view data source
+    
+    public func numberOfSections(in tableView: UITableView) -> Int {
+        return Item.sections.count
+    }
+    
+    public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
+            return 1
+        }
+    
+    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return Item.menuFor(section: section).count
+    }
+    
+    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
+        cell.accessoryType = .none
+        cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: .greatestFiniteMagnitude)
+        cell.indentationLevel = 0
+        var content = cell.defaultContentConfiguration()
+        content.textProperties.font = UIFont.systemFont(ofSize: 14)
+        content.secondaryTextProperties.font = UIFont.systemFont(ofSize: 14)
+        content.secondaryTextProperties.color = .gray
+        content.prefersSideBySideTextAndSecondaryText = true
+        let section = Item.sections[indexPath.section]
+        if let arr = Item.menus[section] {
+            let menu = arr[indexPath.row]
+            content.image = menu.icon
+            content.imageProperties.tintColor = .mainColor
+            content.imageProperties.maximumSize = CGSize(width: 24, height: 24)
+            content.text = menu.title
+            switch menu.title {
+            case "Personal Information".localized():
+                cell.accessoryType = .disclosureIndicator
+            case "Sign In Admin / Internal".localized():
+                cell.accessoryType = .disclosureIndicator
+            case "Login to Nexilis Web".localized():
+                cell.accessoryType = .disclosureIndicator
+            case "Change Device".localized():
+                cell.accessoryType = .disclosureIndicator
+            case "Change Admin / Internal Password".localized():
+                cell.accessoryType = .disclosureIndicator
+            case "Change Language".localized():
+                cell.accessoryType = .disclosureIndicator
+            case "Version".localized():
+                content.secondaryText = UIApplication.appVersion
+            default:
+                content.secondaryText = nil
+            }
+        }
+        cell.contentConfiguration = content
+        return cell
+    }
+    
+    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let item = Item.menuFor(section: indexPath.section)[indexPath.row]
+        if item.title == "Personal Information".localized() {
+            if(ViewController.checkIsChangePerson()){
+                let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "profileView") as! ProfileViewController
+                controller.data = UserDefaults.standard.string(forKey: "me")!
+                controller.flag = .me
+                controller.dismissImage = { image, imageName in
+                    if !imageName.isEmpty {
+                        Item.menus["Personal"]?[0].icon = image.circleMasked
+                    } else {
+                        Item.menus["Personal"]?[0].icon = UIImage(systemName: "person.fill")
+                    }
+                    self.tableView.reloadData()
+                }
+                navigationController?.show(controller, sender: nil)
+            }
+        } else if item.title == "Sign In Admin / Internal".localized() || item.title == "Change Admin / Internal Password".localized() {
+            Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name FROM BUDDY where f_pin = '\(UserDefaults.standard.string(forKey: "me")!)'"), cursorData.next() {
+                    if (cursorData.string(forColumnIndex: 0)! + " " + cursorData.string(forColumnIndex: 1)!).trimmingCharacters(in: .whitespaces) == "USR\(UserDefaults.standard.string(forKey: "me")!)" {
+                        let alert = UIAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized(), preferredStyle: .alert)
+                        alert.addAction(UIAlertAction(title: "Ok".localized(), style: UIAlertAction.Style.default, handler: {(_) in
+                            let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "profileView") as! ProfileViewController
+                            controller.data = UserDefaults.standard.string(forKey: "me")!
+                            controller.flag = .me
+                            self.navigationController?.show(controller, sender: nil)
+                        }))
+                        self.present(alert, animated: true, completion: nil)
+                    }
+                    cursorData.close()
+                    return
+                }
+            })
+            if !CheckConnection.isConnectedToNetwork()  || API.nGetCLXConnState() == 0 {
+                let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                imageView.tintColor = .white
+                let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                banner.show()
+                return
+            }
+            let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
+            if(item.title.contains("Change")){
+                if let action = self.actionChangePassword(for: "admin", title: "Change Admin Password".localized()) {
+                    alertController.addAction(action)
+                }
+                if let action = self.actionChangePassword(for: "internal", title: "Change Internal Password".localized()) {
+                    alertController.addAction(action)
+                }
+            }
+            else {
+                if let action = self.actionLogin(for: "admin", title: "Login as Admin".localized()) {
+                    alertController.addAction(action)
+                }
+                if let action = self.actionLogin(for: "internal", title: "Login as Internal Team".localized()) {
+                    alertController.addAction(action)
+                }
+            }
+            alertController.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: nil))
+            self.present(alertController, animated: true)
+        } else if item.title == "Change Language".localized() {
+            let vc = UIViewController()
+            vc.preferredContentSize = CGSize(width: UIScreen.main.bounds.width - 10, height: 150)
+            let pickerView = UIPickerView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width - 10, height: 150))
+            pickerView.dataSource = self
+            pickerView.delegate = self
+            
+            let lang = UserDefaults.standard.string(forKey: "i18n_language")
+            var index = 0
+            if lang == "id" {
+                index = 1
+            }
+            pickerView.selectRow(index, inComponent: 0, animated: false)
+            
+            vc.view.addSubview(pickerView)
+            pickerView.translatesAutoresizingMaskIntoConstraints = false
+            pickerView.centerXAnchor.constraint(equalTo: vc.view.centerXAnchor).isActive = true
+            pickerView.centerYAnchor.constraint(equalTo: vc.view.centerYAnchor).isActive = true
+            
+            let alert = UIAlertController(title: "Select Language".localized(), message: "", preferredStyle: .actionSheet)
+            
+            alert.setValue(vc, forKey: "contentViewController")
+            alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (UIAlertAction) in
+            }))
+            
+            alert.addAction(UIAlertAction(title: "Select", style: .default, handler: { (UIAlertAction) in
+                let selectedIndex = pickerView.selectedRow(inComponent: 0)
+                let lang = self.language[selectedIndex].values.first
+                UserDefaults.standard.set(lang, forKey: "i18n_language")
+                self.viewDidLoad()
+                self.tableView.reloadData()
+            }))
+            self.present(alert, animated: true, completion: nil)
+        } else if item.title == "Change Device".localized() {
+            let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "changeDevice") as! ChangeDeviceViewController
+            controller.isDismiss = { newThumb in
+                if Item.menus["Personal"]?[2].title == "Login to Nexilis Web".localized() {
+                    Item.menus["Personal"]?.remove(at: 3)
+                } else {
+                    Item.menus["Personal"]?.remove(at: 2)
+                }
+                if !newThumb.isEmpty {
+                    do {
+                        let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
+                        let file = documentDir.appendingPathComponent(newThumb)
+                        if FileManager().fileExists(atPath: file.path) {
+                            let image = UIImage(contentsOfFile: file.path)
+                            Item.menus["Personal"]?[0].icon = image?.circleMasked
+                        } else {
+                            Download().start(forKey: newThumb) { (name, progress) in
+                                guard progress == 100 else {
+                                    return
+                                }
+
+                                DispatchQueue.main.async {
+                                    let image = UIImage(contentsOfFile: file.path)
+                                    Item.menus["Personal"]?[0].icon = image?.circleMasked
+                                    self.tableView.reloadData()
+                                }
+                            }
+                        }
+                    } catch {}
+                }
+                Item.menus["Version"]?.append(Item(icon: UIImage(systemName: "rectangle.portrait.and.arrow.right"), title: "Logout".localized()))
+                Database.shared.database?.inTransaction({ fmdb, rollback in
+                    let idMe = UserDefaults.standard.string(forKey: "me") as String?
+                    if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type FROM BUDDY where f_pin='\(idMe!)'"), cursorUser.next() {
+                        var groupId = ""
+                        if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorGroup.next() {
+                            groupId = cursorGroup.string(forColumnIndex: 0) ?? ""
+                            cursorGroup.close()
+                        }
+                        var position = ""
+                        if let cursorIsAdmin = Database.shared.getRecords(fmdb: fmdb, query: "SELECT position FROM GROUPZ_MEMBER where group_id = '\(groupId)' AND f_pin = '\(idMe!)'"), cursorIsAdmin.next() {
+                            position = cursorIsAdmin.string(forColumnIndex: 0) ?? ""
+                            cursorIsAdmin.close()
+                        }
+                        if cursorUser.string(forColumnIndex: 0) == "23" && position == "1" {
+                            let itemCP = Item(icon: UIImage(systemName: "person.crop.rectangle"), title: "Change Admin / Internal Password".localized())
+                            Item.menus["Personal"]?[1] = itemCP
+                        } else if cursorUser.string(forColumnIndex: 0) == "23" || cursorUser.string(forColumnIndex: 0) == "24" {
+                            Item.menus["Personal"]?.remove(at: 1)
+                        }
+                        cursorUser.close()
+                    }
+                })
+                self.tableView.reloadData()
+            }
+            navigationController?.show(controller, sender: nil)
+        } else if item.title == "Logout".localized() {
+            let alert = UIAlertController(title: "Logout", message: "Are you sure want to logout?".localized(), preferredStyle: .alert)
+            alert.addAction(UIAlertAction(title: "Cancel".localized(), style: UIAlertAction.Style.default, handler: nil))
+            alert.addAction(UIAlertAction(title: "Yes".localized(), style: .destructive, handler: {(_) in
+                if !CheckConnection.isConnectedToNetwork()  || API.nGetCLXConnState() == 0 {
+                    let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                    imageView.tintColor = .white
+                    let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                    banner.show()
+                    return
+                }
+                DispatchQueue.global().async {
+                    self.deleteAllRecordDatabase()
+                    let apiKey = UserDefaults.standard.string(forKey: "apiKey")!
+                    var id = UIDevice.current.identifierForVendor?.uuidString ?? "UNK-DEVICE"
+                    if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignUpApi(api: apiKey, p_pin: id), timeout: 30 * 1000) {
+                        id = response.getBody(key: CoreMessage_TMessageKey.F_PIN, default_value: "")
+                        if(!id.isEmpty){
+                            Nexilis.changeUser(f_pin: id)
+                            UserDefaults.standard.setValue(id, forKey: "me")
+                            UserDefaults.standard.set("", forKey: "pwd")
+                            UserDefaults.standard.set(false, forKey: "is_change_profile")
+                            UserDefaults.standard.synchronize()
+                            // pos registration
+                            _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: id))
+                            DispatchQueue.main.async {
+                                let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Successfully Logout".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .top)
+                                banner.show()
+                                Item.menus["Personal"]?[0].icon = UIImage(systemName: "person.fill")
+                                Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Change Device".localized()))
+                                Item.menus["Version"]?.remove(at: 1)
+                                if Item.menus["Personal"]?[1].title != "Sign In Admin / Internal".localized() {
+                                    if Item.menus["Personal"]?[1].title == "Change Admin / Internal Password".localized() {
+                                        Item.menus["Personal"]?[1] = Item(icon: UIImage(systemName: "person.crop.rectangle"), title: "Sign In Admin / Internal".localized())
+                                    } else {
+                                        Item.menus["Personal"]?.insert(Item(icon: UIImage(systemName: "person.crop.rectangle"), title: "Sign In Admin / Internal".localized()), at: 1)
+                                    }
+                                }
+                                self.tableView.reloadData()
+                            }
+                        }
+                    } else {
+                        DispatchQueue.main.async {
+                            let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                            imageView.tintColor = .white
+                            let banner = FloatingNotificationBanner(title: "Unable to access servers. 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: .top)
+                            banner.show()
+                        }
+                    }
+                }
+            }))
+            self.present(alert, animated: true, completion: nil)
+        }
+    }
+    
+    private func actionLogin(for type: String, title: String) -> UIAlertAction? {
+        return UIAlertAction(title: title, style: .default) { _ in
+            self.alert = UIAlertController(title: "Login as Admin".localized(), message: nil, preferredStyle: .alert)
+            if type == "internal" {
+                self.alert = UIAlertController(title: "Login as Internal Team".localized(), message: nil, preferredStyle: .alert)
+            }
+            self.textFields.removeAll()
+            self.alert?.addTextField{ (texfield) in
+                texfield.placeholder = "Password"
+                texfield.isSecureTextEntry = true
+                texfield.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
+            }
+            let submitAction = UIAlertAction(title: "Sign In".localized(), style: .default, handler: { (action) -> Void in
+                let textField = self.alert?.textFields![0]
+                if !CheckConnection.isConnectedToNetwork()  || API.nGetCLXConnState() == 0 {
+                    let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                    imageView.tintColor = .white
+                    let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                    banner.show()
+                    return
+                }
+                if type == "admin" {
+                    self.signInAdmin(password: textField!.text!, completion: { result in
+                        if result {
+                            DispatchQueue.main.async {
+                                let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Successfully login Admin".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .top)
+                                banner.show()
+                                let itemCP = Item(icon: UIImage(systemName: "person.crop.rectangle"), title: "Change Admin / Internal Password".localized())
+                                Item.menus["Personal"]?[1] = itemCP
+                                self.tableView.reloadData()
+                            }
+                        }
+                    })
+                } else {
+                    self.signInInternal(password: textField!.text!, completion: { result in
+                        if result {
+                            DispatchQueue.main.async {
+                                let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Successfully login Internal Team".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .top)
+                                banner.show()
+                                Item.menus["Personal"]?.remove(at: 1)
+                                self.tableView.reloadData()
+                            }
+                        }
+                    })
+                }
+            })
+            submitAction.isEnabled = false
+            self.alert?.addAction(submitAction)
+            self.alert?.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: nil))
+            
+            self.present(self.alert!, animated: true, completion: nil)
+        }
+    }
+    
+    private func actionChangePassword(for type: String, title: String) -> UIAlertAction? {
+        return UIAlertAction(title: title, style: .default) { _ in
+            self.alert = UIAlertController(title: "Change Admin Password".localized(), message: nil, preferredStyle: .alert)
+            if type == "internal" {
+                self.alert = UIAlertController(title: "Change Internal Password".localized(), message: nil, preferredStyle: .alert)
+            }
+            self.textFields.removeAll()
+            self.alert?.addTextField{ (texfield) in
+                texfield.placeholder = "Old Password"
+                texfield.isSecureTextEntry = true
+                texfield.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
+                self.textFields.append(texfield)
+            }
+            self.alert?.addTextField{ (texfield) in
+                texfield.placeholder = "New Password"
+                texfield.isSecureTextEntry = true
+                texfield.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
+                self.textFields.append(texfield)
+            }
+            let submitAction = UIAlertAction(title: "Change Password".localized(), style: .default, handler: { (action) -> Void in
+                let textFieldOld = self.alert?.textFields![0]
+                let textFieldNew = self.alert?.textFields![1]
+                if !CheckConnection.isConnectedToNetwork()  || API.nGetCLXConnState() == 0 {
+                    let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                    imageView.tintColor = .white
+                    let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                    banner.show()
+                    return
+                }
+                if type == "admin" {
+                    self.changePasswordAdmin(oldPassword: textFieldOld!.text!, newPassword: textFieldNew!.text!, completion: { result in
+                        if result {
+                            DispatchQueue.main.async {
+                                let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Admin password changed successfully".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .top)
+                                banner.show()
+                            }
+                        }
+                    })
+                } else {
+                    self.changePasswordInternal(oldPassword: textFieldOld!.text!, newPassword: textFieldNew!.text!, completion: { result in
+                        if result {
+                            DispatchQueue.main.async {
+                                let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Internal password changed successfully".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .top)
+                                banner.show()
+                            }
+                        }
+                    })
+                }
+            })
+            submitAction.isEnabled = false
+            self.alert?.addAction(submitAction)
+            self.alert?.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: nil))
+            
+            self.present(self.alert!, animated: true, completion: nil)
+        }
+    }
+    
+    @objc func alertTextFieldDidChange(_ sender: UITextField) {
+        if(!textFields.isEmpty){
+            print("text count 0: \(textFields[0].text!.count)")
+            print("text count 1: \(textFields[1].text!.count)")
+            alert?.actions[0].isEnabled = textFields[0].text!.count > 0 && textFields[1].text!.count > 0
+        }
+        else {
+            alert?.actions[0].isEnabled = sender.text!.count > 0
+        }
+    }
+    
+    private func signInAdmin(password: String, completion: @escaping (Bool) -> ()) {
+        DispatchQueue.global().async {
+            let idMe = UserDefaults.standard.string(forKey: "me") as String?
+            let p_password = password
+            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
+            var result: Bool = false
+            if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiAdmin(p_name: idMe!, p_password: md5Hex)) {
+                if response.isOk() {
+                    result = true
+                }
+                DispatchQueue.main.async {
+                    if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "11" {
+                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                        imageView.tintColor = .white
+                        let banner = FloatingNotificationBanner(title: "Username or password does not match".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: .top)
+                        banner.show()
+                    } else if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "20" {
+                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                        imageView.tintColor = .white
+                        let banner = FloatingNotificationBanner(title: "Invalid password".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: .top)
+                        banner.show()
+                    }
+                }
+            } else {
+                DispatchQueue.main.async {
+                    let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                    imageView.tintColor = .white
+                    let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                    banner.show()
+                }
+            }
+            completion(result)
+        }
+    }
+    
+    private func signInInternal(password: String, completion: @escaping (Bool) -> ()) {
+        DispatchQueue.global().async {
+            let idMe = UserDefaults.standard.string(forKey: "me") as String?
+            let p_password = password
+            let md5Hex = Utils.getMD5(string: p_password).map { String(format: "%02hhx", $0) }.joined()
+            var result: Bool = false
+            if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiInternal(p_name: idMe!, p_password: md5Hex)) {
+                if response.isOk() {
+                    result = true
+                }
+                DispatchQueue.main.async {
+                    if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "11" {
+                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                        imageView.tintColor = .white
+                        let banner = FloatingNotificationBanner(title: "Username or password does not match".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: .top)
+                        banner.show()
+                    } else if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "20" {
+                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                        imageView.tintColor = .white
+                        let banner = FloatingNotificationBanner(title: "Invalid password".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: .top)
+                        banner.show()
+                    }
+                }
+            } else {
+                DispatchQueue.main.async {
+                    let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                    imageView.tintColor = .white
+                    let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                    banner.show()
+                }
+            }
+            completion(result)
+        }
+    }
+    
+    private func changePasswordAdmin(oldPassword: String, newPassword: String, completion: @escaping (Bool) -> ()) {
+        DispatchQueue.global().async {
+            let idMe = UserDefaults.standard.string(forKey: "me") as String?
+            let p_password = oldPassword
+            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()
+            var result: Bool = false
+            if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordAdmin(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
+                if response.isOk() {
+                    result = true
+                }
+                DispatchQueue.main.async {
+                    if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "11" {
+                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                        imageView.tintColor = .white
+                        let banner = FloatingNotificationBanner(title: "Username or password does not match".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: .top)
+                        banner.show()
+                    } else if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "20" {
+                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                        imageView.tintColor = .white
+                        let banner = FloatingNotificationBanner(title: "Invalid password".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: .top)
+                        banner.show()
+                    }
+                }
+            } else {
+                DispatchQueue.main.async {
+                    let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                    imageView.tintColor = .white
+                    let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                    banner.show()
+                }
+            }
+            completion(result)
+        }
+    }
+    
+    private func changePasswordInternal(oldPassword: String, newPassword: String, completion: @escaping (Bool) -> ()) {
+        DispatchQueue.global().async {
+            let idMe = UserDefaults.standard.string(forKey: "me") as String?
+            let p_password = oldPassword
+            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()
+            var result: Bool = false
+            if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getChangePasswordInternal(p_f_pin: idMe!, pwd_en: md5HexNew, pwd_old: md5Hex)) {
+                if response.isOk() {
+                    result = true
+                }
+                DispatchQueue.main.async {
+                    if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "11" {
+                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                        imageView.tintColor = .white
+                        let banner = FloatingNotificationBanner(title: "Username or password does not match".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: .top)
+                        banner.show()
+                    } else if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "20" {
+                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                        imageView.tintColor = .white
+                        let banner = FloatingNotificationBanner(title: "Invalid password".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: .top)
+                        banner.show()
+                    }
+                }
+            } else {
+                DispatchQueue.main.async {
+                    let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                    imageView.tintColor = .white
+                    let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                    banner.show()
+                }
+            }
+            completion(result)
+        }
+    }
+}
+
+// MARK: - Item
+
+struct Item: Hashable {
+    
+    static func == (lhs: Item, rhs: Item) -> Bool {
+        return lhs.title == rhs.title
+    }
+    
+    var icon: UIImage?
+    var title = ""
+    
+    static var sections: [String] {
+        return ["Personal", "Call", "Etc", "Version", "Powered"]
+    }
+    
+    static var menus: [String: [Item]] = [:]
+    
+    static func menuFor(section: Int) -> [Item] {
+        let sec = sections[section]
+        if let arr = menus[sec] {
+            return arr
+        }
+        return []
+    }
+    
+}
+
+extension FourthTabViewController: UIPickerViewDelegate, UIPickerViewDataSource {
+    public func numberOfComponents(in pickerView: UIPickerView) -> Int {
+        return 1
+    }
+    
+    public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
+        return language.count
+    }
+    
+    public func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
+        return 60
+    }
+    
+    public func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
+        let label = UILabel(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width - 10, height: 30))
+        label.text = (language[row]).keys.first
+        label.sizeToFit()
+        return label
+    }
+}

+ 102 - 0
appbuilder-ios/AppBuilder/AppBuilder/Info.plist

@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>CFBundleDisplayName</key>
+	<string>AppBuilder</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
+	<key>CFBundleShortVersionString</key>
+	<string>$(MARKETING_VERSION)</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>NSCameraUsageDescription</key>
+	<string>Video Call, Conference Room, Content Creation and Live Streaming.</string>
+	<key>NSContactsUsageDescription</key>
+	<string>Get File Contact from Local Dictionary for Send Message.</string>
+	<key>NSDocumentsFolderUsageDescription</key>
+	<string>Get File from Local Dictionary for Send Message.</string>
+	<key>NSMicrophoneUsageDescription</key>
+	<string>VoIP Call, Video Call, Conference Room, and Live Streaming.</string>
+	<key>NSMotionUsageDescription</key>
+	<string>Service nuSDK.</string>
+	<key>NSPhotoLibraryAddUsageDescription</key>
+	<string>Get File Photos from Local Dictionary for Send Message and Content Creation.</string>
+	<key>NSPhotoLibraryUsageDescription</key>
+	<string>Get File Photos from Local Dictionary for Send Message and Content Creation.</string>
+	<key>NSSpeechRecognitionUsageDescription</key>
+	<string>Used for speech recognition features.</string>
+	<key>UIAppFonts</key>
+	<array>
+		<string>Poppins-Light.ttf</string>
+		<string>Poppins-Medium.ttf</string>
+		<string>Poppins-SemiBoldItalic.ttf</string>
+		<string>Poppins-Regular.ttf</string>
+		<string>Poppins-LightItalic.ttf</string>
+		<string>Poppins-SemiBold.ttf</string>
+		<string>Poppins-MediumItalic.ttf</string>
+	</array>
+	<key>UIApplicationSceneManifest</key>
+	<dict>
+		<key>UIApplicationSupportsMultipleScenes</key>
+		<false/>
+		<key>UISceneConfigurations</key>
+		<dict>
+			<key>UIWindowSceneSessionRoleApplication</key>
+			<array>
+				<dict>
+					<key>UISceneConfigurationName</key>
+					<string>Default Configuration</string>
+					<key>UISceneDelegateClassName</key>
+					<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
+					<key>UISceneStoryboardFile</key>
+					<string>Main</string>
+				</dict>
+			</array>
+		</dict>
+	</dict>
+	<key>UIApplicationSupportsIndirectInputEvents</key>
+	<true/>
+	<key>UIBackgroundModes</key>
+	<array>
+		<string>fetch</string>
+		<string>location</string>
+		<string>processing</string>
+		<string>remote-notification</string>
+		<string>voip</string>
+	</array>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIMainStoryboardFile</key>
+	<string>Main</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UIUserInterfaceStyle</key>
+	<string>Light</string>
+</dict>
+</plist>

+ 185 - 0
appbuilder-ios/AppBuilder/AppBuilder/PrefsUtil.swift

@@ -0,0 +1,185 @@
+//
+//  PrefsUtil.swift
+//  AppBuilder
+//
+//  Created by Kevin Maulana on 23/03/22.
+//
+
+import Foundation
+
+
+class PrefsUtil {
+    static let CPAAS_MODE_FLOATING = 0
+    static let CPAAS_MODE_DOCKED = 1
+    static let CPAAS_MODE_BURGER = 2
+    static let CPAAS_MODE_MIX = 4
+    static let DEFAULT_CPAAS_MODE = CPAAS_MODE_DOCKED
+    
+    static func getCpaasMode() -> Int {
+        let mode = UserDefaults.standard.integer(forKey: "cpaas_mode")
+        if(mode != 0) {
+            return mode - 1
+        }
+        return PrefsUtil.DEFAULT_CPAAS_MODE
+    }
+    
+    static func setCpaasMode(mode: Int){
+        UserDefaults.standard.set(mode+1, forKey: "cpaas_mode")
+    }
+    
+    static var CUSTOM_TAB = "1,2,3,4"
+    
+    static func getCustomTab() -> String {
+        if let cust = UserDefaults.standard.string(forKey: "custom_tab"){
+            if(!cust.isEmpty){
+                return cust
+            }
+        }
+        return PrefsUtil.CUSTOM_TAB
+    }
+    
+    static func setCustomTab(cust: String){
+        UserDefaults.standard.set(cust, forKey: "custom_tab")
+    }
+    
+    static func getURLFirstTab() -> String? {
+        return UserDefaults.standard.string(forKey: "app_builder_url_first_tab")
+    }
+    
+    static func getURLThirdTab() -> String? {
+        return UserDefaults.standard.string(forKey: "app_builder_url_third_tab")
+    }
+    
+    static func setURLFirstTab(value: String) {
+        UserDefaults.standard.set(value, forKey: "app_builder_url_first_tab")
+    }
+    
+    static func setURLThirdTab(value: String) {
+        UserDefaults.standard.set(value, forKey: "app_builder_url_third_tab")
+    }
+    
+    static func getTerms() -> Bool {
+        return UserDefaults.standard.bool(forKey: "terms_app")
+    }
+    
+    static func setTerms(value: Bool){
+        UserDefaults.standard.set(value, forKey: "terms_app")
+    }
+    
+}
+//public static String getHeaderColorSetting(Context pContext) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        String header_color = sharedPref.getString("header_color", "#00000000");
+//        return header_color;
+//    }
+//
+//    public static String getHeaderTextColorSetting(Context pContext) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        String header_text_color = sharedPref.getString("header_text_color", "#FF000000");
+//        return header_text_color;
+//    }
+//
+//    public static void setContentFilter(Context pContext, String new_value) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        SharedPreferences.Editor edit = sharedPref.edit();
+//        edit.putString("content_filter",new_value);
+//        edit.apply();
+//    }
+//
+//    public static String getContentFilter(Context pContext) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        String header_text_color = sharedPref.getString("content_filter", "1,2,3,4,5");
+//        return header_text_color;
+//    }
+//
+//    public static void setContentSort(Context pContext, int new_value) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        SharedPreferences.Editor edit = sharedPref.edit();
+//        edit.putInt("content_sort",new_value);
+//        edit.apply();
+//    }
+//
+//    public static int getContentSort(Context pContext) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        int header_text_color = sharedPref.getInt("content_sort", 1);
+//        return header_text_color;
+//    }
+//
+//    public static void setContentClassification(Context pContext, String new_value) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        SharedPreferences.Editor edit = sharedPref.edit();
+//        edit.putString("content_class",new_value);
+//        edit.apply();
+//    }
+//
+//    public static String getContentClassification(Context pContext) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        String header_text_color = sharedPref.getString("content_class", "1,2,3,4");
+//        return header_text_color;
+//    }
+//
+//    public static final int CPAAS_MODE_FLOATING = 0;
+//    public static final int CPAAS_MODE_DOCKED = 1;
+//    public static final int CPAAS_MODE_BURGER = 2;
+//    public static final int CPAAS_MODE_MIX = 4;
+//    public static final int DEFAULT_CPAAS_MODE = CPAAS_MODE_DOCKED;
+//    public static int getCpaasMode(Context pContext) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        int mode_index = sharedPref.getInt("cpaas_mode", DEFAULT_CPAAS_MODE);
+//        return mode_index;
+//    }
+//
+//    public static void setCpaasMode(Context pContext, int new_value) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        SharedPreferences.Editor edit = sharedPref.edit();
+//        edit.putInt("cpaas_mode",new_value);
+//        edit.apply();
+//    }
+//
+//    public static final int CPAAS_FLOAT_MODE_IN_APP = 3;
+//    public static final int CPAAS_FLOAT_MODE_OUT_APP = 4;
+//    public static int getCpaasFloatMode(Context pContext) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        int mode_index = sharedPref.getInt("cpaas_float_mode", CPAAS_FLOAT_MODE_IN_APP);
+//        return mode_index;
+//    }
+//    public static void setCpaasFloatMode(Context pContext, int new_value) {
+//        final SharedPreferences sharedPref = pContext.getSharedPreferences("PREF_SYS", Context.MODE_PRIVATE);
+//        SharedPreferences.Editor edit = sharedPref.edit();
+//        edit.putInt("cpaas_float_mode",new_value);
+//        edit.apply();
+//    }
+//
+//    public static String getURLFirstTab() {
+//        return CoreDataSqlite_PrefsDB.get("app_builder_url_first_tab", "");
+//    }
+//
+//    public static String getURLThirdTab() {
+//        return  CoreDataSqlite_PrefsDB.get("app_builder_url_third_tab", "");
+//    }
+//
+//    public static String getURLBase() {
+//        return  CoreDataSqlite_PrefsDB.get("app_builder_url_base", Util_RandomCrypt.decrypt("3<rl;duhpt<<=vswwk"));
+//    }
+//
+//    public static void setURLFirstTab(String new_value) {
+//        CoreDataSqlite_PrefsDB.put("app_builder_url_first_tab", new_value);
+//    }
+//
+//    public static void setURLThirdTab(String new_value) {
+//        CoreDataSqlite_PrefsDB.put("app_builder_url_third_tab", new_value);
+//    }
+//
+//    public static void setURLBase(String new_value) {
+//        CoreDataSqlite_PrefsDB.put("app_builder_url_base", new_value);
+//    }
+//
+//    public static String DEFAULT_TAB_AMOUNT = "4";
+//
+//    public static String getTabAmount(){
+//        return CoreDataSqlite_PrefsDB.get("app_builder_tab_amount", DEFAULT_TAB_AMOUNT);
+//    }
+//
+//    public static void setTabAmount(Context pContext, String new_value){
+//        CoreDataSqlite_PrefsDB.put("app_builder_tab_amount", new_value);
+//    }

+ 52 - 0
appbuilder-ios/AppBuilder/AppBuilder/SceneDelegate.swift

@@ -0,0 +1,52 @@
+//
+//  SceneDelegate.swift
+//  TestQmeraLite
+//
+//  Created by Qindi on 29/11/21.
+//
+
+import UIKit
+
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+
+    var window: UIWindow?
+
+
+    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
+        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
+        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
+        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
+        guard let _ = (scene as? UIWindowScene) else { return }
+    }
+
+    func sceneDidDisconnect(_ scene: UIScene) {
+        // Called as the scene is being released by the system.
+        // This occurs shortly after the scene enters the background, or when its session is discarded.
+        // Release any resources associated with this scene that can be re-created the next time the scene connects.
+        // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
+    }
+
+    func sceneDidBecomeActive(_ scene: UIScene) {
+        // Called when the scene has moved from an inactive state to an active state.
+        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+    }
+
+    func sceneWillResignActive(_ scene: UIScene) {
+        // Called when the scene will move from an active state to an inactive state.
+        // This may occur due to temporary interruptions (ex. an incoming phone call).
+    }
+
+    func sceneWillEnterForeground(_ scene: UIScene) {
+        // Called as the scene transitions from the background to the foreground.
+        // Use this method to undo the changes made on entering the background.
+    }
+
+    func sceneDidEnterBackground(_ scene: UIScene) {
+        // Called as the scene transitions from the foreground to the background.
+        // Use this method to save data, release shared resources, and store enough scene-specific state information
+        // to restore the scene back to its current state.
+    }
+
+
+}
+

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

@@ -0,0 +1,919 @@
+//
+//  SecondTabViewController.swift
+//  AppBuilder
+//
+//  Created by Kevin Maulana on 30/03/22.
+//
+
+import UIKit
+import FMDB
+import NexilisLite
+import Speech
+
+class SecondTabViewController: UIViewController, UIScrollViewDelegate {
+    
+    deinit {
+        print(#function, ">>>> TADAA")
+        NotificationCenter.default.removeObserver(self)
+    }
+    
+    var isChooser: ((String, String) -> ())?
+    
+    var isAdmin: Bool = false
+    
+    var chats: [Chat] = []
+    
+    var contacts: [User] = []
+    
+    var groups: [Group] = []
+    
+    var cancelSearchButton = UIBarButtonItem()
+    var menuItem = UIBarButtonItem()
+    var voiceItem = UIBarButtonItem()
+    
+    var childrenMenu = [UIAction]()
+
+    lazy var searchController: UISearchController = {
+        var searchController = UISearchController(searchResultsController: nil)
+        searchController.delegate = self
+        searchController.searchResultsUpdater = self
+//        searchController.searchBar.showsBookmarkButton = true
+        searchController.searchBar.autocapitalizationType = .none
+        searchController.searchBar.delegate = self
+        searchController.searchBar.placeholder = "Search chats & messages".localized()
+        searchController.searchBar.barTintColor = .secondaryColor
+        searchController.searchBar.searchTextField.backgroundColor = .secondaryColor
+        searchController.obscuresBackgroundDuringPresentation = false
+        return searchController
+    }()
+    
+    lazy var segment: UISegmentedControl = {
+        print("Chat".localized())
+        var segment = UISegmentedControl(items: ["Chat".localized(), "Group".localized()])
+        segment.sizeToFit()
+        segment.selectedSegmentIndex = 0
+        segment.addTarget(self, action: #selector(segmentChanged(sender:)), for: .valueChanged)
+        return segment
+    }()
+    
+    var fillteredData: [Any] = []
+    
+    var isSearchBarEmpty: Bool {
+        return searchController.searchBar.text?.isEmpty ?? true
+    }
+    
+    var isFilltering: Bool {
+        return searchController.isActive && !isSearchBarEmpty
+    }
+    @IBOutlet var tableView: UITableView!
+    
+    let speechRecognizer = SFSpeechRecognizer()
+
+    var recognitionRequest : SFSpeechAudioBufferRecognitionRequest?
+    var recognitionTask : SFSpeechRecognitionTask?
+    let audioEngine = AVAudioEngine()
+    
+    func filterContentForSearchText(_ searchText: String) {
+        switch segment.selectedSegmentIndex {
+        case 1:
+            fillteredData = self.groups.filter { $0.name.lowercased().contains(searchText.lowercased()) }
+        default:
+            fillteredData = self.chats.filter { $0.name.lowercased().contains(searchText.lowercased()) || $0.messageText.lowercased().contains(searchText.lowercased()) }
+        }
+        tableView.reloadData()
+    }
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        SFSpeechRecognizer.requestAuthorization({ authStatus in
+            var isButtonEnabled = false
+
+            OperationQueue.main.addOperation {
+                switch authStatus {
+                case .authorized:
+                    isButtonEnabled = true
+                    print("User allowed access to speech recognition")
+
+                case .denied:
+                    isButtonEnabled = false
+                    print("User denied access to speech recognition")
+
+                case .restricted:
+                    isButtonEnabled = false
+                    print("Speech recognition restricted on this device")
+
+                case .notDetermined:
+                    isButtonEnabled = false
+                    print("Speech recognition not yet authorized")
+                @unknown default:
+                    print("Speech recognition not yet authorized")
+                }
+            }
+        })
+        let me = UserDefaults.standard.string(forKey: "me")!
+        Database.shared.database?.inTransaction({ fmdb, rollback in
+            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME, LAST_NAME, IMAGE_ID, USER_TYPE from BUDDY where F_PIN = '\(me)'"), cursor.next() {
+                isAdmin = cursor.string(forColumnIndex: 3) == "23" || cursor.string(forColumnIndex: 3) == "24"
+                cursor.close()
+            }
+        })
+        
+//        navigationController?.title = "Start Conversation"
+        
+        //        navigationController?.navigationBar.prefersLargeTitles = true
+        
+        cancelSearchButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancel(sender:)))
+        
+        var childrenMenu : [UIAction] = [
+//            UIAction(title: "Create Group", image: UIImage(systemName: "person.and.person"), handler: {[weak self](_) in
+//                let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "createGroupNav") as! UINavigationController
+//                let vc = controller.topViewController as! GroupCreateViewController
+//                vc.isDismiss = { id in
+//                    let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "groupDetailView") as! GroupDetailViewController
+//                    controller.data = id
+//                    self?.navigationController?.show(controller, sender: nil)
+//                }
+//                self?.navigationController?.present(controller, animated: true, completion: nil)
+//            }),
+//            UIAction(title: "Add Friends", image: UIImage(systemName: "person.badge.plus"), handler: {[weak self](_) in
+//                let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "addFriendNav") as! UINavigationController
+//                if let vc = controller.viewControllers.first as? AddFriendTableViewController {
+//                    vc.isDismiss = {
+//                        self?.getContacts {
+//                            DispatchQueue.main.async {
+//                                self?.tableView.reloadData()
+//                            }
+//                        }
+//                    }
+//                }
+//                self?.navigationController?.present(controller, animated: true, completion: nil)
+//            }),
+//            UIAction(title: "Configure Email", image: UIImage(systemName: "mail"), handler: {[weak self](_) in
+//
+//            }),
+//            UIAction(title: "Favorite Messages", image: UIImage(systemName: "star"), handler: {[weak self](_) in
+//                let editorStaredVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "staredVC") as! EditorStarMessages
+//                self?.navigationController?.show(editorStaredVC, sender: nil)
+//            }),
+        ]
+        //debug only
+//        isAdmin = true
+        if(isAdmin){
+            childrenMenu.append(UIAction(title: "Broadcast Message", image: UIImage(systemName: "envelope.open"), handler: {[weak self](_) in
+                let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "broadcastNav")
+                self?.navigationController?.present(controller, animated: true, completion: nil)
+            }))
+        }
+        
+//        let menu = UIMenu(title: "", children: childrenMenu)
+        menuItem = UIBarButtonItem(image: UIImage(systemName: "square.and.pencil"), style: .plain, target: self, action: #selector(startConversation))
+        voiceItem = UIBarButtonItem(image: UIImage(systemName: "mic.fill"), style: .plain, target: self, action: #selector(recordAudio))
+        
+//        tabBarController?.navigationItem.leftBarButtonItem = cancelSearchButton
+        tabBarController?.navigationItem.leftBarButtonItem = voiceItem
+        tabBarController?.navigationItem.rightBarButtonItem = menuItem
+        tabBarController?.navigationItem.searchController = searchController
+//        navigationItem.searchController = searchController
+//        navigationItem.hidesSearchBarWhenScrolling = true
+        
+        definesPresentationContext = true
+        
+        
+        NotificationCenter.default.addObserver(self, selector: #selector(onReceiveMessage(notification:)), name: NSNotification.Name(rawValue: "onReceiveChat"), object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(onReload(notification:)), name: NSNotification.Name(rawValue: "onMember"), object: nil)
+        
+        
+        
+        tableView.tableHeaderView = segment
+        
+        pullBuddy()
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        let isBurger = cpaasMode == PrefsUtil.CPAAS_MODE_BURGER
+        navigationController?.setNavigationBarHidden(!isBurger, animated: false)
+    }
+    
+    @objc func startConversation(){
+        let navigationController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactChatNav") as! UINavigationController
+        navigationController.modalPresentationStyle = .fullScreen
+        navigationController.navigationBar.tintColor = .white
+        navigationController.navigationBar.barTintColor = .mainColor
+        navigationController.navigationBar.isTranslucent = false
+        let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+        navigationController.navigationBar.titleTextAttributes = textAttributes
+        navigationController.view.backgroundColor = .mainColor
+        self.navigationController?.present(navigationController, animated: true, completion: nil)
+    }
+    
+    @objc func recordAudio(){
+        if audioEngine.isRunning {
+            self.audioEngine.stop()
+            self.recognitionRequest?.endAudio()
+            voiceItem.image = UIImage(systemName: "mic.fill")
+            searchController.searchBar.isUserInteractionEnabled = true
+            searchController.automaticallyShowsCancelButton = true
+            searchController.hidesNavigationBarDuringPresentation = true
+        } else {
+            print("start recording")
+            self.startRecording()
+            voiceItem.image = UIImage(systemName: "mic")
+            searchController.searchBar.isUserInteractionEnabled = false
+        }
+    }
+    
+    func startRecording() {
+
+            // Clear all previous session data and cancel task
+            if recognitionTask != nil {
+                recognitionTask?.cancel()
+                recognitionTask = nil
+            }
+
+            // Create instance of audio session to record voice
+            let audioSession = AVAudioSession.sharedInstance()
+            do {
+                try audioSession.setCategory(AVAudioSession.Category.record, mode: AVAudioSession.Mode.measurement, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
+                try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
+            } catch {
+                print("audioSession properties weren't set because of an error.")
+            }
+
+            self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
+
+            let inputNode = audioEngine.inputNode
+
+            guard let recognitionRequest = recognitionRequest else {
+                fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
+            }
+
+            recognitionRequest.shouldReportPartialResults = true
+
+            self.recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
+
+                var isFinal = false
+
+                if result != nil {
+
+                    self.searchController.searchBar.searchTextField.text = result?.bestTranscription.formattedString
+                    self.updateSearchResults(for: self.searchController)
+                    isFinal = (result?.isFinal)!
+                }
+
+                if error != nil || isFinal {
+
+                    self.audioEngine.stop()
+                    inputNode.removeTap(onBus: 0)
+
+                    self.recognitionRequest = nil
+                    self.recognitionTask = nil
+
+//                    self.btnStart.isEnabled = true
+                }
+            })
+
+            let recordingFormat = inputNode.outputFormat(forBus: 0)
+            inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
+                self.recognitionRequest?.append(buffer)
+            }
+
+            self.audioEngine.prepare()
+
+            do {
+                try self.audioEngine.start()
+            } catch {
+                print("audioEngine couldn't start because of an error.")
+            }
+//
+//            self.lblText.text = "Say something, I'm listening!"
+        }
+    
+    override func viewWillAppear(_ animated: Bool) {
+//        tabBarController?.navigationItem.leftBarButtonItem = cancelSearchButton
+        self.navigationController?.navigationBar.topItem?.title = Bundle.main.displayName
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        let isBurger = cpaasMode == PrefsUtil.CPAAS_MODE_BURGER
+        navigationController?.navigationBar.backgroundColor = .clear
+        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
+        navigationController?.navigationBar.shadowImage = UIImage()
+        navigationController?.navigationBar.isTranslucent = true
+        navigationController?.setNavigationBarHidden(false, animated: false)
+        tabBarController?.navigationItem.leftBarButtonItem = voiceItem
+        tabBarController?.navigationItem.searchController = searchController
+        tabBarController?.navigationItem.rightBarButtonItem = menuItem
+        let randomInt = Int.random(in: 1..<2)
+        backgroundImage.image = UIImage(named: "pb_lbackground_\(randomInt)")
+        getData()
+    }
+    
+    override func viewWillDisappear(_ animated: Bool) {
+        tabBarController?.navigationItem.leftBarButtonItem = nil
+        tabBarController?.navigationItem.searchController = nil
+        tabBarController?.navigationItem.rightBarButtonItem = nil
+    }
+    
+    @objc func onReload(notification: NSNotification) {
+        let data:[AnyHashable : Any] = notification.userInfo!
+        if data["member"] as! String == UserDefaults.standard.string(forKey: "me")! {
+            DispatchQueue.main.async {
+                self.getData()
+            }
+        }
+    }
+    
+    @objc func onReceiveMessage(notification: NSNotification) {
+        let data:[AnyHashable : Any] = notification.userInfo!
+        guard let dataMessage = data["message"] as? TMessage else {
+            return
+        }
+        let isUser = User.getData(pin: dataMessage.getBody(key: CoreMessage_TMessageKey.L_PIN)) != nil
+        let chatId = dataMessage.getBody(key: CoreMessage_TMessageKey.CHAT_ID, default_value: "").isEmpty ? dataMessage.getBody(key: CoreMessage_TMessageKey.L_PIN) : dataMessage.getBody(key: CoreMessage_TMessageKey.CHAT_ID, default_value: "")
+        let pin = isUser ? dataMessage.getBody(key: CoreMessage_TMessageKey.F_PIN) : chatId
+        let messageId = dataMessage.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
+        if let index = chats.firstIndex(of: Chat(pin: pin)) {
+            guard let chat = Chat.getData(messageId: messageId).first else {
+                return
+            }
+            DispatchQueue.main.async {
+                if self.segment.selectedSegmentIndex == 0 {
+                    self.tableView.beginUpdates()
+                    self.chats.remove(at: index)
+                    self.tableView.deleteRows(at: [IndexPath(row: index, section: 0)], with: .none)
+                }
+                self.chats.insert(chat, at: 0)
+                if self.segment.selectedSegmentIndex == 0 {
+                    self.tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .none)
+                    self.tableView.endUpdates()
+                }
+            }
+        } else {
+            guard let chat = Chat.getData(messageId: messageId).first else {
+                return
+            }
+            DispatchQueue.main.async {
+                if self.segment.selectedSegmentIndex == 0 {
+                    self.tableView.beginUpdates()
+                }
+                self.chats.insert(chat, at: 0)
+                if self.segment.selectedSegmentIndex == 0 {
+                    self.tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .none)
+                    self.tableView.endUpdates()
+                }
+            }
+        }
+    }
+    
+    @objc func add(sender: Any) {
+        
+    }
+    
+    @objc func cancel(sender: Any) {
+        navigationController?.dismiss(animated: true, completion: nil)
+    }
+    
+    @objc func segmentChanged(sender: Any) {
+        filterContentForSearchText(searchController.searchBar.text!)
+    }
+    
+    // MARK: - Data source
+    
+    func getData() {
+        getChats {
+            self.getContacts {
+                self.getGroups { g1 in
+                    self.getOpenGroups(listGroups: g1, completion: { g in
+                        self.groups.removeAll()
+                        self.groups.append(contentsOf: g1)
+                        for og in g {
+                            if self.groups.first(where: { $0.id == og.id }) == nil {
+                                self.groups.append(og)
+                            }
+                        }
+                        DispatchQueue.main.async {
+                            self.tableView.reloadData()
+                        }
+                    })
+                }
+            }
+        }
+    }
+    
+    func getChats(completion: @escaping ()->()) {
+        DispatchQueue.global().async {
+            self.chats.removeAll()
+            self.chats.append(contentsOf: Chat.getData())
+            completion()
+        }
+    }
+    
+    private func getContacts(completion: @escaping ()->()) {
+        DispatchQueue.global().async {
+            self.contacts.removeAll()
+            Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                do {
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, image_id, official_account, user_type FROM BUDDY where f_pin <> '\(UserDefaults.standard.string(forKey: "me")!)' order by 5 desc, 2 collate nocase asc") {
+                        while cursorData.next() {
+                            let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
+                                            firstName: cursorData.string(forColumnIndex: 1) ?? "",
+                                            lastName: cursorData.string(forColumnIndex: 2) ?? "",
+                                            thumb: cursorData.string(forColumnIndex: 3) ?? "",
+                                            userType: cursorData.string(forColumnIndex: 5) ?? "")
+                            if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
+                                continue
+                            }
+                            user.official = cursorData.string(forColumnIndex: 4) ?? ""
+                            self.contacts.append(user)
+                        }
+                        cursorData.close()
+                    }
+                } catch {
+                    rollback.pointee = true
+                    print(error)
+                }
+                completion()
+            })
+        }
+    }
+    
+    private func getGroupRecursive(fmdb: FMDatabase, id: String = "", parent: String = "") -> [Group] {
+        var data: [Group] = []
+        var query = "select g.group_id, g.f_name, g.image_id, g.quote, g.created_by, g.created_date, g.parent, g.group_type, g.is_open, g.official, g.is_education from GROUPZ g where "
+        if id.isEmpty {
+            query += "g.parent = '\(parent)'"
+        } else {
+            query += "g.group_id = '\(id)'"
+        }
+        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query) {
+            while cursor.next() {
+                let group = Group(
+                    id: cursor.string(forColumnIndex: 0) ?? "",
+                    name: cursor.string(forColumnIndex: 1) ?? "",
+                    profile: cursor.string(forColumnIndex: 2) ?? "",
+                    quote: cursor.string(forColumnIndex: 3) ?? "",
+                    by: cursor.string(forColumnIndex: 4) ?? "",
+                    date: cursor.string(forColumnIndex: 5) ?? "",
+                    parent: cursor.string(forColumnIndex: 6) ?? "",
+                    chatId: "",
+                    groupType: cursor.string(forColumnIndex: 7) ?? "",
+                    isOpen: cursor.string(forColumnIndex: 8) ?? "",
+                    official: cursor.string(forColumnIndex: 9) ?? "",
+                    isEducation: cursor.string(forColumnIndex: 10) ?? "")
+                
+                if group.chatId.isEmpty {
+                    let lounge = Group(id: group.id, name: "Lounge".localized(), profile: "", quote: group.quote, by: group.by, date: group.date, parent: group.id, chatId: group.chatId, groupType: group.groupType, isOpen: group.isOpen, official: group.official, isEducation: group.isEducation, isLounge: true)
+                    group.childs.append(lounge)
+                }
+                
+                if let topicCursor = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id, title, thumb from DISCUSSION_FORUM where group_id = '\(group.id)'") {
+                    while topicCursor.next() {
+                        let topic = Group(id: group.id,
+                                          name: topicCursor.string(forColumnIndex: 1) ?? "",
+                                          profile: topicCursor.string(forColumnIndex: 2) ?? "",
+                                          quote: group.quote,
+                                          by: group.by,
+                                          date: group.date,
+                                          parent: group.id,
+                                          chatId: topicCursor.string(forColumnIndex: 0) ?? "",
+                                          groupType: group.groupType,
+                                          isOpen: group.isOpen,
+                                          official: group.official,
+                                          isEducation: group.isEducation)
+                        group.childs.append(topic)
+                    }
+                    topicCursor.close()
+                }
+                
+                if !group.id.isEmpty {
+                    if group.official == "1" {
+                        let idMe = UserDefaults.standard.string(forKey: "me") as String?
+                        if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type FROM BUDDY where f_pin='\(idMe!)'"), cursorUser.next() {
+                            if cursorUser.string(forColumnIndex: 0) == "23" || cursorUser.string(forColumnIndex: 0) == "24" {
+                                group.childs.append(contentsOf: getGroupRecursive(fmdb: fmdb, parent: group.id))
+                            }
+                            cursorUser.close()
+                        }
+                    } else if group.official != "1"{
+                        group.childs.append(contentsOf: getGroupRecursive(fmdb: fmdb, parent: group.id))
+                    }
+                }
+                data.append(group)
+            }
+            cursor.close()
+        }
+        return data
+    }
+    
+    private func getOpenGroups(listGroups: [Group], completion: @escaping ([Group]) -> ()) {
+        if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getOpenGroups(p_account: "1,2,3,5,6,7", offset: "0", search: "")) {
+            var dataGroups: [Group] = []
+            if (response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "00") {
+                let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
+                if let json = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: []) as? [[String: Any?]] {
+                    for dataJson in json {
+                        let group = Group(
+                            id: dataJson[CoreMessage_TMessageKey.GROUP_ID] as? String ?? "",
+                            name: dataJson[CoreMessage_TMessageKey.GROUP_NAME] as? String ?? "",
+                            profile: dataJson[CoreMessage_TMessageKey.THUMB_ID] as? String ?? "",
+                            quote: dataJson[CoreMessage_TMessageKey.QUOTE] as? String ?? "",
+                            by: dataJson[CoreMessage_TMessageKey.BLOCK] as? String ?? "",
+                            date: "",
+                            parent: "",
+                            chatId: "",
+                            groupType: "NOTJOINED",
+                            isOpen: dataJson[CoreMessage_TMessageKey.IS_OPEN] as? String ?? "",
+                            official: "0",
+                            isEducation: "")
+                        dataGroups.append(group)
+                    }
+                }
+            } else {
+                DispatchQueue.main.async {
+                    self.groups.removeAll()
+                    self.groups.append(contentsOf: listGroups)
+                    self.tableView.reloadData()
+                }
+            }
+            completion(dataGroups)
+        }
+    }
+    
+    private func getGroups(id: String = "", parent: String = "", completion: @escaping ([Group]) -> ()) {
+        DispatchQueue.global().async {
+            Database.shared.database?.inTransaction({ fmdb, rollback in
+                completion(self.getGroupRecursive(fmdb: fmdb, id: id, parent: parent))
+            })
+        }
+    }
+    
+    private func pullBuddy() {
+        if let me = UserDefaults.standard.string(forKey: "me") {
+            DispatchQueue.global().async {
+                let _ = Nexilis.write(message: CoreMessage_TMessageBank.getBatchBuddiesInfos(p_f_pin: me, last_update: 0))
+            }
+        }
+    }
+    
+    private func joinOpenGroup(groupId: String, flagMember: String = "0", completion: @escaping (Bool) -> ()) {
+        DispatchQueue.global().async {
+            var result: Bool = false
+            let idMe = UserDefaults.standard.string(forKey: "me") as String?
+            if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddGroupMember(p_group_id: groupId, p_member_pin: idMe!, p_position: "0")), response.isOk() {
+                result = true
+            }
+            completion(result)
+        }
+    }
+
+    @IBOutlet weak var backgroundImage: UIImageView!
+    
+
+    /*
+    // MARK: - Navigation
+
+    // In a storyboard-based application, you will often want to do a little preparation before navigation
+    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
+        // Get the new view controller using segue.destination.
+        // Pass the selected object to the new view controller.
+    }
+    */
+
+}
+
+// MARK: - Table view data source
+
+extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
+    
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        switch segment.selectedSegmentIndex {
+        case 0:
+            let data: Chat
+            if isFilltering {
+                data = fillteredData[indexPath.row] as! Chat
+            } else {
+                data = chats[indexPath.row]
+            }
+            if let chooser = isChooser {
+                if data.pin == "-999"{
+                    return
+                }
+                chooser(data.messageScope, data.pin)
+                dismiss(animated: true, completion: nil)
+                return
+            }
+            let user = User.getData(pin: data.pin)
+            if user != nil || data.pin == "-999" {
+                let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
+                editorPersonalVC.hidesBottomBarWhenPushed = true
+                editorPersonalVC.unique_l_pin = data.pin
+                navigationController?.show(editorPersonalVC, sender: nil)
+            } else {
+                let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
+                editorGroupVC.hidesBottomBarWhenPushed = true
+                editorGroupVC.unique_l_pin = data.pin
+                navigationController?.show(editorGroupVC, sender: nil)
+            }
+        case 1:
+            let group: Group
+            if isFilltering {
+                if indexPath.row == 0 {
+                    group = fillteredData[indexPath.section] as! Group
+                } else {
+                    group = (fillteredData[indexPath.section] as! Group).childs[indexPath.row - 1]
+                }
+            } else {
+                if indexPath.row == 0 {
+                    group = groups[indexPath.section]
+                } else {
+                    group = groups[indexPath.section].childs[indexPath.row - 1]
+                }
+            }
+            group.isSelected = !group.isSelected
+            if group.groupType == "NOTJOINED" {
+                let alert = UIAlertController(title: "Do you want to join this group?".localized(), message: "Groups : \(group.name)\nMembers: \(group.by)".localized(), preferredStyle: .alert)
+                alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: nil))
+                alert.addAction(UIAlertAction(title: "Join".localized(), style: .default, handler: {(_) in
+                    self.joinOpenGroup(groupId: group.id, completion: { result in
+                        if result {
+                            DispatchQueue.main.async {
+                                let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
+                                editorGroupVC.hidesBottomBarWhenPushed = true
+                                editorGroupVC.unique_l_pin = group.id
+                                self.navigationController?.show(editorGroupVC, sender: nil)
+                            }
+                        }
+                    })
+                }))
+                self.present(alert, animated: true, completion: nil)
+                return
+            }
+            if group.childs.count == 0 {
+                let groupId = group.chatId.isEmpty ? group.id : group.chatId
+                if let chooser = isChooser {
+                    chooser("4", groupId)
+                    dismiss(animated: true, completion: nil)
+                    return
+                }
+                let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
+                editorGroupVC.hidesBottomBarWhenPushed = true
+                editorGroupVC.unique_l_pin = groupId
+                navigationController?.show(editorGroupVC, sender: nil)
+            } else {
+                if indexPath.row == 0 {
+                    tableView.reloadData()
+                } else {
+                    getGroups(id: group.id) { g in
+                        DispatchQueue.main.async {
+                            if self.isFilltering {
+                                self.fillteredData.remove(at: indexPath.section)
+                                self.fillteredData.insert(contentsOf: g, at: indexPath.section)
+                            } else {
+                                self.groups.remove(at: indexPath.section)
+                                self.groups.insert(contentsOf: g, at: indexPath.section)
+                            }
+                            tableView.reloadData()
+                        }
+                    }
+                }
+            }
+        default:
+            let data = contacts[indexPath.row]
+            let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
+            editorPersonalVC.hidesBottomBarWhenPushed = true
+            editorPersonalVC.unique_l_pin = data.pin
+            navigationController?.show(editorPersonalVC, sender: nil)
+        }
+    }
+    
+    func numberOfSections(in tableView: UITableView) -> Int {
+        if isFilltering {
+            if segment.selectedSegmentIndex == 1 {
+                return fillteredData.count
+            }
+            return 1
+        } else {
+            if segment.selectedSegmentIndex == 1 {
+                return groups.count
+            }
+            return 1
+        }
+    }
+    
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        var value = 0
+        if isFilltering {
+            if segment.selectedSegmentIndex == 1, let groups = fillteredData as? [Group] {
+                let group = groups[section]
+                if group.isSelected {
+                    value = group.childs.count + 1
+                } else {
+                    value = 1
+                }
+                return value
+            }
+            return fillteredData.count
+        }
+        switch segment.selectedSegmentIndex {
+        case 0:
+            value = chats.count
+        case 1:
+            let group = groups[section]
+            if group.isSelected {
+                value = group.childs.count + 1
+            } else {
+                value = 1
+            }
+        default:
+            value = chats.count
+        }
+        return value
+    }
+    
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        var cell: UITableViewCell!
+        switch segment.selectedSegmentIndex {
+        case 0:
+            cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifierChat", for: indexPath)
+            cell.separatorInset.left = 60.0
+            let content = cell.contentView
+            if content.subviews.count > 0 {
+                content.subviews.forEach { $0.removeFromSuperview() }
+            }
+            let data: Chat
+            if isFilltering {
+                data = fillteredData[indexPath.row] as! Chat
+            } else {
+                data = chats[indexPath.row]
+            }
+            let imageView = UIImageView()
+            content.addSubview(imageView)
+            imageView.translatesAutoresizingMaskIntoConstraints = false
+            NSLayoutConstraint.activate([
+                imageView.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 10.0),
+                imageView.topAnchor.constraint(equalTo: content.topAnchor, constant: 10.0),
+                imageView.bottomAnchor.constraint(equalTo: content.bottomAnchor, constant: -20.0),
+                imageView.widthAnchor.constraint(equalToConstant: 40.0),
+                imageView.heightAnchor.constraint(equalToConstant: 40.0)
+            ])
+            if data.profile.isEmpty && data.pin != "-999" {
+                let user = User.getData(pin: data.pin)
+                if user != nil {
+                    imageView.image = UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
+                } else {
+                    imageView.image = UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
+                }
+            } else {
+                getImage(name: data.profile, placeholderImage: UIImage(named: data.pin == "-999" ? "pb_ball" : "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, completion: { result, isDownloaded, image in
+                    imageView.image = image
+                    if !result {
+                        imageView.tintColor = .mainColor
+                    }
+                    if isDownloaded {
+                        tableView.reloadRows(at: [indexPath], with: .none)
+                    }
+                })
+            }
+            let titleView = UILabel()
+            content.addSubview(titleView)
+            titleView.translatesAutoresizingMaskIntoConstraints = false
+            NSLayoutConstraint.activate([
+                titleView.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 10.0),
+                titleView.topAnchor.constraint(equalTo: content.topAnchor, constant: 10.0),
+                titleView.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -40.0),
+            ])
+            titleView.text = data.name
+            titleView.font = UIFont.systemFont(ofSize: 14, weight: .medium)
+            
+            let messageView = UILabel()
+            content.addSubview(messageView)
+            messageView.translatesAutoresizingMaskIntoConstraints = false
+            NSLayoutConstraint.activate([
+                messageView.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 10.0),
+                messageView.topAnchor.constraint(equalTo: titleView.bottomAnchor, constant: 5.0),
+                messageView.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -40.0),
+            ])
+            messageView.textColor = .gray
+            let text = Utils.previewMessageText(chat: data)
+            if let attributeText = text as? NSAttributedString {
+                messageView.attributedText = attributeText
+            } else if let stringText = text as? String {
+                messageView.text = stringText
+            }
+            messageView.font = UIFont.systemFont(ofSize: 12)
+            messageView.numberOfLines = 2
+            
+            if data.counter != "0" {
+                let viewCounter = UIView()
+                content.addSubview(viewCounter)
+                viewCounter.translatesAutoresizingMaskIntoConstraints = false
+                NSLayoutConstraint.activate([
+                    viewCounter.centerYAnchor.constraint(equalTo: content.centerYAnchor),
+                    viewCounter.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -20),
+                    viewCounter.widthAnchor.constraint(greaterThanOrEqualToConstant: 20),
+                    viewCounter.heightAnchor.constraint(equalToConstant: 20)
+                ])
+                viewCounter.backgroundColor = .systemRed
+                viewCounter.layer.cornerRadius = 10
+                viewCounter.clipsToBounds = true
+                viewCounter.layer.borderWidth = 0.5
+                viewCounter.layer.borderColor = UIColor.secondaryColor.cgColor
+
+                let labelCounter = UILabel()
+                viewCounter.addSubview(labelCounter)
+                labelCounter.translatesAutoresizingMaskIntoConstraints = false
+                NSLayoutConstraint.activate([
+                    labelCounter.centerYAnchor.constraint(equalTo: viewCounter.centerYAnchor),
+                    labelCounter.leadingAnchor.constraint(equalTo: viewCounter.leadingAnchor, constant: 2),
+                    labelCounter.trailingAnchor.constraint(equalTo: viewCounter.trailingAnchor, constant: -2),
+                ])
+                labelCounter.font = UIFont.systemFont(ofSize: 11)
+                if Int(data.counter)! > 99 {
+                    labelCounter.text = "99+"
+                } else {
+                    labelCounter.text = data.counter
+                }
+                labelCounter.textColor = .secondaryColor
+                labelCounter.textAlignment = .center
+            }
+        case 1:
+            cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifierGroup", for: indexPath)
+            var content = cell.defaultContentConfiguration()
+            content.textProperties.font = UIFont.systemFont(ofSize: 14)
+            let group: Group
+            if isFilltering {
+                if indexPath.row == 0 {
+                    group = fillteredData[indexPath.section] as! Group
+                } else {
+                    group = (fillteredData[indexPath.section] as! Group).childs[indexPath.row - 1]
+                }
+            } else {
+                if indexPath.row == 0 {
+                    group = groups[indexPath.section]
+                } else {
+                    group = groups[indexPath.section].childs[indexPath.row - 1]
+                }
+            }
+            if group.official == "1" && group.parent == "" {
+                content.attributedText = self.set(image: UIImage(named: "ic_official_flag", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "  \(group.name)", size: 15, y: -4)
+            }
+            else if group.isOpen == "1" && group.parent == "" {
+                if self.traitCollection.userInterfaceStyle == .dark {
+                    content.attributedText = self.set(image: UIImage(systemName: "globe")!.withTintColor(.white), with: "  \(group.name)", size: 15, y: -4)
+                } else {
+                    content.attributedText = self.set(image: UIImage(systemName: "globe")!, with: "  \(group.name)", size: 15, y: -4)
+                }
+            } else if group.parent == "" {
+                if self.traitCollection.userInterfaceStyle == .dark {
+                    content.attributedText = self.set(image: UIImage(systemName: "lock.fill")!.withTintColor(.white), with: "  \(group.name)", size: 15, y: -4)
+                } else {
+                    content.attributedText = self.set(image: UIImage(systemName: "lock.fill")!, with: "  \(group.name)", size: 15, y: -4)
+                }
+            } else {
+                content.text = group.name
+            }
+            content.imageProperties.maximumSize = CGSize(width: 40, height: 40)
+            getImage(name: group.profile, placeholderImage: UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true) { result, isDownloaded, image in
+                content.image = image
+                tableView.reloadRows(at: [indexPath], with: .none)
+            }
+            cell.contentConfiguration = content
+        default:
+            cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifierContact", for: indexPath)
+            var content = cell.defaultContentConfiguration()
+            content.text = ""
+            cell.contentConfiguration = content
+        }
+        return cell
+    }
+    
+    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+        return 70.0
+    }
+    
+}
+
+
+extension SecondTabViewController: UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating {
+    
+    func updateSearchResults(for searchController: UISearchController) {
+        filterContentForSearchText(searchController.searchBar.text!)
+    }
+    
+    func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) {
+        recordAudio()
+    }
+    
+    func set(image: UIImage, with text: String, size: CGFloat, y: CGFloat) -> NSAttributedString {
+        let attachment = NSTextAttachment()
+        attachment.image = image
+        attachment.bounds = CGRect(x: 0, y: y, width: size, height: size)
+        let attachmentStr = NSAttributedString(attachment: attachment)
+        
+        let mutableAttributedString = NSMutableAttributedString()
+        mutableAttributedString.append(attachmentStr)
+        
+        let textString = NSAttributedString(string: text)
+        mutableAttributedString.append(textString)
+        
+        return mutableAttributedString
+    }
+    
+}
+

+ 141 - 0
appbuilder-ios/AppBuilder/AppBuilder/ThirdTabViewController.swift

@@ -0,0 +1,141 @@
+//
+//  ThirdTabViewController.swift
+//  AppBuilder
+//
+//  Created by Kevin Maulana on 30/03/22.
+//
+
+import UIKit
+import WebKit
+
+class ThirdTabViewController: UIViewController, UIScrollViewDelegate, UIGestureRecognizerDelegate  {
+
+    @IBOutlet weak var webView: WKWebView!
+    var address = ""
+    private var lastContentOffset: CGFloat = 0
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(collapseDocked))
+        tapGesture.cancelsTouchesInView = false
+        tapGesture.delegate = self
+        webView.scrollView.addGestureRecognizer(tapGesture)
+        let refreshControl = UIRefreshControl()
+        refreshControl.addTarget(self, action: #selector(reloadWebView(_:)), for: .valueChanged)
+        webView.scrollView.addSubview(refreshControl)
+        webView.scrollView.delegate = self
+        // Do any additional setup after loading the view.
+    }
+    
+    override func viewWillAppear(_ animated: Bool) {
+        let me = UserDefaults.standard.string(forKey: "me")
+        
+        var myURL : URL?
+        switch(ViewController.tab3){
+        case "0":
+            address = "https://qmera.io/nexilis/pages/tab1-main-only?f_pin=\(me ?? "")"
+            myURL = URL(string: address)
+        case "1":
+            address = "https://qmera.io/nexilis/pages/tab3-main-only?f_pin=\(me ?? "")"
+            myURL = URL(string: address)
+        case "2":
+            address = "https://qmera.io/nexilis/pages/tab1-main?f_pin=\(me ?? "")"
+            myURL = URL(string: address)
+        case "3":
+            address = "https://qmera.io/nexilis/pages/tab3-commerce?f_pin=\(me ?? "")"
+            myURL = URL(string: address)
+        default:
+            if(!ViewController.tab3.isEmpty){
+                if(ViewController.tab3.lowercased().contains("https://")){
+                    address = ViewController.tab3
+                    myURL = URL(string: address)
+                }
+                else {
+                    address = "https://\(ViewController.tab3)"
+                    myURL = URL(string: address)
+                }
+            }
+        }
+        print(address)
+        if let u = myURL{
+            let myRequest = URLRequest(url: u)
+            webView.load(myRequest)
+        }
+        self.navigationController?.navigationBar.topItem?.title = Bundle.main.displayName
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        let isBurger = cpaasMode == PrefsUtil.CPAAS_MODE_BURGER
+        navigationController?.navigationBar.backgroundColor = .white
+        navigationController?.setNavigationBarHidden(!isBurger, animated: false)
+    }
+    
+    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        if (self.lastContentOffset > scrollView.contentOffset.y && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)) {
+            showTabBar();
+        }
+        else if (self.lastContentOffset != 0 && self.lastContentOffset < scrollView.contentOffset.y && self.lastContentOffset >= 0) {
+            hideTabBar();
+        }
+        self.lastContentOffset = scrollView.contentOffset.y
+        self.collapseDocked()
+    }
+
+    
+    @objc func collapseDocked() {
+        if ViewController.isExpandButton {
+            ViewController.expandButton()
+        }
+    }
+    
+    @objc func reloadWebView(_ sender: UIRefreshControl) {
+        webView.reload()
+        sender.endRefreshing()
+    }
+
+    func hideTabBar() {
+        var viewController = UIApplication.shared.windows.first!.rootViewController
+        if !(viewController is ViewController) {
+            viewController = self.parent
+        }
+        if ViewController.middleButton.isDescendant(of: viewController!.view) {
+            DispatchQueue.main.async {
+                if let viewController = viewController as? ViewController {
+                    viewController.tabBar.isHidden = true
+                }
+                ViewController.removeMiddleButton()
+            }
+        }
+    }
+
+    func showTabBar() {
+        if(ViewController.alwaysHideButton){
+            return
+        }
+        var viewController = UIApplication.shared.windows.first!.rootViewController
+        if !(viewController is ViewController) {
+            viewController = self.parent
+        }
+        if !ViewController.middleButton.isDescendant(of: viewController!.view) {
+            ViewController.isExpandButton = false
+            if let viewController = viewController as? ViewController {
+                viewController.tabBar.isHidden = false
+                viewController.createMidFloatingButton()
+            }
+        }
+    }
+
+    func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
+        scrollView.pinchGestureRecognizer?.isEnabled = false
+    }
+
+
+    /*
+    // MARK: - Navigation
+
+    // In a storyboard-based application, you will often want to do a little preparation before navigation
+    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
+        // Get the new view controller using segue.destination.
+        // Pass the selected object to the new view controller.
+    }
+    */
+
+}

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

@@ -0,0 +1,595 @@
+//
+//  ViewController.swift
+//  TestQmeraLite
+//
+//  Created by Qindi on 29/11/21.
+//
+
+import UIKit
+import NexilisLite
+import AVKit
+import AVFoundation
+import SwiftUI
+import Speech
+import Alamofire
+
+class ViewController: UITabBarController, UITabBarControllerDelegate {
+    let playerController = AVPlayerViewController()
+    static var sURL = "https://www.google.com"
+    static var tab3 = "0"
+    public var isShow: Bool = false
+    public static var chatButton = UIButton()
+    public static var callButton = UIButton()
+    public static var ccButton = UIButton()
+    public static var streamingButton = UIButton()
+    public static var postButton = UIButton()
+    public static var middleButton = UIButton()
+    var buttonChatGR : UITapGestureRecognizer?
+    var buttonCallGR : UITapGestureRecognizer?
+    var buttonCCGR : UITapGestureRecognizer?
+    var buttonStreamGR : UITapGestureRecognizer?
+    var floating : FloatingButton?
+    var firstTab : FirstTabViewController?
+    var secondTab : SecondTabViewController?
+    var thirdTab : ThirdTabViewController?
+    var fourthTab : FourthTabViewController?
+    let emptyTab = EmptyTabViewController()
+    public static var isTab1 = true
+    public static var isTab2 = false
+    public static var isTab3 = false
+    public static var isTab4 = false
+    public static var isExpandButton = false
+    public static var alwaysHideButton = false
+    
+    public static var def: ViewController?
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        ViewController.def = self
+        title = Bundle.main.displayName
+        let customTab = PrefsUtil.getCustomTab().split(separator: ",")
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        var tabs : [UIViewController] = []
+        firstTab = storyboard?.instantiateViewController(withIdentifier: "firstTabVC") as? FirstTabViewController
+        secondTab = storyboard?.instantiateViewController(withIdentifier: "secondTabVC") as? SecondTabViewController
+        thirdTab = storyboard?.instantiateViewController(withIdentifier: "thirdTabVC") as? ThirdTabViewController
+        fourthTab = storyboard?.instantiateViewController(withIdentifier: "fourthTabVC") as? FourthTabViewController
+        
+        self.delegate = self
+        
+        
+        firstTab?.tabBarItem.image = resizeImage(image: UIImage(named: "tab_1_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal)
+        firstTab?.tabBarItem.imageInsets = UIEdgeInsets.init(top: 5,left: 0,bottom: -5,right: 0)
+        secondTab?.tabBarItem.image = resizeImage(image: UIImage(named: "tab_2_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal)
+        secondTab?.tabBarItem.imageInsets = UIEdgeInsets.init(top: 5,left: 0,bottom: -5,right: 0)
+        thirdTab?.tabBarItem.image = resizeImage(image: UIImage(named: "tab_3_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal)
+        thirdTab?.tabBarItem.imageInsets = UIEdgeInsets.init(top: 5,left: 0,bottom: -5,right: 0)
+        fourthTab?.tabBarItem.image = resizeImage(image: UIImage(named: "tab_4_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal)
+        fourthTab?.tabBarItem.imageInsets = UIEdgeInsets.init(top: 5,left: 0,bottom: -5,right: 0)
+        var i = 0
+        var j = 0
+        while j < customTab.count {
+            if(((i == 1 && customTab.count == 3) || i == 2) &&
+               (cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)){
+                tabs.append(emptyTab)
+            }
+            else {
+                switch(customTab[j]){
+                case "1":
+                    tabs.append(firstTab!)
+                case "2":
+                    tabs.append(secondTab!)
+                case "3":
+                    tabs.append(thirdTab!)
+                case "4":
+                    tabs.append(fourthTab!)
+                default:
+                    break
+                }
+                j += 1
+            }
+            i += 1
+        }
+        if(cpaasMode == PrefsUtil.CPAAS_MODE_BURGER){
+            navigationController?.setNavigationBarHidden(false, animated: false)
+            print("cpaas mode burger")
+            let childrenMenu : [UIAction] = [
+                UIAction(title: "Contact Center", handler: {[weak self](_) in
+                    self?.ccTap()
+                }),
+                UIAction(title: "Chat", handler: {[weak self](_) in
+                    self?.chatTap()
+                }),
+                UIAction(title: "Call", handler: {[weak self](_) in
+                    self?.callTap()
+                }),
+//                UIAction(title: "New Post", handler: {[weak self](_) in
+//
+//                }),
+                UIAction(title: "Live Streaming", handler: {[weak self](_) in
+                    self?.streamTap()
+                }),
+//                UIAction(title: "Settings", handler: {[weak self](_) in
+//                    self?.settingTap()
+//                }),
+            ]
+            let menu = UIMenu(title: "", children: childrenMenu)
+            navigationItem.rightBarButtonItem = UIBarButtonItem(image: resizeImage(image: UIImage(named: "pb_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), primaryAction: .none, menu: menu)
+        }
+        if((cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)){
+            createMidFloatingButton()
+            navigationController?.setNavigationBarHidden(true, animated: false)
+        }
+        if((cpaasMode == PrefsUtil.CPAAS_MODE_FLOATING || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)) {
+            let rect = CGRect(x: self.view.bounds.width - 100, y: self.view.bounds.height / 2, width: 50, height: 250)
+            floating = FloatingButton()
+            floating?.frame = rect
+            floating?.isShow = true
+            
+            view.addSubview(floating!)
+            navigationController?.setNavigationBarHidden(true, animated: false)
+        }
+        
+        
+        
+        self.setViewControllers(tabs, animated: false)
+        if(cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX){
+            if(customTab.count == 3){
+                self.tabBar.items?[1].isEnabled = false
+            }
+            self.tabBar.items?[2].isEnabled = false
+        }
+        let numberOfItems = CGFloat(tabBar.items!.count)
+        let tabBarItemSize = CGSize(width: tabBar.frame.width / numberOfItems, height: tabBar.frame.height)
+        tabBar.selectionIndicatorImage = UIImage.imageWithColor(color: UIColor.white, size: tabBarItemSize).resizableImage(withCapInsets: .zero)
+        UIFont.overrideInitialize()
+    }
+    
+    public static func checkIsChangePerson() -> Bool {
+        let isChangeProfile = UserDefaults.standard.bool(forKey: "is_change_profile")
+        if !isChangeProfile {
+            let alert = UIAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized().localized(), preferredStyle: .alert)
+            alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .destructive, handler: {_ in
+                ViewController.def?.thirdTab?.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}")
+                
+                 
+            }))
+            alert.addAction(UIAlertAction(title: "Ok".localized(), style: UIAlertAction.Style.default, handler: {(_) in
+                ViewController.resetTabSelected()
+                let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "changeNS") as! ChangeNamePassswordViewController
+                let navigationController = UINavigationController(rootViewController: controller)
+                navigationController.modalPresentationStyle = .fullScreen
+                navigationController.navigationBar.tintColor = .white
+                navigationController.navigationBar.barTintColor = .mainColor
+                navigationController.navigationBar.isTranslucent = false
+                let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+                navigationController.navigationBar.titleTextAttributes = textAttributes
+                navigationController.view.backgroundColor = .mainColor
+                ViewController.def?.show(b: false)
+                UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.dismiss(animated: true, completion: nil)
+                UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(navigationController, animated: true, completion: nil)
+                }))
+            UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(alert, animated: true, completion: nil)
+            return false
+        }
+        return true
+    }
+    public static func resetTabSelected(){
+        ViewController.isTab1 = true
+        ViewController.isTab2 = false
+        ViewController.isTab3 = false
+        ViewController.isTab4 = false
+//        if ViewController.isTab1 {
+//            ViewController.imageTab1.image = UIImage(named: "tab_1_nexilis")!
+//        }
+//        else {
+//            ViewController.imageTab1.image = UIImage(named: "tab_1_nexilis_off")!
+//        }
+//        if ViewController.isTab2 {
+//            ViewController.imageTab2.image = UIImage(named: "tab_2_nexilis")!
+//        }
+//        else {
+//            ViewController.imageTab2.image = UIImage(named: "tab_2_nexilis_off")!
+//        }
+//        if ViewController.isTab3 {
+//            ViewController.imageTab3.image = UIImage(named: "tab_3_nexilis")!
+//        }
+//        else {
+//            ViewController.imageTab3.image = UIImage(named: "tab_3_nexilis_off")!
+//        }
+//        if ViewController.isTab4 {
+//            ViewController.imageTab4.image = UIImage(named: "tab_4_nexilis")!
+//        }
+//        else {
+//            ViewController.imageTab4.image = UIImage(named: "tab_4_nexilis_off")!
+//        }
+    }
+    
+    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        let customTab = PrefsUtil.getCustomTab().split(separator: ",")
+        if(cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX){
+            if(customTab.count == 2){
+                ViewController.isTab1 = item == tabBar.items?[0]
+                ViewController.isTab2 = item == tabBar.items?[2]
+            }
+            else if(customTab.count == 3){
+                ViewController.isTab1 = item == tabBar.items?[0]
+                ViewController.isTab2 = item == tabBar.items?[2]
+                ViewController.isTab3 = item == tabBar.items?[3]
+            }
+            else if(customTab.count == 4){
+                ViewController.isTab1 = item == tabBar.items?[0]
+                ViewController.isTab2 = item == tabBar.items?[1]
+                ViewController.isTab3 = item == tabBar.items?[3]
+                ViewController.isTab4 = item == tabBar.items?[4]
+            }
+        }
+        else{
+            ViewController.isTab1 = item == tabBar.items?[0]
+            ViewController.isTab2 = item == tabBar.items?[1]
+            if(customTab.count > 2){
+                ViewController.isTab3 = item == tabBar.items?[2]
+            }
+            if(customTab.count > 3){
+                ViewController.isTab4 = item == tabBar.items?[3]
+            }
+        }
+    }
+    
+    func createMidFloatingButton(){
+        ViewController.chatButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 30 , y: self.view.bounds.height - 80, width: 45, height: 45))
+        ViewController.chatButton.setBackgroundImage(UIImage(named: "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
+        ViewController.chatButton.layer.shadowColor = UIColor.black.cgColor
+        ViewController.chatButton.layer.shadowOpacity = 0.1
+        ViewController.chatButton.layer.shadowOffset = CGSize(width: 4, height: 4)
+        ViewController.chatButton.addTarget(self, action: #selector(chatTap), for: .touchUpInside)
+
+        ViewController.callButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 30 , y: self.view.bounds.height - 80, width: 45, height: 45))
+        ViewController.callButton.setBackgroundImage(UIImage(named: "pb_button_call", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
+        ViewController.callButton.layer.shadowColor = UIColor.black.cgColor
+        ViewController.callButton.layer.shadowOpacity = 0.1
+        ViewController.callButton.layer.shadowOffset = CGSize(width: 4, height: 4)
+        ViewController.callButton.addTarget(self, action: #selector(callTap), for: .touchUpInside)
+
+        ViewController.ccButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 30 , y: self.view.bounds.height - 80, width: 45, height: 45))
+        ViewController.ccButton.setBackgroundImage(UIImage(named: "pb_button_cc", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
+        ViewController.ccButton.layer.shadowColor = UIColor.black.cgColor
+        ViewController.ccButton.layer.shadowOpacity = 0.1
+        ViewController.ccButton.layer.shadowOffset = CGSize(width: 4, height: 4)
+        ViewController.ccButton.addTarget(self, action: #selector(ccTap), for: .touchUpInside)
+
+        ViewController.streamingButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 30 , y: self.view.bounds.height - 80, width: 45, height: 45))
+        ViewController.streamingButton.setBackgroundImage(UIImage(named: "pb_button_stream", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
+        ViewController.streamingButton.layer.shadowColor = UIColor.black.cgColor
+        ViewController.streamingButton.layer.shadowOpacity = 0.1
+        ViewController.streamingButton.layer.shadowOffset = CGSize(width: 4, height: 4)
+        ViewController.streamingButton.addTarget(self, action: #selector(streamTap), for: .touchUpInside)
+
+        ViewController.postButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 30 , y: self.view.bounds.height - 80, width: 45, height: 45))
+        ViewController.postButton.setBackgroundImage(UIImage(named: "pb_button_stream", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
+        ViewController.postButton.layer.shadowColor = UIColor.black.cgColor
+        ViewController.postButton.layer.shadowOpacity = 0.1
+        ViewController.postButton.layer.shadowOffset = CGSize(width: 4, height: 4)
+        ViewController.postButton.addTarget(self, action: #selector(streamTap), for: .touchUpInside)
+        let buttonCenterX = self.view.bounds.width / 2
+        let buttonCenterY = self.view.bounds.height - self.tabBar.bounds.height
+        print("buttonCenterX \(buttonCenterX)")
+        print("buttonCenterY \(buttonCenterY)")
+        ViewController.middleButton = UIButton(frame: CGRect(x: buttonCenterX - 40 , y: buttonCenterY - 40, width: 80, height: 80))
+        ViewController.middleButton.setBackgroundImage(UIImage(named: "pb_icon")!.withRenderingMode(.alwaysOriginal), for: .normal)
+        ViewController.middleButton.layer.shadowColor = UIColor.black.cgColor
+        ViewController.middleButton.layer.shadowOffset = CGSize(width: 0.0, height: 2.0)
+        ViewController.middleButton.layer.shadowOpacity = 1.0
+        ViewController.middleButton.layer.shadowRadius = 5.0
+        ViewController.middleButton.layer.masksToBounds = false
+        ViewController.middleButton.layer.cornerRadius = 4.0
+        ViewController.middleButton.addTarget(self, action: #selector(middleBtnTapped), for: .touchUpInside)
+        self.view.addSubview(ViewController.chatButton)
+        self.view.addSubview(ViewController.callButton)
+        self.view.addSubview(ViewController.ccButton)
+        self.view.addSubview(ViewController.streamingButton)
+        self.view.addSubview(ViewController.postButton)
+        self.view.addSubview(ViewController.middleButton)
+        
+        ViewController.hideDockedButton()
+    }
+    
+    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
+        if(viewController == secondTab){
+            if(!ViewController.checkIsChangePerson()){
+                return false
+            }
+        }
+        return true
+    }
+    
+    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
+        print("select tabbar")
+        let cpaasMode = PrefsUtil.getCpaasMode()
+        var childrenMenu = [UIAction]()
+        if(cpaasMode == PrefsUtil.CPAAS_MODE_BURGER){
+            print("cpaas mode burger")
+            childrenMenu.append(contentsOf: [
+                UIAction(title: "Contact Center", handler: {[weak self](_) in
+                    self?.ccTap()
+                }),
+                UIAction(title: "Chat", handler: {[weak self](_) in
+                    self?.chatTap()
+                }),
+                UIAction(title: "Call", handler: {[weak self](_) in
+                    self?.callTap()
+                }),
+                UIAction(title: "New Post", handler: {[weak self](_) in
+
+                }),
+                UIAction(title: "Live Streaming", handler: {[weak self](_) in
+                    self?.streamTap()
+                }),
+//                UIAction(title: "Settings", handler: {[weak self](_) in
+//                    self?.settingTap()
+//                }),
+            ])
+            if let vc = viewController as? SecondTabViewController {
+                childrenMenu.append(contentsOf: vc.childrenMenu)
+            }
+            let menu = UIMenu(title: "", children: childrenMenu)
+            navigationItem.rightBarButtonItem = UIBarButtonItem(image: resizeImage(image: UIImage(named: "pb_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), primaryAction: .none, menu: menu)
+        }
+    }
+    
+    override func viewDidAppear(_ animated: Bool) {
+        
+    }
+    
+    @objc func middleBtnTapped() {
+        ViewController.expandButton()
+    }
+
+
+
+    public func show(b: Bool) {
+        if(!b){
+            if(ViewController.isExpandButton){
+                ViewController.expandButton()
+            }
+        }
+    }
+    
+    @objc func qmeraLongPress() {
+        let navigationController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "settingNav") as! UINavigationController
+        navigationController.modalPresentationStyle = .fullScreen
+        navigationController.navigationBar.tintColor = .white
+        navigationController.navigationBar.barTintColor = .mainColor
+        navigationController.navigationBar.isTranslucent = false
+        let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+        navigationController.navigationBar.titleTextAttributes = textAttributes
+        navigationController.view.backgroundColor = .mainColor
+        UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(navigationController, animated: true, completion: nil)
+    }
+    
+    @objc func ccTap() {
+        print("ccTap")
+        if(ViewController.checkIsChangePerson()){
+            var isOfficer = false
+            Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                let idMe = UserDefaults.standard.string(forKey: "me") as String?
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type, image_id FROM BUDDY where f_pin='\(idMe!)'"), cursorData.next() {
+                    if cursorData.string(forColumnIndex: 0) == "24" {
+                        isOfficer = true
+                    }
+                    cursorData.close()
+                    return
+                }
+            })
+            show(b: false)
+            if isOfficer {
+                let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "myHistoryCC") as! HistoryCCViewController
+                controller.isOfficer = true
+                let navigationController = UINavigationController(rootViewController: controller)
+                navigationController.navigationBar.tintColor = .white
+                navigationController.modalPresentationStyle = .fullScreen
+                navigationController.navigationBar.barTintColor = .mainColor
+                navigationController.navigationBar.isTranslucent = false
+                let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+                navigationController.navigationBar.titleTextAttributes = textAttributes
+                navigationController.view.backgroundColor = .mainColor
+                UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.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.modalPresentationStyle = .fullScreen
+                UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(navigationController, animated: true, completion: nil)
+            }
+        }
+        
+    }
+    
+    @objc func streamTap() {
+        print("streamTap")
+        if(ViewController.checkIsChangePerson()){
+            show(b: false)
+            let navigationController = UINavigationController(rootViewController: QmeraCreateStreamingViewController())
+            navigationController.modalPresentationStyle = .fullScreen
+            navigationController.navigationBar.tintColor = .white
+            navigationController.navigationBar.barTintColor = .mainColor
+            navigationController.navigationBar.isTranslucent = false
+            let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+            navigationController.navigationBar.titleTextAttributes = textAttributes
+            navigationController.view.backgroundColor = .mainColor
+            UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(navigationController, animated: true, completion: nil)
+        }
+    }
+    
+    @objc func callTap() {
+        print("callTap")
+        if(ViewController.checkIsChangePerson()){
+            show(b: false)
+            let callContact = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactSID")
+            let navigationController = UINavigationController(rootViewController: callContact)
+            navigationController.modalPresentationStyle = .fullScreen
+            navigationController.navigationBar.tintColor = .white
+            navigationController.navigationBar.barTintColor = .mainColor
+            navigationController.navigationBar.isTranslucent = false
+            let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+            navigationController.navigationBar.titleTextAttributes = textAttributes
+            navigationController.view.backgroundColor = .mainColor
+            UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(navigationController, animated: true, completion: nil)
+        }
+    }
+    
+    @objc func chatTap() {
+        print("chatTap")
+        if(ViewController.checkIsChangePerson()){
+            show(b: false)
+            let navigationController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactChatNav") as! UINavigationController
+            navigationController.modalPresentationStyle = .fullScreen
+            navigationController.navigationBar.tintColor = .white
+            navigationController.navigationBar.barTintColor = .mainColor
+            navigationController.navigationBar.isTranslucent = false
+            let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+            navigationController.navigationBar.titleTextAttributes = textAttributes
+            navigationController.view.backgroundColor = .mainColor
+            UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(navigationController, animated: true, completion: nil)
+        }
+    }
+    
+    @objc func settingTap() {
+        let navigationController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "settingNav") as! UINavigationController
+        navigationController.modalPresentationStyle = .fullScreen
+        navigationController.navigationBar.tintColor = .white
+        navigationController.navigationBar.barTintColor = .mainColor
+        navigationController.navigationBar.isTranslucent = false
+        let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+        navigationController.navigationBar.titleTextAttributes = textAttributes
+        navigationController.view.backgroundColor = .mainColor
+        UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.present(navigationController, animated: true, completion: nil)
+    }
+    
+    public static func showDockedButton() {
+        ViewController.chatButton.isHidden = false
+        ViewController.callButton.isHidden = false
+        ViewController.ccButton.isHidden = false
+        ViewController.streamingButton.isHidden = false
+        ViewController.postButton.isHidden = false
+    }
+    
+    public static func hideDockedButton() {
+        ViewController.chatButton.isHidden = true
+        ViewController.callButton.isHidden = true
+        ViewController.ccButton.isHidden = true
+        ViewController.streamingButton.isHidden = true
+        ViewController.postButton.isHidden = true
+    }
+    
+    public static func expandButton() {
+        if ViewController.alwaysHideButton && !ViewController.isExpandButton {
+            return
+        }
+        if ViewController.isExpandButton {
+            ViewController.isExpandButton = false
+            let xChatPosition = ViewController.chatButton.frame.origin.x + 80
+            let yChatPosition = ViewController.chatButton.frame.origin.y + 20
+
+            let xCallPosition = ViewController.callButton.frame.origin.x + 50
+            let yCallPosition = ViewController.callButton.frame.origin.y + 70
+
+            let xCCPosition = ViewController.ccButton.frame.origin.x
+            let yCCPosition = ViewController.ccButton.frame.origin.y + 90
+
+            let xStreamingPosition = ViewController.streamingButton.frame.origin.x - 50
+            let yStreamingPosition = ViewController.streamingButton.frame.origin.y + 70
+
+            let xPostPosition = ViewController.postButton.frame.origin.x - 80
+            let yPostPosition = ViewController.postButton.frame.origin.y + 20
+            UIView.animate(withDuration: 0.5, animations: {
+//                if !ViewController.isBlue {
+//                    ViewController.middleButton.transform = CGAffineTransform(rotationAngle: 0)
+//                }
+                ViewController.chatButton.frame.origin = CGPoint(x: xChatPosition, y: yChatPosition)
+                ViewController.callButton.frame.origin = CGPoint(x: xCallPosition, y: yCallPosition)
+                ViewController.ccButton.frame.origin = CGPoint(x: xCCPosition, y: yCCPosition)
+                ViewController.streamingButton.frame.origin = CGPoint(x: xStreamingPosition, y: yStreamingPosition)
+                ViewController.postButton.frame.origin = CGPoint(x: xPostPosition, y: yPostPosition)
+            })
+            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
+                if !ViewController.isExpandButton {
+                    ViewController.hideDockedButton()
+                }
+            })
+        } else {
+            ViewController.isExpandButton = true
+            ViewController.showDockedButton()
+            let xChatPosition = ViewController.chatButton.frame.origin.x - 80
+            let yChatPosition = ViewController.chatButton.frame.origin.y - 20
+
+            let xCallPosition = ViewController.callButton.frame.origin.x - 50
+            let yCallPosition = ViewController.callButton.frame.origin.y - 70
+
+            let xCCPosition = ViewController.ccButton.frame.origin.x
+            let yCCPosition = ViewController.ccButton.frame.origin.y - 90
+
+            let xStreamingPosition = ViewController.streamingButton.frame.origin.x + 50
+            let yStreamingPosition = ViewController.streamingButton.frame.origin.y - 70
+
+            let xPostPosition = ViewController.postButton.frame.origin.x + 80
+            let yPostPosition = ViewController.postButton.frame.origin.y - 20
+            UIView.animate(withDuration: 0.5, animations: {
+//                if !ViewController.isBlue{
+//                    ViewController.middleButton.transform = CGAffineTransform(rotationAngle: .pi / 2)
+//                }
+                ViewController.chatButton.frame.origin = CGPoint(x: xChatPosition, y: yChatPosition)
+                ViewController.callButton.frame.origin = CGPoint(x: xCallPosition, y: yCallPosition)
+                ViewController.ccButton.frame.origin = CGPoint(x: xCCPosition, y: yCCPosition)
+                ViewController.streamingButton.frame.origin = CGPoint(x: xStreamingPosition, y: yStreamingPosition)
+                ViewController.postButton.frame.origin = CGPoint(x: xPostPosition, y: yPostPosition)
+            })
+        }
+    }
+    
+    public static func removeMiddleButton() {
+        ViewController.chatButton.removeFromSuperview()
+        ViewController.callButton.removeFromSuperview()
+        ViewController.ccButton.removeFromSuperview()
+        ViewController.streamingButton.removeFromSuperview()
+        ViewController.postButton.removeFromSuperview()
+        ViewController.middleButton.removeFromSuperview()
+    }
+
+}
+
+class EmptyTabViewController: UIViewController {
+    override func viewDidLoad() {
+        
+    }
+}
+                
+extension Bundle {
+    // Name of the app - title under the icon.
+    var displayName: String? {
+            return object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ??
+                object(forInfoDictionaryKey: "CFBundleName") as? String
+    }
+}
+
+extension BinaryInteger {
+    var degreesToRadians: CGFloat { CGFloat(self) * .pi / 180 }
+}
+
+extension FloatingPoint {
+    var degreesToRadians: Self { self * .pi / 180 }
+    var radiansToDegrees: Self { self * 180 / .pi }
+}
+
+extension UIImage {
+    class func imageWithColor(color: UIColor, size: CGSize) -> UIImage {
+        let rect: CGRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
+        UIGraphicsBeginImageContextWithOptions(size, false, 0)
+        color.setFill()
+        UIRectFill(rect)
+        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
+        UIGraphicsEndImageContext()
+        return image
+    }
+}

BIN
appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-Light.ttf


BIN
appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-LightItalic.ttf


BIN
appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-Medium.ttf


BIN
appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-MediumItalic.ttf


BIN
appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-Regular.ttf


BIN
appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-SemiBold.ttf


BIN
appbuilder-ios/AppBuilder/AppBuilder/fonts/Poppins-SemiBoldItalic.ttf


+ 31 - 0
appbuilder-ios/AppBuilder/Podfile

@@ -0,0 +1,31 @@
+# Uncomment the next line to define a global platform for your project
+# platform :ios, '9.0'
+
+target 'AppBuilder' do
+  # Comment the next line if you don't want to use dynamic frameworks
+  use_frameworks!
+
+#  pod 'QmeraLite', '~> 1.0.2'
+#  pod 'GoogleUtilitiesComponents', '~> 1.1'
+  pod 'NexilisLite', :path => '../NexilisLite'
+
+  # Pods for AppBuilder
+
+  # target 'AppBuilderTests' do
+    #inherit! :search_paths
+    # Pods for testing
+  # end
+
+  #target 'AppBuilderUITests' do
+    # Pods for testing
+  #end
+  
+#  post_install do |installer|
+#    installer.pods_project.targets.each do |target|
+#      target.build_configurations.each do |config|
+#        config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
+#      end
+#    end
+#  end
+
+end

BIN
appbuilder-ios/NexilisLite/.DS_Store