From 07b57cf01857e2800ad34a14aca0699d60e945b7 Mon Sep 17 00:00:00 2001 From: Chathura Date: Tue, 11 Jun 2024 11:20:28 +0530 Subject: [PATCH] keyboard/ react animation and drag behaviour changes --- example/App.tsx | 9 +- example/PaymentScreen.tsx | 1 + payment_sdk/src/components/PaymentSheet.tsx | 1 - payment_sdk/src/components/PillContainer.tsx | 3 +- payment_sdk/src/components/Sheet.tsx | 149 ++++++++++--------- payment_sdk/src/components/SheetContent.tsx | 24 ++- 6 files changed, 105 insertions(+), 82 deletions(-) diff --git a/example/App.tsx b/example/App.tsx index 83d7e55..8ef34e8 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -2,16 +2,13 @@ import React from 'react'; import {KomojuSDK} from 'react-native-komoju'; import {PUBLIC_KEY} from '@env'; -import {GestureHandlerRootView} from 'react-native-gesture-handler'; import PaymentScreen from './PaymentScreen'; function App(): React.JSX.Element { return ( - - - - - + + + ); } diff --git a/example/PaymentScreen.tsx b/example/PaymentScreen.tsx index ee1085d..ab798e4 100644 --- a/example/PaymentScreen.tsx +++ b/example/PaymentScreen.tsx @@ -119,6 +119,7 @@ const styles = StyleSheet.create({ flexDirection: 'row', justifyContent: 'space-between', minHeight: 100, + zIndex: -100, }, currencyRow: { flexDirection: 'row', diff --git a/payment_sdk/src/components/PaymentSheet.tsx b/payment_sdk/src/components/PaymentSheet.tsx index 33357ae..e577f4f 100644 --- a/payment_sdk/src/components/PaymentSheet.tsx +++ b/payment_sdk/src/components/PaymentSheet.tsx @@ -1,5 +1,4 @@ import React, { useRef, forwardRef, useImperativeHandle } from "react"; -import { GestureHandlerRootView } from "react-native-gesture-handler"; import { StyleSheet } from "react-native"; import Sheet, { SheetRefProps } from "./Sheet"; diff --git a/payment_sdk/src/components/PillContainer.tsx b/payment_sdk/src/components/PillContainer.tsx index 15c4660..9e6223e 100644 --- a/payment_sdk/src/components/PillContainer.tsx +++ b/payment_sdk/src/components/PillContainer.tsx @@ -1,7 +1,6 @@ import React from "react"; -import { StyleSheet, View } from "react-native"; +import { StyleSheet, View, FlatList } from "react-native"; import Pill from "./Pill"; -import { FlatList } from "react-native-gesture-handler"; import { PaymentType } from "../util/types"; type Props = { diff --git a/payment_sdk/src/components/Sheet.tsx b/payment_sdk/src/components/Sheet.tsx index 506023f..953909c 100644 --- a/payment_sdk/src/components/Sheet.tsx +++ b/payment_sdk/src/components/Sheet.tsx @@ -1,8 +1,11 @@ import React, { useCallback, useImperativeHandle, - ForwardRefRenderFunction, + forwardRef, useContext, + useRef, + useEffect, + ForwardRefRenderFunction, } from "react"; import { Dimensions, @@ -11,15 +14,9 @@ import { Text, TouchableOpacity, View, + Animated as RNAnimated, + PanResponder, } from "react-native"; -import { Gesture, GestureDetector } from "react-native-gesture-handler"; -import Animated, { - useAnimatedProps, - useAnimatedStyle, - useSharedValue, - withSpring, - withTiming, -} from "react-native-reanimated"; import ResponseScreen from "./ResponseScreen"; import { Actions, DispatchContext, StateContext } from "../state"; import SheetContent from "./SheetContent"; @@ -47,21 +44,46 @@ const Sheet: ForwardRefRenderFunction = ( { children, swipeClose }, ref ) => { + const translateY = useRef(new RNAnimated.Value(0)).current; + const active = useRef(new RNAnimated.Value(0)).current; + const context = useRef(new RNAnimated.Value(0)).current; + + const activeState = useRef(false); + const translateYState = useRef(0); + const contextState = useRef(0); + const { paymentState } = useContext(StateContext); const dispatch = useContext(DispatchContext); - const translateY = useSharedValue(0); - const active = useSharedValue(false); + useEffect(() => { + const yListener = translateY.addListener(({ value }) => { + translateYState.current = value; + }); + const activeListener = active.addListener(({ value }) => { + activeState.current = value === 1; + }); + const contextID = context.addListener(({ value }) => { + contextState.current = value; + }); + return () => { + translateY.removeListener(yListener); + active.removeListener(activeListener); + context.removeListener(contextID); + }; + }, []); const scrollTo = useCallback((destination: number) => { - "worklet"; - active.value = destination !== 0; - - translateY.value = withSpring(destination, { damping: 50 }); + active.setValue(destination !== 0 ? 1 : 0); + RNAnimated.spring(translateY, { + toValue: destination, + friction: 10, + tension: 10, + useNativeDriver: true, + }).start(); }, []); const isActive = useCallback(() => { - return active.value; + return activeState.current; }, []); useImperativeHandle( @@ -79,40 +101,25 @@ const Sheet: ForwardRefRenderFunction = ( [scrollTo, isActive] ); - const context = useSharedValue({ y: 0 }); - const gesture = Gesture.Pan() - .onStart(() => { - context.value = { y: translateY.value }; - }) - .onUpdate((event) => { - translateY.value = event.translationY + context.value.y; - translateY.value = Math.max(translateY.value, MAX_TRANSLATE_Y + 50); + const panResponder = useRef( + PanResponder.create({ + onStartShouldSetPanResponder: () => true, + onPanResponderGrant: () => { + context.setValue(translateYState.current); + }, + onPanResponderMove: (event, gestureState) => { + const totalYMovement = gestureState.dy + contextState.current; + translateY.setValue(Math.max(totalYMovement, MAX_TRANSLATE_Y + 50)); + }, + onPanResponderRelease: () => { + if (translateYState.current > -SCREEN_HEIGHT / 1.5) { + scrollTo(0); + } else if (translateYState.current < -SCREEN_HEIGHT / 1.5) { + scrollTo(MAX_TRANSLATE_Y + 50); + } + }, }) - .onEnd(() => { - if (translateY.value > -SCREEN_HEIGHT / 1) { - scrollTo(0); - } else if (translateY.value < -SCREEN_HEIGHT / 1.5) { - scrollTo(MAX_TRANSLATE_Y); - } - }); - - const rSheetStyle = useAnimatedStyle(() => { - return { - transform: [{ translateY: translateY.value }], - }; - }); - - const rBackdropStyle = useAnimatedStyle(() => { - return { - opacity: withTiming(active.value ? 1 : 0), - }; - }, []); - - const rBackdropProps = useAnimatedProps(() => { - return { - pointerEvents: active.value ? "auto" : "none", - } as any; - }, []); + ).current; const getCtaText = () => { switch (paymentState) { @@ -141,29 +148,31 @@ const Sheet: ForwardRefRenderFunction = ( return ( <> - { - swipeClose ? scrollTo(0) : null; + if (swipeClose) scrollTo(0); }} - animatedProps={rBackdropProps} - style={[styles.backDrop, rBackdropStyle]} + pointerEvents="none" + style={[styles.backDrop, { opacity: active }]} /> - - - - - {!paymentState ? ( - Payment Options - ) : null} - scrollTo(0)} - > - - - - - + + + + Payment Options + scrollTo(0)} + > + + + + {paymentState ? ( = ( ) : ( )} - + ); }; diff --git a/payment_sdk/src/components/SheetContent.tsx b/payment_sdk/src/components/SheetContent.tsx index c4c94c9..2d7cb08 100644 --- a/payment_sdk/src/components/SheetContent.tsx +++ b/payment_sdk/src/components/SheetContent.tsx @@ -1,5 +1,5 @@ -import React, { useContext } from "react"; -import { ScrollView } from "react-native"; +import React, { useContext, useEffect, useState } from "react"; +import { Keyboard, ScrollView } from "react-native"; import PillContainer from "./PillContainer"; import WebView from "./WebView"; @@ -13,6 +13,24 @@ import { PaymentType } from "../util/types"; const SheetContent = () => { const { paymentType, webViewData, loading } = useContext(StateContext); const dispatch = useContext(DispatchContext); + const [keyboardHeight, setKeyboardHeight] = useState(0); + + useEffect(() => { + const keyboardDidShowListener = Keyboard.addListener( + 'keyboardDidShow', + (e) => setKeyboardHeight(e.endCoordinates.height) + ); + + const keyboardDidHideListener = Keyboard.addListener( + 'keyboardDidHide', + () => setKeyboardHeight(0) + ); + + return () => { + keyboardDidShowListener.remove(); + keyboardDidHideListener.remove(); + }; + }, []); const handlePillSelect = (type: PaymentType) => { dispatch({ type: Actions.SET_PAYMENT_OPTION, payload: type }); @@ -30,7 +48,7 @@ const SheetContent = () => { return ( <> - + {paymentType === PaymentType.CREDIT && } {paymentType === PaymentType.PAY_PAY && }