Skip to content

Commit

Permalink
Add react-native-turbo-haptics (#6264)
Browse files Browse the repository at this point in the history
  • Loading branch information
christianbaroni authored Nov 19, 2024
1 parent 3324ea5 commit 9bf4998
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 43 deletions.
25 changes: 25 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,27 @@ PODS:
- TOCropViewController (2.7.4)
- ToolTipMenu (5.2.1):
- React
- TurboHaptics (1.0.4):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.01.01.00)
- RCTRequired
- RCTTypeSafety
- React-Codegen
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-NativeModulesApple
- React-RCTFabric
- React-rendererdebug
- React-utils
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- VisionCamera (4.4.2):
- VisionCamera/Core (= 4.4.2)
- VisionCamera/React (= 4.4.2)
Expand Down Expand Up @@ -2035,6 +2056,7 @@ DEPENDENCIES:
- TcpSockets (from `../node_modules/react-native-tcp`)
- TOCropViewController (~> 2.7.4)
- ToolTipMenu (from `../node_modules/react-native-tooltip`)
- TurboHaptics (from `../node_modules/react-native-turbo-haptics`)
- VisionCamera (from `../node_modules/react-native-vision-camera`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)

Expand Down Expand Up @@ -2345,6 +2367,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-tcp"
ToolTipMenu:
:path: "../node_modules/react-native-tooltip"
TurboHaptics:
:path: "../node_modules/react-native-turbo-haptics"
VisionCamera:
:path: "../node_modules/react-native-vision-camera"
Yoga:
Expand Down Expand Up @@ -2524,6 +2548,7 @@ SPEC CHECKSUMS:
TcpSockets: bd31674146c0931a064fc254a59812dfd1a73ae0
TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654
ToolTipMenu: 8ac61aded0fbc4acfe7e84a7d0c9479d15a9a382
TurboHaptics: 6381613d33ab97aeb30d9b15c3df94dc616a25e4
VisionCamera: 2af28201c3de77245f8c58b7a5274d5979df70df
Yoga: 04f1db30bb810187397fa4c37dd1868a27af229c

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@
"react-native-text-size": "rainbow-me/react-native-text-size#15b21c9f88c6df0d1b5e0f2ba792fe59b5dc255a",
"react-native-tooltip": "rainbow-me/react-native-tooltip#e0e88d212b5b7f350e5eabba87f588a32e0f2590",
"react-native-tooltips": "rainbow-me/react-native-tooltips#fdafbc7ba33ee231229f5d3f58b29d0d1c55ddfa",
"react-native-turbo-haptics": "1.0.4",
"react-native-udp": "2.7.0",
"react-native-url-polyfill": "2.0.0",
"react-native-version-number": "0.3.6",
Expand Down
32 changes: 14 additions & 18 deletions src/__swaps__/screens/Swap/components/SearchInputButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import React, { useCallback } from 'react';
import { GestureHandlerButton } from './GestureHandlerButton';
import { AnimatedText, Box } from '@/design-system';
import Animated, { SharedValue, runOnJS, useAnimatedStyle, useDerivedValue, withTiming } from 'react-native-reanimated';
import { triggerHaptics } from 'react-native-turbo-haptics';
import { NavigationSteps, useSwapContext } from '@/__swaps__/screens/Swap/providers/swap-provider';
import Clipboard from '@react-native-clipboard/clipboard';
import { useSwapsStore } from '@/state/swaps/swapsStore';
import * as i18n from '@/languages';
import { THICK_BORDER_WIDTH } from '../constants';
import { useClipboard } from '@/hooks';
import { TIMING_CONFIGS } from '@/components/animations/animationConfigs';
import { triggerHapticFeedback } from '@/screens/points/constants';
import { IS_ANDROID } from '@/env';

const CANCEL_LABEL = i18n.t(i18n.l.button.cancel);
Expand Down Expand Up @@ -54,22 +54,14 @@ export const SearchInputButton = ({
return PASTE_LABEL;
});

const onPaste = useCallback(
(isPasteDisabled: boolean) => {
if (isPasteDisabled) {
triggerHapticFeedback('notificationError');
return;
}

Clipboard.getString().then(text => {
// Slice the pasted text to the length of an ETH address
const v = text.trim().slice(0, 42);
pastedSearchInputValue.value = v;
useSwapsStore.setState({ outputSearchQuery: v });
});
},
[pastedSearchInputValue]
);
const onPaste = useCallback(() => {
Clipboard.getString().then(text => {
// Slice the pasted text to the length of an ETH address
const v = text.trim().slice(0, 42);
pastedSearchInputValue.value = v;
useSwapsStore.setState({ outputSearchQuery: v });
});
}, [pastedSearchInputValue]);

