diff --git a/lib/types/react-types.js b/lib/types/react-types.js --- a/lib/types/react-types.js +++ b/lib/types/react-types.js @@ -4,3 +4,5 @@ export type ReactRefSetter = | { current: null | I, ... } | ((null | I) => mixed); + +export type ReactRef = { current: null | T }; diff --git a/native/chat/swipeable-message.react.js b/native/chat/swipeable-message.react.js --- a/native/chat/swipeable-message.react.js +++ b/native/chat/swipeable-message.react.js @@ -2,9 +2,13 @@ import type { IconProps } from '@expo/vector-icons'; import * as Haptics from 'expo-haptics'; +import invariant from 'invariant'; import * as React from 'react'; import { View } from 'react-native'; -import { PanGestureHandler } from 'react-native-gesture-handler'; +import { + PanGestureHandler, + type PanGestureEvent, +} from 'react-native-gesture-handler'; import Animated, { useAnimatedGestureHandler, useSharedValue, @@ -192,14 +196,25 @@ }, [triggerReply, triggerSidebar]); const translateX = useSharedValue(0); - const swipeEvent = useAnimatedGestureHandler( + const swipeEvent = useAnimatedGestureHandler( { - onStart: (event, ctx) => { + onStart: ( + event /*: PanGestureEvent */, + ctx /*: { [string]: mixed } */, + ) => { ctx.translationAtStart = translateX.value; cancelAnimation(translateX.value); }, - onActive: (event, ctx) => { - const translationX = ctx.translationAtStart + event.translationX; + onActive: ( + event /*: PanGestureEvent */, + ctx /*: { [string]: mixed } */, + ) => { + const { translationAtStart } = ctx; + invariant( + typeof translationAtStart === 'number', + 'translationAtStart should be number', + ); + const translationX = translationAtStart + event.translationX; const baseActiveTranslation = isViewer ? Math.min(translationX, 0) : Math.max(translationX, 0); @@ -222,7 +237,7 @@ } ctx.prevPastSecondaryThreshold = pastSecondaryThreshold; }, - onEnd: event => { + onEnd: (event /*: PanGestureEvent */) => { const absValue = Math.abs(translateX.value); if (absValue >= secondaryThreshold && secondaryActionExists) { runOnJS(secondaryAction)(); diff --git a/native/components/full-screen-view-modal.react.js b/native/components/full-screen-view-modal.react.js --- a/native/components/full-screen-view-modal.react.js +++ b/native/components/full-screen-view-modal.react.js @@ -14,12 +14,17 @@ PanGestureHandler, TapGestureHandler, State as GestureState, + type PinchGestureEvent, + type PanGestureEvent, + type TapGestureEvent, } from 'react-native-gesture-handler'; import Orientation from 'react-native-orientation-locker'; import Animated from 'react-native-reanimated'; +import type { EventResult } from 'react-native-reanimated'; import { SafeAreaView } from 'react-native-safe-area-context'; import { type Dimensions } from 'lib/types/media-types.js'; +import type { ReactRef } from 'lib/types/react-types.js'; import SWMansionIcon from './swmansion-icon.react.js'; import ConnectedStatusBar from '../connected-status-bar.react.js'; @@ -187,23 +192,35 @@ imageWidth: Value; imageHeight: Value; - pinchHandler = React.createRef(); - panHandler = React.createRef(); - singleTapHandler = React.createRef(); - doubleTapHandler = React.createRef(); - handlerRefs = [ + pinchHandler: ReactRef = React.createRef(); + panHandler: ReactRef = React.createRef(); + singleTapHandler: ReactRef = React.createRef(); + doubleTapHandler: ReactRef = React.createRef(); + handlerRefs: $ReadOnlyArray< + | ReactRef + | ReactRef + | ReactRef, + > = [ this.pinchHandler, this.panHandler, this.singleTapHandler, this.doubleTapHandler, ]; - beforeDoubleTapRefs; - beforeSingleTapRefs; - - pinchEvent; - panEvent; - singleTapEvent; - doubleTapEvent; + beforeDoubleTapRefs: $ReadOnlyArray< + | ReactRef + | ReactRef + | ReactRef, + >; + beforeSingleTapRefs: $ReadOnlyArray< + | ReactRef + | ReactRef + | ReactRef, + >; + + pinchEvent: EventResult; + panEvent: EventResult; + singleTapEvent: EventResult; + doubleTapEvent: EventResult; scale: Node; x: Node; @@ -244,7 +261,7 @@ const panVelocityY = new Value(0); const panAbsoluteX = new Value(0); const panAbsoluteY = new Value(0); - this.panEvent = event([ + this.panEvent = event([ { nativeEvent: { state: panState, @@ -283,7 +300,7 @@ const pinchScale = new Value(1); const pinchFocalX = new Value(0); const pinchFocalY = new Value(0); - this.pinchEvent = event([ + this.pinchEvent = event([ { nativeEvent: { state: pinchState, @@ -299,7 +316,7 @@ const singleTapState = new Value(-1); const singleTapX = new Value(0); const singleTapY = new Value(0); - this.singleTapEvent = event([ + this.singleTapEvent = event([ { nativeEvent: { state: singleTapState, @@ -313,7 +330,7 @@ const doubleTapState = new Value(-1); const doubleTapX = new Value(0); const doubleTapY = new Value(0); - this.doubleTapEvent = event([ + this.doubleTapEvent = event([ { nativeEvent: { state: doubleTapState, diff --git a/native/components/gesture-touchable-opacity.react.js b/native/components/gesture-touchable-opacity.react.js --- a/native/components/gesture-touchable-opacity.react.js +++ b/native/components/gesture-touchable-opacity.react.js @@ -6,6 +6,8 @@ LongPressGestureHandler, TapGestureHandler, State as GestureState, + type LongPressGestureEvent, + type TapGestureEvent, } from 'react-native-gesture-handler'; import Animated, { EasingNode } from 'react-native-reanimated'; @@ -81,7 +83,7 @@ const tapState = useValue(-1); const longPressEvent = React.useMemo( () => - event([ + event([ { nativeEvent: { state: longPressState, @@ -92,7 +94,7 @@ ); const tapEvent = React.useMemo( () => - event([ + event([ { nativeEvent: { state: tapState, diff --git a/native/flow-typed/npm/react-native-gesture-handler_v2.x.x.js b/native/flow-typed/npm/react-native-gesture-handler_v2.x.x.js --- a/native/flow-typed/npm/react-native-gesture-handler_v2.x.x.js +++ b/native/flow-typed/npm/react-native-gesture-handler_v2.x.x.js @@ -379,8 +379,8 @@ ...$EventHandlers, id?: string, enabled?: boolean, - waitFor?: React$Ref | Array>, - simultaneousHandlers?: React$Ref | Array>, + waitFor?: React$Ref | $ReadOnlyArray>, + simultaneousHandlers?: React$Ref | $ReadOnlyArray>, shouldCancelWhenOutside?: boolean, minPointers?: number, hitSlop?: HitSlop, @@ -403,6 +403,14 @@ ///////////////////////////////////////////////////////////////////////////// // Tap + declare export type TapGestureEvent = { + +x: number, + +y: number, + +absoluteX: number, + +absoluteY: number, + ... + }; + declare export type TapGestureHandlerProps = $GestureHandlerProps< { maxDurationMs?: number, @@ -412,13 +420,7 @@ minPointers?: number, ... }, - { - x: number, - y: number, - absoluteX: number, - absoluteY: number, - ... - } + TapGestureEvent, >; declare export class TapGestureHandler extends React$Component {} @@ -463,19 +465,21 @@ ///////////////////////////////////////////////////////////////////////////// // LongPress + declare export type LongPressGestureEvent = { + +x: number, + +y: number, + +absoluteX: number, + +absoluteY: number, + ... + }; + declare export type LongPressGestureHandlerProps = $GestureHandlerProps< { minDurationMs?: number, maxDist?: number, ... }, - { - x: number, - y: number, - absoluteX: number, - absoluteY: number, - ... - } + LongPressGestureEvent, >; declare export class LongPressGestureHandler extends React$Component {} @@ -483,6 +487,18 @@ ///////////////////////////////////////////////////////////////////////////// // PanGesture + declare export type PanGestureEvent = { + +x: number, + +y: number, + +absoluteX: number, + +absoluteY: number, + +translationX: number, + +translationY: number, + +velocityX: number, + +velocityY: number, + ... + }; + declare export type PanGestureHandlerProps = $GestureHandlerProps< { activeOffsetY?: number | [number, number], @@ -498,17 +514,7 @@ avgTouches?: boolean, ... }, - { - x: number, - y: number, - absoluteX: number, - absoluteY: number, - translationX: number, - translationY: number, - velocityX: number, - velocityY: number, - ... - } + PanGestureEvent, >; declare export class PanGestureHandler extends React$Component {} @@ -516,15 +522,17 @@ ///////////////////////////////////////////////////////////////////////////// // Pinch + declare export type PinchGestureEvent = { + +scale: number, + +focalX: number, + +focalY: number, + +velocity: number, + ... + }; + declare export type PinchGestureHandlerProps = $GestureHandlerProps< { ... }, - { - scale: number, - focalX: number, - focalY: number, - velocity: number, - ... - } + PinchGestureEvent, >; declare export class PinchGestureHandler extends React$Component {} diff --git a/native/flow-typed/npm/react-native-reanimated_v2.x.x.js b/native/flow-typed/npm/react-native-reanimated_v2.x.x.js --- a/native/flow-typed/npm/react-native-reanimated_v2.x.x.js +++ b/native/flow-typed/npm/react-native-reanimated_v2.x.x.js @@ -447,7 +447,7 @@ | GestureStateActive | GestureStateEnd; - declare type $Event = { + declare export type $Event = { handlerTag: number, numberOfPointers: number, state: GestureState, @@ -456,11 +456,16 @@ ... }; + declare export type EventResult = $Event> = + $SyntheticEvent => void; + declare type ToValue = (val: mixed) => ValueImpl; - declare type Event = >(defs: $ReadOnlyArray<{ - +nativeEvent: $Shape<$ObjMap>, - ... - }>) => $SyntheticEvent => void; + declare type Event = = $Event>( + defs: $ReadOnlyArray<{ + +nativeEvent: $Shape<$ObjMap>, + ... + }>, + ) => EventResult; declare type UseValue = (initialVal: number) => ValueImpl; @@ -469,7 +474,7 @@ context: {| [name: string]: mixed |}, ) => mixed; - declare type UseAnimatedGestureHandler = >( + declare type UseAnimatedGestureHandler = = $Event>( callbacks: $Shape<{| +onStart: AnimatedGestureHandlerEventCallback, +onActive: AnimatedGestureHandlerEventCallback, @@ -479,7 +484,7 @@ +onFinish: AnimatedGestureHandlerEventCallback, |}>, dependencies?: $ReadOnlyArray, - ) => E; + ) => $SyntheticEvent => mixed; declare export type SharedValue = { value: T, diff --git a/native/media/video-playback-modal.react.js b/native/media/video-playback-modal.react.js --- a/native/media/video-playback-modal.react.js +++ b/native/media/video-playback-modal.react.js @@ -6,7 +6,10 @@ import { useState } from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import filesystem from 'react-native-fs'; -import { TapGestureHandler } from 'react-native-gesture-handler'; +import { + TapGestureHandler, + type TapGestureEvent, +} from 'react-native-gesture-handler'; import * as Progress from 'react-native-progress'; import Animated from 'react-native-reanimated'; import { SafeAreaView } from 'react-native-safe-area-context'; @@ -232,7 +235,7 @@ const singleTapEvent = React.useMemo( () => - event([ + event([ { nativeEvent: { state: singleTapState,