import React, {useImperativeHandle} from 'react' import { FlatList, FlatListProps, StyleProp, TouchableWithoutFeedback, View, ViewStyle, } from 'react-native' import Animated, {FadeIn, FadeInDown} from 'react-native-reanimated' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {DismissableLayer} from '@radix-ui/react-dismissable-layer' import {useFocusGuards} from '@radix-ui/react-focus-guards' import {FocusScope} from '@radix-ui/react-focus-scope' import {logger} from '#/logger' import {useDialogStateControlContext} from '#/state/dialogs' import {atoms as a, flatten, useBreakpoints, useTheme, web} from '#/alf' import {Button, ButtonIcon} from '#/components/Button' import {Context} from '#/components/Dialog/context' import { DialogControlProps, DialogInnerProps, DialogOuterProps, } from '#/components/Dialog/types' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {Portal} from '#/components/Portal' export {useDialogContext, useDialogControl} from '#/components/Dialog/context' export * from '#/components/Dialog/shared' export * from '#/components/Dialog/types' export * from '#/components/Dialog/utils' export {Input} from '#/components/forms/TextField' const stopPropagation = (e: any) => e.stopPropagation() const preventDefault = (e: any) => e.preventDefault() export function Outer({ children, control, onClose, }: React.PropsWithChildren) { const {_} = useLingui() const t = useTheme() const {gtMobile} = useBreakpoints() const [isOpen, setIsOpen] = React.useState(false) const {setDialogIsOpen} = useDialogStateControlContext() const open = React.useCallback(() => { setDialogIsOpen(control.id, true) setIsOpen(true) }, [setIsOpen, setDialogIsOpen, control.id]) const close = React.useCallback( cb => { setDialogIsOpen(control.id, false) setIsOpen(false) try { if (cb && typeof cb === 'function') { // This timeout ensures that the callback runs at the same time as it would on native. I.e. // console.log('Step 1') -> close(() => console.log('Step 3')) -> console.log('Step 2') // This should always output 'Step 1', 'Step 2', 'Step 3', but without the timeout it would output // 'Step 1', 'Step 3', 'Step 2'. setTimeout(cb) } } catch (e: any) { logger.error(`Dialog closeCallback failed`, { message: e.message, }) } onClose?.() }, [control.id, onClose, setDialogIsOpen], ) const handleBackgroundPress = React.useCallback(async () => { close() }, [close]) useImperativeHandle( control.ref, () => ({ open, close, }), [close, open], ) const context = React.useMemo( () => ({ close, isNativeDialog: false, nativeSnapPoint: 0, disableDrag: false, setDisableDrag: () => {}, }), [close], ) return ( <> {isOpen && ( {children} )} ) } export function Inner({ children, style, label, accessibilityLabelledBy, accessibilityDescribedBy, header, contentContainerStyle, }: DialogInnerProps) { const t = useTheme() const {close} = React.useContext(Context) const {gtMobile} = useBreakpoints() useFocusGuards() return ( true} onTouchEnd={stopPropagation} entering={FadeInDown.duration(100)} // exiting={FadeOut.duration(100)} style={flatten([ a.relative, a.rounded_md, a.w_full, a.border, t.atoms.bg, { maxWidth: 600, borderColor: t.palette.contrast_200, shadowColor: t.palette.black, shadowOpacity: t.name === 'light' ? 0.1 : 0.4, shadowRadius: 30, }, flatten(style), ])}> {header} {children} ) } export const ScrollableInner = Inner export const InnerFlatList = React.forwardRef< FlatList, FlatListProps & {label: string} & {webInnerStyle?: StyleProp} >(function InnerFlatList({label, style, webInnerStyle, ...props}, ref) { const {gtMobile} = useBreakpoints() return ( ) }) export function Close() { const {_} = useLingui() const {close} = React.useContext(Context) return ( ) } export function Handle() { return null }