const buttonInfo = useDerivedValue(() => {
const isInputSearchFocused = inputProgress.value === NavigationSteps.SEARCH_FOCUSED;
Expand Down Expand Up @@ -106,7 +98,11 @@ export const SearchInputButton = ({
onPressWorklet={() => {
'worklet';
if (output && outputProgress.value === NavigationSteps.TOKEN_LIST_FOCUSED && !internalSelectedOutputAsset.value) {
runOnJS(onPaste)(buttonInfo.value.isPasteDisabled);
if (buttonInfo.value.isPasteDisabled) {
triggerHaptics('notificationError');
} else {
runOnJS(onPaste)();
}
}

if (isSearchFocused.value || (output && internalSelectedOutputAsset.value) || (!output && internalSelectedInputAsset.value)) {
Expand Down
14 changes: 3 additions & 11 deletions src/__swaps__/screens/Swap/components/SwapBottomPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,15 @@ import { Box, Separator, globalColors, useColorMode } from '@/design-system';
import React from 'react';
import { StyleSheet } from 'react-native';
import { PanGestureHandler } from 'react-native-gesture-handler';
import Animated, {
Easing,
runOnJS,
useAnimatedStyle,
useDerivedValue,
useSharedValue,
withSpring,
withTiming,
} from 'react-native-reanimated';
import Animated, { Easing, useAnimatedStyle, useDerivedValue, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
import { triggerHaptics } from 'react-native-turbo-haptics';
import { useBottomPanelGestureHandler } from '../hooks/useBottomPanelGestureHandler';
import { GasButton } from './GasButton';
import { GasPanel } from './GasPanel';
import { ReviewPanel } from './ReviewPanel';
import { SwapActionButton } from './SwapActionButton';
import { SettingsPanel } from './SettingsPanel';
import { SPRING_CONFIGS } from '@/components/animations/animationConfigs';
import { triggerHapticFeedback } from '@/screens/points/constants';

const HOLD_TO_SWAP_DURATION_MS = 400;

Expand Down Expand Up @@ -123,7 +115,7 @@ export function SwapBottomPanel() {
onLongPressWorklet={() => {
'worklet';
if (type.value === 'hold') {
runOnJS(triggerHapticFeedback)('notificationSuccess');
triggerHaptics('notificationSuccess');
SwapNavigation.handleSwapAction();
}
}}
Expand Down
8 changes: 4 additions & 4 deletions src/__swaps__/screens/Swap/components/SwapSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import Animated, {
withSpring,
withTiming,
} from 'react-native-reanimated';
import { triggerHaptics } from 'react-native-turbo-haptics';
import { SPRING_CONFIGS, TIMING_CONFIGS } from '@/components/animations/animationConfigs';
import { AnimatedText, Bleed, Box, Column, Columns, Inline, globalColors, useColorMode, useForegroundColor } from '@/design-system';
import { IS_IOS } from '@/env';
import { triggerHapticFeedback } from '@/screens/points/constants';
import { greaterThanWorklet } from '@/safe-math/SafeMath';
import {
SCRUBBER_WIDTH,
Expand Down Expand Up @@ -124,10 +124,10 @@ export const SwapSlider = ({
(current, previous) => {
if (current !== previous && SwapInputController.inputMethod.value === 'slider') {
if (current.x >= width * 0.995 && previous?.x && previous?.x < width * 0.995) {
runOnJS(triggerHapticFeedback)('impactMedium');
triggerHaptics('impactMedium');
}
if (current.x < width * 0.005 && previous?.x && previous?.x >= width * 0.005) {
runOnJS(triggerHapticFeedback)('impactLight');
triggerHaptics('impactLight');
}
}
},
Expand Down Expand Up @@ -160,7 +160,7 @@ export const SwapSlider = ({
ctx.exceedsMax = true;
isQuoteStale.value = 1;
sliderXPosition.value = width * 0.999;
runOnJS(triggerHapticFeedback)('impactMedium');
triggerHaptics('impactMedium');
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ import {
externalTokenQueryKey,
fetchExternalToken,
} from '@/resources/assets/externalAssetsQuery';
import { triggerHapticFeedback } from '@/screens/points/constants';
import { swapsStore } from '@/state/swaps/swapsStore';
import { CrosschainQuote, Quote, QuoteError, getCrosschainQuote, getQuote } from '@rainbow-me/swaps';
import { useCallback } from 'react';
import { SharedValue, runOnJS, runOnUI, useAnimatedReaction, useDerivedValue, useSharedValue, withSpring } from 'react-native-reanimated';
import { triggerHaptics } from 'react-native-turbo-haptics';
import { useDebouncedCallback } from 'use-debounce';
import { NavigationSteps } from './useSwapNavigation';
import { deepEqualWorklet } from '@/worklets/comparisons';
Expand Down Expand Up @@ -584,7 +584,7 @@ export function useSwapInputsController({
const exceedsMax = maxSwappableAmount ? greaterThanWorklet(currentInputValue, maxSwappableAmount) : false;

if (isAlreadyMax) {
runOnJS(triggerHapticFeedback)('impactMedium');
triggerHaptics('impactMedium');
} else {
quoteFetchingInterval.stop();

Expand Down
8 changes: 4 additions & 4 deletions src/screens/points/components/AnimatedText.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { HapticFeedbackType } from '@/utils/haptics';
import { Bleed } from '@/design-system';
import { Text as RNText, StyleSheet } from 'react-native';
import { HapticType, triggerHaptics } from 'react-native-turbo-haptics';
import { useTheme } from '@/theme';
import { useAnimationContext } from '../contexts/AnimationContext';
import {
Expand All @@ -14,15 +14,15 @@ import {
withSequence,
withTiming,
} from 'react-native-reanimated';
import { generateRainbowColors, triggerHapticFeedback } from '../constants';
import { generateRainbowColors } from '../constants';
import { fonts } from '@/styles';

type AnimatedTextProps = {
color?: { text: string; shadow: string };
delayStart?: number;
disableShadow?: boolean;
enableHapticTyping?: boolean;
hapticType?: HapticFeedbackType;
hapticType?: HapticType;
multiline?: boolean;
onComplete?: () => void;
opacity?: number;
Expand Down Expand Up @@ -145,7 +145,7 @@ export const AnimatedText = ({

runOnJS(setDisplayedText)(newText);
if (enableHapticTyping && Math.round(current.displayedValue) && newText[newText.length - 1] !== ' ') {
runOnJS(triggerHapticFeedback)(hapticType);
triggerHaptics(hapticType);
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions src/screens/points/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { HapticFeedbackType } from '@/utils/haptics';
import { safeAreaInsetValues } from '@/utils';
import { OnboardPointsMutation, PointsOnboardingCategory } from '@/graphql/__generated__/metadata';
import * as i18n from '@/languages';
Expand Down Expand Up @@ -69,8 +67,6 @@ export const generateRainbowColors = (text: string): Array<{ text: string; shado
return colors;
};

export const triggerHapticFeedback = (hapticType: HapticFeedbackType) => ReactNativeHapticFeedback?.trigger(hapticType);

const BASE_URL = `https://twitter.com/intent/tweet?text=`;
const NEWLINE_OR_SPACE = IS_IOS ? '\n\n' : ' ';
export const buildTwitterIntentMessage = (
Expand Down
11 changes: 11 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9404,6 +9404,7 @@ __metadata:
react-native-text-size: "rainbow-me/react-native-text-size#15b21c9f88c6df0d1b5e0f2ba792fe59b5dc255a"
react-native-tooltip: "rainbow-me/react-native-tooltip#e0e88d212b5b7f350e5eabba87f588a32e0f2590"
react-native-tooltips: "rainbow-me/react-native-tooltips#fdafbc7ba33ee231229f5d3f58b29d0d1c55ddfa"
react-native-turbo-haptics: "npm:1.0.4"
react-native-udp: "npm:2.7.0"
react-native-url-polyfill: "npm:2.0.0"
react-native-version-number: "npm:0.3.6"
Expand Down Expand Up @@ -23734,6 +23735,16 @@ react-native-safe-area-view@rainbow-me/react-native-safe-area-view:
languageName: node
linkType: hard

"react-native-turbo-haptics@npm:1.0.4":
version: 1.0.4
resolution: "react-native-turbo-haptics@npm:1.0.4"
peerDependencies:
react: ^18.2.0
react-native: ">=0.72.0"
checksum: 10c0/1c65d3c6380a438e55540cbdc82d865f26aa2b6c24364d2be5092c87f347115471162f8a61c8f9c71324d88bf392da7fbe19c4a489e74a8394bbbdf0664da24e
languageName: node
linkType: hard

"react-native-udp@npm:2.7.0":
version: 2.7.0
resolution: "react-native-udp@npm:2.7.0"
Expand Down

0 comments on commit 9bf4998

Please sign in to comment.