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.
- package/README.md +19 -9
- package/android/src/main/java/com/orientationdirector/OrientationDirectorModule.kt +15 -0
- package/android/src/main/java/com/orientationdirector/implementation/OrientationAutoRotationObserver.kt +45 -0
- package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorImpl.kt +65 -19
- package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorUtilsImpl.kt +27 -25
- package/android/src/main/java/com/orientationdirector/implementation/OrientationEventManager.kt +8 -0
- package/android/src/oldarch/OrientationDirectorSpec.kt +3 -1
- package/ios/OrientationDirector.mm +22 -1
- package/ios/implementation/OrientationDirectorImpl.swift +95 -37
- package/ios/implementation/OrientationDirectorUtils.swift +38 -0
- package/ios/implementation/OrientationEventManager.swift +14 -0
- package/lib/commonjs/NativeOrientationDirector.js.map +1 -1
- package/lib/commonjs/RNOrientationDirector.js +17 -0
- package/lib/commonjs/RNOrientationDirector.js.map +1 -1
- package/lib/commonjs/hooks/useIsInterfaceOrientationLocked.hook.js +28 -0
- package/lib/commonjs/hooks/useIsInterfaceOrientationLocked.hook.js.map +1 -0
- package/lib/commonjs/index.js +14 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types/AutoRotation.enum.js +13 -0
- package/lib/commonjs/types/AutoRotation.enum.js.map +1 -0
- package/lib/commonjs/types/Event.enum.js +1 -0
- package/lib/commonjs/types/Event.enum.js.map +1 -1
- package/lib/commonjs/types/LockedEvent.interface.js +2 -0
- package/lib/commonjs/types/LockedEvent.interface.js.map +1 -0
- package/lib/module/NativeOrientationDirector.js.map +1 -1
- package/lib/module/RNOrientationDirector.js +17 -0
- package/lib/module/RNOrientationDirector.js.map +1 -1
- package/lib/module/hooks/useIsInterfaceOrientationLocked.hook.js +21 -0
- package/lib/module/hooks/useIsInterfaceOrientationLocked.hook.js.map +1 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/AutoRotation.enum.js +7 -0
- package/lib/module/types/AutoRotation.enum.js.map +1 -0
- package/lib/module/types/Event.enum.js +1 -0
- package/lib/module/types/Event.enum.js.map +1 -1
- package/lib/module/types/LockedEvent.interface.js +2 -0
- package/lib/module/types/LockedEvent.interface.js.map +1 -0
- package/lib/typescript/src/NativeOrientationDirector.d.ts +3 -0
- package/lib/typescript/src/NativeOrientationDirector.d.ts.map +1 -1
- package/lib/typescript/src/RNOrientationDirector.d.ts +6 -0
- package/lib/typescript/src/RNOrientationDirector.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useIsInterfaceOrientationLocked.hook.d.ts +7 -0
- package/lib/typescript/src/hooks/useIsInterfaceOrientationLocked.hook.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types/AutoRotation.enum.d.ts +6 -0
- package/lib/typescript/src/types/AutoRotation.enum.d.ts.map +1 -0
- package/lib/typescript/src/types/Event.enum.d.ts +2 -1
- package/lib/typescript/src/types/Event.enum.d.ts.map +1 -1
- package/lib/typescript/src/types/LockedEvent.interface.d.ts +4 -0
- package/lib/typescript/src/types/LockedEvent.interface.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/NativeOrientationDirector.ts +3 -0
- package/src/RNOrientationDirector.ts +24 -0
- package/src/hooks/useIsInterfaceOrientationLocked.hook.ts +28 -0
- package/src/index.tsx +4 -0
- package/src/types/AutoRotation.enum.ts +5 -0
- package/src/types/Event.enum.ts +1 -0
- package/src/types/LockedEvent.interface.ts +3 -0
package/README.md
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
|
+

|
|
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
|
|
64
|
-
|
|
65
|
-
| [useInterfaceOrientation](https://github.com/gladiuscode/react-native-orientation-director/blob/main/src/hooks/useInterfaceOrientation.hook.ts)
|
|
66
|
-
| [useDeviceOrientation](https://github.com/gladiuscode/react-native-orientation-director/blob/main/src/hooks/useDeviceOrientation.hook.ts)
|
|
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
|
+
}
|
package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorImpl.kt
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
-
|
|
89
|
+
updateIsLockedTo(true)
|
|
64
90
|
}
|
|
65
91
|
|
|
66
92
|
fun unlock() {
|
|
67
93
|
context.currentActivity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
|
68
|
-
|
|
94
|
+
updateIsLockedTo(false)
|
|
69
95
|
adaptInterfaceTo(getDeviceOrientation())
|
|
70
96
|
}
|
|
71
97
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
111
|
-
|
|
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 {
|
package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorUtilsImpl.kt
CHANGED
|
@@ -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
|
|
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
|
}
|
package/android/src/main/java/com/orientationdirector/implementation/OrientationEventManager.kt
CHANGED
|
@@ -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
|
|
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
|
|
16
|
-
private var lastInterfaceOrientation
|
|
17
|
-
private var lastDeviceOrientation
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
155
|
+
return
|
|
113
156
|
}
|
|
114
157
|
|
|
115
158
|
if (lastInterfaceOrientation == deviceOrientation) {
|
|
116
|
-
|
|
159
|
+
return
|
|
117
160
|
}
|
|
118
|
-
|
|
161
|
+
|
|
119
162
|
if (deviceOrientation == Orientation.FACE_UP || deviceOrientation == Orientation.FACE_DOWN) {
|
|
120
|
-
|
|
163
|
+
return
|
|
121
164
|
}
|
|
122
165
|
|
|
123
|
-
|
|
124
|
-
|
|
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
|
}
|