Skip to content

Commit

Permalink
5 refactor (#6)
Browse files Browse the repository at this point in the history
* refactor: extension

* refactor: withLock
  • Loading branch information
duguyihou authored Mar 17, 2024
1 parent 7e45170 commit ec21dc7
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 96 deletions.
157 changes: 61 additions & 96 deletions ios/NeoOrientation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,36 @@ class NeoOrientation: RCTEventEmitter {
}
private var lastOrientation: UIInterfaceOrientation?
private var lastDeviceOrientation: UIDeviceOrientation?
private var isLocking = false
private let lock: os_unfair_lock_t = .allocate(capacity: 1)
private static var orientationMask: UIInterfaceOrientationMask = .all

private var deviceOrientation: UIDeviceOrientation {
return UIDevice.current.orientation
}

private var orientation: UIInterfaceOrientation? {
private var orientation: UIInterfaceOrientation {
let windowScene = UIApplication.shared.windows.first?.windowScene
let orientation = windowScene?.interfaceOrientation
let orientation = windowScene?.interfaceOrientation ?? .unknown
return orientation
}

private func setOrientation(_ orientationMask: UIInterfaceOrientationMask) {
NeoOrientation.orientationMask = orientationMask
}

@objc
static func getOrientation() -> UIInterfaceOrientationMask {
return orientationMask
}

override func supportedEvents() -> [String] {
return [
Constants.orientationDidChange,
Constants.deviceOrientationDidChange,
Constants.lockDidChange
]
}

override init() {
super.init()
lastOrientation = orientation
Expand All @@ -49,94 +49,86 @@ class NeoOrientation: RCTEventEmitter {
object: nil)
addListener(Constants.orientationDidChange)
}

deinit {
NotificationCenter.default.removeObserver(self)
removeListeners(1)
}


@objc
func getOrientation(callback: @escaping RCTResponseSenderBlock) {
OperationQueue.main.addOperation { [self] in
let orientationStr = getOrientationStr(orientation)
callback([orientationStr])
callback([orientation.toString])
}
}

@objc
func getDeviceOrientation(callback: @escaping RCTResponseSenderBlock) {
OperationQueue.main.addOperation { [self] in
let deviceOrientationStr = getDeviceOrientationStr(deviceOrientation)
callback([deviceOrientationStr])
callback([deviceOrientation.toString])
}
}

@objc
func lockToPortrait() {
OperationQueue.main.addOperation { [self] in
lockToOrientation(.portrait, withMask: .portrait)
}
}

@objc
func lockToPortraitUpsideDown() {
OperationQueue.main.addOperation { [self] in
lockToOrientation(.portraitUpsideDown, withMask: .portraitUpsideDown)
}
}

@objc
func lockToLandscape() {
OperationQueue.main.addOperation { [self] in
isLocking = true
let orientationStr = getOrientationStr(orientation)

UIDevice.current.setValue(UIInterfaceOrientation.unknown.rawValue, forKey: "orientation")

if orientationStr == "landscapeRight" {

setOrientation(.landscape)
UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
} else {
withLock {
OperationQueue.main.addOperation { [self] in
UIDevice.current.setValue(UIInterfaceOrientation.unknown.rawValue,
forKey: "orientation")

let landscape = orientation == .landscapeRight ? UIInterfaceOrientation.landscapeLeft.rawValue : UIInterfaceOrientation.landscapeRight.rawValue
setOrientation(.landscape)
UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
UIDevice.current.setValue(landscape, forKey: "orientation")

UIViewController.attemptRotationToDeviceOrientation()
sendEvent(withName: Constants.lockDidChange,
body: ["orientation": "landscapeLeft"])
}

UIDevice.current.setValue(lastDeviceOrientation, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
sendEvent(withName: Constants.lockDidChange,
body: ["orientation": "landscapeLeft"])
isLocking = false

}
}

@objc
func lockToLandscapeRight() {
OperationQueue.main.addOperation { [self] in
lockToOrientation(.landscapeLeft, withMask: .landscapeLeft)
}
}

@objc
func lockToLandscapeLeft() {
OperationQueue.main.addOperation { [self] in
lockToOrientation(.landscapeRight, withMask: .landscapeRight)
}
}

@objc
func unlockAllOrientations() {
OperationQueue.main.addOperation { [self] in
lockToOrientation(.unknown, withMask: .all)
}
}

@objc
override func constantsToExport() -> [AnyHashable : Any]! {
return ["initialOrientation": getOrientationStr(orientation)]
return ["initialOrientation": orientation.toString]
}

override class func requiresMainQueueSetup() -> Bool {
return true
}
Expand All @@ -146,68 +138,41 @@ extension NeoOrientation {
@objc
private func deviceOrientationDidChange() {
guard deviceOrientation != .unknown else { return }

if orientation != .unknown && orientation != lastOrientation {
sendEvent(withName: Constants.orientationDidChange,
body: ["orientation" : getOrientationStr(orientation)])
body: ["orientation" : orientation.toString])
lastOrientation = orientation
}

if !isLocking && deviceOrientation != lastDeviceOrientation {
if deviceOrientation != lastDeviceOrientation {
sendEvent(withName: Constants.deviceOrientationDidChange,
body: ["orientation": getDeviceOrientationStr(deviceOrientation)])
body: ["orientation": deviceOrientation.toString])
lastDeviceOrientation = deviceOrientation
}
}
private func lockToOrientation(_ newOrientation: UIInterfaceOrientation, withMask mask: UIInterfaceOrientationMask) {
isLocking = true
setOrientation(mask)
let currentDevice = UIDevice.current
currentDevice.setValue(newOrientation, forKey: "orientation")

if #available(iOS 16.0, *) {
let windowScene = UIApplication.shared.connectedScenes.first as! UIWindowScene
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: mask))
windowScene.keyWindow?.rootViewController?.setNeedsUpdateOfSupportedInterfaceOrientations()
} else {
UIViewController.attemptRotationToDeviceOrientation()
}
sendEvent(withName: Constants.lockDidChange,
body: ["orientation": getOrientationStr(newOrientation)])
isLocking = false
}

private func getOrientationStr(_ orientation: UIInterfaceOrientation?) -> String {
switch orientation {
case .portrait:
return "portrait"
case .landscapeLeft:
return "landscapeLeft"
case .landscapeRight:
return "landscapeRight"
case .portraitUpsideDown:
return "portraitUpsideDown"
default:
return "unknown"
withLock {
setOrientation(mask)
let currentDevice = UIDevice.current
currentDevice.setValue(newOrientation, forKey: "orientation")

if #available(iOS 16.0, *) {
let windowScene = UIApplication.shared.connectedScenes.first as! UIWindowScene
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: mask))
windowScene.keyWindow?.rootViewController?.setNeedsUpdateOfSupportedInterfaceOrientations()
} else {
UIViewController.attemptRotationToDeviceOrientation()
}
sendEvent(withName: Constants.lockDidChange,
body: ["orientation": newOrientation.toString])
}
}

