expo-rotation-module 0.1.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/.eslintrc.js +5 -0
- package/README.md +77 -0
- package/android/.gradle/8.14.3/checksums/checksums.lock +0 -0
- package/android/.gradle/8.14.3/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.14.3/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.14.3/gc.properties +0 -0
- package/android/.gradle/9.0-milestone-1/checksums/checksums.lock +0 -0
- package/android/.gradle/9.0-milestone-1/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.0-milestone-1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.0-milestone-1/gc.properties +0 -0
- package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
- package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.2.0/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/config.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/.idea/AndroidProjectSystem.xml +6 -0
- package/android/.idea/caches/deviceStreaming.xml +1210 -0
- package/android/.idea/gradle.xml +12 -0
- package/android/.idea/migrations.xml +10 -0
- package/android/.idea/misc.xml +10 -0
- package/android/.idea/runConfigurations.xml +17 -0
- package/android/.idea/vcs.xml +6 -0
- package/android/.idea/workspace.xml +63 -0
- package/android/build.gradle +43 -0
- package/android/kls_database.db +0 -0
- package/android/local.properties +8 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/ktsierra/expo/rotationmodule/ExpoRotationModule.kt +131 -0
- package/app.plugin.js +3 -0
- package/build/ExpoRotationModule.d.ts +15 -0
- package/build/ExpoRotationModule.d.ts.map +1 -0
- package/build/ExpoRotationModule.js +76 -0
- package/build/ExpoRotationModule.js.map +1 -0
- package/build/ExpoRotationModule.types.d.ts +18 -0
- package/build/ExpoRotationModule.types.d.ts.map +1 -0
- package/build/ExpoRotationModule.types.js +2 -0
- package/build/ExpoRotationModule.types.js.map +1 -0
- package/build/ExpoRotationModule.web.d.ts +12 -0
- package/build/ExpoRotationModule.web.d.ts.map +1 -0
- package/build/ExpoRotationModule.web.js +17 -0
- package/build/ExpoRotationModule.web.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +3 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/index.js +2 -0
- package/ios/ExpoRotationModule.podspec +29 -0
- package/ios/ExpoRotationModule.swift +48 -0
- package/package.json +48 -0
- package/plugin/index.js +33 -0
- package/src/ExpoRotationModule.ts +86 -0
- package/src/ExpoRotationModule.types.ts +19 -0
- package/src/ExpoRotationModule.web.ts +21 -0
- package/src/index.d.ts +17 -0
- package/src/index.ts +2 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="GradleSettings">
|
|
4
|
+
<option name="linkedExternalProjectsSettings">
|
|
5
|
+
<GradleProjectSettings>
|
|
6
|
+
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
|
7
|
+
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
8
|
+
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
|
9
|
+
</GradleProjectSettings>
|
|
10
|
+
</option>
|
|
11
|
+
</component>
|
|
12
|
+
</project>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
4
|
+
<component name="ProjectRootManager">
|
|
5
|
+
<output url="file://$PROJECT_DIR$/build/classes" />
|
|
6
|
+
</component>
|
|
7
|
+
<component name="ProjectType">
|
|
8
|
+
<option name="id" value="Android" />
|
|
9
|
+
</component>
|
|
10
|
+
</project>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="RunConfigurationProducerService">
|
|
4
|
+
<option name="ignoredProducers">
|
|
5
|
+
<set>
|
|
6
|
+
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
|
7
|
+
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
|
8
|
+
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
|
9
|
+
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
|
10
|
+
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
|
11
|
+
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
|
12
|
+
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
|
13
|
+
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
|
14
|
+
</set>
|
|
15
|
+
</option>
|
|
16
|
+
</component>
|
|
17
|
+
</project>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="AutoImportSettings">
|
|
4
|
+
<option name="autoReloadType" value="NONE" />
|
|
5
|
+
</component>
|
|
6
|
+
<component name="ChangeListManager">
|
|
7
|
+
<list default="true" id="7cfb0c43-9e0d-469b-992d-eaa816beccfc" name="Changes" comment="">
|
|
8
|
+
<change beforePath="$PROJECT_DIR$/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/build.gradle" afterDir="false" />
|
|
9
|
+
<change beforePath="$PROJECT_DIR$/src/main/java/expo/modules/rotationmodule/ExpoRotationModule.kt" beforeDir="false" />
|
|
10
|
+
<change beforePath="$PROJECT_DIR$/src/main/java/expo/modules/rotationmodule/ExpoRotationModuleView.kt" beforeDir="false" />
|
|
11
|
+
<change beforePath="$PROJECT_DIR$/../example/app.json" beforeDir="false" afterPath="$PROJECT_DIR$/../example/app.json" afterDir="false" />
|
|
12
|
+
<change beforePath="$PROJECT_DIR$/../expo-module.config.json" beforeDir="false" afterPath="$PROJECT_DIR$/../expo-module.config.json" afterDir="false" />
|
|
13
|
+
<change beforePath="$PROJECT_DIR$/../ios/ExpoRotationModuleView.swift" beforeDir="false" />
|
|
14
|
+
<change beforePath="$PROJECT_DIR$/../package.json" beforeDir="false" afterPath="$PROJECT_DIR$/../package.json" afterDir="false" />
|
|
15
|
+
<change beforePath="$PROJECT_DIR$/../src/ExpoRotationModule.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../src/ExpoRotationModule.ts" afterDir="false" />
|
|
16
|
+
<change beforePath="$PROJECT_DIR$/../src/ExpoRotationModule.web.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../src/ExpoRotationModule.web.ts" afterDir="false" />
|
|
17
|
+
<change beforePath="$PROJECT_DIR$/../src/ExpoRotationModuleView.tsx" beforeDir="false" />
|
|
18
|
+
<change beforePath="$PROJECT_DIR$/../src/ExpoRotationModuleView.web.tsx" beforeDir="false" />
|
|
19
|
+
<change beforePath="$PROJECT_DIR$/../src/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../src/index.ts" afterDir="false" />
|
|
20
|
+
</list>
|
|
21
|
+
<option name="SHOW_DIALOG" value="false" />
|
|
22
|
+
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
23
|
+
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
24
|
+
<option name="LAST_RESOLUTION" value="IGNORE" />
|
|
25
|
+
</component>
|
|
26
|
+
<component name="ClangdSettings">
|
|
27
|
+
<option name="formatViaClangd" value="false" />
|
|
28
|
+
</component>
|
|
29
|
+
<component name="Git.Settings">
|
|
30
|
+
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
|
|
31
|
+
</component>
|
|
32
|
+
<component name="ProjectColorInfo"><![CDATA[{
|
|
33
|
+
"associatedIndex": 8
|
|
34
|
+
}]]></component>
|
|
35
|
+
<component name="ProjectId" id="37tXyc4Sf01tKNEqBOQAJzFjl52" />
|
|
36
|
+
<component name="ProjectViewState">
|
|
37
|
+
<option name="hideEmptyMiddlePackages" value="true" />
|
|
38
|
+
<option name="showLibraryContents" value="true" />
|
|
39
|
+
</component>
|
|
40
|
+
<component name="PropertiesComponent"><![CDATA[{
|
|
41
|
+
"keyToString": {
|
|
42
|
+
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
|
43
|
+
"RunOnceActivity.ShowReadmeOnStart": "true",
|
|
44
|
+
"RunOnceActivity.cidr.known.project.marker": "true",
|
|
45
|
+
"RunOnceActivity.git.unshallow": "true",
|
|
46
|
+
"RunOnceActivity.readMode.enableVisualFormatting": "true",
|
|
47
|
+
"android.gradle.sync.needed": "true",
|
|
48
|
+
"cf.first.check.clang-format": "false",
|
|
49
|
+
"cidr.known.project.marker": "true",
|
|
50
|
+
"git-widget-placeholder": "main"
|
|
51
|
+
}
|
|
52
|
+
}]]></component>
|
|
53
|
+
<component name="TaskManager">
|
|
54
|
+
<task active="true" id="Default" summary="Default task">
|
|
55
|
+
<changelist id="7cfb0c43-9e0d-469b-992d-eaa816beccfc" name="Changes" comment="" />
|
|
56
|
+
<created>1767723596460</created>
|
|
57
|
+
<option name="number" value="Default" />
|
|
58
|
+
<option name="presentableId" value="Default" />
|
|
59
|
+
<updated>1767723596460</updated>
|
|
60
|
+
</task>
|
|
61
|
+
<servers />
|
|
62
|
+
</component>
|
|
63
|
+
</project>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
apply plugin: 'com.android.library'
|
|
2
|
+
|
|
3
|
+
group = 'ktsierra.expo.rotationmodule'
|
|
4
|
+
version = '0.1.0'
|
|
5
|
+
|
|
6
|
+
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
|
+
apply from: expoModulesCorePlugin
|
|
8
|
+
applyKotlinExpoModulesCorePlugin()
|
|
9
|
+
useCoreDependencies()
|
|
10
|
+
useExpoPublishing()
|
|
11
|
+
|
|
12
|
+
// If you want to use the managed Android SDK versions from expo-modules-core, set this to true.
|
|
13
|
+
// The Android SDK versions will be bumped from time to time in SDK releases and may introduce breaking changes in your module code.
|
|
14
|
+
// Most of the time, you may like to manage the Android SDK versions yourself.
|
|
15
|
+
def useManagedAndroidSdkVersions = false
|
|
16
|
+
if (useManagedAndroidSdkVersions) {
|
|
17
|
+
useDefaultAndroidSdkVersions()
|
|
18
|
+
} else {
|
|
19
|
+
buildscript {
|
|
20
|
+
// Simple helper that allows the root project to override versions declared by this library.
|
|
21
|
+
ext.safeExtGet = { prop, fallback ->
|
|
22
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
project.android {
|
|
26
|
+
compileSdkVersion safeExtGet("compileSdkVersion", 36)
|
|
27
|
+
defaultConfig {
|
|
28
|
+
minSdkVersion safeExtGet("minSdkVersion", 24)
|
|
29
|
+
targetSdkVersion safeExtGet("targetSdkVersion", 36)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
android {
|
|
35
|
+
namespace = "ktsierra.expo.rotationmodule"
|
|
36
|
+
defaultConfig {
|
|
37
|
+
versionCode = 1
|
|
38
|
+
versionName = "0.1.0"
|
|
39
|
+
}
|
|
40
|
+
lintOptions {
|
|
41
|
+
abortOnError = false
|
|
42
|
+
}
|
|
43
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## This file must *NOT* be checked into Version Control Systems,
|
|
2
|
+
# as it contains information specific to your local configuration.
|
|
3
|
+
#
|
|
4
|
+
# Location of the SDK. This is only used by Gradle.
|
|
5
|
+
# For customization when using a Version Control System, please read the
|
|
6
|
+
# header note.
|
|
7
|
+
#Tue Jan 06 13:19:56 EST 2026
|
|
8
|
+
sdk.dir=/Users/ktsierra/Library/Android/sdk
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
package ktsierra.expo.rotationmodule
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.ContentResolver
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
import android.os.Build
|
|
8
|
+
import android.provider.Settings
|
|
9
|
+
import android.util.Log
|
|
10
|
+
import expo.modules.kotlin.modules.Module
|
|
11
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
12
|
+
|
|
13
|
+
class ExpoRotationModule : Module() {
|
|
14
|
+
companion object {
|
|
15
|
+
const val NAME = "ExpoRotationModule"
|
|
16
|
+
const val TAG = "ExpoRotationModule"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun definition() = ModuleDefinition {
|
|
20
|
+
Name(NAME)
|
|
21
|
+
|
|
22
|
+
AsyncFunction("canWrite") {
|
|
23
|
+
try {
|
|
24
|
+
val ctx = appContext.activityProvider?.currentActivity ?: appContext.reactContext!!
|
|
25
|
+
val can = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
26
|
+
Settings.System.canWrite(ctx)
|
|
27
|
+
} else {
|
|
28
|
+
true
|
|
29
|
+
}
|
|
30
|
+
return@AsyncFunction can
|
|
31
|
+
} catch (e: Exception) {
|
|
32
|
+
Log.e(TAG, "canWrite error", e)
|
|
33
|
+
throw Exception("E_GET_ROTATION: ${e.message}")
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
Function("requestWritePermission") {
|
|
38
|
+
try {
|
|
39
|
+
val activity: Activity? = appContext.activityProvider?.currentActivity
|
|
40
|
+
val activityPkg = activity?.applicationContext?.packageName
|
|
41
|
+
val reactPkg = appContext.reactContext?.packageName
|
|
42
|
+
val pkgName = activityPkg ?: reactPkg ?: ""
|
|
43
|
+
Log.i(TAG, "requestWritePermission - activityPkg=$activityPkg reactPkg=$reactPkg chosen=$pkgName")
|
|
44
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
45
|
+
val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
|
|
46
|
+
intent.data = Uri.parse("package:$pkgName")
|
|
47
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
48
|
+
Log.i(TAG, "Opening WRITE_SETTINGS for package: $pkgName")
|
|
49
|
+
if (activity != null) {
|
|
50
|
+
activity.startActivity(intent)
|
|
51
|
+
} else {
|
|
52
|
+
appContext.reactContext?.startActivity(intent)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
} catch (e: Exception) {
|
|
56
|
+
Log.e(TAG, "requestWritePermission error", e)
|
|
57
|
+
}
|
|
58
|
+
return@Function null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
Function("getPackageName") {
|
|
62
|
+
try {
|
|
63
|
+
val pkg = appContext.activityProvider?.currentActivity?.packageName ?: appContext.reactContext?.packageName ?: ""
|
|
64
|
+
return@Function pkg
|
|
65
|
+
} catch (e: Exception) {
|
|
66
|
+
Log.e(TAG, "getPackageName error", e)
|
|
67
|
+
return@Function ""
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
AsyncFunction("getRotationState") {
|
|
72
|
+
try {
|
|
73
|
+
val ctx = appContext.activityProvider?.currentActivity ?: appContext.reactContext!!
|
|
74
|
+
val resolver: ContentResolver = ctx.contentResolver
|
|
75
|
+
val auto = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
|
76
|
+
Settings.System.getInt(resolver, Settings.System.ACCELEROMETER_ROTATION, 1)
|
|
77
|
+
} else {
|
|
78
|
+
1
|
|
79
|
+
}
|
|
80
|
+
if (auto == 1) {
|
|
81
|
+
return@AsyncFunction "AUTOROTATE"
|
|
82
|
+
} else {
|
|
83
|
+
val rotation = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
|
84
|
+
Settings.System.getInt(resolver, Settings.System.USER_ROTATION, 0)
|
|
85
|
+
} else {
|
|
86
|
+
0
|
|
87
|
+
}
|
|
88
|
+
return@AsyncFunction when (rotation) {
|
|
89
|
+
0 -> "PORTRAIT"
|
|
90
|
+
1 -> "LANDSCAPE"
|
|
91
|
+
3 -> "LANDSCAPE"
|
|
92
|
+
else -> "PORTRAIT"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} catch (e: Exception) {
|
|
96
|
+
Log.e(TAG, "getRotationState error", e)
|
|
97
|
+
throw Exception("E_GET_ROTATION: ${e.message}")
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
AsyncFunction("setRotationState") { state: String ->
|
|
102
|
+
try {
|
|
103
|
+
val ctx = appContext.activityProvider?.currentActivity ?: appContext.reactContext!!
|
|
104
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.System.canWrite(ctx)) {
|
|
105
|
+
throw Exception("E_PERMISSION: WRITE_SETTINGS not granted")
|
|
106
|
+
}
|
|
107
|
+
val resolver: ContentResolver = ctx.contentResolver
|
|
108
|
+
when (state) {
|
|
109
|
+
"AUTOROTATE" -> {
|
|
110
|
+
Settings.System.putInt(resolver, Settings.System.ACCELEROMETER_ROTATION, 1)
|
|
111
|
+
}
|
|
112
|
+
"PORTRAIT" -> {
|
|
113
|
+
Settings.System.putInt(resolver, Settings.System.ACCELEROMETER_ROTATION, 0)
|
|
114
|
+
Settings.System.putInt(resolver, Settings.System.USER_ROTATION, 0)
|
|
115
|
+
}
|
|
116
|
+
"LANDSCAPE" -> {
|
|
117
|
+
Settings.System.putInt(resolver, Settings.System.ACCELEROMETER_ROTATION, 0)
|
|
118
|
+
Settings.System.putInt(resolver, Settings.System.USER_ROTATION, 1)
|
|
119
|
+
}
|
|
120
|
+
else -> {
|
|
121
|
+
throw Exception("E_INVALID_STATE: Invalid rotation state: $state")
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return@AsyncFunction null
|
|
125
|
+
} catch (e: Exception) {
|
|
126
|
+
Log.e(TAG, "setRotationState error", e)
|
|
127
|
+
throw Exception("E_SET_ROTATION: ${e.message}")
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type RotationState = 'AUTOROTATE' | 'PORTRAIT' | 'LANDSCAPE';
|
|
2
|
+
export declare function canWrite(): Promise<boolean>;
|
|
3
|
+
export declare function requestWritePermission(): void;
|
|
4
|
+
export declare function getPackageName(): Promise<string>;
|
|
5
|
+
export declare function getRotationState(): Promise<RotationState>;
|
|
6
|
+
export declare function setRotationState(state: RotationState): Promise<void>;
|
|
7
|
+
declare const _default: {
|
|
8
|
+
canWrite: typeof canWrite;
|
|
9
|
+
requestWritePermission: typeof requestWritePermission;
|
|
10
|
+
getRotationState: typeof getRotationState;
|
|
11
|
+
setRotationState: typeof setRotationState;
|
|
12
|
+
getPackageName: typeof getPackageName;
|
|
13
|
+
};
|
|
14
|
+
export default _default;
|
|
15
|
+
//# sourceMappingURL=ExpoRotationModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoRotationModule.d.ts","sourceRoot":"","sources":["../src/ExpoRotationModule.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;AAcpE,wBAAsB,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAOjD;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAO7C;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAOtD;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC,CAO/D;AAaD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAW1E;;;;;;;;AAED,wBAME"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { requireNativeModule } from 'expo';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
// This call loads the native module object from the JSI on native platforms.
|
|
4
|
+
const isAndroid = Platform.OS === 'android';
|
|
5
|
+
const nativeModule = isAndroid ? requireNativeModule('ExpoRotationModule') : null;
|
|
6
|
+
export async function canWrite() {
|
|
7
|
+
if (!isAndroid || !nativeModule || !nativeModule.canWrite)
|
|
8
|
+
return false;
|
|
9
|
+
try {
|
|
10
|
+
return await nativeModule.canWrite();
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
throw normalizeError(e);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function requestWritePermission() {
|
|
17
|
+
if (!isAndroid || !nativeModule || !nativeModule.requestWritePermission)
|
|
18
|
+
return;
|
|
19
|
+
try {
|
|
20
|
+
nativeModule.requestWritePermission();
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
throw normalizeError(e);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function getPackageName() {
|
|
27
|
+
if (!isAndroid || !nativeModule || !nativeModule.getPackageName)
|
|
28
|
+
return '';
|
|
29
|
+
try {
|
|
30
|
+
return await nativeModule.getPackageName();
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
throw normalizeError(e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function getRotationState() {
|
|
37
|
+
if (!isAndroid || !nativeModule || !nativeModule.getRotationState)
|
|
38
|
+
return 'AUTOROTATE';
|
|
39
|
+
try {
|
|
40
|
+
return await nativeModule.getRotationState();
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
throw normalizeError(e);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function normalizeError(e) {
|
|
47
|
+
const err = new Error(e?.message || String(e));
|
|
48
|
+
// Try to extract code from messages like "E_PERMISSION: ..."
|
|
49
|
+
const m = (e?.message || '').match(/^([A-Z_]+):\s*(.*)$/);
|
|
50
|
+
if (m) {
|
|
51
|
+
err.code = m[1];
|
|
52
|
+
err.message = m[2] || err.message;
|
|
53
|
+
}
|
|
54
|
+
return err;
|
|
55
|
+
}
|
|
56
|
+
export async function setRotationState(state) {
|
|
57
|
+
if (!isAndroid || !nativeModule || !nativeModule.setRotationState) {
|
|
58
|
+
const err = new Error('Rotation native module not available');
|
|
59
|
+
err.code = 'E_NO_MODULE';
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
return await nativeModule.setRotationState(state);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
throw normalizeError(e);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export default {
|
|
70
|
+
canWrite,
|
|
71
|
+
requestWritePermission,
|
|
72
|
+
getRotationState,
|
|
73
|
+
setRotationState,
|
|
74
|
+
getPackageName,
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=ExpoRotationModule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoRotationModule.js","sourceRoot":"","sources":["../src/ExpoRotationModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAcxC,6EAA6E;AAC7E,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,KAAK,SAAS,CAAC;AAC5C,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAqB,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAEtG,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IACxE,IAAI,CAAC;QACH,OAAO,MAAM,YAAY,CAAC,QAAQ,EAAE,CAAC;IACvC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,cAAc,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,sBAAsB;QAAE,OAAO;IAChF,IAAI,CAAC;QACH,YAAY,CAAC,sBAAsB,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,cAAc,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,cAAc;QAAE,OAAO,EAAE,CAAC;IAC3E,IAAI,CAAC;QACH,OAAO,MAAM,YAAY,CAAC,cAAc,EAAE,CAAC;IAC7C,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,cAAc,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,gBAAgB;QAAE,OAAO,YAAY,CAAC;IACvF,IAAI,CAAC;QACH,OAAO,MAAM,YAAY,CAAC,gBAAgB,EAAE,CAAC;IAC/C,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,cAAc,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,CAAM;IAC5B,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,6DAA6D;IAC7D,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC1D,IAAI,CAAC,EAAE,CAAC;QACL,GAAW,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC;IACpC,CAAC;IACD,OAAO,GAAgC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAoB;IACzD,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;QAClE,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,sCAAsC,CAA8B,CAAC;QAC3F,GAAG,CAAC,IAAI,GAAG,aAAa,CAAC;QACzB,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,cAAc,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,eAAe;IACb,QAAQ;IACR,sBAAsB;IACtB,gBAAgB;IAChB,gBAAgB;IAChB,cAAc;CACf,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from 'expo';\nimport { Platform } from 'react-native';\n\nimport { ExpoRotationModuleEvents } from './ExpoRotationModule.types';\n\nexport type RotationState = 'AUTOROTATE' | 'PORTRAIT' | 'LANDSCAPE';\n\ndeclare class ExpoRotationModule extends NativeModule<ExpoRotationModuleEvents> {\n canWrite(): Promise<boolean>;\n requestWritePermission(): void;\n getRotationState(): Promise<RotationState>;\n setRotationState(state: RotationState): Promise<void>;\n getPackageName(): Promise<string>;\n}\n\n// This call loads the native module object from the JSI on native platforms.\nconst isAndroid = Platform.OS === 'android';\nconst nativeModule = isAndroid ? requireNativeModule<ExpoRotationModule>('ExpoRotationModule') : null;\n\nexport async function canWrite(): Promise<boolean> {\n if (!isAndroid || !nativeModule || !nativeModule.canWrite) return false;\n try {\n return await nativeModule.canWrite();\n } catch (e: any) {\n throw normalizeError(e);\n }\n}\n\nexport function requestWritePermission(): void {\n if (!isAndroid || !nativeModule || !nativeModule.requestWritePermission) return;\n try {\n nativeModule.requestWritePermission();\n } catch (e: any) {\n throw normalizeError(e);\n }\n}\n\nexport async function getPackageName(): Promise<string> {\n if (!isAndroid || !nativeModule || !nativeModule.getPackageName) return '';\n try {\n return await nativeModule.getPackageName();\n } catch (e: any) {\n throw normalizeError(e);\n }\n}\n\nexport async function getRotationState(): Promise<RotationState> {\n if (!isAndroid || !nativeModule || !nativeModule.getRotationState) return 'AUTOROTATE';\n try {\n return await nativeModule.getRotationState();\n } catch (e: any) {\n throw normalizeError(e);\n }\n}\n\nfunction normalizeError(e: any): Error & { code?: string } {\n const err = new Error(e?.message || String(e));\n // Try to extract code from messages like \"E_PERMISSION: ...\"\n const m = (e?.message || '').match(/^([A-Z_]+):\\s*(.*)$/);\n if (m) {\n (err as any).code = m[1];\n err.message = m[2] || err.message;\n }\n return err as Error & { code?: string };\n}\n\nexport async function setRotationState(state: RotationState): Promise<void> {\n if (!isAndroid || !nativeModule || !nativeModule.setRotationState) {\n const err = new Error('Rotation native module not available') as Error & { code?: string };\n err.code = 'E_NO_MODULE';\n throw err;\n }\n try {\n return await nativeModule.setRotationState(state);\n } catch (e: any) {\n throw normalizeError(e);\n }\n}\n\nexport default {\n canWrite,\n requestWritePermission,\n getRotationState,\n setRotationState,\n getPackageName,\n};\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
export type OnLoadEventPayload = {
|
|
3
|
+
url: string;
|
|
4
|
+
};
|
|
5
|
+
export type ExpoRotationModuleEvents = {
|
|
6
|
+
onChange: (params: ChangeEventPayload) => void;
|
|
7
|
+
};
|
|
8
|
+
export type ChangeEventPayload = {
|
|
9
|
+
value: string;
|
|
10
|
+
};
|
|
11
|
+
export type ExpoRotationModuleViewProps = {
|
|
12
|
+
url: string;
|
|
13
|
+
onLoad: (event: {
|
|
14
|
+
nativeEvent: OnLoadEventPayload;
|
|
15
|
+
}) => void;
|
|
16
|
+
style?: StyleProp<ViewStyle>;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=ExpoRotationModule.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoRotationModule.types.d.ts","sourceRoot":"","sources":["../src/ExpoRotationModule.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,kBAAkB,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoRotationModule.types.js","sourceRoot":"","sources":["../src/ExpoRotationModule.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StyleProp, ViewStyle } from 'react-native';\n\nexport type OnLoadEventPayload = {\n url: string;\n};\n\nexport type ExpoRotationModuleEvents = {\n onChange: (params: ChangeEventPayload) => void;\n};\n\nexport type ChangeEventPayload = {\n value: string;\n};\n\nexport type ExpoRotationModuleViewProps = {\n url: string;\n onLoad: (event: { nativeEvent: OnLoadEventPayload }) => void;\n style?: StyleProp<ViewStyle>;\n};\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NativeModule } from 'expo';
|
|
2
|
+
import { ExpoRotationModuleEvents } from './ExpoRotationModule.types';
|
|
3
|
+
import type { RotationState } from './ExpoRotationModule';
|
|
4
|
+
declare class ExpoRotationModule extends NativeModule<ExpoRotationModuleEvents> {
|
|
5
|
+
canWrite(): Promise<boolean>;
|
|
6
|
+
requestWritePermission(): void;
|
|
7
|
+
getRotationState(): Promise<RotationState>;
|
|
8
|
+
setRotationState(state: RotationState): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
declare const _default: typeof ExpoRotationModule;
|
|
11
|
+
export default _default;
|
|
12
|
+
//# sourceMappingURL=ExpoRotationModule.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoRotationModule.web.d.ts","sourceRoot":"","sources":["../src/ExpoRotationModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,MAAM,MAAM,CAAC;AAEvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,cAAM,kBAAmB,SAAQ,YAAY,CAAC,wBAAwB,CAAC;IAC/D,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAGlC,sBAAsB,IAAI,IAAI;IAGxB,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC;IAG1C,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAG5D;;AAED,wBAA2E"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { registerWebModule, NativeModule } from 'expo';
|
|
2
|
+
class ExpoRotationModule extends NativeModule {
|
|
3
|
+
async canWrite() {
|
|
4
|
+
return true;
|
|
5
|
+
}
|
|
6
|
+
requestWritePermission() {
|
|
7
|
+
// no-op on web
|
|
8
|
+
}
|
|
9
|
+
async getRotationState() {
|
|
10
|
+
return 'AUTOROTATE';
|
|
11
|
+
}
|
|
12
|
+
async setRotationState(state) {
|
|
13
|
+
// no-op on web
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export default registerWebModule(ExpoRotationModule, 'ExpoRotationModule');
|
|
17
|
+
//# sourceMappingURL=ExpoRotationModule.web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoRotationModule.web.js","sourceRoot":"","sources":["../src/ExpoRotationModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAKvD,MAAM,kBAAmB,SAAQ,YAAsC;IACrE,KAAK,CAAC,QAAQ;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IACD,sBAAsB;QACpB,eAAe;IACjB,CAAC;IACD,KAAK,CAAC,gBAAgB;QACpB,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,KAAK,CAAC,gBAAgB,CAAC,KAAoB;QACzC,eAAe;IACjB,CAAC;CACF;AAED,eAAe,iBAAiB,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,CAAC","sourcesContent":["import { registerWebModule, NativeModule } from 'expo';\n\nimport { ExpoRotationModuleEvents } from './ExpoRotationModule.types';\nimport type { RotationState } from './ExpoRotationModule';\n\nclass ExpoRotationModule extends NativeModule<ExpoRotationModuleEvents> {\n async canWrite(): Promise<boolean> {\n return true;\n }\n requestWritePermission(): void {\n // no-op on web\n }\n async getRotationState(): Promise<RotationState> {\n return 'AUTOROTATE';\n }\n async setRotationState(state: RotationState): Promise<void> {\n // no-op on web\n }\n}\n\nexport default registerWebModule(ExpoRotationModule, 'ExpoRotationModule');\n"]}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC","sourcesContent":["export * from './ExpoRotationModule';\nexport * from './ExpoRotationModule.types';\n"]}
|
package/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'ExpoRotationModule'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.description = package['description']
|
|
10
|
+
s.license = package['license']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.homepage = package['homepage']
|
|
13
|
+
s.platforms = {
|
|
14
|
+
:ios => '15.1',
|
|
15
|
+
:tvos => '15.1'
|
|
16
|
+
}
|
|
17
|
+
s.swift_version = '5.9'
|
|
18
|
+
s.source = { git: 'https://github.com/Ktsierra/expo-rotation-module' }
|
|
19
|
+
s.static_framework = true
|
|
20
|
+
|
|
21
|
+
s.dependency 'ExpoModulesCore'
|
|
22
|
+
|
|
23
|
+
# Swift/Objective-C compatibility
|
|
24
|
+
s.pod_target_xcconfig = {
|
|
25
|
+
'DEFINES_MODULE' => 'YES',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
|
|
29
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
|
|
3
|
+
public class ExpoRotationModule: Module {
|
|
4
|
+
// Each module class must implement the definition function. The definition consists of components
|
|
5
|
+
// that describes the module's functionality and behavior.
|
|
6
|
+
// See https://docs.expo.dev/modules/module-api for more details about available components.
|
|
7
|
+
public func definition() -> ModuleDefinition {
|
|
8
|
+
// Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
|
|
9
|
+
// Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
|
|
10
|
+
// The module will be accessible from `requireNativeModule('ExpoRotationModule')` in JavaScript.
|
|
11
|
+
Name("ExpoRotationModule")
|
|
12
|
+
|
|
13
|
+
// Defines constant property on the module.
|
|
14
|
+
Constant("PI") {
|
|
15
|
+
Double.pi
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Defines event names that the module can send to JavaScript.
|
|
19
|
+
Events("onChange")
|
|
20
|
+
|
|
21
|
+
// Defines a JavaScript synchronous function that runs the native code on the JavaScript thread.
|
|
22
|
+
Function("hello") {
|
|
23
|
+
return "Hello world! 👋"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Defines a JavaScript function that always returns a Promise and whose native code
|
|
27
|
+
// is by default dispatched on the different thread than the JavaScript runtime runs on.
|
|
28
|
+
AsyncFunction("setValueAsync") { (value: String) in
|
|
29
|
+
// Send an event to JavaScript.
|
|
30
|
+
self.sendEvent("onChange", [
|
|
31
|
+
"value": value
|
|
32
|
+
])
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Enables the module to be used as a native view. Definition components that are accepted as part of the
|
|
36
|
+
// view definition: Prop, Events.
|
|
37
|
+
View(ExpoRotationModuleView.self) {
|
|
38
|
+
// Defines a setter for the `url` prop.
|
|
39
|
+
Prop("url") { (view: ExpoRotationModuleView, url: URL) in
|
|
40
|
+
if view.webView.url != url {
|
|
41
|
+
view.webView.load(URLRequest(url: url))
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Events("onLoad")
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|