Skip to content

Commit a90e5c8

Browse files
committed
Includes responder event plugin
1 parent 1718b4b commit a90e5c8

5 files changed

Lines changed: 304 additions & 99 deletions

File tree

Lines changed: 20 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,24 @@
11
import React, {Component} from 'react'
2-
import Touchable from './vendor/Touchable'
32
import Animated from 'animated/lib/targets/react-dom'
43

5-
export default class AnimatedView extends Component {
6-
constructor( props ){
7-
super( props )
8-
this.state = this.touchableGetInitialState()
9-
}
10-
11-
/**
12-
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
13-
* defined on your component.
14-
*/
15-
touchableHandlePress(e) {
16-
this.props.onPress && this.props.onPress(e);
17-
}
18-
19-
touchableHandleActivePressIn(e) {
20-
this.props.onPressIn && this.props.onPressIn(e);
21-
}
22-
23-
touchableHandleActivePressOut(e) {
24-
this.props.onPressOut && this.props.onPressOut(e);
25-
}
26-
27-
touchableHandleLongPress(e) {
28-
this.props.onLongPress && this.props.onLongPress(e);
29-
}
30-
31-
touchableGetPressRectOffset() {
32-
return this.props.pressRetentionOffset || PRESS_RETENTION_OFFSET;
33-
}
34-
35-
touchableGetHitSlop() {
36-
return this.props.hitSlop;
37-
}
38-
39-
touchableGetHighlightDelayMS() {
40-
return this.props.delayPressIn || 0;
41-
}
42-
43-
touchableGetLongPressDelayMS() {
44-
return this.props.delayLongPress === 0 ? 0 : this.props.delayLongPress || 500;
45-
}
46-
47-
touchableGetPressOutDelayMS() {
48-
return this.props.delayPressOut || 0;
49-
}
50-
51-
render() {
52-
const {
53-
/* eslint-disable */
54-
delayLongPress,
55-
delayPressIn,
56-
delayPressOut,
57-
onLongPress,
58-
onPress,
59-
onPressIn,
60-
onPressOut,
61-
pressRetentionOffset,
62-
/* eslint-enable */
63-
...other
64-
} = this.props;
65-
66-
return (
67-
<Animated.div {...other}
68-
accessible= { this.props.accessible !== false }
69-
onKeyDown={this.touchableHandleKeyEvent}
70-
onKeyUp={this.touchableHandleKeyEvent}
71-
onResponderGrant={this.touchableHandleResponderGrant}
72-
onResponderMove={this.touchableHandleResponderMove}
73-
onResponderRelease={this.touchableHandleResponderRelease}
74-
onResponderTerminate={this.touchableHandleResponderTerminate}
75-
onResponderTerminationRequest={this.touchableHandleResponderTerminationRequest}
76-
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}>
77-
{ this.props.children }
78-
</Animated.div>
79-
)
80-
81-
return React.cloneElement(this.props.children, {
82-
...other,
83-
accessible: this.props.accessible !== false,
84-
children,
85-
onKeyDown: this.touchableHandleKeyEvent,
86-
onKeyUp: this.touchableHandleKeyEvent,
87-
onResponderGrant: this.touchableHandleResponderGrant,
88-
onResponderMove: this.touchableHandleResponderMove,
89-
onResponderRelease: this.touchableHandleResponderRelease,
90-
onResponderTerminate: this.touchableHandleResponderTerminate,
91-
onResponderTerminationRequest: this.touchableHandleResponderTerminationRequest,
92-
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
93-
style
94-
});
95-
}
4+
export default function AnimatedView(props){
5+
// Don't pass responder listeners down AnimatedView
6+
// is going to be the responder, not Animated.div
7+
const {
8+
/* eslint-disable */
9+
onResponderGrant,
10+
onResponderMove,
11+
onResponderRelease,
12+
onResponderTerminate,
13+
onResponderTerminationRequest,
14+
onStartShouldSetResponder,
15+
/* eslint-enable */
16+
...other
17+
} = props;
18+
19+
return (
20+
<Animated.div {...other}>
21+
{ props.children }
22+
</Animated.div>
23+
)
9624
}
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Animated, PanResponder } from 'react-native'
22
import injectDependencies from './InteractableView'
33

