forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add react-native-oss-library-example package (facebook#43068)
Summary: This diff adds `react-native-oss-library-example` package. It contains native module and native component example, and targets both the new and the old architecture. It has structure similar to many OSS React Native libraries, and is supposed to be used to test the integration with third-party libraries. It is integrated with RNTester as the **OSS Library Example** screen. {F1457510909} **Change Background** tests native commands. **Set Opacity** tests native props. **Get Random Number** tests native module. Changelog: [Internal] Differential Revision: D50793835
- Loading branch information
1 parent
eca78c3
commit 2781e62
Showing
22 changed files
with
897 additions
and
1 deletion.
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
packages/react-native-oss-library-example/OSSLibraryExample.podspec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Copyright (c) Meta Platforms, Inc. and affiliates. | ||
# | ||
# This source code is licensed under the MIT license found in the | ||
# LICENSE file in the root directory of this source tree. | ||
|
||
require 'json' | ||
|
||
package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) | ||
|
||
Pod::Spec.new do |s| | ||
s.name = 'OSSLibraryExample' | ||
s.version = package['version'] | ||
s.summary = package['description'] | ||
s.description = package['description'] | ||
s.homepage = package['homepage'] | ||
s.license = package['license'] | ||
s.platforms = min_supported_versions | ||
s.author = 'Meta Platforms, Inc. and its affiliates' | ||
s.source = { :git => package['repository'], :tag => "#{s.version}" } | ||
|
||
s.source_files = 'ios/**/*.{h,m,mm,cpp}' | ||
|
||
install_modules_dependencies(s) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
## Important | ||
This package is for testing only. It is a subject to frequent change. It does not represent the recomended structure for React native libraries. It should not be used as a referece for such purposes. | ||
|
||
## Building | ||
``` | ||
yarn install | ||
yarn build | ||
npx react-native codegen | ||
``` |
50 changes: 50 additions & 0 deletions
50
packages/react-native-oss-library-example/android/build.gradle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
buildscript { | ||
ext.safeExtGet = {prop, fallback -> | ||
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback | ||
} | ||
repositories { | ||
google() | ||
gradlePluginPortal() | ||
} | ||
dependencies { | ||
classpath("com.android.tools.build:gradle:7.0.4") | ||
} | ||
} | ||
|
||
apply plugin: 'com.android.library' | ||
apply plugin: 'kotlin-android' | ||
|
||
android { | ||
compileSdkVersion safeExtGet('compileSdkVersion', 31) | ||
|
||
defaultConfig { | ||
minSdkVersion safeExtGet('minSdkVersion', 23) | ||
targetSdkVersion safeExtGet('targetSdkVersion', 31) | ||
} | ||
|
||
sourceSets { | ||
main { | ||
java.srcDirs += ['src', 'java'] | ||
} | ||
} | ||
} | ||
|
||
repositories { | ||
maven { | ||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm | ||
url "$projectDir/../node_modules/react-native/android" | ||
} | ||
mavenCentral() | ||
google() | ||
} | ||
|
||
dependencies { | ||
implementation 'com.facebook.react:react-native:+' | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/react-native-oss-library-example/android/src/main/AndroidManifest.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="com.reactnative.osslibraryexample"> | ||
</manifest> |
30 changes: 30 additions & 0 deletions
30
...ary-example/android/src/main/java/com/reactnative/osslibraryexample/NativeSampleModule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.reactnative.osslibraryexample | ||
|
||
import com.facebook.fbreact.specs.NativeSampleModuleSpec | ||
import com.facebook.react.bridge.ReactApplicationContext | ||
import com.facebook.react.bridge.ReactContextBaseJavaModule | ||
import com.facebook.react.bridge.ReactMethod | ||
import com.facebook.react.module.annotations.ReactModule | ||
|
||
@ReactModule(name = NativeSampleModuleSpec.NAME) | ||
class NativeSampleModule(reactContext: ReactApplicationContext?) : | ||
ReactContextBaseJavaModule(reactContext) { | ||
|
||
override fun getName(): String = NAME | ||
|
||
companion object { | ||
const val NAME = "NativeSampleModule" | ||
} | ||
|
||
@ReactMethod | ||
public fun getRandomNumber(): Int { | ||
return (0..99).random() | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
...ample/android/src/main/java/com/reactnative/osslibraryexample/OSSLibraryExamplePackage.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.reactnative.osslibraryexample | ||
|
||
import com.facebook.react.ReactPackage | ||
import com.facebook.react.bridge.NativeModule | ||
import com.facebook.react.bridge.ReactApplicationContext | ||
import com.facebook.react.uimanager.ViewManager | ||
|
||
class OSSLibraryExamplePackage : ReactPackage { | ||
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> = | ||
listOf(NativeSampleModule(reactContext)) | ||
|
||
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = | ||
listOf(SampleNativeComponentViewManager()) | ||
} |
94 changes: 94 additions & 0 deletions
94
...droid/src/main/java/com/reactnative/osslibraryexample/SampleNativeComponentViewManager.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.reactnative.osslibraryexample | ||
|
||
import android.graphics.Color | ||
import com.facebook.react.bridge.ReadableArray | ||
import com.facebook.react.common.MapBuilder | ||
import com.facebook.react.module.annotations.ReactModule | ||
import com.facebook.react.uimanager.SimpleViewManager | ||
import com.facebook.react.uimanager.ThemedReactContext | ||
import com.facebook.react.uimanager.ViewProps | ||
import com.facebook.react.uimanager.annotations.ReactProp | ||
import com.facebook.react.viewmanagers.SampleNativeComponentManagerInterface | ||
|
||
/** Legacy View manager (non Fabric compatible) for {@link SampleNativeView} components. */ | ||
@ReactModule(name = SampleNativeComponentViewManager.REACT_CLASS) | ||
internal class SampleNativeComponentViewManager : | ||
SimpleViewManager<SampleNativeView>(), SampleNativeComponentManagerInterface<SampleNativeView> { | ||
|
||
override fun getName(): String = REACT_CLASS | ||
|
||
@ReactProp(name = ViewProps.OPACITY, defaultFloat = 1f) | ||
override fun setOpacity(view: SampleNativeView, opacity: Float) { | ||
super.setOpacity(view, opacity) | ||
} | ||
|
||
@ReactProp(name = ViewProps.COLOR) | ||
fun setColor(view: SampleNativeView, color: String) { | ||
view.setBackgroundColor(Color.parseColor(color)) | ||
} | ||
|
||
@ReactProp(name = "cornerRadius") | ||
fun setCornerRadius(view: SampleNativeView, cornerRadius: Float) { | ||
if (cornerRadius !== null) { | ||
view.setCornerRadius(cornerRadius) | ||
} | ||
} | ||
|
||
override fun createViewInstance(reactContext: ThemedReactContext): SampleNativeView = | ||
SampleNativeView(reactContext) | ||
|
||
override fun changeBackgroundColor(view: SampleNativeView, color: String) { | ||
view.setBackgroundColor(Color.parseColor(color)) | ||
} | ||
|
||
override fun getExportedViewConstants(): Map<String, Any> = mapOf("PI" to 3.14) | ||
|
||
override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> { | ||
return MapBuilder.builder<String, Any>() | ||
.put( | ||
"onColorChanged", | ||
MapBuilder.of( | ||
"phasedRegistrationNames", | ||
MapBuilder.of("bubbled", "onColorChanged", "captured", "onColorChangedCapture"))) | ||
.build() | ||
} | ||
|
||
override fun receiveCommand(view: SampleNativeView, commandId: String, args: ReadableArray?) { | ||
if (commandId.contentEquals("changeBackgroundColor")) { | ||
val sentColor: Int = Color.parseColor(args?.getString(0)) | ||
view.setBackgroundColor(sentColor) | ||
} | ||
} | ||
|
||
@Suppress("DEPRECATION") // We intentionally want to test against the legacy API here. | ||
override fun receiveCommand(view: SampleNativeView, commandId: Int, args: ReadableArray?) { | ||
when (commandId) { | ||
COMMAND_CHANGE_BACKGROUND_COLOR -> { | ||
val sentColor: Int = Color.parseColor(args?.getString(0)) | ||
view.setBackgroundColor(sentColor) | ||
} | ||
} | ||
} | ||
|
||
override fun getCommandsMap(): Map<String, Int> = | ||
mapOf("changeBackgroundColor" to COMMAND_CHANGE_BACKGROUND_COLOR) | ||
|
||
companion object { | ||
const val REACT_CLASS = "SampleNativeComponent" | ||
const val COMMAND_CHANGE_BACKGROUND_COLOR = 42 | ||
} | ||
|
||
@ReactProp(name = "values") | ||
override fun setValues(view: SampleNativeView, value: ReadableArray?) { | ||
val values = mutableListOf<Int>() | ||
value?.toArrayList()?.forEach { values.add((it as Double).toInt()) } | ||
view.emitOnArrayChangedEvent(values) | ||
} | ||
} |
117 changes: 117 additions & 0 deletions
117
...brary-example/android/src/main/java/com/reactnative/osslibraryexample/SampleNativeView.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.reactnative.osslibraryexample | ||
|
||
import android.graphics.Color | ||
import android.graphics.drawable.GradientDrawable | ||
import android.view.View | ||
import com.facebook.react.bridge.Arguments | ||
import com.facebook.react.bridge.ReactContext | ||
import com.facebook.react.bridge.WritableArray | ||
import com.facebook.react.bridge.WritableMap | ||
import com.facebook.react.uimanager.ThemedReactContext | ||
import com.facebook.react.uimanager.UIManagerHelper | ||
import com.facebook.react.uimanager.events.Event | ||
import com.facebook.react.uimanager.events.RCTEventEmitter | ||
|
||
class SampleNativeView(context: ThemedReactContext) : View(context) { | ||
private var currentColor = 0 | ||
private var background: GradientDrawable = GradientDrawable() | ||
private var reactContext: ReactContext = context.reactApplicationContext | ||
|
||
override fun setBackgroundColor(color: Int) { | ||
if (color != currentColor) { | ||
background.setColor(color) | ||
currentColor = color | ||
emitNativeEvent(color) | ||
setBackground(background) | ||
} | ||
} | ||
|
||
fun setCornerRadius(cornerRadius: Float) { | ||
background.cornerRadius = cornerRadius | ||
setBackground(background) | ||
} | ||
|
||
private fun emitNativeEvent(color: Int) { | ||
val event = Arguments.createMap() | ||
val hsv = FloatArray(3) | ||
Color.colorToHSV(color, hsv) | ||
val backgroundColor = | ||
Arguments.createMap().apply { | ||
putDouble("hue", hsv[0].toDouble()) | ||
putDouble("saturation", hsv[1].toDouble()) | ||
putDouble("brightness", hsv[2].toDouble()) | ||
putDouble("alpha", Color.alpha(color).toDouble()) | ||
} | ||
|
||
event.putMap("backgroundColor", backgroundColor) | ||
|
||
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(id, "onColorChanged", event) | ||
} | ||
|
||
fun emitOnArrayChangedEvent(ints: List<Int>) { | ||
val newIntArray = Arguments.createArray() | ||
val newBoolArray = Arguments.createArray() | ||
val newFloatArray = Arguments.createArray() | ||
val newDoubleArray = Arguments.createArray() | ||
val newYesNoArray = Arguments.createArray() | ||
val newStringArray = Arguments.createArray() | ||
val newObjectArray = Arguments.createArray() | ||
val newArrayArray = Arguments.createArray() | ||
|
||
for (i in ints) { | ||
newIntArray.pushInt(i * 2) | ||
newBoolArray.pushBoolean(i % 2 == 1) | ||
newFloatArray.pushDouble(i * 3.14) | ||
newDoubleArray.pushDouble(i / 3.14) | ||
newYesNoArray.pushString(if (i % 2 == 1) "yep" else "nope") | ||
newStringArray.pushString(i.toString()) | ||
|
||
val latLon = Arguments.createMap() | ||
latLon.putDouble("lat", -1.0 * i) | ||
latLon.putDouble("lon", 2.0 * i) | ||
newObjectArray.pushMap(latLon) | ||
|
||
val innerArray: WritableArray = Arguments.createArray() | ||
innerArray.pushInt(i) | ||
innerArray.pushInt(i) | ||
innerArray.pushInt(i) | ||
newArrayArray.pushArray(innerArray) | ||
} | ||
|
||
val payload = | ||
Arguments.createMap().apply { | ||
putArray("values", newIntArray) | ||
putArray("boolValues", newBoolArray) | ||
putArray("floats", newFloatArray) | ||
putArray("doubles", newDoubleArray) | ||
putArray("yesNos", newYesNoArray) | ||
putArray("strings", newStringArray) | ||
putArray("latLons", newObjectArray) | ||
putArray("multiArrays", newArrayArray) | ||
} | ||
|
||
val reactContext = context as ReactContext | ||
val surfaceId = UIManagerHelper.getSurfaceId(reactContext) | ||
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id) | ||
val event = OnIntArrayChangedEvent(surfaceId, id, payload) | ||
|
||
eventDispatcher?.dispatchEvent(event) | ||
} | ||
|
||
inner class OnIntArrayChangedEvent( | ||
surfaceId: Int, | ||
viewId: Int, | ||
private val payload: WritableMap | ||
) : Event<OnIntArrayChangedEvent>(surfaceId, viewId) { | ||
override fun getEventName() = "topIntArrayChanged" | ||
|
||
override fun getEventData() = payload | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
module.exports = { | ||
presets: [['module:@react-native/babel-preset', {disableStaticViewConfigsCodegen: false}]], | ||
}; |
Oops, something went wrong.