Sfoglia il codice sorgente

update Add Confgure FB on setting

alqindiirsyam 1 anno fa
parent
commit
a8aba01f8b

+ 14 - 1
appbuilder-ios/AppBuilder/AppBuilder/FourthTabViewController.swift

@@ -174,6 +174,9 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
                     ]
                 }
                 if !isChangeProfile {
+                    if Nexilis.showButtonFB {
+                        Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
+                    }
                     Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
                 } else if isChangeProfile {
                     Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.clockwise.icloud"), title: "Backup & Restore".localized()))
@@ -220,8 +223,11 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
                     Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
                         Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
                     Item(icon: UIImage(systemName: "person.badge.key"), title: "Access Admin / Internal Features".localized()),
-                    Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized())
                 ]
+                if Nexilis.showButtonFB {
+                    Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
+                }
+                Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
                 if !imageSignIn.isEmpty {
                     do {
                         let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
@@ -358,6 +364,8 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
                 cell.accessoryType = .disclosureIndicator
                 separatorLogin.removeFromSuperview()
                 cell.addBottomBorder(with: .lightGray.withAlphaComponent(0.5), andWidth: 1, view: separatorLogin)
+            case "Configure Floating Button".localized():
+                cell.accessoryType = .disclosureIndicator
             case "Notification Message(s)".localized():
                 cell.accessoryType = .disclosureIndicator
                 separatorNotifPersonal.removeFromSuperview()
@@ -668,6 +676,11 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
             let controller = SetInternalCSAccount()
             controller.isSetCS = true
             navigationController?.show(controller, sender: nil)
+        } else if item.title == "Configure Floating Button".localized() {
+            let viewConfigureFB = ConfigureFloatingButton()
+            viewConfigureFB.modalTransitionStyle = .crossDissolve
+            viewConfigureFB.modalPresentationStyle = .custom
+            self.present(viewConfigureFB, animated: true)
         }
     }
     

+ 4 - 0
appbuilder-ios/DigiXLite/DigiXLite.xcodeproj/project.pbxproj

@@ -208,6 +208,7 @@
 		CD95517C2A6688ED00AF6476 /* Inter-ExtraLight.ttf in Resources */ = {isa = PBXBuildFile; fileRef = CDAEC11A2A612981007DE08D /* Inter-ExtraLight.ttf */; };
 		CD95517D2A6688ED00AF6476 /* Inter-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = CDAEC11D2A612981007DE08D /* Inter-MediumItalic.ttf */; };
 		CD9829B72A3C07CB009F6743 /* SeminarListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD9829B62A3C07CB009F6743 /* SeminarListViewController.swift */; };
+		CDA461202AB99D2D001CD010 /* ConfigureFloatingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA4611F2AB99D2D001CD010 /* ConfigureFloatingButton.swift */; };
 		CDDF46752A2DD81300049A19 /* CreateSeminarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDF46732A2DD81300049A19 /* CreateSeminarViewController.swift */; };
 		CDDF46762A2DD81300049A19 /* SeminarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDF46742A2DD81300049A19 /* SeminarViewController.swift */; };
 		CDDF467A2A2EF0A700049A19 /* ScreenSharingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDF46792A2EF0A700049A19 /* ScreenSharingViewController.swift */; };
@@ -444,6 +445,7 @@
 		CD46A0C42A0D0D5D009E4C87 /* MyArchive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyArchive.swift; sourceTree = "<group>"; };
 		CD5A73AA2A736761000541A5 /* ListGroupImages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListGroupImages.swift; sourceTree = "<group>"; };
 		CD9829B62A3C07CB009F6743 /* SeminarListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeminarListViewController.swift; sourceTree = "<group>"; };
+		CDA4611F2AB99D2D001CD010 /* ConfigureFloatingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigureFloatingButton.swift; sourceTree = "<group>"; };
 		CDAEC1102A612981007DE08D /* Inter-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inter-Medium.ttf"; sourceTree = "<group>"; };
 		CDAEC1112A612981007DE08D /* Inter-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inter-Light.ttf"; sourceTree = "<group>"; };
 		CDAEC1122A612981007DE08D /* Inter-ExtraLightItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inter-ExtraLightItalic.ttf"; sourceTree = "<group>"; };
@@ -744,6 +746,7 @@
 				CD1E71902A0BA86100BF871F /* SignUpSignIn.swift */,
 				CD1E719F2A0BA86100BF871F /* TypeViewController.swift */,
 				CD1E71A02A0BA86100BF871F /* VerifyEmail.swift */,
+				CDA4611F2AB99D2D001CD010 /* ConfigureFloatingButton.swift */,
 			);
 			path = Control;
 			sourceTree = "<group>";
@@ -1205,6 +1208,7 @@
 				CD1E724E2A0BA86100BF871F /* VerifyEmail.swift in Sources */,
 				CDDF46762A2DD81300049A19 /* SeminarViewController.swift in Sources */,
 				CD1E721A2A0BA86100BF871F /* NotifSound.swift in Sources */,
+				CDA461202AB99D2D001CD010 /* ConfigureFloatingButton.swift in Sources */,
 				CD1E724F2A0BA86100BF871F /* SetInternalCSAccount.swift in Sources */,
 				CD1E721C2A0BA86100BF871F /* ContactCallViewController.swift in Sources */,
 				CD1E723B2A0BA86100BF871F /* GroupDescViewController.swift in Sources */,

+ 28 - 18
appbuilder-ios/DigiXLite/DigiXLite/Source/DigiX.swift

