mirror of
https://github.com/VibedByKaKi/t3-code-android-nightly.git
synced 2026-10-10 12:21:16 +02:00
Some checks are pending
CI / Lint (push) Waiting to run
CI / Typecheck (push) Waiting to run
CI / Build (push) Waiting to run
CI / Test (push) Waiting to run
CI / Test Web (push) Waiting to run
CI / Test Server 1 (push) Waiting to run
CI / Test Server 2 (push) Waiting to run
CI / Test Server 3 (push) Waiting to run
CI / Test Server 4 (push) Waiting to run
CI / Test Server 5 (push) Waiting to run
CI / Test Server 6 (push) Waiting to run
CI / Transfer report artifact (push) Blocked by required conditions
CI / Rust (push) Waiting to run
CI / Mobile Native Changes (push) Waiting to run
CI / Mobile Native Static Analysis (push) Blocked by required conditions
CI / Release Smoke (push) Waiting to run
CI / Check (push) Blocked by required conditions
Forward to Cursor hygiene / POST to Cursor (push) Waiting to run
Deploy T3 Connect relay / Deploy production relay (push) Waiting to run
Mobile EAS Production / EAS production (push) Waiting to run
95 lines
3.3 KiB
Swift
95 lines
3.3 KiB
Swift
import ExpoModulesCore
|
|
import UIKit
|
|
|
|
/// Reports geometry in the observing view's coordinate space, including system
|
|
/// reservations that safe-area rectangles cannot represent, such as the fold.
|
|
final class T3LayoutMetricsView: ExpoView {
|
|
let onMetricsChange = EventDispatcher()
|
|
private var lastMetrics: NSDictionary?
|
|
private var hasHinge: Bool? = false
|
|
|
|
required init(appContext: AppContext? = nil) {
|
|
super.init(appContext: appContext)
|
|
isUserInteractionEnabled = false
|
|
registerForTraitChanges([UITraitHorizontalSizeClass.self, UITraitVerticalSizeClass.self]) { (view: T3LayoutMetricsView, _: UITraitCollection) in
|
|
view.publishMetrics()
|
|
}
|
|
#if compiler(>=6.4)
|
|
if #available(iOS 27.1, *) {
|
|
hasHinge = nil
|
|
addInteraction(UIHingeInteraction { [weak self] _, update in
|
|
guard let self, self.window != nil else { return }
|
|
// Capability survives temporary detachment and does not follow the hinge angle.
|
|
let hasHinge = self.hasHinge == true || update.hinge != nil
|
|
guard self.hasHinge != hasHinge else { return }
|
|
self.hasHinge = hasHinge
|
|
self.publishMetrics()
|
|
})
|
|
registerForTraitChanges(UITraitCollection.systemTraitsAffectingVerticalBarEdge) { (view: T3LayoutMetricsView, _: UITraitCollection) in
|
|
view.publishMetrics()
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
override func didMoveToWindow() {
|
|
super.didMoveToWindow()
|
|
lastMetrics = nil
|
|
publishMetrics()
|
|
}
|
|
|
|
override func layoutSubviews() {
|
|
super.layoutSubviews()
|
|
publishMetrics()
|
|
}
|
|
|
|
override func safeAreaInsetsDidChange() {
|
|
super.safeAreaInsetsDidChange()
|
|
publishMetrics()
|
|
}
|
|
|
|
private func publishMetrics() {
|
|
guard let window, bounds.width > 0, bounds.height > 0, let hasHinge else { return }
|
|
if hasHinge {
|
|
T3WorkspaceOrientationSubscriber.allowHingeOrientations(in: window)
|
|
}
|
|
var verticalBarEdge = "none"
|
|
var regions: [[String: Any]] = []
|
|
#if compiler(>=6.4)
|
|
if #available(iOS 27.1, *) {
|
|
let rtl = effectiveUserInterfaceLayoutDirection == .rightToLeft
|
|
switch traitCollection.verticalBarEdge {
|
|
case .leading: verticalBarEdge = rtl ? "right" : "left"
|
|
case .trailing: verticalBarEdge = rtl ? "left" : "right"
|
|
default: break
|
|
}
|
|
for kind in [UIView.ReservedRegion.Kind.division, .occlusion] {
|
|
for region in reservedRegions(kind: kind) where region.isActive {
|
|
let frame = region.frame.intersection(bounds)
|
|
guard !frame.isNull, !frame.isEmpty else { continue }
|
|
regions.append([
|
|
"kind": kind == .division ? "division" : "occlusion",
|
|
"x": frame.minX, "y": frame.minY,
|
|
"width": frame.width, "height": frame.height,
|
|
])
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
let metrics: [String: Any] = [
|
|
"width": bounds.width, "height": bounds.height,
|
|
"hasHinge": hasHinge,
|
|
"horizontalSizeClass": traitCollection.horizontalSizeClass == .regular ? "regular" : "compact",
|
|
"verticalBarEdge": verticalBarEdge,
|
|
"safeArea": [
|
|
"top": safeAreaInsets.top, "bottom": safeAreaInsets.bottom,
|
|
"left": safeAreaInsets.left, "right": safeAreaInsets.right,
|
|
],
|
|
"reservedRegions": regions,
|
|
]
|
|
let next = metrics as NSDictionary
|
|
guard lastMetrics?.isEqual(next) != true else { return }
|
|
lastMetrics = next
|
|
onMetricsChange(metrics)
|
|
}
|
|
}
|