alqindiirsyam 1 éve
szülő
commit
4533278482

+ 91 - 63
appbuilder-ios/DigiXLite/DigiXLite/Source/FloatingButton/FloatingButton.swift

@@ -43,6 +43,11 @@ public class FloatingButton: UIView {
     let heightFBSideTab = (UIScreen.main.bounds.height * 1.05) / 7.5
     let widthFBSideTab: CGFloat = 18
     
+    final let MODE_HORIZONTAL_SIDE_TAB = "1"
+    final let MODE_VERTICAL_ANIMATION = "2"
+    final let MODE_VERTICAL_FLOATING_BUTTON = "3"
+    final let MODE_HORIZONTAL_ANIMATION = "4"
+    
     var countMenuFB: CGFloat = 5 {
         didSet {
             if isShow {
@@ -72,38 +77,38 @@ public class FloatingButton: UIView {
         nexilis_button = UIImageView()
         nexilis_button.translatesAutoresizingMaskIntoConstraints = false
         nexilis_button.isUserInteractionEnabled = true
-        if !Utils.getIconDock().isEmpty && Utils.getConfigModeFB() != "1" {
-            var dataImage: Data?
-            if Utils.getConfigModeFB() == "2" || Utils.getConfigModeFB() == "4" {
-                defaultWidthFB = widthFBAnim
-                defaultHeightFB = heightFBAnim
-                nexilis_button.sd_setImage(with: URL(string: Utils.getIconCenterAnim2()!)) { [self] (image, error, cacheType, imageURL) in
-                    if error != nil {
-                        //print("Error loading GIF: \(error.localizedDescription)")
-                    } else {
-                        // Configure the animation
-                        nexilis_button.animationImages = image?.images
-                        nexilis_button.animationDuration = image?.duration ?? 0.0
-                        nexilis_button.animationRepeatCount = 0
-                        nexilis_button.startAnimating()
-                    }
+        var dataImage: Data?
+        if Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION || Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION {
+            defaultWidthFB = widthFBAnim
+            defaultHeightFB = heightFBAnim
+            nexilis_button.sd_setImage(with: URL(string: Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION ? Utils.getIconCenterAnim2()! :  Utils.getIconCenterAnim4()!)) { [self] (image, error, cacheType, imageURL) in
+                if error != nil {
+                    //print("Error loading GIF: \(error.localizedDescription)")
+                } else {
+                    // Configure the animation
+                    nexilis_button.animationImages = image?.images
+                    nexilis_button.animationDuration = image?.duration ?? 0.0
+                    nexilis_button.animationRepeatCount = 0
+                    nexilis_button.startAnimating()
                 }
-            } else {
+            }
+        } else {
+            if !Utils.getIconDock().isEmpty && Utils.getConfigModeFB() == MODE_VERTICAL_FLOATING_BUTTON {
                 dataImage = try? Data(contentsOf: URL(string: Utils.getUrlDock()!)!)
                 if dataImage != nil {
                     nexilis_button.image = UIImage(data: dataImage!)
                 }
+            } else {
+                if Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB {
+                    defaultWidthFB = widthFBSideTab
+                    defaultHeightFB = heightFBSideTab
+                }
+                nexilis_button.image = UIImage(named: Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB ? "pb_button" : "pb_side_tab", in: Bundle.resourceBundle(for: DigiX.self), with: nil)
             }
-        } else {
-            if Utils.getConfigModeFB() == "1" {
-                defaultWidthFB = widthFBSideTab
-                defaultHeightFB = heightFBSideTab
-            }
-            nexilis_button.image = UIImage(named: Utils.getConfigModeFB() != "1" ? "pb_button" : "pb_side_tab", in: Bundle.resourceBundle(for: DigiX.self), with: nil)
         }
         
         backgroundColor = .clear
-        frame = CGRect(x: UIScreen.main.bounds.width - defaultWidthFB, y: (UIScreen.main.bounds.height / 2) - defaultHeightFB, width: Utils.getConfigModeFB() == "1" ? UIScreen.main.bounds.width - defaultWidthFB : defaultWidthFB, height: defaultHeightFB)
+        frame = CGRect(x: UIScreen.main.bounds.width - defaultWidthFB, y: (UIScreen.main.bounds.height / 2) - defaultHeightFB, width: Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB ? UIScreen.main.bounds.width - defaultWidthFB : defaultWidthFB, height: defaultHeightFB)
         
         let qmeraTap = UITapGestureRecognizer(target: self, action: #selector(qmeraTap))
         qmeraTap.numberOfTouchesRequired = 1
@@ -128,14 +133,19 @@ public class FloatingButton: UIView {
 //        scrollView.backgroundColor = .black.withAlphaComponent(0.25)
         addSubview(scrollView)
         
-        if Utils.getConfigModeFB() != "1" {
-            scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
+        if Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB {
             scrollView.topAnchor.constraint(equalTo: topAnchor).isActive = true
-            if Utils.getConfigModeFB() == "2" {
+            if Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION {
                 scrollView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
                 scrollView.leftAnchor.constraint(equalTo: nexilis_button.rightAnchor, constant: -20).isActive = true
+                scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
                 scrollView.isHidden = true
+            } else if Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION {
+                scrollView.bottomAnchor.constraint(equalTo: nexilis_button.topAnchor).isActive = true
+                scrollView.leftAnchor.constraint(equalTo: nexilis_button.leftAnchor).isActive = true
+                scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB * (countMenuFB - 1)).isActive = true
             } else {
+                scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
                 scrollView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
                 scrollView.bottomAnchor.constraint(equalTo: nexilis_button.topAnchor).isActive = true
             }
@@ -149,23 +159,23 @@ public class FloatingButton: UIView {
         
         groupView = UIStackView()
         groupView.translatesAutoresizingMaskIntoConstraints = false
-        groupView.axis = Utils.getConfigModeFB() != "1" ? .vertical : .horizontal
-        if Utils.getConfigModeFB() != "1" {
+        groupView.axis = (Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB || Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION) ? .horizontal : .vertical
+        if Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB && Utils.getConfigModeFB() != MODE_HORIZONTAL_ANIMATION {
             groupView.distribution = .fillEqually
         }
 
         scrollView.addSubview(groupView)
 
-        if Utils.getConfigModeFB() != "1" {
-            groupView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
-            groupView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 5).isActive = true
-            groupView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -5).isActive = true
-            groupView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 6).isActive = true
-        } else {
+        if Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB {
             groupView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
             groupView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
             groupView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor).isActive = true
             groupView.heightAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
+        } else {
+            groupView.widthAnchor.constraint(equalToConstant: Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION ? defaultWidthHeightMenuFB * (countMenuFB - 1) : defaultWidthHeightMenuFB).isActive = true
+            groupView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION ? 0 : 5).isActive = true
+            groupView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION ? 0 : -5).isActive = true
+            groupView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION ? 0 : 6).isActive = true
         }
         
         pullButton()
@@ -193,7 +203,7 @@ public class FloatingButton: UIView {
             return
         }
         DispatchQueue.global().async { [self] in
-            if !Utils.getCustomButtons().isEmpty && Utils.getConfigModeFB() != "1" && Utils.getConfigModeFB() != "4" {
+            if !Utils.getCustomButtons().isEmpty && Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB && Utils.getConfigModeFB() != MODE_HORIZONTAL_ANIMATION {
                 DispatchQueue.main.async { [self] in
                     groupView.subviews.forEach({ $0.removeFromSuperview() })
                     let customButtons = Utils.getCustomButtons().components(separatedBy: ",")
@@ -237,46 +247,53 @@ public class FloatingButton: UIView {
                                     countMenuFB = CGFloat(4)
                                     getDefaultButton()
                                 } else {
-                                    countMenuFB = CGFloat(jsonArray.count > 5 ? 5 : jsonArray.count)
+                                    if Utils.getConfigModeFB() != MODE_HORIZONTAL_ANIMATION {
+                                        countMenuFB = CGFloat(jsonArray.count > 5 ? 5 : jsonArray.count)
+                                    } else {
+                                        countMenuFB = CGFloat(jsonArray.filter({ $0["mode"] as? Int == Int(MODE_HORIZONTAL_ANIMATION) }).count)
+                                    }
                                     for json in jsonArray {
                                         let package_id = json["package_id"] as! String
                                         let app_id = (json["app_id"] as? String) ?? ""
                                         let icon = (json["icon"] as? String) ?? ""
-                                        let mode = (json["mode"] as? Int) ?? 1
+                                        let mode = "\((json["mode"] as? Int) ?? 1)"
                                         let newButton = UIButton()
-                                        if mode != Int(Utils.getConfigModeFB()) {
+                                        if mode != Utils.getConfigModeFB() {
                                             continue
                                         }
-                                        if mode == 1 {
+                                        if mode == MODE_HORIZONTAL_SIDE_TAB {
                                             newButton.widthAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
                                             newButton.heightAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
+                                        } else if mode == MODE_HORIZONTAL_ANIMATION {
+                                            newButton.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
+                                            newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
                                         } else {
                                             newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
                                         }
                                         newButton.translatesAutoresizingMaskIntoConstraints = false
                                         var indexTap = 0
                                         if package_id.contains("_fb"){
-                                            indexTap = Int(String(package_id.split(separator: "_")[1]).substring(from: 2, to: 2))!
+                                            let numIdx = package_id.split(separator: "_")[1]
+                                            indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
                                         }
                                         if indexTap == DigiX.IDX_CHAT {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_chat" : "pb_button_chat", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_chat" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_chat" : "pb_button_chat", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         } else if indexTap == DigiX.IDX_CALL {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_call" : "pb_button_call", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_call" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_call" : "pb_button_call", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         } else if indexTap == DigiX.IDX_CC {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_cc" : "pb_button_cc", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_cc" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_cc" : "pb_button_cc", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         } else if indexTap == DigiX.IDX_STREAM {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_stream" : "pb_button_stream", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_stream" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_stream" : "pb_button_stream", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         } else if indexTap == DigiX.IDX_SOCIAL_COMMERCE {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_social_commerce" : "pb_button_commerce", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_social_commerce" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_commerce" : "pb_button_commerce", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         } else if indexTap == DigiX.IDX_NEWS {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_news" : "pb_button_news", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_news" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_news" : "pb_button_news", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         } else if indexTap == DigiX.IDX_POST {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_post" : "pb_button_post", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_post" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_post" : "pb_button_post", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         } else if indexTap == DigiX.IDX_NOTIF_CENTER {
-                                            print("MASUK SINI \(indexTap) <> \(mode == 1)")
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_notif_center" : "pb_button_notification", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_notif_center" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_notif_center" : "pb_button_notification", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         } else {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_more" : "pb_button_others", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_more" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_more" : "pb_button_others", in: Bundle.resourceBundle(for: DigiX.self), with: nil), for: .normal)
                                         }
                                         if !icon.isEmpty {
                                             DispatchQueue.global().async {
@@ -347,26 +364,26 @@ public class FloatingButton: UIView {
         let size = UIScreen.main.bounds
         let widthScreen = size.width
         let heightScreen = size.height
-        let minimumx: CGFloat = Utils.getConfigModeFB() == "2" && isShow ? 60 : 40
-        let maximumx = Utils.getConfigModeFB() == "2" && isShow ? widthScreen - 10 - defaultWidthHeightMenuFB : widthScreen - 40
+        let minimumx: CGFloat = Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION && isShow ? 80 : Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION && isShow ? 60 : 40
+        let maximumx = Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION && isShow ? widthScreen - frame.width + 20 : Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION && isShow ? widthScreen - 10 - defaultWidthHeightMenuFB : widthScreen - 40
         let maxMinXSideTab = isShow ? center.x : widthScreen + (center.x - widthScreen)
         let translation = sender.translation(in: self)
         var xPos = center.x + translation.x
         var yPos = center.y + translation.y
         bringSubviewToFront(self)
-        if Utils.getConfigModeFB() != "1" {
+        if Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB {
+            xPos = maxMinXSideTab
+        } else {
             if (xPos < minimumx) {
                 xPos = minimumx
             }
             if (xPos > maximumx) {
                 xPos = maximumx
             }
-        } else {
-            xPos = maxMinXSideTab
         }
         if(isShow) {
-            let minimumy = Utils.getConfigModeFB() == "1" ? 50 : (defaultWidthHeightMenuFB * countMenuFB) - defaultHeightFB - 10
-            let maximumy = Utils.getConfigModeFB() == "1" ? heightScreen - 50 : heightScreen - defaultHeightFB - 10
+            let minimumy = Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB ? 50 : (defaultWidthHeightMenuFB * countMenuFB) - defaultHeightFB - 10
+            let maximumy = Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB ? heightScreen - 50 : heightScreen - defaultHeightFB - 10
             if(yPos < minimumy) {
                 yPos = minimumy
             }
@@ -451,7 +468,8 @@ public class FloatingButton: UIView {
         var app_id = sender.accessibilityIdentifier!
         var indexTap = 0
         if package_id.contains("_fb"){
-            indexTap = Int(String(package_id.split(separator: "_")[1]).substring(from: 2, to: 2))!
+            let numIdx = package_id.split(separator: "_")[1]
+            indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
         }
         if indexTap == 2 {
             app_id = package_id.components(separatedBy: "_")[2]
@@ -524,20 +542,26 @@ public class FloatingButton: UIView {
             var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
             var width = frame.width
             var xPosition = frame.origin.x
-            if Utils.getConfigModeFB() == "2" {
+            if Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION {
                 height = CGFloat((defaultWidthHeightMenuFB * (countMenuFB - 2)) + defaultHeightFB - 5)
                 width = frame.width + defaultWidthHeightMenuFB
                 if xPosition > UIScreen.main.bounds.width - defaultWidthFB - defaultWidthHeightMenuFB {
                     xPosition = UIScreen.main.bounds.width - defaultWidthFB - defaultWidthHeightMenuFB
                 }
                 scrollView.isHidden = false
+            } else if Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION {
+                height = defaultHeightFB + defaultWidthHeightMenuFB
+                width = defaultWidthHeightMenuFB * (countMenuFB - 1)
+                if xPosition > UIScreen.main.bounds.width - defaultWidthHeightMenuFB * (countMenuFB) {
+                    xPosition = UIScreen.main.bounds.width - defaultWidthHeightMenuFB * (countMenuFB)
+                }
             }
             var yPosition = frame.origin.y - height + defaultHeightFB
             if yPosition <= 25 {
                 lastPosY = frame.origin.y
                 yPosition = 25
             }
-            if Utils.getConfigModeFB() != "1" {
+            if Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB {
                 frame = CGRect(x: xPosition, y: yPosition, width: width, height: height)
             } else {
                 UIView.animate(withDuration: 0.5, animations: {
@@ -557,16 +581,20 @@ public class FloatingButton: UIView {
                 indicatorCounterFBBig.isHidden = false
             }
             var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
-            if Utils.getConfigModeFB() == "2" {
+            var width = defaultWidthFB
+            if Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION {
                 height = CGFloat((defaultWidthHeightMenuFB * 3) + defaultHeightFB - 5)
                 scrollView.isHidden = true
+            } else if Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION {
+                height = defaultHeightFB + defaultWidthHeightMenuFB
+                width = defaultWidthFB
             }
             var yPosition = frame.origin.y + height - defaultHeightFB
             if lastPosY != nil {
                 yPosition = lastPosY!
             }
-            if Utils.getConfigModeFB() != "1" {
-                frame = CGRect(x: frame.origin.x, y: yPosition, width: defaultWidthFB, height: defaultHeightFB)
+            if Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB {
+                frame = CGRect(x: frame.origin.x, y: yPosition, width: width, height: defaultHeightFB)
             } else {
                 UIView.animate(withDuration: 0.5, animations: { [self] in
                     frame.origin.x = UIScreen.main.bounds.width - defaultWidthFB

+ 91 - 63
appbuilder-ios/NexilisLite/NexilisLite/Source/FloatingButton/FloatingButton.swift

@@ -43,6 +43,11 @@ public class FloatingButton: UIView {
     let heightFBSideTab = (UIScreen.main.bounds.height * 1.05) / 7.5
     let widthFBSideTab: CGFloat = 18
     
+    final let MODE_HORIZONTAL_SIDE_TAB = "1"
+    final let MODE_VERTICAL_ANIMATION = "2"
+    final let MODE_VERTICAL_FLOATING_BUTTON = "3"
+    final let MODE_HORIZONTAL_ANIMATION = "4"
+    
     var countMenuFB: CGFloat = 5 {
         didSet {
             if isShow {
@@ -72,38 +77,38 @@ public class FloatingButton: UIView {
         nexilis_button = UIImageView()
         nexilis_button.translatesAutoresizingMaskIntoConstraints = false
         nexilis_button.isUserInteractionEnabled = true
-        if !Utils.getIconDock().isEmpty && Utils.getConfigModeFB() != "1" {
-            var dataImage: Data?
-            if Utils.getConfigModeFB() == "2" || Utils.getConfigModeFB() == "4" {
-                defaultWidthFB = widthFBAnim
-                defaultHeightFB = heightFBAnim
-                nexilis_button.sd_setImage(with: URL(string: Utils.getIconCenterAnim2()!)) { [self] (image, error, cacheType, imageURL) in
-                    if error != nil {
-                        //print("Error loading GIF: \(error.localizedDescription)")
-                    } else {
-                        // Configure the animation
-                        nexilis_button.animationImages = image?.images
-                        nexilis_button.animationDuration = image?.duration ?? 0.0
-                        nexilis_button.animationRepeatCount = 0
-                        nexilis_button.startAnimating()
-                    }
+        var dataImage: Data?
+        if Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION || Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION {
+            defaultWidthFB = widthFBAnim
+            defaultHeightFB = heightFBAnim
+            nexilis_button.sd_setImage(with: URL(string: Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION ? Utils.getIconCenterAnim2()! :  Utils.getIconCenterAnim4()!)) { [self] (image, error, cacheType, imageURL) in
+                if error != nil {
+                    //print("Error loading GIF: \(error.localizedDescription)")
+                } else {
+                    // Configure the animation
+                    nexilis_button.animationImages = image?.images
+                    nexilis_button.animationDuration = image?.duration ?? 0.0
+                    nexilis_button.animationRepeatCount = 0
+                    nexilis_button.startAnimating()
                 }
-            } else {
+            }
+        } else {
+            if !Utils.getIconDock().isEmpty && Utils.getConfigModeFB() == MODE_VERTICAL_FLOATING_BUTTON {
                 dataImage = try? Data(contentsOf: URL(string: Utils.getUrlDock()!)!)
                 if dataImage != nil {
                     nexilis_button.image = UIImage(data: dataImage!)
                 }
+            } else {
+                if Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB {
+                    defaultWidthFB = widthFBSideTab
+                    defaultHeightFB = heightFBSideTab
+                }
+                nexilis_button.image = UIImage(named: Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB ? "pb_button" : "pb_side_tab", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
             }
-        } else {
-            if Utils.getConfigModeFB() == "1" {
-                defaultWidthFB = widthFBSideTab
-                defaultHeightFB = heightFBSideTab
-            }
-            nexilis_button.image = UIImage(named: Utils.getConfigModeFB() != "1" ? "pb_button" : "pb_side_tab", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
         }
         
         backgroundColor = .clear
-        frame = CGRect(x: UIScreen.main.bounds.width - defaultWidthFB, y: (UIScreen.main.bounds.height / 2) - defaultHeightFB, width: Utils.getConfigModeFB() == "1" ? UIScreen.main.bounds.width - defaultWidthFB : defaultWidthFB, height: defaultHeightFB)
+        frame = CGRect(x: UIScreen.main.bounds.width - defaultWidthFB, y: (UIScreen.main.bounds.height / 2) - defaultHeightFB, width: Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB ? UIScreen.main.bounds.width - defaultWidthFB : defaultWidthFB, height: defaultHeightFB)
         
         let qmeraTap = UITapGestureRecognizer(target: self, action: #selector(qmeraTap))
         qmeraTap.numberOfTouchesRequired = 1
@@ -128,14 +133,19 @@ public class FloatingButton: UIView {
 //        scrollView.backgroundColor = .black.withAlphaComponent(0.25)
         addSubview(scrollView)
         
-        if Utils.getConfigModeFB() != "1" {
-            scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
+        if Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB {
             scrollView.topAnchor.constraint(equalTo: topAnchor).isActive = true
-            if Utils.getConfigModeFB() == "2" {
+            if Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION {
                 scrollView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
                 scrollView.leftAnchor.constraint(equalTo: nexilis_button.rightAnchor, constant: -20).isActive = true
+                scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
                 scrollView.isHidden = true
+            } else if Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION {
+                scrollView.bottomAnchor.constraint(equalTo: nexilis_button.topAnchor).isActive = true
+                scrollView.leftAnchor.constraint(equalTo: nexilis_button.leftAnchor).isActive = true
+                scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB * (countMenuFB - 1)).isActive = true
             } else {
+                scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
                 scrollView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
                 scrollView.bottomAnchor.constraint(equalTo: nexilis_button.topAnchor).isActive = true
             }
@@ -149,23 +159,23 @@ public class FloatingButton: UIView {
         
         groupView = UIStackView()
         groupView.translatesAutoresizingMaskIntoConstraints = false
-        groupView.axis = Utils.getConfigModeFB() != "1" ? .vertical : .horizontal
-        if Utils.getConfigModeFB() != "1" {
+        groupView.axis = (Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB || Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION) ? .horizontal : .vertical
+        if Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB && Utils.getConfigModeFB() != MODE_HORIZONTAL_ANIMATION {
             groupView.distribution = .fillEqually
         }
 
         scrollView.addSubview(groupView)
 
-        if Utils.getConfigModeFB() != "1" {
-            groupView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
-            groupView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 5).isActive = true
-            groupView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -5).isActive = true
-            groupView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 6).isActive = true
-        } else {
+        if Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB {
             groupView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
             groupView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
             groupView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor).isActive = true
             groupView.heightAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
+        } else {
+            groupView.widthAnchor.constraint(equalToConstant: Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION ? defaultWidthHeightMenuFB * (countMenuFB - 1) : defaultWidthHeightMenuFB).isActive = true
+            groupView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION ? 0 : 5).isActive = true
+            groupView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION ? 0 : -5).isActive = true
+            groupView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION ? 0 : 6).isActive = true
         }
         
         pullButton()
@@ -193,7 +203,7 @@ public class FloatingButton: UIView {
             return
         }
         DispatchQueue.global().async { [self] in
-            if !Utils.getCustomButtons().isEmpty && Utils.getConfigModeFB() != "1" && Utils.getConfigModeFB() != "4" {
+            if !Utils.getCustomButtons().isEmpty && Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB && Utils.getConfigModeFB() != MODE_HORIZONTAL_ANIMATION {
                 DispatchQueue.main.async { [self] in
                     groupView.subviews.forEach({ $0.removeFromSuperview() })
                     let customButtons = Utils.getCustomButtons().components(separatedBy: ",")
@@ -237,46 +247,53 @@ public class FloatingButton: UIView {
                                     countMenuFB = CGFloat(4)
                                     getDefaultButton()
                                 } else {
-                                    countMenuFB = CGFloat(jsonArray.count > 5 ? 5 : jsonArray.count)
+                                    if Utils.getConfigModeFB() != MODE_HORIZONTAL_ANIMATION {
+                                        countMenuFB = CGFloat(jsonArray.count > 5 ? 5 : jsonArray.count)
+                                    } else {
+                                        countMenuFB = CGFloat(jsonArray.filter({ $0["mode"] as? Int == Int(MODE_HORIZONTAL_ANIMATION) }).count)
+                                    }
                                     for json in jsonArray {
                                         let package_id = json["package_id"] as! String
                                         let app_id = (json["app_id"] as? String) ?? ""
                                         let icon = (json["icon"] as? String) ?? ""
-                                        let mode = (json["mode"] as? Int) ?? 1
+                                        let mode = "\((json["mode"] as? Int) ?? 1)" 
                                         let newButton = UIButton()
-                                        if mode != Int(Utils.getConfigModeFB()) {
+                                        if mode != Utils.getConfigModeFB() {
                                             continue
                                         }
-                                        if mode == 1 {
+                                        if mode == MODE_HORIZONTAL_SIDE_TAB {
                                             newButton.widthAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
                                             newButton.heightAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
+                                        } else if mode == MODE_HORIZONTAL_ANIMATION {
+                                            newButton.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
+                                            newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
                                         } else {
                                             newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
                                         }
                                         newButton.translatesAutoresizingMaskIntoConstraints = false
                                         var indexTap = 0
                                         if package_id.contains("_fb"){
-                                            indexTap = Int(String(package_id.split(separator: "_")[1]).substring(from: 2, to: 2))!
+                                            let numIdx = package_id.split(separator: "_")[1]
+                                            indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
                                         }
                                         if indexTap == Nexilis.IDX_CHAT {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_chat" : "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_chat" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_chat" : "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         } else if indexTap == Nexilis.IDX_CALL {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_call" : "pb_button_call", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_call" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_call" : "pb_button_call", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         } else if indexTap == Nexilis.IDX_CC {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_cc" : "pb_button_cc", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_cc" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_cc" : "pb_button_cc", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         } else if indexTap == Nexilis.IDX_STREAM {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_stream" : "pb_button_stream", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_stream" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_stream" : "pb_button_stream", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         } else if indexTap == Nexilis.IDX_SOCIAL_COMMERCE {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_social_commerce" : "pb_button_commerce", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_social_commerce" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_commerce" : "pb_button_commerce", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         } else if indexTap == Nexilis.IDX_NEWS {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_news" : "pb_button_news", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_news" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_news" : "pb_button_news", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         } else if indexTap == Nexilis.IDX_POST {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_post" : "pb_button_post", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_post" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_post" : "pb_button_post", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         } else if indexTap == Nexilis.IDX_NOTIF_CENTER {
-                                            print("MASUK SINI \(indexTap) <> \(mode == 1)")
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_notif_center" : "pb_button_notification", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_notif_center" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_notif_center" : "pb_button_notification", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         } else {
-                                            newButton.setImage(UIImage(named: mode == 1 ? "pb_button_hrz_more" : "pb_button_others", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
+                                            newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_more" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_more" : "pb_button_others", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
                                         }
                                         if !icon.isEmpty {
                                             DispatchQueue.global().async {
@@ -347,26 +364,26 @@ public class FloatingButton: UIView {
         let size = UIScreen.main.bounds
         let widthScreen = size.width
         let heightScreen = size.height
-        let minimumx: CGFloat = Utils.getConfigModeFB() == "2" && isShow ? 60 : 40
-        let maximumx = Utils.getConfigModeFB() == "2" && isShow ? widthScreen - 10 - defaultWidthHeightMenuFB : widthScreen - 40
+        let minimumx: CGFloat = Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION && isShow ? 80 : Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION && isShow ? 60 : 40
+        let maximumx = Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION && isShow ? widthScreen - frame.width + 20 : Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION && isShow ? widthScreen - 10 - defaultWidthHeightMenuFB : widthScreen - 40
         let maxMinXSideTab = isShow ? center.x : widthScreen + (center.x - widthScreen)
         let translation = sender.translation(in: self)
         var xPos = center.x + translation.x
         var yPos = center.y + translation.y
         bringSubviewToFront(self)
-        if Utils.getConfigModeFB() != "1" {
+        if Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB {
+            xPos = maxMinXSideTab
+        } else {
             if (xPos < minimumx) {
                 xPos = minimumx
             }
             if (xPos > maximumx) {
                 xPos = maximumx
             }
-        } else {
-            xPos = maxMinXSideTab
         }
         if(isShow) {
-            let minimumy = Utils.getConfigModeFB() == "1" ? 50 : (defaultWidthHeightMenuFB * countMenuFB) - defaultHeightFB - 10
-            let maximumy = Utils.getConfigModeFB() == "1" ? heightScreen - 50 : heightScreen - defaultHeightFB - 10
+            let minimumy = Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB ? 50 : (defaultWidthHeightMenuFB * countMenuFB) - defaultHeightFB - 10
+            let maximumy = Utils.getConfigModeFB() == MODE_HORIZONTAL_SIDE_TAB ? heightScreen - 50 : heightScreen - defaultHeightFB - 10
             if(yPos < minimumy) {
                 yPos = minimumy
             }
@@ -451,7 +468,8 @@ public class FloatingButton: UIView {
         var app_id = sender.accessibilityIdentifier!
         var indexTap = 0
         if package_id.contains("_fb"){
-            indexTap = Int(String(package_id.split(separator: "_")[1]).substring(from: 2, to: 2))!
+            let numIdx = package_id.split(separator: "_")[1]
+            indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
         }
         if indexTap == 2 {
             app_id = package_id.components(separatedBy: "_")[2]
@@ -524,20 +542,26 @@ public class FloatingButton: UIView {
             var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
             var width = frame.width
             var xPosition = frame.origin.x
-            if Utils.getConfigModeFB() == "2" {
+            if Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION {
                 height = CGFloat((defaultWidthHeightMenuFB * (countMenuFB - 2)) + defaultHeightFB - 5)
                 width = frame.width + defaultWidthHeightMenuFB
                 if xPosition > UIScreen.main.bounds.width - defaultWidthFB - defaultWidthHeightMenuFB {
                     xPosition = UIScreen.main.bounds.width - defaultWidthFB - defaultWidthHeightMenuFB
                 }
                 scrollView.isHidden = false
+            } else if Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION {
+                height = defaultHeightFB + defaultWidthHeightMenuFB
+                width = defaultWidthHeightMenuFB * (countMenuFB - 1)
+                if xPosition > UIScreen.main.bounds.width - defaultWidthHeightMenuFB * (countMenuFB) {
+                    xPosition = UIScreen.main.bounds.width - defaultWidthHeightMenuFB * (countMenuFB)
+                }
             }
             var yPosition = frame.origin.y - height + defaultHeightFB
             if yPosition <= 25 {
                 lastPosY = frame.origin.y
                 yPosition = 25
             }
-            if Utils.getConfigModeFB() != "1" {
+            if Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB {
                 frame = CGRect(x: xPosition, y: yPosition, width: width, height: height)
             } else {
                 UIView.animate(withDuration: 0.5, animations: {
@@ -557,16 +581,20 @@ public class FloatingButton: UIView {
                 indicatorCounterFBBig.isHidden = false
             }
             var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
-            if Utils.getConfigModeFB() == "2" {
+            var width = defaultWidthFB
+            if Utils.getConfigModeFB() == MODE_VERTICAL_ANIMATION {
                 height = CGFloat((defaultWidthHeightMenuFB * 3) + defaultHeightFB - 5)
                 scrollView.isHidden = true
+            } else if Utils.getConfigModeFB() == MODE_HORIZONTAL_ANIMATION {
+                height = defaultHeightFB + defaultWidthHeightMenuFB
+                width = defaultWidthFB
             }
             var yPosition = frame.origin.y + height - defaultHeightFB
             if lastPosY != nil {
                 yPosition = lastPosY!
             }
-            if Utils.getConfigModeFB() != "1" {
-                frame = CGRect(x: frame.origin.x, y: yPosition, width: defaultWidthFB, height: defaultHeightFB)
+            if Utils.getConfigModeFB() != MODE_HORIZONTAL_SIDE_TAB {
+                frame = CGRect(x: frame.origin.x, y: yPosition, width: width, height: defaultHeightFB)
             } else {
                 UIView.animate(withDuration: 0.5, animations: { [self] in
                     frame.origin.x = UIScreen.main.bounds.width - defaultWidthFB