react-native-orientation-director 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +19 -9
  2. package/android/src/main/java/com/orientationdirector/OrientationDirectorModule.kt +15 -0
  3. package/android/src/main/java/com/orientationdirector/implementation/OrientationAutoRotationObserver.kt +45 -0
  4. package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorImpl.kt +65 -19
  5. package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorUtilsImpl.kt +27 -25
  6. package/android/src/main/java/com/orientationdirector/implementation/OrientationEventManager.kt +8 -0
  7. package/android/src/oldarch/OrientationDirectorSpec.kt +3 -1
  8. package/ios/OrientationDirector.mm +22 -1
  9. package/ios/implementation/OrientationDirectorImpl.swift +95 -37
  10. package/ios/implementation/OrientationDirectorUtils.swift +38 -0
  11. package/ios/implementation/OrientationEventManager.swift +14 -0
  12. package/lib/commonjs/NativeOrientationDirector.js.map +1 -1
  13. package/lib/commonjs/RNOrientationDirector.js +17 -0
  14. package/lib/commonjs/RNOrientationDirector.js.map +1 -1
  15. package/lib/commonjs/hooks/useIsInterfaceOrientationLocked.hook.js +28 -0
  16. package/lib/commonjs/hooks/useIsInterfaceOrientationLocked.hook.js.map +1 -0
  17. package/lib/commonjs/index.js +14 -0
  18. package/lib/commonjs/index.js.map +1 -1
  19. package/lib/commonjs/types/AutoRotation.enum.js +13 -0
  20. package/lib/commonjs/types/AutoRotation.enum.js.map +1 -0
  21. package/lib/commonjs/types/Event.enum.js +1 -0
  22. package/lib/commonjs/types/Event.enum.js.map +1 -1
  23. package/lib/commonjs/types/LockedEvent.interface.js +2 -0
  24. package/lib/commonjs/types/LockedEvent.interface.js.map +1 -0
  25. package/lib/module/NativeOrientationDirector.js.map +1 -1
  26. package/lib/module/RNOrientationDirector.js +17 -0
  27. package/lib/module/RNOrientationDirector.js.map +1 -1
  28. package/lib/module/hooks/useIsInterfaceOrientationLocked.hook.js +21 -0
  29. package/lib/module/hooks/useIsInterfaceOrientationLocked.hook.js.map +1 -0
  30. package/lib/module/index.js +3 -0
  31. package/lib/module/index.js.map +1 -1
  32. package/lib/module/types/AutoRotation.enum.js +7 -0
  33. package/lib/module/types/AutoRotation.enum.js.map +1 -0
  34. package/lib/module/types/Event.enum.js +1 -0
  35. package/lib/module/types/Event.enum.js.map +1 -1
  36. package/lib/module/types/LockedEvent.interface.js +2 -0
  37. package/lib/module/types/LockedEvent.interface.js.map +1 -0
  38. package/lib/typescript/src/NativeOrientationDirector.d.ts +3 -0
  39. package/lib/typescript/src/NativeOrientationDirector.d.ts.map +1 -1
  40. package/lib/typescript/src/RNOrientationDirector.d.ts +6 -0
  41. package/lib/typescript/src/RNOrientationDirector.d.ts.map +1 -1
  42. package/lib/typescript/src/hooks/useIsInterfaceOrientationLocked.hook.d.ts +7 -0
  43. package/lib/typescript/src/hooks/useIsInterfaceOrientationLocked.hook.d.ts.map +1 -0
  44. package/lib/typescript/src/index.d.ts +3 -0
  45. package/lib/typescript/src/index.d.ts.map +1 -1
  46. package/lib/typescript/src/types/AutoRotation.enum.d.ts +6 -0
  47. package/lib/typescript/src/types/AutoRotation.enum.d.ts.map +1 -0
  48. package/lib/typescript/src/types/Event.enum.d.ts +2 -1
  49. package/lib/typescript/src/types/Event.enum.d.ts.map +1 -1
  50. package/lib/typescript/src/types/LockedEvent.interface.d.ts +4 -0
  51. package/lib/typescript/src/types/LockedEvent.interface.d.ts.map +1 -0
  52. package/package.json +1 -1
  53. package/src/NativeOrientationDirector.ts +3 -0
  54. package/src/RNOrientationDirector.ts +24 -0
  55. package/src/hooks/useIsInterfaceOrientationLocked.hook.ts +28 -0
  56. package/src/index.tsx +4 -0
  57. package/src/types/AutoRotation.enum.ts +5 -0
  58. package/src/types/Event.enum.ts +1 -0
  59. package/src/types/LockedEvent.interface.ts +3 -0
