import React, { FC, memo, useCallback, useEffect, useMemo, useRef, useState, } from '../../../lib/teact/teact'; import { withGlobal } from '../../../lib/teact/teactn'; import { ApiChat, ApiChatFolder, ApiUser } from '../../../api/types'; import { GlobalActions } from '../../../global/types'; import { IS_TOUCH_ENV } from '../../../util/environment'; import { buildCollectionByKey, pick } from '../../../util/iteratees'; import { captureEvents, SwipeDirection } from '../../../util/captureEvents'; import { getFolderUnreadDialogs } from '../../../modules/helpers'; import useShowTransition from '../../../hooks/useShowTransition'; import buildClassName from '../../../util/buildClassName'; import useThrottledMemo from '../../../hooks/useThrottledMemo'; import useLang from '../../../hooks/useLang'; import Transition from '../../ui/Transition'; import TabList from '../../ui/TabList'; import ChatList from './ChatList'; type StateProps = { chatsById: Record; usersById: Record; chatFoldersById: Record; orderedFolderIds?: number[]; lastSyncTime?: number; }; type DispatchProps = Pick; const INFO_THROTTLE = 3000; const ChatFolders: FC = ({ chatsById, usersById, chatFoldersById, orderedFolderIds, lastSyncTime, loadChatFolders, }) => { // eslint-disable-next-line no-null/no-null const transitionRef = useRef(null); const [activeTab, setActiveTab] = useState(0); useEffect(() => { if (lastSyncTime) { loadChatFolders(); } }, [lastSyncTime, loadChatFolders]); const displayedFolders = useMemo(() => { return orderedFolderIds ? orderedFolderIds.map((id) => chatFoldersById[id] || {}).filter(Boolean) : undefined; }, [chatFoldersById, orderedFolderIds]); const folderCountersById = useThrottledMemo(() => { if (!displayedFolders || !displayedFolders.length) { return undefined; } const chatIds = Object.keys(chatsById).map(Number); const counters = displayedFolders.map((folder) => { const { unreadDialogsCount, hasActiveDialogs, } = getFolderUnreadDialogs(chatsById, usersById, folder, chatIds) || {}; return { id: folder.id, badgeCount: unreadDialogsCount, isBadgeActive: hasActiveDialogs, }; }); return buildCollectionByKey(counters, 'id'); }, INFO_THROTTLE, [displayedFolders, chatsById, usersById]); const folderTabs = useMemo(() => { if (!displayedFolders || !displayedFolders.length) { return undefined; } return [ { title: 'All' }, ...displayedFolders.map((folder) => ({ title: folder.title, ...(folderCountersById && folderCountersById[folder.id]), })), ]; }, [displayedFolders, folderCountersById]); const handleSwitchTab = useCallback((index: number) => { setActiveTab(index); }, []); // Prevent `activeTab` pointing at non-existing folder after update useEffect(() => { if (!folderTabs || !folderTabs.length) { return; } if (activeTab >= folderTabs.length) { setActiveTab(0); } }, [activeTab, folderTabs]); useEffect(() => { if (!transitionRef.current || !IS_TOUCH_ENV || !folderTabs || !folderTabs.length) { return undefined; } return captureEvents(transitionRef.current, { onSwipe: ((e, direction) => { if (direction === SwipeDirection.Left) { setActiveTab(Math.min(activeTab + 1, folderTabs.length - 1)); } else if (direction === SwipeDirection.Right) { setActiveTab(Math.max(0, activeTab - 1)); } }), }); }, [activeTab, folderTabs]); const { shouldRender: shouldRenderPlaceholder, transitionClassNames, } = useShowTransition(!orderedFolderIds, undefined, true); const lang = useLang(); function renderCurrentTab() { const activeFolder = Object.values(chatFoldersById) .find(({ title }) => title === folderTabs![activeTab].title); if (!activeFolder || activeTab === 0) { return ; } return ; } return (
{folderTabs && folderTabs.length ? ( ) : shouldRenderPlaceholder ? (
) : undefined} {renderCurrentTab}
); }; export default memo(withGlobal( (global): StateProps => { const { chats: { byId: chatsById }, users: { byId: usersById }, chatFolders: { byId: chatFoldersById, orderedIds: orderedFolderIds, }, lastSyncTime, } = global; return { chatsById, usersById, chatFoldersById, orderedFolderIds, lastSyncTime, }; }, (setGlobal, actions): DispatchProps => pick(actions, ['loadChatFolders']), )(ChatFolders));