mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-12 11:03:06 +00:00
ResponderTouchHistoryStore into instanciated class
Refactor ResponderTouchHistoryStore from singleton to class instantiated in ResponderSystem. This is a part of greater effort to enable support for multiple browser windows Close #2190
This commit is contained in:
committed by
Nicolas Gallagher
parent
32a4bf8e51
commit
bbffe86fd6
@@ -150,7 +150,7 @@ import {
|
||||
isPrimaryPointerDown,
|
||||
setResponderId
|
||||
} from './utils';
|
||||
import ResponderTouchHistoryStore from './ResponderTouchHistoryStore';
|
||||
import { ResponderTouchHistoryStore } from './ResponderTouchHistoryStore';
|
||||
import canUseDOM from '../canUseDom';
|
||||
|
||||
/* ------------ TYPES ------------ */
|
||||
@@ -232,6 +232,7 @@ let currentResponder: ResponderInstance = {
|
||||
node: null,
|
||||
idPath: null
|
||||
};
|
||||
const responderTouchHistoryStore = new ResponderTouchHistoryStore();
|
||||
|
||||
function changeCurrentResponder(responder: ResponderInstance) {
|
||||
currentResponder = responder;
|
||||
@@ -294,7 +295,10 @@ 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 +314,7 @@ function eventListener(domEvent: any) {
|
||||
trackedTouchCount = 0;
|
||||
}
|
||||
}
|
||||
ResponderTouchHistoryStore.recordTouchTrack(
|
||||
responderTouchHistoryStore.recordTouchTrack(
|
||||
eventType,
|
||||
responderEvent.nativeEvent
|
||||
);
|
||||
@@ -665,7 +669,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);
|
||||
}
|
||||
|
||||
@@ -11,18 +11,25 @@ import type { Touch, TouchEvent } from './ResponderEventTypes';
|
||||
import { isStartish, isMoveish, isEndish } from './ResponderEventTypes';
|
||||
|
||||
type TouchRecord = {|
|
||||
touchActive: boolean,
|
||||
startPageX: number,
|
||||
startPageY: number,
|
||||
startTimeStamp: number,
|
||||
currentPageX: number,
|
||||
currentPageY: number,
|
||||
currentTimeStamp: number,
|
||||
previousPageX: number,
|
||||
previousPageY: number,
|
||||
previousTimeStamp: number
|
||||
previousTimeStamp: number,
|
||||
startPageX: number,
|
||||
startPageY: number,
|
||||
startTimeStamp: number,
|
||||
touchActive: boolean
|
||||
|};
|
||||
|
||||
export type TouchHistory = $ReadOnly<{|
|
||||
indexOfSingleActiveTouch: number,
|
||||
mostRecentTimeStamp: number,
|
||||
numberActiveTouches: number,
|
||||
touchBank: Array<TouchRecord>
|
||||
|}>;
|
||||
|
||||
/**
|
||||
* Tracks the position and time of each active touch by `touch.identifier`. We
|
||||
* should typically only see IDs in the range of 1-20 because IDs get recycled
|
||||
@@ -31,16 +38,6 @@ type TouchRecord = {|
|
||||
|
||||
const __DEV__ = process.env.NODE_ENV !== 'production';
|
||||
const MAX_TOUCH_BANK = 20;
|
||||
const touchBank: Array<TouchRecord> = [];
|
||||
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,19 +94,19 @@ function getTouchIdentifier({ identifier }: Touch): number {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
function recordTouchStart(touch: Touch): void {
|
||||
function recordTouchStart(touch: Touch, touchHistory): void {
|
||||
const identifier = getTouchIdentifier(touch);
|
||||
const touchRecord = touchBank[identifier];
|
||||
const touchRecord = touchHistory.touchBank[identifier];
|
||||
if (touchRecord) {
|
||||
resetTouchRecord(touchRecord, touch);
|
||||
} else {
|
||||
touchBank[identifier] = createTouchRecord(touch);
|
||||
touchHistory.touchBank[identifier] = createTouchRecord(touch);
|
||||
}
|
||||
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
|
||||
}
|
||||
|
||||
function recordTouchMove(touch: Touch): void {
|
||||
const touchRecord = touchBank[getTouchIdentifier(touch)];
|
||||
function recordTouchMove(touch: Touch, touchHistory): void {
|
||||
const touchRecord = touchHistory.touchBank[getTouchIdentifier(touch)];
|
||||
if (touchRecord) {
|
||||
touchRecord.touchActive = true;
|
||||
touchRecord.previousPageX = touchRecord.currentPageX;
|
||||
@@ -123,13 +120,13 @@ function recordTouchMove(touch: Touch): void {
|
||||
console.warn(
|
||||
'Cannot record touch move without a touch start.\n',
|
||||
`Touch Move: ${printTouch(touch)}\n`,
|
||||
`Touch Bank: ${printTouchBank()}`
|
||||
`Touch Bank: ${printTouchBank(touchHistory)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function recordTouchEnd(touch: Touch): void {
|
||||
const touchRecord = touchBank[getTouchIdentifier(touch)];
|
||||
function recordTouchEnd(touch: Touch, touchHistory): void {
|
||||
const touchRecord = touchHistory.touchBank[getTouchIdentifier(touch)];
|
||||
if (touchRecord) {
|
||||
touchRecord.touchActive = false;
|
||||
touchRecord.previousPageX = touchRecord.currentPageX;
|
||||
@@ -143,7 +140,7 @@ function recordTouchEnd(touch: Touch): void {
|
||||
console.warn(
|
||||
'Cannot record touch end without a touch start.\n',
|
||||
`Touch End: ${printTouch(touch)}\n`,
|
||||
`Touch Bank: ${printTouchBank()}`
|
||||
`Touch Bank: ${printTouchBank(touchHistory)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -157,7 +154,8 @@ function printTouch(touch: Touch): string {
|
||||
});
|
||||
}
|
||||
|
||||
function printTouchBank(): string {
|
||||
function printTouchBank(touchHistory): string {
|
||||
const { touchBank } = touchHistory;
|
||||
let printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK));
|
||||
if (touchBank.length > MAX_TOUCH_BANK) {
|
||||
printed += ' (original size: ' + touchBank.length + ')';
|
||||
@@ -165,21 +163,39 @@ function printTouchBank(): string {
|
||||
return printed;
|
||||
}
|
||||
|
||||
const ResponderTouchHistoryStore = {
|
||||
export class ResponderTouchHistoryStore {
|
||||
_touchHistory = {
|
||||
touchBank: [], //Array<TouchRecord>
|
||||
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
|
||||
};
|
||||
|
||||
recordTouchTrack(topLevelType: string, nativeEvent: TouchEvent): void {
|
||||
const touchHistory = this._touchHistory;
|
||||
if (isMoveish(topLevelType)) {
|
||||
nativeEvent.changedTouches.forEach(recordTouchMove);
|
||||
nativeEvent.changedTouches.forEach((touch) =>
|
||||
recordTouchMove(touch, touchHistory)
|
||||
);
|
||||
} else if (isStartish(topLevelType)) {
|
||||
nativeEvent.changedTouches.forEach(recordTouchStart);
|
||||
nativeEvent.changedTouches.forEach((touch) =>
|
||||
recordTouchStart(touch, touchHistory)
|
||||
);
|
||||
touchHistory.numberActiveTouches = nativeEvent.touches.length;
|
||||
if (touchHistory.numberActiveTouches === 1) {
|
||||
touchHistory.indexOfSingleActiveTouch =
|
||||
nativeEvent.touches[0].identifier;
|
||||
}
|
||||
} else if (isEndish(topLevelType)) {
|
||||
nativeEvent.changedTouches.forEach(recordTouchEnd);
|
||||
nativeEvent.changedTouches.forEach((touch) =>
|
||||
recordTouchEnd(touch, touchHistory)
|
||||
);
|
||||
touchHistory.numberActiveTouches = nativeEvent.touches.length;
|
||||
if (touchHistory.numberActiveTouches === 1) {
|
||||
const { touchBank } = touchHistory;
|
||||
for (let i = 0; i < touchBank.length; i++) {
|
||||
const touchTrackToCheck = touchBank[i];
|
||||
if (touchTrackToCheck != null && touchTrackToCheck.touchActive) {
|
||||
@@ -195,9 +211,9 @@ const ResponderTouchHistoryStore = {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
touchHistory
|
||||
};
|
||||
|
||||
export default ResponderTouchHistoryStore;
|
||||
get touchHistory(): TouchHistory {
|
||||
return this._touchHistory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,13 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import type {
|
||||
ResponderTouchHistoryStore,
|
||||
TouchHistory
|
||||
} from './ResponderTouchHistoryStore';
|
||||
import type { TouchEvent } from './ResponderEventTypes';
|
||||
|
||||
import getBoundingClientRect from '../../modules/getBoundingClientRect';
|
||||
import ResponderTouchHistoryStore from './ResponderTouchHistoryStore';
|
||||
|
||||
export type ResponderEvent = {|
|
||||
bubbles: boolean,
|
||||
@@ -34,23 +37,7 @@ export type ResponderEvent = {|
|
||||
persist: () => void,
|
||||
target: ?any,
|
||||
timeStamp: number,
|
||||
touchHistory: $ReadOnly<{|
|
||||
indexOfSingleActiveTouch: number,
|
||||
mostRecentTimeStamp: number,
|
||||
numberActiveTouches: number,
|
||||
touchBank: Array<{|
|
||||
currentPageX: number,
|
||||
currentPageY: number,
|
||||
currentTimeStamp: number,
|
||||
previousPageX: number,
|
||||
previousPageY: number,
|
||||
previousTimeStamp: number,
|
||||
startPageX: number,
|
||||
startPageY: number,
|
||||
startTimeStamp: number,
|
||||
touchActive: boolean
|
||||
|}>
|
||||
|}>
|
||||
touchHistory: TouchHistory
|
||||
|};
|
||||
|
||||
const emptyFunction = () => {};
|
||||
@@ -70,7 +57,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;
|
||||
@@ -193,7 +183,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:
|
||||
|
||||
Reference in New Issue
Block a user