react-native-orientation-director 1.0.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/LICENSE +20 -0
- package/README.md +87 -0
- package/android/build.gradle +120 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/orientationdirector/OrientationDirectorModule.kt +50 -0
- package/android/src/main/java/com/orientationdirector/OrientationDirectorPackage.kt +35 -0
- package/android/src/main/java/com/orientationdirector/implementation/Orientation.kt +12 -0
- package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorImpl.kt +117 -0
- package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorUtilsImpl.kt +65 -0
- package/android/src/main/java/com/orientationdirector/implementation/OrientationEventManager.kt +42 -0
- package/android/src/main/java/com/orientationdirector/implementation/OrientationLifecycleListener.kt +33 -0
- package/android/src/main/java/com/orientationdirector/implementation/OrientationSensorListener.kt +26 -0
- package/android/src/newarch/OrientationDirectorSpec.kt +7 -0
- package/android/src/oldarch/OrientationDirectorSpec.kt +16 -0
- package/ios/OrientationDirector.h +22 -0
- package/ios/OrientationDirector.mm +121 -0
- package/ios/implementation/Orientation.swift +12 -0
- package/ios/implementation/OrientationDirectorImpl.swift +126 -0
- package/ios/implementation/OrientationDirectorUtils.swift +111 -0
- package/ios/implementation/OrientationEventManager.swift +56 -0
- package/ios/implementation/OrientationSensorListener.swift +37 -0
- package/ios/react-native-orientation-director-Bridging-Header.h +6 -0
- package/lib/commonjs/NativeOrientationDirector.js +9 -0
- package/lib/commonjs/NativeOrientationDirector.js.map +1 -0
- package/lib/commonjs/RNOrientationDirector.js +49 -0
- package/lib/commonjs/RNOrientationDirector.js.map +1 -0
- package/lib/commonjs/hooks/useDeviceOrientation.hook.js +39 -0
- package/lib/commonjs/hooks/useDeviceOrientation.hook.js.map +1 -0
- package/lib/commonjs/hooks/useInterfaceOrientation.hook.js +39 -0
- package/lib/commonjs/hooks/useInterfaceOrientation.hook.js.map +1 -0
- package/lib/commonjs/index.js +31 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/module.js +23 -0
- package/lib/commonjs/module.js.map +1 -0
- package/lib/commonjs/types/Event.enum.js +13 -0
- package/lib/commonjs/types/Event.enum.js.map +1 -0
- package/lib/commonjs/types/InterfaceOrientationToLocalizedStringProvider.type.js +6 -0
- package/lib/commonjs/types/InterfaceOrientationToLocalizedStringProvider.type.js.map +1 -0
- package/lib/commonjs/types/LockableOrientation.type.js +6 -0
- package/lib/commonjs/types/LockableOrientation.type.js.map +1 -0
- package/lib/commonjs/types/Orientation.enum.js +17 -0
- package/lib/commonjs/types/Orientation.enum.js.map +1 -0
- package/lib/commonjs/types/OrientationEvent.interface.js +6 -0
- package/lib/commonjs/types/OrientationEvent.interface.js.map +1 -0
- package/lib/module/NativeOrientationDirector.js +3 -0
- package/lib/module/NativeOrientationDirector.js.map +1 -0
- package/lib/module/RNOrientationDirector.js +40 -0
- package/lib/module/RNOrientationDirector.js.map +1 -0
- package/lib/module/hooks/useDeviceOrientation.hook.js +31 -0
- package/lib/module/hooks/useDeviceOrientation.hook.js.map +1 -0
- package/lib/module/hooks/useInterfaceOrientation.hook.js +31 -0
- package/lib/module/hooks/useInterfaceOrientation.hook.js.map +1 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/module.js +17 -0
- package/lib/module/module.js.map +1 -0
- package/lib/module/types/Event.enum.js +7 -0
- package/lib/module/types/Event.enum.js.map +1 -0
- package/lib/module/types/InterfaceOrientationToLocalizedStringProvider.type.js +2 -0
- package/lib/module/types/InterfaceOrientationToLocalizedStringProvider.type.js.map +1 -0
- package/lib/module/types/LockableOrientation.type.js +2 -0
- package/lib/module/types/LockableOrientation.type.js.map +1 -0
- package/lib/module/types/Orientation.enum.js +11 -0
- package/lib/module/types/Orientation.enum.js.map +1 -0
- package/lib/module/types/OrientationEvent.interface.js +2 -0
- package/lib/module/types/OrientationEvent.interface.js.map +1 -0
- package/lib/typescript/src/NativeOrientationDirector.d.ts +12 -0
- package/lib/typescript/src/NativeOrientationDirector.d.ts.map +1 -0
- package/lib/typescript/src/RNOrientationDirector.d.ts +17 -0
- package/lib/typescript/src/RNOrientationDirector.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useDeviceOrientation.hook.d.ts +8 -0
- package/lib/typescript/src/hooks/useDeviceOrientation.hook.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useInterfaceOrientation.hook.d.ts +8 -0
- package/lib/typescript/src/hooks/useInterfaceOrientation.hook.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +8 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/module.d.ts +6 -0
- package/lib/typescript/src/module.d.ts.map +1 -0
- package/lib/typescript/src/types/Event.enum.d.ts +6 -0
- package/lib/typescript/src/types/Event.enum.d.ts.map +1 -0
- package/lib/typescript/src/types/InterfaceOrientationToLocalizedStringProvider.type.d.ts +3 -0
- package/lib/typescript/src/types/InterfaceOrientationToLocalizedStringProvider.type.d.ts.map +1 -0
- package/lib/typescript/src/types/LockableOrientation.type.d.ts +3 -0
- package/lib/typescript/src/types/LockableOrientation.type.d.ts.map +1 -0
- package/lib/typescript/src/types/Orientation.enum.d.ts +10 -0
- package/lib/typescript/src/types/Orientation.enum.d.ts.map +1 -0
- package/lib/typescript/src/types/OrientationEvent.interface.d.ts +5 -0
- package/lib/typescript/src/types/OrientationEvent.interface.d.ts.map +1 -0
- package/package.json +178 -0
- package/react-native-orientation-director.podspec +41 -0
- package/src/NativeOrientationDirector.ts +14 -0
- package/src/RNOrientationDirector.ts +64 -0
- package/src/hooks/useDeviceOrientation.hook.ts +40 -0
- package/src/hooks/useInterfaceOrientation.hook.ts +40 -0
- package/src/index.tsx +10 -0
- package/src/module.ts +30 -0
- package/src/types/Event.enum.ts +6 -0
- package/src/types/InterfaceOrientationToLocalizedStringProvider.type.ts +6 -0
- package/src/types/LockableOrientation.type.ts +7 -0
- package/src/types/Orientation.enum.ts +11 -0
- package/src/types/OrientationEvent.interface.ts +5 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 gladius
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# react-native-orientation-director
|
|
2
|
+
|
|
3
|
+
A simple library that allows you to handle orientation changes in your React Native app.
|
|
4
|
+
Written in Kotlin, Swift and Typescript. It supports both the Old and New React Native architecture.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- [x] Get the current orientation of the device
|
|
9
|
+
- [x] Get the current orientation of the interface
|
|
10
|
+
- [x] Listen to device orientation changes
|
|
11
|
+
- [x] Listen to interface orientation changes
|
|
12
|
+
- [x] Lock the interface orientation to a specific orientation
|
|
13
|
+
- [x] Unlock the interface orientation
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
You can install the package via npm or yarn:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install react-native-orientation-director
|
|
21
|
+
```
|
|
22
|
+
```sh
|
|
23
|
+
yarn add react-native-orientation-director
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Don't forget to run pod-install
|
|
27
|
+
|
|
28
|
+
## Setup
|
|
29
|
+
|
|
30
|
+
To properly handle interface orientation changes in iOS, you need to update your AppDelegate.mm file.
|
|
31
|
+
In your AppDelegate.mm file, import "OrientationDirector.h" and implement supportedInterfaceOrientationsForWindow method as follows:
|
|
32
|
+
|
|
33
|
+
```objc
|
|
34
|
+
#import <OrientationDirector.h>
|
|
35
|
+
|
|
36
|
+
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
|
|
37
|
+
{
|
|
38
|
+
return [OrientationDirector getSupportedInterfaceOrientationsForWindow];
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
If you need help, you can check the example project.
|
|
43
|
+
|
|
44
|
+
There is no need to do anything in Android, it works out of the box.
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
This library exports a class called: [RNOrientationDirector](https://github.com/gladiuscode/react-native-orientation-director/blob/main/src/RNOrientationDirector.ts) that exposes the following methods:
|
|
49
|
+
|
|
50
|
+
| Method | Description |
|
|
51
|
+
|-----------------------------------------|---------------------------------------------------------------------------------|
|
|
52
|
+
| getInterfaceOrientation | Returns the last interface orientation |
|
|
53
|
+
| getDeviceOrientation | Returns the last device orientation |
|
|
54
|
+
| lockTo | Locks the interface to a specific orientation |
|
|
55
|
+
| unlock | Unlock the interface |
|
|
56
|
+
| listenForDeviceOrientationChanges | Triggers a provided callback each time the device orientation changes |
|
|
57
|
+
| listenForInterfaceOrientationChanges | Triggers a provided callback each time the interface orientation changes |
|
|
58
|
+
| convertOrientationToHumanReadableString | Returns a human readable string based on the given orientation |
|
|
59
|
+
| setLocalizedStringProvider | Sets the mapping needed to convert orientation values to human readable strings |
|
|
60
|
+
|
|
61
|
+
In addition, the library exposes the following hooks:
|
|
62
|
+
|
|
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 |
|
|
67
|
+
|
|
68
|
+
Head over to the [example project](example) to see how to use the library.
|
|
69
|
+
|
|
70
|
+
## Roadmap
|
|
71
|
+
|
|
72
|
+
- [ ] Add support for Expo
|
|
73
|
+
- [ ] Add JS side tests
|
|
74
|
+
- [ ] Add Android side tests
|
|
75
|
+
- [ ] Add iOS side tests
|
|
76
|
+
|
|
77
|
+
## Contributing
|
|
78
|
+
|
|
79
|
+
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
|
|
3
|
+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["OrientationDirector_kotlinVersion"]
|
|
4
|
+
|
|
5
|
+
repositories {
|
|
6
|
+
google()
|
|
7
|
+
mavenCentral()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
dependencies {
|
|
11
|
+
classpath "com.android.tools.build:gradle:7.2.1"
|
|
12
|
+
// noinspection DifferentKotlinGradleVersion
|
|
13
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def isNewArchitectureEnabled() {
|
|
18
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
apply plugin: "com.android.library"
|
|
22
|
+
apply plugin: "kotlin-android"
|
|
23
|
+
|
|
24
|
+
if (isNewArchitectureEnabled()) {
|
|
25
|
+
apply plugin: "com.facebook.react"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def getExtOrDefault(name) {
|
|
29
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["OrientationDirector_" + name]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
def getExtOrIntegerDefault(name) {
|
|
33
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["OrientationDirector_" + name]).toInteger()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
def supportsNamespace() {
|
|
37
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
38
|
+
def major = parsed[0].toInteger()
|
|
39
|
+
def minor = parsed[1].toInteger()
|
|
40
|
+
|
|
41
|
+
// Namespace support was added in 7.3.0
|
|
42
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
android {
|
|
46
|
+
if (supportsNamespace()) {
|
|
47
|
+
namespace "com.orientationdirector"
|
|
48
|
+
|
|
49
|
+
sourceSets {
|
|
50
|
+
main {
|
|
51
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
57
|
+
|
|
58
|
+
defaultConfig {
|
|
59
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
60
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
61
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
buildFeatures {
|
|
66
|
+
buildConfig true
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
buildTypes {
|
|
70
|
+
release {
|
|
71
|
+
minifyEnabled false
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
lintOptions {
|
|
76
|
+
disable "GradleCompatible"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
compileOptions {
|
|
80
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
81
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
sourceSets {
|
|
85
|
+
main {
|
|
86
|
+
if (isNewArchitectureEnabled()) {
|
|
87
|
+
java.srcDirs += [
|
|
88
|
+
"src/newarch",
|
|
89
|
+
// This is needed to build Kotlin project with NewArch enabled
|
|
90
|
+
"${project.buildDir}/generated/source/codegen/java"
|
|
91
|
+
]
|
|
92
|
+
} else {
|
|
93
|
+
java.srcDirs += ["src/oldarch"]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
repositories {
|
|
100
|
+
mavenCentral()
|
|
101
|
+
google()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
105
|
+
|
|
106
|
+
dependencies {
|
|
107
|
+
// For < 0.71, this will be from the local maven repo
|
|
108
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
109
|
+
//noinspection GradleDynamicVersion
|
|
110
|
+
implementation "com.facebook.react:react-native:+"
|
|
111
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (isNewArchitectureEnabled()) {
|
|
115
|
+
react {
|
|
116
|
+
jsRootDir = file("../src/")
|
|
117
|
+
libraryName = "OrientationDirector"
|
|
118
|
+
codegenJavaPackageName = "com.orientationdirector"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
package com.orientationdirector
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
+
import com.facebook.react.bridge.ReactMethod
|
|
5
|
+
import com.facebook.react.bridge.Promise
|
|
6
|
+
import com.orientationdirector.implementation.OrientationDirectorImpl
|
|
7
|
+
|
|
8
|
+
class OrientationDirectorModule internal constructor(context: ReactApplicationContext) :
|
|
9
|
+
OrientationDirectorSpec(context) {
|
|
10
|
+
|
|
11
|
+
private var orientationDirectorImpl: OrientationDirectorImpl
|
|
12
|
+
|
|
13
|
+
override fun getName(): String {
|
|
14
|
+
return NAME
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
init {
|
|
18
|
+
orientationDirectorImpl = OrientationDirectorImpl(context)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@ReactMethod()
|
|
22
|
+
override fun getInterfaceOrientation(promise: Promise) {
|
|
23
|
+
promise.resolve(orientationDirectorImpl.getInterfaceOrientation().ordinal)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@ReactMethod()
|
|
27
|
+
override fun getDeviceOrientation(promise: Promise) {
|
|
28
|
+
promise.resolve(orientationDirectorImpl.getDeviceOrientation().ordinal)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@ReactMethod()
|
|
32
|
+
override fun lockTo(orientation: Double) {
|
|
33
|
+
orientationDirectorImpl.lockTo(orientation.toInt())
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@ReactMethod()
|
|
37
|
+
override fun unlock() {
|
|
38
|
+
orientationDirectorImpl.unlock()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@ReactMethod()
|
|
42
|
+
override fun addListener(eventName: String) {}
|
|
43
|
+
|
|
44
|
+
@ReactMethod()
|
|
45
|
+
override fun removeListeners(count: Double) {}
|
|
46
|
+
|
|
47
|
+
companion object {
|
|
48
|
+
const val NAME = "OrientationDirector"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
package com.orientationdirector
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.TurboReactPackage
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.bridge.NativeModule
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
8
|
+
import java.util.HashMap
|
|
9
|
+
|
|
10
|
+
class OrientationDirectorPackage : TurboReactPackage() {
|
|
11
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
+
return if (name == OrientationDirectorModule.NAME) {
|
|
13
|
+
OrientationDirectorModule(reactContext)
|
|
14
|
+
} else {
|
|
15
|
+
null
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
20
|
+
return ReactModuleInfoProvider {
|
|
21
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
22
|
+
val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
|
23
|
+
moduleInfos[OrientationDirectorModule.NAME] = ReactModuleInfo(
|
|
24
|
+
OrientationDirectorModule.NAME,
|
|
25
|
+
OrientationDirectorModule.NAME,
|
|
26
|
+
false, // canOverrideExistingModule
|
|
27
|
+
false, // needsEagerInit
|
|
28
|
+
true, // hasConstants
|
|
29
|
+
false, // isCxxModule
|
|
30
|
+
isTurboModule // isTurboModule
|
|
31
|
+
)
|
|
32
|
+
moduleInfos
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorImpl.kt
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
package com.orientationdirector.implementation
|
|
2
|
+
|
|
3
|
+
import android.content.pm.ActivityInfo
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
|
|
6
|
+
class OrientationDirectorImpl internal constructor(private val context: ReactApplicationContext) {
|
|
7
|
+
private var mUtils = OrientationDirectorUtilsImpl()
|
|
8
|
+
private var mEventEmitter = OrientationEventManager(context)
|
|
9
|
+
private var mSensorListener = OrientationSensorListener(context)
|
|
10
|
+
private var mLifecycleListener = OrientationLifecycleListener()
|
|
11
|
+
private var isLocked: Boolean = false
|
|
12
|
+
private var lastInterfaceOrientation = Orientation.UNKNOWN
|
|
13
|
+
private var lastDeviceOrientation = Orientation.UNKNOWN
|
|
14
|
+
private var initialized = false
|
|
15
|
+
|
|
16
|
+
init {
|
|
17
|
+
mSensorListener.setOnOrientationChangedCallback { orientation ->
|
|
18
|
+
onOrientationChanged(orientation)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (mSensorListener.canDetectOrientation()) {
|
|
22
|
+
mSensorListener.enable()
|
|
23
|
+
} else {
|
|
24
|
+
mSensorListener.disable()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
context.addLifecycleEventListener(mLifecycleListener)
|
|
28
|
+
mLifecycleListener.setOnHostResumeCallback {
|
|
29
|
+
if (mSensorListener.canDetectOrientation()) {
|
|
30
|
+
mSensorListener.enable()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
mLifecycleListener.setOnHostPauseCallback {
|
|
34
|
+
if (initialized) {
|
|
35
|
+
mSensorListener.disable()
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
mLifecycleListener.setOnHostDestroyCallback {
|
|
39
|
+
mSensorListener.disable()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
lastInterfaceOrientation = initInterfaceOrientation()
|
|
43
|
+
lastDeviceOrientation = initDeviceOrientation()
|
|
44
|
+
|
|
45
|
+
initialized = true
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fun getInterfaceOrientation(): Orientation {
|
|
49
|
+
return lastInterfaceOrientation
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fun getDeviceOrientation(): Orientation {
|
|
53
|
+
return lastDeviceOrientation
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fun lockTo(jsOrientation: Int) {
|
|
57
|
+
val interfaceOrientation = mUtils.getOrientationEnumFrom(jsOrientation)
|
|
58
|
+
val screenOrientation =
|
|
59
|
+
mUtils.getActivityOrientationFrom(interfaceOrientation)
|
|
60
|
+
context.currentActivity?.requestedOrientation = screenOrientation
|
|
61
|
+
mEventEmitter.sendInterfaceOrientationDidChange(interfaceOrientation.ordinal)
|
|
62
|
+
lastInterfaceOrientation = interfaceOrientation
|
|
63
|
+
isLocked = true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fun unlock() {
|
|
67
|
+
context.currentActivity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
|
68
|
+
isLocked = false
|
|
69
|
+
adaptInterfaceTo(getDeviceOrientation())
|
|
70
|
+
}
|
|
71
|
+
|
|
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
|
|
83
|
+
|
|
84
|
+
return mUtils.getDeviceOrientationFrom(lastRotationDetected)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private fun initDeviceOrientation(): Orientation {
|
|
88
|
+
val lastRotationDetected = mSensorListener.getLastRotationDetected()
|
|
89
|
+
?: return Orientation.UNKNOWN
|
|
90
|
+
|
|
91
|
+
return mUtils.getDeviceOrientationFrom(lastRotationDetected)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private fun onOrientationChanged(rawDeviceOrientation: Int) {
|
|
95
|
+
val deviceOrientation = mUtils.getDeviceOrientationFrom(rawDeviceOrientation)
|
|
96
|
+
mEventEmitter.sendDeviceOrientationDidChange(deviceOrientation.ordinal)
|
|
97
|
+
lastDeviceOrientation = deviceOrientation
|
|
98
|
+
adaptInterfaceTo(deviceOrientation)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private fun adaptInterfaceTo(deviceOrientation: Orientation) {
|
|
102
|
+
if (isLocked) {
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (lastInterfaceOrientation == deviceOrientation) {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
lastInterfaceOrientation = deviceOrientation
|
|
111
|
+
mEventEmitter.sendInterfaceOrientationDidChange(lastInterfaceOrientation.ordinal)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
companion object {
|
|
115
|
+
const val NAME = "OrientationDirectorImpl"
|
|
116
|
+
}
|
|
117
|
+
}
|
package/android/src/main/java/com/orientationdirector/implementation/OrientationDirectorUtilsImpl.kt
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
package com.orientationdirector.implementation
|
|
2
|
+
|
|
3
|
+
import android.content.pm.ActivityInfo
|
|
4
|
+
|
|
5
|
+
class OrientationDirectorUtilsImpl() {
|
|
6
|
+
|
|
7
|
+
fun getDeviceOrientationFrom(rotation: Int): Orientation {
|
|
8
|
+
var orientation = Orientation.UNKNOWN
|
|
9
|
+
|
|
10
|
+
if (rotation == -1) {
|
|
11
|
+
orientation = Orientation.UNKNOWN
|
|
12
|
+
} else if (rotation > 355 || rotation < 5) {
|
|
13
|
+
orientation = Orientation.PORTRAIT
|
|
14
|
+
} else if (rotation in 86..94) {
|
|
15
|
+
orientation = Orientation.LANDSCAPE_RIGHT
|
|
16
|
+
} else if (rotation in 176..184) {
|
|
17
|
+
orientation = Orientation.PORTRAIT_UPSIDE_DOWN
|
|
18
|
+
} else if (rotation in 266..274) {
|
|
19
|
+
orientation = Orientation.LANDSCAPE_LEFT
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return orientation
|
|
23
|
+
}
|
|
24
|
+
|
|
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
|
+
fun getActivityOrientationFrom(interfaceOrientation: Orientation): Int {
|
|
49
|
+
return when (interfaceOrientation) {
|
|
50
|
+
Orientation.LANDSCAPE_RIGHT -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
|
51
|
+
Orientation.PORTRAIT_UPSIDE_DOWN -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
|
|
52
|
+
Orientation.LANDSCAPE_LEFT -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
|
|
53
|
+
else -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fun getOrientationEnumFrom(jsOrientation: Int): Orientation {
|
|
58
|
+
return when (jsOrientation) {
|
|
59
|
+
2 -> Orientation.LANDSCAPE_RIGHT
|
|
60
|
+
3 -> Orientation.PORTRAIT_UPSIDE_DOWN
|
|
61
|
+
4 -> Orientation.LANDSCAPE_LEFT
|
|
62
|
+
else -> Orientation.PORTRAIT
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
package/android/src/main/java/com/orientationdirector/implementation/OrientationEventManager.kt
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
package com.orientationdirector.implementation
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.bridge.Arguments
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.WritableMap
|
|
7
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
8
|
+
|
|
9
|
+
enum class Event {
|
|
10
|
+
DeviceOrientationDidChange,
|
|
11
|
+
InterfaceOrientationDidChange,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class OrientationEventManager(private val context: ReactApplicationContext) {
|
|
15
|
+
|
|
16
|
+
fun sendDeviceOrientationDidChange(orientationValue: Int) {
|
|
17
|
+
val params = Arguments.createMap().apply {
|
|
18
|
+
putInt("orientation", orientationValue)
|
|
19
|
+
}
|
|
20
|
+
sendEvent(Event.DeviceOrientationDidChange, params)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fun sendInterfaceOrientationDidChange(orientationValue: Int) {
|
|
24
|
+
val params = Arguments.createMap().apply {
|
|
25
|
+
putInt("orientation", orientationValue)
|
|
26
|
+
}
|
|
27
|
+
sendEvent(Event.InterfaceOrientationDidChange, params)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private fun sendEvent(eventName: Event, params: WritableMap?) {
|
|
31
|
+
Log.d(NAME, "sendEvent - $eventName")
|
|
32
|
+
Log.d(NAME, "sendEvent - $params")
|
|
33
|
+
context
|
|
34
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
35
|
+
.emit(eventName.name, params)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
companion object {
|
|
39
|
+
val NAME = "OrientationEventManager"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
package/android/src/main/java/com/orientationdirector/implementation/OrientationLifecycleListener.kt
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.orientationdirector.implementation
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.LifecycleEventListener
|
|
4
|
+
|
|
5
|
+
class OrientationLifecycleListener() : LifecycleEventListener {
|
|
6
|
+
|
|
7
|
+
private var onHostResumeCallback: (() -> Unit)? = null
|
|
8
|
+
private var onHostPauseCallback: (() -> Unit)? = null
|
|
9
|
+
private var onHostDestroyCallback: (() -> Unit)? = null
|
|
10
|
+
|
|
11
|
+
fun setOnHostResumeCallback(callback: () -> Unit) {
|
|
12
|
+
this.onHostResumeCallback = callback
|
|
13
|
+
}
|
|
14
|
+
fun setOnHostPauseCallback(callback: () -> Unit) {
|
|
15
|
+
this.onHostResumeCallback = callback
|
|
16
|
+
}
|
|
17
|
+
fun setOnHostDestroyCallback(callback: () -> Unit) {
|
|
18
|
+
this.onHostDestroyCallback = callback
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override fun onHostResume() {
|
|
22
|
+
this.onHostResumeCallback?.invoke()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
override fun onHostPause() {
|
|
26
|
+
this.onHostPauseCallback?.invoke()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun onHostDestroy() {
|
|
30
|
+
this.onHostDestroyCallback?.invoke()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
}
|
package/android/src/main/java/com/orientationdirector/implementation/OrientationSensorListener.kt
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.orientationdirector.implementation
|
|
2
|
+
|
|
3
|
+
import android.hardware.SensorManager
|
|
4
|
+
import android.view.OrientationEventListener
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
|
|
7
|
+
class OrientationSensorListener(
|
|
8
|
+
context: ReactApplicationContext,
|
|
9
|
+
) : OrientationEventListener(context, SensorManager.SENSOR_DELAY_UI) {
|
|
10
|
+
|
|
11
|
+
private var lastRotationDetected: Int? = null
|
|
12
|
+
private var onOrientationChangedCallback: ((orientation: Int) -> Unit)? = null
|
|
13
|
+
|
|
14
|
+
fun getLastRotationDetected(): Int? {
|
|
15
|
+
return lastRotationDetected
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fun setOnOrientationChangedCallback(callback: (orientation: Int) -> Unit) {
|
|
19
|
+
onOrientationChangedCallback = callback
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
override fun onOrientationChanged(orientation: Int) {
|
|
23
|
+
lastRotationDetected = orientation
|
|
24
|
+
onOrientationChangedCallback?.invoke(orientation)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.orientationdirector
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
5
|
+
import com.facebook.react.bridge.Promise
|
|
6
|
+
|
|
7
|
+
abstract class OrientationDirectorSpec internal constructor(context: ReactApplicationContext) :
|
|
8
|
+
ReactContextBaseJavaModule(context) {
|
|
9
|
+
|
|
10
|
+
abstract fun getInterfaceOrientation(promise: Promise)
|
|
11
|
+
abstract fun getDeviceOrientation(promise: Promise)
|
|
12
|
+
abstract fun lockTo(orientation: Double)
|
|
13
|
+
abstract fun unlock()
|
|
14
|
+
abstract fun addListener(eventName: String)
|
|
15
|
+
abstract fun removeListeners(count: Double)
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#import <React/RCTEventEmitter.h>
|
|
2
|
+
|
|
3
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
4
|
+
#import <RNOrientationDirectorSpec/RNOrientationDirectorSpec.h>
|
|
5
|
+
|
|
6
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
7
|
+
|
|
8
|
+
@interface OrientationDirector : RCTEventEmitter <NativeOrientationDirectorSpec>
|
|
9
|
+
|
|
10
|
+
NS_ASSUME_NONNULL_END
|
|
11
|
+
|
|
12
|
+
#else
|
|
13
|
+
#import <React/RCTBridgeModule.h>
|
|
14
|
+
|
|
15
|
+
@interface OrientationDirector : RCTEventEmitter <RCTBridgeModule>
|
|
16
|
+
#endif
|
|
17
|
+
|
|
18
|
+
@property (nonatomic, assign) BOOL isJsListening;
|
|
19
|
+
|
|
20
|
+
+(UIInterfaceOrientationMask)getSupportedInterfaceOrientationsForWindow;
|
|
21
|
+
|
|
22
|
+
@end
|