package/README.md CHANGED
@@ -1,14 +1,25 @@
1
+ ![NPM Version](https://img.shields.io/npm/v/react-native-orientation-director)
2
+
3
+ ---
4
+
1
5
  # react-native-orientation-director
2
6
 
3
7
  A simple library that allows you to handle orientation changes in your React Native app.
4
8
  Written in Kotlin, Swift and Typescript. It supports both the Old and New React Native architecture.
5
9
 
10
+ This library takes inspiration from and builds upon the following amazing alternatives:
11
+
12
+ 1. [react-native-orientation-locker](https://github.com/wonday/react-native-orientation-locker)
13
+ 2. [react-native-orientation-handler](https://github.com/KroosX4V/react-native-orientation-manager)
14
+
6
15
  ## Features
7
16
 
8
17
  - [x] Get the current orientation of the device
9
18
  - [x] Get the current orientation of the interface
19
+ - [x] Get the current interface orientation status (locked or unlocked)
10
20
  - [x] Listen to device orientation changes
11
21
  - [x] Listen to interface orientation changes
22
+ - [x] Listen to interface orientation status changes
12
23
  - [x] Lock the interface orientation to a specific orientation
13
24
  - [x] Unlock the interface orientation
14
25
 
@@ -23,7 +34,7 @@ npm install react-native-orientation-director
23
34
  yarn add react-native-orientation-director
24
35
  ```
25
36
 
26
- Don't forget to run pod-install
37
+ Don't forget to run pod-install.
27
38
 
28
39
  ## Setup
29
40
 
@@ -53,17 +64,20 @@ This library exports a class called: [RNOrientationDirector](https://github.com/
53
64
  | getDeviceOrientation | Returns the last device orientation |
54
65
  | lockTo | Locks the interface to a specific orientation |
55
66
  | unlock | Unlock the interface |
67
+ | isLocked | Returns the current interface orientation status (locked / unlocked) |
56
68
  | listenForDeviceOrientationChanges | Triggers a provided callback each time the device orientation changes |
57
69
  | listenForInterfaceOrientationChanges | Triggers a provided callback each time the interface orientation changes |
70
+ | listenForLockChanges | Triggers a provided callback each time the interface orientation status changes |
58
71
  | convertOrientationToHumanReadableString | Returns a human readable string based on the given orientation |
59
72
  | setLocalizedStringProvider | Sets the mapping needed to convert orientation values to human readable strings |
60
73
 
61
74
  In addition, the library exposes the following hooks:
62
75
 
63
- | Hook | Description |
64
- |-------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
65
- | [useInterfaceOrientation](https://github.com/gladiuscode/react-native-orientation-director/blob/main/src/hooks/useInterfaceOrientation.hook.ts) | Returns the current interface orientation and listens to changes |
66
- | [useDeviceOrientation](https://github.com/gladiuscode/react-native-orientation-director/blob/main/src/hooks/useDeviceOrientation.hook.ts) | Returns the current device orientation and listens to changes |
76
+ | Hook | Description |
77
+ |-----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
78
+ | [useInterfaceOrientation](https://github.com/gladiuscode/react-native-orientation-director/blob/main/src/hooks/useInterfaceOrientation.hook.ts) | Returns the current interface orientation and listens to changes |
79
+ | [useDeviceOrientation](https://github.com/gladiuscode/react-native-orientation-director/blob/main/src/hooks/useDeviceOrientation.hook.ts) | Returns the current device orientation and listens to changes |
80
+ | [useIsInterfaceOrientationLocked](https://github.com/gladiuscode/react-native-orientation-director/blob/main/src/hooks/useIsInterfaceOrientationLocked.hook.ts) | Returns the current interface orientation status and listens to changes |
67
81
 
68
82
  Head over to the [example project](example) to see how to use the library.
69
83
 
@@ -78,10 +92,6 @@ Head over to the [example project](example) to see how to use the library.
78
92
 
79
93
  See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
80
94
 
81
- ## License
82
-
83
- MIT
84
-
85
95
  ---
86
96
 
87
97
  Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
@@ -38,6 +38,21 @@ class OrientationDirectorModule internal constructor(context: ReactApplicationCo
38
38
  orientationDirectorImpl.unlock()
39
39
  }
40
40
 
41
+ @ReactMethod()
42
+ override fun resetSupportedInterfaceOrientations() {
43
+ orientationDirectorImpl.resetSupportedInterfaceOrientations()
44
+ }
45
+
46
+ @ReactMethod(isBlockingSynchronousMethod = true)
47
+ override fun isLocked(): Boolean {
48
+ return orientationDirectorImpl.getIsLocked()
49
+ }
50
+
51
+ @ReactMethod(isBlockingSynchronousMethod = true)
52
+ override fun isAutoRotationEnabled(): Boolean {
53
+ return orientationDirectorImpl.getIsAutoRotationEnabled()
54
+ }
55
+
41
56
  @ReactMethod()
42
57
  override fun addListener(eventName: String) {}
43
58
 
@@ -0,0 +1,45 @@
1
+ package com.orientationdirector.implementation
2
+
3
+ import android.database.ContentObserver
4
+ import android.os.Handler
5
+ import android.provider.Settings
6
+ import android.util.Log
7
+ import com.facebook.react.bridge.ReactContext
8
+
9
+ class OrientationAutoRotationObserver(val context: ReactContext, handler: Handler?) : ContentObserver(handler) {
10
+ private var lastAutoRotationStatus: Boolean = isAutoRotationEnabled()
11
+
12
+ fun getLastAutoRotationStatus(): Boolean {
13
+ return lastAutoRotationStatus
14
+ }
15
+
16
+ override fun onChange(selfChange: Boolean) {
17
+ super.onChange(selfChange)
18
+ val status = isAutoRotationEnabled()
19
+ lastAutoRotationStatus = status
20
+ }
21
+
22
+ fun enable() {
23
+ context.contentResolver.registerContentObserver(
24
+ Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION),
25
+ true,
26
+ this,
27
+ )
28
+ }
29
+
30
+ fun disable() {
31
+ context.contentResolver.unregisterContentObserver(this)
32
+ }
33
+
34
+ private fun isAutoRotationEnabled(): Boolean {
35
+ return try {
36
+ Settings.System.getInt(context.contentResolver, Settings.System.ACCELEROMETER_ROTATION) == 1;
37
+ } catch (ex: Settings.SettingNotFoundException) {
38
+ false
39
+ }
40
+ }
41
+
42
+ companion object {
43
+ const val NAME = "AutoRotationObserver"
44
+ }
45
+ }
@@ -1,17 +1,26 @@
1
1
  package com.orientationdirector.implementation
2
2
 
3
3
  import android.content.pm.ActivityInfo
4
+ import android.os.Handler
5
+ import android.os.Looper
4
6
  import com.facebook.react.bridge.ReactApplicationContext
5
7
 
6
8
  class OrientationDirectorImpl internal constructor(private val context: ReactApplicationContext) {
7
- private var mUtils = OrientationDirectorUtilsImpl()
9
+ private var mUtils = OrientationDirectorUtilsImpl(context)
8
10
  private var mEventEmitter = OrientationEventManager(context)
9
11
  private var mSensorListener = OrientationSensorListener(context)
12
+ private var mAutoRotationObserver = OrientationAutoRotationObserver(
13
+ context, Handler(
14
+ Looper.getMainLooper()
15
+ )
16
+ )
10
17
  private var mLifecycleListener = OrientationLifecycleListener()
11
- private var isLocked: Boolean = false
18
+
19
+ private var initialSupportedInterfaceOrientations = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
12
20
  private var lastInterfaceOrientation = Orientation.UNKNOWN
13
21
  private var lastDeviceOrientation = Orientation.UNKNOWN
14
22
  private var initialized = false
23
+ private var isLocked: Boolean = false
15
24
 
16
25
  init {
17
26
  mSensorListener.setOnOrientationChangedCallback { orientation ->
@@ -24,23 +33,32 @@ class OrientationDirectorImpl internal constructor(private val context: ReactApp
24
33
  mSensorListener.disable()
25
34
  }
26
35
 
36
+ mAutoRotationObserver.enable()
37
+
27
38
  context.addLifecycleEventListener(mLifecycleListener)
28
39
  mLifecycleListener.setOnHostResumeCallback {
29
40
  if (mSensorListener.canDetectOrientation()) {
30
41
  mSensorListener.enable()
31
42
  }
43
+
44
+ mAutoRotationObserver.enable()
32
45
  }
33
46
  mLifecycleListener.setOnHostPauseCallback {
34
47
  if (initialized) {
35
48
  mSensorListener.disable()
49
+ mAutoRotationObserver.disable()
36
50
  }
37
51
  }
38
52
  mLifecycleListener.setOnHostDestroyCallback {
39
53
  mSensorListener.disable()
54
+ mAutoRotationObserver.disable()
40
55
  }
41
56
 
57
+ initialSupportedInterfaceOrientations =
58
+ context.currentActivity?.requestedOrientation ?: initialSupportedInterfaceOrientations
42
59
  lastInterfaceOrientation = initInterfaceOrientation()
43
60
  lastDeviceOrientation = initDeviceOrientation()
61
+ isLocked = initIsLocked()
44
62
 
45
63
  initialized = true
46
64
  }
@@ -53,35 +71,39 @@ class OrientationDirectorImpl internal constructor(private val context: ReactApp
53
71
  return lastDeviceOrientation
54
72
  }
55
73
 
74
+ fun getIsLocked(): Boolean {
75
+ return isLocked
76
+ }
77
+
78
+ fun getIsAutoRotationEnabled(): Boolean {
79
+ return mAutoRotationObserver.getLastAutoRotationStatus()
80
+ }
81
+
56
82
  fun lockTo(jsOrientation: Int) {
57
- val interfaceOrientation = mUtils.getOrientationEnumFrom(jsOrientation)
83
+ val interfaceOrientation = mUtils.getOrientationFromJsOrientation(jsOrientation)
58
84
  val screenOrientation =
59
85
  mUtils.getActivityOrientationFrom(interfaceOrientation)
60
86
  context.currentActivity?.requestedOrientation = screenOrientation
61
87
  mEventEmitter.sendInterfaceOrientationDidChange(interfaceOrientation.ordinal)
62
88
  lastInterfaceOrientation = interfaceOrientation
63
- isLocked = true
89
+ updateIsLockedTo(true)
64
90
  }
65
91
 
66
92
  fun unlock() {
67
93
  context.currentActivity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
68
- isLocked = false
94
+ updateIsLockedTo(false)
69
95
  adaptInterfaceTo(getDeviceOrientation())
70
96
  }
71
97
 
72
- private fun initInterfaceOrientation(): Orientation {
73
- val activityOrientation = context.currentActivity!!.requestedOrientation
74
- if (
75
- mUtils.isActivityInPortraitOrientation(activityOrientation) ||
76
- mUtils.isActivityInLandscapeOrientation(activityOrientation)
77
- ) {
78
- return mUtils.getInterfaceOrientationFrom(activityOrientation)
79
- }
80
-
81
- val lastRotationDetected = mSensorListener.getLastRotationDetected()
82
- ?: return lastInterfaceOrientation
98
+ fun resetSupportedInterfaceOrientations() {
99
+ context.currentActivity?.requestedOrientation = initialSupportedInterfaceOrientations
100
+ updateIsLockedTo(initIsLocked())
101
+ updateLastInterfaceOrientationTo(initInterfaceOrientation())
102
+ }
83
103
 
84
- return mUtils.getDeviceOrientationFrom(lastRotationDetected)
104
+ private fun initInterfaceOrientation(): Orientation {
105
+ val rotation = mUtils.getInterfaceRotation()
106
+ return mUtils.getOrientationFromRotation(rotation)
85
107
  }
86
108
 
87
109
  private fun initDeviceOrientation(): Orientation {
@@ -91,6 +113,17 @@ class OrientationDirectorImpl internal constructor(private val context: ReactApp
91
113
  return mUtils.getDeviceOrientationFrom(lastRotationDetected)
92
114
  }
93
115
 
116
+ private fun initIsLocked(): Boolean {
117
+ val activity = context.currentActivity ?: return false
118
+ return listOf(
119
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
120
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
121
+ ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,
122
+ ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
123
+ ActivityInfo.SCREEN_ORIENTATION_LOCKED,
124
+ ).contains(activity.requestedOrientation)
125
+ }
126
+
94
127
  private fun onOrientationChanged(rawDeviceOrientation: Int) {
95
128
  val deviceOrientation = mUtils.getDeviceOrientationFrom(rawDeviceOrientation)
96
129
  mEventEmitter.sendDeviceOrientationDidChange(deviceOrientation.ordinal)
@@ -99,6 +132,10 @@ class OrientationDirectorImpl internal constructor(private val context: ReactApp
99
132
  }
100
133
 
101
134
  private fun adaptInterfaceTo(deviceOrientation: Orientation) {
135
+ if (!mAutoRotationObserver.getLastAutoRotationStatus()) {
136
+ return
137
+ }
138
+
102
139
  if (isLocked) {
103
140
  return
104
141
  }
@@ -107,8 +144,17 @@ class OrientationDirectorImpl internal constructor(private val context: ReactApp
107
144
  return
108
145
  }
109
146
 
110
- lastInterfaceOrientation = deviceOrientation
111
- mEventEmitter.sendInterfaceOrientationDidChange(lastInterfaceOrientation.ordinal)
147
+ updateLastInterfaceOrientationTo(deviceOrientation)
148
+ }
149
+
150
+ private fun updateIsLockedTo(value: Boolean) {
151
+ mEventEmitter.sendLockDidChange(value)
152
+ isLocked = value
153
+ }
154
+
155
+ private fun updateLastInterfaceOrientationTo(value: Orientation) {
156
+ lastInterfaceOrientation = value
157
+ mEventEmitter.sendInterfaceOrientationDidChange(value.ordinal)
112
158
  }
113
159
 
114
160
  companion object {
@@ -1,8 +1,24 @@
1
1
  package com.orientationdirector.implementation
2
2
 
3
+ import android.content.Context
3
4
  import android.content.pm.ActivityInfo
5
+ import android.os.Build
6
+ import android.provider.Settings
7
+ import android.view.Surface
8
+ import android.view.WindowManager
9
+ import com.facebook.react.bridge.ReactContext
4
10
 
5
- class OrientationDirectorUtilsImpl() {
11
+ class OrientationDirectorUtilsImpl(val context: ReactContext) {
12
+
13
+ fun getInterfaceRotation(): Int {
14
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
15
+ context.currentActivity?.display?.rotation ?: Surface.ROTATION_0
16
+ } else {
17
+ val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
18
+ @Suppress("DEPRECATION")
19
+ windowManager.defaultDisplay.rotation
20
+ }
21
+ }
6
22
 
7
23
  fun getDeviceOrientationFrom(rotation: Int): Orientation {
8
24
  var orientation = Orientation.UNKNOWN
@@ -22,29 +38,6 @@ class OrientationDirectorUtilsImpl() {
22
38
  return orientation
23
39
  }
24
40
 
25
- fun getInterfaceOrientationFrom(activityInfo: Int): Orientation {
26
- return when (activityInfo) {
27
- ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE -> Orientation.LANDSCAPE_RIGHT
28
- ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT -> Orientation.PORTRAIT_UPSIDE_DOWN
29
- ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE -> Orientation.LANDSCAPE_LEFT
30
- else -> Orientation.PORTRAIT
31
- };
32
- }
33
-
34
- fun isActivityInLandscapeOrientation(orientation: Int): Boolean {
35
- return listOf(
36
- ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
37
- ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
38
- ).contains(orientation);
39
- }
40
-
41
- fun isActivityInPortraitOrientation(orientation: Int): Boolean {
42
- return listOf(
43
- ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
44
- ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,
45
- ).contains(orientation);
46
- }
47
-
48
41
  fun getActivityOrientationFrom(interfaceOrientation: Orientation): Int {
49
42
  return when (interfaceOrientation) {
50
43
  Orientation.LANDSCAPE_RIGHT -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
@@ -54,7 +47,7 @@ class OrientationDirectorUtilsImpl() {
54
47
  }
55
48
  }
56
49
 
57
- fun getOrientationEnumFrom(jsOrientation: Int): Orientation {
50
+ fun getOrientationFromJsOrientation(jsOrientation: Int): Orientation {
58
51
  return when (jsOrientation) {
59
52
  2 -> Orientation.LANDSCAPE_RIGHT
60
53
  3 -> Orientation.PORTRAIT_UPSIDE_DOWN
@@ -62,4 +55,13 @@ class OrientationDirectorUtilsImpl() {
62
55
  else -> Orientation.PORTRAIT
63
56
  }
64
57
  }
58
+
59
+ fun getOrientationFromRotation(rotation: Int): Orientation {
60
+ return when(rotation) {
61
+ Surface.ROTATION_270 -> Orientation.LANDSCAPE_RIGHT
62
+ Surface.ROTATION_90 -> Orientation.LANDSCAPE_LEFT
63
+ Surface.ROTATION_180 -> Orientation.PORTRAIT_UPSIDE_DOWN
64
+ else -> Orientation.PORTRAIT
65
+ }
66
+ }
65
67
  }
@@ -9,6 +9,7 @@ import com.facebook.react.modules.core.DeviceEventManagerModule
9
9
  enum class Event {
10
10
  DeviceOrientationDidChange,
11
11
  InterfaceOrientationDidChange,
12
+ LockDidChange,
12
13
  }
13
14
 
14
15
  class OrientationEventManager(private val context: ReactApplicationContext) {
@@ -27,6 +28,13 @@ class OrientationEventManager(private val context: ReactApplicationContext) {
27
28
  sendEvent(Event.InterfaceOrientationDidChange, params)
28
29
  }
29
30
 
31
+ fun sendLockDidChange(value: Boolean) {
32
+ val params = Arguments.createMap().apply {
33
+ putBoolean("locked", value)
34
+ }
35
+ sendEvent(Event.LockDidChange, params)
36
+ }
37
+
30
38
  private fun sendEvent(eventName: Event, params: WritableMap?) {
31
39
  Log.d(NAME, "sendEvent - $eventName")
32
40
  Log.d(NAME, "sendEvent - $params")
@@ -6,11 +6,13 @@ import com.facebook.react.bridge.Promise
6
6
 
7
7
  abstract class OrientationDirectorSpec internal constructor(context: ReactApplicationContext) :
8
8
  ReactContextBaseJavaModule(context) {
9
-
10
9
  abstract fun getInterfaceOrientation(promise: Promise)
11
10
  abstract fun getDeviceOrientation(promise: Promise)
12
11
  abstract fun lockTo(orientation: Double)
13
12
  abstract fun unlock()
13
+ abstract fun resetSupportedInterfaceOrientations()
14
+ abstract fun isLocked(): Boolean
15
+ abstract fun isAutoRotationEnabled(): Boolean
14
16
  abstract fun addListener(eventName: String)
15
17
  abstract fun removeListeners(count: Double)
16
18
  }
@@ -64,7 +64,7 @@ RCT_EXPORT_MODULE()
64
64
 
65
65
  + (UIInterfaceOrientationMask)getSupportedInterfaceOrientationsForWindow
66
66
  {
67
- return [_director supportedInterfaceOrientation];
67
+ return [_director supportedInterfaceOrientations];
68
68
  }
69
69
 
70
70
  #ifdef RCT_NEW_ARCH_ENABLED
@@ -114,6 +114,27 @@ RCT_EXPORT_METHOD(unlock)
114
114
  });
115
115
  }
116
116
 
117
+ #ifdef RCT_NEW_ARCH_ENABLED
118
+ - (NSNumber *)isLocked
119
+ #else
120
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isLocked)
121
+ #endif
122
+ {
123
+ return @([_director isLocked]);
124
+ }
125
+
126
+ #ifdef RCT_NEW_ARCH_ENABLED
127
+ - (void)resetSupportedInterfaceOrientations
128
+ #else
129
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(resetSupportedInterfaceOrientations)
130
+ #endif
131
+ {
132
+ dispatch_async(dispatch_get_main_queue(), ^{
133
+ [_director resetSupportedInterfaceOrientations];
134
+ });
135
+ }
136
+
137
+
117
138
  // Don't compile this code when we build for the old architecture.
118
139
  #ifdef RCT_NEW_ARCH_ENABLED
119
140
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
@@ -12,19 +12,24 @@ import UIKit
12
12
  private static let TAG = "OrientationDirectorImpl"
13
13
  private let sensorListener: OrientationSensorListener
14
14
  private let eventManager: OrientationEventManager
15
- private var isLocked: Bool = false
16
- private var lastInterfaceOrientation: Orientation = Orientation.UNKNOWN
17
- private var lastDeviceOrientation: Orientation = Orientation.UNKNOWN
15
+ private var initialSupportedInterfaceOrientations: UIInterfaceOrientationMask = UIInterfaceOrientationMask.all
16
+ private var lastInterfaceOrientation = Orientation.UNKNOWN
17
+ private var lastDeviceOrientation = Orientation.UNKNOWN
18
18
 
19
- @objc public var supportedInterfaceOrientation: UIInterfaceOrientationMask = UIInterfaceOrientationMask.all
19
+ @objc public var supportedInterfaceOrientations: UIInterfaceOrientationMask = UIInterfaceOrientationMask.all
20
+ @objc public var isLocked = false
20
21
 
21
22
  @objc public override init() {
22
23
  eventManager = OrientationEventManager()
23
24
  sensorListener = OrientationSensorListener()
24
25
  super.init()
25
26
  sensorListener.setOnOrientationChanged(callback: self.onOrientationChanged)
27
+ initialSupportedInterfaceOrientations = initInitialSupportedInterfaceOrientations()
26
28
  lastInterfaceOrientation = initInterfaceOrientation()
27
29
  lastDeviceOrientation = initDeviceOrientation()
30
+ isLocked = initIsLocked()
31
+
32
+ supportedInterfaceOrientations = initialSupportedInterfaceOrientations
28
33
  }
29
34
 
30
35
  ///////////////////////////////////////////////////////////////////////////////////////
@@ -51,17 +56,50 @@ import UIKit
51
56
 
52
57
  eventManager.sendInterfaceOrientationDidChange(orientationValue: orientation.rawValue)
53
58
  lastInterfaceOrientation = orientation
54
- isLocked = true
59
+ updateIsLockedTo(value: true)
55
60
  }
56
61
 
57
62
  @objc public func unlock() {
58
63
  self.requestInterfaceUpdateTo(mask: UIInterfaceOrientationMask.all)
59
64
 
60
65
  let deviceOrientation = OrientationDirectorUtils.getOrientationFrom(deviceOrientation: UIDevice.current.orientation)
61
- isLocked = false
66
+ updateIsLockedTo(value: false)
62
67
  self.adaptInterfaceTo(deviceOrientation: deviceOrientation)
63
68
  }
64
69
 
70
+ @objc public func resetSupportedInterfaceOrientations() {
71
+ self.supportedInterfaceOrientations = self.initialSupportedInterfaceOrientations
72
+ self.requestInterfaceUpdateTo(mask: self.supportedInterfaceOrientations)
73
+ self.updateIsLockedTo(value: self.initIsLocked())
74
+
75
+ let lastMask = OrientationDirectorUtils.getMaskFrom(orientation: lastInterfaceOrientation)
76
+ let isLastInterfaceOrientationAlreadySupported = self.supportedInterfaceOrientations.contains(lastMask)
77
+ if (isLastInterfaceOrientationAlreadySupported) {
78
+ return
79
+ }
80
+
81
+ let supportedInterfaceOrientations = OrientationDirectorUtils.readSupportedInterfaceOrientationsFromBundle()
82
+ if (supportedInterfaceOrientations.contains(UIInterfaceOrientationMask.portrait)) {
83
+ self.updateLastInterfaceOrientation(value: Orientation.PORTRAIT)
84
+ return
85
+ }
86
+ if (supportedInterfaceOrientations.contains(UIInterfaceOrientationMask.landscapeRight)) {
87
+ self.updateLastInterfaceOrientation(value: Orientation.LANDSCAPE_LEFT)
88
+ return
89
+ }
90
+ if (supportedInterfaceOrientations.contains(UIInterfaceOrientationMask.landscapeLeft)) {
91
+ self.updateLastInterfaceOrientation(value: Orientation.LANDSCAPE_RIGHT)
92
+ return
93
+ }
94
+
95
+ self.updateLastInterfaceOrientation(value: Orientation.PORTRAIT_UPSIDE_DOWN)
96
+ }
97
+
98
+ private func initInitialSupportedInterfaceOrientations() -> UIInterfaceOrientationMask {
99
+ let supportedInterfaceOrientations = OrientationDirectorUtils.readSupportedInterfaceOrientationsFromBundle()
100
+ return supportedInterfaceOrientations.reduce(UIInterfaceOrientationMask()) { $0.union($1) }
101
+ }
102
+
65
103
  private func initInterfaceOrientation() -> Orientation {
66
104
  let interfaceOrientation = OrientationDirectorUtils.getInterfaceOrientation()
67
105
  return OrientationDirectorUtils.getOrientationFrom(uiInterfaceOrientation: interfaceOrientation)
@@ -71,32 +109,37 @@ import UIKit
71
109
  return OrientationDirectorUtils.getOrientationFrom(deviceOrientation: UIDevice.current.orientation)
72
110
  }
73
111
 
112
+ private func initIsLocked() -> Bool {
113
+ let supportedOrientations = OrientationDirectorUtils.readSupportedInterfaceOrientationsFromBundle()
114
+ if (supportedOrientations.count > 1) {
115
+ return false
116
+ }
117
+
118
+ return supportedOrientations.first != UIInterfaceOrientationMask.all
119
+ }
120
+
74
121
  private func requestInterfaceUpdateTo(mask: UIInterfaceOrientationMask) {
75
- self.supportedInterfaceOrientation = mask
76
-
77
- DispatchQueue.main.async {
78
- if #available(iOS 16.0, *) {
79
- guard let window = OrientationDirectorUtils.getCurrentWindow() else {
80
- return
81
- }
82
-
83
- guard let rootViewController = window.rootViewController else {
84
- return
85
- }
86
-
87
- guard let windowScene = window.windowScene else {
88
- return
89
- }
90
-
91
- rootViewController.setNeedsUpdateOfSupportedInterfaceOrientations()
92
-
93
- windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: mask)) { error in
94
- print("\(OrientationDirectorImpl.TAG) - requestGeometryUpdate error", error)
95
- }
96
- } else {
97
- UIDevice.current.setValue(mask.rawValue, forKey: "orientation")
98
- UIViewController.attemptRotationToDeviceOrientation()
122
+ self.supportedInterfaceOrientations = mask
123
+
124
+ if #available(iOS 16.0, *) {
125
+ let window = OrientationDirectorUtils.getCurrentWindow()
126
+
127
+ guard let rootViewController = window?.rootViewController else {
128
+ return
129
+ }
130
+
131
+ guard let windowScene = window?.windowScene else {
132
+ return
99
133
  }
134
+
135
+ rootViewController.setNeedsUpdateOfSupportedInterfaceOrientations()
136
+
137
+ windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: mask)) { error in
138
+ print("\(OrientationDirectorImpl.TAG) - requestGeometryUpdate error", error)
139
+ }
140
+ } else {
141
+ UIDevice.current.setValue(mask.rawValue, forKey: "orientation")
142
+ UIViewController.attemptRotationToDeviceOrientation()
100
143
  }
101
144
  }
102
145
 
@@ -109,18 +152,33 @@ import UIKit
109
152
 
110
153
  private func adaptInterfaceTo(deviceOrientation: Orientation) {
111
154
  if (isLocked) {
112
- return
155
+ return
113
156
  }
114
157
 
115
158
  if (lastInterfaceOrientation == deviceOrientation) {
116
- return
159
+ return
117
160
  }
118
-
161
+
119
162
  if (deviceOrientation == Orientation.FACE_UP || deviceOrientation == Orientation.FACE_DOWN) {
120
- return
163
+ return
121
164
  }
122
165
 
123
- self.eventManager.sendInterfaceOrientationDidChange(orientationValue: deviceOrientation.rawValue)
124
- lastInterfaceOrientation = deviceOrientation
125
- }
166
+ let deviceOrientationMask = OrientationDirectorUtils.getMaskFrom(orientation: deviceOrientation)
167
+ let isDeviceOrientationMaskSupported = self.supportedInterfaceOrientations.contains(deviceOrientationMask)
168
+ if (!isDeviceOrientationMaskSupported) {
169
+ return
170
+ }
171
+
172
+ updateLastInterfaceOrientation(value: deviceOrientation)
173
+ }
174
+
175
+ private func updateIsLockedTo(value: Bool) {
176
+ eventManager.sendLockDidChange(value: value)
177
+ isLocked = value
178
+ }
179
+
180
+ private func updateLastInterfaceOrientation(value: Orientation) {
181
+ self.eventManager.sendInterfaceOrientationDidChange(orientationValue: value.rawValue)
182
+ lastInterfaceOrientation = value
183
+ }
126
184
  }