import React, { useCallback, useContext, useEffect, useRef } from 'react'; import { Animated, BackHandler, Easing, KeyboardAvoidingView, Modal as ModalRN, Platform, Pressable, StyleSheet, View, } from 'react-native'; import { ApplicationContext, MiniAppContext } from '../Context'; import { Styles } from '../Consts'; import Navigation from './Navigation'; import { ModalParams } from './types'; import BottomSheet from './BottomSheet'; import { runOnJS } from 'react-native-reanimated'; const ModalScreen: React.FC = props => { if (props.route?.params?.isBottomSheet) { return ; } return ; }; const Modal: React.FC = props => { const { navigator } = useContext(ApplicationContext); const context = useContext(MiniAppContext); const { screen, barrierDismissible, modalStyle, useNativeModal = false, description, title, } = props.route.params; const Component = useRef(screen).current; /** * Fire auto_popup_displayed tracking event on mount */ useEffect(() => { context.autoTracking({ componentName: 'Modal', description, title, }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const opacity = useRef(new Animated.Value(0)).current; const scale = useRef(new Animated.Value(0.8)).current; const navigation = new Navigation(props.navigation); const params = { ...props.route.params, navigation, }; delete params.screen; let Container: any = View; if (useNativeModal) { Container = ModalRN; } useEffect(() => { Animated.parallel([ Animated.timing(opacity, { toValue: 1, duration: 250, useNativeDriver: true, }), Animated.timing(scale, { toValue: 1, duration: 250, easing: Easing.bezier(0.2, 0.0, 0, 1.0), useNativeDriver: true, }), ]).start(); return () => { props.route.params?.onDismiss?.(); }; }, [opacity, props.route.params, scale]); const onDismiss = useCallback( (callback = () => {}, preventClose = false) => { if (preventClose) { return; } Animated.parallel([ Animated.timing(opacity, { toValue: 0, duration: 200, useNativeDriver: true, }), Animated.timing(scale, { toValue: 0.8, duration: 200, easing: Easing.linear, useNativeDriver: true, }), ]).start(() => { navigator?.pop(); runOnJS(callback)(); }); }, [navigator, opacity, scale], ); useEffect(() => { const backHandler = BackHandler.addEventListener( 'hardwareBackPress', () => { onDismiss(undefined, barrierDismissible); return true; }, ); return () => backHandler.remove(); }, [barrierDismissible, onDismiss]); return ( onDismiss(undefined, barrierDismissible)} > ); }; const styles = StyleSheet.create({ overlayContent: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.6)', }, }); export default ModalScreen;