From 52648326e6ac4470eeffc0a56d91bc487bc1eae4 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 14 Jan 2018 19:32:33 -0800 Subject: [PATCH] Generalization of `isInAParentText` context Summary: Currently `isInAParentText` context works as imaginary `isInAAncestorText` context (not like a real `isInAParentText`). Let's imagine we have hierarchy like: `View -> Text -> Text* -> View* -> Text* -> Text* -> View*` With current implementation all nodes marked with asterisk have `isInAParentText` context, which is incorrect (because some of them actually in View context). With the new implemetations it will work like this: `View -> Text -> Text* -> View* -> Text -> Text* -> View*` So, only nodes which have (or ) as a parent will have `isInAParentText` context. This change allows to select proper `Text` vs. `VirtualText` component in cases where and components can interleave each other. Reviewed By: sahrens Differential Revision: D6690495 fbshipit-source-id: f7c59b23d0eaf68a1d08036b858d99c9547f7878 --- Libraries/Components/TextInput/TextInput.js | 22 ++++++++++++-------- Libraries/Components/View/View.js | 11 +++++++--- Libraries/Components/View/ViewContext.js | 23 +++++++++++++++++++++ Libraries/Image/Image.android.js | 8 +++---- Libraries/Text/Text.js | 17 ++++++++------- 5 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 Libraries/Components/View/ViewContext.js diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 1b32396c541152..d16115cad7e9bb 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -31,6 +31,7 @@ const TimerMixin = require('react-timer-mixin'); const TouchableWithoutFeedback = require('TouchableWithoutFeedback'); const UIManager = require('UIManager'); const ViewPropTypes = require('ViewPropTypes'); +const {ViewContextTypes} = require('ViewContext'); /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error * found when Flow v0.54 was deployed. To see the error delete this comment and @@ -48,6 +49,8 @@ const onlyMultiline = { children: true, }; +import type {ViewChildContext} from 'ViewContext'; + if (Platform.OS === 'android') { var AndroidTextInput = requireNativeComponent('AndroidTextInput', null); } else if (Platform.OS === 'ios') { @@ -612,11 +615,6 @@ const TextInput = createReactClass({ ); }, - contextTypes: { - onFocusRequested: PropTypes.func, - focusEmitter: PropTypes.instanceOf(EventEmitter), - }, - _inputRef: (undefined: any), _focusSubscription: (undefined: ?Function), _lastNativeText: (undefined: ?string), @@ -652,12 +650,18 @@ const TextInput = createReactClass({ } }, - getChildContext: function(): Object { - return {isInAParentText: true}; + getChildContext(): ViewChildContext { + return { + isInAParentText: true, + }; }, - childContextTypes: { - isInAParentText: PropTypes.bool, + childContextTypes: ViewContextTypes, + + contextTypes: { + ...ViewContextTypes, + onFocusRequested: PropTypes.func, + focusEmitter: PropTypes.instanceOf(EventEmitter), }, /** diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 87a8ca0884cc9c..2393f43526b709 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -14,17 +14,18 @@ const NativeMethodsMixin = require('NativeMethodsMixin'); const Platform = require('Platform'); -const PropTypes = require('prop-types'); const React = require('React'); const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); const ReactNativeViewAttributes = require('ReactNativeViewAttributes'); const ViewPropTypes = require('ViewPropTypes'); +const {ViewContextTypes} = require('ViewContext'); const createReactClass = require('create-react-class'); const invariant = require('fbjs/lib/invariant'); const requireNativeComponent = require('requireNativeComponent'); import type {ViewProps} from 'ViewPropTypes'; +import type {ViewChildContext} from 'ViewContext'; export type Props = ViewProps; @@ -56,8 +57,12 @@ const View = createReactClass({ validAttributes: ReactNativeViewAttributes.RCTView, }, - contextTypes: { - isInAParentText: PropTypes.bool, + childContextTypes: ViewContextTypes, + + getChildContext(): ViewChildContext { + return { + isInAParentText: false, + }; }, render() { diff --git a/Libraries/Components/View/ViewContext.js b/Libraries/Components/View/ViewContext.js new file mode 100644 index 00000000000000..ed73187b0bb8d6 --- /dev/null +++ b/Libraries/Components/View/ViewContext.js @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ViewContext + * @flow + * @format + */ +'use strict'; + +const PropTypes = require('prop-types'); + +export type ViewChildContext = {| + +isInAParentText: boolean, +|}; + +export const ViewContextTypes = { + isInAParentText: PropTypes.bool, +}; diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index a8cac24a513181..dc561bdb2bffee 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -22,17 +22,17 @@ var ReactNativeViewAttributes = require('ReactNativeViewAttributes'); var Set = require('Set'); var StyleSheet = require('StyleSheet'); var StyleSheetPropType = require('StyleSheetPropType'); -var View = require('View'); var ViewPropTypes = require('ViewPropTypes'); var ViewStylePropTypes = require('ViewStylePropTypes'); var createReactClass = require('create-react-class'); -var filterObject = require('fbjs/lib/filterObject'); var flattenStyle = require('flattenStyle'); var merge = require('merge'); var requireNativeComponent = require('requireNativeComponent'); var resolveAssetSource = require('resolveAssetSource'); +const {ViewContextTypes} = require('ViewContext'); + var {ImageLoader} = NativeModules; let _requestId = 1; @@ -261,9 +261,7 @@ var Image = createReactClass({ validAttributes: ReactNativeViewAttributes.RCTView, }, - contextTypes: { - isInAParentText: PropTypes.bool, - }, + contextTypes: ViewContextTypes, render: function() { const source = resolveAssetSource(this.props.source); diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 0f8fe1a1767b76..44b327da8943dc 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -26,9 +26,12 @@ const createReactClass = require('create-react-class'); const requireNativeComponent = require('requireNativeComponent'); const mergeFast = require('mergeFast'); const processColor = require('processColor'); +const {ViewContextTypes} = require('ViewContext'); const stylePropType = StyleSheetPropType(TextStylePropTypes); +import type {ViewChildContext} from 'ViewContext'; + /** * A React component for displaying text. * @@ -401,15 +404,13 @@ const Text = createReactClass({ }); }, mixins: [NativeMethodsMixin], - getChildContext(): Object { - return {isInAParentText: true}; - }, - childContextTypes: { - isInAParentText: PropTypes.bool, - }, - contextTypes: { - isInAParentText: PropTypes.bool, + getChildContext(): ViewChildContext { + return { + isInAParentText: true, + }; }, + childContextTypes: ViewContextTypes, + contextTypes: ViewContextTypes, /** * Only assigned if touch is needed. */