import React, { useCallback, useImperativeHandle, useMemo, useRef, useState, } from 'react' import {Modal, ScrollView, TextInput, View} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {cleanError} from '#/lib/strings/errors' import { Gif, useFeaturedGifsQuery, useGifSearchQuery, } from '#/state/queries/tenor' import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {FlatList_INTERNAL} from '#/view/com/util/Views' import {atoms as a, useBreakpoints, useTheme} from '#/alf' import * as TextField from '#/components/forms/TextField' import {MagnifyingGlass2_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass2' import {Button, ButtonText} from '../Button' import {Handle} from '../Dialog' import {useThrottledValue} from '../hooks/useThrottledValue' import {ListFooter, ListMaybePlaceholder} from '../Lists' import {GifPreview} from './GifSelect.shared' export function GifSelectDialog({ controlRef, onClose, onSelectGif: onSelectGifProp, }: { controlRef: React.RefObject<{open: () => void}> onClose: () => void onSelectGif: (gif: Gif) => void }) { const t = useTheme() const [open, setOpen] = useState(false) useImperativeHandle(controlRef, () => ({ open: () => setOpen(true), })) const close = useCallback(() => { setOpen(false) onClose() }, [onClose]) const onSelectGif = useCallback( (gif: Gif) => { onSelectGifProp(gif) close() }, [onSelectGifProp, close], ) const renderErrorBoundary = useCallback( (error: any) => , [close], ) return ( ) } function GifList({ onSelectGif, }: { close: () => void onSelectGif: (gif: Gif) => void }) { const {_} = useLingui() const t = useTheme() const {gtMobile} = useBreakpoints() const textInputRef = useRef(null) const listRef = useRef(null) const [undeferredSearch, setSearch] = useState('') const search = useThrottledValue(undeferredSearch, 500) const isSearching = search.length > 0 const trendingQuery = useFeaturedGifsQuery() const searchQuery = useGifSearchQuery(search) const { data, fetchNextPage, isFetchingNextPage, hasNextPage, error, isLoading, isError, refetch, } = isSearching ? searchQuery : trendingQuery const flattenedData = useMemo(() => { return data?.pages.flatMap(page => page.results) || [] }, [data]) const renderItem = useCallback( ({item}: {item: Gif}) => { return }, [onSelectGif], ) const onEndReached = React.useCallback(() => { if (isFetchingNextPage || !hasNextPage || error) return fetchNextPage() }, [isFetchingNextPage, hasNextPage, error, fetchNextPage]) const hasData = flattenedData.length > 0 const onGoBack = useCallback(() => { if (isSearching) { // clear the input and reset the state textInputRef.current?.clear() setSearch('') } else { close() } }, [isSearching]) const listHeader = useMemo(() => { return ( {/* cover top corners */} { setSearch(text) listRef.current?.scrollToOffset({offset: 0, animated: false}) }} returnKeyType="search" clearButtonMode="while-editing" inputRef={textInputRef} maxLength={50} /> ) }, [t.atoms.bg, _]) return ( {listHeader} {!hasData && ( )} } stickyHeaderIndices={[0]} onEndReached={onEndReached} onEndReachedThreshold={4} keyExtractor={(item: Gif) => item.id} keyboardDismissMode="on-drag" ListFooterComponent={ hasData ? ( ) : null } /> ) } function ModalError({details, close}: {details?: string; close: () => void}) { const {_} = useLingui() return ( ) }