mirror of
https://github.com/danog/telegram-tt.git
synced 2025-01-22 05:11:55 +01:00
[Perf] Chat List: Some optimizations
This commit is contained in:
parent
f09de4ca28
commit
1a6f0bb28f
@ -14,7 +14,9 @@ import { ALL_CHATS_PRELOAD_DISABLED, CHAT_HEIGHT_PX, CHAT_LIST_SLICE } from '../
|
||||
import { IS_ANDROID, IS_MAC_OS, IS_PWA } from '../../../util/environment';
|
||||
import usePrevious from '../../../hooks/usePrevious';
|
||||
import { mapValues, pick } from '../../../util/iteratees';
|
||||
import { getChatOrder, prepareChatList, prepareFolderListIds } from '../../../modules/helpers';
|
||||
import {
|
||||
getChatOrder, prepareChatList, prepareFolderListIds, reduceChatList,
|
||||
} from '../../../modules/helpers';
|
||||
import {
|
||||
selectChatFolder, selectNotifyExceptions, selectNotifySettings,
|
||||
} from '../../../modules/selectors';
|
||||
@ -80,19 +82,20 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
: [listIds, orderedPinnedIds];
|
||||
}, [folderType, chatFolder, chatsById, usersById, notifySettings, notifyExceptions, listIds, orderedPinnedIds]);
|
||||
|
||||
const [orderById, orderedIds] = useMemo(() => {
|
||||
const [orderById, orderedIds, chatArrays] = useMemo(() => {
|
||||
if (!currentListIds || (folderType === 'folder' && !chatFolder)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const newChatArrays = prepareChatList(chatsById, currentListIds, currentPinnedIds, folderType);
|
||||
const singleList = [...newChatArrays.pinnedChats, ...newChatArrays.otherChats];
|
||||
const singleList = ([] as ApiChat[]).concat(newChatArrays.pinnedChats, newChatArrays.otherChats);
|
||||
const newOrderedIds = singleList.map(({ id }) => id);
|
||||
const newOrderById = singleList.reduce((acc, chat, i) => {
|
||||
acc[chat.id] = i;
|
||||
return acc;
|
||||
}, {} as Record<string, number>);
|
||||
|
||||
return [newOrderById, newOrderedIds];
|
||||
return [newOrderById, newOrderedIds, newChatArrays];
|
||||
}, [currentListIds, currentPinnedIds, folderType, chatFolder, chatsById]);
|
||||
|
||||
const prevOrderById = usePrevious(orderById);
|
||||
@ -119,8 +122,13 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
folderType === 'all' && !ALL_CHATS_PRELOAD_DISABLED,
|
||||
);
|
||||
|
||||
// TODO Refactor to not call `prepareChatList` twice
|
||||
const chatArrays = viewportIds && prepareChatList(chatsById, viewportIds, currentPinnedIds, folderType);
|
||||
const viewportChatArrays = useMemo(() => {
|
||||
if (!viewportIds || !chatArrays) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return reduceChatList(chatArrays, viewportIds);
|
||||
}, [chatArrays, viewportIds]);
|
||||
|
||||
useEffect(() => {
|
||||
if (lastSyncTime && folderType === 'all') {
|
||||
@ -133,7 +141,7 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
|
||||
function renderChats() {
|
||||
const viewportOffset = orderedIds!.indexOf(viewportIds![0]);
|
||||
const pinnedOffset = viewportOffset + chatArrays!.pinnedChats.length;
|
||||
const pinnedOffset = viewportOffset + viewportChatArrays!.pinnedChats.length;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -142,7 +150,7 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
style={IS_ANDROID ? `height: ${orderedIds!.length * CHAT_HEIGHT_PX}px` : undefined}
|
||||
teactFastList
|
||||
>
|
||||
{chatArrays!.pinnedChats.map(({ id }, i) => (
|
||||
{viewportChatArrays!.pinnedChats.map(({ id }, i) => (
|
||||
<Chat
|
||||
key={id}
|
||||
teactOrderKey={i}
|
||||
@ -155,7 +163,7 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
|
||||
/>
|
||||
))}
|
||||
{chatArrays!.otherChats.map((chat, i) => (
|
||||
{viewportChatArrays!.otherChats.map((chat, i) => (
|
||||
<Chat
|
||||
key={chat.id}
|
||||
teactOrderKey={getChatOrder(chat)}
|
||||
@ -210,7 +218,7 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
noFastList
|
||||
noScrollRestore
|
||||
>
|
||||
{viewportIds?.length && chatArrays ? (
|
||||
{viewportIds?.length && viewportChatArrays ? (
|
||||
renderChats()
|
||||
) : viewportIds && !viewportIds.length ? (
|
||||
(
|
||||
|
@ -24,8 +24,8 @@ export function useChatAnimationType(orderDiffById: Record<string, number>) {
|
||||
if (
|
||||
orderDiff === Infinity
|
||||
|| orderDiff === -Infinity
|
||||
|| (movesUp(chatId) && numberOfUp <= numberOfDown)
|
||||
|| (movesDown(chatId) && numberOfDown < numberOfUp)
|
||||
|| (numberOfUp <= numberOfDown && movesUp(chatId))
|
||||
|| (numberOfDown < numberOfUp && movesDown(chatId))
|
||||
) {
|
||||
return ChatAnimationTypes.Opacity;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ type DispatchProps = Pick<GlobalActions, 'cancelMessageMediaDownload'>;
|
||||
|
||||
const startedDownloads = new Set<string>();
|
||||
|
||||
const DownloadsManager: FC<StateProps & DispatchProps> = ({
|
||||
const DownloadManager: FC<StateProps & DispatchProps> = ({
|
||||
activeDownloads,
|
||||
messages,
|
||||
cancelMessageMediaDownload,
|
||||
@ -78,4 +78,4 @@ export default memo(withGlobal(
|
||||
};
|
||||
},
|
||||
(setGlobal, actions): DispatchProps => pick(actions, ['cancelMessageMediaDownload']),
|
||||
)(DownloadsManager));
|
||||
)(DownloadManager));
|
||||
|
@ -223,11 +223,7 @@ export function getChatSlowModeOptions(chat?: ApiChat) {
|
||||
}
|
||||
|
||||
export function getChatOrder(chat: ApiChat) {
|
||||
return Math.max(
|
||||
chat.joinDate || 0,
|
||||
chat.draftDate || 0,
|
||||
chat.lastMessage ? chat.lastMessage.date : 0,
|
||||
);
|
||||
return Math.max(chat.joinDate || 0, chat.draftDate || 0, chat.lastMessage?.date || 0);
|
||||
}
|
||||
|
||||
export function isChatArchived(chat: ApiChat) {
|
||||
@ -370,8 +366,38 @@ export function prepareChatList(
|
||||
orderedPinnedIds?: string[],
|
||||
folderType: 'all' | 'archived' | 'folder' = 'all',
|
||||
) {
|
||||
function chatFilter(chat?: ApiChat) {
|
||||
if (!chat || !chat.lastMessage || chat.migratedTo) {
|
||||
const listIdsSet = new Set(listIds);
|
||||
const orderedPinnedIdsSet = orderedPinnedIds ? new Set(orderedPinnedIds) : undefined;
|
||||
|
||||
const pinnedChats = orderedPinnedIds?.reduce((acc, id) => {
|
||||
const chat = chatsById[id];
|
||||
|
||||
if (chat && listIdsSet.has(chat.id) && chatFilter(chat, folderType)) {
|
||||
acc.push(chat);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, [] as ApiChat[]) || [];
|
||||
|
||||
const otherChats = listIds.reduce((acc, id) => {
|
||||
const chat = chatsById[id];
|
||||
|
||||
if (chat && (!orderedPinnedIdsSet || !orderedPinnedIdsSet.has(chat.id)) && chatFilter(chat, folderType)) {
|
||||
acc.push(chat);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, [] as ApiChat[]);
|
||||
const otherChatsOrdered = orderBy(otherChats, getChatOrder, 'desc');
|
||||
|
||||
return {
|
||||
pinnedChats,
|
||||
otherChats: otherChatsOrdered,
|
||||
};
|
||||
}
|
||||
|
||||
function chatFilter(chat: ApiChat, folderType: 'all' | 'archived' | 'folder') {
|
||||
if (!chat.lastMessage || chat.migratedTo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -389,33 +415,17 @@ export function prepareChatList(
|
||||
}
|
||||
|
||||
return !chat.isRestricted && !chat.isNotJoined;
|
||||
}
|
||||
}
|
||||
|
||||
const listedChats = listIds
|
||||
.map((id) => chatsById[id])
|
||||
.filter(chatFilter);
|
||||
|
||||
const listIdsSet = new Set(listIds);
|
||||
const pinnedChats = orderedPinnedIds
|
||||
? (
|
||||
orderedPinnedIds
|
||||
.map((id) => chatsById[id])
|
||||
.filter(chatFilter)
|
||||
.filter((chat) => listIdsSet.has(chat.id))
|
||||
)
|
||||
: [];
|
||||
|
||||
const otherChats = orderBy(
|
||||
orderedPinnedIds
|
||||
? listedChats.filter((chat) => !orderedPinnedIds.includes(chat.id))
|
||||
: listedChats,
|
||||
getChatOrder,
|
||||
'desc',
|
||||
);
|
||||
export function reduceChatList(
|
||||
chatArrays: { pinnedChats: ApiChat[]; otherChats: ApiChat[] },
|
||||
filteredIds: string[],
|
||||
) {
|
||||
const filteredIdsSet = new Set(filteredIds);
|
||||
|
||||
return {
|
||||
pinnedChats,
|
||||
otherChats,
|
||||
pinnedChats: chatArrays.pinnedChats.filter(({ id }) => filteredIdsSet.has(id)),
|
||||
otherChats: chatArrays.otherChats.filter(({ id }) => filteredIdsSet.has(id)),
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user