about summary refs log tree commit diff
path: root/modules/expo-bluesky-swiss-army/ios/Visibility/VisibilityViewManager.swift
diff options
context:
space:
mode:
Diffstat (limited to 'modules/expo-bluesky-swiss-army/ios/Visibility/VisibilityViewManager.swift')
-rw-r--r--modules/expo-bluesky-swiss-army/ios/Visibility/VisibilityViewManager.swift86
1 files changed, 86 insertions, 0 deletions
diff --git a/modules/expo-bluesky-swiss-army/ios/Visibility/VisibilityViewManager.swift b/modules/expo-bluesky-swiss-army/ios/Visibility/VisibilityViewManager.swift
new file mode 100644
index 000000000..ae8e16868
--- /dev/null
+++ b/modules/expo-bluesky-swiss-army/ios/Visibility/VisibilityViewManager.swift
@@ -0,0 +1,86 @@
+import Foundation
+
+class VisibilityViewManager {
+  static let shared = VisibilityViewManager()
+
+  private let views = NSHashTable<VisibilityView>(options: .weakMemory)
+  private var currentlyActiveView: VisibilityView?
+  private var screenHeight: CGFloat = UIScreen.main.bounds.height
+  private var prevCount = 0
+
+  func addView(_ view: VisibilityView) {
+    self.views.add(view)
+
+    if self.prevCount == 0 {
+      self.updateActiveView()
+    }
+    self.prevCount = self.views.count
+  }
+
+  func removeView(_ view: VisibilityView) {
+    self.views.remove(view)
+    self.prevCount = self.views.count
+  }
+
+  func updateActiveView() {
+    DispatchQueue.main.async {
+      var activeView: VisibilityView?
+
+      if self.views.count == 1 {
+        let view = self.views.allObjects[0]
+        if view.isViewableEnough() {
+          activeView = view
+        }
+      } else if self.views.count > 1 {
+        let views = self.views.allObjects
+        var mostVisibleView: VisibilityView?
+        var mostVisiblePosition: CGRect?
+
+        views.forEach { view in
+          if !view.isViewableEnough() {
+            return
+          }
+
+          guard let position = view.getPositionOnScreen() else {
+            return
+          }
+
+          if position.minY >= 150 {
+            if mostVisiblePosition == nil {
+              mostVisiblePosition = position
+            }
+
+            if let unwrapped = mostVisiblePosition,
+               position.minY <= unwrapped.minY {
+              mostVisibleView = view
+              mostVisiblePosition = position
+            }
+          }
+        }
+
+        activeView = mostVisibleView
+      }
+
+      if activeView == self.currentlyActiveView {
+        return
+      }
+
+      self.clearActiveView()
+      if let view = activeView {
+        self.setActiveView(view)
+      }
+    }
+  }
+
+  private func clearActiveView() {
+    if let currentlyActiveView = self.currentlyActiveView {
+      currentlyActiveView.setIsCurrentlyActive(isActive: false)
+      self.currentlyActiveView = nil
+    }
+  }
+
+  private func setActiveView(_ view: VisibilityView) {
+    view.setIsCurrentlyActive(isActive: true)
+    self.currentlyActiveView = view
+  }
+}