import React, { PropsWithChildren, useEffect, useMemo, useState } from 'react'; import { BackHandler } from 'react-native'; import { cancelAnimation, useSharedValue, withTiming } from 'react-native-reanimated'; import { PortalProvider } from 'react-native-teleport'; import { MessageOverlayHostLayer } from './MessageOverlayHostLayer'; import { OverlayContext, OverlayProviderProps } from './OverlayContext'; import { ImageGallery } from '../../components/ImageGallery/ImageGallery'; import { useStreami18n } from '../../hooks/useStreami18n'; import { ImageGalleryProvider } from '../imageGalleryContext/ImageGalleryContext'; import { ThemeProvider } from '../themeContext/ThemeContext'; import { DEFAULT_USER_LANGUAGE, TranslationProvider, } from '../translationContext/TranslationContext'; /** * - The highest level of these components is the `OverlayProvider`. The `OverlayProvider` allows users to interact with messages on long press above the underlying views, use the full screen image viewer, and use the `AttachmentPicker` as a keyboard-esk view. * Because these views must exist above all others `OverlayProvider` should wrap your navigation stack as well. Assuming [`React Navigation`](https://reactnavigation.org/) is being used, your highest level navigation stack should be wrapped in the provider: * * ```js * * * * * * * * ``` * * - Don't forget to check our cookbook section of [OverlayProvider](https://github.com/GetStream/stream-chat-react-native/wiki/Cookbook-v3.0#overlayprovider) * * - Also check the [visual component guide](https://github.com/GetStream/stream-chat-react-native/wiki/Cookbook-v3.0#custom-components), to learn about component customizations. * * @example ./OverlayProvider.md */ export const OverlayProvider = (props: PropsWithChildren) => { const { children, i18nInstance, value, autoPlayVideo, giphyVersion, numberOfImageGalleryGridColumns, } = props; const [overlay, setOverlay] = useState(value?.overlay || 'none'); const overlayOpacity = useSharedValue(0); // Setup translators const translators = useStreami18n(i18nInstance); useEffect(() => { const backAction = () => { if (overlay !== 'none') { setOverlay('none'); return true; } return false; }; const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction); return () => backHandler.remove(); }, [overlay]); useEffect(() => { cancelAnimation(overlayOpacity); if (overlay !== 'none') { overlayOpacity.value = withTiming(1); } else { overlayOpacity.value = withTiming(0); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [overlay]); const overlayContext = { overlay, overlayOpacity, setOverlay, style: value?.style, }; const imageGalleryProviderProps = useMemo( () => ({ autoPlayVideo, giphyVersion, numberOfImageGalleryGridColumns, }), [autoPlayVideo, giphyVersion, numberOfImageGalleryGridColumns], ); return ( {children} {overlay === 'gallery' && } ); };