Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flow-strict] Flow strict ScrollResponder #22181

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 31 additions & 27 deletions Libraries/Components/ScrollResponder.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const warning = require('fbjs/lib/warning');

const {ScrollViewManager} = require('NativeModules');

import type {PressEvent, ScrollEvent} from 'CoreEventTypes';
import type {KeyboardEvent} from 'Keyboard';
import type EmitterSubscription from 'EmitterSubscription';

/**
Expand Down Expand Up @@ -113,7 +115,6 @@ type State = {
observedScrollSinceBecomingResponder: boolean,
becameResponderWhileAnimating: boolean,
};
type Event = Object;

const ScrollResponderMixin = {
_subscriptionKeyboardWillShow: (null: ?EmitterSubscription),
Expand Down Expand Up @@ -168,7 +169,9 @@ const ScrollResponderMixin = {
* true.
*
*/
scrollResponderHandleStartShouldSetResponder: function(e: Event): boolean {
scrollResponderHandleStartShouldSetResponder: function(
e: PressEvent,
): boolean {
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();

if (
Expand All @@ -193,7 +196,7 @@ const ScrollResponderMixin = {
* Invoke this from an `onStartShouldSetResponderCapture` event.
*/
scrollResponderHandleStartShouldSetResponderCapture: function(
e: Event,
e: PressEvent,
): boolean {
// The scroll view should receive taps instead of its descendants if:
// * it is already animating/decelerating
Expand All @@ -212,6 +215,7 @@ const ScrollResponderMixin = {
if (
keyboardNeverPersistTaps &&
currentlyFocusedTextInput != null &&
e.target &&
!TextInputState.isTextInput(e.target)
) {
return true;
Expand Down Expand Up @@ -254,9 +258,9 @@ const ScrollResponderMixin = {
/**
* Invoke this from an `onTouchEnd` event.
*
* @param {SyntheticEvent} e Event.
* @param {PressEvent} e Event.
*/
scrollResponderHandleTouchEnd: function(e: Event) {
scrollResponderHandleTouchEnd: function(e: PressEvent) {
const nativeEvent = e.nativeEvent;
this.state.isTouching = nativeEvent.touches.length !== 0;
this.props.onTouchEnd && this.props.onTouchEnd(e);
Expand All @@ -265,17 +269,17 @@ const ScrollResponderMixin = {
/**
* Invoke this from an `onTouchCancel` event.
*
* @param {SyntheticEvent} e Event.
* @param {PressEvent} e Event.
*/
scrollResponderHandleTouchCancel: function(e: Event) {
scrollResponderHandleTouchCancel: function(e: PressEvent) {
this.state.isTouching = false;
this.props.onTouchCancel && this.props.onTouchCancel(e);
},

/**
* Invoke this from an `onResponderRelease` event.
*/
scrollResponderHandleResponderRelease: function(e: Event) {
scrollResponderHandleResponderRelease: function(e: PressEvent) {
this.props.onResponderRelease && this.props.onResponderRelease(e);

// By default scroll views will unfocus a textField
Expand All @@ -295,15 +299,15 @@ const ScrollResponderMixin = {
}
},

scrollResponderHandleScroll: function(e: Event) {
scrollResponderHandleScroll: function(e: ScrollEvent) {
this.state.observedScrollSinceBecomingResponder = true;
this.props.onScroll && this.props.onScroll(e);
},

/**
* Invoke this from an `onResponderGrant` event.
*/
scrollResponderHandleResponderGrant: function(e: Event) {
scrollResponderHandleResponderGrant: function(e: ScrollEvent) {
this.state.observedScrollSinceBecomingResponder = false;
this.props.onResponderGrant && this.props.onResponderGrant(e);
this.state.becameResponderWhileAnimating = this.scrollResponderIsAnimating();
Expand All @@ -316,15 +320,15 @@ const ScrollResponderMixin = {
*
* Invoke this from an `onScrollBeginDrag` event.
*/
scrollResponderHandleScrollBeginDrag: function(e: Event) {
scrollResponderHandleScrollBeginDrag: function(e: ScrollEvent) {
FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e);
},

/**
* Invoke this from an `onScrollEndDrag` event.
*/
scrollResponderHandleScrollEndDrag: function(e: Event) {
scrollResponderHandleScrollEndDrag: function(e: ScrollEvent) {
const {velocity} = e.nativeEvent;
// - If we are animating, then this is a "drag" that is stopping the scrollview and momentum end
// will fire.
Expand All @@ -343,15 +347,15 @@ const ScrollResponderMixin = {
/**
* Invoke this from an `onMomentumScrollBegin` event.
*/
scrollResponderHandleMomentumScrollBegin: function(e: Event) {
scrollResponderHandleMomentumScrollBegin: function(e: ScrollEvent) {
this.state.lastMomentumScrollBeginTime = performanceNow();
this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e);
},

/**
* Invoke this from an `onMomentumScrollEnd` event.
*/
scrollResponderHandleMomentumScrollEnd: function(e: Event) {
scrollResponderHandleMomentumScrollEnd: function(e: ScrollEvent) {
FrameRateLogger.endScroll();
this.state.lastMomentumScrollEndTime = performanceNow();
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e);
Expand All @@ -366,9 +370,9 @@ const ScrollResponderMixin = {
* responder). The `onResponderReject` won't fire in that case - it only
* fires when a *current* responder rejects our request.
*
* @param {SyntheticEvent} e Touch Start event.
* @param {PressEvent} e Touch Start event.
*/
scrollResponderHandleTouchStart: function(e: Event) {
scrollResponderHandleTouchStart: function(e: PressEvent) {
this.state.isTouching = true;
this.props.onTouchStart && this.props.onTouchStart(e);
},
Expand All @@ -382,9 +386,9 @@ const ScrollResponderMixin = {
* responder). The `onResponderReject` won't fire in that case - it only
* fires when a *current* responder rejects our request.
*
* @param {SyntheticEvent} e Touch Start event.
* @param {PressEvent} e Touch Start event.
*/
scrollResponderHandleTouchMove: function(e: Event) {
scrollResponderHandleTouchMove: function(e: PressEvent) {
this.props.onTouchMove && this.props.onTouchMove(e);
},

Expand All @@ -409,7 +413,7 @@ const ScrollResponderMixin = {
* Components can pass what node to use by defining a `getScrollableNode`
* function otherwise `this` is used.
*/
scrollResponderGetScrollableNode: function(): any {
scrollResponderGetScrollableNode: function(): ?number {
return this.getScrollableNode
? this.getScrollableNode()
: ReactNative.findNodeHandle(this);
Expand Down Expand Up @@ -527,14 +531,14 @@ const ScrollResponderMixin = {
* This method should be used as the callback to onFocus in a TextInputs'
* parent view. Note that any module using this mixin needs to return
* the parent view's ref in getScrollViewRef() in order to use this method.
* @param {any} nodeHandle The TextInput node handle
* @param {number} nodeHandle The TextInput node handle
* @param {number} additionalOffset The scroll view's bottom "contentInset".
* Default is 0.
* @param {bool} preventNegativeScrolling Whether to allow pulling the content
* down to make it meet the keyboard's top. Default is false.
*/
scrollResponderScrollNativeHandleToKeyboard: function(
nodeHandle: any,
nodeHandle: number,
additionalOffset?: number,
preventNegativeScrollOffset?: boolean,
) {
Expand Down Expand Up @@ -584,8 +588,8 @@ const ScrollResponderMixin = {
this.preventNegativeScrollOffset = false;
},

scrollResponderTextInputFocusError: function(e: Event) {
console.error('Error measuring text field: ', e);
scrollResponderTextInputFocusError: function(msg: string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this function always being called with a string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the function is finally passed to UIManager.measureLayout as error callback.
In Java, the error callback argument is string, and in Objective-C, the callback is never called.

ref:

console.error('Error measuring text field: ', msg);
},

/**
Expand Down Expand Up @@ -667,17 +671,17 @@ const ScrollResponderMixin = {
* relevant to you. (For example, only if you receive these callbacks after
* you had explicitly focused a node etc).
*/
scrollResponderKeyboardWillShow: function(e: Event) {
scrollResponderKeyboardWillShow: function(e: KeyboardEvent) {
this.keyboardWillOpenTo = e;
this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e);
},

scrollResponderKeyboardWillHide: function(e: Event) {
scrollResponderKeyboardWillHide: function(e: KeyboardEvent) {
this.keyboardWillOpenTo = null;
this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e);
},

scrollResponderKeyboardDidShow: function(e: Event) {
scrollResponderKeyboardDidShow: function(e: KeyboardEvent) {
// TODO(7693961): The event for DidShow is not available on iOS yet.
// Use the one from WillShow and do not assign.
if (e) {
Expand All @@ -686,7 +690,7 @@ const ScrollResponderMixin = {
this.props.onKeyboardDidShow && this.props.onKeyboardDidShow(e);
},

scrollResponderKeyboardDidHide: function(e: Event) {
scrollResponderKeyboardDidHide: function(e: KeyboardEvent) {
this.keyboardWillOpenTo = null;
this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(e);
},
Expand Down