Giphy / giphy-react-native-sdk

GIPHY React Native SDK
https://developers.giphy.com
Apache License 2.0
67 stars 25 forks source link

Attribution tooltip appearing over GiphyMediaView on other gestures than long press, such as rotation, pinch, pan. Expo / Android / React Native Gesture Handler #165

Open oliverjarvis opened 6 months ago

oliverjarvis commented 6 months ago

🐛 Bug Report

Android Simulator: The attribution tooltip that appears on long presses over the MediaViews appears when the object is panned, rotated, pinched etc. This may be caused somehow by React-Native-Gesture-Handler, but I don't think so; A long press gesture handler attached to the component fires before the attribution bubble appears.

To Reproduce

Wrap the GiphyMediaView component in an Animated.View with a react-native-gesture-handler gesture component attached to it. Example shown in the code at the bottom.

Expected behavior

I expect the attribution tooltip to appear exclusively on longpress gestures, and not count longpress gestures that stem from pans, rotations, pinches.

The same code works fine on iOS.

Actual Behavior

The tooltip appears on any gestures. Pans, Rotations, Pinches obviously result in holding down the object for a longer period of time, which on android seems to trigger the long press gesture detector.

Your Environment

Reproducible Demo

import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';

export default function StudioScreen() {
  function GiphyObject() {

    // VARIABLES
    const offset = useSharedValue({ x: 0, y: 0 });

    const rotation = useSharedValue(0);
    const savedRotation = useSharedValue(1);

    const scale = useSharedValue(1);
    const savedScale = useSharedValue(1);

    // ROTATION, PINCH and PAN GESTURES
    const rotationGesture = Gesture.Rotation()
      .onUpdate((e) => {
        rotation.value = savedRotation.value + e.rotation;
      })
      .onEnd(() => {
        savedRotation.value = rotation.value;
      })

    const pinchGesture = Gesture.Pinch()
      .onUpdate((e) => {
        scale.value = savedScale.value * e.scale;
      })
      .onEnd(() => {
        savedScale.value = scale.value;
      })

    const gesture = Gesture.Pan()
      .onBegin(() => {
        'worklet';
      })
      .onChange((e) => {
        'worklet';
        offset.value = {
          x: e.changeX + offset.value.x,
          y: e.changeY + offset.value.y,
        };
    })

    const animatedStyles = useAnimatedStyle(() => {
      return {
        transform: [
          { translateX: offset.value.x },
          { translateY: offset.value.y },
          { scale: scale.value },
          { rotateZ: `${(rotation.value / Math.PI) * 180}deg` }
        ],
      };
    });  

    const composed = Gesture.Simultaneous(gesture, rotationGesture, pinchGesture, longpressGesture);

    return (
      <GestureDetector gesture={composed}>
        <Animated.View style={[animatedStyles]}>
            {media && <GiphyMediaView
              className='h-full w-full'
              media={media}
              style={{ aspectRatio: media.aspectRatio }}
            />}
        </Animated.View>
      </GestureDetector>
    );
  }

return (<View className='bg-white w-full h-full rounded-3xl overflow-hidden'>
      <GiphyObject/>
   </View>);
}
ALexanderLonsky commented 6 months ago

Hey @oliverjarvis , Thanks for flagging this issue.

I have reproduced it on an Android device. The tooltip is indeed triggered while dragging the view across the screen. We use setOnLongClickListener in the native component, so I believe the problem lies between the gesture handlers and the native view implementation. I can revisit this issue later, but I cannot promise a quick fix.

If it's critical to you, you may want to consider building your own custom view to display a gif url.

oliverjarvis commented 6 months ago

I'll do as you advise and implement a solution myself. Thank you replicating it Alexander!