1import React, { Component } from 'react';
2import { StyleSheet, View, StyleProp, ViewStyle } from 'react-native';
3import {
4  LongPressGestureHandler,
5  State,
6  TapGestureHandler,
7  LongPressGestureHandlerStateChangeEvent,
8  TapGestureHandlerStateChangeEvent,
9} from 'react-native-gesture-handler';
10
11interface FBState {
12  singleTap?: State;
13  longPress?: State;
14}
15
16export default class FancyButton extends Component<
17  {
18    style?: StyleProp<ViewStyle>;
19    onLongPress?: () => void;
20    onSingleTap?: () => void;
21    onDoubleTap?: () => void;
22  },
23  FBState
24> {
25  doubleTapRef = React.createRef<TapGestureHandler>();
26
27  readonly state: FBState = {};
28
29  render() {
30    return (
31      <LongPressGestureHandler minDurationMs={800} onHandlerStateChange={this._onLongPressEvent}>
32        <TapGestureHandler
33          numberOfTaps={1}
34          waitFor={this.doubleTapRef}
35          onHandlerStateChange={this._onSingleTapEvent}>
36          <TapGestureHandler
37            numberOfTaps={2}
38            ref={this.doubleTapRef}
39            onHandlerStateChange={this._onDoubleTapEvent}>
40            <View
41              style={[styles.button, this.props.style, { opacity: this._isPressed() ? 0.5 : 1 }]}>
42              {this.props.children}
43            </View>
44          </TapGestureHandler>
45        </TapGestureHandler>
46      </LongPressGestureHandler>
47    );
48  }
49
50  _isPressed = () => {
51    const { longPress, singleTap } = this.state;
52
53    // Intentionally leave out double tap
54    if (longPress === State.BEGAN || singleTap === State.BEGAN) {
55      return true;
56    } else {
57      return false;
58    }
59  };
60
61  _onLongPressEvent = (event: LongPressGestureHandlerStateChangeEvent) => {
62    const { state } = event.nativeEvent;
63    this.setState({ longPress: state });
64
65    if (state === State.ACTIVE) {
66      this.props.onLongPress && this.props.onLongPress();
67    }
68  };
69
70  _onSingleTapEvent = (event: TapGestureHandlerStateChangeEvent) => {
71    const { state } = event.nativeEvent;
72    this.setState({ singleTap: state });
73
74    if (state === State.ACTIVE) {
75      this.props.onSingleTap && this.props.onSingleTap();
76    }
77  };
78
79  _onDoubleTapEvent = (event: TapGestureHandlerStateChangeEvent) => {
80    const { state } = event.nativeEvent;
81
82    if (state === State.ACTIVE) {
83      this.props.onDoubleTap && this.props.onDoubleTap();
84    }
85  };
86}
87
88const styles = StyleSheet.create({
89  button: {
90    paddingHorizontal: 30,
91    paddingVertical: 20,
92    backgroundColor: '#cacaca',
93    borderRadius: 5,
94    alignItems: 'center',
95  },
96});
97