Merge commit '8e66f0b35b5ec1054994f7048ef3e66002544197' into 0.67-merge-latest
This commit is contained in:
Коммит
39fd16d0fe
|
@ -79,4 +79,4 @@ untyped-import
|
|||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.158.0
|
||||
^0.159.0
|
||||
|
|
|
@ -82,4 +82,4 @@ untyped-import
|
|||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.158.0
|
||||
^0.159.0
|
||||
|
|
|
@ -79,4 +79,4 @@ untyped-import
|
|||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.158.0
|
||||
^0.159.0
|
||||
|
|
|
@ -1275,11 +1275,6 @@ class ScrollView extends React.Component<Props, State> {
|
|||
);
|
||||
}
|
||||
}
|
||||
if (Platform.OS === 'android') {
|
||||
if (this.props.keyboardDismissMode === 'on-drag' && this._isTouching) {
|
||||
dismissKeyboard();
|
||||
}
|
||||
}
|
||||
this._observedScrollSinceBecomingResponder = true;
|
||||
this.props.onScroll && this.props.onScroll(e);
|
||||
};
|
||||
|
@ -1396,6 +1391,14 @@ class ScrollView extends React.Component<Props, State> {
|
|||
*/
|
||||
_handleScrollBeginDrag: (e: ScrollEvent) => void = (e: ScrollEvent) => {
|
||||
FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation
|
||||
|
||||
if (
|
||||
Platform.OS === 'android' &&
|
||||
this.props.keyboardDismissMode === 'on-drag'
|
||||
) {
|
||||
dismissKeyboard();
|
||||
}
|
||||
|
||||
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,25 +4,29 @@
|
|||
* 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
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type {LayoutEvent} from '../../Types/CoreEventTypes';
|
||||
import setAndForwardRef from 'react-native/Libraries/Utilities/setAndForwardRef';
|
||||
import Platform from '../../Utilities/Platform';
|
||||
import StyleSheet from '../../StyleSheet/StyleSheet';
|
||||
import Animated from '../../Animated/Animated';
|
||||
import * as React from 'react';
|
||||
import {useEffect, useMemo, useRef, useCallback} from 'react';
|
||||
import AnimatedImplementation from '../../Animated/AnimatedImplementation';
|
||||
import AnimatedAddition from '../../Animated/nodes/AnimatedAddition';
|
||||
import AnimatedDiffClamp from '../../Animated/nodes/AnimatedDiffClamp';
|
||||
import AnimatedNode from '../../Animated/nodes/AnimatedNode';
|
||||
|
||||
const AnimatedView = Animated.View;
|
||||
import * as React from 'react';
|
||||
import StyleSheet from '../../StyleSheet/StyleSheet';
|
||||
import View from '../View/View';
|
||||
import Platform from '../../Utilities/Platform';
|
||||
|
||||
import type {LayoutEvent} from '../../Types/CoreEventTypes';
|
||||
|
||||
const AnimatedView = AnimatedImplementation.createAnimatedComponent(View);
|
||||
|
||||
export type Props = $ReadOnly<{
|
||||
children?: React.Element<$FlowFixMe>,
|
||||
children?: React.Element<any>,
|
||||
nextHeaderLayoutY: ?number,
|
||||
onLayout: (event: LayoutEvent) => void,
|
||||
scrollAnimatedValue: Animated.Value,
|
||||
scrollAnimatedValue: AnimatedImplementation.Value,
|
||||
// Will cause sticky headers to stick at the bottom of the ScrollView instead
|
||||
// of the top.
|
||||
inverted: ?boolean,
|
||||
|
@ -32,275 +36,287 @@ export type Props = $ReadOnly<{
|
|||
hiddenOnScroll?: ?boolean,
|
||||
}>;
|
||||
|
||||
const ScrollViewStickyHeaderWithForwardedRef: React.AbstractComponent<
|
||||
Props,
|
||||
$ReadOnly<{
|
||||
setNextHeaderY: number => void,
|
||||
...$Exact<React.ElementRef<typeof AnimatedView>>,
|
||||
}>,
|
||||
> = React.forwardRef(function ScrollViewStickyHeader(props, forwardedRef) {
|
||||
const {
|
||||
inverted,
|
||||
scrollViewHeight,
|
||||
hiddenOnScroll,
|
||||
scrollAnimatedValue,
|
||||
nextHeaderLayoutY: _nextHeaderLayoutY,
|
||||
} = props;
|
||||
type State = {
|
||||
measured: boolean,
|
||||
layoutY: number,
|
||||
layoutHeight: number,
|
||||
nextHeaderLayoutY: ?number,
|
||||
translateY: ?number,
|
||||
...
|
||||
};
|
||||
|
||||
const [measured, setMeasured] = React.useState<boolean>(false);
|
||||
const [layoutY, setLayoutY] = React.useState<number>(0);
|
||||
const [layoutHeight, setLayoutHeight] = React.useState<number>(0);
|
||||
const [translateY, setTranslateY] = React.useState<?number>(null);
|
||||
const [nextHeaderLayoutY, setNextHeaderLayoutY] = React.useState<?number>(
|
||||
_nextHeaderLayoutY,
|
||||
);
|
||||
const [isFabric, setIsFabric] = React.useState<boolean>(false);
|
||||
class ScrollViewStickyHeader extends React.Component<Props, State> {
|
||||
state: State = {
|
||||
measured: false,
|
||||
layoutY: 0,
|
||||
layoutHeight: 0,
|
||||
nextHeaderLayoutY: this.props.nextHeaderLayoutY,
|
||||
translateY: null,
|
||||
};
|
||||
|
||||
const componentRef = React.useRef<?React.ElementRef<typeof AnimatedView>>();
|
||||
const _setNativeRef = setAndForwardRef({
|
||||
getForwardedRef: () => forwardedRef,
|
||||
setLocalRef: ref => {
|
||||
componentRef.current = ref;
|
||||
if (ref) {
|
||||
ref.setNextHeaderY = value => {
|
||||
setNextHeaderLayoutY(value);
|
||||
};
|
||||
setIsFabric(
|
||||
!!(
|
||||
// An internal transform mangles variables with leading "_" as private.
|
||||
// eslint-disable-next-line dot-notation
|
||||
ref['_internalInstanceHandle']?.stateNode?.canonical
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
_translateY: ?AnimatedNode = null;
|
||||
_shouldRecreateTranslateY: boolean = true;
|
||||
_haveReceivedInitialZeroTranslateY: boolean = true;
|
||||
_ref: any; // TODO T53738161: flow type this, and the whole file
|
||||
|
||||
const offset = useMemo(
|
||||
() =>
|
||||
hiddenOnScroll === true
|
||||
? Animated.diffClamp(
|
||||
scrollAnimatedValue
|
||||
.interpolate({
|
||||
extrapolateLeft: 'clamp',
|
||||
inputRange: [layoutY, layoutY + 1],
|
||||
outputRange: ([0, 1]: Array<number>),
|
||||
})
|
||||
.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ([0, -1]: Array<number>),
|
||||
}),
|
||||
-layoutHeight,
|
||||
0,
|
||||
)
|
||||
: null,
|
||||
[scrollAnimatedValue, layoutHeight, layoutY, hiddenOnScroll],
|
||||
);
|
||||
// Fabric-only:
|
||||
_timer: ?TimeoutID;
|
||||
_animatedValueListenerId: string;
|
||||
_animatedValueListener: (valueObject: $ReadOnly<{|value: number|}>) => void;
|
||||
_debounceTimeout: number = Platform.OS === 'android' ? 15 : 64;
|
||||
|
||||
const [
|
||||
animatedTranslateY,
|
||||
setAnimatedTranslateY,
|
||||
] = React.useState<Animated.Node>(() => {
|
||||
const inputRange: Array<number> = [-1, 0];
|
||||
const outputRange: Array<number> = [0, 0];
|
||||
const initialTranslateY: Animated.Interpolation = scrollAnimatedValue.interpolate(
|
||||
{
|
||||
inputRange,
|
||||
outputRange,
|
||||
},
|
||||
);
|
||||
setNextHeaderY: (y: number) => void = (y: number): void => {
|
||||
this._shouldRecreateTranslateY = true;
|
||||
this.setState({nextHeaderLayoutY: y});
|
||||
};
|
||||
|
||||
if (offset != null) {
|
||||
return Animated.add(initialTranslateY, offset);
|
||||
componentWillUnmount() {
|
||||
if (this._translateY != null && this._animatedValueListenerId != null) {
|
||||
this._translateY.removeListener(this._animatedValueListenerId);
|
||||
}
|
||||
return initialTranslateY;
|
||||
});
|
||||
|
||||
const _haveReceivedInitialZeroTranslateY = useRef<boolean>(true);
|
||||
const _timer = useRef<?TimeoutID>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (translateY !== 0 && translateY != null) {
|
||||
_haveReceivedInitialZeroTranslateY.current = false;
|
||||
if (this._timer) {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
}, [translateY]);
|
||||
}
|
||||
|
||||
// This is called whenever the (Interpolated) Animated Value
|
||||
// updates, which is several times per frame during scrolling.
|
||||
// To ensure that the Fabric ShadowTree has the most recent
|
||||
// translate style of this node, we debounce the value and then
|
||||
// pass it through to the underlying node during render.
|
||||
// This is:
|
||||
// 1. Only an issue in Fabric.
|
||||
// 2. Worse in Android than iOS. In Android, but not iOS, you
|
||||
// can touch and move your finger slightly and still trigger
|
||||
// a "tap" event. In iOS, moving will cancel the tap in
|
||||
// both Fabric and non-Fabric. On Android when you move
|
||||
// your finger, the hit-detection moves from the Android
|
||||
// platform to JS, so we need the ShadowTree to have knowledge
|
||||
// of the current position.
|
||||
const animatedValueListener = useCallback(
|
||||
({value}) => {
|
||||
const _debounceTimeout: number = Platform.OS === 'android' ? 15 : 64;
|
||||
// When the AnimatedInterpolation is recreated, it always initializes
|
||||
// to a value of zero and emits a value change of 0 to its listeners.
|
||||
if (value === 0 && !_haveReceivedInitialZeroTranslateY.current) {
|
||||
_haveReceivedInitialZeroTranslateY.current = true;
|
||||
return;
|
||||
}
|
||||
if (_timer.current != null) {
|
||||
clearTimeout(_timer.current);
|
||||
}
|
||||
_timer.current = setTimeout(() => {
|
||||
if (value !== translateY) {
|
||||
setTranslateY(value);
|
||||
UNSAFE_componentWillReceiveProps(nextProps: Props) {
|
||||
if (
|
||||
nextProps.scrollViewHeight !== this.props.scrollViewHeight ||
|
||||
nextProps.scrollAnimatedValue !== this.props.scrollAnimatedValue ||
|
||||
nextProps.inverted !== this.props.inverted
|
||||
) {
|
||||
this._shouldRecreateTranslateY = true;
|
||||
}
|
||||
}
|
||||
|
||||
updateTranslateListener(
|
||||
translateY: AnimatedImplementation.Interpolation,
|
||||
isFabric: boolean,
|
||||
offset: AnimatedDiffClamp | null,
|
||||
) {
|
||||
if (this._translateY != null && this._animatedValueListenerId != null) {
|
||||
this._translateY.removeListener(this._animatedValueListenerId);
|
||||
}
|
||||
offset
|
||||
? (this._translateY = new AnimatedAddition(translateY, offset))
|
||||
: (this._translateY = translateY);
|
||||
|
||||
this._shouldRecreateTranslateY = false;
|
||||
|
||||
if (!isFabric) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._animatedValueListener) {
|
||||
// This is called whenever the (Interpolated) Animated Value
|
||||
// updates, which is several times per frame during scrolling.
|
||||
// To ensure that the Fabric ShadowTree has the most recent
|
||||
// translate style of this node, we debounce the value and then
|
||||
// pass it through to the underlying node during render.
|
||||
// This is:
|
||||
// 1. Only an issue in Fabric.
|
||||
// 2. Worse in Android than iOS. In Android, but not iOS, you
|
||||
// can touch and move your finger slightly and still trigger
|
||||
// a "tap" event. In iOS, moving will cancel the tap in
|
||||
// both Fabric and non-Fabric. On Android when you move
|
||||
// your finger, the hit-detection moves from the Android
|
||||
// platform to JS, so we need the ShadowTree to have knowledge
|
||||
// of the current position.
|
||||
this._animatedValueListener = ({value}) => {
|
||||
// When the AnimatedInterpolation is recreated, it always initializes
|
||||
// to a value of zero and emits a value change of 0 to its listeners.
|
||||
if (value === 0 && !this._haveReceivedInitialZeroTranslateY) {
|
||||
this._haveReceivedInitialZeroTranslateY = true;
|
||||
return;
|
||||
}
|
||||
}, _debounceTimeout);
|
||||
},
|
||||
[translateY],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const inputRange: Array<number> = [-1, 0];
|
||||
const outputRange: Array<number> = [0, 0];
|
||||
|
||||
if (measured) {
|
||||
if (inverted === true) {
|
||||
// The interpolation looks like:
|
||||
// - Negative scroll: no translation
|
||||
// - `stickStartPoint` is the point at which the header will start sticking.
|
||||
// It is calculated using the ScrollView viewport height so it is a the bottom.
|
||||
// - Headers that are in the initial viewport will never stick, `stickStartPoint`
|
||||
// will be negative.
|
||||
// - From 0 to `stickStartPoint` no translation. This will cause the header
|
||||
// to scroll normally until it reaches the top of the scroll view.
|
||||
// - From `stickStartPoint` to when the next header y hits the bottom edge of the header: translate
|
||||
// equally to scroll. This will cause the header to stay at the top of the scroll view.
|
||||
// - Past the collision with the next header y: no more translation. This will cause the
|
||||
// header to continue scrolling up and make room for the next sticky header.
|
||||
// In the case that there is no next header just translate equally to
|
||||
// scroll indefinitely.
|
||||
if (scrollViewHeight != null) {
|
||||
const stickStartPoint = layoutY + layoutHeight - scrollViewHeight;
|
||||
if (stickStartPoint > 0) {
|
||||
inputRange.push(stickStartPoint);
|
||||
outputRange.push(0);
|
||||
inputRange.push(stickStartPoint + 1);
|
||||
outputRange.push(1);
|
||||
// If the next sticky header has not loaded yet (probably windowing) or is the last
|
||||
// we can just keep it sticked forever.
|
||||
const collisionPoint =
|
||||
(nextHeaderLayoutY || 0) - layoutHeight - scrollViewHeight;
|
||||
if (collisionPoint > stickStartPoint) {
|
||||
inputRange.push(collisionPoint, collisionPoint + 1);
|
||||
outputRange.push(
|
||||
collisionPoint - stickStartPoint,
|
||||
collisionPoint - stickStartPoint,
|
||||
);
|
||||
}
|
||||
if (this._timer) {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
this._timer = setTimeout(() => {
|
||||
if (value !== this.state.translateY) {
|
||||
this.setState({
|
||||
translateY: value,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The interpolation looks like:
|
||||
// - Negative scroll: no translation
|
||||
// - From 0 to the y of the header: no translation. This will cause the header
|
||||
// to scroll normally until it reaches the top of the scroll view.
|
||||
// - From header y to when the next header y hits the bottom edge of the header: translate
|
||||
// equally to scroll. This will cause the header to stay at the top of the scroll view.
|
||||
// - Past the collision with the next header y: no more translation. This will cause the
|
||||
// header to continue scrolling up and make room for the next sticky header.
|
||||
// In the case that there is no next header just translate equally to
|
||||
// scroll indefinitely.
|
||||
inputRange.push(layoutY);
|
||||
outputRange.push(0);
|
||||
// If the next sticky header has not loaded yet (probably windowing) or is the last
|
||||
// we can just keep it sticked forever.
|
||||
const collisionPoint = (nextHeaderLayoutY || 0) - layoutHeight;
|
||||
if (collisionPoint >= layoutY) {
|
||||
inputRange.push(collisionPoint, collisionPoint + 1);
|
||||
outputRange.push(collisionPoint - layoutY, collisionPoint - layoutY);
|
||||
} else {
|
||||
inputRange.push(layoutY + 1);
|
||||
outputRange.push(1);
|
||||
}
|
||||
}
|
||||
}, this._debounceTimeout);
|
||||
};
|
||||
}
|
||||
if (this.state.translateY !== 0 && this.state.translateY != null) {
|
||||
this._haveReceivedInitialZeroTranslateY = false;
|
||||
}
|
||||
this._animatedValueListenerId = translateY.addListener(
|
||||
this._animatedValueListener,
|
||||
);
|
||||
}
|
||||
|
||||
_onLayout = event => {
|
||||
const layoutY = event.nativeEvent.layout.y;
|
||||
const layoutHeight = event.nativeEvent.layout.height;
|
||||
const measured = true;
|
||||
|
||||
if (
|
||||
layoutY !== this.state.layoutY ||
|
||||
layoutHeight !== this.state.layoutHeight ||
|
||||
measured !== this.state.measured
|
||||
) {
|
||||
this._shouldRecreateTranslateY = true;
|
||||
}
|
||||
|
||||
let newAnimatedTranslateY: Animated.Node = scrollAnimatedValue.interpolate({
|
||||
inputRange,
|
||||
outputRange,
|
||||
this.setState({
|
||||
measured,
|
||||
layoutY,
|
||||
layoutHeight,
|
||||
});
|
||||
|
||||
if (offset != null) {
|
||||
newAnimatedTranslateY = Animated.add(newAnimatedTranslateY, offset);
|
||||
}
|
||||
|
||||
// add the event listener
|
||||
let animatedListenerId;
|
||||
if (isFabric) {
|
||||
animatedListenerId = newAnimatedTranslateY.addListener(
|
||||
animatedValueListener,
|
||||
);
|
||||
}
|
||||
|
||||
setAnimatedTranslateY(newAnimatedTranslateY);
|
||||
|
||||
// clean up the event listener and timer
|
||||
return () => {
|
||||
if (animatedListenerId) {
|
||||
newAnimatedTranslateY.removeListener(animatedListenerId);
|
||||
}
|
||||
if (_timer.current != null) {
|
||||
clearTimeout(_timer.current);
|
||||
}
|
||||
};
|
||||
}, [nextHeaderLayoutY, measured, layoutHeight, layoutY, scrollViewHeight, scrollAnimatedValue, inverted, offset, animatedValueListener, isFabric]);
|
||||
|
||||
const _onLayout = (event: LayoutEvent) => {
|
||||
setLayoutY(event.nativeEvent.layout.y);
|
||||
setLayoutHeight(event.nativeEvent.layout.height);
|
||||
setMeasured(true);
|
||||
|
||||
props.onLayout(event);
|
||||
const child = React.Children.only(props.children);
|
||||
this.props.onLayout(event);
|
||||
const child = React.Children.only(this.props.children);
|
||||
if (child.props.onLayout) {
|
||||
child.props.onLayout(event);
|
||||
}
|
||||
};
|
||||
|
||||
const child = React.Children.only(props.children);
|
||||
_setComponentRef = ref => {
|
||||
this._ref = ref;
|
||||
};
|
||||
|
||||
// TODO T68319535: remove this if NativeAnimated is rewritten for Fabric
|
||||
const passthroughAnimatedPropExplicitValues =
|
||||
isFabric && translateY != null
|
||||
? {
|
||||
style: {transform: [{translateY: translateY}]},
|
||||
render(): React.Node {
|
||||
// Fabric Detection
|
||||
const isFabric = !!(
|
||||
// An internal transform mangles variables with leading "_" as private.
|
||||
// eslint-disable-next-line dot-notation
|
||||
(this._ref && this._ref['_internalInstanceHandle']?.stateNode?.canonical)
|
||||
);
|
||||
// Initially and in the case of updated props or layout, we
|
||||
// recreate this interpolated value. Otherwise, we do not recreate
|
||||
// when there are state changes.
|
||||
if (this._shouldRecreateTranslateY) {
|
||||
const {inverted, scrollViewHeight} = this.props;
|
||||
const {measured, layoutHeight, layoutY, nextHeaderLayoutY} = this.state;
|
||||
const inputRange: Array<number> = [-1, 0];
|
||||
const outputRange: Array<number> = [0, 0];
|
||||
|
||||
if (measured) {
|
||||
if (inverted) {
|
||||
// The interpolation looks like:
|
||||
// - Negative scroll: no translation
|
||||
// - `stickStartPoint` is the point at which the header will start sticking.
|
||||
// It is calculated using the ScrollView viewport height so it is a the bottom.
|
||||
// - Headers that are in the initial viewport will never stick, `stickStartPoint`
|
||||
// will be negative.
|
||||
// - From 0 to `stickStartPoint` no translation. This will cause the header
|
||||
// to scroll normally until it reaches the top of the scroll view.
|
||||
// - From `stickStartPoint` to when the next header y hits the bottom edge of the header: translate
|
||||
// equally to scroll. This will cause the header to stay at the top of the scroll view.
|
||||
// - Past the collision with the next header y: no more translation. This will cause the
|
||||
// header to continue scrolling up and make room for the next sticky header.
|
||||
// In the case that there is no next header just translate equally to
|
||||
// scroll indefinitely.
|
||||
if (scrollViewHeight != null) {
|
||||
const stickStartPoint = layoutY + layoutHeight - scrollViewHeight;
|
||||
if (stickStartPoint > 0) {
|
||||
inputRange.push(stickStartPoint);
|
||||
outputRange.push(0);
|
||||
inputRange.push(stickStartPoint + 1);
|
||||
outputRange.push(1);
|
||||
// If the next sticky header has not loaded yet (probably windowing) or is the last
|
||||
// we can just keep it sticked forever.
|
||||
const collisionPoint =
|
||||
(nextHeaderLayoutY || 0) - layoutHeight - scrollViewHeight;
|
||||
if (collisionPoint > stickStartPoint) {
|
||||
inputRange.push(collisionPoint, collisionPoint + 1);
|
||||
outputRange.push(
|
||||
collisionPoint - stickStartPoint,
|
||||
collisionPoint - stickStartPoint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The interpolation looks like:
|
||||
// - Negative scroll: no translation
|
||||
// - From 0 to the y of the header: no translation. This will cause the header
|
||||
// to scroll normally until it reaches the top of the scroll view.
|
||||
// - From header y to when the next header y hits the bottom edge of the header: translate
|
||||
// equally to scroll. This will cause the header to stay at the top of the scroll view.
|
||||
// - Past the collision with the next header y: no more translation. This will cause the
|
||||
// header to continue scrolling up and make room for the next sticky header.
|
||||
// In the case that there is no next header just translate equally to
|
||||
// scroll indefinitely.
|
||||
inputRange.push(layoutY);
|
||||
outputRange.push(0);
|
||||
// If the next sticky header has not loaded yet (probably windowing) or is the last
|
||||
// we can just keep it sticked forever.
|
||||
const collisionPoint = (nextHeaderLayoutY || 0) - layoutHeight;
|
||||
if (collisionPoint >= layoutY) {
|
||||
inputRange.push(collisionPoint, collisionPoint + 1);
|
||||
outputRange.push(
|
||||
collisionPoint - layoutY,
|
||||
collisionPoint - layoutY,
|
||||
);
|
||||
} else {
|
||||
inputRange.push(layoutY + 1);
|
||||
outputRange.push(1);
|
||||
}
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
return (
|
||||
/* $FlowFixMe[prop-missing] passthroughAnimatedPropExplicitValues isn't properly
|
||||
included in the Animated.View flow type. */
|
||||
<AnimatedView
|
||||
collapsable={false}
|
||||
nativeID={props.nativeID}
|
||||
onLayout={_onLayout}
|
||||
ref={_setNativeRef}
|
||||
style={[
|
||||
child.props.style,
|
||||
styles.header,
|
||||
{transform: [{translateY: animatedTranslateY}]},
|
||||
]}
|
||||
passthroughAnimatedPropExplicitValues={
|
||||
passthroughAnimatedPropExplicitValues
|
||||
}>
|
||||
{React.cloneElement(child, {
|
||||
style: styles.fill, // We transfer the child style to the wrapper.
|
||||
onLayout: undefined, // we call this manually through our this._onLayout
|
||||
})}
|
||||
</AnimatedView>
|
||||
);
|
||||
});
|
||||
this.updateTranslateListener(
|
||||
this.props.scrollAnimatedValue.interpolate({
|
||||
inputRange,
|
||||
outputRange,
|
||||
}),
|
||||
isFabric,
|
||||
this.props.hiddenOnScroll
|
||||
? new AnimatedDiffClamp(
|
||||
this.props.scrollAnimatedValue
|
||||
.interpolate({
|
||||
extrapolateLeft: 'clamp',
|
||||
inputRange: [layoutY, layoutY + 1],
|
||||
outputRange: ([0, 1]: Array<number>),
|
||||
})
|
||||
.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ([0, -1]: Array<number>),
|
||||
}),
|
||||
-this.state.layoutHeight,
|
||||
0,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
const child = React.Children.only(this.props.children);
|
||||
|
||||
// TODO T68319535: remove this if NativeAnimated is rewritten for Fabric
|
||||
const passthroughAnimatedPropExplicitValues =
|
||||
isFabric && this.state.translateY != null
|
||||
? {
|
||||
style: {transform: [{translateY: this.state.translateY}]},
|
||||
}
|
||||
: null;
|
||||
|
||||
return (
|
||||
<AnimatedView
|
||||
collapsable={false}
|
||||
nativeID={this.props.nativeID}
|
||||
onLayout={this._onLayout}
|
||||
ref={this._setComponentRef}
|
||||
style={[
|
||||
child.props.style,
|
||||
styles.header,
|
||||
{transform: [{translateY: this._translateY}]},
|
||||
]}
|
||||
passthroughAnimatedPropExplicitValues={
|
||||
passthroughAnimatedPropExplicitValues
|
||||
}>
|
||||
{React.cloneElement(child, {
|
||||
style: styles.fill, // We transfer the child style to the wrapper.
|
||||
onLayout: undefined, // we call this manually through our this._onLayout
|
||||
})}
|
||||
</AnimatedView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
header: {
|
||||
|
@ -312,4 +328,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
export default ScrollViewStickyHeaderWithForwardedRef;
|
||||
module.exports = ScrollViewStickyHeader;
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
@implementation RCTPropsAnimatedNode
|
||||
{
|
||||
NSNumber *_connectedViewTag;
|
||||
NSNumber *_rootTag;
|
||||
NSString *_connectedViewName;
|
||||
__weak RCTBridge *_bridge;
|
||||
__weak id<RCTSurfacePresenterStub> _surfacePresenter;
|
||||
|
@ -48,7 +47,6 @@
|
|||
_connectedViewTag = viewTag;
|
||||
_connectedViewName = viewName;
|
||||
_managedByFabric = RCTUIManagerTypeForTagIsFabric(viewTag);
|
||||
_rootTag = nil;
|
||||
}
|
||||
|
||||
- (void)disconnectFromView:(NSNumber *)viewTag
|
||||
|
@ -58,7 +56,6 @@
|
|||
_connectedViewTag = nil;
|
||||
_connectedViewName = nil;
|
||||
_managedByFabric = NO;
|
||||
_rootTag = nil;
|
||||
}
|
||||
|
||||
- (void)updateView
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#import <React/RCTBridge.h>
|
||||
|
||||
@class RCTModuleRegistry;
|
||||
@class RCTModuleData;
|
||||
@protocol RCTJavaScriptExecutor;
|
||||
|
||||
|
@ -62,6 +63,13 @@ RCT_EXTERN void RCTRegisterModule(Class);
|
|||
*/
|
||||
@property (nonatomic, strong, readwrite) NSURL *bundleURL;
|
||||
|
||||
/**
|
||||
* An object that allows one to require NativeModules/TurboModules.
|
||||
* RCTModuleRegistry is implemented in bridgeless mode and bridge mode.
|
||||
* Used by RCTRootView.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridge (RCTCxxBridge)
|
||||
|
|
|
@ -258,6 +258,11 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
|
|||
});
|
||||
}
|
||||
|
||||
- (RCTModuleRegistry *)moduleRegistry
|
||||
{
|
||||
return self.batchedBridge.moduleRegistry;
|
||||
}
|
||||
|
||||
- (NSArray<Class> *)moduleClasses
|
||||
{
|
||||
return self.batchedBridge.moduleClasses;
|
||||
|
|
|
@ -81,6 +81,8 @@ typedef NS_ENUM(NSInteger, RCTTextEventType) {
|
|||
*/
|
||||
@protocol RCTEventDispatcherProtocol <RCTBridgeModule, RCTJSDispatcherModule>
|
||||
|
||||
- (void)sendViewEventWithName:(NSString *)name reactTag:(NSNumber *)reactTag;
|
||||
|
||||
/**
|
||||
* Deprecated, do not use.
|
||||
*/
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#import <React/RCTUIKit.h> // TODO(macOS GH#774)
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTEventDispatcherProtocol.h>
|
||||
|
||||
@protocol RCTRootViewDelegate;
|
||||
|
||||
|
@ -75,6 +77,19 @@ extern
|
|||
initialProperties:(nullable NSDictionary *)initialProperties
|
||||
launchOptions:(nullable NSDictionary *)launchOptions;
|
||||
|
||||
/**
|
||||
* This API allows RCTRootView users to know if the root view is backed by the bridge.
|
||||
*/
|
||||
@property (nonatomic, readonly) BOOL hasBridge;
|
||||
|
||||
/**
|
||||
* This API allows users of RCTRootView to access other NativeModules, without
|
||||
* directly accessing the bridge.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry;
|
||||
|
||||
@property (nonatomic, strong, readonly) id<RCTEventDispatcherProtocol> eventDispatcher;
|
||||
|
||||
/**
|
||||
* The name of the JavaScript module to execute within the
|
||||
* specified scriptURL (required). Setting this will not have
|
||||
|
|
|
@ -136,6 +136,21 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat
|
|||
RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
|
||||
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
|
||||
|
||||
- (BOOL)hasBridge
|
||||
{
|
||||
return _bridge != nil;
|
||||
}
|
||||
|
||||
- (RCTModuleRegistry *)moduleRegistry
|
||||
{
|
||||
return _bridge.moduleRegistry;
|
||||
}
|
||||
|
||||
- (id<RCTEventDispatcherProtocol>)eventDispatcher
|
||||
{
|
||||
return [self.moduleRegistry moduleForName:"EventDispatcher"];
|
||||
}
|
||||
|
||||
#pragma mark - passThroughTouches
|
||||
|
||||
- (BOOL)passThroughTouches
|
||||
|
|
|
@ -26,6 +26,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@property (nonatomic, copy, readonly) NSString *moduleName;
|
||||
@property (nonatomic, strong, readonly) RCTBridge *bridge;
|
||||
@property (nonatomic, readonly) BOOL hasBridge;
|
||||
@property (nonatomic, strong, readonly) RCTModuleRegistry *moduleRegistry;
|
||||
@property (nonatomic, strong, readonly) id<RCTEventDispatcherProtocol> eventDispatcher;
|
||||
@property (nonatomic, copy, readwrite) NSDictionary *appProperties;
|
||||
@property (nonatomic, assign) RCTRootViewSizeFlexibility sizeFlexibility;
|
||||
@property (nonatomic, weak) id<RCTRootViewDelegate> delegate;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#import <objc/runtime.h>
|
||||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTBridge+Private.h"
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTPerformanceLogger.h"
|
||||
|
@ -94,6 +95,21 @@ static RCTRootViewSizeFlexibility convertToRootViewSizeFlexibility(RCTSurfaceSiz
|
|||
return [self initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
|
||||
}
|
||||
|
||||
- (BOOL)hasBridge
|
||||
{
|
||||
return _bridge != nil;
|
||||
}
|
||||
|
||||
- (RCTModuleRegistry *)moduleRegistry
|
||||
{
|
||||
return _bridge.moduleRegistry;
|
||||
}
|
||||
|
||||
- (id<RCTEventDispatcherProtocol>)eventDispatcher
|
||||
{
|
||||
return [self.moduleRegistry moduleForName:"EventDispatcher"];
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
|
||||
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
|
||||
|
||||
|
|
|
@ -56,6 +56,11 @@ RCT_EXPORT_MODULE()
|
|||
_observersLock = [NSLock new];
|
||||
}
|
||||
|
||||
- (void)sendViewEventWithName:(NSString *)name reactTag:(NSNumber *)reactTag
|
||||
{
|
||||
[_callableJSModules invokeModule:@"RCTViewEventEmitter" method:@"emit" withArgs:@[ name, RCTNullIfNil(reactTag) ]];
|
||||
}
|
||||
|
||||
- (void)sendAppEventWithName:(NSString *)name body:(id)body
|
||||
{
|
||||
[_callableJSModules invokeModule:@"RCTNativeAppEventEmitter"
|
||||
|
|
|
@ -245,6 +245,11 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||
@synthesize performanceLogger = _performanceLogger;
|
||||
@synthesize valid = _valid;
|
||||
|
||||
- (RCTModuleRegistry *)moduleRegistry
|
||||
{
|
||||
return _objCModuleRegistry;
|
||||
}
|
||||
|
||||
- (void)setRCTTurboModuleRegistry:(id<RCTTurboModuleRegistry>)turboModuleRegistry
|
||||
{
|
||||
_turboModuleRegistry = turboModuleRegistry;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#import <better/map.h>
|
||||
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTComponent.h>
|
||||
#import <React/RCTFollyConvert.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
@ -26,6 +27,18 @@
|
|||
|
||||
using namespace facebook::react;
|
||||
|
||||
static SurfaceId RCTSurfaceIdForView(UIView *view)
|
||||
{
|
||||
do {
|
||||
if (RCTIsReactRootView(@(view.tag))) {
|
||||
return view.tag;
|
||||
}
|
||||
view = view.superview;
|
||||
} while (view != nil);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void RCTPerformMountInstructions(
|
||||
ShadowViewMutationList const &mutations,
|
||||
RCTComponentViewRegistry *registry,
|
||||
|
@ -282,9 +295,10 @@ static void RCTPerformMountInstructions(
|
|||
{
|
||||
RCTAssertMainQueue();
|
||||
UIView<RCTComponentViewProtocol> *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag];
|
||||
SurfaceId surfaceId = RCTSurfaceIdForView(componentView);
|
||||
SharedProps oldProps = [componentView props];
|
||||
SharedProps newProps = componentDescriptor.cloneProps(
|
||||
PropsParserContext{-1, *_contextContainer.get()}, oldProps, RawProps(convertIdToFollyDynamic(props)));
|
||||
PropsParserContext{surfaceId, *_contextContainer.get()}, oldProps, RawProps(convertIdToFollyDynamic(props)));
|
||||
|
||||
NSSet<NSString *> *propKeys = componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN ?: [NSSet new];
|
||||
propKeys = [propKeys setByAddingObjectsFromArray:props.allKeys];
|
||||
|
|
|
@ -49,7 +49,6 @@ rn_android_library(
|
|||
react_native_target("java/com/facebook/react/config:config"),
|
||||
react_native_target("java/com/facebook/react/turbomodule/core:core"),
|
||||
react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"),
|
||||
react_native_target("java/com/facebook/react/runtimescheduler:runtimescheduler"),
|
||||
],
|
||||
exported_deps = [
|
||||
react_native_target("java/com/facebook/react/modules/core:core"),
|
||||
|
|
|
@ -92,7 +92,6 @@ import com.facebook.react.modules.core.ReactChoreographer;
|
|||
import com.facebook.react.modules.debug.interfaces.DeveloperSettings;
|
||||
import com.facebook.react.modules.fabric.ReactFabric;
|
||||
import com.facebook.react.packagerconnection.RequestHandler;
|
||||
import com.facebook.react.runtimescheduler.RuntimeSchedulerManager;
|
||||
import com.facebook.react.surface.ReactStage;
|
||||
import com.facebook.react.turbomodule.core.TurboModuleManager;
|
||||
import com.facebook.react.turbomodule.core.TurboModuleManagerDelegate;
|
||||
|
@ -167,7 +166,6 @@ public class ReactInstanceManager {
|
|||
private final boolean mUseDeveloperSupport;
|
||||
private final boolean mRequireActivity;
|
||||
private @Nullable ComponentNameResolverManager mComponentNameResolverManager;
|
||||
private @Nullable RuntimeSchedulerManager mRuntimeSchedulerManager;
|
||||
private final @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
|
||||
private final Object mReactContextLock = new Object();
|
||||
private @Nullable volatile ReactContext mCurrentReactContext;
|
||||
|
@ -759,7 +757,6 @@ public class ReactInstanceManager {
|
|||
mViewManagerNames = null;
|
||||
}
|
||||
mComponentNameResolverManager = null;
|
||||
mRuntimeSchedulerManager = null;
|
||||
FLog.d(ReactConstants.TAG, "ReactInstanceManager has been destroyed");
|
||||
}
|
||||
|
||||
|
@ -1394,9 +1391,6 @@ public class ReactInstanceManager {
|
|||
});
|
||||
catalystInstance.setGlobalVariable("__fbStaticViewConfig", "true");
|
||||
}
|
||||
if (ReactFeatureFlags.enableRuntimeScheduler) {
|
||||
mRuntimeSchedulerManager = new RuntimeSchedulerManager(catalystInstance.getRuntimeExecutor());
|
||||
}
|
||||
|
||||
ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START);
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "runJSBundle");
|
||||
|
|
|
@ -13,6 +13,7 @@ import static com.facebook.react.fabric.FabricUIManager.ENABLE_FABRIC_LOGS;
|
|||
import static com.facebook.react.fabric.FabricUIManager.IS_DEVELOPMENT_ENVIRONMENT;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.view.View;
|
||||
import androidx.annotation.AnyThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -274,10 +275,17 @@ public class MountItemDispatcher {
|
|||
executeOrEnqueue(mountItem);
|
||||
} catch (Throwable e) {
|
||||
// If there's an exception, we want to log diagnostics in prod and rethrow.
|
||||
FLog.e(TAG, "dispatchMountItems: caught exception, displaying all MountItems", e);
|
||||
FLog.e(TAG, "dispatchMountItems: caught exception, displaying mount state", e);
|
||||
for (MountItem m : mountItemsToDispatch) {
|
||||
printMountItem(m, "dispatchMountItems: mountItem");
|
||||
}
|
||||
if (mountItem.getSurfaceId() != View.NO_ID) {
|
||||
SurfaceMountingManager surfaceManager =
|
||||
mMountingManager.getSurfaceManager(mountItem.getSurfaceId());
|
||||
if (surfaceManager != null) {
|
||||
surfaceManager.printSurfaceState();
|
||||
}
|
||||
}
|
||||
|
||||
if (ReactIgnorableMountingException.isIgnorable(e)) {
|
||||
ReactSoftExceptionLogger.logSoftException(TAG, e);
|
||||
|
|
|
@ -963,6 +963,25 @@ public class SurfaceMountingManager {
|
|||
return (ViewGroupManager<ViewGroup>) viewState.mViewManager;
|
||||
}
|
||||
|
||||
public void printSurfaceState() {
|
||||
FLog.e(TAG, "Views created for surface {%d}:", getSurfaceId());
|
||||
for (ViewState viewState : mTagToViewState.values()) {
|
||||
String viewManagerName =
|
||||
viewState.mViewManager != null ? viewState.mViewManager.getName() : null;
|
||||
@Nullable View view = viewState.mView;
|
||||
@Nullable View parent = view != null ? (View) view.getParent() : null;
|
||||
@Nullable Integer parentTag = parent != null ? parent.getId() : null;
|
||||
|
||||
FLog.e(
|
||||
TAG,
|
||||
"<%s id=%d parentTag=%s isRoot=%b />",
|
||||
viewManagerName,
|
||||
viewState.mReactTag,
|
||||
parentTag,
|
||||
viewState.mIsRoot);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class holds view state for react tags. Objects of this class are stored into the {@link
|
||||
* #mTagToViewState}, and they should be updated in the same thread.
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library")
|
||||
|
||||
rn_android_library(
|
||||
name = "runtimescheduler",
|
||||
srcs = glob(["**/*.java"]),
|
||||
autoglob = False,
|
||||
is_androidx = True,
|
||||
labels = ["supermodule:xplat/default/public.react_native.infra"],
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
react_native_target("java/com/facebook/react/runtimescheduler/jni:jni"),
|
||||
react_native_dep("third-party/android/androidx:annotation"),
|
||||
react_native_dep("third-party/java/infer-annotations:infer-annotations"),
|
||||
react_native_dep("libraries/fbjni:java"),
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"),
|
||||
],
|
||||
)
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.runtimescheduler;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.proguard.annotations.DoNotStripAny;
|
||||
import com.facebook.react.bridge.RuntimeExecutor;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
@DoNotStripAny
|
||||
public class RuntimeSchedulerManager {
|
||||
|
||||
static {
|
||||
staticInit();
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
@SuppressWarnings("unused")
|
||||
private final HybridData mHybridData;
|
||||
|
||||
public RuntimeSchedulerManager(RuntimeExecutor runtimeExecutor) {
|
||||
mHybridData = initHybrid(runtimeExecutor);
|
||||
installJSIBindings();
|
||||
}
|
||||
|
||||
private native HybridData initHybrid(RuntimeExecutor runtimeExecutor);
|
||||
|
||||
private native void installJSIBindings();
|
||||
|
||||
private static void staticInit() {
|
||||
SoLoader.loadLibrary("runtimeschedulerjni");
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := runtimeschedulerjni
|
||||
|
||||
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libglog libfb libfbjni libglog_init libreact_render_runtimescheduler librrc_native
|
||||
|
||||
LOCAL_STATIC_LIBRARIES :=
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
-DLOG_TAG=\"ReacTNative\"
|
||||
|
||||
LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
$(call import-module,fbgloginit)
|
||||
$(call import-module,fb)
|
||||
$(call import-module,fbjni)
|
||||
$(call import-module,glog)
|
||||
|
||||
$(call import-module,react/renderer/runtimescheduler)
|
|
@ -1,35 +0,0 @@
|
|||
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob")
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "jni",
|
||||
srcs = glob(["*.cpp"]),
|
||||
headers = glob(["*.h"]),
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[
|
||||
("", "**/*.h"),
|
||||
],
|
||||
prefix = "react/runtimescheduler",
|
||||
),
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++17",
|
||||
"-Wall",
|
||||
],
|
||||
fbandroid_allow_jni_merging = True,
|
||||
labels = ["supermodule:xplat/default/public.react_native.infra"],
|
||||
platforms = ANDROID,
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
soname = "libruntimeschedulerjni.$(ext)",
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
react_native_xplat_target("react/renderer/runtimescheduler:runtimescheduler"),
|
||||
react_native_xplat_target("runtimeexecutor:runtimeexecutor"),
|
||||
react_native_target("jni/react/jni:jni"),
|
||||
FBJNI_TARGET,
|
||||
],
|
||||
)
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include "RuntimeSchedulerManager.h"
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
||||
return facebook::jni::initialize(
|
||||
vm, [] { facebook::react::RuntimeSchedulerManager::registerNatives(); });
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
|
||||
#include <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
|
||||
|
||||
#include "RuntimeSchedulerManager.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
RuntimeSchedulerManager::RuntimeSchedulerManager(
|
||||
RuntimeExecutor runtimeExecutor)
|
||||
: runtimeExecutor_(runtimeExecutor) {}
|
||||
|
||||
jni::local_ref<RuntimeSchedulerManager::jhybriddata>
|
||||
RuntimeSchedulerManager::initHybrid(
|
||||
jni::alias_ref<jclass>,
|
||||
jni::alias_ref<JRuntimeExecutor::javaobject> runtimeExecutor) {
|
||||
return makeCxxInstance(runtimeExecutor->cthis()->get());
|
||||
}
|
||||
|
||||
void RuntimeSchedulerManager::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", RuntimeSchedulerManager::initHybrid),
|
||||
makeNativeMethod(
|
||||
"installJSIBindings", RuntimeSchedulerManager::installJSIBindings),
|
||||
});
|
||||
}
|
||||
|
||||
void RuntimeSchedulerManager::installJSIBindings() {
|
||||
runtimeExecutor_([runtimeExecutor = runtimeExecutor_](jsi::Runtime &runtime) {
|
||||
auto runtimeScheduler = std::make_shared<RuntimeScheduler>(runtimeExecutor);
|
||||
RuntimeSchedulerBinding::createAndInstallIfNeeded(
|
||||
runtime, runtimeScheduler);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ReactCommon/CallInvokerHolder.h>
|
||||
#include <ReactCommon/RuntimeExecutor.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <react/jni/JRuntimeExecutor.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class RuntimeSchedulerManager
|
||||
: public facebook::jni::HybridClass<RuntimeSchedulerManager> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor =
|
||||
"Lcom/facebook/react/runtimescheduler/RuntimeSchedulerManager;";
|
||||
|
||||
static facebook::jni::local_ref<jhybriddata> initHybrid(
|
||||
jni::alias_ref<jclass>,
|
||||
facebook::jni::alias_ref<JRuntimeExecutor::javaobject> runtimeExecutor);
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
private:
|
||||
friend HybridBase;
|
||||
RuntimeExecutor runtimeExecutor_;
|
||||
|
||||
void installJSIBindings();
|
||||
|
||||
explicit RuntimeSchedulerManager(RuntimeExecutor runtimeExecutor);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -56,6 +56,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
|||
private boolean mAdjustsFontSizeToFit = false;
|
||||
private int mLinkifyMaskType = 0;
|
||||
private boolean mNotifyOnInlineViewLayout;
|
||||
private boolean mTextIsSelectable = false;
|
||||
|
||||
private ReactViewBackgroundManager mReactBackgroundManager;
|
||||
private Spannable mSpanned;
|
||||
|
@ -433,9 +434,16 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextIsSelectable(boolean selectable) {
|
||||
mTextIsSelectable = selectable;
|
||||
super.setTextIsSelectable(selectable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
setTextIsSelectable(mTextIsSelectable);
|
||||
if (mContainsImages && getText() instanceof Spanned) {
|
||||
Spanned text = (Spanned) getText();
|
||||
TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <memory>
|
||||
|
||||
#include <folly/Hash.h>
|
||||
#include <folly/Optional.h>
|
||||
#include <react/renderer/attributedstring/TextAttributes.h>
|
||||
#include <react/renderer/core/Sealable.h>
|
||||
#include <react/renderer/core/ShadowNode.h>
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
#include <better/optional.h>
|
||||
#include <folly/Hash.h>
|
||||
#include <folly/Optional.h>
|
||||
#include <react/renderer/attributedstring/primitives.h>
|
||||
#include <react/renderer/core/LayoutPrimitives.h>
|
||||
#include <react/renderer/core/ReactPrimitives.h>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <react/renderer/core/ConcreteState.h>
|
||||
#include <react/renderer/core/Props.h>
|
||||
#include <react/renderer/core/PropsParserContext.h>
|
||||
#include <react/renderer/core/RawProps.h>
|
||||
#include <react/renderer/core/ShadowNode.h>
|
||||
#include <react/renderer/core/StateData.h>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <folly/dynamic.h>
|
||||
|
||||
#include <react/renderer/core/PropsParserContext.h>
|
||||
#include <react/renderer/core/RawProps.h>
|
||||
#include <react/renderer/core/ReactPrimitives.h>
|
||||
#include <react/renderer/core/Sealable.h>
|
||||
#include <react/renderer/debug/DebugStringConvertible.h>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <react/renderer/core/ReactPrimitives.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
namespace facebook {
|
||||
|
@ -20,8 +21,8 @@ struct PropsParserContext {
|
|||
PropsParserContext(const PropsParserContext &) = delete;
|
||||
PropsParserContext &operator=(const PropsParserContext &) = delete;
|
||||
|
||||
int surfaceId; // TODO: use SurfaceId type
|
||||
const ContextContainer &contextContainer;
|
||||
SurfaceId const surfaceId;
|
||||
ContextContainer const &contextContainer;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
#include <react/renderer/core/RawProps.h>
|
||||
#include <react/renderer/core/RawValue.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include <better/mutex.h>
|
||||
#include <better/small_vector.h>
|
||||
|
||||
#include <react/renderer/core/EventEmitter.h>
|
||||
#include <react/renderer/core/ReactPrimitives.h>
|
||||
|
|
|
@ -50,7 +50,6 @@ rn_xplat_cxx_library(
|
|||
tests = [":tests"],
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
react_native_xplat_target("react/renderer/core:core"),
|
||||
react_native_xplat_target("runtimeexecutor:runtimeexecutor"),
|
||||
react_native_xplat_target("react/renderer/debug:debug"),
|
||||
react_native_xplat_target("better:better"),
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
#include "RuntimeScheduler.h"
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
|
@ -113,4 +114,5 @@ void RuntimeScheduler::startWorkLoop(jsi::Runtime &runtime) const {
|
|||
isPerformingWork_ = false;
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class RuntimeScheduler final {
|
||||
public:
|
||||
|
@ -100,4 +101,5 @@ class RuntimeScheduler final {
|
|||
mutable bool isPerformingWork_{false};
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
#include "primitives.h"
|
||||
|
||||
#include <react/debug/react_native_assert.h>
|
||||
#include <react/renderer/core/PropsParserContext.h>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
std::shared_ptr<RuntimeSchedulerBinding>
|
||||
RuntimeSchedulerBinding::createAndInstallIfNeeded(
|
||||
|
@ -167,4 +167,5 @@ jsi::Value RuntimeSchedulerBinding::get(
|
|||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
#include <jsi/jsi.h>
|
||||
#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Exposes RuntimeScheduler to JavaScript realm.
|
||||
|
@ -39,4 +40,5 @@ class RuntimeSchedulerBinding : public jsi::HostObject {
|
|||
std::shared_ptr<RuntimeScheduler> runtimeScheduler_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
#include <chrono>
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Represents a monotonic clock suitable for measuring intervals.
|
||||
|
@ -19,4 +20,5 @@ using RuntimeSchedulerClock = std::chrono::steady_clock;
|
|||
using RuntimeSchedulerTimePoint = RuntimeSchedulerClock::time_point;
|
||||
using RuntimeSchedulerDuration = RuntimeSchedulerClock::duration;
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <react/debug/react_native_assert.h>
|
||||
#include <react/renderer/core/PropsParserContext.h>
|
||||
#include <chrono>
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
enum class SchedulerPriority : int {
|
||||
ImmediatePriority = 1,
|
||||
|
@ -61,4 +61,5 @@ static inline std::chrono::milliseconds timeoutForSchedulerPriority(
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
#include "RuntimeScheduler.h"
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
Task::Task(
|
||||
SchedulerPriority priority,
|
||||
|
@ -32,4 +33,5 @@ jsi::Value Task::execute(jsi::Runtime &runtime) {
|
|||
return result;
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
#include <react/renderer/runtimescheduler/RuntimeSchedulerClock.h>
|
||||
#include <react/renderer/runtimescheduler/SchedulerPriority.h>
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class RuntimeScheduler;
|
||||
class TaskPriorityComparer;
|
||||
|
@ -43,4 +44,5 @@ class TaskPriorityComparer {
|
|||
}
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
#include <jsi/jsi.h>
|
||||
#include <react/renderer/runtimescheduler/Task.h>
|
||||
|
||||
namespace facebook::react {
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct TaskWrapper : public jsi::HostObject {
|
||||
TaskWrapper(std::shared_ptr<Task> const &task) : task(task) {}
|
||||
|
@ -36,4 +37,5 @@ inline static std::shared_ptr<Task> taskFromValue(
|
|||
return value.getObject(runtime).getHostObject<TaskWrapper>(runtime)->task;
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -6,4 +6,4 @@ org.gradle.parallel=true
|
|||
|
||||
ANDROID_NDK_VERSION=21.4.7075529
|
||||
android.useAndroidX=true
|
||||
kotlin_version=1.4.21
|
||||
kotlin_version=1.4.32
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -153,7 +153,7 @@
|
|||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"eslint-plugin-react-native": "^3.11.0",
|
||||
"eslint-plugin-relay": "1.8.1",
|
||||
"flow-bin": "^0.158.0",
|
||||
"flow-bin": "^0.159.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-junit": "^10.0.0",
|
||||
"jscodeshift": "^0.11.0",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -419,6 +419,7 @@ DEPENDENCIES:
|
|||
- FlipperKit/FlipperKitUserDefaultsPlugin (= 0.99.0)
|
||||
- FlipperKit/SKIOSNetworkPlugin (= 0.99.0)
|
||||
- glog (from `../../third-party-podspecs/glog.podspec`)
|
||||
- OpenSSL-Universal (= 1.1.180)
|
||||
- RCT-Folly (from `../../third-party-podspecs/RCT-Folly.podspec`)
|
||||
- RCTRequired (from `../../Libraries/RCTRequired`)
|
||||
- RCTTypeSafety (from `../../Libraries/TypeSafety`)
|
||||
|
|
|
@ -1683,7 +1683,6 @@
|
|||
"$(inherited)",
|
||||
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
|
||||
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
|
||||
"\"$(SDKROOT)/usr/lib/swift\"",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"$(inherited)",
|
||||
|
|
|
@ -57,13 +57,14 @@ class ItemComponent extends React.PureComponent<{
|
|||
onPress: (key: string) => void,
|
||||
onShowUnderlay?: () => void,
|
||||
onHideUnderlay?: () => void,
|
||||
textSelectable?: ?boolean,
|
||||
...
|
||||
}> {
|
||||
_onPress = () => {
|
||||
this.props.onPress(this.props.item.key);
|
||||
};
|
||||
render(): React.Node {
|
||||
const {fixedHeight, horizontal, item} = this.props;
|
||||
const {fixedHeight, horizontal, item, textSelectable} = this.props;
|
||||
const itemHash = Math.abs(hashCode(item.title));
|
||||
const imgSource = THUMB_URLS[itemHash % THUMB_URLS.length];
|
||||
return (
|
||||
|
@ -81,6 +82,7 @@ class ItemComponent extends React.PureComponent<{
|
|||
{!item.noImage && <Image style={styles.thumb} source={imgSource} />}
|
||||
<Text
|
||||
style={styles.text}
|
||||
selectable={textSelectable}
|
||||
numberOfLines={horizontal || fixedHeight ? 3 : undefined}>
|
||||
{item.title} - {item.text}
|
||||
</Text>
|
||||
|
|
|
@ -59,6 +59,8 @@ type State = {|
|
|||
empty: boolean,
|
||||
useFlatListItemComponent: boolean,
|
||||
fadingEdgeLength: number,
|
||||
onPressDisabled: boolean,
|
||||
textSelectable: boolean,
|
||||
|};
|
||||
|
||||
class FlatListExample extends React.PureComponent<Props, State> {
|
||||
|
@ -74,6 +76,8 @@ class FlatListExample extends React.PureComponent<Props, State> {
|
|||
empty: false,
|
||||
useFlatListItemComponent: false,
|
||||
fadingEdgeLength: 0,
|
||||
onPressDisabled: false,
|
||||
textSelectable: true,
|
||||
};
|
||||
|
||||
_onChangeFilterText = filterText => {
|
||||
|
@ -161,6 +165,16 @@ class FlatListExample extends React.PureComponent<Props, State> {
|
|||
this.state.debug,
|
||||
this._setBooleanValue('debug'),
|
||||
)}
|
||||
{renderSmallSwitchOption(
|
||||
'onPress Disabled',
|
||||
this.state.onPressDisabled,
|
||||
this._setBooleanValue('onPressDisabled'),
|
||||
)}
|
||||
{renderSmallSwitchOption(
|
||||
'Text Selectable',
|
||||
this.state.textSelectable,
|
||||
this._setBooleanValue('textSelectable'),
|
||||
)}
|
||||
{renderSmallSwitchOption(
|
||||
'Use FlatListItemComponent',
|
||||
this.state.useFlatListItemComponent,
|
||||
|
@ -236,6 +250,12 @@ class FlatListExample extends React.PureComponent<Props, State> {
|
|||
data: state.data.concat(genItemData(100, state.data.length)),
|
||||
}));
|
||||
};
|
||||
_onPressCallback = () => {
|
||||
const {onPressDisabled} = this.state;
|
||||
const warning = () => console.log('onPress disabled');
|
||||
const onPressAction = onPressDisabled ? warning : this._pressItem;
|
||||
return onPressAction;
|
||||
};
|
||||
_onRefresh = () => Alert.alert('onRefresh: nothing to refresh :P');
|
||||
_renderItemComponent = () => {
|
||||
const flatListPropKey = this.state.useFlatListItemComponent
|
||||
|
@ -253,9 +273,10 @@ class FlatListExample extends React.PureComponent<Props, State> {
|
|||
item={item}
|
||||
horizontal={this.state.horizontal}
|
||||
fixedHeight={this.state.fixedHeight}
|
||||
onPress={this._pressItem}
|
||||
onPress={this._onPressCallback()}
|
||||
onShowUnderlay={separators.highlight}
|
||||
onHideUnderlay={separators.unhighlight}
|
||||
textSelectable={this.state.textSelectable}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"eslint-plugin-react-native": "^3.11.0",
|
||||
"eslint-plugin-relay": "^1.8.2",
|
||||
"flow-bin": "^0.158.0",
|
||||
"flow-bin": "^0.159.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-junit": "^10.0.0",
|
||||
"jscodeshift": "^0.11.0",
|
||||
|
|
|
@ -82,6 +82,7 @@ def use_flipper!(versions = {}, configurations: ['Debug'])
|
|||
versions['Flipper-Glog'] ||= '0.3.6'
|
||||
versions['Flipper-PeerTalk'] ||= '0.0.4'
|
||||
versions['Flipper-RSocket'] ||= '1.4.3'
|
||||
versions['OpenSSL-Universal'] ||= '1.1.180'
|
||||
pod 'FlipperKit', versions['Flipper'], :configurations => configurations
|
||||
pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configurations => configurations
|
||||
pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configurations => configurations
|
||||
|
@ -105,6 +106,7 @@ def use_flipper!(versions = {}, configurations: ['Debug'])
|
|||
pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configurations => configurations
|
||||
pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configurations => configurations
|
||||
pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configurations => configurations
|
||||
pod 'OpenSSL-Universal', versions['OpenSSL-Universal'], :configurations => configurations
|
||||
end
|
||||
|
||||
def has_pod(installer, name)
|
||||
|
|
|
@ -65,4 +65,4 @@ untyped-import
|
|||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.158.0
|
||||
^0.159.0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -439,7 +439,6 @@
|
|||
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
|
||||
"\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"",
|
||||
"\"$(inherited)\"",
|
||||
"\"$(SDKROOT)/usr/lib/swift\"",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
|
@ -498,7 +497,6 @@
|
|||
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
|
||||
"\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"",
|
||||
"\"$(inherited)\"",
|
||||
"\"$(SDKROOT)/usr/lib/swift\"",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
|
|
|
@ -3993,10 +3993,10 @@ flatted@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
|
||||
integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
|
||||
|
||||
flow-bin@^0.158.0:
|
||||
version "0.158.0"
|
||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.158.0.tgz#0a09763d41eb8ec7135ced6a3b9f8fa370a393d8"
|
||||
integrity sha512-Gk5md8XTwk/M+J5M+rFyS1LJfFen6ldY60jM9+meWixlKf4b0vwdoUO8R7oo471pze+GY+blrnskUeqLDxFJfg==
|
||||
flow-bin@^0.159.0:
|
||||
version "0.159.0"
|
||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.159.0.tgz#f788480d54db6da021e3440648c1dbb5dbc8aee8"
|
||||
integrity sha512-5SugX7mOdfruzn2/+42DF74bxJO2SGmSEzCvTH9wOoBi98Ie87D5Hmb9OoGfwAE5SnXJmB6OCwN2WDiJe4lI+w==
|
||||
|
||||
flow-parser@0.*:
|
||||
version "0.176.2"
|
||||
|
|
Загрузка…
Ссылка в новой задаче