FloatingButton.swift 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. //
  2. // FloatingButton.swift
  3. // Qmera
  4. //
  5. // Created by Yayan Dwi on 03/09/21.
  6. //
  7. import UIKit
  8. import nuSDKService
  9. import NotificationBannerSwift
  10. public class FloatingButton: UIView, UIGestureRecognizerDelegate {
  11. var groupView: UIStackView!
  12. var scrollView: UIScrollView!
  13. var imageScrollView: UIImageView!
  14. var button_fb1: UIButton!
  15. var button_fb2: UIButton!
  16. var button_fb3: UIButton!
  17. var button_fb4: UIButton!
  18. var nexilis_button: UIImageView!
  19. var nexilis_pin: UIImageView!
  20. var leadingConstraintPin: NSLayoutConstraint!
  21. var bottomConstraintPin: NSLayoutConstraint!
  22. var trailingConstraintPin: NSLayoutConstraint!
  23. var topConstraintPin: NSLayoutConstraint!
  24. var lastPosY: CGFloat?
  25. var lastImageButton = ""
  26. var iconCC = ""
  27. let indicatorCounterFB = UIView()
  28. let labelCounterFB = UILabel()
  29. let indicatorCounterFBBig = UIImageView()
  30. var datePull: Date?
  31. var animationTimer = Timer()
  32. var configAnim: Int = Int(Utils.getFloatingAnim().components(separatedBy: "~")[0]) ?? 1
  33. var isLoopingAnim = (Int(Utils.getFloatingAnim().components(separatedBy: "~")[1]) ?? 1) == 1 ? true : false
  34. var lastRunAnimationHrz = -1
  35. var lastRunAnimationVrt = -1
  36. var panGesture: UIPanGestureRecognizer?
  37. var defaultWidthFB = (UIScreen.main.bounds.height * 0.5) / 7.5
  38. var defaultHeightFB = (UIScreen.main.bounds.height * 0.5) / 7.5
  39. let defaultWidthHeightMenuFB = (UIScreen.main.bounds.height * 0.45) / 7.5
  40. let widthFBAnim = (UIScreen.main.bounds.height * 0.8) / 7.5
  41. let heightFBAnim = (UIScreen.main.bounds.height * 1) / 7.5
  42. let heightFBSideTab = (UIScreen.main.bounds.height * 1.05) / 7.5
  43. let widthFBSideTab: CGFloat = 18
  44. let widthVerticalSideTab: CGFloat = 50
  45. let heightVerticalSideTab: CGFloat = 220
  46. final let MODE_VERTICAL_FLOATING_BUTTON = "1"
  47. final let MODE_VERTICAL_ANIMATION = "2"
  48. final let MODE_HORIZONTAL_ANIMATION = "3"
  49. final let MODE_HORIZONTAL_SIDE_TAB = "4"
  50. final let MODE_VERTICAL_SIDE_TAB = "5"
  51. var configModeFB = "1"
  52. var countMenuFB: CGFloat = 6 {
  53. didSet {
  54. if isShow {
  55. show(isShow: isShow)
  56. }
  57. }
  58. }
  59. public weak var mySettingDelegate: SettingMABDelegate?
  60. public var isShow: Bool = false
  61. override init(frame: CGRect) {
  62. super.init(frame: frame)
  63. commonInit()
  64. }
  65. required init?(coder: NSCoder) {
  66. super.init(coder: coder)
  67. commonInit()
  68. }
  69. private func commonInit() {
  70. panGesture = UIPanGestureRecognizer(target: self, action: #selector(draggedView(_:)))
  71. addGestureRecognizer(panGesture!)
  72. configModeFB = Utils.getConfigModeFB()
  73. nexilis_button = UIImageView()
  74. nexilis_button.translatesAutoresizingMaskIntoConstraints = false
  75. nexilis_button.isUserInteractionEnabled = true
  76. if configModeFB == MODE_VERTICAL_ANIMATION || configModeFB == MODE_HORIZONTAL_ANIMATION {
  77. defaultWidthFB = widthFBAnim
  78. if configModeFB == MODE_HORIZONTAL_ANIMATION {
  79. defaultHeightFB = heightFBAnim + 30
  80. } else {
  81. defaultHeightFB = heightFBAnim
  82. }
  83. var urlGif = URL(string: configModeFB == MODE_VERTICAL_ANIMATION ? Utils.getIconCenterAnim2() : Utils.getIconCenterAnim4())
  84. if (urlGif == nil) {
  85. urlGif = Bundle.resourceBundle(for: Nexilis.self).url(forResource: configModeFB == MODE_VERTICAL_ANIMATION ? "pb_def_icon_mode2" : "pb_def_icon_mode4", withExtension: "gif") ?? nil
  86. if urlGif == nil {
  87. urlGif = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: configModeFB == MODE_VERTICAL_ANIMATION ? "pb_def_icon_mode2" : "pb_def_icon_mode4", withExtension: "gif")!
  88. }
  89. }
  90. nexilis_button.sd_setImage(with: urlGif) { [self] (image, error, cacheType, imageURL) in
  91. if error == nil {
  92. nexilis_button.animationImages = image?.images
  93. nexilis_button.animationDuration = image?.duration ?? 0.0
  94. nexilis_button.animationRepeatCount = 0
  95. nexilis_button.startAnimating()
  96. }
  97. }
  98. } else {
  99. if !Utils.getIconDock().isEmpty && configModeFB == MODE_VERTICAL_FLOATING_BUTTON && Nexilis.fromMAB {
  100. setImageWithURL(true)
  101. } else {
  102. if configModeFB == MODE_HORIZONTAL_SIDE_TAB || configModeFB == MODE_VERTICAL_SIDE_TAB {
  103. defaultWidthFB = widthFBSideTab
  104. defaultHeightFB = heightFBSideTab
  105. }
  106. if !Utils.getIconCenter().isEmpty && configModeFB == MODE_VERTICAL_FLOATING_BUTTON {
  107. setImageWithURL(false)
  108. } else {
  109. nexilis_button.image = UIImage(named: configModeFB == MODE_VERTICAL_SIDE_TAB ? "pb_side_tab_vtc" : configModeFB == MODE_HORIZONTAL_SIDE_TAB ? "pb_side_tab" : "pb_button", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
  110. }
  111. }
  112. }
  113. backgroundColor = .clear
  114. frame = CGRect(x: UIScreen.main.bounds.width - defaultWidthFB, y: (UIScreen.main.bounds.height / 2) - defaultHeightFB, width: configModeFB == MODE_VERTICAL_SIDE_TAB ? 50 + defaultWidthFB : configModeFB == MODE_HORIZONTAL_SIDE_TAB ? UIScreen.main.bounds.width - defaultWidthFB : defaultWidthFB, height: configModeFB == MODE_VERTICAL_SIDE_TAB ? heightVerticalSideTab : defaultHeightFB)
  115. if configModeFB == MODE_VERTICAL_ANIMATION || configModeFB == MODE_HORIZONTAL_ANIMATION {
  116. if configAnim == 0 { //left to right
  117. lastRunAnimationHrz = 1
  118. } else if configAnim == 1 { //right to left
  119. lastRunAnimationHrz = -1
  120. } else if configAnim == 2 { //top to bottom
  121. lastRunAnimationVrt = 1
  122. } else if configAnim == 3 { //top to bottom
  123. lastRunAnimationVrt = -1
  124. }
  125. if configAnim >= 0 && configAnim <= 3 {
  126. checkDelayAnimation()
  127. }
  128. }
  129. let qmeraTap = UITapGestureRecognizer(target: self, action: #selector(qmeraTap))
  130. qmeraTap.numberOfTouchesRequired = 1
  131. nexilis_button.addGestureRecognizer(qmeraTap)
  132. qmeraTap.delegate = self
  133. let qmeraLongPress = UILongPressGestureRecognizer(target: self, action: #selector(qmeraLongPress(gestureRecognizer:)))
  134. self.addGestureRecognizer(qmeraLongPress)
  135. addSubview(nexilis_button)
  136. nexilis_button.widthAnchor.constraint(equalToConstant: defaultWidthFB).isActive = true
  137. nexilis_button.heightAnchor.constraint(equalToConstant: defaultHeightFB).isActive = true
  138. nexilis_button.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
  139. if configModeFB == MODE_VERTICAL_SIDE_TAB {
  140. nexilis_button.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
  141. } else {
  142. nexilis_button.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
  143. }
  144. scrollView = UIScrollView()
  145. scrollView.translatesAutoresizingMaskIntoConstraints = false
  146. if Utils.getFBItemBg() == "1" && configModeFB == MODE_VERTICAL_FLOATING_BUTTON {
  147. scrollView.layer.borderWidth = 1.0
  148. scrollView.layer.borderColor = UIColor.white.cgColor
  149. scrollView.layer.cornerRadius = 8.0
  150. scrollView.layer.masksToBounds = true
  151. scrollView.backgroundColor = .black.withAlphaComponent(0.25)
  152. }
  153. addSubview(scrollView)
  154. if configModeFB == MODE_VERTICAL_SIDE_TAB {
  155. scrollView.backgroundColor = UIColor.white.withAlphaComponent(0.8)
  156. scrollView.layer.borderColor = UIColor.gray.cgColor
  157. scrollView.layer.borderWidth = 0.2
  158. scrollView.layer.cornerRadius = 5.0
  159. scrollView.layer.masksToBounds = true
  160. scrollView.leftAnchor.constraint(equalTo: nexilis_button.rightAnchor).isActive = true
  161. scrollView.centerYAnchor.constraint(equalTo: nexilis_button.centerYAnchor).isActive = true
  162. scrollView.widthAnchor.constraint(equalToConstant: widthVerticalSideTab).isActive = true
  163. scrollView.heightAnchor.constraint(equalToConstant: heightVerticalSideTab).isActive = true
  164. } else if configModeFB != MODE_HORIZONTAL_SIDE_TAB {
  165. scrollView.topAnchor.constraint(equalTo: topAnchor).isActive = true
  166. if configModeFB == MODE_VERTICAL_ANIMATION {
  167. scrollView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
  168. scrollView.leftAnchor.constraint(equalTo: nexilis_button.rightAnchor, constant: -20).isActive = true
  169. scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
  170. scrollView.isHidden = true
  171. } else if configModeFB == MODE_HORIZONTAL_ANIMATION {
  172. scrollView.bottomAnchor.constraint(equalTo: nexilis_button.topAnchor).isActive = true
  173. scrollView.leftAnchor.constraint(equalTo: nexilis_button.leftAnchor).isActive = true
  174. scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB * (countMenuFB - 1)).isActive = true
  175. } else {
  176. scrollView.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB + 10).isActive = true
  177. scrollView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
  178. scrollView.bottomAnchor.constraint(equalTo: nexilis_button.topAnchor).isActive = true
  179. }
  180. } else {
  181. scrollView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - defaultWidthFB).isActive = true
  182. scrollView.heightAnchor.constraint(equalToConstant: defaultHeightFB).isActive = true
  183. scrollView.leftAnchor.constraint(equalTo: nexilis_button.rightAnchor).isActive = true
  184. scrollView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
  185. scrollView.backgroundColor = .black.withAlphaComponent(0.25)
  186. }
  187. groupView = UIStackView()
  188. groupView.translatesAutoresizingMaskIntoConstraints = false
  189. groupView.axis = (configModeFB == MODE_HORIZONTAL_SIDE_TAB || configModeFB == MODE_HORIZONTAL_ANIMATION) ? .horizontal : .vertical
  190. if configModeFB != MODE_HORIZONTAL_SIDE_TAB && configModeFB != MODE_HORIZONTAL_ANIMATION {
  191. groupView.distribution = .fillEqually
  192. }
  193. scrollView.addSubview(groupView)
  194. if configModeFB == MODE_VERTICAL_SIDE_TAB {
  195. groupView.spacing = 20.0
  196. groupView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 10).isActive = true
  197. groupView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -10).isActive = true
  198. groupView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
  199. } else if configModeFB == MODE_HORIZONTAL_SIDE_TAB {
  200. groupView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
  201. groupView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
  202. groupView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor).isActive = true
  203. groupView.heightAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
  204. } else {
  205. groupView.widthAnchor.constraint(equalToConstant: configModeFB == MODE_HORIZONTAL_ANIMATION ? defaultWidthHeightMenuFB * (countMenuFB - 1) : defaultWidthHeightMenuFB).isActive = true
  206. groupView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: configModeFB == MODE_HORIZONTAL_ANIMATION ? 0 : 5).isActive = true
  207. groupView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: configModeFB == MODE_HORIZONTAL_ANIMATION ? 0 : -5).isActive = true
  208. groupView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: configModeFB == MODE_HORIZONTAL_ANIMATION ? 0 : 6).isActive = true
  209. }
  210. pullButton()
  211. let center: NotificationCenter = NotificationCenter.default
  212. center.addObserver(self, selector: #selector(imageFBUpdate(notification:)), name: NSNotification.Name(rawValue: "imageFBUpdate"), object: nil)
  213. center.addObserver(self, selector: #selector(checkCounter), name: NSNotification.Name(rawValue: Nexilis.listenerReceiveChat), object: nil)
  214. center.addObserver(self, selector: #selector(checkCounter), name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil)
  215. let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hideButton))
  216. tapGesture.cancelsTouchesInView = false
  217. UIApplication.shared.windows.first?.rootViewController?.view.addGestureRecognizer(tapGesture)
  218. }
  219. @objc func handleTap(_ sender: UITapGestureRecognizer) {
  220. let location = sender.location(in: self)
  221. print("Tap location: \(location)")
  222. }
  223. public func setImageWithURL(_ isDocked: Bool) {
  224. if configModeFB != MODE_VERTICAL_FLOATING_BUTTON {
  225. return
  226. }
  227. var urlFb = Utils.getIconCenter()
  228. if isDocked {
  229. urlFb = Utils.getUrlDock() ?? ""
  230. }
  231. if urlFb.isEmpty {
  232. return
  233. }
  234. let task = URLSession.shared.dataTask(with: URL(string: (urlFb))!) { dataImage, response, error in
  235. if let error = error {
  236. print("Failed to load data: \(error)")
  237. return
  238. }
  239. DispatchQueue.main.async { [self] in
  240. if dataImage != nil && UIImage(data: dataImage!) != nil {
  241. if let image = UIImage(data: dataImage!) {
  242. nexilis_button.image = image
  243. } else {
  244. nexilis_button.image = UIImage(named: Utils.getFBIconBg() == "1" ? "pb_button" : "pb_ball", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
  245. }
  246. } else {
  247. nexilis_button.image = UIImage(named: Utils.getFBIconBg() == "1" ? "pb_button" : "pb_ball", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
  248. }
  249. }
  250. }
  251. task.resume()
  252. }
  253. private func checkDelayAnimation() {
  254. DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: { [self] in
  255. if !isShow {
  256. animationTimer.invalidate()
  257. animationTimer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(runAnimation), userInfo: nil, repeats: true)
  258. }
  259. })
  260. }
  261. @objc func runAnimation(){
  262. DispatchQueue.main.async { [self] in
  263. if configAnim == 0 || configAnim == 1 {
  264. if (lastRunAnimationHrz == -1 && frame.origin.x >= 0) || lastRunAnimationHrz == 1 && frame.origin.x <= UIScreen.main.bounds.width - defaultWidthFB {
  265. if lastRunAnimationHrz == -1 {
  266. frame.origin.x-=0.1
  267. } else {
  268. frame.origin.x+=0.1
  269. }
  270. } else {
  271. lastRunAnimationHrz = lastRunAnimationHrz == 1 ? -1 : 1
  272. if (lastRunAnimationHrz == -1 && configAnim == 1) || (lastRunAnimationHrz == 1 && configAnim == 0) {
  273. animationTimer.invalidate()
  274. if isLoopingAnim {
  275. checkDelayAnimation()
  276. }
  277. }
  278. }
  279. } else {
  280. if (lastRunAnimationVrt == -1 && frame.origin.y >= 0) || lastRunAnimationVrt == 1 && frame.origin.y <= UIScreen.main.bounds.height - defaultHeightFB {
  281. if lastRunAnimationVrt == -1 {
  282. frame.origin.y-=0.1
  283. } else {
  284. frame.origin.y+=0.1
  285. }
  286. } else {
  287. lastRunAnimationVrt = lastRunAnimationVrt == 1 ? -1 : 1
  288. if (lastRunAnimationVrt == -1 && configAnim == 3) || (lastRunAnimationVrt == 1 && configAnim == 2) {
  289. animationTimer.invalidate()
  290. if isLoopingAnim {
  291. checkDelayAnimation()
  292. }
  293. }
  294. }
  295. }
  296. }
  297. }
  298. private func pullButton() {
  299. if datePull == nil || Int(Date().timeIntervalSince(datePull!)) >= 60 {
  300. datePull = Date()
  301. } else if Int(Date().timeIntervalSince(datePull!)) < 60 {
  302. return
  303. }
  304. if groupView.subviews.count == 0 {
  305. getDefaultButton()
  306. }
  307. DispatchQueue.global().async { [self] in
  308. if !Utils.getCustomButtons().isEmpty && configModeFB != MODE_HORIZONTAL_SIDE_TAB && configModeFB != MODE_HORIZONTAL_ANIMATION && configModeFB != MODE_VERTICAL_SIDE_TAB && Nexilis.fromMAB {
  309. DispatchQueue.main.async { [self] in
  310. groupView.subviews.forEach({ $0.removeFromSuperview() })
  311. let customButtons = Utils.getCustomButtons().components(separatedBy: ",")
  312. let customIcons = Utils.getCustomFBIcon().components(separatedBy: ",")
  313. countMenuFB = CGFloat(customButtons.count > 5 ? 5 : customButtons.count)
  314. for i in 0..<customButtons.count {
  315. let package_id = customButtons[i]
  316. let app_id = ""
  317. let icon = customIcons[i]
  318. let newButton = UIButton()
  319. newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
  320. newButton.translatesAutoresizingMaskIntoConstraints = false
  321. if !APIS.checkAppStateisBackground() {
  322. DispatchQueue.global().async {
  323. let urlString = Utils.getURLBase() + "get_file_from_path?img=" + icon
  324. if let cachedImage = ImageCache.shared.image(forKey: urlString) {
  325. DispatchQueue.main.async() {
  326. newButton.setImage(cachedImage, for: .normal)
  327. }
  328. return
  329. }
  330. Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: urlString)!) { data, response, error in
  331. guard let data = data, error == nil else { return }
  332. // always update the UI from the main thread
  333. DispatchQueue.main.async() {
  334. if let image = UIImage(data: data) {
  335. newButton.setImage(image, for: .normal)
  336. ImageCache.shared.save(image: UIImage(data: data)!, forKey: urlString)
  337. }
  338. }
  339. }
  340. }
  341. }
  342. groupView.addArrangedSubview(newButton)
  343. newButton.restorationIdentifier = package_id
  344. newButton.accessibilityIdentifier = app_id
  345. newButton.addTarget(self, action: #selector(fbTap), for: .touchUpInside)
  346. let qmeraLongPress = UILongPressGestureRecognizer(target: self, action: #selector(qmeraLongPress(gestureRecognizer:)))
  347. newButton.addGestureRecognizer(qmeraLongPress)
  348. }
  349. }
  350. } else {
  351. if !Utils.getHistoryPullFB().isEmpty {
  352. setFBFromPull()
  353. }
  354. while Nexilis.isProcessWriteSync {
  355. Thread.sleep(forTimeInterval: 0.5)
  356. }
  357. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.pullFloatingButton(), timeout: 30 * 1000){
  358. if response.isOk() {
  359. Utils.setHistoryPullFB(value: response.getBody(key: CoreMessage_TMessageKey.DATA, default_value: ""))
  360. setFBFromPull()
  361. }
  362. }
  363. }
  364. }
  365. }
  366. private func setFBFromPull() {
  367. DispatchQueue.main.async {
  368. let data = Utils.getHistoryPullFB()
  369. if !data.isEmpty {
  370. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  371. DispatchQueue.main.async { [self] in
  372. let filteredData = jsonArray.filter({ $0["mode"] as? Int == Int(configModeFB) })
  373. if filteredData.count != 0 {
  374. groupView.subviews.forEach({ $0.removeFromSuperview() })
  375. countMenuFB = CGFloat(filteredData.count > 5 ? 5 : filteredData.count)
  376. for json in filteredData {
  377. let package_id = json["package_id"] as! String
  378. let app_id = (json["app_id"] as? String) ?? ""
  379. let icon = (json["icon"] as? String) ?? ""
  380. let mode = "\((json["mode"] as? Int) ?? 1)"
  381. let newButton = UIButton()
  382. if mode != configModeFB {
  383. continue
  384. }
  385. if mode == MODE_HORIZONTAL_SIDE_TAB {
  386. newButton.widthAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
  387. newButton.heightAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
  388. } else if mode == MODE_HORIZONTAL_ANIMATION {
  389. newButton.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
  390. newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
  391. } else if mode == MODE_VERTICAL_SIDE_TAB {
  392. newButton.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
  393. newButton.widthAnchor.constraint(equalToConstant: 25).isActive = true
  394. newButton.heightAnchor.constraint(equalToConstant: 25).isActive = true
  395. newButton.contentMode = .scaleAspectFill
  396. newButton.clipsToBounds = true
  397. } else {
  398. newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
  399. }
  400. newButton.translatesAutoresizingMaskIntoConstraints = false
  401. var indexTap = 0
  402. if package_id.contains("_fb"){
  403. let listSplit = package_id.split(separator: "_", maxSplits: 1)
  404. let idxFB = listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0
  405. let numIdx = listSplit[idxFB]
  406. indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count)) ?? 0
  407. }
  408. if indexTap == Nexilis.IDX_CHAT {
  409. newButton.setImage(UIImage(named: mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_chat" : 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)
  410. } else if indexTap == Nexilis.IDX_CONVERSATION {
  411. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_chat" : mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_conversation" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_conversation" : "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
  412. } else if indexTap == Nexilis.IDX_CALL {
  413. 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)
  414. } else if indexTap == Nexilis.IDX_CC {
  415. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_cc" : 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)
  416. } else if indexTap == Nexilis.IDX_STREAM {
  417. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_stream" : 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)
  418. } else if indexTap == Nexilis.IDX_SOCIAL_COMMERCE {
  419. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_commerce" : 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)
  420. } else if indexTap == Nexilis.IDX_NEWS {
  421. 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)
  422. } else if indexTap == Nexilis.IDX_POST {
  423. 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)
  424. } else if indexTap == Nexilis.IDX_NOTIF_CENTER {
  425. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_notif_center" : 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)
  426. } else {
  427. 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)
  428. }
  429. if !icon.isEmpty {
  430. if !APIS.checkAppStateisBackground() {
  431. DispatchQueue.global().async {
  432. let urlString = Utils.getURLBase() + "get_file_from_path?img=" + icon
  433. if let cachedImage = ImageCache.shared.image(forKey: urlString) {
  434. DispatchQueue.main.async() {
  435. newButton.setImage(cachedImage, for: .normal)
  436. }
  437. return
  438. }
  439. Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: urlString)!) { data, response, error in
  440. guard let data = data, error == nil else { return }
  441. // always update the UI from the main thread
  442. DispatchQueue.main.async() {
  443. if let image = UIImage(data: data) {
  444. newButton.setImage(image, for: .normal)
  445. ImageCache.shared.save(image: UIImage(data: data)!, forKey: urlString)
  446. }
  447. }
  448. }
  449. }
  450. }
  451. }
  452. groupView.addArrangedSubview(newButton)
  453. newButton.restorationIdentifier = package_id
  454. newButton.accessibilityIdentifier = app_id
  455. newButton.addTarget(self, action: #selector(fbTap), for: .touchUpInside)
  456. let qmeraLongPress = UILongPressGestureRecognizer(target: self, action: #selector(qmeraLongPress(gestureRecognizer:)))
  457. newButton.addGestureRecognizer(qmeraLongPress)
  458. }
  459. }
  460. }
  461. }
  462. }
  463. }
  464. }
  465. func getDefaultButton() {
  466. let mode = configModeFB
  467. var data = [Nexilis.IDX_NOTIF_CENTER, Nexilis.IDX_CC, Nexilis.IDX_CONVERSATION, Nexilis.IDX_CALL, Nexilis.IDX_STREAM]
  468. if Nexilis.defaultFloatingButton.count > 0 {
  469. data = Nexilis.defaultFloatingButton
  470. }
  471. if mode == MODE_VERTICAL_SIDE_TAB {
  472. data = [Nexilis.IDX_NOTIF_CENTER, Nexilis.IDX_CC, Nexilis.IDX_CONVERSATION, Nexilis.IDX_STREAM, Nexilis.IDX_SOCIAL_COMMERCE]
  473. } else if mode == MODE_HORIZONTAL_ANIMATION {
  474. data = [Nexilis.IDX_NOTIF_CENTER, Nexilis.IDX_CC, Nexilis.IDX_CONVERSATION, Nexilis.IDX_SOCIAL_COMMERCE, Nexilis.IDX_STREAM]
  475. }
  476. countMenuFB = CGFloat(data.count > 5 ? 5 : data.count)
  477. for i in 0..<data.count {
  478. let newButton = UIButton()
  479. if mode == MODE_HORIZONTAL_SIDE_TAB {
  480. newButton.widthAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
  481. newButton.heightAnchor.constraint(equalToConstant: defaultHeightFB - 10).isActive = true
  482. } else if mode == MODE_HORIZONTAL_ANIMATION {
  483. newButton.widthAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
  484. newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
  485. } else if mode == MODE_VERTICAL_SIDE_TAB {
  486. newButton.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
  487. newButton.widthAnchor.constraint(equalToConstant: 25).isActive = true
  488. newButton.heightAnchor.constraint(equalToConstant: 25).isActive = true
  489. newButton.contentMode = .scaleAspectFill
  490. newButton.clipsToBounds = true
  491. } else {
  492. newButton.heightAnchor.constraint(equalToConstant: defaultWidthHeightMenuFB).isActive = true
  493. }
  494. newButton.translatesAutoresizingMaskIntoConstraints = false
  495. let indexTap = data[i]
  496. if indexTap == Nexilis.IDX_CHAT {
  497. 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)
  498. } else if indexTap == Nexilis.IDX_CONVERSATION {
  499. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_chat" : mode == MODE_HORIZONTAL_SIDE_TAB ? "pb_button_hrz_conversation" : mode == MODE_HORIZONTAL_ANIMATION ? "pb_button_hrz_anim_conversation" : "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
  500. } else if indexTap == Nexilis.IDX_CALL {
  501. 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)
  502. } else if indexTap == Nexilis.IDX_CC {
  503. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_cc" : 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)
  504. } else if indexTap == Nexilis.IDX_STREAM {
  505. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_stream" : 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)
  506. } else if indexTap == Nexilis.IDX_SOCIAL_COMMERCE {
  507. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_commerce" : 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)
  508. } else if indexTap == Nexilis.IDX_NEWS {
  509. 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)
  510. } else if indexTap == Nexilis.IDX_POST {
  511. 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)
  512. } else if indexTap == Nexilis.IDX_NOTIF_CENTER {
  513. newButton.setImage(UIImage(named: mode == MODE_VERTICAL_SIDE_TAB ? "pb_button_vtcst_notif_center" : 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)
  514. if mode == MODE_VERTICAL_SIDE_TAB {
  515. newButton.imageView?.contentMode = .scaleAspectFit
  516. }
  517. } else {
  518. 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)
  519. }
  520. groupView.addArrangedSubview(newButton)
  521. newButton.restorationIdentifier = "default_fb\(data[i])"
  522. newButton.accessibilityIdentifier = ""
  523. newButton.addTarget(self, action: #selector(fbTap), for: .touchUpInside)
  524. let qmeraLongPress = UILongPressGestureRecognizer(target: self, action: #selector(qmeraLongPress(gestureRecognizer:)))
  525. newButton.addGestureRecognizer(qmeraLongPress)
  526. }
  527. }
  528. @objc func draggedView(_ sender:UIPanGestureRecognizer){
  529. let size = UIScreen.main.bounds
  530. let widthScreen = size.width
  531. let heightScreen = size.height
  532. let minimumx: CGFloat = configModeFB == MODE_HORIZONTAL_ANIMATION && isShow ? widthFBAnim + defaultWidthHeightMenuFB : configModeFB == MODE_VERTICAL_ANIMATION && isShow ? 60 : 40
  533. let maximumx = configModeFB == MODE_HORIZONTAL_ANIMATION && isShow ? widthScreen - widthFBAnim - defaultWidthHeightMenuFB : configModeFB == MODE_VERTICAL_ANIMATION && isShow ? widthScreen - 10 - defaultWidthHeightMenuFB : widthScreen - 40
  534. let maxMinXSideTab = isShow ? center.x : widthScreen + (center.x - widthScreen)
  535. let translation = sender.translation(in: self)
  536. var xPos = center.x + translation.x
  537. var yPos = center.y + translation.y
  538. bringSubviewToFront(self)
  539. if configModeFB == MODE_HORIZONTAL_SIDE_TAB || configModeFB == MODE_VERTICAL_SIDE_TAB {
  540. xPos = maxMinXSideTab
  541. } else {
  542. if (xPos < minimumx) {
  543. xPos = minimumx
  544. }
  545. if (xPos > maximumx) {
  546. xPos = maximumx
  547. }
  548. }
  549. if(isShow) {
  550. let minimumy = configModeFB == MODE_VERTICAL_SIDE_TAB ? heightVerticalSideTab - 100 : configModeFB == MODE_HORIZONTAL_SIDE_TAB ? 50 : configModeFB == MODE_HORIZONTAL_ANIMATION ? defaultWidthHeightMenuFB * 2 + 10 : configModeFB == MODE_VERTICAL_ANIMATION ? defaultHeightFB + defaultWidthHeightMenuFB : self.frame.size.height - 120 + ((5 - countMenuFB) * 25)
  551. let maximumy = configModeFB == MODE_VERTICAL_SIDE_TAB ? heightScreen - (heightVerticalSideTab - 100) : configModeFB == MODE_HORIZONTAL_SIDE_TAB ? heightScreen - 50 : configModeFB == MODE_HORIZONTAL_ANIMATION ? heightScreen - defaultWidthHeightMenuFB - 30 : configModeFB == MODE_VERTICAL_ANIMATION ? heightScreen - defaultHeightFB - 30 : heightScreen - 50
  552. if(yPos < minimumy) {
  553. yPos = minimumy
  554. }
  555. if(yPos > maximumy) {
  556. yPos = maximumy
  557. }
  558. } else {
  559. let minimumy: CGFloat = 50
  560. let maximumy = heightScreen - 50
  561. if(yPos < minimumy) {
  562. yPos = minimumy
  563. }
  564. if(yPos > maximumy) {
  565. yPos = maximumy
  566. }
  567. }
  568. center = CGPoint(x: xPos, y: yPos)
  569. sender.setTranslation(CGPoint.zero, in: self)
  570. if lastPosY != nil {
  571. lastPosY = nil
  572. }
  573. // SecureUserDefaults.shared.set(center.x, forKey: "xlastPosFB")
  574. // SecureUserDefaults.shared.set(center.y, forKey: "ylastPosFB")
  575. }
  576. @objc func imageFBUpdate(notification: NSNotification) {
  577. }
  578. @objc func checkCounter() {
  579. DispatchQueue.global().async { [self] in
  580. let counter = APIS.getTotalCounter()
  581. if counter > 0 {
  582. DispatchQueue.main.async { [self] in
  583. if button_fb2 != nil && !indicatorCounterFB.isDescendant(of: button_fb2) {
  584. button_fb2.addSubview(indicatorCounterFB)
  585. indicatorCounterFB.layer.cornerRadius = 7.5
  586. indicatorCounterFB.layer.masksToBounds = true
  587. indicatorCounterFB.backgroundColor = .systemRed
  588. indicatorCounterFB.anchor(top: button_fb2.topAnchor, left: button_fb2.leftAnchor, height: 15, minWidth: 15, maxWidth: 20)
  589. indicatorCounterFB.addSubview(labelCounterFB)
  590. labelCounterFB.anchor(left: indicatorCounterFB.leftAnchor, right: indicatorCounterFB.rightAnchor, paddingLeft: 5, paddingRight: 5, centerX: indicatorCounterFB.centerXAnchor, centerY: indicatorCounterFB.centerYAnchor)
  591. labelCounterFB.font = .systemFont(ofSize: 10)
  592. labelCounterFB.textColor = .white
  593. }
  594. if !indicatorCounterFBBig.isDescendant(of: nexilis_button){
  595. nexilis_button.addSubview(indicatorCounterFBBig)
  596. indicatorCounterFBBig.tintColor = .systemRed
  597. indicatorCounterFBBig.image = UIImage(systemName: "staroflife.circle.fill")
  598. indicatorCounterFBBig.anchor(top: nexilis_button.topAnchor, left: nexilis_button.leftAnchor, paddingTop: 5, paddingLeft: 5, width: 15, height: 15)
  599. }
  600. labelCounterFB.text = "\(counter)"
  601. }
  602. } else {
  603. DispatchQueue.main.async { [self] in
  604. if button_fb2 != nil && indicatorCounterFB.isDescendant(of: button_fb2) {
  605. indicatorCounterFB.removeFromSuperview()
  606. }
  607. if indicatorCounterFBBig.isDescendant(of: nexilis_button) {
  608. indicatorCounterFBBig.removeFromSuperview()
  609. }
  610. }
  611. }
  612. }
  613. }
  614. @objc func qmeraTap() {
  615. show(isShow: !isShow)
  616. }
  617. @objc func fbTap(_ sender: UIButton) {
  618. let package_id = sender.restorationIdentifier!
  619. var app_id = sender.accessibilityIdentifier!
  620. var indexTap = 0
  621. if package_id.contains("_fb"){
  622. let listSplit = package_id.split(separator: "_", maxSplits: 1)
  623. let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0]
  624. indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
  625. if listSplit.count == 2 {
  626. app_id = String(listSplit[1])
  627. }
  628. }
  629. Nexilis.buttonClicked(index: indexTap, id: app_id)
  630. hideButton()
  631. }
  632. @objc func qmeraLongPress(gestureRecognizer: UILongPressGestureRecognizer) {
  633. if gestureRecognizer.state == .began {
  634. if mySettingDelegate != nil {
  635. mySettingDelegate?.settingDelegate()
  636. } else {
  637. APIS.openSetting()
  638. }
  639. hideButton()
  640. }
  641. }
  642. @objc public func hideButton() {
  643. animationTimer.invalidate()
  644. if isShow {
  645. show(isShow: false)
  646. }
  647. if self.frame.origin.x < UIScreen.main.bounds.width / 2 - 30 {
  648. self.frame.origin.x = 0
  649. } else {
  650. self.frame.origin.x = UIScreen.main.bounds.width - defaultWidthFB
  651. }
  652. }
  653. public func show(isShow: Bool) {
  654. self.isShow = isShow
  655. if isShow {
  656. animationTimer.invalidate()
  657. pullButton()
  658. if indicatorCounterFBBig.isDescendant(of: nexilis_button) {
  659. indicatorCounterFBBig.isHidden = true
  660. }
  661. var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
  662. var width = frame.width
  663. var xPosition = frame.origin.x
  664. if configModeFB == MODE_VERTICAL_ANIMATION {
  665. height = CGFloat((defaultWidthHeightMenuFB * (countMenuFB - 2)) + defaultHeightFB - 5)
  666. width = frame.width + defaultWidthHeightMenuFB
  667. if xPosition > UIScreen.main.bounds.width - defaultWidthFB - defaultWidthHeightMenuFB {
  668. xPosition = UIScreen.main.bounds.width - defaultWidthFB - defaultWidthHeightMenuFB
  669. }
  670. scrollView.isHidden = false
  671. } else if configModeFB == MODE_HORIZONTAL_ANIMATION {
  672. height = defaultHeightFB + defaultWidthHeightMenuFB
  673. width = defaultWidthHeightMenuFB * (countMenuFB - 1)
  674. if xPosition > UIScreen.main.bounds.width - width {
  675. xPosition = UIScreen.main.bounds.width - width
  676. }
  677. }
  678. var yPosition = frame.origin.y - height + defaultHeightFB
  679. if yPosition <= 25 {
  680. lastPosY = frame.origin.y
  681. yPosition = 25
  682. }
  683. if configModeFB != MODE_HORIZONTAL_SIDE_TAB && configModeFB != MODE_VERTICAL_SIDE_TAB {
  684. frame = CGRect(x: xPosition, y: yPosition, width: width, height: height)
  685. } else {
  686. UIView.animate(withDuration: 0.5, animations: { [self] in
  687. var vst: CGFloat = 0.0
  688. if configModeFB == MODE_VERTICAL_SIDE_TAB {
  689. vst = UIScreen.main.bounds.width - defaultWidthFB - widthVerticalSideTab
  690. let size = UIScreen.main.bounds
  691. let heightScreen = size.height
  692. if frame.origin.y < 20 {
  693. frame.origin.y = 20
  694. } else if frame.origin.y > heightScreen - heightVerticalSideTab {
  695. frame.origin.y = heightScreen - heightVerticalSideTab
  696. }
  697. }
  698. frame.origin.x = 0 + vst
  699. })
  700. }
  701. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: { [self] in
  702. if isShow {
  703. let countSubviewsAfter = groupView.subviews.count
  704. if countSubviewsAfter > 5 {
  705. scrollView.flashScrollIndicators()
  706. }
  707. }
  708. })
  709. } else {
  710. if indicatorCounterFBBig.isDescendant(of: nexilis_button) {
  711. indicatorCounterFBBig.isHidden = false
  712. }
  713. var height = CGFloat((defaultWidthHeightMenuFB * countMenuFB) + defaultHeightFB + 5) //defaultWidthHeightMenuFB
  714. var width = defaultWidthFB
  715. if configModeFB == MODE_VERTICAL_ANIMATION {
  716. height = CGFloat((defaultWidthHeightMenuFB * 3) + defaultHeightFB - 5)
  717. scrollView.isHidden = true
  718. } else if configModeFB == MODE_HORIZONTAL_ANIMATION {
  719. height = defaultHeightFB + defaultWidthHeightMenuFB
  720. width = defaultWidthFB
  721. }
  722. var yPosition = frame.origin.y + height - defaultHeightFB
  723. if lastPosY != nil {
  724. yPosition = lastPosY!
  725. }
  726. if configModeFB != MODE_HORIZONTAL_SIDE_TAB && configModeFB != MODE_VERTICAL_SIDE_TAB {
  727. frame = CGRect(x: frame.origin.x, y: yPosition, width: width, height: defaultHeightFB)
  728. } else {
  729. UIView.animate(withDuration: 0.5, animations: { [self] in
  730. frame.origin.x = UIScreen.main.bounds.width - defaultWidthFB
  731. })
  732. }
  733. if configModeFB == MODE_VERTICAL_ANIMATION || configModeFB == MODE_HORIZONTAL_ANIMATION {
  734. checkDelayAnimation()
  735. }
  736. }
  737. }
  738. }
  739. public protocol SettingMABDelegate: AnyObject {
  740. func settingDelegate()
  741. }