import type { FC } from '../../lib/teact/teact'; import React, { memo, useRef, useCallback } from '../../lib/teact/teact'; import { getActions, withGlobal } from '../../global'; import type { ApiChat, ApiVideo } from '../../api/types'; import { IS_TOUCH_ENV } from '../../util/windowEnvironment'; import { selectCurrentGifSearch, selectChat, selectIsChatWithBot, selectCurrentMessageList, selectCanScheduleUntilOnline, selectIsChatWithSelf, selectThreadInfo, } from '../../global/selectors'; import { getAllowedAttachmentOptions, getCanPostInChat } from '../../global/helpers'; import buildClassName from '../../util/buildClassName'; import { useIntersectionObserver } from '../../hooks/useIntersectionObserver'; import useLang from '../../hooks/useLang'; import useHistoryBack from '../../hooks/useHistoryBack'; import useSchedule from '../../hooks/useSchedule'; import InfiniteScroll from '../ui/InfiniteScroll'; import GifButton from '../common/GifButton'; import Loading from '../ui/Loading'; import './GifSearch.scss'; type OwnProps = { onClose: NoneToVoidFunction; isActive: boolean; }; type StateProps = { query?: string; results?: ApiVideo[]; chat?: ApiChat; isChatWithBot?: boolean; canScheduleUntilOnline?: boolean; isSavedMessages?: boolean; canPostInChat?: boolean; }; const PRELOAD_BACKWARDS = 96; // GIF Search bot results are multiplied by 24 const INTERSECTION_DEBOUNCE = 300; const GifSearch: FC = ({ isActive, query, results, chat, isChatWithBot, canScheduleUntilOnline, isSavedMessages, canPostInChat, onClose, }) => { const { searchMoreGifs, sendMessage, setGifSearchQuery, } = getActions(); // eslint-disable-next-line no-null/no-null const containerRef = useRef(null); const [requestCalendar, calendar] = useSchedule(canScheduleUntilOnline); const { observe: observeIntersection, } = useIntersectionObserver({ rootRef: containerRef, debounceMs: INTERSECTION_DEBOUNCE }); const canSendGifs = canPostInChat && getAllowedAttachmentOptions(chat, isChatWithBot).canSendGifs; const handleGifClick = useCallback((gif: ApiVideo, isSilent?: boolean, shouldSchedule?: boolean) => { if (canSendGifs) { if (shouldSchedule) { requestCalendar((scheduledAt) => { sendMessage({ gif, scheduledAt, isSilent }); }); } else { sendMessage({ gif, isSilent }); } } if (IS_TOUCH_ENV) { setGifSearchQuery({ query: undefined }); } }, [canSendGifs, requestCalendar, sendMessage, setGifSearchQuery]); const handleSearchMoreGifs = useCallback(() => { searchMoreGifs(); }, [searchMoreGifs]); const lang = useLang(); useHistoryBack({ isActive, onBack: onClose, }); function renderContent() { if (query === undefined) { return undefined; } if (!results) { return ( ); } if (!results.length) { return (

{lang('NoGIFsFound')}

); } return results.map((gif) => ( )); } const hasResults = Boolean(query !== undefined && results && results.length); return (
{renderContent()} {calendar}
); }; export default memo(withGlobal( (global): StateProps => { const currentSearch = selectCurrentGifSearch(global); const { query, results } = currentSearch || {}; const { chatId, threadId } = selectCurrentMessageList(global) || {}; const chat = chatId ? selectChat(global, chatId) : undefined; const isChatWithBot = chat ? selectIsChatWithBot(global, chat) : undefined; const isSavedMessages = Boolean(chatId) && selectIsChatWithSelf(global, chatId); const threadInfo = chatId && threadId ? selectThreadInfo(global, chatId, threadId) : undefined; const isComments = Boolean(threadInfo?.originChannelId); const canPostInChat = Boolean(chat) && Boolean(threadId) && getCanPostInChat(chat, threadId, isComments); return { query, results, chat, isChatWithBot, isSavedMessages, canPostInChat, canScheduleUntilOnline: Boolean(chatId) && selectCanScheduleUntilOnline(global, chatId), }; }, )(GifSearch));