diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java index 09ae7a272ad0..7b98cae55d99 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java @@ -330,6 +330,29 @@ public BoxedIntPropSetter(ReactPropGroup prop, Method setter, int index) { } } + private static class BoxedFloatPropSetter extends PropSetter { + + public BoxedFloatPropSetter(ReactProp prop, Method setter) { + super(prop, "number", setter); + } + + public BoxedFloatPropSetter(ReactPropGroup prop, Method setter, int index) { + super(prop, "number", setter, index); + } + + @Override + protected @Nullable Object getValueOrDefault(Object value, Context context) { + if (value != null) { + if (value instanceof Double) { + return ((Double) value).floatValue(); + } else { + return (Float) value; + } + } + return null; + } + } + private static class BoxedColorPropSetter extends PropSetter { public BoxedColorPropSetter(ReactProp prop, Method setter) { @@ -450,6 +473,8 @@ private static PropSetter createPropSetter( return new BoxedColorPropSetter(annotation, method); } return new BoxedIntPropSetter(annotation, method); + } else if (propTypeClass == Float.class) { + return new BoxedFloatPropSetter(annotation, method); } else if (propTypeClass == ReadableArray.class) { return new ArrayPropSetter(annotation, method); } else if (propTypeClass == ReadableMap.class) { @@ -500,6 +525,10 @@ private static void createPropSetters( props.put(names[i], new BoxedIntPropSetter(annotation, method, i)); } } + } else if (propTypeClass == Float.class) { + for (int i = 0; i < names.length; i++) { + props.put(names[i], new BoxedFloatPropSetter(annotation, method, i)); + } } else { throw new RuntimeException( "Unrecognized type: " diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.kt index e2e683a7c443..23abeecccbb0 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropAnnotationSetterTest.kt @@ -41,6 +41,8 @@ class ReactPropAnnotationSetterTest { fun onBoxedIntSetterCalled(value: Int?) + fun onBoxedFloatSetterCalled(value: Float?) + fun onArraySetterCalled(value: ReadableArray?) fun onMapSetterCalled(value: ReadableMap?) @@ -50,6 +52,8 @@ class ReactPropAnnotationSetterTest { fun onIntGroupPropSetterCalled(index: Int, value: Int) fun onBoxedIntGroupPropSetterCalled(index: Int, value: Int?) + + fun onBoxedFloatGroupPropSetterCalled(index: Int, value: Float?) } @Suppress("UNUSED_PARAMETER", "DEPRECATION") @@ -128,6 +132,11 @@ class ReactPropAnnotationSetterTest { viewManagerUpdatesReceiver.onBoxedIntSetterCalled(value) } + @ReactProp(name = "boxedFloatProp") + fun setBoxedFloatProp(v: View?, value: Float?) { + viewManagerUpdatesReceiver.onBoxedFloatSetterCalled(value) + } + @ReactProp(name = "arrayProp") fun setArrayProp(v: View?, value: ReadableArray?) { viewManagerUpdatesReceiver.onArraySetterCalled(value) @@ -168,6 +177,11 @@ class ReactPropAnnotationSetterTest { fun setBoxedIntGroupProp(v: View?, index: Int, value: Int?) { viewManagerUpdatesReceiver.onBoxedIntGroupPropSetterCalled(index, value) } + + @ReactPropGroup(names = ["boxedFloatGroupPropFirst", "boxedFloatGroupPropSecond"]) + fun setBoxedFloatGroupProp(v: View?, index: Int, value: Float?) { + viewManagerUpdatesReceiver.onBoxedFloatGroupPropSetterCalled(index, value) + } } private lateinit var viewManager: ViewManagerUnderTest @@ -314,6 +328,22 @@ class ReactPropAnnotationSetterTest { Mockito.reset(updatesReceiverMock) } + @Test + fun testBoxedFloatSetter() { + viewManager.updateProperties(targetView, buildStyles("boxedFloatProp", 55.5)) + Mockito.verify(updatesReceiverMock).onBoxedFloatSetterCalled(55.5f) + Mockito.verifyNoMoreInteractions(updatesReceiverMock) + Mockito.reset(updatesReceiverMock) + viewManager.updateProperties(targetView, buildStyles("boxedFloatProp", 1.0)) + Mockito.verify(updatesReceiverMock).onBoxedFloatSetterCalled(1.0f) + Mockito.verifyNoMoreInteractions(updatesReceiverMock) + Mockito.reset(updatesReceiverMock) + viewManager.updateProperties(targetView, buildStyles("boxedFloatProp", null)) + Mockito.verify(updatesReceiverMock).onBoxedFloatSetterCalled(null) + Mockito.verifyNoMoreInteractions(updatesReceiverMock) + Mockito.reset(updatesReceiverMock) + } + @Test fun testArraySetter() { val array: ReadableArray = JavaOnlyArray() @@ -404,6 +434,22 @@ class ReactPropAnnotationSetterTest { Mockito.reset(updatesReceiverMock) } + @Test + fun testBoxedFloatGroupSetter() { + viewManager.updateProperties(targetView, buildStyles("boxedFloatGroupPropFirst", -7.75)) + Mockito.verify(updatesReceiverMock).onBoxedFloatGroupPropSetterCalled(0, -7.75f) + Mockito.verifyNoMoreInteractions(updatesReceiverMock) + Mockito.reset(updatesReceiverMock) + viewManager.updateProperties(targetView, buildStyles("boxedFloatGroupPropSecond", 12345.0)) + Mockito.verify(updatesReceiverMock).onBoxedFloatGroupPropSetterCalled(1, 12345.0f) + Mockito.verifyNoMoreInteractions(updatesReceiverMock) + Mockito.reset(updatesReceiverMock) + viewManager.updateProperties(targetView, buildStyles("boxedFloatGroupPropSecond", null)) + Mockito.verify(updatesReceiverMock).onBoxedFloatGroupPropSetterCalled(1, null) + Mockito.verifyNoMoreInteractions(updatesReceiverMock) + Mockito.reset(updatesReceiverMock) + } + @Test(expected = JSApplicationIllegalArgumentException::class) fun testFailToUpdateBoolPropWithMap() { viewManager.updateProperties(targetView, buildStyles("boolProp", JavaOnlyMap())) diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.kt index bee7ae8b9adf..e1b11ba6de87 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.kt @@ -66,6 +66,8 @@ class ReactPropConstantsTest { @ReactProp(name = "boxedIntProp") fun setBoxedIntProp(v: View?, value: Int?) = Unit + @ReactProp(name = "boxedFloatProp") fun setBoxedFloatProp(v: View?, value: Float?) = Unit + @ReactProp(name = "arrayProp") fun setArrayProp(v: View?, value: ReadableArray?) = Unit @ReactProp(name = "mapProp") fun setMapProp(v: View?, value: ReadableMap?) = Unit @@ -79,6 +81,9 @@ class ReactPropConstantsTest { @ReactPropGroup(names = ["boxedIntGroupPropFirst", "boxedIntGroupPropSecond"]) fun setBoxedIntGroupProp(v: View?, index: Int, value: Int?) = Unit + @ReactPropGroup(names = ["boxedFloatGroupPropFirst", "boxedFloatGroupPropSecond"]) + fun setBoxedFloatGroupProp(v: View?, index: Int, value: Float?) = Unit + @ReactProp(name = "customIntProp", customType = "date") fun customIntProp(v: View?, value: Int) = Unit @@ -112,6 +117,7 @@ class ReactPropConstantsTest { "stringProp" to "String", "boxedBoolProp" to "boolean", "boxedIntProp" to "number", + "boxedFloatProp" to "number", "arrayProp" to "Array", "mapProp" to "Map", "floatGroupPropFirst" to "number", @@ -120,6 +126,8 @@ class ReactPropConstantsTest { "intGroupPropSecond" to "number", "boxedIntGroupPropFirst" to "number", "boxedIntGroupPropSecond" to "number", + "boxedFloatGroupPropFirst" to "number", + "boxedFloatGroupPropSecond" to "number", "customIntProp" to "date", "customBoxedIntGroupPropFirst" to "color", "customBoxedIntGroupPropSecond" to "color",