@@ -54,6 +54,10 @@ public class DigiX: NSObject {
     
     public static var loadingAlert = LibAlertController()
     
+    public static var floatingButton = FloatingButton()
+    
+    public static var showButtonFB = false
+    
     public static var imageCache = NSCache<NSString, UIImage>()
     
     public static let listenerReceiveChat = "onReceiveChatLibLite"
@@ -122,6 +126,8 @@ public class DigiX: NSObject {
             
             DigiX.sAPIKey = apiKey
             
+            DigiX.showButtonFB = showButton
+            
             Database.shared.openDatabase()
             
             IncomingThread.default.run()
@@ -225,17 +231,7 @@ public class DigiX: NSObject {
                                 notNull = true
                             }
                         }
-                        let fb = FloatingButton()
-                        if fromMAB {
-                            var vc = viewController
-                            if viewController is UINavigationController {
-                                vc = (viewController as! UINavigationController).rootViewController
-                            }
-                            vc?.view.addSubview(fb)
-                            fb.mySettingDelegate = vc as? any SettingMABDelegate
-                        } else {
-                            viewController?.view.addSubview(fb)
-                        }
+                        addFB(viewController: viewController!, fromMAB: fromMAB)
                     }
                 }
             }
@@ -255,6 +251,19 @@ public class DigiX: NSObject {
         }
     }
     
+    static func addFB(viewController: UIViewController, fromMAB: Bool) {
+        if fromMAB {
+            var vc = viewController
+            if viewController is UINavigationController {
+                vc = (viewController as! UINavigationController).rootViewController!
+            }
+            vc.view.addSubview(floatingButton)
+            floatingButton.mySettingDelegate = vc as? any SettingMABDelegate
+        } else {
+            viewController.view.addSubview(floatingButton)
+        }
+    }
+    
     private static func getPullDefaultCC() {
         DispatchQueue.global().async {
             if let response = DigiX.writeSync(message: getPrefs(key: "default_cc"), timeout: 30 * 1000) {
@@ -1032,13 +1041,6 @@ public class DigiX: NSObject {
                     rollback.pointee = true
                     //print(error)
                 }
-            } else {
-                DispatchQueue.main.async {
-                    if let delegate = DigiX.shared.messageDelegate, Utils.getSetProfile() {
-                        message.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString()
-                        delegate.onReceive(message: message)
-                    }
-                }
             }
             var pin = l_pin
             if l_pin == me {
@@ -1089,6 +1091,14 @@ public class DigiX: NSObject {
                     //print(error)
                 }
             }
+            if !withStatus {
+                DispatchQueue.main.async {
+                    if let delegate = DigiX.shared.messageDelegate, Utils.getSetProfile() {
+                        message.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString()
+                        delegate.onReceive(message: message)
+                    }
+                }
+            }
             //print(("insert db message summary \(message_id)")
         })
         

+ 8 - 7
appbuilder-ios/DigiXLite/DigiXLite/Source/FloatingButton/FloatingButton.swift

