import type { FC } from '../../../../lib/teact/teact'; import React, { useCallback, useRef, useEffect, memo, } from '../../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../../global'; import { isUserId } from '../../../../global/helpers'; import type { FolderChatType } from '../../../../hooks/reducers/useFoldersReducer'; import { INCLUDED_CHAT_TYPES, EXCLUDED_CHAT_TYPES, } from '../../../../hooks/reducers/useFoldersReducer'; import useInfiniteScroll from '../../../../hooks/useInfiniteScroll'; import useLang from '../../../../hooks/useLang'; import { selectCurrentLimit } from '../../../../global/selectors/limits'; import Checkbox from '../../../ui/Checkbox'; import InputText from '../../../ui/InputText'; import ListItem from '../../../ui/ListItem'; import PrivateChatInfo from '../../../common/PrivateChatInfo'; import GroupChatInfo from '../../../common/GroupChatInfo'; import PickerSelectedItem from '../../../common/PickerSelectedItem'; import InfiniteScroll from '../../../ui/InfiniteScroll'; import Loading from '../../../ui/Loading'; import '../../../common/Picker.scss'; import './SettingsFoldersChatsPicker.scss'; type OwnProps = { mode: 'included' | 'excluded'; chatIds: string[]; selectedIds: string[]; selectedChatTypes: string[]; filterValue?: string; onSelectedIdsChange: (ids: string[]) => void; onSelectedChatTypesChange: (types: string[]) => void; onFilterChange: (value: string) => void; }; // Focus slows down animation, also it breaks transition layout in Chrome const FOCUS_DELAY_MS = 500; const MAX_FULL_ITEMS = 10; const ALWAYS_FULL_ITEMS_COUNT = 5; type StateProps = { maxChats: number; }; const SettingsFoldersChatsPicker: FC = ({ mode, chatIds, selectedIds, selectedChatTypes, filterValue, onSelectedIdsChange, onSelectedChatTypesChange, onFilterChange, maxChats, }) => { const { openLimitReachedModal } = getActions(); // eslint-disable-next-line no-null/no-null const inputRef = useRef(null); const chatTypes = mode === 'included' ? INCLUDED_CHAT_TYPES : EXCLUDED_CHAT_TYPES; const shouldMinimize = selectedIds.length + selectedChatTypes.length > MAX_FULL_ITEMS; useEffect(() => { setTimeout(() => { requestAnimationFrame(() => { inputRef.current!.focus(); }); }, FOCUS_DELAY_MS); }, []); const handleItemClick = useCallback((id: string) => { const newSelectedIds = [...selectedIds]; if (newSelectedIds.includes(id)) { newSelectedIds.splice(newSelectedIds.indexOf(id), 1); } else { if (selectedIds.length >= maxChats && mode === 'included') { openLimitReachedModal({ limit: 'dialogFiltersChats', }); return; } newSelectedIds.push(id); } onSelectedIdsChange(newSelectedIds); }, [selectedIds, onSelectedIdsChange, maxChats, mode, openLimitReachedModal]); const handleChatTypeClick = useCallback((key: FolderChatType['key']) => { const newSelectedChatTypes = [...selectedChatTypes]; if (newSelectedChatTypes.includes(key)) { newSelectedChatTypes.splice(newSelectedChatTypes.indexOf(key), 1); } else { newSelectedChatTypes.push(key); } onSelectedChatTypesChange(newSelectedChatTypes); }, [selectedChatTypes, onSelectedChatTypesChange]); const handleFilterChange = useCallback((e: React.ChangeEvent) => { const { value } = e.currentTarget; onFilterChange(value); }, [onFilterChange]); const lang = useLang(); function renderSelectedChatType(key: string) { const selectedType = chatTypes.find(({ key: typeKey }) => key === typeKey); if (!selectedType) { return undefined; } return ( ); } function renderChatType(type: FolderChatType) { return ( handleChatTypeClick(type.key)} ripple >

{lang(type.title)}

); } function renderItem(id: string) { const isSelected = selectedIds.includes(id); return ( handleItemClick(id)} ripple > {isUserId(id) ? ( ) : ( )} ); } const [viewportIds, getMore] = useInfiniteScroll(undefined, chatIds, Boolean(filterValue)); return (
{selectedChatTypes.map(renderSelectedChatType)} {selectedIds.map((id, i) => ( ))}
{(!viewportIds || !viewportIds.length || viewportIds.includes(chatIds[0])) && ( <>

{lang('FilterChatTypes')}

{chatTypes.map(renderChatType)}

{lang('FilterChats')}

)} {viewportIds?.length ? ( viewportIds.map(renderItem) ) : viewportIds && !viewportIds.length ? (

Sorry, nothing found.

) : ( )}
); }; export default memo(withGlobal( (global): StateProps => { return { maxChats: selectCurrentLimit(global, 'dialogFiltersChats'), }; }, )(SettingsFoldersChatsPicker));