import React, { FC, useCallback, useRef, useEffect, memo, } from '../../../../lib/teact/teact'; import { isChatPrivate } from '../../../../modules/helpers'; import { INCLUDED_CHAT_TYPES, EXCLUDED_CHAT_TYPES, FolderChatType, } from '../../../../hooks/reducers/useFoldersReducer'; import useInfiniteScroll from '../../../../hooks/useInfiniteScroll'; import useLang from '../../../../hooks/useLang'; 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: number[]; selectedIds: number[]; selectedChatTypes: string[]; filterValue?: string; onSelectedIdsChange: (ids: number[]) => void; onSelectedChatTypesChange: (types: string[]) => void; onFilterChange: (value: string) => void; onLoadMore: () => void; }; // Focus slows down animation, also it breaks transition layout in Chrome const FOCUS_DELAY_MS = 500; const MAX_CHATS = 100; const MAX_FULL_ITEMS = 10; const ALWAYS_FULL_ITEMS_COUNT = 5; const SettingsFoldersChatsPicker: FC = ({ mode, chatIds, selectedIds, selectedChatTypes, filterValue, onSelectedIdsChange, onSelectedChatTypesChange, onFilterChange, onLoadMore, }) => { // 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; const hasMaxChats = selectedIds.length >= MAX_CHATS; useEffect(() => { setTimeout(() => { requestAnimationFrame(() => { inputRef.current!.focus(); }); }, FOCUS_DELAY_MS); }, []); const handleItemClick = useCallback((id: number) => { const newSelectedIds = [...selectedIds]; if (newSelectedIds.includes(id)) { newSelectedIds.splice(newSelectedIds.indexOf(id), 1); } else { newSelectedIds.push(id); } onSelectedIdsChange(newSelectedIds); }, [selectedIds, onSelectedIdsChange]); 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: number) { const isSelected = selectedIds.includes(id); return ( handleItemClick(id)} ripple disabled={!isSelected && hasMaxChats} > {isChatPrivate(id) ? ( ) : ( )} ); } const [viewportIds, getMore] = useInfiniteScroll(onLoadMore, chatIds, Boolean(filterValue)); return (
{selectedChatTypes.map(renderSelectedChatType)} {selectedIds.map((id, i) => ( ))} {!hasMaxChats ? ( ) : (

{`Sorry, you can't add more than ${MAX_CHATS} chats.`}

)}
{(!viewportIds || !viewportIds.length || viewportIds.includes(chatIds[0])) && ( <>

{lang('FilterChatTypes')}

{chatTypes.map(renderChatType)}

{lang('FilterChats')}

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

Sorry, nothing found.

) : ( )}
); }; export default memo(SettingsFoldersChatsPicker);