diff --git a/packages/react-native-web/src/modules/useResponderEvents/ResponderSystem.js b/packages/react-native-web/src/modules/useResponderEvents/ResponderSystem.js index b9aaad703..d2350cf7a 100644 --- a/packages/react-native-web/src/modules/useResponderEvents/ResponderSystem.js +++ b/packages/react-native-web/src/modules/useResponderEvents/ResponderSystem.js @@ -232,6 +232,7 @@ let currentResponder: ResponderInstance = { node: null, idPath: null }; +const responderTouchHistoryStore = new ResponderTouchHistoryStore(); function changeCurrentResponder(responder: ResponderInstance) { currentResponder = responder; @@ -294,7 +295,7 @@ function eventListener(domEvent: any) { const isEndEvent = isEndish(eventType); const isScrollEvent = isScroll(eventType); const isSelectionChangeEvent = isSelectionChange(eventType); - const responderEvent = createResponderEvent(domEvent); + const responderEvent = createResponderEvent(domEvent, responderTouchHistoryStore); /** * Record the state of active pointers @@ -310,7 +311,7 @@ function eventListener(domEvent: any) { trackedTouchCount = 0; } } - ResponderTouchHistoryStore.recordTouchTrack(eventType, responderEvent.nativeEvent); + responderTouchHistoryStore.recordTouchTrack(eventType, responderEvent.nativeEvent); } /** @@ -646,7 +647,7 @@ export function terminateResponder() { if (id != null && node != null) { const { onResponderTerminate } = getResponderConfig(id); if (onResponderTerminate != null) { - const event = createResponderEvent({}); + const event = createResponderEvent({}, responderTouchHistoryStore); event.currentTarget = node; onResponderTerminate(event); } diff --git a/packages/react-native-web/src/modules/useResponderEvents/ResponderTouchHistoryStore.js b/packages/react-native-web/src/modules/useResponderEvents/ResponderTouchHistoryStore.js index 07d97dc02..4061019c5 100644 --- a/packages/react-native-web/src/modules/useResponderEvents/ResponderTouchHistoryStore.js +++ b/packages/react-native-web/src/modules/useResponderEvents/ResponderTouchHistoryStore.js @@ -31,16 +31,6 @@ type TouchRecord = {| const __DEV__ = process.env.NODE_ENV !== 'production'; const MAX_TOUCH_BANK = 20; -const touchBank: Array = []; -const touchHistory = { - touchBank, - numberActiveTouches: 0, - // If there is only one active touch, we remember its location. This prevents - // us having to loop through all of the touches all the time in the most - // common case. - indexOfSingleActiveTouch: -1, - mostRecentTimeStamp: 0 -}; function timestampForTouch(touch: Touch): number { // The legacy internal implementation provides "timeStamp", which has been @@ -97,106 +87,117 @@ function getTouchIdentifier({ identifier }: Touch): number { return identifier; } -function recordTouchStart(touch: Touch): void { - const identifier = getTouchIdentifier(touch); - const touchRecord = touchBank[identifier]; - if (touchRecord) { - resetTouchRecord(touchRecord, touch); - } else { - touchBank[identifier] = createTouchRecord(touch); - } - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); -} +export default class ResponderTouchHistoryStore { + _touchBank: Array = []; + _touchHistory = { + touchBank: this._touchBank, + numberActiveTouches: 0, + // If there is only one active touch, we remember its location. This prevents + // us having to loop through all of the touches all the time in the most + // common case. + indexOfSingleActiveTouch: -1, + mostRecentTimeStamp: 0 + }; -function recordTouchMove(touch: Touch): void { - const touchRecord = touchBank[getTouchIdentifier(touch)]; - if (touchRecord) { - touchRecord.touchActive = true; - touchRecord.previousPageX = touchRecord.currentPageX; - touchRecord.previousPageY = touchRecord.currentPageY; - touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; - touchRecord.currentPageX = touch.pageX; - touchRecord.currentPageY = touch.pageY; - touchRecord.currentTimeStamp = timestampForTouch(touch); - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); - } else { - console.warn( - 'Cannot record touch move without a touch start.\n', - `Touch Move: ${printTouch(touch)}\n`, - `Touch Bank: ${printTouchBank()}` - ); - } -} + _recordTouchStart = (touch: Touch): void => { + const identifier = getTouchIdentifier(touch); + const touchRecord = this._touchBank[identifier]; + if (touchRecord) { + resetTouchRecord(touchRecord, touch); + } else { + this._touchBank[identifier] = createTouchRecord(touch); + } + this._touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + }; -function recordTouchEnd(touch: Touch): void { - const touchRecord = touchBank[getTouchIdentifier(touch)]; - if (touchRecord) { - touchRecord.touchActive = false; - touchRecord.previousPageX = touchRecord.currentPageX; - touchRecord.previousPageY = touchRecord.currentPageY; - touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; - touchRecord.currentPageX = touch.pageX; - touchRecord.currentPageY = touch.pageY; - touchRecord.currentTimeStamp = timestampForTouch(touch); - touchHistory.mostRecentTimeStamp = timestampForTouch(touch); - } else { - console.warn( - 'Cannot record touch end without a touch start.\n', - `Touch End: ${printTouch(touch)}\n`, - `Touch Bank: ${printTouchBank()}` - ); - } -} + _recordTouchMove = (touch: Touch): void => { + const touchRecord = this._touchBank[getTouchIdentifier(touch)]; + if (touchRecord) { + touchRecord.touchActive = true; + touchRecord.previousPageX = touchRecord.currentPageX; + touchRecord.previousPageY = touchRecord.currentPageY; + touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + this._touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } else { + console.warn( + 'Cannot record touch move without a touch start.\n', + `Touch Move: ${this._printTouch(touch)}\n`, + `Touch Bank: ${this._printTouchBank()}` + ); + } + }; -function printTouch(touch: Touch): string { - return JSON.stringify({ - identifier: touch.identifier, - pageX: touch.pageX, - pageY: touch.pageY, - timestamp: timestampForTouch(touch) - }); -} + _recordTouchEnd = (touch: Touch): void => { + const touchRecord = this._touchBank[getTouchIdentifier(touch)]; + if (touchRecord) { + touchRecord.touchActive = false; + touchRecord.previousPageX = touchRecord.currentPageX; + touchRecord.previousPageY = touchRecord.currentPageY; + touchRecord.previousTimeStamp = touchRecord.currentTimeStamp; + touchRecord.currentPageX = touch.pageX; + touchRecord.currentPageY = touch.pageY; + touchRecord.currentTimeStamp = timestampForTouch(touch); + this._touchHistory.mostRecentTimeStamp = timestampForTouch(touch); + } else { + console.warn( + 'Cannot record touch end without a touch start.\n', + `Touch End: ${this._printTouch(touch)}\n`, + `Touch Bank: ${this._printTouchBank()}` + ); + } + }; -function printTouchBank(): string { - let printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK)); - if (touchBank.length > MAX_TOUCH_BANK) { - printed += ' (original size: ' + touchBank.length + ')'; + _printTouch(touch: Touch): string { + return JSON.stringify({ + identifier: touch.identifier, + pageX: touch.pageX, + pageY: touch.pageY, + timestamp: timestampForTouch(touch) + }); + } + + _printTouchBank(): string { + let printed = JSON.stringify(this._touchBank.slice(0, MAX_TOUCH_BANK)); + if (this._touchBank.length > MAX_TOUCH_BANK) { + printed += ' (original size: ' + this._touchBank.length + ')'; + } + return printed; } - return printed; -} -const ResponderTouchHistoryStore = { recordTouchTrack(topLevelType: string, nativeEvent: TouchEvent): void { if (isMoveish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchMove); + nativeEvent.changedTouches.forEach(this._recordTouchMove); } else if (isStartish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchStart); - touchHistory.numberActiveTouches = nativeEvent.touches.length; - if (touchHistory.numberActiveTouches === 1) { - touchHistory.indexOfSingleActiveTouch = nativeEvent.touches[0].identifier; + nativeEvent.changedTouches.forEach(this._recordTouchStart); + this._touchHistory.numberActiveTouches = nativeEvent.touches.length; + if (this._touchHistory.numberActiveTouches === 1) { + this._touchHistory.indexOfSingleActiveTouch = nativeEvent.touches[0].identifier; } } else if (isEndish(topLevelType)) { - nativeEvent.changedTouches.forEach(recordTouchEnd); - touchHistory.numberActiveTouches = nativeEvent.touches.length; - if (touchHistory.numberActiveTouches === 1) { - for (let i = 0; i < touchBank.length; i++) { - const touchTrackToCheck = touchBank[i]; + nativeEvent.changedTouches.forEach(this._recordTouchEnd); + this._touchHistory.numberActiveTouches = nativeEvent.touches.length; + if (this._touchHistory.numberActiveTouches === 1) { + for (let i = 0; i < this._touchBank.length; i++) { + const touchTrackToCheck = this._touchBank[i]; if (touchTrackToCheck != null && touchTrackToCheck.touchActive) { - touchHistory.indexOfSingleActiveTouch = i; + this._touchHistory.indexOfSingleActiveTouch = i; break; } } if (__DEV__) { - const activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; + const activeRecord = this._touchBank[this._touchHistory.indexOfSingleActiveTouch]; if (!(activeRecord != null && activeRecord.touchActive)) { console.error('Cannot find single active touch.'); } } } } - }, - - touchHistory -}; + } -export default ResponderTouchHistoryStore; + get touchHistory() { + return this._touchHistory; + } +} diff --git a/packages/react-native-web/src/modules/useResponderEvents/createResponderEvent.js b/packages/react-native-web/src/modules/useResponderEvents/createResponderEvent.js index b7a686bdc..c8ae4b6d5 100644 --- a/packages/react-native-web/src/modules/useResponderEvents/createResponderEvent.js +++ b/packages/react-native-web/src/modules/useResponderEvents/createResponderEvent.js @@ -10,7 +10,7 @@ import type { TouchEvent } from './ResponderEventTypes'; import getBoundingClientRect from '../../modules/getBoundingClientRect'; -import ResponderTouchHistoryStore from './ResponderTouchHistoryStore'; +import type ResponderTouchHistoryStore from './ResponderTouchHistoryStore'; export type ResponderEvent = {| bubbles: boolean, @@ -70,7 +70,10 @@ function normalizeIdentifier(identifier) { * Converts a native DOM event to a ResponderEvent. * Mouse events are transformed into fake touch events. */ -export default function createResponderEvent(domEvent: any): ResponderEvent { +export default function createResponderEvent( + domEvent: any, + responderTouchHistoryStore: ResponderTouchHistoryStore +): ResponderEvent { let rect; let propagationWasStopped = false; let changedTouches; @@ -182,7 +185,7 @@ export default function createResponderEvent(domEvent: any): ResponderEvent { }, target: domEvent.target, timeStamp: timestamp, - touchHistory: ResponderTouchHistoryStore.touchHistory + touchHistory: responderTouchHistoryStore.touchHistory }; // Using getters and functions serves two purposes: