import React, { memo, useCallback, useRef, useState, } from '../../../lib/teact/teact'; import { getActions } from '../../../global'; import type { FC } from '../../../lib/teact/teact'; import type { IAnchorPosition } from '../../../types'; import type { ApiVideo, ApiSticker } from '../../../api/types'; import { EDITABLE_INPUT_CSS_SELECTOR, EDITABLE_INPUT_MODAL_CSS_SELECTOR } from '../../../config'; import buildClassName from '../../../util/buildClassName'; import useFlag from '../../../hooks/useFlag'; import useMenuPosition from '../../../hooks/useMenuPosition'; import Button from '../../ui/Button'; import Spinner from '../../ui/Spinner'; import ResponsiveHoverButton from '../../ui/ResponsiveHoverButton'; import SymbolMenu from './SymbolMenu.async'; const MOBILE_KEYBOARD_HIDE_DELAY_MS = 100; type OwnProps = { chatId: string; threadId?: number; isMobile?: boolean; isReady?: boolean; isSymbolMenuOpen?: boolean; canSendGifs?: boolean; canSendStickers?: boolean; openSymbolMenu: VoidFunction; closeSymbolMenu: VoidFunction; onCustomEmojiSelect: (emoji: ApiSticker) => void; onStickerSelect?: ( sticker: ApiSticker, isSilent?: boolean, shouldSchedule?: boolean, shouldPreserveInput?: boolean, canUpdateStickerSetsOrder?: boolean ) => void; onGifSelect?: (gif: ApiVideo, isSilent?: boolean, shouldSchedule?: boolean) => void; onRemoveSymbol: VoidFunction; onEmojiSelect: (emoji: string) => void; closeBotCommandMenu?: VoidFunction; closeSendAsMenu?: VoidFunction; isSymbolMenuForced?: boolean; isAttachmentModal?: boolean; canSendPlainText?: boolean; className?: string; }; const SymbolMenuButton: FC = ({ chatId, threadId, isMobile, canSendGifs, canSendStickers, isReady, isSymbolMenuOpen, openSymbolMenu, closeSymbolMenu, onCustomEmojiSelect, onStickerSelect, onGifSelect, isAttachmentModal, canSendPlainText, onRemoveSymbol, onEmojiSelect, closeBotCommandMenu, closeSendAsMenu, isSymbolMenuForced, className, }) => { const { setStickerSearchQuery, setGifSearchQuery, addRecentEmoji, addRecentCustomEmoji, } = getActions(); // eslint-disable-next-line no-null/no-null const triggerRef = useRef(null); const [isSymbolMenuLoaded, onSymbolMenuLoadingComplete] = useFlag(); const [contextMenuPosition, setContextMenuPosition] = useState(undefined); const symbolMenuButtonClassName = buildClassName( 'mobile-symbol-menu-button', !isReady && 'not-ready', isSymbolMenuLoaded ? (isSymbolMenuOpen && 'menu-opened') : (isSymbolMenuOpen && 'is-loading'), ); const handleActivateSymbolMenu = useCallback(() => { closeBotCommandMenu?.(); closeSendAsMenu?.(); openSymbolMenu(); const triggerEl = triggerRef.current; if (!triggerEl) return; const { x, y } = triggerEl.getBoundingClientRect(); setContextMenuPosition({ x, y }); }, [closeBotCommandMenu, closeSendAsMenu, openSymbolMenu]); const handleSearchOpen = useCallback((type: 'stickers' | 'gifs') => { if (type === 'stickers') { setStickerSearchQuery({ query: '' }); setGifSearchQuery({ query: undefined }); } else { setGifSearchQuery({ query: '' }); setStickerSearchQuery({ query: undefined }); } }, [setStickerSearchQuery, setGifSearchQuery]); const handleSymbolMenuOpen = useCallback(() => { const messageInput = document.querySelector( isAttachmentModal ? EDITABLE_INPUT_MODAL_CSS_SELECTOR : EDITABLE_INPUT_CSS_SELECTOR, ); if (!isMobile || messageInput !== document.activeElement) { openSymbolMenu(); return; } messageInput?.blur(); setTimeout(() => { closeBotCommandMenu?.(); openSymbolMenu(); }, MOBILE_KEYBOARD_HIDE_DELAY_MS); }, [isAttachmentModal, isMobile, openSymbolMenu, closeBotCommandMenu]); const getTriggerElement = useCallback(() => triggerRef.current, []); const getRootElement = useCallback( () => triggerRef.current?.closest('.custom-scroll, .no-scrollbar'), [], ); const getMenuElement = useCallback( () => document.querySelector('#portals .SymbolMenu .bubble'), [], ); const getLayout = useCallback(() => ({ withPortal: true, }), []); const { positionX, positionY, transformOriginX, transformOriginY, style: menuStyle, } = useMenuPosition( contextMenuPosition, getTriggerElement, getRootElement, getMenuElement, getLayout, ); return ( <> {isMobile ? ( ) : (
)} ); }; export default memo(SymbolMenuButton);