Summary:
This diff refactors the view update process into two stages:
1. The `reactSubviews` array is set, whose order matches the order of the JS components and shadowView components, as specified by the UIManager.
2. The `didUpdateReactSubviews` method is called, which actually inserts the reactSubviews into the view hierarchy.
This simplifies a lot of the hacks we had for special-case treatment of subviews: In many cases we don't want to actually insert `reactSubviews` into the parentView, and we had a bunch of component-specific solutions for that (typically overriding all of the reactSubviews methods to store views in an array). Now, we can simply override the `didUpdateReactSubviews` method for those views to do nothing, or do something different.
Reviewed By: wwjholmes
Differential Revision: D3396594
fbshipit-source-id: 92fc56fd31db0cfc66aac3d1634a4d4ae3903085
Summary:
RCTShadowText currently explicitly defaults to black text color:
https://github.com/facebook/react-native/blob/d46ac11/Libraries/Text/RCTShadowText.m#L204
However, the UITextView used by RCTTextInput doesn't explicitly default to black text color.
This causes issues when RCTTextInput is in rich text editing mode (i.e. when the <TextInput> element uses child <Text> nodes to provide extra styling info) and the client doesn't provide us with any explicit color info. In this case, the following series of badness occurs:
1. -[UITextView attributedText] will return an attributed string without the NSColor property set.
2. -[RCTShadowText attributedString] will return an attributed string with NSColor equal to blackColor.
3. The `[_textView.attributedText isEqualToAttributedString:_pendingAttributedText]` check in -performPendingTextUpdate will fail and causes -[UITextView setText:] to be called.
4. -setText: clears the marked text range in the text view, which breaks multi-character autocomplete (e.g. QWERTY input methods for CJK languages).
The easiest fix for now is to just make sure RCTUITextView and RCTShadowText default to the same text color.
Reviewed By: nicklockwood
Differential Revision: D3368726
fbshipit-source-id: a92cb188c60bac80d963af6b1f2a09f27ae084f5
Summary:
The TextInput when configured with `multiline=true` has a minor issue due to which if the initial text doesn't fit in one line, the input won't span multiple lines. The root cause of the problem is that the `onChange` event is not fired for the initial render. This issue has been reported on open-source: 481f560f64
This is an attempt to fix this problem by moving the logic to fire the event to the method that updates the content size. This way we can guarantee that anytime the content size changes we'll trigger the JS event.
The downside of this approach is that it's possible that multiple events get fired for a single character change. As per the comment that was removed, this was already happening when adding a character that when rendered, would increase the content size. By moving the code to the new place, this can happen more often (twice per character tapped). Let me know if you think this is an issue.
I don't know this code much, so please be careful reviewing. I'm happy to add more test cases I may have missed to the test plan :).
Reviewed By: nicklockwood
Differential Revision: D3348218
fbshipit-source-id: 6b457624c9126e771c326eac61cd1cdd6496671d
Summary:
The TextInput when configured with `multiline=true` has a minor issue due to which if the initial text doesn't fit in one line, the input won't span multiple lines. The root cause of the problem is that the `onChange` event is not fired for the initial render. This issue has been reported on open-source: 481f560f64
This is an attempt to fix this problem by moving the logic to fire the event to the method that updates the content size. This way we can guarantee that anytime the content size changes we'll trigger the JS event.
The downside of this approach is that it's possible that multiple events get fired for a single character change. As per the comment that was removed, this was already happening when adding a character that when rendered, would increase the content size. By moving the code to the new place, this can happen more often (twice per character tapped). Let me know if you think this is an issue.
I don't know this code much, so please be careful reviewing. I'm happy to add more test cases I may have missed to the test plan :).
Reviewed By: nicklockwood
Differential Revision: D3348218
fbshipit-source-id: d3da3c0da1a0da9b9960625441191497e91d322e
Summary:
Previously, only Text and Image could be nested within Text. Now, any
view can be nested within Text. One restriction of this feature is
that developers must give inline views a width and a height via
the style prop.
Previously, inline Images were supported by using iOS's built-in support
for rendering images with an NSAttributedString via NSTextAttachment.
However, NSAttributedString doesn't support rendering arbitrary views.
This change adds support for nesting views within Text by creating one
NSTextAttachment per inline view. The NSTextAttachments act as placeholders.
They are set to be the size of the corresponding view. After the text is
laid out, we query the text system to find out where it has positioned each
NSTextAttachment. We then position the views to be at those locations.
This commit also contains a change in `RCTShadowText.m`
`_setParagraphStyleOnAttributedString:heightOfTallestSubview:`. It now only sets
`lineHeight`, `textAlign`, and `writingDirection` when they've actua
Closes https://github.com/facebook/react-native/pull/7304
Reviewed By: javache
Differential Revision: D3365373
Pulled By: nicklockwood
fbshipit-source-id: 66d149eb80c5c6725311e1e46d7323eec086ce64
Summary: AppState now subclasses NativeEventEmitter instead of using global RCTDeviceEventEmitter.
Reviewed By: javache
Differential Revision: D3310488
fbshipit-source-id: f0116599223f4411307385c0dab683659d8d63b6
Summary:
Previously, only Text and Image could be nested within Text. Now, any
view can be nested within Text. One restriction of this feature is
that developers must give inline views a width and a height via
the style prop.
Previously, inline Images were supported by using iOS's built-in support
for rendering images with an NSAttributedString via NSTextAttachment.
However, NSAttributedString doesn't support rendering arbitrary views.
This change adds support for nesting views within Text by creating one
NSTextAttachment per inline view. The NSTextAttachments act as placeholders.
They are set to be the size of the corresponding view. After the text is
laid out, we query the text system to find out where it has positioned each
NSTextAttachment. We then position the views to be at those locations.
This commit also contains a change in `RCTShadowText.m`
`_setParagraphStyleOnAttributedString:heightOfTallestSubview:`. It now only sets
`lineHeight`, `textAlign`, and `writingDirection` when they've actua
Closes https://github.com/facebook/react-native/pull/7304
Differential Revision: D3269333
Pulled By: nicklockwood
fbshipit-source-id: 2b59f1c5445a4012f9c29df9f10f5010060ea517
Summary: To prevent layout popping, when inserting images inside text we would render a blank placeholder image while the real image was loading. It turns out that this isn't necessary, as we can just specify the size of the image without having an actual image to display.
Reviewed By: javache
Differential Revision: D3212766
fb-gh-sync-id: e98851b32a2d0ae809fc0a4be47e6b77f3b17996
fbshipit-source-id: e98851b32a2d0ae809fc0a4be47e6b77f3b17996
Summary:Fixes #5408 as per ide and vjeux suggestions here https://github.com/facebook/react-native/issues/529#issuecomment-107328799
Could've been probably done in a single `if` clause, but this is more explicit and leaves potential place for future implementation (if we ever decide to do so)
Closes https://github.com/facebook/react-native/pull/7197
Differential Revision: D3217740
Pulled By: vjeux
fb-gh-sync-id: aa08a5c42e43c1abe17b72a424ee96146f2667f6
fbshipit-source-id: aa08a5c42e43c1abe17b72a424ee96146f2667f6
Summary:Fixes #5855
Tested with `UIExplorer`, first <Text> is the `onPress`, second is the `onLongPress`.
Closes https://github.com/facebook/react-native/pull/7099
Differential Revision: D3212436
Pulled By: mkonicek
fb-gh-sync-id: 0a1cbcd4eaf39ad4fe67d861c3be2e042e1acb27
fbshipit-source-id: 0a1cbcd4eaf39ad4fe67d861c3be2e042e1acb27
Summary: We only measure text at the root node, we shouldn't be trying to build a text storage later on for tree lower in the shadow node tree.
Reviewed By: nicklockwood
Differential Revision: D3212614
fb-gh-sync-id: 574fa7f2c029ca9ad2d5fabe7bbb148157f85ca7
fbshipit-source-id: 574fa7f2c029ca9ad2d5fabe7bbb148157f85ca7
Summary:This fixes autocomplete for CJK text input by making sure that the `<Text>` nodes that JS controls to produce attributed text matches the text view's attributed text as much as possible. This is done by giving the disconnected `<Text>` child the same style as the `<TextInput>` parent.
This works because `-[RKTextView performPendingTextUpdate]` avoids setting the attributedText property on textView if the JS attributedText and textView attributedText are equal. This is important because setting attributedText on a text view clears the autocomplete state (markedText property) on a text view, breaking autocomplete for multistage input styles like CJK with a phonetic keyboard.
Reviewed By: nicklockwood
Differential Revision: D3207513
fb-gh-sync-id: 02e582ea5f15191974f15a65ebc1820401715f8d
fbshipit-source-id: 02e582ea5f15191974f15a65ebc1820401715f8d
Summary:The default value for fontSizeMultiplier was zero. Although this was usually overriden with the correct value (typically 1.0), it sometimes wasn't resulting in a divide-by-zero in the text height calculation.
This diff corrects that bug by setting 1.0 as the default, and guarding against zero values being set.
I also fixed some suspicious logic that seemed to assume the result of BOOL && CGFloat would be 0 or the CGFloat value, which is true in JS but not in C (it would always be 0 or 1).
Reviewed By: javache
Differential Revision: D3179196
fb-gh-sync-id: cc09b104c9087fc1a2f45d8d3f70af221c2ad823
fbshipit-source-id: cc09b104c9087fc1a2f45d8d3f70af221c2ad823
Summary:Set `Touchable.TOUCH_TARGET_DEBUG` to see colored borders/text to all touchables.
Different touchable types are color-coded differently.
If there is `hitSlop`, it will be rendered with an extra view with a dashed border of the same color (not visible on
Android because `overflow: 'hidden'`).
`Text` with `onPress` directly set is just colored.
Added some extra checks to `TouchableWithoutFeedback` since it could silently break if the child is not a native
component.
Also added better error output for `ensureComponentIsNative` so it's easier to track down issues. I really wish there
was a cleaner way to get the component and owner names consistently, it would help make good debug messages way easier
to write.
Reviewed By: ericvicenti
Differential Revision: D3149865
fb-gh-sync-id: 602fc3474ae7636e32af529eb7ac52ac5b858030
fbshipit-source-id: 602fc3474ae7636e32af529eb7ac52ac5b858030
Summary:First I searched for special cases that destructor PropTypes:
```
(?s)React\s*=\s*require\('react\-native'\).*(Children|PropTypes)[^\{\}]*\}\s*=\s*React;
```
I split them up manually.
Then I replaced the React = require('react-native') + destructuring pattern...
```
(?s)(const|var)\s+React\s*=\s*require\('react\-native'\)(.*[^\{\}]*\}\s*=\s*)React;
```
...with...
```
$1 React = require('react');
$1 ReactNative = require('react-native')$2ReactNative;
```
I used lint to figure out if I left some unnecessary imports.
Finally I grepped for just
```
React\s*=\s*require\('react\-native'\)
```
to catch any remaining patterns.
Also, `} = React.NativeModules` -> `} = ReactNative.NativeModules`.
Reviewed By: spicyj
Differential Revision: D3158991
fb-gh-sync-id: f97e8e921e193d6ea1a49d8d1bf3f09be7bed5c3
fbshipit-source-id: f97e8e921e193d6ea1a49d8d1bf3f09be7bed5c3
Summary:Remove Trailing Spaces.
Why:
Sometimes there are conflicts with trailing spaces
Saves space
Those whose tools automatically delete them will have their pr watered down with trailing space removal
Closes https://github.com/facebook/react-native/pull/6787
Differential Revision: D3144704
fb-gh-sync-id: d8a62f115a3f8a8a49d5b07f56c540a02af38cf8
fbshipit-source-id: d8a62f115a3f8a8a49d5b07f56c540a02af38cf8
Summary:I've tested this manually, but I'm not sure how to write a test for this. Hopefully someone can help out there. The least I could do is provide a starting point for a PR to be accepted.
Additionally, I've renamed the existing `NSLineBreakMode` enum converter (inside `RCTConvert`) to use dashes in the names instead of camelcase (eg: `word-wrapping` instead of `wordWrapping`).
Fixes#6338
Closes https://github.com/facebook/react-native/pull/6339
Differential Revision: D3052391
Pulled By: nicklockwood
fb-gh-sync-id: 1536dfc139d7995095e9ee9d5f13ca86f90783c5
shipit-source-id: 1536dfc139d7995095e9ee9d5f13ca86f90783c5
Summary:**Motivation**
Multiple instances of `Text` inside a `ListView` is a bad idea for the performance of the app.
When you create 1000 elements and you scroll through the list it is really slow and laggy because the `NSTextStorage`, which is the backbone of the `RCTText` element, will set more than 1,000 times and also the method `setNeedsDisplay` is called multiple times. This will causes huge memory problems and the app crashes.
With this commit I check in `RCTText` if the `NSTextStorage` differs from the old value. If yes then set it otherwise don't set the `NSTextStorage`. This will prevent to call `setNeedsDisplay` when not really needed.
Gist with sample app to show behavior can be found here: https://gist.github.com/bpoetzschke/28a17969c6aa54219e18
Closes https://github.com/facebook/react-native/pull/6341
Differential Revision: D3035485
Pulled By: nicklockwood
fb-gh-sync-id: 181f01b7f87f765dbb01a4ad3196fc40f9d50694
shipit-source-id: 181f01b7f87f765dbb01a4ad3196fc40f9d50694
Summary:
public
This adds support to set the highlight color on TextInput on Android. See https://github.com/facebook/react-native/pull/5678 for the iOS implementation.
Note : We will merge these two properties with one name 'selectionColor' in a follow on diff, and may move it to a style.
Reviewed By: nicklockwood
Differential Revision: D2895253
fb-gh-sync-id: 6f2c08c812ff0028973185356a8af285f7dd7969
Summary:
public
This diff adds support for auto-resizing multiline text fields. This has been a long-requested feature, with several native solutions having been proposed (see https://github.com/facebook/react-native/pull/1229 and D2846915).
Rather than making this a feature of the native component, this diff simply exposes some extra information in the `onChange` event that makes it easy to implement this in pure JS code. I think this is preferable, since it's simpler, works cross-platform, and avoids any controversy about what the API should look like, or how the props should be named. It also makes it easier to implement custom min/max-height logic.
Reviewed By: sahrens
Differential Revision: D2849889
fb-gh-sync-id: d9ddf4ba4037d388dac0558aa467d958300aa691
Summary:
public
Previously, `<Image>` elements embedded inside `<Text>` ignored all style attributes and props apart from `source`. Now, the `width`, `height` and `resizeMode` styles are observed. I've also added a transparent placeholder to be displayed while the image is loading, to prevent the layout from changing after the image has loaded.
Reviewed By: javache
Differential Revision: D2838659
fb-gh-sync-id: c27f9685b6976705ac2b24075922b2bf247e06ba
Summary:
change `setTextAlign` and `setTextAlignVertical` to receive argument of type `String` (the same as in `StyleSheet`), so that native props and stylesheet props are calling the same ReactMethod
- add demo (may not be necessary)
Closes https://github.com/facebook/react-native/pull/4481
Reviewed By: svcscm
Differential Revision: D2823456
Pulled By: mkonicek
fb-gh-sync-id: 349d17549f419b5bdc001d70b583423ade06bfe8
Summary:
public
React Native currently exposes the iOS layer shadow properties more-or-less directly, however there are a number of problems with this:
1) Performance when using these properties is poor by default. That's because iOS calculates the shadow by getting the exact pixel mask of the view, including any tranlucent content, and all of its subviews, which is very CPU and GPU-intensive.
2) The iOS shadow properties do not match the syntax or semantics of the CSS box-shadow standard, and are unlikely to be possible to implement on Android.
3) We don't expose the `layer.shadowPath` property, which is crucial to getting good performance out of layer shadows.
This diff solves problem number 1) by implementing a default `shadowPath` that matches the view border for views with an opaque background. This improves the performance of shadows by optimizing for the common usage case. I've also reinstated background color propagation for views which have shadow props - this should help ensure that this best-case scenario occurs more often.
For views with an explicit transparent background, the shadow will continue to work as it did before ( `shadowPath` will be left unset, and the shadow will be derived exactly from the pixels of the view and its subviews). This is the worst-case path for performance, however, so you should avoid it unless absolutely necessary. **Support for this may be disabled by default in future, or dropped altogether.**
For translucent images, it is suggested that you bake the shadow into the image itself, or use another mechanism to pre-generate the shadow. For text shadows, you should use the textShadow properties, which work cross-platform and have much better performance.
Problem number 2) will be solved in a future diff, possibly by renaming the iOS shadowXXX properties to boxShadowXXX, and changing the syntax and semantics to match the CSS standards.
Problem number 3) is now mostly moot, since we generate the shadowPath automatically. In future, we may provide an iOS-specific prop to set the path explicitly if there's a demand for more precise control of the shadow.
Reviewed By: weicool
Differential Revision: D2827581
fb-gh-sync-id: 853aa018e1d61d5f88304c6fc1b78f9d7e739804
Summary:
public
This was caused by the change to background color propagation, but was actually due to having an unnecessary wrapper view around the headers, which was itself a workaround for a padding bug that was fixed some time ago :-)
Reviewed By: tadeuzagallo
Differential Revision: D2830890
fb-gh-sync-id: b64e701dedb90b357ed7c463b745de021f38637b
Summary:
public
Blending semitransparent pixels against their background is fairly a fairly expensive operation on mobile GPUs. To reduce blending, React Native has a system called "background color propagation", where the background color of parent views is automatically inherited by child views unless explicitly overridden. This means that translucent pixels can be blended directly against a known background color, avoiding the need to do this dynamically on the GPU.
In practice, this is only useful for views that do their own drawing, which is basically just `<Image/>` and `<Text/>` components, and for image components it only really matters when the image has an alpha component.
The automatic background propagation is a bit of a hack, and often does the wrong thing - for example if a view overflows its bounds, or if it overlaps a sibling, the background color will often be incorrect and need to be manually disabled. Because the only place that it provides a significant performance benefit is for text, this diff disables the behavior for everything except `<Text/>` nodes. It might still be useful for `<Image/>` nodes too, but looking through the examples in UIExplorer, the number of places where it does the wrong thing for images outnumbers the cases where it provides significant reduction in blending.
Note that this diff does not prevent you from eliminating blending on image components by manually setting an opaque background color, nor does it stop you from disabling color propagation on text components by manually setting a transparent background.
Reviewed By: javache
Differential Revision: D2811031
fb-gh-sync-id: 2eb08918c9031c582a3dd2d40e04b27a663dac82
Summary:
Problem: https://github.com/facebook/react-native/issues/4708
Solution: Added a ColorPropType that validates the color used by the dev
Notes:
1) I'm working a Win8.1 machine and couldn't build the react-native using the github repo. As soon as I figure that out, I'll probably figure how to run the tests and how to add some for this feature.
2) It's my first pull request. Be gentle :)
Closes https://github.com/facebook/react-native/pull/4866
Reviewed By: bestander, svcscm
Differential Revision: D2783672
Pulled By: nicklockwood
fb-gh-sync-id: ca22aa3c0999188075681b5d20fff0631496e238
Summary:
This is useful for applying input masks in the onChange handler that you then need to propagate down to the native component. In our case, we add commas as the user enters a price. Without this change, the cursor will end up in the wrong place when the text is transformed in our onChange handler.
Closes https://github.com/facebook/react-native/pull/4716
Reviewed By: svcscm
Differential Revision: D2766236
Pulled By: nicklockwood
fb-gh-sync-id: c4057d77d62507ec9e09eb0242888bf2858d822f
Summary:
public
Most apps create tons of text components but they are actually quite heavy because of the the Touchable mixin which requires binding tons of functions for every instance created.
This diff makes the binding lazy, so that the main handlers are only bound if there is a valid touch action configured (e.g. onPress), and the Touchable mixin functions are only bound the first time the node is actually touched and becomes the responder.
ScanLab testing shows 5-10% win on render time and memory for various products.
Reviewed By: sebmarkbage
Differential Revision: D2716823
fb-gh-sync-id: 30adb2ed2231c5635c9336369616cf31c776b930
Summary:
public
The scrolling fix I added to RCTTextView doesn't work on iOS 8 because the underlying UITextField doesn't resize correctly, which breaks text input functionality. This diff fixes it.
Reviewed By: tadeuzagallo
Differential Revision: D2712618
fb-gh-sync-id: 1d0282df3a16f1cb6ddf9d005d640738bb1b5659