Compare commits

..
Author SHA1 Message Date
Devmate Bot 77e9c6da24 xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp
Reviewed By: rshest

Differential Revision: D79874231
2025-08-11 00:01:20 -07:00
David Vacca d3bbbd893a Deprecate com/facebook/react Legacy Architecture classes (#53104)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53104

Deprecate com/facebook/react Legacy Architecture classes

changelog: [Android][Changed] Depreacate CoreModulesPackage and NativeModuleRegistryBuilder legacy architecture classes, these classes unused in the new architecture and will be deleted in the future

Reviewed By: shwanton

Differential Revision: D79676942

fbshipit-source-id: a2c447bee251fdac79d3dc81a17851eaf5271413
2025-08-09 04:39:35 -07:00
David Vacca da74d5da2c Deprecate Legacy Architecture ViewManagers (#53107)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53107

Deprecate Legacy Architecture ViewManagers, these classes are not used as part of the new architecture and will be deleted in the future

changelog: [Android][Changed] Deprecate Legacy Architecture ViewManagers, these classes are not used as part of the new architecture and will be deleted in the future

Reviewed By: shwanton

Differential Revision: D79676585

fbshipit-source-id: 72cb6fe0bbe666cfa317cf28d6aec475f1c38c35
2025-08-09 04:39:35 -07:00
David Vacca 07091a9ae8 Deprecate custom ShadowNode classes included in React Native (#53192)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53192

In this diff I'm deprecating ShadowNode classes included in React Native library

These classes are part of the legacy architecture and will be deleted in the future

changelog: [Android][Changed] Deprecate LegacyArchitecture ShadowNode classes included in React Native

Reviewed By: mlord93

Differential Revision: D79676584

fbshipit-source-id: a39267e6e430fcf4f6a73c96cd28d02eafc88a32
2025-08-09 04:39:35 -07:00
David Vacca c1f7c5e321 Depreacte remaining LegacyArchitecture classes from the bridge package (#53191)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53191

Depreacte remaining LegacyArchitecture classes from the bridge package

changelog: [Android][Changed] Depreacte all LegacyArchitecture classes from the bridge package

Reviewed By: mlord93

Differential Revision: D79674635

fbshipit-source-id: 6a873d05157e17ef0434821e1c8a77959d7f079a
2025-08-09 04:39:35 -07:00
David Vacca b29b86f275 Deprecate LegacyArchitecture class UIManagerProvider (#53190)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53190

Deprecate LegacyArchitecture class UIManagerProvider

changelog: [Android][Changed] Deprecate LegacyArchitecture class UIManagerProvider

Reviewed By: mlord93

Differential Revision: D79674639

fbshipit-source-id: 6802a35c4bd643f138a54b4f22f3804743f89249
2025-08-09 04:39:35 -07:00
David Vacca 25c011eb4d Deprecate BridgeDevSupportManager and JSInstance (#53108)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53108

Deprecate BridgeDevSupportManager and JSInstance

changelog: [Android][Changed] Deprecate BridgeDevSupportManager and JSInstance

Reviewed By: mlord93

Differential Revision: D79674636

fbshipit-source-id: c34c4ed386ab6c130fc12e03659fe2d15b42658d
2025-08-09 04:39:35 -07:00
David Vacca 3306cdbbe9 Update deprecation message for BridgeReactContext class (#53110)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53110

Update deprecation message for BridgeReactContext class

changelog: [internal] internal

Reviewed By: mlord93

Differential Revision: D79674637

fbshipit-source-id: 0942b0c8479cd1eba8e29bd9dcfc4547790910f1
2025-08-09 04:39:35 -07:00
David Vacca 22e4c25211 Deprecate NativeModuleRegistry Legacy Architecture class (#53123)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53123

Deprecate NativeModuleRegistry Legacy Architecture class

changelog: [Android][Changed] Deprecate NativeModuleRegistry Legacy Architecture class

Reviewed By: mlord93

Differential Revision: D79674638

fbshipit-source-id: 7791ceb53545aa456e92f051ed4c1f070305b5fc
2025-08-09 04:39:35 -07:00
David Vacca 78a3ff81eb Deprecate subset of LegacyArchitecture classes in com/facebook/react/bridge (#53106)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53106

Deprecate subset of LegacyArchitecture classes in com/facebook/react/bridge

changelog: [Android][Changed] Deprecate subset of LegacyArchitecture classes in com/facebook/react/bridge

Reviewed By: mlord93

Differential Revision: D79674640

fbshipit-source-id: 58b8fde8bed739fd04272215e399cfbed7a0188a
2025-08-09 04:39:35 -07:00
David Vacca 25f466cc4d Deprecate FrescoBasedReactTextInlineImageShadowNode (#53121)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53121

Deprecate FrescoBasedReactTextInlineImageShadowNode

changelog: [Android][Changed] Deprecate LegacyArchitecture class FrescoBasedReactTextInlineImageShadowNode

Reviewed By: mlord93

Differential Revision: D79672291

fbshipit-source-id: 482939981b735e7f96d7cde874430e2895c0d10c
2025-08-09 04:39:35 -07:00
David Vacca 718126fcf0 Deprecate Legacy Architecture class CallbackImpl (#53105)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53105

Deprecate Legacy Architecture class CallbackImpl

changelog: [Android][Changed] Deprecate Legacy Architecture class CallbackImpl

Reviewed By: mlord93

Differential Revision: D79672292

fbshipit-source-id: d35ae53093f464f2bb088a8247dbbde8591572c6
2025-08-09 04:39:35 -07:00
David Vacca 19a99dd088 Deprecate JavaMethodWrapper (#53124)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53124

Deprecate LegacyArchitecture class JavaMethodWrapperchagelog:

changelog: [Android][Changed] Deprecate LegacyArchitecture class JavaMethodWrapper

Reviewed By: mlord93

Differential Revision: D79672296

fbshipit-source-id: 05432263c4452294c667226cb8e062c50f036931
2025-08-09 04:39:35 -07:00
David Vacca c4715886a9 Deprecate Legacy Architecture ShadowNode classes
Summary:
Deprecate Legacy Architecture ShadowNode classes

Changelog: [Android][Changed] Deprecate Legacy Architecture ShadowNode classes

Reviewed By: mlord93

Differential Revision: D79672295

fbshipit-source-id: e510debd3718e6bc9e42c9b61d6a63858970077d
2025-08-09 04:39:35 -07:00
David Vacca 1a85185cfc Deprecate ShadowNodes on the codegen (#53184)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53184

Deprecate ShadowNodes on the codegen

changelog: [internal] internal

Reviewed By: shwanton

Differential Revision: D79911692

fbshipit-source-id: ad24488d186fd5b82c3953a75f52be03e4770cc2
2025-08-09 04:39:35 -07:00
David Vacca d2912e7997 EZ fix naming in kotlin file (#53109)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53109

EZ fix naming in kotlin file

changelog: [internal] internal

Reviewed By: cortinico, shwanton, mlord93

Differential Revision: D79735705

fbshipit-source-id: b1061a9aa0f245de29efb1b0f3d6c9ada9c43660
2025-08-08 16:43:31 -07:00
Ramanpreet Nara 7d6d0a7735 native modules: Show message in redundant rejection redbox (#53152)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53152

When a redundant reject is called, show the rejection message in the redbox. This can help us pin down the error we need to elminiate in production.

Changelog: [Internal]

Reviewed By: sanjay-io

Differential Revision: D79837541

fbshipit-source-id: 879b5dc42980867051cfab6ccb575304a4a9c4c6
2025-08-08 14:39:42 -07:00
Ramanpreet Nara dc879950d1 native modules: Guard against concurrent resolve/reject calls (#53151)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53151

If the native module calls the resolve/reject, resolve/resolve, reject/resolve, reject/reject concurrently, the turbomodule infra could run into a null pointer exception. This diff mitigates that problem.

Changelog: [iOS][Fixed] - Fix concurrent calls into resolve/reject inside native modules

Reviewed By: sanjay-io

Differential Revision: D79824319

fbshipit-source-id: 675264781f303d12fc1eb9649ecdc78601b7720b
2025-08-08 14:39:42 -07:00
Calix Tang e0ea781908 Basic Fantom Tests for Pressable (#53181)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53181

Adds basic Fantom tests for the <Pressable> React Native component.

Following T233710053, adds tests for some of the listed props and refs.

Covered props:
* children
* disabled
* onPress
* style

Ref:
* Pressable is a Native Component and has the correct tag

I did not cover the rest of the listed props due to Fantom not having suitable events to trigger to test them and/or inease of implementing functionality to do so.

## Changelog:

[Internal]

Reviewed By: andrewdacenko

Differential Revision: D79745215

fbshipit-source-id: 26caaabf72ea7ffff3e652616dfd9f0cf7fc2020
2025-08-08 12:56:58 -07:00
Luna Wei b3f397f343 VirtualViewExperimental on iOS (#52852)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52852

Changelog: [Internal] - Implementation of ScrollView-managed VirtualViews for iOS

In previous diffs we've introduced a "VirtualViewExperimental" which is a clone of VirtualView. This diff updates the experimental version to move interection logic (whether something is visible, in prerender-space, etc.) to the ScrollView so there are less listeners. We now use 1 scroll listener vs. N

Reviewed By: philIip

Differential Revision: D78825701

fbshipit-source-id: d515e3cb2dae53d779b5d3f4c317a2c7a6b25857
2025-08-08 11:12:12 -07:00
Zeya Peng 5517c046ab Cache result when RenderOutput::render() is called (#53112)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53112

## Changelog:

[Internal] [Changed] - Cache result when RenderOutput::render() is called

Rreviously, root.getRenderedOutput in fantom doesn't really reflect the result of direct manipulation from native animated (see the test case added here). This stack is enabling it.

* make RenderOutput an instance owned by TestMountingManager that can cache render result
  * why is this needed - native animation's direct manipulation should modify the render result (analog to directly manipulating host views on a platform) instead of props on a StubView
* here i also make sure that `RenderOutput::render()` will only re calculate the render result for a tree after StubViewTree::mutate is called

Reviewed By: andrewdacenko

Differential Revision: D79737991

fbshipit-source-id: ee2193b708e319c1519b06bc672054c4f7105da1
2025-08-08 10:54:05 -07:00
Mateo Guzmán 8ccfff9a46 Migrate ReactBaseTextShadowNode to Kotlin (#52449)
Summary:
Migrate com.facebook.react.views.text.ReactBaseTextShadowNode to Kotlin.

## Changelog:

[Android][Changed] - Migrated ReactBaseTextShadowNode to Kotlin. You might need to update your property access to use camelCase instead of Hungarian notation.

Pull Request resolved: https://github.com/facebook/react-native/pull/52449

Test Plan:
```bash
yarn test-android
yarn android
```

Reviewed By: mdvacca

Differential Revision: D79341403

Pulled By: cortinico

fbshipit-source-id: ff5dd7a8c3e0220812dd3a214d8d680ccd83f4d8
2025-08-08 10:36:32 -07:00
Ruslan Shestopalyuk 0aeb26bdfc e2e test for Text.role (#53176)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53176

# Changelog:
[Internal] -

As in the title

Reviewed By: andrewdacenko

Differential Revision: D79891116

fbshipit-source-id: 13042a9b82373b8e0073c8421e532e6e463d60f8
2025-08-08 10:02:57 -07:00
Ruslan Shestopalyuk 3d37d2d2ce Add test for Text.maxFontSizeMultiplier (#53171)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53171

# Changelog:
[Internal] -

As in the title.

Reviewed By: andrewdacenko

Differential Revision: D79888839

fbshipit-source-id: 52964ce9484c51dc5ff1065343ef9d2f829425c9
2025-08-08 10:02:57 -07:00
Ruslan Shestopalyuk 5a38948034 e2e test for Text.id/nativeID (#53170)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53170

# Changelog:
[Internal] -

As in the title.

Reviewed By: andrewdacenko

Differential Revision: D79887689

fbshipit-source-id: a8a6a16a0fbf3f1481758a2d91c7813d51a4d9d1
2025-08-08 10:02:57 -07:00
Riccardo Cipolleschi 1a58fdf172 Add tests for Modal.animiated prop (#53174)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53174

Add Fantom tests for Modal.animiated prop

Notice that animated is deprecated and ignored when rendering.

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79888036

fbshipit-source-id: aa9003d376f356e9934a61a7cfc958b44d9892eb
2025-08-08 08:52:46 -07:00
Riccardo Cipolleschi 618254d8e9 Add tests for Modal.allowSwipeDismissal prop (#53173)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53173

Add Fantom tests for Modal.allowSwipeDismissal prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79885004

fbshipit-source-id: 9db4bc38c739223a36180d09397bad09ecc67d86
2025-08-08 08:52:46 -07:00
Riccardo Cipolleschi 01e3f8d75e Add tests for Modal.visible prop (#53172)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53172

Add Fantom tests for Modal.visible prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79884676

fbshipit-source-id: 7c3ca4e16596022096a634a7232b616cf15c79c4
2025-08-08 08:52:46 -07:00
Riccardo Cipolleschi 2812e20ecc Add tests for Modal.hardwareAccelerated prop (#53162)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53162

Add Fantom tests for Modal.hardwareAccelerated prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79881565

fbshipit-source-id: 80aaeb0659883d536c37996e86231c9d1d9eff49
2025-08-08 08:52:46 -07:00
Riccardo Cipolleschi 674fd79eaf Add tests for Modal.navigationBarTranslucent prop (#53157)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53157

Add Fantom tests for Modal.navigationBarTranslucent prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79881358

fbshipit-source-id: 75816bf9bb18dc2115477965953fcd88a65d5be5
2025-08-08 08:52:46 -07:00
Riccardo Cipolleschi de76f3436c Add tests for Modal.statusBarTranslucent prop (#53158)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53158

Add Fantom tests for Modal.statusBarTranslucent prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79881104

fbshipit-source-id: 9ee9edbff67059eeb815be2a7a095eac91ec7420
2025-08-08 08:52:46 -07:00
Riccardo Cipolleschi 99ae977345 Add tests for Modal.transparent prop (#53159)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53159

Add Fantom tests for Modal.transparent prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79880909

fbshipit-source-id: f597decb29f578433d6c7ac594327b6130945a8e
2025-08-08 08:52:46 -07:00
Riccardo Cipolleschi fee81401d7 Add tests for Modal.presentationStyle prop (#53160)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53160

Add Fantom tests for Modal.presentationStyle prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79880310

fbshipit-source-id: fda68a481b85e58e5f94d012c71a55cf51b9c8df
2025-08-08 08:52:46 -07:00
Nicola Corti ec9f62865c Update firebase DB url. (#53166)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53166

Our DB doesn't have that suffix, so I'm removing it.

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi

Differential Revision: D79883740

fbshipit-source-id: a52ab275129807cbb6e066baefccd71a8ac7398d
2025-08-08 08:05:54 -07:00
Nicola Corti e16def43c9 Reland: Add tests for DisplayMetricsHolder (#53165)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53165

This is a re-land of D78981753
Those tests were OOM-ing because we were using a old version of robolectric.
I've bumped it and this should fix it.

Changelog:
[Internal] [Changed] -

Reviewed By: lenaic

Differential Revision: D79883742

fbshipit-source-id: 4c2c640d6b601ec07d0a4a12cd7b86a879740a41
2025-08-08 07:09:32 -07:00
Ruslan Shestopalyuk afb6294335 Add Fantom test for Text.selectable (#53168)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53168

# Changelog:
[Internal]-
Adds Fantom test for `Text.selectable` prop.

Reviewed By: andrewdacenko

Differential Revision: D79885301

fbshipit-source-id: d66895397ee0bbcfedc3f744ae8138d2741b2b1e
2025-08-08 06:49:05 -07:00
Ruslan Shestopalyuk 5b9063ed70 E2E test for numberOfLines prop in Text (#53167)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53167

# Changelog
[Internal] -

As in the title.

Reviewed By: andrewdacenko

Differential Revision: D79884649

fbshipit-source-id: fa2d0be9d455449d5a806b06c0480dcefdaaae3e
2025-08-08 06:49:05 -07:00
Ruslan Shestopalyuk 404c975ff2 Prop test for Text.allowFontScaling
Summary:
# Changelog:
[Internal] -

Adds Fantom test for `Text.allowFontScaling`.

Reviewed By: andrewdacenko

Differential Revision: D79882955

fbshipit-source-id: b1426c1e7f2667c2db017d749710320ec1e6aadd
2025-08-08 06:49:05 -07:00
Ruslan Shestopalyuk 91f9ff042d Create e2e test for Text.ellipsizeMode prop (#53163)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53163

# Changelog:
[Internal] -

Adds a Fantom test that tests the `Text.ellipsizeMode` prop.

It also adds a test for the `<Text/>` component without any props

Reviewed By: andrewdacenko

Differential Revision: D79882336

fbshipit-source-id: f938c85092325374f562d610432781e2d412b88e
2025-08-08 06:49:05 -07:00
Riccardo Cipolleschi 20c91f2bd4 Add tests for Modal.animationStyle prop (#53141)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53141

Add Fantom tests for Modal.animationStyle prop

## Changelog:
[Internal] -

Reviewed By: andrewdacenko, rubennorte

Differential Revision: D79808162

fbshipit-source-id: 36ba61bf741dc7cfa7a736fd83a824285304d5b2
2025-08-08 06:47:23 -07:00
Riccardo Cipolleschi 7035391b04 Add basic test for Modal (#53140)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53140

As per title, this change adds the boilerplate code for a Fantom test on Modal

## Changelog:
[Internal] -

Reviewed By: andrewdacenko

Differential Revision: D79805808

fbshipit-source-id: c8c77e576a09b346cf29b290d68c75e540d5f146
2025-08-08 06:47:23 -07:00
Riccardo Cipolleschi e547f466ee Improve codegen to add getDebugProps to components (#53135)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53135

Our Codegenerated components are not generating code for `getDebugProps`. This change modifies Codegen to add those functions for all the codegen components.

## Changelog:
[General][Added] - Added getDebugProps to codegen

## Facebook:
`getDebugProps` are required by Fantom to write tests. However, we can't generate these function for third party components, because codegen can generate arbitrary structs and we don't have a generic `toString()` method that can be used or automatically generated by C++.

By generating this function only for Core Components, we can ensure that we can write Fantom tests without breaking all the users of React Native.

Reviewed By: rubennorte

Differential Revision: D79805145

fbshipit-source-id: 0e41c65fc30eaa886a05557ca233fb0a9cb18a71
2025-08-08 06:47:23 -07:00
Andrew Datsenko 8363a4c515 Add static methods tests (#53087)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53087

Changelog: [Internal]
As title

Reviewed By: lenaic

Differential Revision: D79665922

fbshipit-source-id: 024c10960a59e1332aacf2411a68ca85c17142db
2025-08-08 06:00:58 -07:00
generatedunixname89002005287564 ec3d9c60f1 Fix CQS signal readability-container-size-empty in xplat/js/react-native-github/packages (#53155)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53155

Reviewed By: rshest

Differential Revision: D79788547

fbshipit-source-id: a18465d5c16ab1822c4e9f6302767505fe6f5ee5
2025-08-08 04:24:03 -07:00
Rubén Norte 2f33eece41 Fix retry logic in Fantom when requesting bundles from Metro (#53161)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53161

Changelog: [internal]

This fixes a bug in the retry logic in Fantom when requesting bundles from Metro, where we cache the error from a previous attempt and use it to determine we didn't succeed after the attemps.

Reviewed By: rshest

Differential Revision: D79881488

fbshipit-source-id: 566b2d700db2f9653b9ea9acd577d7eb03770b76
2025-08-08 04:22:16 -07:00
generatedunixname1395667395051502 81fdb9dd93 Update React Native DevTools binaries
Summary:
Automated update of React Native DevTools binaries
bypass-github-export-checks
Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D79836825

fbshipit-source-id: 82484ab99d7813b79bfb75a6c3ad3bd9863f8856
2025-08-08 04:11:28 -07:00
Andrew Datsenko d4ea32493e Revert resizeMode to Stretch as unset (#53144)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53144

Changelog: [Internal]
This is a fix to "unset" prop value for Image.
In my previous diff D79600137 I have changed this behaviour to have Cover as a default, but it is not "default" value, but rather "unset" value.

Reviewed By: rshest

Differential Revision: D79813759

fbshipit-source-id: cc6d43742e51fb2087d6023bd0ff50a3d54eed49
2025-08-08 03:43:06 -07:00
Nicola Corti ba518bbb30 RNGP - Make sure the newArchEnabled is set to true for all the libs (#53138)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53138

Without this patch, library could break if the user removes the `newArchEnabled=`
property from the `gradle.properties` file.

With this patch instead we hardcode the property to true, so all the libraries can consume
it if they wish.

Changelog:
[Internal] [Changed] -

Reviewed By: cipolleschi

Differential Revision: D79805857

fbshipit-source-id: 88dda707a0d80ac79e96c955ded2ef0823f3d3ff
2025-08-08 03:42:35 -07:00
David Vacca 85610c8b43 Deprecate Legacy Architecture UIManagerModules class (#53122)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53122

Deprecate LegacyArchitecture UIManagerModules class

changelog: [Android][Changed] Deprecate LegacyArchitecture UIManagerModules class

Reviewed By: mlord93

Differential Revision: D79672294

fbshipit-source-id: 8a22df4a4341a2ab501fc003ee213fb0047847fc
2025-08-08 02:52:36 -07:00
David Vacca 7f5b2b8f84 Deprecate Legacy Architecture classes belonging to com/facebook/react/uimanager (#53102)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53102

Deprecate large subset of Legacy Architecture classes belonging to com/facebook/react/uimanager

changelog: [Android][Changed] Deprecate LegacyArchitecture classes from com/facebook/react/uimanager

Reviewed By: mlord93

Differential Revision: D79672293

fbshipit-source-id: 2d32eb885af3ec2928510608330740229abf93db
2025-08-08 02:52:36 -07:00
David Vacca 39d24bade3 Deprecate LegacyArchitecture classes from package com.facebook.react.uimanager (#53120)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53120

Deprecate com.facebook.react.uimanager classes

changelog: [Android][Changed] Deprecate LegacyArchitecture classes from package com.facebook.react.uimanager

Reviewed By: mlord93

Differential Revision: D79660036

fbshipit-source-id: 981f7938e54e40f810caec72fa485cc4a00029f6
2025-08-08 02:52:36 -07:00
132 changed files with 3419 additions and 1093 deletions
@@ -46,9 +46,7 @@ describe('FirebaseClient', () => {
expect(client.password).toBe('testpassword');
expect(client.apiKey).toBe('test-api-key');
expect(client.projectId).toBe('test-project');
expect(client.databaseUrl).toBe(
'test-project-default-rtdb.firebaseio.com',
);
expect(client.databaseUrl).toBe('test-project.firebaseio.com');
expect(client.idToken).toBeNull();
});
});
@@ -230,7 +228,7 @@ describe('FirebaseClient', () => {
expect(result).toEqual(mockData);
expect(global.fetch).toHaveBeenCalledWith(
'https://test-project-default-rtdb.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
'https://test-project.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
{
method: 'GET',
headers: {
@@ -275,7 +273,7 @@ describe('FirebaseClient', () => {
await client.makeDatabaseRequest('2023-12-01', 'PUT', testData);
expect(global.fetch).toHaveBeenCalledWith(
'https://test-project-default-rtdb.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
'https://test-project.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
{
method: 'PUT',
headers: {
@@ -301,7 +299,7 @@ describe('FirebaseClient', () => {
await client.storeResults('2023-12-01', results);
expect(global.fetch).toHaveBeenCalledWith(
'https://test-project-default-rtdb.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
'https://test-project.firebaseio.com/nightly-results/2023-12-01.json?auth=existing-token',
{
method: 'PUT',
headers: {
+1 -1
View File
@@ -15,7 +15,7 @@ class FirebaseClient {
this.password = process.env.FIREBASE_APP_PASS;
this.apiKey = process.env.FIREBASE_APP_APIKEY;
this.projectId = process.env.FIREBASE_APP_PROJECTNAME;
this.databaseUrl = `${this.projectId}-default-rtdb.firebaseio.com`;
this.databaseUrl = `${this.projectId}.firebaseio.com`;
this.idToken = null;
}
@@ -1,58 +1,58 @@
#!/usr/bin/env dotslash
// @generated SignedSource<<686df5695b32a90cd465412d979a1a3f>>
// @generated SignedSource<<14de73ea0ed751d80c7c687c6aeb123f>>
{
"name": "React Native DevTools",
"platforms": {
"linux-aarch64": {
"size": 113511487,
"size": 116120331,
"hash": "sha256",
"digest": "c22f7d5e029357f05055ce7c56cc284a0d441d558e103a7b7ebae118c67d0b95",
"digest": "5a1747bdb50f8140d96e99b31f9a603ceaf52e777e5dd59f65edacd87f8c6348",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPRilWDJV8xyKEv9lqYn7Hf2kyZg6nqW8KctGZCXsU95lS_MTFyAmEULrB3J6hGCjqBY2Zl-uq_FjERAIgzbZFWX2eceacTbutBSOKEj6QTZzkVN_L1zPh2lGh24x29MHpkwUzw4E-kAXV43f-11QxqD7orI1QicyOnsmUqeRNKE_QjM9rNRsw6iE8"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQMRq1ou56GjpsIRFHpozEYiPfCuVvgWQVwiMMPBbwKyBnebit8HDGKof5XgDHbAKCqAZSgC8L22eJETnqIUM3kEAMYNXcHviIGy41rsXKVDYDgyWlGFB1zP2WzHrjWagfD062Pt4q5GqvCG5RVlhz656BOsutU7B4pDXGFCIdry7FveKn0PXGxvd1E"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-arm64/React Native DevTools"
},
"linux-x86_64": {
"size": 113244728,
"size": 116056146,
"hash": "sha256",
"digest": "d749aee18d6c969f033511ed631b439c578068cc20786974bc0ee707c6c2f177",
"digest": "b48a3e392ac482de8058917879cf07fd5934dcb84aa901d4fe0d29273b503f54",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQP8NAAXjHJ-9NJThip1nnmVim4yiS1tdYAXmWl2Remiluq5f13nXA8YEadsmGRLWxXz2WJouHXSK47ea4a30fxewyKeTt0niFn3T-lr_91m3Ve5ZS-FOZ_9CRVCkv5zC-Z1FlXJGOnphfWetIU10Pw9tho3IzjdSNlXle0XTrkJ2AyKSl4cKPaX"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOyyb_LXrME2ubBGSkEi1vDw-2hwuHgHwnR-kAGQyhJK7lnELQDXKX1xW_u0joDwbTOhmiptwenq07G2NFkrY3t_AXefb_xTu2qHzpmrsX2YcwJlewbprgbuX7Uvdhqncb_IRAnJ4ogYKHUg6CZBNmLCQsyDsoqmkXtJ9ikJcQeDu2aiqbb-RWJ"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-x64/React Native DevTools"
},
"macos-aarch64": {
"size": 108805847,
"size": 110957864,
"hash": "sha256",
"digest": "dc4a6cfa3d2d8646db8793ef497e43ad72be54bb14ed96345d059880ff72ce1e",
"digest": "7964d83c857f12bb741abf4377771f3f3697b81df6283dd88d75ae43991afb73",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPuZx9G4h30mUDM0hZ8y74LbzAi7-S6jnOqq8uyfDdIptLwIgpb8CKB8F2tduvaBFMGd7obwXd2NVy01r6XKVdgAK5-QTp8PYUPUE7VSCi6QAqobXcQ2uq_lY-jgyj8XkV4Ua4gA6KR609Bmh-beSTOrSqMymqVodaGqoGjB_9jVwfD99_PfFlex-Ta"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQM7USVzavWxZkjOO6CasnSfPIfE08jJAkwfVO0qWiYBli136vpzA_HS89ZqsIsAC_GXeT7K-K9BxdON7z5qBoRMUygAay7z4DGT5OZ9YSf9MDCd0JOzah5_6s3ijw2j4eeRu8ZNYzI3aTutDXtPMJAb2KfBHGx2lEiSW5YK9idcB5Y2boAWeDXXX5nb"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"macos-x86_64": {
"size": 113766610,
"size": 117827315,
"hash": "sha256",
"digest": "74178859ce6a1c26c32055e192b1b123822c76c827ea86a6dfdb5463b89b1ace",
"digest": "bab2fac43def4a82fb88300aac05180eeda24f31cc00402a3ff7ca2e612bd532",
"providers": [
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQN6DjGhr8_L7N_cwrh8pi3cfNcbn9dot_QQpgwe3Vv-780FDgi6JUeMvbo_wbFoT2rogxfHZ0-NbXbKdWYwhGUoGeQuikT57QnVMOYuPUTjlQUgYy0Ng9XPhq3iSEYwlMV1XsUJuPFRUg-hIHcgaaA55JoTLXZ1fLYydhHnmgRxGHc4pxaHvSpTtQ"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQPYS0ZRQ7RV1S-yy3tut6pRqcKdPcOiKfekrA5AXdd_M-HDaXLwJS57iAFU2K2X-EA_cyg25C3L-5L7O3eyNKPMToZHbV282GiojnNSKFNjsjj9_B737lOwHI_XqbDQEIiNJZ7NjbkZ8_iMKK-LNL-Ydha2ORWWqytuzP4sWQ6sm0XIxsdyQ6bOLw"
}
],
"format": "tar.gz",
@@ -29,7 +29,6 @@ import com.facebook.react.utils.JdkConfiguratorUtils.configureJavaToolChains
import com.facebook.react.utils.JsonUtils
import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
import com.facebook.react.utils.PropertyUtils
import com.facebook.react.utils.findPackageJsonFile
import java.io.File
import kotlin.system.exitProcess
@@ -43,7 +42,6 @@ import org.gradle.internal.jvm.Jvm
class ReactPlugin : Plugin<Project> {
override fun apply(project: Project) {
checkJvmVersion(project)
checkLegacyArchProperty(project)
val extension = project.extensions.create("react", ReactExtension::class.java, project)
// We register a private extension on the rootProject so that project wide configs
@@ -116,30 +114,6 @@ class ReactPlugin : Plugin<Project> {
}
}
private fun checkLegacyArchProperty(project: Project) {
if ((project.hasProperty(PropertyUtils.NEW_ARCH_ENABLED) &&
!project.property(PropertyUtils.NEW_ARCH_ENABLED).toString().toBoolean()) ||
(project.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED) &&
!project.property(PropertyUtils.SCOPED_NEW_ARCH_ENABLED).toString().toBoolean())) {
project.logger.error(
"""
********************************************************************************
WARNING: Setting `newArchEnabled=false` in your `gradle.properties` file is not
supported anymore since React Native 0.82.
You can remove the line from your `gradle.properties` file.
The application will run with the New Architecture enabled by default.
********************************************************************************
"""
.trimIndent())
}
}
/** This function configures Android resources - in this case just the bundle */
private fun configureResources(project: Project, reactExtension: ReactExtension) {
project.extensions.getByType(ApplicationAndroidComponentsExtension::class.java).finalizeDsl {
@@ -7,8 +7,10 @@
package com.facebook.react
import com.facebook.react.utils.PropertyUtils
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.extraProperties
/**
* Gradle plugin applied to the `android/build.gradle` file.
@@ -18,13 +20,25 @@ import org.gradle.api.Project
*/
class ReactRootProjectPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.subprojects {
checkLegacyArchProperty(project)
project.subprojects { subproject ->
// As the :app project (i.e. ReactPlugin) configures both namespaces and JVM toolchains
// for libraries, its evaluation must happen before the libraries' evaluation.
// Eventually the configuration of namespace/JVM toolchain can be moved inside this plugin.
if (it.path != ":app") {
it.evaluationDependsOn(":app")
if (subproject.path != ":app") {
subproject.evaluationDependsOn(":app")
}
// We set the New Architecture properties to true for all subprojects. So that
// libraries don't need to be modified and can keep on using the isNewArchEnabled()
// function to check if property is set.
if (subproject.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) {
subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
}
if (subproject.hasProperty(PropertyUtils.NEW_ARCH_ENABLED)) {
subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true")
}
subproject.extraProperties.set(PropertyUtils.NEW_ARCH_ENABLED, "true")
subproject.extraProperties.set(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
}
// We need to make sure that `:app:preBuild` task depends on all other subprojects' preBuild
// tasks. This is necessary in order to have all the codegen generated code before the CMake
@@ -43,4 +57,27 @@ class ReactRootProjectPlugin : Plugin<Project> {
}
}
}
private fun checkLegacyArchProperty(project: Project) {
if ((project.hasProperty(PropertyUtils.NEW_ARCH_ENABLED) &&
!project.property(PropertyUtils.NEW_ARCH_ENABLED).toString().toBoolean()) ||
(project.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED) &&
!project.property(PropertyUtils.SCOPED_NEW_ARCH_ENABLED).toString().toBoolean())) {
project.logger.error(
"""
********************************************************************************
WARNING: Setting `newArchEnabled=false` in your `gradle.properties` file is not
supported anymore since React Native 0.82.
You can remove the line from your `gradle.properties` file.
The application will run with the New Architecture enabled by default.
********************************************************************************
"""
.trimIndent())
}
}
}
@@ -717,7 +717,7 @@ InterfaceOnlyNativeComponentViewProps::InterfaceOnlyNativeComponentViewProps(
const InterfaceOnlyNativeComponentViewProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
title(convertRawProp(context, rawProps, \\"title\\", sourceProps.title, {\\"\\"})) {}
title(convertRawProp(context, rawProps, \\"title\\", sourceProps.title, {std::string{\\"\\"}})) {}
#ifdef RN_SERIALIZABLE_STATE
ComponentName InterfaceOnlyNativeComponentViewProps::getDiffPropsImplementationTarget() const {
@@ -1060,7 +1060,7 @@ StringPropNativeComponentViewProps::StringPropNativeComponentViewProps(
const StringPropNativeComponentViewProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
placeholder(convertRawProp(context, rawProps, \\"placeholder\\", sourceProps.placeholder, {\\"\\"})),
placeholder(convertRawProp(context, rawProps, \\"placeholder\\", sourceProps.placeholder, {std::string{\\"\\"}})),
defaultValue(convertRawProp(context, rawProps, \\"defaultValue\\", sourceProps.defaultValue, {})) {}
#ifdef RN_SERIALIZABLE_STATE
@@ -18,6 +18,7 @@ Object {
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/graphics/RectangleEdges.h>
@@ -89,6 +90,7 @@ static inline std::string toString(const ArrayPropsNativeComponentViewSizesMaskW
struct ArrayPropsNativeComponentViewObjectStruct {
std::string prop{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentViewObjectStruct&) const = default;
@@ -133,6 +135,7 @@ struct ArrayPropsNativeComponentViewArrayOfObjectsStruct {
Float prop1{0.0};
int prop2{0};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentViewArrayOfObjectsStruct&) const = default;
@@ -203,6 +206,8 @@ class ArrayPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -225,6 +230,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -243,6 +249,8 @@ class BooleanPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -265,6 +273,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
namespace facebook::react {
@@ -283,6 +292,8 @@ class ColorPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -306,6 +317,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <yoga/Yoga.h>
namespace facebook::react {
@@ -324,6 +336,8 @@ class DimensionPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -346,6 +360,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -363,6 +378,8 @@ class EdgeInsetsPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -385,6 +402,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -468,6 +486,8 @@ class EnumPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -490,6 +510,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -507,6 +528,8 @@ class EventNestedObjectPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -529,6 +552,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -546,6 +570,8 @@ class EventPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -568,6 +594,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -591,6 +618,8 @@ class FloatPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -613,6 +642,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/imagemanager/primitives.h>
namespace facebook::react {
@@ -631,6 +661,8 @@ class ImagePropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -653,6 +685,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -672,6 +705,8 @@ class IntegerPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -694,6 +729,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -704,13 +740,15 @@ class InterfaceOnlyNativeComponentViewProps final : public ViewProps {
#pragma mark - Props
std::string title{\\"\\"};
std::string title{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
ComponentName getDiffPropsImplementationTarget() const override;
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -733,6 +771,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -750,6 +789,8 @@ class MixedPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -772,6 +813,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -795,6 +837,8 @@ class MultiNativePropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -817,6 +861,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -834,6 +879,8 @@ class NoPropsNoEventsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -858,6 +905,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -918,13 +966,14 @@ static inline folly::dynamic toDynamic(const ObjectPropsNativeComponentIntEnumPr
}
#endif
struct ObjectPropsNativeComponentObjectPropStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
bool booleanProp{false};
Float floatProp{0.0};
int intProp{0};
ObjectPropsNativeComponentStringEnumProp stringEnumProp{ObjectPropsNativeComponentStringEnumProp::Small};
ObjectPropsNativeComponentIntEnumProp intEnumProp{ObjectPropsNativeComponentIntEnumProp::IntEnumProp0};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectPropStruct&) const = default;
@@ -983,6 +1032,7 @@ static inline folly::dynamic toDynamic(const ObjectPropsNativeComponentObjectPro
struct ObjectPropsNativeComponentObjectArrayPropStruct {
std::vector<std::string> array{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectArrayPropStruct&) const = default;
@@ -1018,6 +1068,7 @@ struct ObjectPropsNativeComponentObjectPrimitiveRequiredPropStruct {
SharedColor color{};
Point point{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectPrimitiveRequiredPropStruct&) const = default;
@@ -1073,6 +1124,8 @@ class ObjectPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1095,6 +1148,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Point.h>
namespace facebook::react {
@@ -1113,6 +1167,8 @@ class PointPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1135,6 +1191,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1145,7 +1202,7 @@ class StringPropNativeComponentViewProps final : public ViewProps {
#pragma mark - Props
std::string placeholder{\\"\\"};
std::string placeholder{std::string{\\"\\"}};
std::string defaultValue{};
#ifdef RN_SERIALIZABLE_STATE
@@ -1153,6 +1210,8 @@ class StringPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -20,6 +20,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ArrayPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ArrayPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ArrayPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -94,6 +95,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class BooleanPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & BooleanPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public BooleanPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -136,6 +138,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ColorPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ColorPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ColorPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -175,6 +178,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class DimensionPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & DimensionPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public DimensionPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -213,6 +217,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EdgeInsetsPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EdgeInsetsPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EdgeInsetsPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -245,6 +250,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EnumPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EnumPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EnumPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -286,6 +292,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventNestedObjectPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventNestedObjectPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventNestedObjectPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -324,6 +331,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -362,6 +370,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class FloatPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & FloatPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public FloatPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -419,6 +428,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ImagePropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ImagePropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ImagePropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -457,6 +467,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class IntegerPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & IntegerPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public IntegerPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -501,6 +512,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InterfaceOnlyNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InterfaceOnlyNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InterfaceOnlyNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -540,6 +552,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MixedPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MixedPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MixedPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -580,6 +593,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiNativePropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiNativePropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiNativePropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -627,6 +641,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class NoPropsNoEventsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & NoPropsNoEventsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public NoPropsNoEventsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -660,6 +675,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ObjectPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ObjectPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ObjectPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -705,6 +721,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class PointPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & PointPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public PointPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -743,6 +760,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class StringPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StringPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public StringPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -717,7 +717,7 @@ InterfaceOnlyNativeComponentViewProps::InterfaceOnlyNativeComponentViewProps(
const InterfaceOnlyNativeComponentViewProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
title(convertRawProp(context, rawProps, \\"title\\", sourceProps.title, {\\"\\"})) {}
title(convertRawProp(context, rawProps, \\"title\\", sourceProps.title, {std::string{\\"\\"}})) {}
#ifdef RN_SERIALIZABLE_STATE
ComponentName InterfaceOnlyNativeComponentViewProps::getDiffPropsImplementationTarget() const {
@@ -1060,7 +1060,7 @@ StringPropNativeComponentViewProps::StringPropNativeComponentViewProps(
const StringPropNativeComponentViewProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
placeholder(convertRawProp(context, rawProps, \\"placeholder\\", sourceProps.placeholder, {\\"\\"})),
placeholder(convertRawProp(context, rawProps, \\"placeholder\\", sourceProps.placeholder, {std::string{\\"\\"}})),
defaultValue(convertRawProp(context, rawProps, \\"defaultValue\\", sourceProps.defaultValue, {})) {}
#ifdef RN_SERIALIZABLE_STATE
@@ -18,6 +18,7 @@ Object {
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/graphics/RectangleEdges.h>
@@ -89,6 +90,7 @@ static inline std::string toString(const ArrayPropsNativeComponentViewSizesMaskW
struct ArrayPropsNativeComponentViewObjectStruct {
std::string prop{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentViewObjectStruct&) const = default;
@@ -133,6 +135,7 @@ struct ArrayPropsNativeComponentViewArrayOfObjectsStruct {
Float prop1{0.0};
int prop2{0};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentViewArrayOfObjectsStruct&) const = default;
@@ -203,6 +206,8 @@ class ArrayPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -225,6 +230,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -243,6 +249,8 @@ class BooleanPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -265,6 +273,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
namespace facebook::react {
@@ -283,6 +292,8 @@ class ColorPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -306,6 +317,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <yoga/Yoga.h>
namespace facebook::react {
@@ -324,6 +336,8 @@ class DimensionPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -346,6 +360,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -363,6 +378,8 @@ class EdgeInsetsPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -385,6 +402,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -468,6 +486,8 @@ class EnumPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -490,6 +510,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -507,6 +528,8 @@ class EventNestedObjectPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -529,6 +552,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -546,6 +570,8 @@ class EventPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -568,6 +594,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -591,6 +618,8 @@ class FloatPropsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -613,6 +642,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/imagemanager/primitives.h>
namespace facebook::react {
@@ -631,6 +661,8 @@ class ImagePropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -653,6 +685,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -672,6 +705,8 @@ class IntegerPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -694,6 +729,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -704,13 +740,15 @@ class InterfaceOnlyNativeComponentViewProps final : public ViewProps {
#pragma mark - Props
std::string title{\\"\\"};
std::string title{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
ComponentName getDiffPropsImplementationTarget() const override;
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -733,6 +771,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -750,6 +789,8 @@ class MixedPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -772,6 +813,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -795,6 +837,8 @@ class MultiNativePropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -817,6 +861,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -834,6 +879,8 @@ class NoPropsNoEventsNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -858,6 +905,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -918,13 +966,14 @@ static inline folly::dynamic toDynamic(const ObjectPropsNativeComponentIntEnumPr
}
#endif
struct ObjectPropsNativeComponentObjectPropStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
bool booleanProp{false};
Float floatProp{0.0};
int intProp{0};
ObjectPropsNativeComponentStringEnumProp stringEnumProp{ObjectPropsNativeComponentStringEnumProp::Small};
ObjectPropsNativeComponentIntEnumProp intEnumProp{ObjectPropsNativeComponentIntEnumProp::IntEnumProp0};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectPropStruct&) const = default;
@@ -983,6 +1032,7 @@ static inline folly::dynamic toDynamic(const ObjectPropsNativeComponentObjectPro
struct ObjectPropsNativeComponentObjectArrayPropStruct {
std::vector<std::string> array{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectArrayPropStruct&) const = default;
@@ -1018,6 +1068,7 @@ struct ObjectPropsNativeComponentObjectPrimitiveRequiredPropStruct {
SharedColor color{};
Point point{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsNativeComponentObjectPrimitiveRequiredPropStruct&) const = default;
@@ -1073,6 +1124,8 @@ class ObjectPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1095,6 +1148,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Point.h>
namespace facebook::react {
@@ -1113,6 +1167,8 @@ class PointPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1135,6 +1191,7 @@ Object {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1145,7 +1202,7 @@ class StringPropNativeComponentViewProps final : public ViewProps {
#pragma mark - Props
std::string placeholder{\\"\\"};
std::string placeholder{std::string{\\"\\"}};
std::string defaultValue{};
#ifdef RN_SERIALIZABLE_STATE
@@ -1153,6 +1210,8 @@ class StringPropNativeComponentViewProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -20,6 +20,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ArrayPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ArrayPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ArrayPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -94,6 +95,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class BooleanPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & BooleanPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public BooleanPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -136,6 +138,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ColorPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ColorPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ColorPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -175,6 +178,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class DimensionPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & DimensionPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public DimensionPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -213,6 +217,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EdgeInsetsPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EdgeInsetsPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EdgeInsetsPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -245,6 +250,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EnumPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EnumPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EnumPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -286,6 +292,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventNestedObjectPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventNestedObjectPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventNestedObjectPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -324,6 +331,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -362,6 +370,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class FloatPropsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & FloatPropsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public FloatPropsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -419,6 +428,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ImagePropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ImagePropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ImagePropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -457,6 +467,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class IntegerPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & IntegerPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public IntegerPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -501,6 +512,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InterfaceOnlyNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InterfaceOnlyNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InterfaceOnlyNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -540,6 +552,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MixedPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MixedPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MixedPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -580,6 +593,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiNativePropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiNativePropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiNativePropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -627,6 +641,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class NoPropsNoEventsNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & NoPropsNoEventsNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public NoPropsNoEventsNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -660,6 +675,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ObjectPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ObjectPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ObjectPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -705,6 +721,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class PointPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & PointPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public PointPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -743,6 +760,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class StringPropNativeComponentViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StringPropNativeComponentViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public StringPropNativeComponentViewManagerDelegate(U viewManager) {
super(viewManager);
@@ -46,9 +46,17 @@ try {
} catch (err) {
throw new Error(`Can't parse schema to JSON. ${schemaPath}`);
}
const includeGetDebugPropsImplementation: boolean =
libraryName.includes('FBReactNativeSpec');
RNCodegen.generate(
{libraryName, schema, outputDirectory, packageName, assumeNonnull},
{
libraryName,
schema,
outputDirectory,
packageName,
assumeNonnull,
includeGetDebugPropsImplementation,
},
{
generators: [
'descriptors',
@@ -81,6 +81,7 @@ export type GenerateFunction = (
packageName?: string,
assumeNonnull: boolean,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean,
) => FilesOutput;
export type LibraryGeneratorsFunctions = $ReadOnly<{
@@ -94,6 +95,7 @@ export type LibraryOptions = $ReadOnly<{
packageName?: string, // Some platforms have a notion of package, which should be configurable.
assumeNonnull: boolean,
useLocalIncludePaths?: boolean,
includeGetDebugPropsImplementation?: boolean,
libraryGenerators?: LibraryGeneratorsFunctions,
}>;
@@ -255,6 +257,7 @@ module.exports = {
packageName,
assumeNonnull,
useLocalIncludePaths,
includeGetDebugPropsImplementation = false,
libraryGenerators = LIBRARY_GENERATORS,
}: LibraryOptions,
{generators, test}: LibraryConfig,
@@ -299,6 +302,7 @@ module.exports = {
packageName,
assumeNonnull,
headerPrefix,
includeGetDebugPropsImplementation,
).forEach((contents: string, fileName: string) => {
generatedFiles.push({
name: fileName,
@@ -190,7 +190,7 @@ function convertDefaultTypeToString(
if (typeAnnotation.default == null) {
return '';
}
return `"${typeAnnotation.default}"`;
return `std::string{"${typeAnnotation.default}"}`;
case 'Int32TypeAnnotation':
return String(typeAnnotation.default);
case 'DoubleTypeAnnotation':
@@ -61,6 +61,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'ComponentDescriptors.cpp';
@@ -63,6 +63,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'ComponentDescriptors.h';
@@ -381,6 +381,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'RCTComponentViewHelpers.h';
@@ -413,6 +413,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const moduleComponents: ComponentCollection = Object.keys(schema.modules)
.map(moduleName => {
@@ -320,6 +320,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const moduleComponents: ComponentCollection = Object.keys(schema.modules)
.map(moduleName => {
@@ -77,6 +77,8 @@ function generatePropsDiffString(
className: string,
componentName: string,
component: ComponentShape,
debugProps: string = '',
includeGetDebugPropsImplementation?: boolean = false,
) {
const diffProps = component.props
.map(prop => {
@@ -134,6 +136,12 @@ function generatePropsDiffString(
})
.join('\n' + ' ');
const getDebugPropsString = `#if RN_DEBUG_STRING_CONVERTIBLE
SharedDebugStringConvertibleList ${className}::getDebugProps() const {
return ViewProps::getDebugProps()${debugProps && debugProps.length > 0 ? ` +\n\t\tSharedDebugStringConvertibleList{${debugProps}\n\t}` : ''};
}
#endif`;
return `
#ifdef RN_SERIALIZABLE_STATE
ComponentName ${className}::getDiffPropsImplementationTarget() const {
@@ -153,8 +161,11 @@ folly::dynamic ${className}::getDiffProps(
${diffProps}
return result;
}
#endif`;
#endif
${includeGetDebugPropsImplementation ? getDebugPropsString : ''}
`;
}
function generatePropsString(componentName: string, component: ComponentShape) {
return component.props
.map(prop => {
@@ -170,6 +181,24 @@ function generatePropsString(componentName: string, component: ComponentShape) {
.join(',\n' + ' ');
}
function generateDebugPropsString(
componentName: string,
component: ComponentShape,
) {
return component.props
.map(prop => {
if (prop.typeAnnotation.type === 'ObjectTypeAnnotation') {
// Skip ObjectTypeAnnotation because there is no generic `toString`
// method for it. We would have to define an interface that the structs implement.
return '';
}
const defaultValue = convertDefaultTypeToString(componentName, prop);
return `\n\t\t\tdebugStringConvertibleItem("${prop.name}", ${prop.name}${defaultValue ? `, ${defaultValue}` : ''})`;
})
.join(',');
}
function getClassExtendString(component: ComponentShape): string {
const extendString =
' ' +
@@ -202,6 +231,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'Props.cpp';
const allImports: Set<string> = new Set([
@@ -209,6 +239,13 @@ module.exports = {
'#include <react/renderer/core/PropsParserContext.h>',
]);
if (includeGetDebugPropsImplementation) {
allImports.add('#include <react/renderer/core/graphicsConversions.h>');
allImports.add(
'#include <react/renderer/debug/debugStringConvertibleUtils.h>',
);
}
const componentProps = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
@@ -229,10 +266,15 @@ module.exports = {
const propsString = generatePropsString(componentName, component);
const extendString = getClassExtendString(component);
const debugProps = includeGetDebugPropsImplementation
? generateDebugPropsString(componentName, component)
: '';
const diffPropsString = generatePropsDiffString(
newName,
componentName,
component,
debugProps,
includeGetDebugPropsImplementation,
);
const imports = getImports(component.props);
@@ -65,14 +65,20 @@ const ClassTemplate = ({
className,
props,
extendClasses,
includeGetDebugPropsImplementation,
}: {
enums: string,
structs: string,
className: string,
props: string,
extendClasses: string,
}) =>
`
includeGetDebugPropsImplementation: boolean,
}) => {
const getDebugPropsString = `#if RN_DEBUG_STRING_CONVERTIBLE
SharedDebugStringConvertibleList getDebugProps() const override;
#endif`;
return `
${enums}
${structs}
class ${className} final${extendClasses} {
@@ -89,8 +95,11 @@ class ${className} final${extendClasses} {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
${includeGetDebugPropsImplementation ? getDebugPropsString : ''}
};
`.trim();
};
const EnumTemplate = ({
enumName,
@@ -178,6 +187,7 @@ const StructTemplate = ({
`struct ${structName} {
${fields}
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ${structName}&) const = default;
@@ -536,6 +546,7 @@ function getExtendsImports(
const imports: Set<string> = new Set();
imports.add('#include <react/renderer/core/PropsParserContext.h>');
imports.add('#include <react/renderer/debug/DebugStringConvertible.h>');
extendsProps.forEach(extendProps => {
switch (extendProps.type) {
@@ -783,6 +794,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'Props.h';
@@ -831,6 +843,7 @@ module.exports = {
className: newName,
extendClasses: extendString,
props: propsString,
includeGetDebugPropsImplementation,
});
return replacedTemplate;
@@ -55,6 +55,7 @@ package ${packageName};
${imports}
@SuppressWarnings("deprecation")
public class ${className}<T extends ${extendClasses}, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ${interfaceClassName}<T>> extends BaseViewManagerDelegate<T, U> {
public ${className}(U viewManager) {
super(viewManager);
@@ -299,6 +300,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
// TODO: This doesn't support custom package name yet.
const normalizedPackageName = 'com.facebook.react.viewmanagers';
@@ -238,6 +238,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
// TODO: This doesn't support custom package name yet.
const normalizedPackageName = 'com.facebook.react.viewmanagers';
@@ -54,6 +54,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'ShadowNodes.cpp';
@@ -74,6 +74,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'ShadowNodes.h';
@@ -50,6 +50,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'States.cpp';
@@ -57,6 +57,7 @@ module.exports = {
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
includeGetDebugPropsImplementation?: boolean = false,
): FilesOutput {
const fileName = 'States.h';
@@ -347,7 +347,7 @@ CommandNativeComponentProps::CommandNativeComponentProps(
const CommandNativeComponentProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {\\"\\"})) {}
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {std::string{\\"\\"}})) {}
#ifdef RN_SERIALIZABLE_STATE
ComponentName CommandNativeComponentProps::getDiffPropsImplementationTarget() const {
@@ -1168,7 +1168,7 @@ InterfaceOnlyComponentProps::InterfaceOnlyComponentProps(
const InterfaceOnlyComponentProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {\\"\\"})) {}
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {std::string{\\"\\"}})) {}
#ifdef RN_SERIALIZABLE_STATE
ComponentName InterfaceOnlyComponentProps::getDiffPropsImplementationTarget() const {
@@ -1554,7 +1554,7 @@ StringPropComponentProps::StringPropComponentProps(
const StringPropComponentProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {\\"\\"})),
accessibilityHint(convertRawProp(context, rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, {std::string{\\"\\"}})),
accessibilityRole(convertRawProp(context, rawProps, \\"accessibilityRole\\", sourceProps.accessibilityRole, {})) {}
#ifdef RN_SERIALIZABLE_STATE
@@ -18,6 +18,7 @@ Map {
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -86,7 +87,8 @@ static inline std::string toString(const ArrayPropsNativeComponentSizesMaskWrapp
return result;
}
struct ArrayPropsNativeComponentObjectStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentObjectStruct&) const = default;
@@ -129,7 +131,8 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
struct ArrayPropsNativeComponentArrayObjectStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentArrayObjectStruct&) const = default;
@@ -174,6 +177,7 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
struct ArrayPropsNativeComponentArrayStruct {
std::vector<ArrayPropsNativeComponentArrayObjectStruct> object{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentArrayStruct&) const = default;
@@ -215,7 +219,8 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
struct ArrayPropsNativeComponentArrayOfArrayOfObjectStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentArrayOfArrayOfObjectStruct&) const = default;
@@ -286,6 +291,8 @@ class ArrayPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -310,6 +317,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -322,6 +330,7 @@ struct ArrayPropsNativeComponentNativePrimitivesStruct {
std::vector<ImageSource> srcs{};
std::vector<Point> points{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ArrayPropsNativeComponentNativePrimitivesStruct&) const = default;
@@ -385,6 +394,8 @@ class ArrayPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -407,6 +418,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -424,6 +436,8 @@ class BooleanPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -446,6 +460,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
namespace facebook::react {
@@ -464,6 +479,8 @@ class ColorPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -486,6 +503,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -503,6 +521,8 @@ class CommandNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -525,6 +545,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -535,13 +556,15 @@ class CommandNativeComponentProps final : public ViewProps {
#pragma mark - Props
std::string accessibilityHint{\\"\\"};
std::string accessibilityHint{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
ComponentName getDiffPropsImplementationTarget() const override;
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -565,6 +588,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <yoga/Yoga.h>
namespace facebook::react {
@@ -583,6 +607,8 @@ class DimensionPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -605,6 +631,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -627,6 +654,8 @@ class DoublePropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -649,6 +678,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -666,6 +696,8 @@ class EventsNestedObjectNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -688,6 +720,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -705,6 +738,8 @@ class EventsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -727,6 +762,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -744,6 +780,8 @@ class InterfaceOnlyComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -766,6 +804,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -783,6 +822,8 @@ class ExcludedAndroidComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -805,6 +846,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -822,6 +864,8 @@ class ExcludedAndroidIosComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -844,6 +888,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -861,6 +906,8 @@ class ExcludedIosComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
class MultiFileIncludedNativeComponentProps final : public ViewProps {
@@ -877,6 +924,8 @@ class MultiFileIncludedNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -899,6 +948,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -921,6 +971,8 @@ class FloatPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -943,6 +995,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/imagemanager/primitives.h>
namespace facebook::react {
@@ -961,6 +1014,8 @@ class ImagePropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -983,6 +1038,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/RectangleEdges.h>
namespace facebook::react {
@@ -1001,6 +1057,8 @@ class InsetsPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1023,6 +1081,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1077,6 +1136,8 @@ class Int32EnumPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1099,6 +1160,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1118,6 +1180,8 @@ class IntegerPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1140,6 +1204,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1150,13 +1215,15 @@ class InterfaceOnlyComponentProps final : public ViewProps {
#pragma mark - Props
std::string accessibilityHint{\\"\\"};
std::string accessibilityHint{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
ComponentName getDiffPropsImplementationTarget() const override;
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1179,6 +1246,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1196,6 +1264,8 @@ class MixedPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1218,6 +1288,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -1241,6 +1312,8 @@ class ImageColorPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1263,6 +1336,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1280,6 +1354,8 @@ class NoPropsNoEventsComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1304,6 +1380,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Point.h>
#include <react/renderer/imagemanager/primitives.h>
@@ -1359,6 +1436,7 @@ static inline folly::dynamic toDynamic(const ObjectPropsIntEnumProp &value) {
struct ObjectPropsObjectPropObjectArrayPropStruct {
std::vector<std::string> array{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropObjectArrayPropStruct&) const = default;
@@ -1394,6 +1472,7 @@ struct ObjectPropsObjectPropObjectPrimitiveRequiredPropStruct {
SharedColor color{};
Point point{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropObjectPrimitiveRequiredPropStruct&) const = default;
@@ -1435,7 +1514,8 @@ static inline folly::dynamic toDynamic(const ObjectPropsObjectPropObjectPrimitiv
#endif
struct ObjectPropsObjectPropNestedPropANestedPropBStruct {
std::string nestedPropC{\\"\\"};
std::string nestedPropC{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropNestedPropANestedPropBStruct&) const = default;
@@ -1470,6 +1550,7 @@ static inline folly::dynamic toDynamic(const ObjectPropsObjectPropNestedPropANes
struct ObjectPropsObjectPropNestedPropAStruct {
ObjectPropsObjectPropNestedPropANestedPropBStruct nestedPropB{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropNestedPropAStruct&) const = default;
@@ -1501,7 +1582,8 @@ static inline folly::dynamic toDynamic(const ObjectPropsObjectPropNestedPropAStr
#endif
struct ObjectPropsObjectPropNestedArrayAsPropertyArrayPropStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropNestedArrayAsPropertyArrayPropStruct&) const = default;
@@ -1546,6 +1628,7 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
struct ObjectPropsObjectPropNestedArrayAsPropertyStruct {
std::vector<ObjectPropsObjectPropNestedArrayAsPropertyArrayPropStruct> arrayProp{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropNestedArrayAsPropertyStruct&) const = default;
@@ -1577,11 +1660,11 @@ static inline folly::dynamic toDynamic(const ObjectPropsObjectPropNestedArrayAsP
#endif
struct ObjectPropsObjectPropStruct {
std::string stringProp{\\"\\"};
std::string stringProp{std::string{\\"\\"}};
bool booleanProp{false};
Float floatProp{0.0};
int intProp{0};
std::string stringUserDefaultProp{\\"user_default\\"};
std::string stringUserDefaultProp{std::string{\\"user_default\\"}};
bool booleanUserDefaultProp{true};
Float floatUserDefaultProp{3.14};
int intUserDefaultProp{9999};
@@ -1592,6 +1675,7 @@ struct ObjectPropsObjectPropStruct {
ObjectPropsObjectPropNestedPropAStruct nestedPropA{};
ObjectPropsObjectPropNestedArrayAsPropertyStruct nestedArrayAsProperty{};
#ifdef RN_SERIALIZABLE_STATE
bool operator==(const ObjectPropsObjectPropStruct&) const = default;
@@ -1700,6 +1784,8 @@ class ObjectPropsProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1722,6 +1808,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/graphics/Point.h>
namespace facebook::react {
@@ -1740,6 +1827,8 @@ class PointPropNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1762,6 +1851,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1803,6 +1893,8 @@ class StringEnumPropsNativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1825,6 +1917,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1835,7 +1928,7 @@ class StringPropComponentProps final : public ViewProps {
#pragma mark - Props
std::string accessibilityHint{\\"\\"};
std::string accessibilityHint{std::string{\\"\\"}};
std::string accessibilityRole{};
#ifdef RN_SERIALIZABLE_STATE
@@ -1843,6 +1936,8 @@ class StringPropComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1865,6 +1960,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1882,6 +1978,8 @@ class MultiFile1NativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
class MultiFile2NativeComponentProps final : public ViewProps {
@@ -1898,6 +1996,8 @@ class MultiFile2NativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -1920,6 +2020,7 @@ Map {
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
@@ -1937,6 +2038,8 @@ class MultiComponent1NativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
class MultiComponent2NativeComponentProps final : public ViewProps {
@@ -1953,6 +2056,8 @@ class MultiComponent2NativeComponentProps final : public ViewProps {
folly::dynamic getDiffProps(const Props* prevProps) const override;
#endif
};
} // namespace facebook::react
@@ -20,6 +20,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ArrayPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ArrayPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ArrayPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -95,6 +96,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ArrayPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ArrayPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ArrayPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -133,6 +135,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class BooleanPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & BooleanPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public BooleanPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -172,6 +175,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ColorPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ColorPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ColorPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -211,6 +215,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class CommandNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & CommandNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public CommandNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -256,6 +261,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class CommandNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & CommandNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public CommandNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -310,6 +316,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class DimensionPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & DimensionPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public DimensionPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -348,6 +355,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class DoublePropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & DoublePropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public DoublePropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -401,6 +409,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventsNestedObjectNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventsNestedObjectNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventsNestedObjectNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -439,6 +448,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class EventsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EventsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public EventsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -477,6 +487,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InterfaceOnlyComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InterfaceOnlyComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InterfaceOnlyComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -513,6 +524,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ExcludedIosComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ExcludedIosComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ExcludedIosComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -540,6 +552,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiFileIncludedNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiFileIncludedNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiFileIncludedNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -578,6 +591,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class FloatPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & FloatPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public FloatPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -632,6 +646,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ImagePropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ImagePropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ImagePropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -671,6 +686,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InsetsPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InsetsPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InsetsPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -709,6 +725,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class Int32EnumPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & Int32EnumPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public Int32EnumPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -747,6 +764,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class IntegerPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & IntegerPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public IntegerPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -791,6 +809,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class InterfaceOnlyComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & InterfaceOnlyComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public InterfaceOnlyComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -830,6 +849,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MixedPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MixedPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MixedPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -870,6 +890,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ImageColorPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ImageColorPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ImageColorPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -917,6 +938,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class NoPropsNoEventsComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & NoPropsNoEventsComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public NoPropsNoEventsComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -950,6 +972,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class ObjectPropsManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & ObjectPropsManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public ObjectPropsManagerDelegate(U viewManager) {
super(viewManager);
@@ -989,6 +1012,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class PointPropNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & PointPropNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public PointPropNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1027,6 +1051,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class StringEnumPropsNativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StringEnumPropsNativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public StringEnumPropsNativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1065,6 +1090,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class StringPropComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StringPropComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public StringPropComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1106,6 +1132,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiFile1NativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiFile1NativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiFile1NativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1139,6 +1166,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiFile2NativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiFile2NativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiFile2NativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1177,6 +1205,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiComponent1NativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiComponent1NativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiComponent1NativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -1210,6 +1239,7 @@ import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
@SuppressWarnings(\\"deprecation\\")
public class MultiComponent2NativeComponentManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & MultiComponent2NativeComponentManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
public MultiComponent2NativeComponentManagerDelegate(U viewManager) {
super(viewManager);
@@ -0,0 +1,186 @@
/**
* 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.
*
* @flow strict-local
* @format
* @oncall react_native
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {Pressable} from 'react-native';
import {Text} from 'react-native';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
describe('<Pressable>', () => {
describe('props', () => {
describe('style', () => {
it('can be set with ViewStyle', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Pressable
style={{
width: 100,
height: 50,
backgroundColor: 'blue',
borderColor: 'red',
borderWidth: 3,
opacity: 40,
}}
/>,
);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-view
accessible="true"
backgroundColor="rgba(0, 0, 255, 1)"
borderWidth="3.000000"
height="50.000000"
opacity="40"
width="100.000000"
/>,
);
});
it('function that receives a boolean reflecting whether the component is currently pressed ', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Pressable
style={({pressed}) => ({
backgroundColor: pressed ? 'red' : 'gray',
})}
/>,
);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-view
accessible="true"
backgroundColor="rgba(128, 128, 128, 1)"
/>,
);
});
});
describe('onPress', () => {
it('triggers callback when the element is pressed', () => {
const elementRef = createRef<HostInstance>();
const onPressCallback = jest.fn();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Pressable
ref={elementRef}
onPress={onPressCallback}
style={{height: 100}}
/>,
);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
Fantom.dispatchNativeEvent(element, 'click');
expect(onPressCallback).toHaveBeenCalledTimes(1);
});
});
describe('disabled', () => {
it('cannot be pressed', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
const onPressCallback = jest.fn();
Fantom.runTask(() => {
root.render(
<Pressable
ref={elementRef}
onPress={onPressCallback}
disabled={true}
/>,
);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
Fantom.dispatchNativeEvent(element, 'change', {value: true});
expect(onPressCallback).toHaveBeenCalledTimes(0);
});
});
describe('children', () => {
it('adds children to the component', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Pressable ref={elementRef}>
<Text>the quick brown fox</Text>
</Pressable>,
);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.childNodes.length).toBe(1);
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-view accessible="true">
<rn-paragraph
allowFontScaling="true"
ellipsizeMode="tail"
fontSize="NaN"
fontSizeMultiplier="NaN"
foregroundColor="rgba(0, 0, 0, 0)">
the quick brown fox
</rn-paragraph>
</rn-view>,
);
});
});
});
describe('ref', () => {
describe('instance', () => {
it('is an element node', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Pressable ref={elementRef} />);
});
expect(elementRef.current).toBeInstanceOf(ReactNativeElement);
});
it('uses the "RN:View" tag name', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Pressable ref={elementRef} />);
});
const element = ensureInstance(elementRef.current, ReactNativeElement);
// Pressable is implemented with a <View> under the hood
expect(element.tagName).toBe('RN:View');
});
});
});
});
+197 -18
View File
@@ -17,6 +17,7 @@ import * as React from 'react';
import {createRef} from 'react';
import {Image} from 'react-native';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import NativeFantom from 'react-native/src/private/testing/fantom/specs/NativeFantom';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
const LOGO_SOURCE = {uri: 'https://reactnative.dev/img/tiny_logo.png'};
@@ -33,7 +34,12 @@ describe('<Image>', () => {
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-image overflow="hidden" source-scale="1" source-type="remote" />,
<rn-image
overflow="hidden"
source-scale="1"
source-type="remote"
resizeMode="cover"
/>,
);
Fantom.runTask(() => {
@@ -41,7 +47,12 @@ describe('<Image>', () => {
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-image overflow="hidden" source-scale="1" source-type="remote" />,
<rn-image
overflow="hidden"
source-scale="1"
source-type="remote"
resizeMode="cover"
/>,
);
});
});
@@ -312,35 +323,47 @@ describe('<Image>', () => {
});
expect(root.getRenderedOutput({props: ['resizeMode']}).toJSX()).toEqual(
<rn-image />,
<rn-image resizeMode="cover" />,
);
});
it('can be set to "cover" explicitly', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Image resizeMode="cover" source={LOGO_SOURCE} />);
});
expect(root.getRenderedOutput({props: ['resizeMode']}).toJSX()).toEqual(
<rn-image resizeMode="cover" />,
);
});
it('can be set to "stretch", which is the same as not setting it', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Image resizeMode="stretch" source={LOGO_SOURCE} />);
});
expect(root.getRenderedOutput({props: ['resizeMode']}).toJSX()).toEqual(
<rn-image />,
);
});
(['stretch', 'contain', 'repeat', 'center'] as const).forEach(
resizeMode => {
it(`can be set to "${resizeMode}"`, () => {
const root = Fantom.createRoot();
(['contain', 'repeat', 'center'] as const).forEach(resizeMode => {
it(`can be set to "${resizeMode}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Image resizeMode={resizeMode} source={LOGO_SOURCE} />,
);
});
expect(
root.getRenderedOutput({props: ['resizeMode']}).toJSX(),
).toEqual(<rn-image resizeMode={resizeMode} />);
Fantom.runTask(() => {
root.render(<Image resizeMode={resizeMode} source={LOGO_SOURCE} />);
});
},
);
expect(
root.getRenderedOutput({props: ['resizeMode']}).toJSX(),
).toEqual(<rn-image resizeMode={resizeMode} />);
});
});
});
describe('source', () => {
@@ -653,4 +676,160 @@ describe('<Image>', () => {
});
});
});
describe('static methods', () => {
afterEach(() => {
NativeFantom.clearAllImages();
});
describe('getSize', () => {
it('returns the size of the image when image is loaded', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
});
let size;
Fantom.runTask(() => {
Image.getSize(uri, (width, height) => {
size = {width, height};
});
});
expect(size).toEqual({width: 100, height: 100});
});
it('fails when image is not loaded', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
let size;
let err: ?Error;
Fantom.runTask(async () => {
Image.getSize(
uri,
(width, height) => {
size = {width, height};
},
(e: mixed) => {
if (e instanceof Error) {
err = e;
}
},
);
});
expect(size).toBeUndefined();
expect(err).toBeInstanceOf(Error);
expect(err?.message).toBe('image not loaded');
});
});
describe('getSizeWithHeaders', () => {
afterEach(() => {
NativeFantom.clearAllImages();
});
it('returns the size of the image when image is loaded', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
});
let size;
Fantom.runTask(() => {
Image.getSizeWithHeaders(
uri,
{
Authorization: 'Basic RandomString',
},
(width: number, height: number) => {
size = {width, height};
},
);
});
expect(size).toEqual({width: 100, height: 100});
});
});
describe('prefetch', () => {
it('prefetches the image', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
});
let result;
Fantom.runTask(async () => {
result = await Image.prefetch(uri);
});
expect(result).toEqual(true);
});
it('can fail to prefetch image', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
errorMessage: 'Failed to prefetch image',
});
let result;
let error;
Fantom.runTask(async () => {
try {
result = await Image.prefetch(uri);
} catch (e) {
error = e;
}
});
expect(result).toEqual(undefined);
expect(error).toBeInstanceOf(Error);
expect(error?.message).toBe('Failed to prefetch image');
});
});
describe('queryCache', () => {
it('returns empty when image is not cached', () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
let result;
Fantom.runTask(async () => {
result = await Image.queryCache([uri]);
});
expect(result).toEqual({});
});
(['disk', 'memory', 'disk/memory'] as const).forEach(cacheStatus => {
it(`returns the '${cacheStatus}' record when image is cached`, () => {
const uri = 'https://reactnative.dev/img/tiny_logo.png';
NativeFantom.setImageResponse(uri, {
width: 100,
height: 100,
cacheStatus,
});
let result;
Fantom.runTask(async () => {
result = await Image.queryCache([uri]);
});
expect(result).toEqual({
[uri]: cacheStatus,
});
});
});
});
});
});
@@ -0,0 +1,370 @@
/**
* 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.
*
* @flow strict-local
* @format
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {Modal} from 'react-native';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
const DEFAULT_MODAL_CHILD_VIEW = (
<rn-view
backgroundColor="rgba(255, 255, 255, 1)"
flex="1.000000"
left="0.000000"
top="0.000000"
/>
);
describe('<Modal>', () => {
describe('props', () => {
it('renders a Modal with the default values when no props are passed', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal />);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-modalHostView positionType="absolute" visible="true">
{DEFAULT_MODAL_CHILD_VIEW}
</rn-modalHostView>,
);
});
describe('animationType', () => {
it('renders a Modal with animationType="none" by default', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal animationType="none" />);
});
expect(
root.getRenderedOutput({props: ['animationType']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
(['slide', 'fade'] as const).forEach(animationType => {
it(`renders a Modal with animationType="${animationType}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal animationType={animationType} />);
});
expect(
root.getRenderedOutput({props: ['animationType']}).toJSX(),
).toEqual(
<rn-modalHostView animationType={animationType}>
<rn-view />
</rn-modalHostView>,
);
});
});
});
describe('presentationStyle', () => {
it('renders a Modal with presentationStyle="fullScreen" by default', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal presentationStyle="fullScreen" />);
});
expect(
root.getRenderedOutput({props: ['presentationStyle']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
(['pageSheet', 'formSheet', 'overFullScreen'] as const).forEach(
presentationStyle => {
it(`renders a Modal with presentationStyle="${presentationStyle}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal presentationStyle={presentationStyle} />);
});
expect(
root.getRenderedOutput({props: ['presentationStyle']}).toJSX(),
).toEqual(
<rn-modalHostView presentationStyle={presentationStyle}>
<rn-view />
</rn-modalHostView>,
);
});
},
);
});
describe('transparent', () => {
it('renders a Modal with transparent="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal transparent={true} />);
});
expect(
root
.getRenderedOutput({props: ['transparent', 'presentationStyle']})
.toJSX(),
).toEqual(
<rn-modalHostView
transparent="true"
presentationStyle="overFullScreen">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with transparent="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal transparent={false} />);
});
expect(
root
.getRenderedOutput({props: ['transparent', 'presentationStyle']})
.toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('statusBarTranslucent', () => {
it('renders a Modal with statusBarTranslucent="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal statusBarTranslucent={true} />);
});
expect(
root.getRenderedOutput({props: ['statusBarTranslucent']}).toJSX(),
).toEqual(
<rn-modalHostView statusBarTranslucent="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with statusBarTranslucent="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal statusBarTranslucent={false} />);
});
expect(
root.getRenderedOutput({props: ['statusBarTranslucent']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('navigationBarTranslucent', () => {
it('renders a Modal with navigationBarTranslucent="true" and statusBarTranslucent="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
// navigationBarTranslucent=true with statusBarTranslucent=false is not supported
// and it emits a warning.
root.render(
<Modal
navigationBarTranslucent={true}
statusBarTranslucent={true}
/>,
);
});
expect(
root
.getRenderedOutput({
props: ['navigationBarTranslucent', 'statusBarTranslucent'],
})
.toJSX(),
).toEqual(
<rn-modalHostView
navigationBarTranslucent="true"
statusBarTranslucent="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with navigationBarTranslucent="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal navigationBarTranslucent={false} />);
});
expect(
root
.getRenderedOutput({
props: ['navigationBarTranslucent', 'statusBarTranslucent'],
})
.toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('hardwareAccelerated', () => {
it('renders a Modal with hardwareAccelerated="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal hardwareAccelerated={true} />);
});
expect(
root.getRenderedOutput({props: ['hardwareAccelerated']}).toJSX(),
).toEqual(
<rn-modalHostView hardwareAccelerated="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with hardwareAccelerated="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal hardwareAccelerated={false} />);
});
expect(
root.getRenderedOutput({props: ['hardwareAccelerated']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('visible', () => {
it('renders a Modal with visible="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal visible={true} />);
});
expect(root.getRenderedOutput({props: ['visible']}).toJSX()).toEqual(
<rn-modalHostView visible="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders nothing when visible="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal visible={false} />);
});
expect(root.getRenderedOutput({props: ['visible']}).toJSX()).toBeNull();
});
});
describe('allowSwipeDismissal', () => {
it('renders a Modal with allowSwipeDismissal="true"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal allowSwipeDismissal={true} />);
});
expect(
root.getRenderedOutput({props: ['allowSwipeDismissal']}).toJSX(),
).toEqual(
<rn-modalHostView allowSwipeDismissal="true">
<rn-view />
</rn-modalHostView>,
);
});
it('renders a Modal with allowSwipeDismissal="false"', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal allowSwipeDismissal={false} />);
});
expect(
root.getRenderedOutput({props: ['allowSwipeDismissal']}).toJSX(),
).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
describe('animated', () => {
[true, false].forEach(animated => {
// The 'animated' prop is deprecated and ignored when the Modal is rendered
// Users should use the 'animationType' prop instead.
it(`[DEPRECATED] renders a Modal with animated="${animated ? 'true' : 'false'}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal animated={animated} />);
});
expect(root.getRenderedOutput({props: ['animated']}).toJSX()).toEqual(
<rn-modalHostView>
<rn-view />
</rn-modalHostView>,
);
});
});
});
// ... more props
});
describe('ref', () => {
describe('exampleMethod()', () => {
// more describe('<context>') or tests with it('<behaviour>')
});
// ... more methods
describe('instance', () => {
it('uses the "RN:ModalHostView" tag name', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Modal ref={elementRef} />);
});
expect(elementRef.current).toBeInstanceOf(ReactNativeElement);
const element = ensureInstance(elementRef.current, ReactNativeElement);
expect(element.tagName).toBe('RN:ModalHostView');
});
});
});
});
@@ -11,6 +11,7 @@
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {Role} from '../../Components/View/ViewAccessibility';
import type {HostInstance} from 'react-native';
import ensureInstance from '../../../src/private/__tests__/utilities/ensureInstance';
@@ -21,8 +22,372 @@ import {Text} from 'react-native';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
import ReadOnlyText from 'react-native/src/private/webapis/dom/nodes/ReadOnlyText';
const TEST_TEXT = 'the text';
describe('<Text>', () => {
describe('props', () => {
describe('empty props', () => {
it('renders an empty element when there are no props', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-paragraph
allowFontScaling="true"
ellipsizeMode="tail"
fontSize="NaN"
fontSizeMultiplier="NaN"
foregroundColor="rgba(0, 0, 0, 0)">
{TEST_TEXT}
</rn-paragraph>,
);
});
});
describe('allowFontScaling', () => {
([true, false] as const).forEach(propVal => {
it(`can be set to "${propVal.toString()}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text allowFontScaling={propVal}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['allowFontScaling']}).toJSX(),
).toEqual(
<rn-paragraph allowFontScaling={propVal.toString()}>
{TEST_TEXT}
</rn-paragraph>,
);
});
});
it(`has 'true' as default`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['allowFontScaling']}).toJSX(),
).toEqual(
<rn-paragraph allowFontScaling={'true'}>{TEST_TEXT}</rn-paragraph>,
);
});
});
describe('ellipsizeMode', () => {
it(`has 'tail' as default on JS side`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['ellipsizeMode']}).toJSX(),
).toEqual(
<rn-paragraph ellipsizeMode="tail">{TEST_TEXT}</rn-paragraph>,
);
});
it(`has 'clip' as default on C++ side`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text ellipsizeMode="clip">{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['ellipsizeMode']}).toJSX(),
).toEqual(<rn-paragraph>{TEST_TEXT}</rn-paragraph>);
});
(['head', 'middle', 'tail'] as const).forEach(propVal => {
it(`can be set to "${propVal}"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text ellipsizeMode={propVal}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['ellipsizeMode']}).toJSX(),
).toEqual(
<rn-paragraph ellipsizeMode={propVal}>{TEST_TEXT}</rn-paragraph>,
);
});
});
});
describe('id and nativeID', () => {
it(`has 'id' propagated correctly`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text id="alpha">{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['nativeID']}).toJSX()).toEqual(
<rn-paragraph nativeID={'alpha'}>{TEST_TEXT}</rn-paragraph>,
);
});
it(`has 'nativeID' propagated correctly`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text nativeID="alpha">{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['nativeID']}).toJSX()).toEqual(
<rn-paragraph nativeID={'alpha'}>{TEST_TEXT}</rn-paragraph>,
);
});
it(`has a precedence of 'id' over 'nativeID'`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<Text id="alpha" nativeID="gamma">
{TEST_TEXT}
</Text>,
);
});
expect(
root.getRenderedOutput({props: ['id', 'nativeID']}).toJSX(),
).toEqual(<rn-paragraph nativeID={'alpha'}>{TEST_TEXT}</rn-paragraph>);
});
});
describe('maxFontSizeMultiplier', () => {
it(`propagates valid numbers correctly`, () => {
const root = Fantom.createRoot();
[-1, 0, 1, 3, 1000].forEach(val => {
Fantom.runTask(() => {
root.render(<Text maxFontSizeMultiplier={val}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['maxFontSizeMultiplier']}).toJSX(),
).toEqual(
<rn-paragraph maxFontSizeMultiplier={val.toString()}>
{TEST_TEXT}
</rn-paragraph>,
);
});
});
});
describe('numberOfLines', () => {
let originalConsoleError = null;
afterEach(() => {
if (originalConsoleError != null) {
// $FlowExpectedError[cannot-write]
console.error = originalConsoleError;
originalConsoleError = null;
}
});
it(`doesn't allow negative numbers`, () => {
originalConsoleError = console.error;
// $FlowExpectedError[cannot-write]
console.error = jest.fn();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text numberOfLines={-1}>{TEST_TEXT}</Text>);
});
expect(
// NB. "numberOfLines" is mapped to "maximumNumberOfLines" in C++
root.getRenderedOutput({props: ['maximumNumberOfLines']}).toJSX(),
).toEqual(<rn-paragraph>{TEST_TEXT}</rn-paragraph>);
});
it(`has 0 as defult`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text numberOfLines={0}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['maximumNumberOfLines']}).toJSX(),
).toEqual(<rn-paragraph>{TEST_TEXT}</rn-paragraph>);
});
it(`propagates valid numbers correctly`, () => {
const root = Fantom.createRoot();
[3, 1000].forEach(val => {
Fantom.runTask(() => {
root.render(<Text numberOfLines={val}>{TEST_TEXT}</Text>);
});
expect(
root.getRenderedOutput({props: ['maximumNumberOfLines']}).toJSX(),
).toEqual(
<rn-paragraph maximumNumberOfLines={val.toString()}>
{TEST_TEXT}
</rn-paragraph>,
);
});
});
});
describe('role', () => {
it(`has none by default`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['role']}).toJSX()).toEqual(
<rn-paragraph>{TEST_TEXT}</rn-paragraph>,
);
});
it(`maps invalid values to 'none'`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
// $FlowExpectedError[incompatible-type]
root.render(<Text role="__some_invalid_value">{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['role']}).toJSX()).toEqual(
<rn-paragraph role="none">{TEST_TEXT}</rn-paragraph>,
);
});
it(`propagates correctly all possible values`, () => {
const root = Fantom.createRoot();
(
[
'alert',
'alertdialog',
'application',
'article',
'banner',
'button',
'cell',
'checkbox',
'columnheader',
'combobox',
'complementary',
'contentinfo',
'definition',
'dialog',
'directory',
'document',
'feed',
'figure',
'form',
'grid',
'group',
'heading',
'img',
'link',
'list',
'listitem',
'log',
'main',
'marquee',
'math',
'menu',
'menubar',
'menuitem',
'meter',
'navigation',
'none',
'note',
'option',
'presentation',
'progressbar',
'radio',
'radiogroup',
'region',
'row',
'rowgroup',
'rowheader',
'scrollbar',
'searchbox',
'separator',
'slider',
'spinbutton',
'status',
'summary',
'switch',
'tab',
'table',
'tablist',
'tabpanel',
'term',
'timer',
'toolbar',
'tooltip',
'tree',
'treegrid',
'treeitem',
'treeitem',
] as Array<Role>
).forEach(propVal => {
Fantom.runTask(() => {
root.render(<Text role={propVal}>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['role']}).toJSX()).toEqual(
<rn-paragraph role={propVal}>{TEST_TEXT}</rn-paragraph>,
);
});
});
});
describe('selectable', () => {
it(`can be set to "true"`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text selectable={true}>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['selectable']}).toJSX()).toEqual(
<rn-paragraph selectable={'true'}>{TEST_TEXT}</rn-paragraph>,
);
});
it(`has 'false' as default`, () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Text>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['selectable']}).toJSX()).toEqual(
<rn-paragraph>{TEST_TEXT}</rn-paragraph>,
);
Fantom.runTask(() => {
root.render(<Text selectable={false}>{TEST_TEXT}</Text>);
});
expect(root.getRenderedOutput({props: ['selectable']}).toJSX()).toEqual(
<rn-paragraph>{TEST_TEXT}</rn-paragraph>,
);
});
});
describe('style', () => {
describe('writingDirection', () => {
it('propagates to mounting layer', () => {
@@ -13,6 +13,8 @@
#import <React/RCTScrollableProtocol.h>
#import <React/RCTViewComponentView.h>
#import "RCTVirtualViewContainerProtocol.h"
NS_ASSUME_NONNULL_BEGIN
/*
@@ -23,7 +25,8 @@ NS_ASSUME_NONNULL_BEGIN
* keyboard-avoiding functionality and so on. All that complexity must be implemented inside those components in order
* to keep the complexity of this component manageable.
*/
@interface RCTScrollViewComponentView : RCTViewComponentView <RCTMountingTransactionObserving>
@interface RCTScrollViewComponentView
: RCTViewComponentView <RCTMountingTransactionObserving, RCTVirtualViewContainerProtocol>
/*
* Finds and returns the closet RCTScrollViewComponentView component to the given view
@@ -24,6 +24,7 @@
#import "RCTCustomPullToRefreshViewProtocol.h"
#import "RCTEnhancedScrollView.h"
#import "RCTFabricComponentsPlugins.h"
#import "RCTVirtualViewContainerState.h"
using namespace facebook::react;
@@ -117,6 +118,8 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt
// It is not restored to the default value in prepareForRecycle.
// Once an accessibility API is used, view culling will be disabled for the entire session.
BOOL _isAccessibilityAPIUsed;
RCTVirtualViewContainerState *_virtualViewContainerState;
}
+ (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view
@@ -678,6 +681,7 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
_contentView = nil;
_prevFirstVisibleFrame = CGRectZero;
_firstVisibleView = nil;
_virtualViewContainerState = nil;
}
#pragma mark - UIScrollViewDelegate
@@ -1090,6 +1094,16 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu
}
}
#pragma mark - RCTVirtualViewContainerProtocol
- (RCTVirtualViewContainerState *)virtualViewContainerState
{
if (!_virtualViewContainerState) {
_virtualViewContainerState = [[RCTVirtualViewContainerState alloc] initWithScrollView:self];
}
return _virtualViewContainerState;
}
@end
Class<RCTComponentViewProtocol> RCTScrollViewCls(void)
@@ -0,0 +1,14 @@
/*
* 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.
*/
@class RCTVirtualViewContainerState;
@protocol RCTVirtualViewContainerProtocol
- (RCTVirtualViewContainerState *)virtualViewContainerState;
@end
@@ -0,0 +1,25 @@
/*
* 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.
*/
#import <Foundation/Foundation.h>
#import "RCTVirtualViewProtocol.h"
@class RCTScrollViewComponentView;
NS_ASSUME_NONNULL_BEGIN
@interface RCTVirtualViewContainerState : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)new NS_UNAVAILABLE;
- (instancetype)initWithScrollView:(RCTScrollViewComponentView *)scrollView NS_DESIGNATED_INITIALIZER;
- (void)onChange:(id<RCTVirtualViewProtocol>)virtualView;
- (void)remove:(id<RCTVirtualViewProtocol>)virtualView;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,193 @@
/*
* 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.
*/
#import <React/RCTLog.h>
#import <React/RCTScrollViewComponentView.h>
#import <React/RCTVirtualViewMode.h>
#import <UIKit/UIKit.h>
#import <react/featureflags/ReactNativeFeatureFlags.h>
#import "RCTVirtualViewContainerState.h"
using namespace facebook;
using namespace facebook::react;
#if RCT_DEBUG
static void debugLog(NSString *msg, ...)
{
auto debugEnabled = ReactNativeFeatureFlags::enableVirtualViewDebugFeatures();
if (!debugEnabled) {
return;
}
va_list args;
va_start(args, msg);
NSString *msgString = [[NSString alloc] initWithFormat:msg arguments:args];
RCTLogInfo(@"%@", msgString);
va_end(args); // Don't forget to call va_end to clean up
}
#endif
/**
* Checks whether one CGRect overlaps with another CGRect.
*
* This is different from CGRectIntersectsRect because a CGRect representing
* a line or a point is considered to overlap with another CGRect if the line
* or point is within the rect bounds. However, two CGRects are not considered
* to overlap if they only share a boundary.
*/
static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
{
CGFloat minY1 = CGRectGetMinY(rect1);
CGFloat maxY1 = CGRectGetMaxY(rect1);
CGFloat minY2 = CGRectGetMinY(rect2);
CGFloat maxY2 = CGRectGetMaxY(rect2);
if (minY1 >= maxY2 || minY2 >= maxY1) {
// No overlap on the y-axis.
return NO;
}
CGFloat minX1 = CGRectGetMinX(rect1);
CGFloat maxX1 = CGRectGetMaxX(rect1);
CGFloat minX2 = CGRectGetMinX(rect2);
CGFloat maxX2 = CGRectGetMaxX(rect2);
if (minX1 >= maxX2 || minX2 >= maxX1) {
// No overlap on the x-axis.
return NO;
}
return YES;
}
@interface RCTVirtualViewContainerState () <UIScrollViewDelegate>
@end
@interface RCTVirtualViewContainerState () {
NSMutableSet<id<RCTVirtualViewProtocol>> *_virtualViews;
CGRect _emptyRect;
CGRect _prerenderRect;
__weak RCTScrollViewComponentView *_scrollViewComponentView;
CGFloat _prerenderRatio;
}
@end
@implementation RCTVirtualViewContainerState
- (instancetype)initWithScrollView:(RCTScrollViewComponentView *)scrollView
{
self = [super init];
if (self != nil) {
_virtualViews = [NSMutableSet set];
_emptyRect = CGRectZero;
_prerenderRect = CGRectZero;
_scrollViewComponentView = scrollView;
_prerenderRatio = ReactNativeFeatureFlags::virtualViewPrerenderRatio();
[_scrollViewComponentView addScrollListener:self];
#if RCT_DEBUG
debugLog(@"initWithScrollView");
#endif
}
return self;
}
- (void)dealloc
{
#if RCT_DEBUG
debugLog(@"dealloc");
#endif
if (_scrollViewComponentView != nil) {
[_scrollViewComponentView removeScrollListener:self];
_scrollViewComponentView = nil;
}
[_virtualViews removeAllObjects];
}
#pragma mark - Public API
- (void)onChange:(id<RCTVirtualViewProtocol>)virtualView
{
if (![_virtualViews containsObject:virtualView]) {
[_virtualViews addObject:virtualView];
#if RCT_DEBUG
debugLog(@"Add virtualViewID=%@", virtualView.virtualViewID);
#endif
} else {
#if RCT_DEBUG
debugLog(@"Update virtualViewID=%@", virtualView.virtualViewID);
#endif
}
[self _updateModes:virtualView];
}
- (void)remove:(id<RCTVirtualViewProtocol>)virtualView
{
if (![_virtualViews containsObject:virtualView]) {
RCTLogError(@"Attempting to remove non-existent VirtualView: %@", virtualView.virtualViewID);
}
[_virtualViews removeObject:virtualView];
#if RCT_DEBUG
debugLog(@"Remove virtualViewID=%@", virtualView.virtualViewID);
#endif
}
#pragma mark - Private Helpers
- (void)_updateModes:(id<RCTVirtualViewProtocol>)virtualView
{
auto scrollView = _scrollViewComponentView.scrollView;
CGRect visibleRect = CGRectMake(
scrollView.contentOffset.x,
scrollView.contentOffset.y,
scrollView.frame.size.width,
scrollView.frame.size.height);
_prerenderRect = visibleRect;
_prerenderRect = CGRectInset(
_prerenderRect, -_prerenderRect.size.width * _prerenderRatio, -_prerenderRect.size.height * _prerenderRatio);
NSArray<id<RCTVirtualViewProtocol>> *virtualViewsIt =
(virtualView != nullptr) ? @[ virtualView ] : [_virtualViews allObjects];
for (id<RCTVirtualViewProtocol> vv = nullptr in virtualViewsIt) {
CGRect rect = [vv containerRelativeRect:scrollView];
RCTVirtualViewMode mode = RCTVirtualViewModeHidden;
CGRect thresholdRect = _emptyRect;
if (CGRectIsEmpty(rect)) {
mode = RCTVirtualViewModeHidden;
thresholdRect = _emptyRect;
} else if (CGRectOverlaps(rect, visibleRect)) {
thresholdRect = visibleRect;
mode = RCTVirtualViewModeVisible;
} else if (CGRectOverlaps(rect, _prerenderRect)) {
mode = RCTVirtualViewModePrerender;
thresholdRect = _prerenderRect;
}
#if RCT_DEBUG
debugLog(
@"UpdateModes virtualView=%@ mode=%ld rect=%@ thresholdRect=%@",
vv.virtualViewID,
(long)mode,
NSStringFromCGRect(rect),
NSStringFromCGRect(thresholdRect));
#endif
[vv onModeChange:mode targetRect:rect thresholdRect:thresholdRect];
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self _updateModes:nil];
}
@end
@@ -0,0 +1,20 @@
/*
* 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.
*/
#import <React/RCTVirtualViewMode.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol RCTVirtualViewProtocol <NSObject>
- (NSString *)virtualViewID;
- (CGRect)containerRelativeRect:(UIView *)view;
- (void)onModeChange:(RCTVirtualViewMode)newMode targetRect:(CGRect)targetRect thresholdRect:(CGRect)thresholdRect;
@end
NS_ASSUME_NONNULL_END
@@ -8,10 +8,11 @@
#import <UIKit/UIKit.h>
#import <React/RCTViewComponentView.h>
#import <React/RCTVirtualViewProtocol.h>
NS_ASSUME_NONNULL_BEGIN
@interface RCTVirtualViewExperimentalComponentView : RCTViewComponentView
@interface RCTVirtualViewExperimentalComponentView : RCTViewComponentView <RCTVirtualViewProtocol>
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
@@ -11,6 +11,8 @@
#import <React/RCTConversions.h>
#import <React/RCTScrollViewComponentView.h>
#import <React/RCTScrollableProtocol.h>
#import <React/RCTVirtualViewContainerProtocol.h>
#import <React/RCTVirtualViewContainerState.h>
#import <React/UIView+React.h>
#import <jsi/jsi.h>
@@ -28,50 +30,30 @@
using namespace facebook;
using namespace facebook::react;
/**
* Checks whether one CGRect overlaps with another CGRect.
*
* This is different from CGRectIntersectsRect because a CGRect representing
* a line or a point is considered to overlap with another CGRect if the line
* or point is within the rect bounds. However, two CGRects are not considered
* to overlap if they only share a boundary.
*/
static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
{
CGFloat minY1 = CGRectGetMinY(rect1);
CGFloat maxY1 = CGRectGetMaxY(rect1);
CGFloat minY2 = CGRectGetMinY(rect2);
CGFloat maxY2 = CGRectGetMaxY(rect2);
if (minY1 >= maxY2 || minY2 >= maxY1) {
// No overlap on the y-axis.
return NO;
}
CGFloat minX1 = CGRectGetMinX(rect1);
CGFloat maxX1 = CGRectGetMaxX(rect1);
CGFloat minX2 = CGRectGetMinX(rect2);
CGFloat maxX2 = CGRectGetMaxX(rect2);
if (minX1 >= maxX2 || minX2 >= maxX1) {
// No overlap on the x-axis.
return NO;
}
return YES;
@interface RCTVirtualViewExperimentalComponentView () {
NSString *_virtualViewID;
}
@interface RCTVirtualViewExperimentalComponentView () <UIScrollViewDelegate>
@end
@implementation RCTVirtualViewExperimentalComponentView {
RCTScrollViewComponentView *_lastParentScrollViewComponentView;
id<RCTVirtualViewContainerProtocol> _parentVirtualViewContainer;
std::optional<RCTVirtualViewMode> _mode;
RCTVirtualViewRenderState _renderState;
std::optional<CGRect> _targetRect;
NSString *_nativeId;
BOOL _didLayout;
}
#pragma mark - Public API
- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]) != nil) {
_props = VirtualViewExperimentalShadowNode::defaultSharedProps();
_renderState = RCTVirtualViewRenderStateUnknown;
_virtualViewID = [[NSUUID UUID] UUIDString];
_didLayout = NO;
}
return self;
@@ -103,19 +85,11 @@ static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
}
}
[super updateProps:props oldProps:oldProps];
}
const auto &newBaseViewProps = static_cast<const ViewProps &>(*props);
const auto nativeId = RCTNSStringFromStringNilIfEmpty(newBaseViewProps.nativeId);
_virtualViewID = nativeId == nil ? _virtualViewID : nativeId;
- (RCTScrollViewComponentView *)getParentScrollViewComponentView
{
UIView *view = self.superview;
while (view != nil) {
if ([view isKindOfClass:[RCTScrollViewComponentView class]]) {
return (RCTScrollViewComponentView *)view;
}
view = view.superview;
}
return nil;
[super updateProps:props oldProps:oldProps];
}
/**
@@ -126,18 +100,6 @@ static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
*/
static BOOL sIsAccessibilityUsed = NO;
- (void)_unhideIfNeeded
{
if (!sIsAccessibilityUsed) {
// accessibility is detected for the first time. Make views visible.
sIsAccessibilityUsed = YES;
}
if (self.hidden) {
self.hidden = NO;
}
}
- (NSInteger)accessibilityElementCount
{
// From empirical testing, method `accessibilityElementCount` is called lazily only
@@ -154,19 +116,23 @@ static BOOL sIsAccessibilityUsed = NO;
return [super focusItemsInRect:rect];
}
- (NSString *)virtualViewID
{
// Return a unique identifier for this virtual view
// Using the tag as a unique identifier since it's already unique per view
return _virtualViewID;
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
// No need to remove the scroll listener here since the view is always removed from window before being recycled and
// we do that in didMoveToWindow, which gets called when the view is removed from window.
RCTAssert(
_lastParentScrollViewComponentView == nil,
@"_lastParentScrollViewComponentView should already have been cleared in didMoveToWindow.");
[[_parentVirtualViewContainer virtualViewContainerState] remove:self];
self.hidden = NO;
_didLayout = NO;
_mode.reset();
_targetRect.reset();
_parentVirtualViewContainer = nil;
}
// Handles case when sibling changes size.
@@ -176,84 +142,41 @@ static BOOL sIsAccessibilityUsed = NO;
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
{
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:_layoutMetrics];
_didLayout = YES;
[self updateState];
}
[self dispatchOnModeChangeIfNeeded:YES];
- (void)updateState
{
[[_parentVirtualViewContainer virtualViewContainerState] onChange:self];
}
- (void)didMoveToWindow
{
[super didMoveToWindow];
// here we will set the pointer to the virtualView container
// and if there was a layout, update
if (_lastParentScrollViewComponentView != nil) {
[_lastParentScrollViewComponentView removeScrollListener:self];
_lastParentScrollViewComponentView = nil;
}
if (RCTScrollViewComponentView *parentScrollViewComponentView = [self getParentScrollViewComponentView]) {
if (self.window != nil) {
// TODO(T202601695): We also want the ScrollView to emit layout changes from didLayoutSubviews so that any event
// that may affect visibily of this view notifies the listeners.
[parentScrollViewComponentView addScrollListener:self];
_lastParentScrollViewComponentView = parentScrollViewComponentView;
// We want to dispatch the event immediately when the view is added to the window before any scrolling occurs.
[self dispatchOnModeChangeIfNeeded:NO];
}
_parentVirtualViewContainer = [self _getParentVirtualViewContainer];
if (_parentVirtualViewContainer != nil && self.window != nil && _didLayout) {
[self updateState];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
- (CGRect)containerRelativeRect:(UIView *)scrollView
{
[self dispatchOnModeChangeIfNeeded:NO];
// Return the view's position relative to its container (the scroll view)
return [self convertRect:self.bounds toView:scrollView];
}
- (void)dispatchOnModeChangeIfNeeded:(BOOL)checkForTargetRectChange
- (void)onModeChange:(RCTVirtualViewMode)newMode targetRect:(CGRect)targetRect thresholdRect:(CGRect)thresholdRect
{
if (_lastParentScrollViewComponentView == nullptr) {
return;
}
UIScrollView *scrollView = _lastParentScrollViewComponentView.scrollView;
CGRect targetRect = [self convertRect:self.bounds toView:scrollView];
// While scrolling, the `targetRect` does not change, so we don't check for changed `targetRect` in that case.
if (checkForTargetRectChange) {
if (_targetRect.has_value() && CGRectEqualToRect(targetRect, _targetRect.value())) {
return;
}
_targetRect = targetRect;
}
RCTVirtualViewMode newMode;
CGRect thresholdRect = CGRectMake(
scrollView.contentOffset.x,
scrollView.contentOffset.y,
scrollView.frame.size.width,
scrollView.frame.size.height);
if (CGRectOverlaps(targetRect, thresholdRect)) {
newMode = RCTVirtualViewModeVisible;
} else {
auto prerender = false;
const CGFloat prerenderRatio = ReactNativeFeatureFlags::virtualViewPrerenderRatio();
if (prerenderRatio > 0) {
thresholdRect = CGRectInset(
thresholdRect, -thresholdRect.size.width * prerenderRatio, -thresholdRect.size.height * prerenderRatio);
prerender = CGRectOverlaps(targetRect, thresholdRect);
}
if (prerender) {
newMode = RCTVirtualViewModePrerender;
} else {
newMode = RCTVirtualViewModeHidden;
thresholdRect = CGRectZero;
}
}
if (_mode.has_value() && newMode == _mode.value()) {
return;
}
// NOTE: Make sure to keep these props in sync with dispatchSyncModeChange below where we have to explicitly copy all
// props.
// NOTE: Make sure to keep these props in sync with dispatchSyncModeChange below where we have to explicitly copy
// all props.
VirtualViewEventEmitter::OnModeChange event = {
.mode = (int)newMode,
.targetRect =
@@ -275,24 +198,24 @@ static BOOL sIsAccessibilityUsed = NO;
case RCTVirtualViewModeVisible:
if (_renderState == RCTVirtualViewRenderStateUnknown) {
// Feature flag is disabled, so use the former logic.
[self dispatchSyncModeChange:event];
[self _dispatchSyncModeChange:event];
} else {
// If the previous mode was prerender and the result of dispatching that event was committed, we do not need to
// dispatch an event for visible.
// If the previous mode was prerender and the result of dispatching that event was committed, we do not need
// to dispatch an event for visible.
const auto wasPrerenderCommitted = oldMode.has_value() && oldMode == RCTVirtualViewModePrerender &&
_renderState == RCTVirtualViewRenderStateRendered;
if (!wasPrerenderCommitted) {
[self dispatchSyncModeChange:event];
[self _dispatchSyncModeChange:event];
}
}
break;
case RCTVirtualViewModePrerender:
if (!oldMode.has_value() || oldMode != RCTVirtualViewModeVisible) {
[self dispatchAsyncModeChange:event];
[self _dispatchAsyncModeChange:event];
}
break;
case RCTVirtualViewModeHidden:
[self dispatchAsyncModeChange:event];
[self _dispatchAsyncModeChange:event];
break;
}
@@ -311,7 +234,33 @@ static BOOL sIsAccessibilityUsed = NO;
}
}
- (void)dispatchAsyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
#pragma mark - Private API
- (void)_unhideIfNeeded
{
if (!sIsAccessibilityUsed) {
// accessibility is detected for the first time. Make views visible.
sIsAccessibilityUsed = YES;
}
if (self.hidden) {
self.hidden = NO;
}
}
- (id<RCTVirtualViewContainerProtocol>)_getParentVirtualViewContainer
{
UIView *view = self.superview;
while (view != nil) {
if ([view respondsToSelector:@selector(virtualViewContainerState)]) {
return (id<RCTVirtualViewContainerProtocol>)view;
}
view = view.superview;
}
return nil;
}
- (void)_dispatchAsyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
{
if (!_eventEmitter) {
return;
@@ -322,7 +271,7 @@ static BOOL sIsAccessibilityUsed = NO;
emitter->onModeChange(event);
}
- (void)dispatchSyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
- (void)_dispatchSyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
{
if (!_eventEmitter) {
return;
@@ -6012,6 +6012,7 @@ public final class com/facebook/react/views/text/DefaultStyleValuesUtil {
}
public abstract class com/facebook/react/views/text/ReactBaseTextShadowNode : com/facebook/react/uimanager/LayoutShadowNode {
public static final field Companion Lcom/facebook/react/views/text/ReactBaseTextShadowNode$Companion;
public static final field DEFAULT_TEXT_SHADOW_COLOR I
public static final field PROP_SHADOW_COLOR Ljava/lang/String;
public static final field PROP_SHADOW_OFFSET Ljava/lang/String;
@@ -6019,61 +6020,86 @@ public abstract class com/facebook/react/views/text/ReactBaseTextShadowNode : co
public static final field PROP_SHADOW_OFFSET_WIDTH Ljava/lang/String;
public static final field PROP_SHADOW_RADIUS Ljava/lang/String;
public static final field PROP_TEXT_TRANSFORM Ljava/lang/String;
protected field mAccessibilityRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
protected field mAdjustsFontSizeToFit Z
protected field mBackgroundColor I
protected field mColor I
protected field mContainsImages Z
protected field mFontFamily Ljava/lang/String;
protected field mFontFeatureSettings Ljava/lang/String;
protected field mFontStyle I
protected field mFontWeight I
protected field mHyphenationFrequency I
protected field mIncludeFontPadding Z
protected field mInlineViews Ljava/util/Map;
protected field mIsBackgroundColorSet Z
protected field mIsColorSet Z
protected field mIsLineThroughTextDecorationSet Z
protected field mIsUnderlineTextDecorationSet Z
protected field mJustificationMode I
protected field mMinimumFontScale F
protected field mNumberOfLines I
protected field mReactTextViewManagerCallback Lcom/facebook/react/views/text/ReactTextViewManagerCallback;
protected field mRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
protected field mTextAlign I
protected field mTextAttributes Lcom/facebook/react/views/text/TextAttributes;
protected field mTextBreakStrategy I
protected field mTextShadowColor I
protected field mTextShadowOffsetDx F
protected field mTextShadowOffsetDy F
protected field mTextShadowRadius F
public fun <init> ()V
public fun <init> (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)V
public fun setAccessibilityRole (Ljava/lang/String;)V
public fun setAdjustFontSizeToFit (Z)V
public fun setAllowFontScaling (Z)V
public fun setBackgroundColor (Ljava/lang/Integer;)V
public fun setColor (Ljava/lang/Integer;)V
public fun setFontFamily (Ljava/lang/String;)V
public fun setFontSize (F)V
public fun setFontStyle (Ljava/lang/String;)V
public fun setFontVariant (Lcom/facebook/react/bridge/ReadableArray;)V
public fun setFontWeight (Ljava/lang/String;)V
public fun setIncludeFontPadding (Z)V
public fun setLetterSpacing (F)V
public fun setLineHeight (F)V
public fun setMaxFontSizeMultiplier (F)V
public fun setMinimumFontScale (F)V
public fun setNumberOfLines (I)V
public fun setRole (Ljava/lang/String;)V
public fun setTextAlign (Ljava/lang/String;)V
public synthetic fun <init> (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
protected final fun getAccessibilityRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
protected final fun getAdjustsFontSizeToFit ()Z
protected final fun getBackgroundColor ()I
protected final fun getColor ()I
protected final fun getContainsImages ()Z
protected final fun getFontFamily ()Ljava/lang/String;
protected final fun getFontFeatureSettings ()Ljava/lang/String;
protected final fun getFontStyle ()I
protected final fun getFontWeight ()I
protected final fun getHyphenationFrequency ()I
protected final fun getIncludeFontPadding ()Z
protected final fun getInlineViews ()Ljava/util/Map;
protected final fun getJustificationMode ()I
protected final fun getMinimumFontScale ()F
protected final fun getNumberOfLines ()I
protected final fun getReactTextViewManagerCallback ()Lcom/facebook/react/views/text/ReactTextViewManagerCallback;
protected final fun getRole ()Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
protected final fun getTextAlign ()I
protected final fun getTextAttributes ()Lcom/facebook/react/views/text/TextAttributes;
protected final fun getTextBreakStrategy ()I
protected final fun getTextShadowColor ()I
protected final fun getTextShadowOffsetDx ()F
protected final fun getTextShadowOffsetDy ()F
protected final fun getTextShadowRadius ()F
protected final fun isBackgroundColorSet ()Z
protected final fun isColorSet ()Z
protected final fun isLineThroughTextDecorationSet ()Z
protected final fun isUnderlineTextDecorationSet ()Z
protected final fun setAccessibilityRole (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;)V
public final fun setAccessibilityRole (Ljava/lang/String;)V
public final fun setAdjustFontSizeToFit (Z)V
protected final fun setAdjustsFontSizeToFit (Z)V
public final fun setAllowFontScaling (Z)V
protected final fun setBackgroundColor (I)V
public final fun setBackgroundColor (Ljava/lang/Integer;)V
protected final fun setBackgroundColorSet (Z)V
protected final fun setColor (I)V
public final fun setColor (Ljava/lang/Integer;)V
protected final fun setColorSet (Z)V
protected final fun setContainsImages (Z)V
public final fun setFontFamily (Ljava/lang/String;)V
protected final fun setFontFeatureSettings (Ljava/lang/String;)V
public final fun setFontSize (F)V
protected final fun setFontStyle (I)V
public final fun setFontStyle (Ljava/lang/String;)V
public final fun setFontVariant (Lcom/facebook/react/bridge/ReadableArray;)V
protected final fun setFontWeight (I)V
public final fun setFontWeight (Ljava/lang/String;)V
protected final fun setHyphenationFrequency (I)V
public final fun setIncludeFontPadding (Z)V
protected final fun setInlineViews (Ljava/util/Map;)V
protected final fun setJustificationMode (I)V
public final fun setLetterSpacing (F)V
public final fun setLineHeight (F)V
protected final fun setLineThroughTextDecorationSet (Z)V
public final fun setMaxFontSizeMultiplier (F)V
public final fun setMinimumFontScale (F)V
public final fun setNumberOfLines (I)V
protected final fun setReactTextViewManagerCallback (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)V
protected final fun setRole (Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;)V
public final fun setRole (Ljava/lang/String;)V
public final fun setTextAlign (Ljava/lang/String;)V
protected final fun setTextAttributes (Lcom/facebook/react/views/text/TextAttributes;)V
protected final fun setTextBreakStrategy (I)V
public fun setTextBreakStrategy (Ljava/lang/String;)V
public fun setTextDecorationLine (Ljava/lang/String;)V
public fun setTextShadowColor (I)V
public fun setTextShadowOffset (Lcom/facebook/react/bridge/ReadableMap;)V
public fun setTextShadowRadius (F)V
public fun setTextTransform (Ljava/lang/String;)V
protected fun spannedFromShadowNode (Lcom/facebook/react/views/text/ReactBaseTextShadowNode;Ljava/lang/String;ZLcom/facebook/react/uimanager/NativeViewHierarchyOptimizer;)Landroid/text/Spannable;
public final fun setTextDecorationLine (Ljava/lang/String;)V
public final fun setTextShadowColor (I)V
public final fun setTextShadowOffset (Lcom/facebook/react/bridge/ReadableMap;)V
protected final fun setTextShadowOffsetDx (F)V
protected final fun setTextShadowOffsetDy (F)V
public final fun setTextShadowRadius (F)V
public final fun setTextTransform (Ljava/lang/String;)V
protected final fun setUnderlineTextDecorationSet (Z)V
protected final fun spannedFromShadowNode (Lcom/facebook/react/views/text/ReactBaseTextShadowNode;Ljava/lang/String;ZLcom/facebook/react/uimanager/NativeViewHierarchyOptimizer;)Landroid/text/Spannable;
}
public final class com/facebook/react/views/text/ReactBaseTextShadowNode$Companion {
}
public final class com/facebook/react/views/text/ReactFontManager {
@@ -30,7 +30,6 @@ import com.facebook.react.modules.debug.DevSettingsModule
import com.facebook.react.modules.debug.SourceCodeModule
import com.facebook.react.modules.deviceinfo.DeviceInfoModule
import com.facebook.react.modules.systeminfo.AndroidInfoModule
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.ViewManager
import com.facebook.react.uimanager.ViewManagerResolver
import com.facebook.systrace.Systrace
@@ -38,6 +37,7 @@ import com.facebook.systrace.Systrace
/**
* This is the basic module to support React Native. The debug modules are now in DebugCorePackage.
*/
@Suppress("DEPRECATION")
@ReactModuleList(
// WARNING: If you modify this list, ensure that the list below in method
// getReactModuleInfoByInitialization is also updated
@@ -53,9 +53,11 @@ import com.facebook.systrace.Systrace
HeadlessJsTaskSupportModule::class,
SourceCodeModule::class,
TimingModule::class,
UIManagerModule::class])
com.facebook.react.uimanager.UIManagerModule::class])
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Suppress("DEPRECATION")
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class CoreModulesPackage(
private val reactInstanceManager: ReactInstanceManager,
private val hardwareBackBtnHandler: DefaultHardwareBackBtnHandler,
@@ -103,7 +105,7 @@ internal class CoreModulesPackage(
HeadlessJsTaskSupportModule::class.java,
SourceCodeModule::class.java,
TimingModule::class.java,
UIManagerModule::class.java,
com.facebook.react.uimanager.UIManagerModule::class.java,
)
val reactModuleInfoMap: MutableMap<String, ReactModuleInfo> = HashMap<String, ReactModuleInfo>()
@@ -140,7 +142,7 @@ internal class CoreModulesPackage(
HeadlessJsTaskSupportModule.NAME -> HeadlessJsTaskSupportModule(reactContext)
SourceCodeModule.NAME -> SourceCodeModule(reactContext)
TimingModule.NAME -> TimingModule(reactContext, reactInstanceManager.devSupportManager)
UIManagerModule.NAME -> createUIManager(reactContext)
com.facebook.react.uimanager.UIManagerModule.NAME -> createUIManager(reactContext)
DeviceInfoModule.NAME -> DeviceInfoModule(reactContext)
else ->
throw IllegalArgumentException(
@@ -148,7 +150,9 @@ internal class CoreModulesPackage(
}
}
private fun createUIManager(reactContext: ReactApplicationContext): UIManagerModule {
private fun createUIManager(
reactContext: ReactApplicationContext
): com.facebook.react.uimanager.UIManagerModule {
ReactMarker.logMarker(ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START)
Systrace.beginSection(Systrace.TRACE_TAG_REACT, "createUIManagerModule")
@@ -165,9 +169,10 @@ internal class CoreModulesPackage(
}
}
return UIManagerModule(reactContext, resolver, minTimeLeftInFrameForNonBatchedOperationMs)
return com.facebook.react.uimanager.UIManagerModule(
reactContext, resolver, minTimeLeftInFrameForNonBatchedOperationMs)
} else {
return UIManagerModule(
return com.facebook.react.uimanager.UIManagerModule(
reactContext,
reactInstanceManager.getOrCreateViewManagers(reactContext),
minTimeLeftInFrameForNonBatchedOperationMs)
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react
import com.facebook.react.bridge.ModuleHolder
@@ -16,6 +18,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/** Helper class to build NativeModuleRegistry. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class NativeModuleRegistryBuilder(
private val reactApplicationContext: ReactApplicationContext,
) {
@@ -28,7 +28,6 @@ import com.facebook.react.modules.core.ReactChoreographer
import com.facebook.react.uimanager.GuardedFrameCallback
import com.facebook.react.uimanager.UIBlock
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.common.UIManagerType
import com.facebook.react.uimanager.common.ViewUtil
import java.util.ArrayList
@@ -74,9 +73,9 @@ import kotlin.concurrent.Volatile
* that coordinates all the action: [NativeAnimatedNodesManager]. Since all the methods from
* [NativeAnimatedNodesManager] need to be called from the UI thread, we we create a queue of
* animated graph operations that is then enqueued to be executed in the UI Thread at the end of the
* batch of JS->native calls (similarly to how it's handled in [UIManagerModule]). This isolates us
* from the problems that may be caused by concurrent updates of animated graph while UI thread is
* "executing" the animation loop.
* batch of JS->native calls (similarly to how it's handled in
* [com.facebook.react.uimanager.UIManagerModule]). This isolates us from the problems that may be
* caused by concurrent updates of animated graph while UI thread is "executing" the animation loop.
*/
@OptIn(UnstableReactNativeAPI::class)
@ReactModule(name = NativeAnimatedModuleSpec.NAME)
@@ -306,6 +305,7 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
}
// For non-FabricUIManager only
@Suppress("DEPRECATION")
@UiThread
override fun willDispatchViewUpdates(uiManager: UIManager) {
if (operations.isEmpty && preOperations.isEmpty) {
@@ -325,8 +325,8 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
val operationsUIBlock = UIBlock { operations.executeBatch(frameNo, nodesManager) }
assert(uiManager is UIManagerModule)
val uiManagerModule = uiManager as UIManagerModule
assert(uiManager is com.facebook.react.uimanager.UIManagerModule)
val uiManagerModule = uiManager as com.facebook.react.uimanager.UIManagerModule
uiManagerModule.prependUIBlock(preOperationsUIBlock)
uiManagerModule.addUIBlock(operationsUIBlock)
}
@@ -40,7 +40,8 @@ import java.util.Objects;
*/
@VisibleForTesting
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
@Nullsafe(Nullsafe.Mode.LOCAL)
public class BridgeReactContext extends ReactApplicationContext {
static {
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.bridge
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -13,6 +15,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/** Implementation of javascript callback function that uses Bridge to schedule method execution. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class CallbackImpl(private val jsInstance: JSInstance, private val callbackId: Int) :
Callback {
private var invoked = false
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.bridge
import com.facebook.proguard.annotations.DoNotStrip
@@ -48,6 +48,8 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
@DoNotStrip
@LegacyArchitecture
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class CatalystInstanceImpl implements CatalystInstance {
static {
ReactNativeJNISoLoader.staticInit();
@@ -17,6 +17,9 @@ import com.facebook.systrace.SystraceMessage
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
internal class JavaMethodWrapper(
private val moduleWrapper: JavaModuleWrapper,
@@ -26,6 +29,7 @@ internal class JavaMethodWrapper(
private abstract class ArgumentExtractor<T> {
open fun getJSArgumentsNeeded(): Int = 1
@Suppress("DEPRECATION")
abstract fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -157,6 +161,7 @@ internal class JavaMethodWrapper(
"$startIndex"
}
@Suppress("DEPRECATION")
override fun invoke(jsInstance: JSInstance, parameters: ReadableArray) {
val traceName = moduleWrapper.name + "." + method.name
SystraceMessage.beginSection(TRACE_TAG_REACT, "callJavaModuleMethod")
@@ -240,6 +245,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_BOOLEAN: ArgumentExtractor<Boolean> =
object : ArgumentExtractor<Boolean>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -249,6 +255,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_DOUBLE: ArgumentExtractor<Double> =
object : ArgumentExtractor<Double>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -258,6 +265,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_FLOAT: ArgumentExtractor<Float> =
object : ArgumentExtractor<Float>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -267,6 +275,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_INTEGER: ArgumentExtractor<Int> =
object : ArgumentExtractor<Int>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -276,6 +285,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_STRING: ArgumentExtractor<String> =
object : ArgumentExtractor<String>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -285,6 +295,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_ARRAY: ArgumentExtractor<ReadableArray> =
object : ArgumentExtractor<ReadableArray>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -294,6 +305,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_DYNAMIC: ArgumentExtractor<Dynamic> =
object : ArgumentExtractor<Dynamic>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -303,6 +315,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_MAP: ArgumentExtractor<ReadableMap> =
object : ArgumentExtractor<ReadableMap>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -312,6 +325,7 @@ internal class JavaMethodWrapper(
private val ARGUMENT_EXTRACTOR_CALLBACK: ArgumentExtractor<Callback> =
object : ArgumentExtractor<Callback>() {
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -321,7 +335,7 @@ internal class JavaMethodWrapper(
null
} else {
val id = jsArguments.getDouble(atIndex).toInt()
CallbackImpl(jsInstance, id)
@Suppress("DEPRECATION") CallbackImpl(jsInstance, id)
}
}
@@ -329,6 +343,7 @@ internal class JavaMethodWrapper(
object : ArgumentExtractor<Promise>() {
override fun getJSArgumentsNeeded(): Int = 2
@Suppress("DEPRECATION")
override fun extractArgument(
jsInstance: JSInstance,
jsArguments: ReadableArray,
@@ -25,11 +25,11 @@ import java.lang.reflect.Method
@DoNotStrip
@InteropLegacyArchitecture
internal class JavaModuleWrapper(
private val jsInstance: JSInstance,
@Suppress("DEPRECATION") private val jsInstance: JSInstance,
private val moduleHolder: ModuleHolder
) {
interface NativeMethod {
fun invoke(jsInstance: JSInstance, parameters: ReadableArray)
@Suppress("DEPRECATION") fun invoke(jsInstance: JSInstance, parameters: ReadableArray)
val type: String
}
@@ -74,6 +74,7 @@ internal class JavaModuleWrapper(
targetMethod.getAnnotation(ReactMethod::class.java)?.let { annotation ->
val methodName = targetMethod.name
val md = MethodDescriptor()
@Suppress("DEPRECATION")
val method = JavaMethodWrapper(this, targetMethod, annotation.isBlockingSynchronousMethod)
md.name = methodName
md.type = method.type
@@ -13,6 +13,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/** Exception thrown when a native module method call receives unexpected arguments from JS. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class NativeArgumentsParseException : JSApplicationCausedNativeException {
constructor(detailMessage: String) : super(detailMessage)
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.bridge
import com.facebook.react.bridge.ReactMarker.logMarker
@@ -19,6 +21,9 @@ import com.facebook.systrace.Systrace.endSection
/** A set of Java APIs to expose to a particular JavaScript instance. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class NativeModuleRegistry(
private val reactApplicationContext: ReactApplicationContext,
private val modules: MutableMap<String, ModuleHolder>
@@ -12,6 +12,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
/** Interface for a module that will be notified when a batch of JS->Java calls has finished. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public fun interface OnBatchCompleteListener {
public fun onBatchComplete()
}
@@ -16,6 +16,9 @@ import java.lang.reflect.Method
@DoNotStrip
@LegacyArchitecture
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal object ReactCxxErrorHandler {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.bridge
import com.facebook.jni.HybridData
@@ -17,6 +19,9 @@ import java.util.concurrent.Executor
@DoNotStripAny
@LegacyArchitecture
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class ReactInstanceManagerInspectorTarget(delegate: TargetDelegate) : AutoCloseable {
@DoNotStripAny
@@ -15,6 +15,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
* Native.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public fun interface UIManagerProvider {
/* Provides a [com.facebook.react.bridge.UIManager] for the context received as a parameter. */
@@ -46,6 +46,9 @@ import com.facebook.react.packagerconnection.RequestHandler
* when all the views has been detached from the instance (through `setDevSupportEnabled` method).
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class BridgeDevSupportManager(
applicationContext: Context,
reactInstanceManagerHelper: ReactInstanceDevHelper,
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.fabric
import com.facebook.react.bridge.ReactApplicationContext
@@ -20,6 +22,9 @@ import com.facebook.systrace.Systrace
* @param [componentFactory] The factory for creating components.
* @param [viewManagerRegistry] The registry of view managers.
*/
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class FabricUIManagerProviderImpl(
private val componentFactory: ComponentFactory,
private val viewManagerRegistry: ViewManagerRegistry
@@ -11,7 +11,6 @@ import android.view.Choreographer
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.common.build.ReactBuildConfig
import com.facebook.react.uimanager.UIManagerModule
/**
* Each time a frame is drawn, records whether it should have expected any more callbacks since the
@@ -62,7 +61,8 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) :
// removeBridgeIdleDebugListener for Bridgeless
@Suppress("DEPRECATION")
if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) {
val uiManagerModule = reactContext.getNativeModule(UIManagerModule::class.java)
val uiManagerModule =
reactContext.getNativeModule(com.facebook.react.uimanager.UIManagerModule::class.java)
if (!reactContext.isBridgeless) {
reactContext.catalystInstance.addBridgeIdleDebugListener(didJSUpdateUiDuringFrameDetector)
isRunningOnFabric = false
@@ -83,7 +83,8 @@ internal class FpsDebugFrameCallback(private val reactContext: ReactContext) :
fun stop() {
@Suppress("DEPRECATION")
if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) {
val uiManagerModule = reactContext.getNativeModule(UIManagerModule::class.java)
val uiManagerModule =
reactContext.getNativeModule(com.facebook.react.uimanager.UIManagerModule::class.java)
if (!reactContext.isBridgeless) {
reactContext.catalystInstance.removeBridgeIdleDebugListener(
didJSUpdateUiDuringFrameDetector)
@@ -61,7 +61,6 @@ import com.facebook.react.runtime.internal.bolts.Task
import com.facebook.react.runtime.internal.bolts.TaskCompletionSource
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
import com.facebook.react.uimanager.DisplayMetricsHolder
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.events.BlackHoleEventDispatcher
import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper
@@ -523,9 +522,10 @@ public class ReactHostImpl(
internal val nativeModules: Collection<NativeModule>
get() = reactInstance?.nativeModules ?: listOf()
@Suppress("DEPRECATION")
internal fun <T : NativeModule> getNativeModule(nativeModuleInterface: Class<T>): T? {
if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE &&
nativeModuleInterface == UIManagerModule::class.java) {
nativeModuleInterface == com.facebook.react.uimanager.UIManagerModule::class.java) {
ReactSoftExceptionLogger.logSoftExceptionVerbose(
TAG,
ReactNoCrashSoftException(
@@ -56,9 +56,7 @@ import com.facebook.react.views.scroll.ReactScrollViewManager
import com.facebook.react.views.swiperefresh.SwipeRefreshLayoutManager
import com.facebook.react.views.switchview.ReactSwitchManager
import com.facebook.react.views.text.PreparedLayoutTextViewManager
import com.facebook.react.views.text.ReactRawTextManager
import com.facebook.react.views.text.ReactTextViewManager
import com.facebook.react.views.text.ReactVirtualTextViewManager
import com.facebook.react.views.text.frescosupport.FrescoBasedReactTextInlineImageViewManager
import com.facebook.react.views.textinput.ReactTextInputManager
import com.facebook.react.views.unimplementedview.ReactUnimplementedViewManager
@@ -133,6 +131,7 @@ constructor(private val config: MainPackageConfig? = null) :
else -> null
}
@Suppress("DEPRECATION")
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
listOf(
ReactDrawerLayoutManager(),
@@ -147,18 +146,19 @@ constructor(private val config: MainPackageConfig? = null) :
FrescoBasedReactTextInlineImageViewManager(),
ReactImageManager(),
ReactModalHostManager(),
ReactRawTextManager(),
com.facebook.react.views.text.ReactRawTextManager(),
ReactTextInputManager(),
if (ReactNativeFeatureFlags.enablePreparedTextLayout()) PreparedLayoutTextViewManager()
else ReactTextViewManager(),
ReactViewManager(),
ReactVirtualTextViewManager(),
com.facebook.react.views.text.ReactVirtualTextViewManager(),
ReactUnimplementedViewManager())
/**
* A map of view managers that should be registered with
* [com.facebook.react.uimanager.UIManagerModule]
*/
@Suppress("DEPRECATION")
@SuppressLint("VisibleForTests")
public val viewManagersMap: Map<String, ModuleSpec> =
mapOf(
@@ -182,7 +182,8 @@ constructor(private val config: MainPackageConfig? = null) :
ReactImageManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactImageManager() },
ReactModalHostManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactModalHostManager() },
ReactRawTextManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactRawTextManager() },
com.facebook.react.views.text.ReactRawTextManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { com.facebook.react.views.text.ReactRawTextManager() },
ReactTextInputManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactTextInputManager() },
ReactTextViewManager.REACT_CLASS to
@@ -192,8 +193,10 @@ constructor(private val config: MainPackageConfig? = null) :
else ReactTextViewManager()
},
ReactViewManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactViewManager() },
ReactVirtualTextViewManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactVirtualTextViewManager() },
com.facebook.react.views.text.ReactVirtualTextViewManager.REACT_CLASS to
ModuleSpec.viewManagerSpec {
com.facebook.react.views.text.ReactVirtualTextViewManager()
},
ReactUnimplementedViewManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactUnimplementedViewManager() })
@@ -20,7 +20,7 @@ import com.facebook.yoga.YogaConstants
* every view should support, such as rotation, background color, etc.
*/
public abstract class BaseViewManagerDelegate<
T : View, U : BaseViewManager<T, out LayoutShadowNode>>(
T : View, @Suppress("DEPRECATION") U : BaseViewManager<T, out LayoutShadowNode>>(
@Suppress("NoHungarianNotation") @JvmField protected val mViewManager: U
) : ViewManagerDelegate<T> {
@Suppress("ACCIDENTAL_OVERRIDE", "DEPRECATION")
@@ -139,6 +139,6 @@ public object DisplayMetricsHolder {
(checkNotNull(screenDisplayMetrics).heightPixels - verticalInsets).toFloat().pxToDp())
}
private fun encodeFloatsToLong(width: Float, height: Float): Long =
internal fun encodeFloatsToLong(width: Float, height: Float): Long =
(width.toRawBits().toLong()) shl 32 or (height.toRawBits().toLong())
}
@@ -14,6 +14,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import com.facebook.yoga.YogaDirection
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal object LayoutDirectionUtil {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
@@ -38,6 +38,8 @@ import com.facebook.yoga.YogaWrap;
* explored, namely using the VirtualText class in JS and setting the correct set of validAttributes
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class LayoutShadowNode extends ReactShadowNodeImpl {
static {
LegacyArchitectureLogger.assertLegacyArchitecture(
@@ -14,6 +14,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
// - `kind == PARENT` checks whether the node can host children in the native tree.
// - `kind != NONE` checks whether the node appears in the native tree.
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal enum class NativeKind {
// Node is in the native hierarchy and the HierarchyOptimizer should assume it can host children
// (e.g. because it's a ViewGroup). Note that it's okay if the node doesn't support children. When
@@ -68,6 +68,8 @@ import javax.annotation.concurrent.NotThreadSafe;
*/
@NotThreadSafe
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class NativeViewHierarchyManager {
static {
@@ -49,6 +49,8 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger;
* depending on where the views being added/removed are attached in the optimized hierarchy
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class NativeViewHierarchyOptimizer {
static {
@@ -16,6 +16,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
* associated with it.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class NoSuchNativeViewException(detailMessage: String) :
IllegalViewOperationException(detailMessage) {
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager
import androidx.core.util.Pools.SynchronizedPool
@@ -20,6 +22,9 @@ import com.facebook.react.uimanager.events.Event
/** Event used to notify JS component about changes of its position or dimensions. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.WARNING)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class OnLayoutEvent private constructor() : Event<OnLayoutEvent>() {
@VisibleForTesting internal var x: Int = 0
@VisibleForTesting internal var y: Int = 0
@@ -46,6 +46,8 @@ import com.facebook.yoga.YogaWrap;
* NativeViewHierarchyOptimizer} for more information.
*/
@LegacyArchitecture
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public interface ReactShadowNode<T extends ReactShadowNode> {
/**
@@ -60,6 +60,8 @@ import java.util.Arrays;
*/
@ReactPropertyHolder
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class ReactShadowNodeImpl implements ReactShadowNode<ReactShadowNodeImpl> {
private static final YogaConfig sYogaConfig;
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager
import android.util.SparseArray
@@ -20,6 +22,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
* UIManagerModule instance.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class ShadowNodeRegistry {
private val tagsToCSSNodes = SparseArray<ReactShadowNode<*>>()
private val rootTags = SparseBooleanArray()
@@ -17,6 +17,7 @@ import android.view.View
*
* @param <T> the view handled by this manager
*/
@Suppress("DEPRECATION")
public abstract class SimpleViewManager<T : View> : BaseViewManager<T, LayoutShadowNode>() {
public override fun createShadowNodeInstance(): LayoutShadowNode {
@@ -9,5 +9,7 @@ package com.facebook.react.uimanager
/** A task to execute on the UI View for third party libraries. */
public fun interface UIBlock {
public fun execute(nativeViewHierarchyManager: NativeViewHierarchyManager)
public fun execute(
@Suppress("DEPRECATION") nativeViewHierarchyManager: NativeViewHierarchyManager
)
}
@@ -42,6 +42,8 @@ import java.util.Map;
* hierarchy that is then mapped to a native view hierarchy.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class UIImplementation {
static {
LegacyArchitectureLogger.assertLegacyArchitecture(
@@ -88,6 +88,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
@ReactModule(name = UIManagerModule.NAME)
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class UIManagerModule extends ReactContextBaseJavaModule
implements OnBatchCompleteListener, LifecycleEventListener, UIManager {
static {
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -49,6 +49,8 @@ import java.util.Map;
* for operations queue to save on allocations
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
since = "This class is part of Legacy Architecture and will be removed in a future release")
public class UIViewOperationQueue {
static {
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -17,6 +19,9 @@ import java.util.Objects
* operation.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class ViewAtIndex(
@Suppress("NoHungarianNotation") @JvmField public val mTag: Int,
@Suppress("NoHungarianNotation") @JvmField public val mIndex: Int
@@ -13,6 +13,7 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.UiThreadUtil
import java.util.WeakHashMap
@Suppress("DEPRECATION")
public abstract class ViewGroupManager<T : ViewGroup>
@JvmOverloads
constructor(reactContext: ReactApplicationContext? = null) :
@@ -13,6 +13,7 @@ import com.facebook.react.bridge.ReadableArray
import com.facebook.react.uimanager.ViewManagersPropertyCache.PropSetter
import java.util.HashMap
@Suppress("DEPRECATION")
public object ViewManagerPropertyUpdater {
public fun interface Settable {
public fun getProperties(props: MutableMap<String, String>)
@@ -24,7 +25,7 @@ public object ViewManagerPropertyUpdater {
}
@Suppress("FINITE_BOUNDS_VIOLATION_IN_JAVA")
public interface ShadowNodeSetter<in T : ReactShadowNode<*>> : Settable {
public interface ShadowNodeSetter<@Suppress("DEPRECATION") in T : ReactShadowNode<*>> : Settable {
public fun setProperty(node: T, name: String, value: Any?)
}
@@ -71,7 +72,10 @@ public object ViewManagerPropertyUpdater {
@JvmStatic
@Deprecated("Use ViewManager#updateProperties to update a view's properties")
public fun <T : ReactShadowNode<T>> updateProps(node: T, props: ReactStylesDiffMap) {
public fun <@Suppress("DEPRECATION") T : ReactShadowNode<T>> updateProps(
node: T,
props: ReactStylesDiffMap
) {
val setter = findNodeSetter(node.javaClass)
val iterator = props.backingMap.entryIterator
while (iterator.hasNext()) {
@@ -108,7 +112,7 @@ public object ViewManagerPropertyUpdater {
return setter as ViewManagerSetter<ViewManager<V, *>, V>
}
private fun <T : ReactShadowNode<T>> findNodeSetter(
private fun <@Suppress("DEPRECATION") T : ReactShadowNode<T>> findNodeSetter(
nodeClass: Class<out T>
): ShadowNodeSetter<T> {
var setter = SHADOW_NODE_SETTER_MAP[nodeClass]
@@ -143,16 +147,16 @@ public object ViewManagerPropertyUpdater {
private class FallbackViewManagerSetter<V : View>(
viewManagerClass: Class<out ViewManager<V, *>>
) : ViewManagerSetter<ViewManager<V, *>, V> {
private val mPropSetters: Map<String, PropSetter> =
private val propSetters: Map<String, PropSetter> =
ViewManagersPropertyCache.getNativePropSettersForViewManagerClass(viewManagerClass)
override fun setProperty(manager: ViewManager<V, *>, view: V, name: String, value: Any?) {
val setter = mPropSetters[name]
val setter = propSetters[name]
setter?.updateViewProp(manager, view, value)
}
override fun getProperties(props: MutableMap<String, String>) {
for (setter in mPropSetters.values) {
for (setter in propSetters.values) {
props[setter.propName] = setter.propType
}
}
@@ -15,6 +15,9 @@ import com.facebook.yoga.YogaNode
/** Static holder for a recycling pool of YogaNodes. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal object YogaNodePool {
init {
LegacyArchitectureLogger.assertLegacyArchitecture(
@@ -14,7 +14,6 @@ import com.facebook.react.common.annotations.LegacyArchitectureShadowNodeWithCxx
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import com.facebook.react.uimanager.LayoutShadowNode
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.yoga.YogaMeasureFunction
import com.facebook.yoga.YogaMeasureMode
@@ -25,9 +24,14 @@ import com.facebook.yoga.YogaNode
* Node responsible for holding the style of the ProgressBar, see under [ ] for possible styles.
* ReactProgressBarViewManager manages how this style is applied to the ProgressBar.
*/
@Suppress("DEPRECATION")
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@LegacyArchitectureShadowNodeWithCxxImpl
internal class ProgressBarShadowNode : LayoutShadowNode(), YogaMeasureFunction {
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class ProgressBarShadowNode :
com.facebook.react.uimanager.LayoutShadowNode(), YogaMeasureFunction {
private val height: SparseIntArray = SparseIntArray()
private val width: SparseIntArray = SparseIntArray()
private val measured: MutableSet<Int> = HashSet()
@@ -33,6 +33,7 @@ import java.util.WeakHashMap
* a [ProgressBar] changes, we have to drop the existing [ProgressBar] (if there is one) and create
* a new one with the style given.
*/
@Suppress("DEPRECATION")
@ReactModule(name = ReactProgressBarViewManager.REACT_CLASS)
internal class ReactProgressBarViewManager :
BaseViewManager<ProgressBarContainerView, ProgressBarShadowNode>(),
@@ -19,7 +19,6 @@ import com.facebook.react.common.build.ReactBuildConfig
import com.facebook.react.uimanager.PixelUtil.pxToDp
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.UIManagerModule
internal class ReactSafeAreaView(val reactContext: ThemedReactContext) : ViewGroup(reactContext) {
internal var stateWrapper: StateWrapper? = null
@@ -39,6 +38,7 @@ internal class ReactSafeAreaView(val reactContext: ThemedReactContext) : ViewGro
override fun onLayout(p0: Boolean, p1: Int, p2: Int, p3: Int, p4: Int): Unit = Unit
@Suppress("DEPRECATION")
@UiThread
private fun updateState(insets: Insets) {
val sw = stateWrapper
@@ -57,7 +57,7 @@ internal class ReactSafeAreaView(val reactContext: ThemedReactContext) : ViewGro
object : GuardedRunnable(reactContext) {
override fun runGuarded() {
this@ReactSafeAreaView.reactContext.reactApplicationContext
.getNativeModule(UIManagerModule::class.java)
.getNativeModule(com.facebook.react.uimanager.UIManagerModule::class.java)
?.updateInsetsPadding(id, insets.top, insets.left, insets.bottom, insets.right)
}
})
@@ -8,7 +8,6 @@
package com.facebook.react.views.safeareaview
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.LayoutShadowNode
import com.facebook.react.uimanager.ReactStylesDiffMap
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.ThemedReactContext
@@ -31,9 +30,13 @@ internal class ReactSafeAreaViewManager :
override fun getName(): String = REACT_CLASS
override fun createShadowNodeInstance(): LayoutShadowNode = LayoutShadowNode()
@Suppress("DEPRECATION")
override fun createShadowNodeInstance(): com.facebook.react.uimanager.LayoutShadowNode =
com.facebook.react.uimanager.LayoutShadowNode()
override fun getShadowNodeClass(): Class<out LayoutShadowNode> = LayoutShadowNode::class.java
@Suppress("DEPRECATION")
override fun getShadowNodeClass(): Class<out com.facebook.react.uimanager.LayoutShadowNode> =
com.facebook.react.uimanager.LayoutShadowNode::class.java
override fun updateState(
view: ReactSafeAreaView,
@@ -25,6 +25,7 @@ import com.facebook.react.viewmanagers.AndroidSwitchManagerInterface
import com.facebook.yoga.YogaMeasureMode
import com.facebook.yoga.YogaMeasureOutput
@Suppress("DEPRECATION")
internal class ReactSwitchManager :
BaseViewManager<ReactSwitch, ReactSwitchShadowNode>(),
AndroidSwitchManagerInterface<ReactSwitch> {
@@ -12,15 +12,19 @@ import com.facebook.react.common.annotations.LegacyArchitectureShadowNodeWithCxx
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
import com.facebook.react.uimanager.LayoutShadowNode
import com.facebook.yoga.YogaMeasureFunction
import com.facebook.yoga.YogaMeasureMode
import com.facebook.yoga.YogaMeasureOutput
import com.facebook.yoga.YogaNode
@Suppress("DEPRECATION")
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
@LegacyArchitectureShadowNodeWithCxxImpl
internal class ReactSwitchShadowNode : LayoutShadowNode(), YogaMeasureFunction {
internal class ReactSwitchShadowNode :
com.facebook.react.uimanager.LayoutShadowNode(), YogaMeasureFunction {
private var width = 0
private var height = 0
private var measured = false
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.views.text
import android.text.Spannable
@@ -1,669 +0,0 @@
/*
* 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.facebook.react.views.text;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Build;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.view.Gravity;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.annotations.internal.LegacyArchitecture;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.NativeViewHierarchyOptimizer;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole;
import com.facebook.react.uimanager.ReactAccessibilityDelegate.Role;
import com.facebook.react.uimanager.ReactShadowNode;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.text.internal.ReactTextInlineImageShadowNode;
import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan;
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan;
import com.facebook.react.views.text.internal.span.CustomStyleSpan;
import com.facebook.react.views.text.internal.span.ReactAbsoluteSizeSpan;
import com.facebook.react.views.text.internal.span.ReactBackgroundColorSpan;
import com.facebook.react.views.text.internal.span.ReactClickableSpan;
import com.facebook.react.views.text.internal.span.ReactForegroundColorSpan;
import com.facebook.react.views.text.internal.span.ReactSpan;
import com.facebook.react.views.text.internal.span.ReactStrikethroughSpan;
import com.facebook.react.views.text.internal.span.ReactTagSpan;
import com.facebook.react.views.text.internal.span.ReactUnderlineSpan;
import com.facebook.react.views.text.internal.span.SetSpanOperation;
import com.facebook.react.views.text.internal.span.ShadowStyleSpan;
import com.facebook.react.views.text.internal.span.TextInlineImageSpan;
import com.facebook.react.views.text.internal.span.TextInlineViewPlaceholderSpan;
import com.facebook.yoga.YogaDirection;
import com.facebook.yoga.YogaUnit;
import com.facebook.yoga.YogaValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* {@link ReactShadowNode} abstract class for spannable text nodes.
*
* <p>This class handles all text attributes associated with {@code <Text>}-ish node. A concrete
* node can be an anchor {@code <Text>} node, an anchor {@code <TextInput>} node or virtual {@code
* <Text>} node inside {@code <Text>} or {@code <TextInput>} node. Or even something else.
*
* <p>This also node calculates {@link Spannable} object based on subnodes of the same type, which
* can be used in concrete classes to feed native views and compute layout.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Nullsafe(Nullsafe.Mode.LOCAL)
public abstract class ReactBaseTextShadowNode extends LayoutShadowNode {
// Use a direction weak character so the placeholder doesn't change the direction of the previous
// character.
// https://en.wikipedia.org/wiki/Bi-directional_text#weak_characters
private static final String INLINE_VIEW_PLACEHOLDER = "0";
public static final String PROP_SHADOW_OFFSET = "textShadowOffset";
public static final String PROP_SHADOW_OFFSET_WIDTH = "width";
public static final String PROP_SHADOW_OFFSET_HEIGHT = "height";
public static final String PROP_SHADOW_RADIUS = "textShadowRadius";
public static final String PROP_SHADOW_COLOR = "textShadowColor";
public static final String PROP_TEXT_TRANSFORM = "textTransform";
public static final int DEFAULT_TEXT_SHADOW_COLOR = 0x55000000;
protected @Nullable ReactTextViewManagerCallback mReactTextViewManagerCallback;
private static void buildSpannedFromShadowNode(
ReactBaseTextShadowNode textShadowNode,
SpannableStringBuilder sb,
List<SetSpanOperation> ops,
@Nullable TextAttributes parentTextAttributes,
boolean supportsInlineViews,
@Nullable Map<Integer, ReactShadowNode> inlineViews,
int start) {
TextAttributes textAttributes;
if (parentTextAttributes != null) {
textAttributes = parentTextAttributes.applyChild(textShadowNode.mTextAttributes);
} else {
textAttributes = textShadowNode.mTextAttributes;
}
for (int i = 0, length = textShadowNode.getChildCount(); i < length; i++) {
ReactShadowNode child = textShadowNode.getChildAt(i);
if (child instanceof ReactRawTextShadowNode) {
String childText = ((ReactRawTextShadowNode) child).getText();
if (childText != null) {
sb.append(TextTransform.apply(childText, textAttributes.textTransform));
}
} else if (child instanceof ReactBaseTextShadowNode) {
buildSpannedFromShadowNode(
(ReactBaseTextShadowNode) child,
sb,
ops,
textAttributes,
supportsInlineViews,
inlineViews,
sb.length());
} else if (child instanceof ReactTextInlineImageShadowNode) {
// We make the image take up 1 character in the span and put a corresponding character into
// the text so that the image doesn't run over any following text.
sb.append(INLINE_VIEW_PLACEHOLDER);
ops.add(
new SetSpanOperation(
sb.length() - INLINE_VIEW_PLACEHOLDER.length(),
sb.length(),
((ReactTextInlineImageShadowNode) child).buildInlineImageSpan()));
} else if (supportsInlineViews) {
int reactTag = child.getReactTag();
YogaValue widthValue = child.getStyleWidth();
YogaValue heightValue = child.getStyleHeight();
float width;
float height;
if (widthValue.unit != YogaUnit.POINT || heightValue.unit != YogaUnit.POINT) {
// If the measurement of the child isn't calculated, we calculate the layout for the
// view using Yoga
child.calculateLayout();
width = child.getLayoutWidth();
height = child.getLayoutHeight();
} else {
width = widthValue.value;
height = heightValue.value;
}
// We make the inline view take up 1 character in the span and put a corresponding character
// into
// the text so that the inline view doesn't run over any following text.
sb.append(INLINE_VIEW_PLACEHOLDER);
ops.add(
new SetSpanOperation(
sb.length() - INLINE_VIEW_PLACEHOLDER.length(),
sb.length(),
new TextInlineViewPlaceholderSpan(reactTag, (int) width, (int) height)));
// supportsInlineViews is true, so we can assume that inlineViews is not null
Assertions.assertNotNull(inlineViews).put(reactTag, child);
} else {
throw new IllegalViewOperationException(
"Unexpected view type nested under a <Text> or <TextInput> node: " + child.getClass());
}
child.markUpdateSeen();
}
int end = sb.length();
if (end >= start) {
if (textShadowNode.mIsColorSet) {
ops.add(
new SetSpanOperation(start, end, new ReactForegroundColorSpan(textShadowNode.mColor)));
}
if (textShadowNode.mIsBackgroundColorSet) {
ops.add(
new SetSpanOperation(
start, end, new ReactBackgroundColorSpan(textShadowNode.mBackgroundColor)));
}
boolean roleIsLink =
textShadowNode.mRole != null
? textShadowNode.mRole == Role.LINK
: textShadowNode.mAccessibilityRole == AccessibilityRole.LINK;
if (roleIsLink) {
ops.add(
new SetSpanOperation(start, end, new ReactClickableSpan(textShadowNode.getReactTag())));
}
float effectiveLetterSpacing = textAttributes.getEffectiveLetterSpacing();
if (!Float.isNaN(effectiveLetterSpacing)
&& (parentTextAttributes == null
|| parentTextAttributes.getEffectiveLetterSpacing() != effectiveLetterSpacing)) {
ops.add(
new SetSpanOperation(start, end, new CustomLetterSpacingSpan(effectiveLetterSpacing)));
}
int effectiveFontSize = textAttributes.getEffectiveFontSize();
if ( // `getEffectiveFontSize` always returns a value so don't need to check for anything like
// `Float.NaN`.
parentTextAttributes == null
|| parentTextAttributes.getEffectiveFontSize() != effectiveFontSize) {
ops.add(new SetSpanOperation(start, end, new ReactAbsoluteSizeSpan(effectiveFontSize)));
}
if (textShadowNode.mFontStyle != ReactConstants.UNSET
|| textShadowNode.mFontWeight != ReactConstants.UNSET
|| textShadowNode.mFontFamily != null) {
ops.add(
new SetSpanOperation(
start,
end,
new CustomStyleSpan(
textShadowNode.mFontStyle,
textShadowNode.mFontWeight,
textShadowNode.mFontFeatureSettings,
textShadowNode.mFontFamily,
textShadowNode.getThemedContext().getAssets())));
}
if (textShadowNode.mIsUnderlineTextDecorationSet) {
ops.add(new SetSpanOperation(start, end, new ReactUnderlineSpan()));
}
if (textShadowNode.mIsLineThroughTextDecorationSet) {
ops.add(new SetSpanOperation(start, end, new ReactStrikethroughSpan()));
}
if ((textShadowNode.mTextShadowOffsetDx != 0
|| textShadowNode.mTextShadowOffsetDy != 0
|| textShadowNode.mTextShadowRadius != 0)
&& Color.alpha(textShadowNode.mTextShadowColor) != 0) {
ops.add(
new SetSpanOperation(
start,
end,
new ShadowStyleSpan(
textShadowNode.mTextShadowOffsetDx,
textShadowNode.mTextShadowOffsetDy,
textShadowNode.mTextShadowRadius,
textShadowNode.mTextShadowColor)));
}
float effectiveLineHeight = textAttributes.getEffectiveLineHeight();
if (!Float.isNaN(effectiveLineHeight)
&& (parentTextAttributes == null
|| parentTextAttributes.getEffectiveLineHeight() != effectiveLineHeight)) {
ops.add(new SetSpanOperation(start, end, new CustomLineHeightSpan(effectiveLineHeight)));
}
ops.add(new SetSpanOperation(start, end, new ReactTagSpan(textShadowNode.getReactTag())));
}
}
// `nativeViewHierarchyOptimizer` can be `null` as long as `supportsInlineViews` is `false`.
protected Spannable spannedFromShadowNode(
ReactBaseTextShadowNode textShadowNode,
@Nullable String text,
boolean supportsInlineViews,
@Nullable NativeViewHierarchyOptimizer nativeViewHierarchyOptimizer) {
Assertions.assertCondition(
!supportsInlineViews || nativeViewHierarchyOptimizer != null,
"nativeViewHierarchyOptimizer is required when inline views are supported");
SpannableStringBuilder sb = new SpannableStringBuilder();
// TODO(5837930): Investigate whether it's worth optimizing this part and do it if so
// The {@link SpannableStringBuilder} implementation require setSpan operation to be called
// up-to-bottom, otherwise all the spannables that are within the region for which one may set
// a new spannable will be wiped out
List<SetSpanOperation> ops = new ArrayList<>();
Map<Integer, ReactShadowNode> inlineViews = supportsInlineViews ? new HashMap<>() : null;
if (text != null) {
// Handle text that is provided via a prop (e.g. the `value` and `defaultValue` props on
// TextInput).
sb.append(TextTransform.apply(text, textShadowNode.mTextAttributes.textTransform));
}
buildSpannedFromShadowNode(textShadowNode, sb, ops, null, supportsInlineViews, inlineViews, 0);
textShadowNode.mContainsImages = false;
textShadowNode.mInlineViews = inlineViews;
float heightOfTallestInlineViewOrImage = Float.NaN;
// While setting the Spans on the final text, we also check whether any of them are inline views
// or images.
for (int priorityIndex = 0; priorityIndex < ops.size(); priorityIndex++) {
final SetSpanOperation op = ops.get(ops.size() - priorityIndex - 1);
final ReactSpan what = op.what;
boolean isInlineImage = what instanceof TextInlineImageSpan;
if (isInlineImage || what instanceof TextInlineViewPlaceholderSpan) {
int height;
if (isInlineImage) {
height = ((TextInlineImageSpan) what).getHeight();
textShadowNode.mContainsImages = true;
} else {
TextInlineViewPlaceholderSpan placeholder = (TextInlineViewPlaceholderSpan) what;
height = placeholder.getHeight();
// Inline views cannot be layout-only because the ReactTextView needs to be able to grab
// ahold of them on the UI thread to size and position them.
ReactShadowNode childNode =
Assertions.assertNotNull(inlineViews).get(placeholder.getReactTag());
Assertions.assertNotNull(childNode);
Assertions.assertNotNull(nativeViewHierarchyOptimizer);
nativeViewHierarchyOptimizer.handleForceViewToBeNonLayoutOnly(childNode);
// The ReactTextView is responsible for laying out the inline views.
childNode.setLayoutParent(textShadowNode);
}
if (Float.isNaN(heightOfTallestInlineViewOrImage)
|| height > heightOfTallestInlineViewOrImage) {
heightOfTallestInlineViewOrImage = height;
}
}
// Actual order of calling {@code execute} does NOT matter,
// but the {@code priorityIndex} DOES matter.
op.execute(sb, priorityIndex);
}
textShadowNode.mTextAttributes.setHeightOfTallestInlineViewOrImage(
heightOfTallestInlineViewOrImage);
if (mReactTextViewManagerCallback != null) {
mReactTextViewManagerCallback.onPostProcessSpannable(sb);
}
return sb;
}
protected TextAttributes mTextAttributes;
protected boolean mIsColorSet = false;
protected int mColor;
protected boolean mIsBackgroundColorSet = false;
protected int mBackgroundColor;
protected @Nullable AccessibilityRole mAccessibilityRole = null;
protected @Nullable Role mRole = null;
protected int mNumberOfLines = ReactConstants.UNSET;
protected int mTextAlign = Gravity.NO_GRAVITY;
protected int mTextBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
protected int mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
protected int mJustificationMode =
(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) ? 0 : Layout.JUSTIFICATION_MODE_NONE;
protected float mTextShadowOffsetDx = 0;
protected float mTextShadowOffsetDy = 0;
protected float mTextShadowRadius = 0;
protected int mTextShadowColor = DEFAULT_TEXT_SHADOW_COLOR;
protected boolean mIsUnderlineTextDecorationSet = false;
protected boolean mIsLineThroughTextDecorationSet = false;
protected boolean mIncludeFontPadding = true;
protected boolean mAdjustsFontSizeToFit = false;
protected float mMinimumFontScale = 0;
/**
* mFontStyle can be {@link Typeface#NORMAL} or {@link Typeface#ITALIC}. mFontWeight can be {@link
* Typeface#NORMAL} or {@link Typeface#BOLD}.
*/
protected int mFontStyle = ReactConstants.UNSET;
protected int mFontWeight = ReactConstants.UNSET;
/**
* NB: If a font family is used that does not have a style in a certain Android version (ie.
* monospace bold pre Android 5.0), that style (ie. bold) will not be inherited by nested Text
* nodes. To retain that style, you have to add it to those nodes explicitly.
*
* <p>Example, Android 4.4:
*
* <pre>
* <Text style={{fontFamily="serif" fontWeight="bold"}}>Bold Text</Text>
* <Text style={{fontFamily="sans-serif"}}>Bold Text</Text>
* <Text style={{fontFamily="serif}}>Bold Text</Text>
*
* <Text style={{fontFamily="monospace" fontWeight="bold"}}>Not Bold Text</Text>
* <Text style={{fontFamily="sans-serif"}}>Not Bold Text</Text>
* <Text style={{fontFamily="serif}}>Not Bold Text</Text>
*
* <Text style={{fontFamily="monospace" fontWeight="bold"}}>Not Bold Text</Text>
* <Text style={{fontFamily="sans-serif" fontWeight="bold"}}>Bold Text</Text>
* <Text style={{fontFamily="serif}}>Bold Text</Text>
* </pre>
*/
protected @Nullable String mFontFamily = null;
/**
* @see android.graphics.Paint#setFontFeatureSettings
*/
protected @Nullable String mFontFeatureSettings = null;
protected boolean mContainsImages = false;
// Only nullable iff `supportsInlineViews` is `false`.
protected @Nullable Map<Integer, ReactShadowNode> mInlineViews;
public ReactBaseTextShadowNode() {
this(null);
}
public ReactBaseTextShadowNode(
@Nullable ReactTextViewManagerCallback reactTextViewManagerCallback) {
mTextAttributes = new TextAttributes();
mReactTextViewManagerCallback = reactTextViewManagerCallback;
}
// Return text alignment according to LTR or RTL style
private int getTextAlign() {
int textAlign = mTextAlign;
if (getLayoutDirection() == YogaDirection.RTL) {
if (textAlign == Gravity.RIGHT) {
textAlign = Gravity.LEFT;
} else if (textAlign == Gravity.LEFT) {
textAlign = Gravity.RIGHT;
}
}
return textAlign;
}
@ReactProp(name = ViewProps.NUMBER_OF_LINES, defaultInt = ReactConstants.UNSET)
public void setNumberOfLines(int numberOfLines) {
mNumberOfLines = numberOfLines == 0 ? ReactConstants.UNSET : numberOfLines;
markUpdated();
}
@ReactProp(name = ViewProps.LINE_HEIGHT, defaultFloat = Float.NaN)
public void setLineHeight(float lineHeight) {
mTextAttributes.setLineHeight(lineHeight);
markUpdated();
}
@ReactProp(name = ViewProps.LETTER_SPACING, defaultFloat = 0.f)
public void setLetterSpacing(float letterSpacing) {
mTextAttributes.setLetterSpacing(letterSpacing);
markUpdated();
}
@ReactProp(name = ViewProps.ALLOW_FONT_SCALING, defaultBoolean = true)
public void setAllowFontScaling(boolean allowFontScaling) {
if (allowFontScaling != mTextAttributes.getAllowFontScaling()) {
mTextAttributes.setAllowFontScaling(allowFontScaling);
markUpdated();
}
}
@ReactProp(name = ViewProps.MAX_FONT_SIZE_MULTIPLIER, defaultFloat = Float.NaN)
public void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) {
if (maxFontSizeMultiplier != mTextAttributes.getMaxFontSizeMultiplier()) {
mTextAttributes.setMaxFontSizeMultiplier(maxFontSizeMultiplier);
markUpdated();
}
}
@ReactProp(name = ViewProps.TEXT_ALIGN)
public void setTextAlign(@Nullable String textAlign) {
if ("justify".equals(textAlign)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mJustificationMode = Layout.JUSTIFICATION_MODE_INTER_WORD;
}
mTextAlign = Gravity.LEFT;
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
}
if (textAlign == null || "auto".equals(textAlign)) {
mTextAlign = Gravity.NO_GRAVITY;
} else if ("left".equals(textAlign)) {
mTextAlign = Gravity.LEFT;
} else if ("right".equals(textAlign)) {
mTextAlign = Gravity.RIGHT;
} else if ("center".equals(textAlign)) {
mTextAlign = Gravity.CENTER_HORIZONTAL;
} else {
FLog.w(ReactConstants.TAG, "Invalid textAlign: " + textAlign);
mTextAlign = Gravity.NO_GRAVITY;
}
}
markUpdated();
}
@ReactProp(name = ViewProps.FONT_SIZE, defaultFloat = Float.NaN)
public void setFontSize(float fontSize) {
mTextAttributes.setFontSize(fontSize);
markUpdated();
}
@ReactProp(name = ViewProps.COLOR, customType = "Color")
public void setColor(@Nullable Integer color) {
if (color != null) {
mIsColorSet = true;
mColor = color;
}
markUpdated();
}
@ReactProp(name = ViewProps.BACKGROUND_COLOR, customType = "Color")
public void setBackgroundColor(@Nullable Integer color) {
// Background color needs to be handled here for virtual nodes so it can be incorporated into
// the span. However, it doesn't need to be applied to non-virtual nodes because non-virtual
// nodes get mapped to native views and native views get their background colors get set via
// {@link BaseViewManager}.
if (isVirtual()) {
if (color != null) {
mIsBackgroundColorSet = true;
mBackgroundColor = color;
}
markUpdated();
}
}
@ReactProp(name = ViewProps.ACCESSIBILITY_ROLE)
public void setAccessibilityRole(@Nullable String accessibilityRole) {
if (isVirtual()) {
mAccessibilityRole = AccessibilityRole.fromValue(accessibilityRole);
markUpdated();
}
}
@ReactProp(name = ViewProps.ROLE)
public void setRole(@Nullable String role) {
if (isVirtual()) {
mRole = Role.fromValue(role);
markUpdated();
}
}
@ReactProp(name = ViewProps.FONT_FAMILY)
public void setFontFamily(@Nullable String fontFamily) {
mFontFamily = fontFamily;
markUpdated();
}
@ReactProp(name = ViewProps.FONT_WEIGHT)
public void setFontWeight(@Nullable String fontWeightString) {
int fontWeight = ReactTypefaceUtils.parseFontWeight(fontWeightString);
if (fontWeight != mFontWeight) {
mFontWeight = fontWeight;
markUpdated();
}
}
@ReactProp(name = ViewProps.FONT_VARIANT)
public void setFontVariant(@Nullable ReadableArray fontVariantArray) {
String fontFeatureSettings = ReactTypefaceUtils.parseFontVariant(fontVariantArray);
if (!TextUtils.equals(fontFeatureSettings, mFontFeatureSettings)) {
mFontFeatureSettings = fontFeatureSettings;
markUpdated();
}
}
@ReactProp(name = ViewProps.FONT_STYLE)
public void setFontStyle(@Nullable String fontStyleString) {
int fontStyle = ReactTypefaceUtils.parseFontStyle(fontStyleString);
if (fontStyle != mFontStyle) {
mFontStyle = fontStyle;
markUpdated();
}
}
@ReactProp(name = ViewProps.INCLUDE_FONT_PADDING, defaultBoolean = true)
public void setIncludeFontPadding(boolean includepad) {
mIncludeFontPadding = includepad;
}
@ReactProp(name = ViewProps.TEXT_DECORATION_LINE)
public void setTextDecorationLine(@Nullable String textDecorationLineString) {
mIsUnderlineTextDecorationSet = false;
mIsLineThroughTextDecorationSet = false;
if (textDecorationLineString != null) {
for (String textDecorationLineSubString : textDecorationLineString.split(" ")) {
if ("underline".equals(textDecorationLineSubString)) {
mIsUnderlineTextDecorationSet = true;
} else if ("line-through".equals(textDecorationLineSubString)) {
mIsLineThroughTextDecorationSet = true;
}
}
}
markUpdated();
}
@ReactProp(name = ViewProps.TEXT_BREAK_STRATEGY)
public void setTextBreakStrategy(@Nullable String textBreakStrategy) {
if (textBreakStrategy == null || "highQuality".equals(textBreakStrategy)) {
mTextBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
} else if ("simple".equals(textBreakStrategy)) {
mTextBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
} else if ("balanced".equals(textBreakStrategy)) {
mTextBreakStrategy = Layout.BREAK_STRATEGY_BALANCED;
} else {
FLog.w(ReactConstants.TAG, "Invalid textBreakStrategy: " + textBreakStrategy);
mTextBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
}
markUpdated();
}
@ReactProp(name = PROP_SHADOW_OFFSET)
public void setTextShadowOffset(ReadableMap offsetMap) {
mTextShadowOffsetDx = 0;
mTextShadowOffsetDy = 0;
if (offsetMap != null) {
if (offsetMap.hasKey(PROP_SHADOW_OFFSET_WIDTH)
&& !offsetMap.isNull(PROP_SHADOW_OFFSET_WIDTH)) {
mTextShadowOffsetDx =
PixelUtil.toPixelFromDIP(offsetMap.getDouble(PROP_SHADOW_OFFSET_WIDTH));
}
if (offsetMap.hasKey(PROP_SHADOW_OFFSET_HEIGHT)
&& !offsetMap.isNull(PROP_SHADOW_OFFSET_HEIGHT)) {
mTextShadowOffsetDy =
PixelUtil.toPixelFromDIP(offsetMap.getDouble(PROP_SHADOW_OFFSET_HEIGHT));
}
}
markUpdated();
}
@ReactProp(name = PROP_SHADOW_RADIUS, defaultInt = 1)
public void setTextShadowRadius(float textShadowRadius) {
if (textShadowRadius != mTextShadowRadius) {
mTextShadowRadius = textShadowRadius;
markUpdated();
}
}
@ReactProp(name = PROP_SHADOW_COLOR, defaultInt = DEFAULT_TEXT_SHADOW_COLOR, customType = "Color")
public void setTextShadowColor(int textShadowColor) {
if (textShadowColor != mTextShadowColor) {
mTextShadowColor = textShadowColor;
markUpdated();
}
}
@ReactProp(name = PROP_TEXT_TRANSFORM)
public void setTextTransform(@Nullable String textTransform) {
TextTransform textTransformEnum = TextTransform.UNSET;
if (textTransform == null) {
textTransformEnum = TextTransform.UNSET;
} else if ("none".equals(textTransform)) {
textTransformEnum = TextTransform.NONE;
} else if ("uppercase".equals(textTransform)) {
textTransformEnum = TextTransform.UPPERCASE;
} else if ("lowercase".equals(textTransform)) {
textTransformEnum = TextTransform.LOWERCASE;
} else if ("capitalize".equals(textTransform)) {
textTransformEnum = TextTransform.CAPITALIZE;
} else {
FLog.w(ReactConstants.TAG, "Invalid textTransform: " + textTransform);
}
mTextAttributes.textTransform = textTransformEnum;
markUpdated();
}
@ReactProp(name = ViewProps.ADJUSTS_FONT_SIZE_TO_FIT)
public void setAdjustFontSizeToFit(boolean adjustsFontSizeToFit) {
if (adjustsFontSizeToFit != mAdjustsFontSizeToFit) {
mAdjustsFontSizeToFit = adjustsFontSizeToFit;
markUpdated();
}
}
@ReactProp(name = ViewProps.MINIMUM_FONT_SCALE)
public void setMinimumFontScale(float minimumFontScale) {
if (minimumFontScale != mMinimumFontScale) {
mMinimumFontScale = minimumFontScale;
markUpdated();
}
}
}
@@ -0,0 +1,651 @@
/*
* 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.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.views.text
import android.graphics.Color
import android.os.Build
import android.text.Layout
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.view.Gravity
import com.facebook.common.logging.FLog
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.common.ReactConstants
import com.facebook.react.common.annotations.internal.LegacyArchitecture
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
import com.facebook.react.uimanager.IllegalViewOperationException
import com.facebook.react.uimanager.LayoutShadowNode
import com.facebook.react.uimanager.PixelUtil.toPixelFromDIP
import com.facebook.react.uimanager.ReactAccessibilityDelegate
import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ReactShadowNodeImpl
import com.facebook.react.uimanager.ViewProps
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontStyle
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontVariant
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
import com.facebook.react.views.text.TextTransform.Companion.apply
import com.facebook.react.views.text.internal.ReactTextInlineImageShadowNode
import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan
import com.facebook.react.views.text.internal.span.CustomStyleSpan
import com.facebook.react.views.text.internal.span.ReactAbsoluteSizeSpan
import com.facebook.react.views.text.internal.span.ReactBackgroundColorSpan
import com.facebook.react.views.text.internal.span.ReactClickableSpan
import com.facebook.react.views.text.internal.span.ReactForegroundColorSpan
import com.facebook.react.views.text.internal.span.ReactStrikethroughSpan
import com.facebook.react.views.text.internal.span.ReactTagSpan
import com.facebook.react.views.text.internal.span.ReactUnderlineSpan
import com.facebook.react.views.text.internal.span.SetSpanOperation
import com.facebook.react.views.text.internal.span.ShadowStyleSpan
import com.facebook.react.views.text.internal.span.TextInlineImageSpan
import com.facebook.react.views.text.internal.span.TextInlineViewPlaceholderSpan
import com.facebook.yoga.YogaDirection
import com.facebook.yoga.YogaUnit
/**
* [ReactShadowNode] abstract class for spannable text nodes.
*
* This class handles all text attributes associated with `<Text>`-ish node. A concrete node can be
* an anchor `<Text>` node, an anchor `<TextInput>` node or virtual `<Text>` node inside `<Text>` or
* `<TextInput>` node. Or even something else.
*
* This also node calculates [Spannable] object based on sub nodes of the same type, which can be
* used in concrete classes to feed native views and compute layout.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release")
public abstract class ReactBaseTextShadowNode
@JvmOverloads
public constructor(
protected var reactTextViewManagerCallback: ReactTextViewManagerCallback? = null
) : LayoutShadowNode() {
protected var textAttributes: TextAttributes = TextAttributes()
protected var isColorSet: Boolean = false
protected var color: Int = 0
protected var isBackgroundColorSet: Boolean = false
protected var backgroundColor: Int = 0
protected var accessibilityRole: AccessibilityRole? = null
protected var role: ReactAccessibilityDelegate.Role? = null
protected var numberOfLines: Int = ReactConstants.UNSET
private set
protected var textBreakStrategy: Int = Layout.BREAK_STRATEGY_HIGH_QUALITY
protected var hyphenationFrequency: Int = Layout.HYPHENATION_FREQUENCY_NONE
protected var justificationMode: Int =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
0
} else {
Layout.JUSTIFICATION_MODE_NONE
}
// Return text alignment according to LTR or RTL style
protected var textAlign: Int = Gravity.NO_GRAVITY
get() {
return if (layoutDirection == YogaDirection.RTL) {
when (field) {
Gravity.RIGHT -> Gravity.LEFT
Gravity.LEFT -> Gravity.RIGHT
else -> field
}
} else {
field
}
}
private set
/**
* [fontStyle] can be [Typeface.NORMAL] or [Typeface.ITALIC]. [fontWeight] can be
* [Typeface.NORMAL] or [Typeface.BOLD].
*/
protected var fontStyle: Int = ReactConstants.UNSET
protected var fontWeight: Int = ReactConstants.UNSET
/**
* NB: If a font family is used that does not have a style in a certain Android version (ie.
* monospace bold pre Android 5.0), that style (ie. bold) will not be inherited by nested Text
* nodes. To retain that style, you have to add it to those nodes explicitly.
*
* Example, Android 4.4:
* <pre>
* <Text style={{fontFamily="serif" fontWeight="bold" }}>Bold Text</Text>
* <Text style={{fontFamily="sans-serif"}}>Bold Text</Text>
* <Text style={{fontFamily="serif"}}>Bold Text</Text>
*
* <Text style={{fontFamily="monospace" fontWeight="bold" }}>Not Bold Text</Text>
* <Text style={{fontFamily="sans-serif"}}>Not Bold Text</Text>
* <Text style={{fontFamily="serif"}}>Not Bold Text</Text>
*
* <Text style={{fontFamily="monospace" fontWeight="bold" }}>Not Bold Text</Text>
* <Text style={{fontFamily="sans-serif" fontWeight="bold" }}>Bold Text</Text>
* <Text style={{fontFamily="serif"}}>Bold Text</Text>
* </pre>
*/
protected var fontFamily: String? = null
private set
/** @see [android.graphics.Paint.setFontFeatureSettings] */
protected var fontFeatureSettings: String? = null
protected var includeFontPadding: Boolean = true
private set
protected var adjustsFontSizeToFit: Boolean = false
protected var minimumFontScale: Float = 0f
private set
protected var textShadowOffsetDx: Float = 0f
protected var textShadowOffsetDy: Float = 0f
protected var textShadowRadius: Float = 0f
private set
protected var textShadowColor: Int = DEFAULT_TEXT_SHADOW_COLOR
private set
protected var isUnderlineTextDecorationSet: Boolean = false
protected var isLineThroughTextDecorationSet: Boolean = false
protected var containsImages: Boolean = false
// Only nullable if `supportsInlineViews` is `false`.
protected var inlineViews: Map<Int, ReactShadowNode<*>>? = null
// `nativeViewHierarchyOptimizer` can be `null` as long as `supportsInlineViews` is `false`.
@Suppress("DEPRECATION")
protected fun spannedFromShadowNode(
textShadowNode: ReactBaseTextShadowNode,
text: String?,
supportsInlineViews: Boolean,
nativeViewHierarchyOptimizer: com.facebook.react.uimanager.NativeViewHierarchyOptimizer?
): Spannable {
check(!supportsInlineViews || nativeViewHierarchyOptimizer != null) {
"nativeViewHierarchyOptimizer is required when inline views are supported"
}
val sb = SpannableStringBuilder()
// TODO(5837930): Investigate whether it's worth optimizing this part and do it if so
// The [SpannableStringBuilder] implementation require setSpan operation to be called
// up-to-bottom, otherwise all the spannables that are within the region for which one may set
// a new spannable will be wiped out
val ops: MutableList<SetSpanOperation> = ArrayList()
val inlineViews: MutableMap<Int, ReactShadowNode<*>>? =
if (supportsInlineViews) HashMap() else null
if (text != null) {
// Handle text that is provided via a prop (e.g. the `value` and `defaultValue` props on
// TextInput).
sb.append(apply(text, textShadowNode.textAttributes.textTransform))
}
buildSpannedFromShadowNode(textShadowNode, sb, ops, null, supportsInlineViews, inlineViews, 0)
textShadowNode.containsImages = false
textShadowNode.inlineViews = inlineViews
var heightOfTallestInlineViewOrImage = Float.NaN
// While setting the Spans on the final text, we also check whether any of them are inline views
// or images.
for (priorityIndex in ops.indices) {
val op = ops[ops.size - priorityIndex - 1]
val what = op.what
val isInlineImage = what is TextInlineImageSpan
if (isInlineImage || what is TextInlineViewPlaceholderSpan) {
val height: Int
if (isInlineImage) {
height = what.height
textShadowNode.containsImages = true
} else {
val placeholder = what as TextInlineViewPlaceholderSpan
height = placeholder.height
// Inline views cannot be layout-only because ReactTextView needs to access
// them on the UI thread to measure and position them.
val childNode = checkNotNull(inlineViews)[placeholder.reactTag]
checkNotNull(childNode)
checkNotNull(nativeViewHierarchyOptimizer)
nativeViewHierarchyOptimizer.handleForceViewToBeNonLayoutOnly(childNode)
// The ReactTextView is responsible for laying out the inline views.
@Suppress("UNCHECKED_CAST")
(childNode as ReactShadowNode<ReactShadowNodeImpl>).setLayoutParent(textShadowNode)
}
if (heightOfTallestInlineViewOrImage.isNaN() || height > heightOfTallestInlineViewOrImage) {
heightOfTallestInlineViewOrImage = height.toFloat()
}
}
// Actual order of calling `execute` does NOT matter,
// but the `priorityIndex` DOES matter.
op.execute(sb, priorityIndex)
}
textShadowNode.textAttributes.heightOfTallestInlineViewOrImage =
heightOfTallestInlineViewOrImage
reactTextViewManagerCallback?.onPostProcessSpannable(sb)
return sb
}
@ReactProp(name = ViewProps.NUMBER_OF_LINES, defaultInt = ReactConstants.UNSET)
public fun setNumberOfLines(numberOfLines: Int) {
this.numberOfLines = if (numberOfLines == 0) ReactConstants.UNSET else numberOfLines
markUpdated()
}
@ReactProp(name = ViewProps.LINE_HEIGHT, defaultFloat = Float.NaN)
public fun setLineHeight(lineHeight: Float) {
textAttributes.lineHeight = lineHeight
markUpdated()
}
@ReactProp(name = ViewProps.LETTER_SPACING, defaultFloat = 0f)
public fun setLetterSpacing(letterSpacing: Float) {
textAttributes.letterSpacing = letterSpacing
markUpdated()
}
@ReactProp(name = ViewProps.ALLOW_FONT_SCALING, defaultBoolean = true)
public fun setAllowFontScaling(allowFontScaling: Boolean) {
if (allowFontScaling != textAttributes.allowFontScaling) {
textAttributes.allowFontScaling = allowFontScaling
markUpdated()
}
}
@ReactProp(name = ViewProps.MAX_FONT_SIZE_MULTIPLIER, defaultFloat = Float.NaN)
public fun setMaxFontSizeMultiplier(maxFontSizeMultiplier: Float) {
if (maxFontSizeMultiplier != textAttributes.maxFontSizeMultiplier) {
textAttributes.maxFontSizeMultiplier = maxFontSizeMultiplier
markUpdated()
}
}
@ReactProp(name = ViewProps.TEXT_ALIGN)
public fun setTextAlign(textAlign: String?) {
if ("justify" == textAlign) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
justificationMode = Layout.JUSTIFICATION_MODE_INTER_WORD
}
this.textAlign = Gravity.LEFT
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
justificationMode = Layout.JUSTIFICATION_MODE_NONE
}
this.textAlign =
when (textAlign) {
null,
"auto" -> Gravity.NO_GRAVITY
"left" -> Gravity.LEFT
"right" -> Gravity.RIGHT
"center" -> Gravity.CENTER_HORIZONTAL
else -> {
FLog.w(ReactConstants.TAG, "Invalid textAlign: $textAlign")
Gravity.NO_GRAVITY
}
}
}
markUpdated()
}
@ReactProp(name = ViewProps.FONT_SIZE, defaultFloat = Float.NaN)
public fun setFontSize(fontSize: Float) {
textAttributes.fontSize = fontSize
markUpdated()
}
@ReactProp(name = ViewProps.COLOR, customType = "Color")
public fun setColor(color: Int?) {
color?.let { newColor ->
isColorSet = true
this.color = newColor
}
markUpdated()
}
@ReactProp(name = ViewProps.BACKGROUND_COLOR, customType = "Color")
public fun setBackgroundColor(color: Int?) {
// Background color needs to be handled here for virtual nodes so it can be incorporated into
// the span. However, it doesn't need to be applied to non-virtual nodes because non-virtual
// nodes get mapped to native views and native views get their background colors get set via
// [BaseViewManager].
if (isVirtual) {
color?.let { newColor ->
isBackgroundColorSet = true
backgroundColor = newColor
}
markUpdated()
}
}
@ReactProp(name = ViewProps.ACCESSIBILITY_ROLE)
public fun setAccessibilityRole(accessibilityRole: String?) {
if (isVirtual) {
this.accessibilityRole = AccessibilityRole.fromValue(accessibilityRole)
markUpdated()
}
}
@ReactProp(name = ViewProps.ROLE)
public fun setRole(role: String?) {
if (isVirtual) {
this.role = ReactAccessibilityDelegate.Role.fromValue(role)
markUpdated()
}
}
@ReactProp(name = ViewProps.FONT_FAMILY)
public fun setFontFamily(fontFamily: String?) {
this.fontFamily = fontFamily
markUpdated()
}
@ReactProp(name = ViewProps.FONT_WEIGHT)
public fun setFontWeight(fontWeightString: String?) {
val parsedFontWeight = parseFontWeight(fontWeightString)
if (parsedFontWeight != fontWeight) {
fontWeight = parsedFontWeight
markUpdated()
}
}
@ReactProp(name = ViewProps.FONT_VARIANT)
public fun setFontVariant(fontVariantArray: ReadableArray?) {
val fontFeatureSettings = parseFontVariant(fontVariantArray)
if (fontFeatureSettings != this.fontFeatureSettings) {
this.fontFeatureSettings = fontFeatureSettings
markUpdated()
}
}
@ReactProp(name = ViewProps.FONT_STYLE)
public fun setFontStyle(fontStyleString: String?) {
val parsedFontStyle = parseFontStyle(fontStyleString)
if (parsedFontStyle != fontStyle) {
fontStyle = parsedFontStyle
markUpdated()
}
}
@ReactProp(name = ViewProps.INCLUDE_FONT_PADDING, defaultBoolean = true)
public fun setIncludeFontPadding(includepad: Boolean) {
includeFontPadding = includepad
}
@ReactProp(name = ViewProps.TEXT_DECORATION_LINE)
public fun setTextDecorationLine(textDecorationLineString: String?) {
isUnderlineTextDecorationSet = false
isLineThroughTextDecorationSet = false
if (textDecorationLineString != null) {
for (textDecorationLineSubString in
textDecorationLineString.split(" ").dropLastWhile { it.isEmpty() }.toTypedArray()) {
if ("underline" == textDecorationLineSubString) {
isUnderlineTextDecorationSet = true
} else if ("line-through" == textDecorationLineSubString) {
isLineThroughTextDecorationSet = true
}
}
}
markUpdated()
}
@ReactProp(name = ViewProps.TEXT_BREAK_STRATEGY)
public open fun setTextBreakStrategy(textBreakStrategy: String?) {
this.textBreakStrategy =
when (textBreakStrategy) {
null,
"highQuality" -> Layout.BREAK_STRATEGY_HIGH_QUALITY
"simple" -> Layout.BREAK_STRATEGY_SIMPLE
"balanced" -> Layout.BREAK_STRATEGY_BALANCED
else -> {
FLog.w(ReactConstants.TAG, "Invalid textBreakStrategy: $textBreakStrategy")
Layout.BREAK_STRATEGY_HIGH_QUALITY
}
}
markUpdated()
}
@ReactProp(name = PROP_SHADOW_OFFSET)
public fun setTextShadowOffset(offsetMap: ReadableMap?) {
textShadowOffsetDx = 0f
textShadowOffsetDy = 0f
offsetMap?.let { map ->
if (map.hasKey(PROP_SHADOW_OFFSET_WIDTH) && !map.isNull(PROP_SHADOW_OFFSET_WIDTH)) {
textShadowOffsetDx = toPixelFromDIP(map.getDouble(PROP_SHADOW_OFFSET_WIDTH))
}
if (map.hasKey(PROP_SHADOW_OFFSET_HEIGHT) && !map.isNull(PROP_SHADOW_OFFSET_HEIGHT)) {
textShadowOffsetDy = toPixelFromDIP(map.getDouble(PROP_SHADOW_OFFSET_HEIGHT))
}
}
markUpdated()
}
@ReactProp(name = PROP_SHADOW_RADIUS, defaultInt = 1)
public fun setTextShadowRadius(textShadowRadius: Float) {
if (textShadowRadius != this.textShadowRadius) {
this.textShadowRadius = textShadowRadius
markUpdated()
}
}
@ReactProp(name = PROP_SHADOW_COLOR, defaultInt = DEFAULT_TEXT_SHADOW_COLOR, customType = "Color")
public fun setTextShadowColor(textShadowColor: Int) {
if (textShadowColor != this.textShadowColor) {
this.textShadowColor = textShadowColor
markUpdated()
}
}
@ReactProp(name = PROP_TEXT_TRANSFORM)
public fun setTextTransform(textTransform: String?) {
val textTransformEnum =
when (textTransform) {
null -> TextTransform.UNSET
"none" -> TextTransform.NONE
"uppercase" -> TextTransform.UPPERCASE
"lowercase" -> TextTransform.LOWERCASE
"capitalize" -> TextTransform.CAPITALIZE
else -> {
FLog.w(ReactConstants.TAG, "Invalid textTransform: $textTransform")
TextTransform.UNSET
}
}
textAttributes.textTransform = textTransformEnum
markUpdated()
}
@ReactProp(name = ViewProps.ADJUSTS_FONT_SIZE_TO_FIT)
public fun setAdjustFontSizeToFit(adjustsFontSizeToFit: Boolean) {
if (adjustsFontSizeToFit != this.adjustsFontSizeToFit) {
this.adjustsFontSizeToFit = adjustsFontSizeToFit
markUpdated()
}
}
@ReactProp(name = ViewProps.MINIMUM_FONT_SCALE)
public fun setMinimumFontScale(minimumFontScale: Float) {
if (minimumFontScale != this.minimumFontScale) {
this.minimumFontScale = minimumFontScale
markUpdated()
}
}
public companion object {
// Use a direction weak character so the placeholder doesn't change the direction of the
// previous character. https://en.wikipedia.org/wiki/Bi-directional_text#weak_characters
private const val INLINE_VIEW_PLACEHOLDER = "0"
public const val PROP_SHADOW_OFFSET: String = "textShadowOffset"
public const val PROP_SHADOW_OFFSET_WIDTH: String = "width"
public const val PROP_SHADOW_OFFSET_HEIGHT: String = "height"
public const val PROP_SHADOW_RADIUS: String = "textShadowRadius"
public const val PROP_SHADOW_COLOR: String = "textShadowColor"
public const val PROP_TEXT_TRANSFORM: String = "textTransform"
public const val DEFAULT_TEXT_SHADOW_COLOR: Int = 0x55000000
private fun buildSpannedFromShadowNode(
textShadowNode: ReactBaseTextShadowNode,
sb: SpannableStringBuilder,
ops: MutableList<SetSpanOperation>,
parentTextAttributes: TextAttributes?,
supportsInlineViews: Boolean,
inlineViews: MutableMap<Int, ReactShadowNode<*>>?,
start: Int
) {
val textAttributes =
parentTextAttributes?.applyChild(textShadowNode.textAttributes)
?: textShadowNode.textAttributes
var i = 0
val length = textShadowNode.childCount
while (i < length) {
val child: ReactShadowNode<*> = textShadowNode.getChildAt(i)
if (child is ReactRawTextShadowNode) {
child.text?.let { sb.append(apply(it, textAttributes.textTransform)) }
} else if (child is ReactBaseTextShadowNode) {
buildSpannedFromShadowNode(
child, sb, ops, textAttributes, supportsInlineViews, inlineViews, sb.length)
} else if (child is ReactTextInlineImageShadowNode) {
// We make the image take up 1 character in the span and put a corresponding character
// into the text so that the image doesn't run over any following text.
sb.append(INLINE_VIEW_PLACEHOLDER)
ops.add(
SetSpanOperation(
sb.length - INLINE_VIEW_PLACEHOLDER.length,
sb.length,
child.buildInlineImageSpan()))
} else if (supportsInlineViews) {
val reactTag = child.reactTag
val widthValue = child.styleWidth
val heightValue = child.styleHeight
val width: Float
val height: Float
if (widthValue.unit != YogaUnit.POINT || heightValue.unit != YogaUnit.POINT) {
// If the measurement of the child isn't calculated, we calculate the layout for the
// view using Yoga
child.calculateLayout()
width = child.layoutWidth
height = child.layoutHeight
} else {
width = widthValue.value
height = heightValue.value
}
// We make the inline view take up 1 character in the span and put a corresponding
// character
// into
// the text so that the inline view doesn't run over any following text.
sb.append(INLINE_VIEW_PLACEHOLDER)
ops.add(
SetSpanOperation(
sb.length - INLINE_VIEW_PLACEHOLDER.length,
sb.length,
TextInlineViewPlaceholderSpan(reactTag, width.toInt(), height.toInt())))
// supportsInlineViews is true, so we can assume that inlineViews is not null
checkNotNull(inlineViews)[reactTag] = child
} else {
throw IllegalViewOperationException(
"Unexpected view type nested under a <Text> or <TextInput> node: ${child.javaClass}")
}
child.markUpdateSeen()
i++
}
val end = sb.length
if (end >= start) {
if (textShadowNode.isColorSet) {
ops.add(SetSpanOperation(start, end, ReactForegroundColorSpan(textShadowNode.color)))
}
if (textShadowNode.isBackgroundColorSet) {
ops.add(
SetSpanOperation(
start, end, ReactBackgroundColorSpan(textShadowNode.backgroundColor)))
}
val roleIsLink =
if (textShadowNode.role != null)
textShadowNode.role == ReactAccessibilityDelegate.Role.LINK
else textShadowNode.accessibilityRole == AccessibilityRole.LINK
if (roleIsLink) {
ops.add(SetSpanOperation(start, end, ReactClickableSpan(textShadowNode.reactTag)))
}
val effectiveLetterSpacing = textAttributes.effectiveLetterSpacing
if (!java.lang.Float.isNaN(effectiveLetterSpacing) &&
(parentTextAttributes == null ||
parentTextAttributes.effectiveLetterSpacing != effectiveLetterSpacing)) {
ops.add(SetSpanOperation(start, end, CustomLetterSpacingSpan(effectiveLetterSpacing)))
}
val effectiveFontSize = textAttributes.effectiveFontSize
if ( // `getEffectiveFontSize` always returns a value so don't need to check for anything
// like `Float.NaN`.
parentTextAttributes == null ||
parentTextAttributes.effectiveFontSize != effectiveFontSize) {
ops.add(SetSpanOperation(start, end, ReactAbsoluteSizeSpan(effectiveFontSize)))
}
if (textShadowNode.fontStyle != ReactConstants.UNSET ||
textShadowNode.fontWeight != ReactConstants.UNSET ||
textShadowNode.fontFamily != null) {
ops.add(
SetSpanOperation(
start,
end,
CustomStyleSpan(
textShadowNode.fontStyle,
textShadowNode.fontWeight,
textShadowNode.fontFeatureSettings,
textShadowNode.fontFamily,
textShadowNode.themedContext.assets)))
}
if (textShadowNode.isUnderlineTextDecorationSet) {
ops.add(SetSpanOperation(start, end, ReactUnderlineSpan()))
}
if (textShadowNode.isLineThroughTextDecorationSet) {
ops.add(SetSpanOperation(start, end, ReactStrikethroughSpan()))
}
if ((textShadowNode.textShadowOffsetDx != 0f ||
textShadowNode.textShadowOffsetDy != 0f ||
textShadowNode.textShadowRadius != 0f) &&
Color.alpha(textShadowNode.textShadowColor) != 0) {
ops.add(
SetSpanOperation(
start,
end,
ShadowStyleSpan(
textShadowNode.textShadowOffsetDx,
textShadowNode.textShadowOffsetDy,
textShadowNode.textShadowRadius,
textShadowNode.textShadowColor)))
}
val effectiveLineHeight = textAttributes.effectiveLineHeight
if (!java.lang.Float.isNaN(effectiveLineHeight) &&
(parentTextAttributes == null ||
parentTextAttributes.effectiveLineHeight != effectiveLineHeight)) {
ops.add(SetSpanOperation(start, end, CustomLineHeightSpan(effectiveLineHeight)))
}
ops.add(SetSpanOperation(start, end, ReactTagSpan(textShadowNode.reactTag)))
}
}
}
}
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.views.text
import android.view.View
@@ -20,6 +22,9 @@ import com.facebook.react.uimanager.ViewManager
*/
@ReactModule(name = ReactRawTextManager.REACT_CLASS)
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class ReactRawTextManager : ViewManager<View, ReactRawTextShadowNode>() {
override fun getName(): String {
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.views.text
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -17,6 +19,9 @@ import com.facebook.react.uimanager.annotations.ReactProp
* terms of DOM). Raw text node can only have simple string value without any attributes, properties
* or state.
*/
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
internal class ReactRawTextShadowNode : ReactShadowNodeImpl() {
@set:ReactProp(name = "text")
@@ -37,8 +37,8 @@ import com.facebook.react.views.text.DefaultStyleValuesUtil.getDefaultTextColorH
* whole text subtree.
*/
@UnstableReactNativeAPI
public abstract class ReactTextAnchorViewManager<C : ReactBaseTextShadowNode?> :
BaseViewManager<ReactTextView, C>() {
public abstract class ReactTextAnchorViewManager<
@Suppress("DEPRECATION") C : ReactBaseTextShadowNode?> : BaseViewManager<ReactTextView, C>() {
@ReactProp(name = "accessible")
internal fun setAccessible(view: ReactTextView, accessible: Boolean) {
@@ -51,6 +51,9 @@ import kotlin.math.min
* constructed in superclass.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public class ReactTextShadowNode
@JvmOverloads
public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? = null) :
@@ -66,15 +69,15 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
}
var layout = measureSpannedText(text, width, widthMode)
if (mAdjustsFontSizeToFit) {
val initialFontSize = mTextAttributes.effectiveFontSize
var currentFontSize = mTextAttributes.effectiveFontSize
if (adjustsFontSizeToFit) {
val initialFontSize = textAttributes.effectiveFontSize
var currentFontSize = textAttributes.effectiveFontSize
// Minimum font size is 4pts to match the iOS implementation.
val minimumFontSize =
max((mMinimumFontScale * initialFontSize), PixelUtil.toPixelFromDIP(4f)).toInt()
max((minimumFontScale * initialFontSize), PixelUtil.toPixelFromDIP(4f)).toInt()
while (currentFontSize > minimumFontSize &&
(mNumberOfLines != ReactConstants.UNSET && layout.lineCount > mNumberOfLines ||
heightMode != YogaMeasureMode.UNDEFINED && layout.height > height)) {
((numberOfLines != ReactConstants.UNSET && layout.lineCount > numberOfLines) ||
(heightMode != YogaMeasureMode.UNDEFINED && layout.height > height))) {
// TODO: We could probably use a smarter algorithm here. This will require 0(n)
// measurements
// based on the number of points the font size needs to be reduced by.
@@ -111,8 +114,11 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
}
val lineCount =
if (mNumberOfLines == ReactConstants.UNSET) layout.lineCount
else min(mNumberOfLines.toDouble(), layout.lineCount.toDouble()).toInt()
if (numberOfLines == ReactConstants.UNSET) {
layout.lineCount
} else {
min(numberOfLines.toDouble(), layout.lineCount.toDouble()).toInt()
}
// Instead of using `layout.getWidth()` (which may yield a significantly larger width
// for
@@ -175,7 +181,7 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
// TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic)
var width = width
val textPaint = textPaintInstance
textPaint.textSize = mTextAttributes.effectiveFontSize.toFloat()
textPaint.textSize = textAttributes.effectiveFontSize.toFloat()
val layout: Layout
val boring = BoringLayout.isBoring(text, textPaint)
val desiredWidth = if (boring == null) Layout.getDesiredWidth(text, textPaint) else Float.NaN
@@ -184,7 +190,7 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
val unconstrainedWidth = widthMode == YogaMeasureMode.UNDEFINED || width < 0
val alignment =
when (textAlign) {
when (_textAlign) {
Gravity.LEFT -> Layout.Alignment.ALIGN_NORMAL
Gravity.RIGHT -> Layout.Alignment.ALIGN_OPPOSITE
Gravity.CENTER_HORIZONTAL -> Layout.Alignment.ALIGN_CENTER
@@ -201,12 +207,12 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
StaticLayout.Builder.obtain(text, 0, text.length, textPaint, hintWidth)
.setAlignment(alignment)
.setLineSpacing(0f, 1f)
.setIncludePad(mIncludeFontPadding)
.setBreakStrategy(mTextBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency)
.setIncludePad(includeFontPadding)
.setBreakStrategy(textBreakStrategy)
.setHyphenationFrequency(hyphenationFrequency)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setJustificationMode(mJustificationMode)
builder.setJustificationMode(justificationMode)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
builder.setUseLineSpacingFromFallbacks(true)
@@ -224,7 +230,7 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
1f,
0f,
boring,
mIncludeFontPadding)
includeFontPadding)
} else {
// Is used for multiline, boring text and the width is known.
// Android 11+ introduces changes in text width calculation which leads to cases
@@ -238,12 +244,12 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
StaticLayout.Builder.obtain(text, 0, text.length, textPaint, width.toInt())
.setAlignment(alignment)
.setLineSpacing(0f, 1f)
.setIncludePad(mIncludeFontPadding)
.setBreakStrategy(mTextBreakStrategy)
.setHyphenationFrequency(mHyphenationFrequency)
.setIncludePad(includeFontPadding)
.setBreakStrategy(textBreakStrategy)
.setHyphenationFrequency(hyphenationFrequency)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setJustificationMode(mJustificationMode)
builder.setJustificationMode(justificationMode)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@@ -255,9 +261,9 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
}
// Return text alignment according to LTR or RTL style
private val textAlign: Int
private val _textAlign: Int
get() {
var textAlign = mTextAlign
var textAlign = super.textAlign
if (layoutDirection == YogaDirection.RTL) {
if (textAlign == Gravity.RIGHT) {
textAlign = Gravity.LEFT
@@ -300,14 +306,14 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
ReactTextUpdate(
text,
ReactConstants.UNSET,
mContainsImages,
containsImages,
getPadding(Spacing.START),
getPadding(Spacing.TOP),
getPadding(Spacing.END),
getPadding(Spacing.BOTTOM),
textAlign,
mTextBreakStrategy,
mJustificationMode)
_textAlign,
textBreakStrategy,
justificationMode)
uiViewOperationQueue.enqueueUpdateExtraData(reactTag, reactTextUpdate)
}
@@ -319,7 +325,9 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
override fun calculateLayoutOnChildren(): Iterable<ReactShadowNode<*>?>? {
// Run flexbox on and return the descendants which are inline views.
if (mInlineViews.isNullOrEmpty()) return null
if (inlineViews.isNullOrEmpty()) {
return null
}
val text: Spanned =
checkNotNull(preparedSpannableText) {
@@ -329,7 +337,7 @@ public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? =
val shadowNodes = mutableListOf<ReactShadowNode<*>?>()
for (placeholder in placeholders) {
val child = mInlineViews?.get(placeholder.reactTag)
val child = inlineViews?.get(placeholder.reactTag)
checkNotNull(child) { "Child is null" }
child.calculateLayout()
shadowNodes.add(child)
@@ -27,6 +27,7 @@ import java.util.HashMap
* Concrete class for [ReactTextAnchorViewManager] which represents view managers of anchor `<Text>`
* nodes.
*/
@Suppress("DEPRECATION")
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
@OptIn(UnstableReactNativeAPI::class)
public class ReactTextViewManager
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.views.text
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -13,6 +15,9 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
/** A virtual text node. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class ReactVirtualTextShadowNode : ReactBaseTextShadowNode() {
override fun isVirtual(): Boolean = true

Some files were not shown because too many files have changed in this diff Show More