Skip to content

Commit

Permalink
Flow TouchableNativeFeedback.android.js (#22176)
Browse files Browse the repository at this point in the history
Summary:
Related to #22100

Turn Flow strict mode on for Libraries/Components/Touchable/TouchableNativeFeedback.android.js.
Pull Request resolved: #22176

Reviewed By: TheSavior

Differential Revision: D13033239

Pulled By: RSNara

fbshipit-source-id: 57e89ce16040e6238e01e0437327db943a5f2581
  • Loading branch information
mottox2 authored and facebook-github-bot committed Nov 21, 2018
1 parent 6fa997d commit 3649a50
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 23 deletions.
100 changes: 83 additions & 17 deletions Libraries/Components/Touchable/Touchable.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/

Expand All @@ -23,6 +24,9 @@ const View = require('View');
const keyMirror = require('fbjs/lib/keyMirror');
const normalizeColor = require('normalizeColor');

import type {PressEvent} from 'CoreEventTypes';
import type {EdgeInsetsProp} from 'EdgeInsetsPropType';

/**
* `Touchable`: Taps done right.
*
Expand Down Expand Up @@ -111,6 +115,7 @@ const normalizeColor = require('normalizeColor');
/**
* Touchable states.
*/

const States = keyMirror({
NOT_RESPONDER: null, // Not the responder
RESPONDER_INACTIVE_PRESS_IN: null, // Responder, inactive, in the `PressRect`
Expand All @@ -122,10 +127,33 @@ const States = keyMirror({
ERROR: null,
});

/**
type State =
| typeof States.NOT_RESPONDER
| typeof States.RESPONDER_INACTIVE_PRESS_IN
| typeof States.RESPONDER_INACTIVE_PRESS_OUT
| typeof States.RESPONDER_ACTIVE_PRESS_IN
| typeof States.RESPONDER_ACTIVE_PRESS_OUT
| typeof States.RESPONDER_ACTIVE_LONG_PRESS_IN
| typeof States.RESPONDER_ACTIVE_LONG_PRESS_OUT
| typeof States.ERROR;

/*
* Quick lookup map for states that are considered to be "active"
*/

const baseStatesConditions = {
NOT_RESPONDER: false,
RESPONDER_INACTIVE_PRESS_IN: false,
RESPONDER_INACTIVE_PRESS_OUT: false,
RESPONDER_ACTIVE_PRESS_IN: false,
RESPONDER_ACTIVE_PRESS_OUT: false,
RESPONDER_ACTIVE_LONG_PRESS_IN: false,
RESPONDER_ACTIVE_LONG_PRESS_OUT: false,
ERROR: false,
};

const IsActive = {
...baseStatesConditions,
RESPONDER_ACTIVE_PRESS_OUT: true,
RESPONDER_ACTIVE_PRESS_IN: true,
};
Expand All @@ -135,12 +163,14 @@ const IsActive = {
* therefore eligible to result in a "selection" if the press stops.
*/
const IsPressingIn = {
...baseStatesConditions,
RESPONDER_INACTIVE_PRESS_IN: true,
RESPONDER_ACTIVE_PRESS_IN: true,
RESPONDER_ACTIVE_LONG_PRESS_IN: true,
};

const IsLongPressingIn = {
...baseStatesConditions,
RESPONDER_ACTIVE_LONG_PRESS_IN: true,
};

Expand All @@ -157,6 +187,15 @@ const Signals = keyMirror({
LONG_PRESS_DETECTED: null,
});

type Signal =
| typeof Signals.DELAY
| typeof Signals.RESPONDER_GRANT
| typeof Signals.RESPONDER_RELEASE
| typeof Signals.RESPONDER_TERMINATED
| typeof Signals.ENTER_PRESS_RECT
| typeof Signals.LEAVE_PRESS_RECT
| typeof Signals.LONG_PRESS_DETECTED;

/**
* Mapping from States x Signals => States
*/
Expand Down Expand Up @@ -391,7 +430,7 @@ const TouchableMixin = {
* @param {SyntheticEvent} e Synthetic event from event system.
*
*/
touchableHandleResponderGrant: function(e) {
touchableHandleResponderGrant: function(e: PressEvent) {
const dispatchID = e.currentTarget;
// Since e is used in a callback invoked on another event loop
// (as in setTimeout etc), we need to call e.persist() on the
Expand Down Expand Up @@ -432,21 +471,21 @@ const TouchableMixin = {
/**
* Place as callback for a DOM element's `onResponderRelease` event.
*/
touchableHandleResponderRelease: function(e) {
touchableHandleResponderRelease: function(e: PressEvent) {
this._receiveSignal(Signals.RESPONDER_RELEASE, e);
},

/**
* Place as callback for a DOM element's `onResponderTerminate` event.
*/
touchableHandleResponderTerminate: function(e) {
touchableHandleResponderTerminate: function(e: PressEvent) {
this._receiveSignal(Signals.RESPONDER_TERMINATED, e);
},

/**
* Place as callback for a DOM element's `onResponderMove` event.
*/
touchableHandleResponderMove: function(e) {
touchableHandleResponderMove: function(e: PressEvent) {
// Not enough time elapsed yet, wait for highlight -
// this is just a perf optimization.
if (
Expand Down Expand Up @@ -633,7 +672,14 @@ const TouchableMixin = {
UIManager.measure(tag, this._handleQueryLayout);
},

_handleQueryLayout: function(l, t, w, h, globalX, globalY) {
_handleQueryLayout: function(
l: number,
t: number,
w: number,
h: number,
globalX: number,
globalY: number,
) {
//don't do anything UIManager failed to measure node
if (!l && !t && !w && !h && !globalX && !globalY) {
return;
Expand All @@ -652,12 +698,12 @@ const TouchableMixin = {
);
},

_handleDelay: function(e) {
_handleDelay: function(e: PressEvent) {
this.touchableDelayTimeout = null;
this._receiveSignal(Signals.DELAY, e);
},

_handleLongDelay: function(e) {
_handleLongDelay: function(e: PressEvent) {
this.longPressDelayTimeout = null;
const curState = this.state.touchable.touchState;
if (
Expand Down Expand Up @@ -685,7 +731,7 @@ const TouchableMixin = {
* @throws Error if invalid state transition or unrecognized signal.
* @sideeffects
*/
_receiveSignal: function(signal, e) {
_receiveSignal: function(signal: Signal, e: PressEvent) {
const responderID = this.state.touchable.responderID;
const curState = this.state.touchable.touchState;
const nextState = Transitions[curState] && Transitions[curState][signal];
Expand Down Expand Up @@ -725,14 +771,14 @@ const TouchableMixin = {
this.longPressDelayTimeout = null;
},

_isHighlight: function(state) {
_isHighlight: function(state: State) {
return (
state === States.RESPONDER_ACTIVE_PRESS_IN ||
state === States.RESPONDER_ACTIVE_LONG_PRESS_IN
);
},

_savePressInLocation: function(e) {
_savePressInLocation: function(e: PressEvent) {
const touch = TouchEventUtils.extractSingleTouch(e.nativeEvent);
const pageX = touch && touch.pageX;
const pageY = touch && touch.pageY;
Expand All @@ -741,7 +787,12 @@ const TouchableMixin = {
this.pressInLocation = {pageX, pageY, locationX, locationY};
},

_getDistanceBetweenPoints: function(aX, aY, bX, bY) {
_getDistanceBetweenPoints: function(
aX: number,
aY: number,
bX: number,
bY: number,
) {
const deltaX = aX - bX;
const deltaY = aY - bY;
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
Expand All @@ -758,7 +809,12 @@ const TouchableMixin = {
* @param {Event} e Native event.
* @sideeffects
*/
_performSideEffectsForTransition: function(curState, nextState, signal, e) {
_performSideEffectsForTransition: function(
curState: State,
nextState: State,
signal: Signal,
e: PressEvent,
) {
const curIsHighlight = this._isHighlight(curState);
const newIsHighlight = this._isHighlight(nextState);

Expand Down Expand Up @@ -813,12 +869,12 @@ const TouchableMixin = {
UIManager.playTouchSound();
},

_startHighlight: function(e) {
_startHighlight: function(e: PressEvent) {
this._savePressInLocation(e);
this.touchableHandleActivePressIn && this.touchableHandleActivePressIn(e);
},

_endHighlight: function(e) {
_endHighlight: function(e: PressEvent) {
if (this.touchableHandleActivePressOut) {
if (
this.touchableGetPressOutDelayMS &&
Expand All @@ -840,7 +896,13 @@ const Touchable = {
/**
* Renders a debugging overlay to visualize touch target with hitSlop (might not work on Android).
*/
renderDebugView: ({color, hitSlop}) => {
renderDebugView: ({
color,
hitSlop,
}: {
color: string | number,
hitSlop: EdgeInsetsProp,
}) => {
if (!Touchable.TOUCH_TARGET_DEBUG) {
return null;
}
Expand All @@ -854,8 +916,12 @@ const Touchable = {
for (const key in hitSlop) {
debugHitSlopStyle[key] = -hitSlop[key];
}
const normalizedColor = normalizeColor(color);
if (typeof normalizedColor !== 'number') {
return null;
}
const hexColor =
'#' + ('00000000' + normalizeColor(color).toString(16)).substr(-8);
'#' + ('00000000' + normalizedColor.toString(16)).substr(-8);
return (
<View
pointerEvents="none"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/

Expand All @@ -22,6 +23,8 @@ const createReactClass = require('create-react-class');
const ensurePositiveDelayProps = require('ensurePositiveDelayProps');
const processColor = require('processColor');

import type {PressEvent} from 'CoreEventTypes';

const rippleBackgroundPropType = PropTypes.shape({
type: PropTypes.oneOf(['RippleAndroid']),
color: PropTypes.number,
Expand All @@ -38,8 +41,6 @@ const backgroundPropType = PropTypes.oneOfType([
themeAttributeBackgroundPropType,
]);

type Event = Object;

const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};

/**
Expand Down Expand Up @@ -167,7 +168,7 @@ const TouchableNativeFeedback = createReactClass({
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
* defined on your component.
*/
touchableHandleActivePressIn: function(e: Event) {
touchableHandleActivePressIn: function(e: PressEvent) {
this.props.onPressIn && this.props.onPressIn(e);
this._dispatchPressedStateChange(true);
if (this.pressInLocation) {
Expand All @@ -178,16 +179,16 @@ const TouchableNativeFeedback = createReactClass({
}
},

touchableHandleActivePressOut: function(e: Event) {
touchableHandleActivePressOut: function(e: PressEvent) {
this.props.onPressOut && this.props.onPressOut(e);
this._dispatchPressedStateChange(false);
},

touchableHandlePress: function(e: Event) {
touchableHandlePress: function(e: PressEvent) {
this.props.onPress && this.props.onPress(e);
},

touchableHandleLongPress: function(e: Event) {
touchableHandleLongPress: function(e: PressEvent) {
this.props.onLongPress && this.props.onLongPress(e);
},

Expand Down

0 comments on commit 3649a50

Please sign in to comment.