import type { FC } from '../../../lib/teact/teact'; import React, { memo, useMemo, useRef, useState, } from '../../../lib/teact/teact'; import { getActions, getGlobal } from '../../../global'; import type { ApiTopic } from '../../../api/types'; import type { ThreadId } from '../../../types'; import { CHAT_HEIGHT_PX } from '../../../config'; import { getCanPostInChat, isUserId } from '../../../global/helpers'; import buildClassName from '../../../util/buildClassName'; import { REM } from '../helpers/mediaDimensions'; import renderText from '../helpers/renderText'; import useInfiniteScroll from '../../../hooks/useInfiniteScroll'; import useInputFocusOnOpen from '../../../hooks/useInputFocusOnOpen'; import useKeyboardListNavigation from '../../../hooks/useKeyboardListNavigation'; import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import Button from '../../ui/Button'; import InfiniteScroll from '../../ui/InfiniteScroll'; import InputText from '../../ui/InputText'; import ListItem from '../../ui/ListItem'; import Loading from '../../ui/Loading'; import Modal from '../../ui/Modal'; import Transition from '../../ui/Transition'; import GroupChatInfo from '../GroupChatInfo'; import PrivateChatInfo from '../PrivateChatInfo'; import TopicIcon from '../TopicIcon'; import './ChatOrUserPicker.scss'; export type OwnProps = { currentUserId?: string; chatOrUserIds: string[]; isOpen: boolean; searchPlaceholder: string; search: string; className?: string; loadMore?: NoneToVoidFunction; onSearchChange: (search: string) => void; onSelectChatOrUser: (chatOrUserId: string, threadId?: ThreadId) => void; onClose: NoneToVoidFunction; onCloseAnimationEnd?: NoneToVoidFunction; }; const CHAT_LIST_SLIDE = 0; const TOPIC_LIST_SLIDE = 1; const TOPIC_ICON_SIZE = 2.75 * REM; const ChatOrUserPicker: FC = ({ isOpen, currentUserId, chatOrUserIds, search, searchPlaceholder, className, loadMore, onSearchChange, onSelectChatOrUser, onClose, onCloseAnimationEnd, }) => { const { loadTopics } = getActions(); const lang = useOldLang(); // eslint-disable-next-line no-null/no-null const containerRef = useRef(null); // eslint-disable-next-line no-null/no-null const topicContainerRef = useRef(null); // eslint-disable-next-line no-null/no-null const searchRef = useRef(null); // eslint-disable-next-line no-null/no-null const topicSearchRef = useRef(null); const [viewportIds, getMore] = useInfiniteScroll(loadMore, chatOrUserIds, Boolean(search)); const [forumId, setForumId] = useState(undefined); const [topicSearch, setTopicSearch] = useState(''); const activeKey = forumId ? TOPIC_LIST_SLIDE : CHAT_LIST_SLIDE; const viewportOffset = chatOrUserIds!.indexOf(viewportIds![0]); const resetSearch = useLastCallback(() => { onSearchChange(''); }); useInputFocusOnOpen(searchRef, isOpen && activeKey === CHAT_LIST_SLIDE, resetSearch); useInputFocusOnOpen(topicSearchRef, isOpen && activeKey === TOPIC_LIST_SLIDE); const [topicIds, topics] = useMemo(() => { const global = getGlobal(); const chatsById = global.chats.byId; const chatFullInfoById = global.chats.fullInfoById; const topicsResult = forumId ? chatsById[forumId].topics : undefined; if (!topicsResult) { return [undefined, undefined]; } const searchTitle = topicSearch.toLowerCase(); const result = topicsResult ? Object.values(topicsResult).reduce((acc, topic) => { if ( getCanPostInChat(chatsById[forumId!], topic.id, undefined, chatFullInfoById[forumId!]) && (!searchTitle || topic.title.toLowerCase().includes(searchTitle)) ) { acc[topic.id] = topic; } return acc; }, {} as Record) : topicsResult; return [Object.keys(result).map(Number), result]; }, [forumId, topicSearch]); const handleHeaderBackClick = useLastCallback(() => { setForumId(undefined); setTopicSearch(''); }); const handleSearchChange = useLastCallback((e: React.ChangeEvent) => { onSearchChange(e.currentTarget.value); }); const handleTopicSearchChange = useLastCallback((e: React.ChangeEvent) => { setTopicSearch(e.currentTarget.value); }); const handleKeyDown = useKeyboardListNavigation(containerRef, isOpen, (index) => { if (viewportIds && viewportIds.length > 0) { const chatsById = getGlobal().chats.byId; const chatId = viewportIds[index === -1 ? 0 : index]; const chat = chatsById[chatId]; if (chat?.isForum) { if (!chat.topics) loadTopics({ chatId }); setForumId(chatId); } else { onSelectChatOrUser(chatId); } } }, '.ListItem-button', true); const handleTopicKeyDown = useKeyboardListNavigation(topicContainerRef, isOpen, (index) => { if (topicIds?.length) { onSelectChatOrUser(forumId!, topicIds[index === -1 ? 0 : index]); } }, '.ListItem-button', true); const handleClick = useLastCallback((e: React.MouseEvent, chatId: string) => { const chatsById = getGlobal().chats.byId; const chat = chatsById?.[chatId]; if (chat?.isForum) { if (!chat.topics) loadTopics({ chatId }); setForumId(chatId); resetSearch(); } else { onSelectChatOrUser(chatId); } }); const handleTopicClick = useLastCallback((e: React.MouseEvent, topicId: number) => { onSelectChatOrUser(forumId!, topicId); }); function renderTopicList() { return ( <>
{topicIds ? topicIds.map((topicId, i) => (
{renderText(topics[topicId].title)}
)) : }
); } function renderChatList() { return ( <>
{viewportIds?.length ? ( {viewportIds.map((id, i) => ( {isUserId(id) ? ( ) : ( )} ))} ) : viewportIds && !viewportIds.length ? (

{lang('lng_blocked_list_not_found')}

) : ( )} ); } return ( {() => { return activeKey === TOPIC_LIST_SLIDE ? renderTopicList() : renderChatList(); }} ); }; export default memo(ChatOrUserPicker);