4-
let Interactable = injectDependencies( Animated, PanResponder )
5-
Interactable.View = Interactable
6-
export default Interactable
4+
let Interactable = injectDependencies(Animated, PanResponder)
5+
export default { View: Interactable }
Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
2+
import { injectEventPluginsByName } from 'react-dom/unstable-native-dependencies'
3+
import ResponderEventPlugin from './vendor/ResponderEventPlugin'
4+
15
import Animated from 'animated/lib/targets/react-dom'
26
import PanResponder from './vendor/PanResponder'
37
import injectDependencies from './InteractableView'
8+
import AnimatedView from './AnimatedView'
9+
10+
// Add responder events
11+
injectEventPluginsByName(ResponderEventPlugin)
412

5-
// Fake the View component
6-
Animated.View = Animated.div
13+
// Fake the Animated.View component
14+
Animated.View = AnimatedView
715

816
let Interactable = injectDependencies( Animated, PanResponder )
9-
Interactable.View = Interactable
10-
export default Interactable
17+
export default {View: Interactable}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// based on https://github.com/facebook/react/pull/4303/files
2+
3+
import normalizeNativeEvent from './normalizeNativeEvent';
4+
import ReactDOMUnstableNativeDependencies from 'react-dom/unstable-native-dependencies';
5+
6+
const { ResponderEventPlugin, ResponderTouchHistoryStore } = ReactDOMUnstableNativeDependencies;
7+
8+
// On older versions of React (< 16.4) we have to inject the dependencies in
9+
// order for the plugin to work properly in the browser. This version still
10+
// uses `top*` strings to identify the internal event names.
11+
// https://github.com/facebook/react/pull/12629
12+
let types = ResponderEventPlugin.eventTypes
13+
if (!types.responderMove.dependencies) {
14+
15+
const endDependencies = ['topTouchCancel', 'topTouchEnd', 'topMouseUp'];
16+
const moveDependencies = ['topTouchMove', 'topMouseMove'];
17+
const startDependencies = ['topTouchStart', 'topMouseDown'];
18+
19+
/**
20+
* Setup ResponderEventPlugin dependencies
21+
*/
22+
types.responderMove.dependencies = moveDependencies;
23+
types.responderEnd.dependencies = endDependencies;
24+
types.responderStart.dependencies = startDependencies;
25+
types.responderRelease.dependencies = endDependencies;
26+
types.responderTerminationRequest.dependencies = [];
27+
types.responderGrant.dependencies = [];
28+
types.responderReject.dependencies = [];
29+
types.responderTerminate.dependencies = [];
30+
types.moveShouldSetResponder.dependencies = moveDependencies;
31+
types.selectionChangeShouldSetResponder.dependencies = ['topSelectionChange'];
32+
types.scrollShouldSetResponder.dependencies = ['topScroll'];
33+
types.startShouldSetResponder.dependencies = startDependencies;
34+
}
35+
36+
let lastActiveTouchTimestamp = null;
37+
38+
const originalExtractEvents = ResponderEventPlugin.extractEvents;
39+
ResponderEventPlugin.extractEvents = (topLevelType, targetInst, nativeEvent, nativeEventTarget) => {
40+
const hasActiveTouches = ResponderTouchHistoryStore.touchHistory.numberActiveTouches > 0;
41+
const eventType = nativeEvent.type;
42+
43+
let shouldSkipMouseAfterTouch = false;
44+
if (eventType.indexOf('touch') > -1) {
45+
lastActiveTouchTimestamp = Date.now();
46+
} else if (lastActiveTouchTimestamp && eventType.indexOf('mouse') > -1) {
47+
const now = Date.now();
48+
shouldSkipMouseAfterTouch = now - lastActiveTouchTimestamp < 250;
49+
}
50+
51+
if (
52+
// Filter out mousemove and mouseup events when a touch hasn't started yet
53+
((eventType === 'mousemove' || eventType === 'mouseup') && !hasActiveTouches) ||
54+
// Filter out events from wheel/middle and right click.
55+
(nativeEvent.button === 1 || nativeEvent.button === 2) ||
56+
// Filter out mouse events that browsers dispatch immediately after touch events end
57+
// Prevents the REP from calling handlers twice for touch interactions.
58+
// See #802 and #932.
59+
shouldSkipMouseAfterTouch
60+
) {
61+
return;
62+
}
63+
64+
const normalizedEvent = normalizeNativeEvent(nativeEvent);
65+
66+
return originalExtractEvents.call(
67+
ResponderEventPlugin,
68+
topLevelType,
69+
targetInst,
70+
normalizedEvent,
71+
nativeEventTarget
72+
);
73+
};
74+
75+
export default ResponderEventPlugin;

0 commit comments

Comments
 (0)