@@ -72,11 +72,11 @@ public class FloatingButton: UIView {
         nexilis_button.isUserInteractionEnabled = true
         if !Utils.getIconDock().isEmpty {
             var dataImage: Data?
-            if Utils.getIconDock().contains(".gif") {
+            if Utils.getConfigModeFB() == "2" || Utils.getConfigModeFB() == "4" {
                 defaultWidthFB = widthFBAnim
                 defaultHeightFB = heightFBAnim
-                nexilis_button.sd_setImage(with: URL(string: Utils.getIconCenterAnim()!)) { [self] (image, error, cacheType, imageURL) in
-                    if let error = error {
+                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
@@ -124,7 +124,7 @@ public class FloatingButton: UIView {
         
         scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
         scrollView.topAnchor.constraint(equalTo: topAnchor).isActive = true
-        if Utils.getIconDock().contains(".gif") {
+        if Utils.getConfigModeFB() == "2" {
             scrollView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
             scrollView.leftAnchor.constraint(equalTo: nexilis_button.rightAnchor, constant: -20).isActive = true
             scrollView.isHidden = true
@@ -172,6 +172,7 @@ public class FloatingButton: UIView {
         DispatchQueue.global().async { [self] in
             if !Utils.getCustomButtons().isEmpty {
                 DispatchQueue.main.async { [self] in
+                    groupView.subviews.forEach({ $0.removeFromSuperview() })
                     let customButtons = Utils.getCustomButtons().components(separatedBy: ",")
                     let customIcons = Utils.getCustomFBIcon().components(separatedBy: ",")
                     countMenuFB = CGFloat(customButtons.count > 5 ? 5 : customButtons.count)
@@ -327,7 +328,7 @@ public class FloatingButton: UIView {
             xPos = maximumx
         }
         if(isShow) {
-            if Utils.getIconDock().contains(".gif") {
+            if Utils.getConfigModeFB() == "2" {
                 maximumx = widthScreen - 10 - defaultWidthHeightMenuFB
                 if (xPos > maximumx) {
                     xPos = maximumx
@@ -492,7 +493,7 @@ public class FloatingButton: UIView {
             var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
             var width = frame.width
             var xPosition = frame.origin.x
-            if Utils.getIconDock().contains(".gif") {
+            if Utils.getConfigModeFB() == "2" {
                 height = CGFloat((defaultWidthHeightMenuFB * (countMenuFB - 2)) + defaultHeightFB - 5)
                 width = frame.width + defaultWidthHeightMenuFB
                 if xPosition > UIScreen.main.bounds.width - defaultWidthFB - defaultWidthHeightMenuFB {
@@ -519,7 +520,7 @@ public class FloatingButton: UIView {
                 indicatorCounterFBBig.isHidden = false
             }
             var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
-            if Utils.getIconDock().contains(".gif") {
+            if Utils.getConfigModeFB() == "2" {
                 height = CGFloat((defaultWidthHeightMenuFB * 3) + defaultHeightFB - 5)
                 scrollView.isHidden = true
             }

+ 5 - 2
appbuilder-ios/DigiXLite/DigiXLite/Source/IncomingThread.swift

@@ -220,8 +220,11 @@ class IncomingThread {
                     if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_enable_privacy_policy" {
                         Utils.setEnablePrivacyPolicy(value: json[CoreMessage_TMessageKey.VALUE] as! String == "1" ? true : false)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "fb_icon_center_anim" {
-                        Utils.setIconCenterAnim(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "pb_fb_icon_center_self_mode2" {
+                        Utils.setIconCenterAnim2(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    }
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "pb_fb_icon_center_self_mode4" {
+                        Utils.setIconCenterAnim4(value: json[CoreMessage_TMessageKey.VALUE] as! String)
                     }
                     if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_ac_theme" {
                         Utils.setACTheme(value: json[CoreMessage_TMessageKey.VALUE] as! String)

+ 14 - 6
appbuilder-ios/DigiXLite/DigiXLite/Source/Utils.swift

@@ -54,12 +54,20 @@ public final class Utils {
         UserDefaults.standard.set(value, forKey: "is_change_profile")
     }
     
-    static func setIconCenterAnim(value: String){
-        UserDefaults.standard.set(value, forKey: "fb_icon_center_anim")
+    static func setIconCenterAnim2(value: String){
+        UserDefaults.standard.set(value, forKey: "pb_fb_icon_center_self_mode2")
     }
     
-    static func getIconCenterAnim() -> String? {
-        UserDefaults.standard.string(forKey: "fb_icon_center_anim")
+    static func getIconCenterAnim2() -> String? {
+        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode2") ?? "https://nexilis.io/dashboardv2/uploads/logofloat/525_411217560576.gif"
+    }
+    
+    static func setIconCenterAnim4(value: String){
+        UserDefaults.standard.set(value, forKey: "pb_fb_icon_center_self_mode4")
+    }
+    
+    static func getIconCenterAnim4() -> String? {
+        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode4") ?? "https://nexilis.io/dashboardv2/uploads/logofloat/semut1.gif"
     }
     
     static func setURLFirstTab(value: String) {
@@ -218,7 +226,7 @@ public final class Utils {
     }
     
     static func getURLBase() -> String? {
-        return UserDefaults.standard.string(forKey: "app_builder_url_base") ?? "https://newuniverse.io/"
+        return UserDefaults.standard.string(forKey: "app_builder_url_base") ?? "https://nexilis.io/"
     }
     
     static func getIconDock() -> String {
@@ -226,7 +234,7 @@ public final class Utils {
     }
     
     static func getUrlDock() -> String? {
-        return Utils.getURLBase()! + "dashboardv2/uploads/fb_icon/" + Utils.getIconDock()
+        return Utils.getURLBase()! + "dashboardv2/uploads/logofloat/" + Utils.getIconDock()
     }
     
     static func setDefaultCC(value: String){

+ 153 - 11
appbuilder-ios/DigiXLite/DigiXLite/Source/View/Control/ConfigureFloatingButton.swift

@@ -1,29 +1,171 @@
 //
 //  ConfigureFloatingButton.swift
-//  DigiXLite
+//  NexilisLite
 //
 //  Created by Akhmad Al Qindi Irsyam on 19/09/23.
 //
 
 import UIKit
 
-class ConfigureFloatingButton: UIViewController {
+public class ConfigureFloatingButton: UIViewController {
+    let subContainerView = UIView()
+    let titleConfigureFB = UILabel()
+    var chosenMode: String = "1"
+    var fullMode: [String] = ["1", "2", "3", "4"]
+    var dataMode: [String] = ["1. Side-Tab (Horizontal Mode)".localized(),"2. Animation (Vertical Mode)".localized(),"3. Floating Button (Vertical Mode)".localized(),"4. Animation (Horizontal Mode)".localized()]
+    var paddingTopFinishButton = NSLayoutConstraint()
+    let buttonSet = UIButton()
+    let modeButton = UIView()
+    var paddingBottomSLButton = NSLayoutConstraint()
+    var showPickerInt = 0
+    let chosenModeTitle = UILabel()
 
-    override func viewDidLoad() {
+    public override func viewDidLoad() {
         super.viewDidLoad()
+        
+        getInisialData()
+        
+        view.backgroundColor = .black.withAlphaComponent(0.3)
 
-        // Do any additional setup after loading the view.
+        let containerView = UIView()
+        view.addSubview(containerView)
+        containerView.anchor(centerX: view.centerXAnchor, centerY: view.centerYAnchor, width: view.bounds.width - 40, minHeight: 100, maxHeight: view.bounds.height - 100)
+        containerView.backgroundColor = .white.withAlphaComponent(0.9)
+        containerView.layer.cornerRadius = 15.0
+        containerView.clipsToBounds = true
+        
+        subContainerView.backgroundColor = .clear
+        containerView.addSubview(subContainerView)
+        subContainerView.anchor(top: containerView.topAnchor, left: containerView.leftAnchor, bottom: containerView.bottomAnchor, right: containerView.rightAnchor, paddingTop: 20.0, paddingLeft: 10.0, paddingBottom: 20.0, paddingRight: 10.0)
+        
+        let buttonClose = UIButton(type: .close)
+        buttonClose.frame.size = CGSize(width: 30, height: 30)
+        buttonClose.layer.cornerRadius = 15.0
+        buttonClose.clipsToBounds = true
+        buttonClose.backgroundColor = .secondaryColor.withAlphaComponent(0.5)
+        buttonClose.addTarget(self, action: #selector(close), for: .touchUpInside)
+        containerView.addSubview(buttonClose)
+        buttonClose.anchor(top: containerView.topAnchor, right: containerView.rightAnchor, width: 30, height: 30)
+        
+        titleConfigureFB.font = .systemFont(ofSize: 18, weight: .bold)
+        titleConfigureFB.text = "Configure Floating Button".localized()
+        titleConfigureFB.textAlignment = .center
+        subContainerView.addSubview(titleConfigureFB)
+        titleConfigureFB.anchor(top: subContainerView.topAnchor, left: subContainerView.leftAnchor, right: subContainerView.rightAnchor)
+        
+        makeFinish()
+        makeButtonMode()
+        
     }
     
+    private func getInisialData() {
+        chosenMode = Utils.getConfigModeFB()
+    }
+    
+    @objc func close() {
+        self.dismiss(animated: true)
+    }
+    
+    func makeFinish() {
+        buttonSet.backgroundColor = .black
+        buttonSet.setImage(UIImage(systemName: "checkmark"), for: .normal)
+        buttonSet.tintColor = .white
+        buttonSet.setTitle("Set".localized(), for: .normal)
+        buttonSet.titleLabel?.font = .boldSystemFont(ofSize: 15)
+        buttonSet.layer.cornerRadius = 8
+        subContainerView.addSubview(buttonSet)
+        buttonSet.anchor(bottom: subContainerView.bottomAnchor, right: subContainerView.rightAnchor, width: (self.view.bounds.width / 2) - 55, height: 40)
+        paddingTopFinishButton = buttonSet.topAnchor.constraint(equalTo: titleConfigureFB.bottomAnchor, constant: 10)
+        paddingTopFinishButton.isActive = true
+        buttonSet.addTarget(self, action: #selector(setFB), for: .touchUpInside)
+    }
+    
+    func makeButtonMode() {
+        modeButton.backgroundColor = .white
+        modeButton.isUserInteractionEnabled = true
+        subContainerView.addSubview(modeButton)
+        modeButton.anchor(top: titleConfigureFB.bottomAnchor, left: subContainerView.leftAnchor, right: subContainerView.rightAnchor, paddingTop: 10, height: 40)
+        modeButton.layer.cornerRadius = 10
+        modeButton.layer.masksToBounds = true
+        let titleTypeButton = UILabel()
+        titleTypeButton.font = .systemFont(ofSize: 14, weight: .bold)
+        titleTypeButton.text = "New Mode".localized()
+        titleTypeButton.textColor = .gray
+        modeButton.addSubview(titleTypeButton)
+        titleTypeButton.anchor(left: modeButton.leftAnchor, paddingLeft: 10, centerY: modeButton.centerYAnchor)
+        let accessoryType = UIImageView()
+        accessoryType.image = UIImage(systemName: "chevron.right")
+        accessoryType.tintColor = .gray
+        modeButton.addSubview(accessoryType)
+        accessoryType.anchor(right: modeButton.rightAnchor, paddingRight: 10, centerY: modeButton.centerYAnchor)
+        chosenModeTitle.font = .systemFont(ofSize: 14)
+        chosenModeTitle.text = dataMode[Int(chosenMode)! - 1]
+        chosenModeTitle.textColor = .gray
+        modeButton.addSubview(chosenModeTitle)
+        modeButton.tag = 0
+        chosenModeTitle.anchor(right: accessoryType.leftAnchor, paddingLeft: 15, centerY: modeButton.centerYAnchor)
+        let tap = UITapGestureRecognizer(target: self, action: #selector(showPicker(sender:)))
+        modeButton.addGestureRecognizer(tap)
+        let constPaddingTop = 55
+        paddingTopFinishButton.constant = CGFloat(constPaddingTop)
+    }
+    
+    @objc func setFB() {
+        Utils.setConfigModeFB(value: chosenMode)
+        DispatchQueue.main.async {
+            DigiX.floatingButton.removeFromSuperview()
+            DigiX.floatingButton = FloatingButton()
+            let viewController = (UIApplication.shared.windows.first?.rootViewController)!
+            DigiX.addFB(viewController: viewController, fromMAB: true)
+        }
+        close()
+    }
+    
+    @objc func showPicker(sender: UITapGestureRecognizer) {
+        showPickerInt = sender.view!.tag
+        
+        let index = fullMode.firstIndex(of: chosenMode)!
+        let titleChooser = "New Mode".localized()
+        let pickerView = UIPickerView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width - 10, height: 100))
+        pickerView.dataSource = self
+        pickerView.delegate = self
 
-    /*
-    // MARK: - Navigation
+        let vc = UIViewController()
+        vc.preferredContentSize = CGSize(width: UIScreen.main.bounds.width - 10, height: 100)
+        pickerView.selectRow(index, inComponent: 0, animated: false)
 
-    // 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.
+        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 = LibAlertController(title: titleChooser, message: "", preferredStyle: .actionSheet)
+
+        alert.setValue(vc, forKey: "contentViewController")
+        alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { (UIAlertAction) in
+        }))
+        
+        alert.addAction(UIAlertAction(title: "Select".localized(), style: .default, handler: { [self] (UIAlertAction) in
+            let selectedIndex = pickerView.selectedRow(inComponent: 0)
+            chosenMode = fullMode[selectedIndex]
+            chosenModeTitle.text = dataMode[selectedIndex]
+        }))
+        self.present(alert, animated: true, completion: nil)
     }
-    */
 
 }
+
+extension ConfigureFloatingButton: UIPickerViewDelegate, UIPickerViewDataSource {
+    public func numberOfComponents(in pickerView: UIPickerView) -> Int {
+        1
+    }
+    
+    public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
+        return dataMode.count
+    }
+    
+    public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
+        return dataMode[row]
+    }
+}
+

+ 16 - 3
appbuilder-ios/DigiXLite/DigiXLite/Source/View/Control/SettingTableViewController.swift

@@ -129,6 +129,9 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                     ]
                 }
                 if !isChangeProfile {
+                    if DigiX.showButtonFB {
+                        Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
+                    }
                     Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
                 } else if isChangeProfile {
                     Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.clockwise.icloud"), title: "Backup & Restore".localized()))
@@ -175,8 +178,11 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                     Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
                         Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
                     Item(icon: UIImage(systemName: "person.badge.key"), title: "Access Admin / Internal Features".localized()),
-                    Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized())
                 ]
+                if DigiX.showButtonFB {
+                    Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
+                }
+                Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
                 if !imageSignIn.isEmpty {
                     do {
                         let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
@@ -304,6 +310,8 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                 cell.accessoryType = .disclosureIndicator
                 separatorLogin.removeFromSuperview()
                 cell.addBottomBorder(with: .lightGray.withAlphaComponent(0.5), andWidth: 1, view: separatorLogin)
+            case "Configure Floating Button".localized():
+                cell.accessoryType = .disclosureIndicator
             case "Notification Message(s)".localized():
                 cell.accessoryType = .disclosureIndicator
                 separatorNotifPersonal.removeFromSuperview()
@@ -582,6 +590,11 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
             let controller = SetInternalCSAccount()
             controller.isSetCS = true
             navigationController?.show(controller, sender: nil)
+        } else if item.title == "Configure Floating Button".localized() {
+            let viewConfigureFB = ConfigureFloatingButton()
+            viewConfigureFB.modalTransitionStyle = .crossDissolve
+            viewConfigureFB.modalPresentationStyle = .custom
+            self.present(viewConfigureFB, animated: true)
         }
     }
     
@@ -757,8 +770,8 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
     
     @objc func alertTextFieldDidChange(_ sender: UITextField) {
         if(!textFields.isEmpty){
-            //print(("text count 0: \(textFields[0].text!.count)")
-            //print(("text count 1: \(textFields[1].text!.count)")
+            //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 {

+ 8 - 7
appbuilder-ios/NexilisLite/NexilisLite/Source/FloatingButton/FloatingButton.swift

@@ -72,11 +72,11 @@ public class FloatingButton: UIView {
         nexilis_button.isUserInteractionEnabled = true
         if !Utils.getIconDock().isEmpty {
             var dataImage: Data?
-            if Utils.getIconDock().contains(".gif") {
+            if Utils.getConfigModeFB() == "2" || Utils.getConfigModeFB() == "4" {
                 defaultWidthFB = widthFBAnim
                 defaultHeightFB = heightFBAnim
-                nexilis_button.sd_setImage(with: URL(string: Utils.getIconCenterAnim()!)) { [self] (image, error, cacheType, imageURL) in
-                    if let error = error {
+                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
@@ -124,7 +124,7 @@ public class FloatingButton: UIView {
         
         scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
         scrollView.topAnchor.constraint(equalTo: topAnchor).isActive = true
-        if Utils.getIconDock().contains(".gif") {
+        if Utils.getConfigModeFB() == "2" {
             scrollView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
             scrollView.leftAnchor.constraint(equalTo: nexilis_button.rightAnchor, constant: -20).isActive = true
             scrollView.isHidden = true
@@ -172,6 +172,7 @@ public class FloatingButton: UIView {
         DispatchQueue.global().async { [self] in
             if !Utils.getCustomButtons().isEmpty {
                 DispatchQueue.main.async { [self] in
+                    groupView.subviews.forEach({ $0.removeFromSuperview() })
                     let customButtons = Utils.getCustomButtons().components(separatedBy: ",")
                     let customIcons = Utils.getCustomFBIcon().components(separatedBy: ",")
                     countMenuFB = CGFloat(customButtons.count > 5 ? 5 : customButtons.count)
@@ -327,7 +328,7 @@ public class FloatingButton: UIView {
             xPos = maximumx
         }
         if(isShow) {
-            if Utils.getIconDock().contains(".gif") {
+            if Utils.getConfigModeFB() == "2" {
                 maximumx = widthScreen - 10 - defaultWidthHeightMenuFB
                 if (xPos > maximumx) {
                     xPos = maximumx
@@ -492,7 +493,7 @@ public class FloatingButton: UIView {
             var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
             var width = frame.width
             var xPosition = frame.origin.x
-            if Utils.getIconDock().contains(".gif") {
+            if Utils.getConfigModeFB() == "2" {
                 height = CGFloat((defaultWidthHeightMenuFB * (countMenuFB - 2)) + defaultHeightFB - 5)
                 width = frame.width + defaultWidthHeightMenuFB
                 if xPosition > UIScreen.main.bounds.width - defaultWidthFB - defaultWidthHeightMenuFB {
@@ -519,7 +520,7 @@ public class FloatingButton: UIView {
                 indicatorCounterFBBig.isHidden = false
             }
             var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
-            if Utils.getIconDock().contains(".gif") {
+            if Utils.getConfigModeFB() == "2" {
                 height = CGFloat((defaultWidthHeightMenuFB * 3) + defaultHeightFB - 5)
                 scrollView.isHidden = true
             }

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

@@ -220,8 +220,11 @@ class IncomingThread {
                     if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_enable_privacy_policy" {
                         Utils.setEnablePrivacyPolicy(value: json[CoreMessage_TMessageKey.VALUE] as! String == "1" ? true : false)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "fb_icon_center_anim" {
-                        Utils.setIconCenterAnim(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "pb_fb_icon_center_self_mode2" {
+                        Utils.setIconCenterAnim2(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    }
+                    if json[CoreMessage_TMessageKey.KEY] as! String == "pb_fb_icon_center_self_mode4" {
+                        Utils.setIconCenterAnim4(value: json[CoreMessage_TMessageKey.VALUE] as! String)
                     }
                     if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_ac_theme" {
                         Utils.setACTheme(value: json[CoreMessage_TMessageKey.VALUE] as! String)

+ 28 - 18
appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -54,6 +54,10 @@ public class Nexilis: NSObject {
     
     public static var loadingAlert = LibAlertController()
     
+    public static var floatingButton = FloatingButton()
+    
+    public static var showButtonFB = false
+    
     public static var imageCache = NSCache<NSString, UIImage>()
     
     public static let listenerReceiveChat = "onReceiveChatLibLite"
@@ -122,6 +126,8 @@ public class Nexilis: NSObject {
             
             Nexilis.sAPIKey = apiKey
             
+            Nexilis.showButtonFB = showButton
+            
             Database.shared.openDatabase()
             
             IncomingThread.default.run()
@@ -225,17 +231,7 @@ public class Nexilis: NSObject {
                                 notNull = true
                             }
                         }
-                        let fb = FloatingButton()
-                        if fromMAB {
-                            var vc = viewController
-                            if viewController is UINavigationController {
-                                vc = (viewController as! UINavigationController).rootViewController
-                            }
-                            vc?.view.addSubview(fb)
-                            fb.mySettingDelegate = vc as? any SettingMABDelegate
-                        } else {
-                            viewController?.view.addSubview(fb)
-                        }
+                        addFB(viewController: viewController!, fromMAB: fromMAB)
                     }
                 }
             }
@@ -256,6 +252,19 @@ public class Nexilis: NSObject {
         }
     }
     
+    static func addFB(viewController: UIViewController, fromMAB: Bool) {
+        if fromMAB {
+            var vc = viewController
+            if viewController is UINavigationController {
+                vc = (viewController as! UINavigationController).rootViewController!
+            }
+            vc.view.addSubview(floatingButton)
+            floatingButton.mySettingDelegate = vc as? any SettingMABDelegate
+        } else {
+            viewController.view.addSubview(floatingButton)
+        }
+    }
+    
     private static func getPullDefaultCC() {
         DispatchQueue.global().async {
             if let response = Nexilis.writeSync(message: getPrefs(key: "default_cc"), timeout: 30 * 1000) {
@@ -1033,13 +1042,6 @@ public class Nexilis: NSObject {
                     rollback.pointee = true
                     //print(error)
                 }
-            } else {
-                DispatchQueue.main.async {
-                    if let delegate = Nexilis.shared.messageDelegate, Utils.getSetProfile() {
-                        message.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString()
-                        delegate.onReceive(message: message)
-                    }
-                }
             }
             var pin = l_pin
             if l_pin == me {
@@ -1090,6 +1092,14 @@ public class Nexilis: NSObject {
                     //print(error)
                 }
             }
+            if !withStatus {
+                DispatchQueue.main.async {
+                    if let delegate = Nexilis.shared.messageDelegate, Utils.getSetProfile() {
+                        message.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString()
+                        delegate.onReceive(message: message)
+                    }
+                }
+            }
             //print("insert db message summary \(message_id)")
         })
         

+ 14 - 6
appbuilder-ios/NexilisLite/NexilisLite/Source/Utils.swift

@@ -54,12 +54,20 @@ public final class Utils {
         UserDefaults.standard.set(value, forKey: "is_change_profile")
     }
     
-    static func setIconCenterAnim(value: String){
-        UserDefaults.standard.set(value, forKey: "fb_icon_center_anim")
+    static func setIconCenterAnim2(value: String){
+        UserDefaults.standard.set(value, forKey: "pb_fb_icon_center_self_mode2")
     }
     
-    static func getIconCenterAnim() -> String? {
-        UserDefaults.standard.string(forKey: "fb_icon_center_anim")
+    static func getIconCenterAnim2() -> String? {
+        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode2") ?? "https://nexilis.io/dashboardv2/uploads/logofloat/525_411217560576.gif"
+    }
+    
+    static func setIconCenterAnim4(value: String){
+        UserDefaults.standard.set(value, forKey: "pb_fb_icon_center_self_mode4")
+    }
+    
+    static func getIconCenterAnim4() -> String? {
+        UserDefaults.standard.string(forKey: "pb_fb_icon_center_self_mode4") ?? "https://nexilis.io/dashboardv2/uploads/logofloat/semut1.gif"
     }
     
     static func setURLFirstTab(value: String) {
@@ -218,7 +226,7 @@ public final class Utils {
     }
     
     static func getURLBase() -> String? {
-        return UserDefaults.standard.string(forKey: "app_builder_url_base") ?? "https://newuniverse.io/"
+        return UserDefaults.standard.string(forKey: "app_builder_url_base") ?? "https://nexilis.io/"
     }
     
     static func getIconDock() -> String {
@@ -226,7 +234,7 @@ public final class Utils {
     }
     
     static func getUrlDock() -> String? {
-        return Utils.getURLBase()! + "dashboardv2/uploads/fb_icon/" + Utils.getIconDock()
+        return Utils.getURLBase()! + "dashboardv2/uploads/logofloat/" + Utils.getIconDock()
     }
     
     static func setDefaultCC(value: String){

+ 152 - 10
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ConfigureFloatingButton.swift

@@ -7,23 +7,165 @@
 
 import UIKit
 
-class ConfigureFloatingButton: UIViewController {
+public class ConfigureFloatingButton: UIViewController {
+    let subContainerView = UIView()
+    let titleConfigureFB = UILabel()
+    var chosenMode: String = "1"
+    var fullMode: [String] = ["1", "2", "3", "4"]
+    var dataMode: [String] = ["1. Side-Tab (Horizontal Mode)".localized(),"2. Animation (Vertical Mode)".localized(),"3. Floating Button (Vertical Mode)".localized(),"4. Animation (Horizontal Mode)".localized()]
+    var paddingTopFinishButton = NSLayoutConstraint()
+    let buttonSet = UIButton()
+    let modeButton = UIView()
+    var paddingBottomSLButton = NSLayoutConstraint()
+    var showPickerInt = 0
+    let chosenModeTitle = UILabel()
 
-    override func viewDidLoad() {
+    public override func viewDidLoad() {
         super.viewDidLoad()
+        
+        getInisialData()
+        
+        view.backgroundColor = .black.withAlphaComponent(0.3)
 
-        // Do any additional setup after loading the view.
+        let containerView = UIView()
+        view.addSubview(containerView)
+        containerView.anchor(centerX: view.centerXAnchor, centerY: view.centerYAnchor, width: view.bounds.width - 40, minHeight: 100, maxHeight: view.bounds.height - 100)
+        containerView.backgroundColor = .white.withAlphaComponent(0.9)
+        containerView.layer.cornerRadius = 15.0
+        containerView.clipsToBounds = true
+        
+        subContainerView.backgroundColor = .clear
+        containerView.addSubview(subContainerView)
+        subContainerView.anchor(top: containerView.topAnchor, left: containerView.leftAnchor, bottom: containerView.bottomAnchor, right: containerView.rightAnchor, paddingTop: 20.0, paddingLeft: 10.0, paddingBottom: 20.0, paddingRight: 10.0)
+        
+        let buttonClose = UIButton(type: .close)
+        buttonClose.frame.size = CGSize(width: 30, height: 30)
+        buttonClose.layer.cornerRadius = 15.0
+        buttonClose.clipsToBounds = true
+        buttonClose.backgroundColor = .secondaryColor.withAlphaComponent(0.5)
+        buttonClose.addTarget(self, action: #selector(close), for: .touchUpInside)
+        containerView.addSubview(buttonClose)
+        buttonClose.anchor(top: containerView.topAnchor, right: containerView.rightAnchor, width: 30, height: 30)
+        
+        titleConfigureFB.font = .systemFont(ofSize: 18, weight: .bold)
+        titleConfigureFB.text = "Configure Floating Button".localized()
+        titleConfigureFB.textAlignment = .center
+        subContainerView.addSubview(titleConfigureFB)
+        titleConfigureFB.anchor(top: subContainerView.topAnchor, left: subContainerView.leftAnchor, right: subContainerView.rightAnchor)
+        
+        makeFinish()
+        makeButtonMode()
+        
     }
     
+    private func getInisialData() {
+        chosenMode = Utils.getConfigModeFB()
+    }
+    
+    @objc func close() {
+        self.dismiss(animated: true)
+    }
+    
+    func makeFinish() {
+        buttonSet.backgroundColor = .black
+        buttonSet.setImage(UIImage(systemName: "checkmark"), for: .normal)
+        buttonSet.tintColor = .white
+        buttonSet.setTitle("Set".localized(), for: .normal)
+        buttonSet.titleLabel?.font = .boldSystemFont(ofSize: 15)
+        buttonSet.layer.cornerRadius = 8
+        subContainerView.addSubview(buttonSet)
+        buttonSet.anchor(bottom: subContainerView.bottomAnchor, right: subContainerView.rightAnchor, width: (self.view.bounds.width / 2) - 55, height: 40)
+        paddingTopFinishButton = buttonSet.topAnchor.constraint(equalTo: titleConfigureFB.bottomAnchor, constant: 10)
+        paddingTopFinishButton.isActive = true
+        buttonSet.addTarget(self, action: #selector(setFB), for: .touchUpInside)
+    }
+    
+    func makeButtonMode() {
+        modeButton.backgroundColor = .white
+        modeButton.isUserInteractionEnabled = true
+        subContainerView.addSubview(modeButton)
+        modeButton.anchor(top: titleConfigureFB.bottomAnchor, left: subContainerView.leftAnchor, right: subContainerView.rightAnchor, paddingTop: 10, height: 40)
+        modeButton.layer.cornerRadius = 10
+        modeButton.layer.masksToBounds = true
+        let titleTypeButton = UILabel()
+        titleTypeButton.font = .systemFont(ofSize: 14, weight: .bold)
+        titleTypeButton.text = "New Mode".localized()
+        titleTypeButton.textColor = .gray
+        modeButton.addSubview(titleTypeButton)
+        titleTypeButton.anchor(left: modeButton.leftAnchor, paddingLeft: 10, centerY: modeButton.centerYAnchor)
+        let accessoryType = UIImageView()
+        accessoryType.image = UIImage(systemName: "chevron.right")
+        accessoryType.tintColor = .gray
+        modeButton.addSubview(accessoryType)
+        accessoryType.anchor(right: modeButton.rightAnchor, paddingRight: 10, centerY: modeButton.centerYAnchor)
+        chosenModeTitle.font = .systemFont(ofSize: 14)
+        chosenModeTitle.text = dataMode[Int(chosenMode)! - 1]
+        chosenModeTitle.textColor = .gray
+        modeButton.addSubview(chosenModeTitle)
+        modeButton.tag = 0
+        chosenModeTitle.anchor(right: accessoryType.leftAnchor, paddingLeft: 15, centerY: modeButton.centerYAnchor)
+        let tap = UITapGestureRecognizer(target: self, action: #selector(showPicker(sender:)))
+        modeButton.addGestureRecognizer(tap)
+        let constPaddingTop = 55
+        paddingTopFinishButton.constant = CGFloat(constPaddingTop)
+    }
+    
+    @objc func setFB() {
+        Utils.setConfigModeFB(value: chosenMode)
+        DispatchQueue.main.async {
+            Nexilis.floatingButton.removeFromSuperview()
+            Nexilis.floatingButton = FloatingButton()
+            let viewController = (UIApplication.shared.windows.first?.rootViewController)!
+            Nexilis.addFB(viewController: viewController, fromMAB: true)
+        }
+        close()
+    }
+    
+    @objc func showPicker(sender: UITapGestureRecognizer) {
+        showPickerInt = sender.view!.tag
+        
+        let index = fullMode.firstIndex(of: chosenMode)!
+        let titleChooser = "New Mode".localized()
+        let pickerView = UIPickerView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width - 10, height: 100))
+        pickerView.dataSource = self
+        pickerView.delegate = self
 
-    /*
-    // MARK: - Navigation
+        let vc = UIViewController()
+        vc.preferredContentSize = CGSize(width: UIScreen.main.bounds.width - 10, height: 100)
+        pickerView.selectRow(index, inComponent: 0, animated: false)
 
-    // 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.
+        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 = LibAlertController(title: titleChooser, message: "", preferredStyle: .actionSheet)
+
+        alert.setValue(vc, forKey: "contentViewController")
+        alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { (UIAlertAction) in
+        }))
+        
+        alert.addAction(UIAlertAction(title: "Select".localized(), style: .default, handler: { [self] (UIAlertAction) in
+            let selectedIndex = pickerView.selectedRow(inComponent: 0)
+            chosenMode = fullMode[selectedIndex]
+            chosenModeTitle.text = dataMode[selectedIndex]
+        }))
+        self.present(alert, animated: true, completion: nil)
     }
-    */
 
 }
+
+extension ConfigureFloatingButton: UIPickerViewDelegate, UIPickerViewDataSource {
+    public func numberOfComponents(in pickerView: UIPickerView) -> Int {
+        1
+    }
+    
+    public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
+        return dataMode.count
+    }
+    
+    public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
+        return dataMode[row]
+    }
+}
+

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

@@ -129,6 +129,9 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                     ]
                 }
                 if !isChangeProfile {
+                    if Nexilis.showButtonFB {
+                        Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
+                    }
                     Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
                 } else if isChangeProfile {
                     Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.clockwise.icloud"), title: "Backup & Restore".localized()))
@@ -175,8 +178,11 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                     Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
                         Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
                     Item(icon: UIImage(systemName: "person.badge.key"), title: "Access Admin / Internal Features".localized()),
-                    Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized())
                 ]
+                if Nexilis.showButtonFB {
+                    Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
+                }
+                Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
                 if !imageSignIn.isEmpty {
                     do {
                         let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
@@ -304,6 +310,8 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                 cell.accessoryType = .disclosureIndicator
                 separatorLogin.removeFromSuperview()
                 cell.addBottomBorder(with: .lightGray.withAlphaComponent(0.5), andWidth: 1, view: separatorLogin)
+            case "Configure Floating Button".localized():
+                cell.accessoryType = .disclosureIndicator
             case "Notification Message(s)".localized():
                 cell.accessoryType = .disclosureIndicator
                 separatorNotifPersonal.removeFromSuperview()
@@ -582,6 +590,11 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
             let controller = SetInternalCSAccount()
             controller.isSetCS = true
             navigationController?.show(controller, sender: nil)
+        } else if item.title == "Configure Floating Button".localized() {
+            let viewConfigureFB = ConfigureFloatingButton()
+            viewConfigureFB.modalTransitionStyle = .crossDissolve
+            viewConfigureFB.modalPresentationStyle = .custom
+            self.present(viewConfigureFB, animated: true)
         }
     }