Doko-Demo-Doa / react-native-shake

React Native shake event detector
MIT License
274 stars 65 forks source link

Expo SDK 52 CNG Support #68

Open samducker opened 2 months ago

samducker commented 2 months ago

Hi I am trying to run the latest beta version of this library, however when I shake only the expo dev client appears.

Could you clarify if this is expected behaviour or if I should get both the expo dev client appearing and also the shake event from react native shake.

Doko-Demo-Doa commented 2 months ago

Hi @samducker I just made a quick test and it seems to work normally. You may have to run npx expo prebuild --clean and rebuild the app as it involves native code.

image
Doko-Demo-Doa commented 2 months ago

Also, the shake behavior of Android and iOS are different: On iOS, you can just fling the phone in one direction and the event fires. On Android, you can do it gently, but back and forth, for the events to be fired.

samducker commented 2 months ago

Hey @Doko-Demo-Doa unfortunately it doesn't work for me with the same implementation as you in my route layout file.

I'm on latest expo SDK with expo-router, continuous native generation mode and expo dev client.

Could you confirm if you are using latest Expo SDK with the dev client installed?

Do you have any debugging advice also?

Doko-Demo-Doa commented 2 months ago

@samducker Can you create the minimum example so I can reproduce it? In fact this lib must be used with Expo CNG because it involves native code.

I'm using latest stable Expo version, which is 51 at the moment.

image
samducker commented 1 month ago

Hi @Doko-Demo-Doa I'm sorry to report, I couldn't get this library to work maybe it was clashing with expo dev client I'm not really sure.

I produced this custom hook instead which seems to be working well,perhaps you could wrap the expo-sensors library in a future release into this library for expo users.

Sharing incase anyone else is having expo related issues for a solution.

import { useEffect, useCallback, useState } from 'react';
import { DeviceMotion } from 'expo-sensors';

export default function useShakeDetector() {
  const [isShaking, setIsShaking] = useState(false);

  const handleShake = useCallback(() => {
    console.log('Shake detected');
  }, []);

  useEffect(() => {
    const SHAKE_THRESHOLD = 800;
    const SHAKE_COOLDOWN = 1000;
    const UPDATE_INTERVAL = 100;
    let lastUpdate = 0;
    let lastShake = 0;
    let lastX = 0,
      lastY = 0,
      lastZ = 0;

    const subscription = DeviceMotion.addListener((deviceMotionData) => {
      const { x, y, z } = deviceMotionData.accelerationIncludingGravity;
      const currentTime = Date.now();

      if (currentTime - lastUpdate > UPDATE_INTERVAL) {
        const diffTime = currentTime - lastUpdate;
        lastUpdate = currentTime;

        const speed = (Math.abs(x + y + z - lastX - lastY - lastZ) / diffTime) * 10000;

        if (speed > SHAKE_THRESHOLD && currentTime - lastShake > SHAKE_COOLDOWN) {
          lastShake = currentTime;
          setIsShaking(true);
          handleShake();
          setTimeout(() => setIsShaking(false), 300);
        }

        lastX = x;
        lastY = y;
        lastZ = z;
      }
    });

    DeviceMotion.setUpdateInterval(UPDATE_INTERVAL);

    return () => {
      subscription && subscription.remove();
    };
  }, [handleShake]);

  return isShaking;
}