TelegramPWA/src/components/right/hooks/useProfileViewportIds.ts
2023-07-05 13:23:13 +02:00

174 lines
5.4 KiB
TypeScript

import { useMemo, useRef } from '../../../lib/teact/teact';
import type {
ApiChat, ApiChatMember, ApiMessage, ApiUser, ApiUserStatus,
} from '../../../api/types';
import type { ProfileTabType, SharedMediaType } from '../../../types';
import { MEMBERS_SLICE, MESSAGE_SEARCH_SLICE, SHARED_MEDIA_SLICE } from '../../../config';
import { getMessageContentIds, sortChatIds, sortUserIds } from '../../../global/helpers';
import useSyncEffect from '../../../hooks/useSyncEffect';
import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
export default function useProfileViewportIds(
loadMoreMembers: AnyToVoidFunction,
loadCommonChats: AnyToVoidFunction,
searchMessages: AnyToVoidFunction,
tabType: ProfileTabType,
mediaSearchType?: SharedMediaType,
groupChatMembers?: ApiChatMember[],
commonChatIds?: string[],
usersById?: Record<string, ApiUser>,
userStatusesById?: Record<string, ApiUserStatus>,
chatsById?: Record<string, ApiChat>,
chatMessages?: Record<number, ApiMessage>,
foundIds?: number[],
topicId?: number,
) {
const resultType = tabType === 'members' || !mediaSearchType ? tabType : mediaSearchType;
const memberIds = useMemo(() => {
if (!groupChatMembers || !usersById || !userStatusesById) {
return undefined;
}
return sortUserIds(
groupChatMembers.map(({ userId }) => userId),
usersById,
userStatusesById,
);
}, [groupChatMembers, usersById, userStatusesById]);
const chatIds = useMemo(() => {
if (!commonChatIds || !chatsById) {
return undefined;
}
return sortChatIds(commonChatIds, chatsById, true);
}, [chatsById, commonChatIds]);
const [memberViewportIds, getMoreMembers, noProfileInfoForMembers] = useInfiniteScrollForLoadableItems(
loadMoreMembers, memberIds,
);
const [mediaViewportIds, getMoreMedia, noProfileInfoForMedia] = useInfiniteScrollForSharedMedia(
'media', resultType, searchMessages, chatMessages, foundIds, topicId,
);
const [documentViewportIds, getMoreDocuments, noProfileInfoForDocuments] = useInfiniteScrollForSharedMedia(
'documents', resultType, searchMessages, chatMessages, foundIds, topicId,
);
const [linkViewportIds, getMoreLinks, noProfileInfoForLinks] = useInfiniteScrollForSharedMedia(
'links', resultType, searchMessages, chatMessages, foundIds, topicId,
);
const [audioViewportIds, getMoreAudio, noProfileInfoForAudio] = useInfiniteScrollForSharedMedia(
'audio', resultType, searchMessages, chatMessages, foundIds, topicId,
);
const [voiceViewportIds, getMoreVoices, noProfileInfoForVoices] = useInfiniteScrollForSharedMedia(
'voice', resultType, searchMessages, chatMessages, foundIds, topicId,
);
const [commonChatViewportIds, getMoreCommonChats, noProfileInfoForCommonChats] = useInfiniteScrollForLoadableItems(
loadCommonChats, chatIds,
);
let viewportIds: number[] | string[] | undefined;
let getMore: AnyToVoidFunction | undefined;
let noProfileInfo = false;
switch (resultType) {
case 'members':
viewportIds = memberViewportIds;
getMore = getMoreMembers;
noProfileInfo = noProfileInfoForMembers;
break;
case 'commonChats':
viewportIds = commonChatViewportIds;
getMore = getMoreCommonChats;
noProfileInfo = noProfileInfoForCommonChats;
break;
case 'media':
viewportIds = mediaViewportIds;
getMore = getMoreMedia;
noProfileInfo = noProfileInfoForMedia;
break;
case 'documents':
viewportIds = documentViewportIds;
getMore = getMoreDocuments;
noProfileInfo = noProfileInfoForDocuments;
break;
case 'links':
viewportIds = linkViewportIds;
getMore = getMoreLinks;
noProfileInfo = noProfileInfoForLinks;
break;
case 'audio':
viewportIds = audioViewportIds;
getMore = getMoreAudio;
noProfileInfo = noProfileInfoForAudio;
break;
case 'voice':
viewportIds = voiceViewportIds;
getMore = getMoreVoices;
noProfileInfo = noProfileInfoForVoices;
break;
}
return [resultType, viewportIds, getMore, noProfileInfo] as const;
}
function useInfiniteScrollForLoadableItems(
handleLoadMore?: AnyToVoidFunction,
itemIds?: string[],
) {
const [viewportIds, getMore] = useInfiniteScroll(
handleLoadMore,
itemIds,
undefined,
MEMBERS_SLICE,
);
const isOnTop = !viewportIds || !itemIds || viewportIds[0] === itemIds[0];
return [viewportIds, getMore, !isOnTop] as const;
}
function useInfiniteScrollForSharedMedia(
forSharedMediaType: SharedMediaType,
currentResultType?: ProfileTabType,
handleLoadMore?: AnyToVoidFunction,
chatMessages?: Record<number, ApiMessage>,
foundIds?: number[],
topicId?: number,
) {
const messageIdsRef = useRef<number[]>();
useSyncEffect(() => {
messageIdsRef.current = undefined;
}, [topicId]);
useSyncEffect(() => {
if (currentResultType === forSharedMediaType && chatMessages && foundIds) {
messageIdsRef.current = getMessageContentIds(
chatMessages,
foundIds,
forSharedMediaType,
);
}
}, [chatMessages, foundIds, currentResultType, forSharedMediaType]);
const [viewportIds, getMore] = useInfiniteScroll(
handleLoadMore,
messageIdsRef.current,
undefined,
forSharedMediaType === 'media' ? SHARED_MEDIA_SLICE : MESSAGE_SEARCH_SLICE,
);
const isOnTop = !viewportIds || !messageIdsRef.current || viewportIds[0] === messageIdsRef.current[0];
return [viewportIds, getMore, !isOnTop] as const;
}