From 3649a503cf52feac0386b4a10aab5ef6c4ec5ca0 Mon Sep 17 00:00:00 2001 From: mottox2 Date: Wed, 21 Nov 2018 14:39:50 -0800 Subject: [PATCH] Flow TouchableNativeFeedback.android.js (#22176) Summary: Related to #22100 Turn Flow strict mode on for Libraries/Components/Touchable/TouchableNativeFeedback.android.js. Pull Request resolved: https://github.com/facebook/react-native/pull/22176 Reviewed By: TheSavior Differential Revision: D13033239 Pulled By: RSNara fbshipit-source-id: 57e89ce16040e6238e01e0437327db943a5f2581 --- Libraries/Components/Touchable/Touchable.js | 100 +++++++++++++++--- .../TouchableNativeFeedback.android.js | 13 +-- 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/Libraries/Components/Touchable/Touchable.js b/Libraries/Components/Touchable/Touchable.js index e6b8fb19cc059b..5383de2da4ef8f 100644 --- a/Libraries/Components/Touchable/Touchable.js +++ b/Libraries/Components/Touchable/Touchable.js @@ -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 */ @@ -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. * @@ -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` @@ -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, }; @@ -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, }; @@ -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 */ @@ -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 @@ -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 ( @@ -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; @@ -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 ( @@ -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]; @@ -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; @@ -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); @@ -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); @@ -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 && @@ -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; } @@ -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 (