private func getDeviceOrientationStr(_ orientation: UIDeviceOrientation?) -> String {
switch orientation {
case .portrait:
return "portrait"
case .landscapeLeft:
return "landscapeLeft"
case .landscapeRight:
return "landscapeRight"
case .portraitUpsideDown:
return "portraitUpsideDown"
case .faceUp:
return "faceUp"
case .faceDown:
return "faceDown"
default:
return "unknown"
}

private func withLock<T>(_ closure: () -> T) -> T {
os_unfair_lock_lock(lock)
defer { os_unfair_lock_unlock(lock) }
return closure()
}
}

20 changes: 20 additions & 0 deletions ios/UIDeviceOrientation+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
extension UIDeviceOrientation {
var toString: String {
switch self {
case .portrait:
return "portrait"
case .landscapeLeft:
return "landscapeLeft"
case .landscapeRight:
return "landscapeRight"
case .portraitUpsideDown:
return "portraitUpsideDown"
case .faceUp:
return "faceUp"
case .faceDown:
return "faceDown"
default:
return "unknown"
}
}
}
16 changes: 16 additions & 0 deletions ios/UIInterfaceOrientation+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
extension UIInterfaceOrientation {
var toString: String {
switch self {
case .portrait:
return "portrait"
case .landscapeLeft:
return "landscapeLeft"
case .landscapeRight:
return "landscapeRight"
case .portraitUpsideDown:
return "portraitUpsideDown"
default:
return "unknown"
}
}
}

0 comments on commit ec21dc7

Please sign in to comment.