From 19843182971402205a64ff6ec8c9f7c221aafffa Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Thu, 6 May 2021 01:47:48 +0300 Subject: [PATCH] Left Search, New Chat, Forward Picker: Order chats by last message, check rights to post, add archived --- src/api/gramjs/methods/chats.ts | 4 +- src/components/common/GroupChatInfo.tsx | 6 +- src/components/common/PrivateChatInfo.tsx | 8 +-- src/components/left/main/ContactList.tsx | 4 +- src/components/left/newChat/NewChatStep1.tsx | 47 +++++++----- src/components/left/search/ChatResults.tsx | 58 +++++++-------- .../left/search/LeftSearchResultChat.tsx | 8 +-- src/components/main/ForwardPicker.tsx | 72 ++++++++++--------- .../middle/composer/MentionMenu.tsx | 2 +- .../right/hooks/useProfileViewportIds.ts | 4 +- .../right/management/ManageGroupMembers.tsx | 4 +- .../ManageGroupUserPermissionsCreate.tsx | 4 +- src/components/ui/ListItem.scss | 1 + src/global/types.ts | 8 +-- src/modules/actions/api/globalSearch.ts | 10 +-- src/modules/helpers/chats.ts | 38 +++++++++- src/modules/helpers/users.ts | 13 ++-- 17 files changed, 165 insertions(+), 126 deletions(-) diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index ff8b716a5..e7ddba2a8 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -163,8 +163,8 @@ export function fetchFullChat(chat: ApiChat) { : getFullChatInfo(input as number); } -export async function searchChats({ query, limit }: { query: string; limit?: number }) { - const result = await invokeRequest(new GramJs.contacts.Search({ q: query, limit })); +export async function searchChats({ query }: { query: string }) { + const result = await invokeRequest(new GramJs.contacts.Search({ q: query })); if (!result) { return undefined; } diff --git a/src/components/common/GroupChatInfo.tsx b/src/components/common/GroupChatInfo.tsx index 694b78346..003c602b8 100644 --- a/src/components/common/GroupChatInfo.tsx +++ b/src/components/common/GroupChatInfo.tsx @@ -27,7 +27,7 @@ type OwnProps = { typingStatus?: ApiTypingStatus; avatarSize?: 'small' | 'medium' | 'large' | 'jumbo'; withMediaViewer?: boolean; - withHandle?: boolean; + withUsername?: boolean; withFullInfo?: boolean; withUpdatingStatus?: boolean; withChatType?: boolean; @@ -45,7 +45,7 @@ const GroupChatInfo: FC = ({ typingStatus, avatarSize = 'medium', withMediaViewer, - withHandle, + withUsername, withFullInfo, withUpdatingStatus, withChatType, @@ -102,7 +102,7 @@ const GroupChatInfo: FC = ({ ); } - const handle = withHandle ? chat.username : undefined; + const handle = withUsername ? chat.username : undefined; const groupStatus = getGroupStatus(chat, lang); const onlineStatus = onlineCount ? `, ${lang('OnlineCount', onlineCount, 'i')}` : undefined; diff --git a/src/components/common/PrivateChatInfo.tsx b/src/components/common/PrivateChatInfo.tsx index 4aa0d6a6b..067384a60 100644 --- a/src/components/common/PrivateChatInfo.tsx +++ b/src/components/common/PrivateChatInfo.tsx @@ -25,7 +25,7 @@ type OwnProps = { forceShowSelf?: boolean; status?: string; withMediaViewer?: boolean; - withHandle?: boolean; + withUsername?: boolean; withFullInfo?: boolean; withUpdatingStatus?: boolean; noStatusOrTyping?: boolean; @@ -44,7 +44,7 @@ const PrivateChatInfo: FC = ({ avatarSize = 'medium', status, withMediaViewer, - withHandle, + withUsername, withFullInfo, withUpdatingStatus, noStatusOrTyping, @@ -103,7 +103,7 @@ const PrivateChatInfo: FC = ({ return (
- {withHandle && user.username && {user.username}} + {withUsername && user.username && {user.username}} {getUserStatus(user, lang)}
); @@ -129,7 +129,7 @@ const PrivateChatInfo: FC = ({ {user && user.isVerified && } )} - {!isSavedMessages && !noStatusOrTyping && renderStatusOrTyping()} + {(status || (!isSavedMessages && !noStatusOrTyping)) && renderStatusOrTyping()} ); diff --git a/src/components/left/main/ContactList.tsx b/src/components/left/main/ContactList.tsx index 43191559c..1dab6c367 100644 --- a/src/components/left/main/ContactList.tsx +++ b/src/components/left/main/ContactList.tsx @@ -10,7 +10,7 @@ import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { throttle } from '../../../util/schedulers'; import searchWords from '../../../util/searchWords'; import { pick } from '../../../util/iteratees'; -import { getUserFullName, getSortedUserIds } from '../../../modules/helpers'; +import { getUserFullName, sortUserIds } from '../../../modules/helpers'; import useInfiniteScroll from '../../../hooks/useInfiniteScroll'; import PrivateChatInfo from '../../common/PrivateChatInfo'; @@ -63,7 +63,7 @@ const ContactList: FC = ({ return fullName && searchWords(fullName, filter); }) : contactIds; - return getSortedUserIds(resultIds, usersById); + return sortUserIds(resultIds, usersById); }, [filter, usersById, contactIds]); const [viewportIds, getMore] = useInfiniteScroll(undefined, listIds, Boolean(filter)); diff --git a/src/components/left/newChat/NewChatStep1.tsx b/src/components/left/newChat/NewChatStep1.tsx index 479e8d104..42c6ade67 100644 --- a/src/components/left/newChat/NewChatStep1.tsx +++ b/src/components/left/newChat/NewChatStep1.tsx @@ -4,12 +4,12 @@ import React, { import { withGlobal } from '../../../lib/teact/teactn'; import { GlobalActions } from '../../../global/types'; -import { ApiUser } from '../../../api/types'; +import { ApiChat, ApiUser } from '../../../api/types'; import { pick, unique } from '../../../util/iteratees'; import { throttle } from '../../../util/schedulers'; import searchWords from '../../../util/searchWords'; -import { getSortedUserIds, getUserFullName } from '../../../modules/helpers'; +import { getUserFullName, sortChatIds } from '../../../modules/helpers'; import useLang from '../../../hooks/useLang'; import Picker from '../../common/Picker'; @@ -27,11 +27,12 @@ export type OwnProps = { type StateProps = { currentUserId?: number; usersById: Record; + chatsById: Record; localContactIds?: number[]; searchQuery?: string; isSearching?: boolean; - localUsers?: ApiUser[]; - globalUsers?: ApiUser[]; + localUserIds?: number[]; + globalUserIds?: number[]; }; type DispatchProps = Pick; @@ -46,11 +47,12 @@ const NewChatStep1: FC = ({ onReset, currentUserId, usersById, + chatsById, localContactIds, searchQuery, isSearching, - localUsers, - globalUsers, + localUserIds, + globalUserIds, loadContactList, setGlobalSearchQuery, }) => { @@ -67,13 +69,15 @@ const NewChatStep1: FC = ({ }, [setGlobalSearchQuery]); const displayedIds = useMemo(() => { - const contactIds = localContactIds ? localContactIds.filter((id) => id !== currentUserId) : []; + const contactIds = localContactIds + ? sortChatIds(localContactIds.filter((id) => id !== currentUserId), chatsById) + : []; if (!searchQuery) { return contactIds; } - const foundLocalContacts = contactIds.filter((id) => { + const foundContactIds = contactIds.filter((id) => { const user = usersById[id]; if (!user) { return false; @@ -82,16 +86,19 @@ const NewChatStep1: FC = ({ return fullName && searchWords(fullName, searchQuery); }); - return getSortedUserIds( + return sortChatIds( unique([ - ...foundLocalContacts, - ...(localUsers ? localUsers.map((user) => user.id) : []), - ...(globalUsers ? globalUsers.map((user) => user.id) : []), - ]) as number[], - usersById, + ...foundContactIds, + ...(localUserIds || []), + ...(globalUserIds || []), + ]), + chatsById, + false, selectedMemberIds, ); - }, [localContactIds, searchQuery, localUsers, globalUsers, usersById, selectedMemberIds, currentUserId]); + }, [ + localContactIds, searchQuery, localUserIds, globalUserIds, usersById, chatsById, selectedMemberIds, currentUserId, + ]); const handleNextStep = useCallback(() => { if (selectedMemberIds.length) { @@ -144,6 +151,7 @@ export default memo(withGlobal( (global): StateProps => { const { userIds: localContactIds } = global.contactList || {}; const { byId: usersById } = global.users; + const { byId: chatsById } = global.chats; const { currentUserId } = global; const { @@ -152,17 +160,18 @@ export default memo(withGlobal( globalResults, localResults, } = global.globalSearch; - const { users: globalUsers } = globalResults || {}; - const { users: localUsers } = localResults || {}; + const { userIds: globalUserIds } = globalResults || {}; + const { userIds: localUserIds } = localResults || {}; return { currentUserId, usersById, + chatsById, localContactIds, searchQuery, isSearching: fetchingStatus && fetchingStatus.chats, - globalUsers, - localUsers, + globalUserIds, + localUserIds, }; }, (setGlobal, actions): DispatchProps => pick(actions, ['loadContactList', 'setGlobalSearchQuery']), diff --git a/src/components/left/search/ChatResults.tsx b/src/components/left/search/ChatResults.tsx index 4f7e6d144..312915bc1 100644 --- a/src/components/left/search/ChatResults.tsx +++ b/src/components/left/search/ChatResults.tsx @@ -10,7 +10,7 @@ import { LoadMoreDirection } from '../../../types'; import { IS_MOBILE_SCREEN } from '../../../util/environment'; import searchWords from '../../../util/searchWords'; import { unique, pick } from '../../../util/iteratees'; -import { getUserFullName, getMessageSummaryText } from '../../../modules/helpers'; +import { getUserFullName, getMessageSummaryText, sortChatIds } from '../../../modules/helpers'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { throttle } from '../../../util/schedulers'; import useLang from '../../../hooks/useLang'; @@ -36,10 +36,10 @@ export type OwnProps = { type StateProps = { currentUserId?: number; localContactIds?: number[]; - localChats?: ApiChat[]; - localUsers?: ApiUser[]; - globalChats?: ApiChat[]; - globalUsers?: ApiUser[]; + localChatIds?: number[]; + localUserIds?: number[]; + globalChatIds?: number[]; + globalUserIds?: number[]; foundIds?: string[]; globalMessagesByChatId?: Record }>; chatsById: Record; @@ -55,12 +55,11 @@ type DispatchProps = Pick Number(b.isVerified) - Number(a.isVerified); const runThrottled = throttle((cb) => cb(), 500, true); const ChatResults: FC = ({ searchQuery, searchDate, dateSearchQuery, currentUserId, - localContactIds, localChats, localUsers, globalChats, globalUsers, + localContactIds, localChatIds, localUserIds, globalChatIds, globalUserIds, foundIds, globalMessagesByChatId, chatsById, usersById, fetchingStatus, lastSyncTime, onReset, onSearchDateSelect, openChat, addRecentlyFoundChatId, searchMessagesGlobal, setGlobalSearchChatId, }) => { @@ -102,7 +101,7 @@ const ChatResults: FC = ({ return MEMO_EMPTY_ARRAY; } - const foundLocalContacts = localContactIds + const foundContactIds = localContactIds ? localContactIds.filter((id) => { const user = usersById[id]; if (!user) { @@ -111,26 +110,26 @@ const ChatResults: FC = ({ const fullName = getUserFullName(user); return (fullName && searchWords(fullName, searchQuery)) || searchWords(user.username, searchQuery); - }).map((id) => usersById[id]) + }) : []; - return unique([ - ...(searchWords(getTranslation('SavedMessages'), searchQuery) ? [currentUserId] : []), - ...([ - ...foundLocalContacts, - ...(localChats || []), - ...(localUsers || []), - ].sort(sortSearchResults).map((chat) => chat.id)), - ]) as number[]; - }, [searchQuery, localContactIds, localChats, localUsers, usersById, currentUserId]); + return [ + ...(currentUserId && searchWords(getTranslation('SavedMessages'), searchQuery) ? [currentUserId] : []), + ...sortChatIds(unique([ + ...foundContactIds, + ...(localChatIds || []), + ...(localUserIds || []), + ]), chatsById), + ]; + }, [searchQuery, localContactIds, currentUserId, localChatIds, localUserIds, chatsById, usersById]); const globalResults = useMemo(() => { - if (!searchQuery || searchQuery.length < MIN_QUERY_LENGTH_FOR_GLOBAL_SEARCH || !globalChats || !globalUsers) { + if (!searchQuery || searchQuery.length < MIN_QUERY_LENGTH_FOR_GLOBAL_SEARCH || !globalChatIds || !globalUserIds) { return MEMO_EMPTY_ARRAY; } - return unique([...globalChats, ...globalUsers].sort(sortSearchResults).map((chat) => chat.id)); - }, [globalChats, globalUsers, searchQuery]); + return sortChatIds(unique([...globalChatIds, ...globalUserIds]), chatsById, true); + }, [chatsById, globalChatIds, globalUserIds, searchQuery]); const foundMessages = useMemo(() => { if ((!searchQuery && !searchDate) || !foundIds || foundIds.length === 0) { @@ -248,7 +247,7 @@ const ChatResults: FC = ({ return ( ); @@ -283,21 +282,18 @@ export default memo(withGlobal( const { fetchingStatus, globalResults, localResults, resultsByType, } = global.globalSearch; - const { - chats: globalChats, - users: globalUsers, - } = globalResults || {}; - const { chats: localChats, users: localUsers } = localResults || {}; + const { chatIds: globalChatIds, userIds: globalUserIds } = globalResults || {}; + const { chatIds: localChatIds, userIds: localUserIds } = localResults || {}; const { byChatId: globalMessagesByChatId } = messages; const { foundIds } = (resultsByType && resultsByType.text) || {}; return { currentUserId, localContactIds, - localChats, - localUsers, - globalChats, - globalUsers, + localChatIds, + localUserIds, + globalChatIds, + globalUserIds, foundIds, globalMessagesByChatId, chatsById, diff --git a/src/components/left/search/LeftSearchResultChat.tsx b/src/components/left/search/LeftSearchResultChat.tsx index 13d83b4a0..7def4aed3 100644 --- a/src/components/left/search/LeftSearchResultChat.tsx +++ b/src/components/left/search/LeftSearchResultChat.tsx @@ -15,7 +15,7 @@ import ListItem from '../../ui/ListItem'; type OwnProps = { chatId: number; - withHandle?: boolean; + withUsername?: boolean; onClick: (id: number) => void; }; @@ -30,7 +30,7 @@ const LeftSearchResultChat: FC = ({ chat, privateChatUser, isPinned, - withHandle, + withUsername, onClick, }) => { const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useFlag(); @@ -53,9 +53,9 @@ const LeftSearchResultChat: FC = ({ contextActions={contextActions} > {isChatPrivate(chatId) ? ( - + ) : ( - + )} ; - listIds?: number[]; + activeListIds?: number[]; + archivedListIds?: number[]; orderedPinnedIds?: number[]; - currentUser?: ApiUser; + currentUserId?: number; }; type DispatchProps = Pick; @@ -44,9 +46,9 @@ const MODAL_HIDE_DELAY_MS = 300; const ForwardPicker: FC = ({ chatsById, - listIds, - orderedPinnedIds, - currentUser, + activeListIds, + archivedListIds, + currentUserId, isOpen, setForwardChatId, exitForwardMode, @@ -78,30 +80,31 @@ const ForwardPicker: FC = ({ } }, [isOpen]); - const chats = useMemo(() => { - const chatArrays = listIds ? prepareChatList(chatsById, listIds, orderedPinnedIds) : undefined; - if (!chatArrays) { - return undefined; - } - - const chatWithSelf = currentUser ? chatsById[currentUser.id] : undefined; - - return [ - ...(chatWithSelf ? [chatWithSelf] : []), - ...chatArrays.pinnedChats.filter(({ id }) => !chatWithSelf || id !== chatWithSelf.id), - ...chatArrays.otherChats.filter(({ id }) => !chatWithSelf || id !== chatWithSelf.id), - ]; - }, [chatsById, listIds, orderedPinnedIds, currentUser]); - const chatIds = useMemo(() => { - if (!chats) { - return undefined; - } + const listIds = [ + ...activeListIds || [], + ...archivedListIds || [], + ]; - return chats - .filter((chat) => (!filter || searchWords(getChatTitle(chat, currentUser), filter))) - .map(({ id }) => id); - }, [chats, filter, currentUser]); + return sortChatIds([ + ...listIds.filter((id) => { + const chat = chatsById[id]; + if (!chat) { + return true; + } + + if (!getCanPostInChat(chat, MAIN_THREAD_ID)) { + return false; + } + + if (!filter) { + return true; + } + + return searchWords(getChatTitle(chatsById[id], undefined, id === currentUserId), filter); + }), + ], chatsById, undefined, currentUserId ? [currentUserId] : undefined); + }, [activeListIds, archivedListIds, chatsById, currentUserId, filter]); const [viewportIds, getMore] = useInfiniteScroll(loadMoreChats, chatIds, Boolean(filter)); @@ -152,7 +155,7 @@ const ForwardPicker: FC = ({ onClick={() => setForwardChatId({ id })} > {isChatPrivate(id) ? ( - + ) : ( )} @@ -174,16 +177,15 @@ export default memo(withGlobal( chats: { byId: chatsById, listIds, - orderedPinnedIds, }, currentUserId, } = global; return { chatsById, - listIds: listIds.active, - orderedPinnedIds: orderedPinnedIds.active, - currentUser: currentUserId ? selectUser(global, currentUserId) : undefined, + activeListIds: listIds.active, + archivedListIds: listIds.archived, + currentUserId, }; }, (setGlobal, actions): DispatchProps => pick(actions, ['setForwardChatId', 'exitForwardMode', 'loadMoreChats']), diff --git a/src/components/middle/composer/MentionMenu.tsx b/src/components/middle/composer/MentionMenu.tsx index 1ce330a7b..73e3d58d7 100644 --- a/src/components/middle/composer/MentionMenu.tsx +++ b/src/components/middle/composer/MentionMenu.tsx @@ -152,7 +152,7 @@ const MentionMenu: FC = ({ ))} diff --git a/src/components/right/hooks/useProfileViewportIds.ts b/src/components/right/hooks/useProfileViewportIds.ts index 4b66a20a4..60de4294d 100644 --- a/src/components/right/hooks/useProfileViewportIds.ts +++ b/src/components/right/hooks/useProfileViewportIds.ts @@ -4,7 +4,7 @@ import { ApiChatMember, ApiMessage, ApiUser } from '../../../api/types'; import { ProfileTabType, SharedMediaType } from '../../../types'; import { MESSAGE_SEARCH_SLICE, SHARED_MEDIA_SLICE } from '../../../config'; -import { getMessageContentIds, getSortedUserIds } from '../../../modules/helpers'; +import { getMessageContentIds, sortUserIds } from '../../../modules/helpers'; import useOnChange from '../../../hooks/useOnChange'; import useInfiniteScroll from '../../../hooks/useInfiniteScroll'; @@ -27,7 +27,7 @@ export default function useProfileViewportIds( return undefined; } - return getSortedUserIds(groupChatMembers.map(({ userId }) => userId), usersById); + return sortUserIds(groupChatMembers.map(({ userId }) => userId), usersById); }, [groupChatMembers, usersById]); const [mediaViewportIds, getMoreMedia, noProfileInfoForMedia] = useInfiniteScrollForSharedMedia( diff --git a/src/components/right/management/ManageGroupMembers.tsx b/src/components/right/management/ManageGroupMembers.tsx index c2392efd9..87bf55967 100644 --- a/src/components/right/management/ManageGroupMembers.tsx +++ b/src/components/right/management/ManageGroupMembers.tsx @@ -6,7 +6,7 @@ import { withGlobal } from '../../../lib/teact/teactn'; import { ApiChatMember, ApiUser } from '../../../api/types'; import { GlobalActions } from '../../../global/types'; import { selectChat } from '../../../modules/selectors'; -import { getSortedUserIds, isChatChannel } from '../../../modules/helpers'; +import { sortUserIds, isChatChannel } from '../../../modules/helpers'; import { pick } from '../../../util/iteratees'; import PrivateChatInfo from '../../common/PrivateChatInfo'; @@ -36,7 +36,7 @@ const ManageGroupMembers: FC = ({ return undefined; } - return getSortedUserIds(members.map(({ userId }) => userId), usersById); + return sortUserIds(members.map(({ userId }) => userId), usersById); }, [members, usersById]); const handleMemberClick = useCallback((id: number) => { diff --git a/src/components/right/management/ManageGroupUserPermissionsCreate.tsx b/src/components/right/management/ManageGroupUserPermissionsCreate.tsx index 5aa47ec51..4f297d0e2 100644 --- a/src/components/right/management/ManageGroupUserPermissionsCreate.tsx +++ b/src/components/right/management/ManageGroupUserPermissionsCreate.tsx @@ -7,7 +7,7 @@ import { ApiChatMember, ApiUser } from '../../../api/types'; import { ManagementScreens } from '../../../types'; import { selectChat } from '../../../modules/selectors'; -import { getSortedUserIds, isChatChannel } from '../../../modules/helpers'; +import { sortUserIds, isChatChannel } from '../../../modules/helpers'; import PrivateChatInfo from '../../common/PrivateChatInfo'; import ListItem from '../../ui/ListItem'; @@ -37,7 +37,7 @@ const ManageGroupUserPermissionsCreate: FC = ({ return undefined; } - return getSortedUserIds(members.filter((member) => !member.isOwner).map(({ userId }) => userId), usersById); + return sortUserIds(members.filter((member) => !member.isOwner).map(({ userId }) => userId), usersById); }, [members, usersById]); const handleExceptionMemberClick = useCallback((memberId: number) => { diff --git a/src/components/ui/ListItem.scss b/src/components/ui/ListItem.scss index ff9634f47..07c09c64f 100644 --- a/src/components/ui/ListItem.scss +++ b/src/components/ui/ListItem.scss @@ -180,6 +180,7 @@ font-size: 0.875rem; line-height: 1.25rem; color: var(--color-text-secondary); + display: inline-block; &.online { color: var(--color-primary); diff --git a/src/global/types.ts b/src/global/types.ts index ea072a8a1..05c5b5391 100644 --- a/src/global/types.ts +++ b/src/global/types.ts @@ -224,12 +224,12 @@ export type GlobalState = { messages?: boolean; }; localResults?: { - chats?: ApiChat[]; - users?: ApiUser[]; + chatIds?: number[]; + userIds?: number[]; }; globalResults?: { - chats?: ApiChat[]; - users?: ApiUser[]; + chatIds?: number[]; + userIds?: number[]; }; resultsByType?: Partial { }); async function searchChats(query: string) { - const result = await callApi('searchChats', { query, limit: GLOBAL_SEARCH_SLICE }); + const result = await callApi('searchChats', { query }); let global = getGlobal(); const currentSearchQuery = selectCurrentGlobalSearchQuery(global); @@ -89,13 +89,13 @@ async function searchChats(query: string) { global = updateGlobalSearchFetchingStatus(global, { chats: false }); global = updateGlobalSearch(global, { localResults: { - chats: localChats, - users: localUsers, + chatIds: localChats.map(({ id }) => id), + userIds: localUsers.map(({ id }) => id), }, globalResults: { ...global.globalSearch.globalResults, - chats: globalChats, - users: globalUsers, + chatIds: globalUsers.map(({ id }) => id), + userIds: globalChats.map(({ id }) => id), }, }); diff --git a/src/modules/helpers/chats.ts b/src/modules/helpers/chats.ts index 305cbcf44..5cf31a985 100644 --- a/src/modules/helpers/chats.ts +++ b/src/modules/helpers/chats.ts @@ -58,8 +58,9 @@ export function getPrivateChatUserId(chat: ApiChat) { return chat.id; } -export function getChatTitle(chat: ApiChat, user?: ApiUser) { - if (user && chat.id === user.id && user.isSelf) { +// TODO Get rid of `user` +export function getChatTitle(chat: ApiChat, user?: ApiUser, isSelf = false) { + if (isSelf || (user && chat.id === user.id && user.isSelf)) { return getTranslation('SavedMessages'); } return chat.title || getTranslation('HiddenName'); @@ -432,3 +433,36 @@ export function getMessageSenderName(chatId: number, sender?: ApiUser) { return getUserFirstOrLastName(sender); } + +export function sortChatIds( + chatIds: number[], + chatsById: Record, + shouldPrioritizeVerified = false, + priorityIds?: number[], +) { + return orderBy(chatIds, (id) => { + const chat = chatsById[id]; + if (!chat) { + return 0; + } + + let priority = 0; + + if (chat.lastMessage) { + priority += chat.lastMessage.date; + } + + if (shouldPrioritizeVerified && chat.isVerified) { + priority += 3e9; // ~100 years in seconds + } + + if (priorityIds && priorityIds.includes(id)) { + // Assuming that last message date can't be less than now, + // this should place prioritized on top of the list. + // Then we subtract index of `id` in `priorityIds` to preserve selected order + priority += Date.now() + (priorityIds.length - priorityIds.indexOf(id)); + } + + return priority; + }, 'desc'); +} diff --git a/src/modules/helpers/users.ts b/src/modules/helpers/users.ts index 3613d9f7b..e12e5e019 100644 --- a/src/modules/helpers/users.ts +++ b/src/modules/helpers/users.ts @@ -180,7 +180,7 @@ export function isUserBot(user: ApiUser) { return user.type === 'userTypeBot'; } -export function getSortedUserIds( +export function sortUserIds( userIds: number[], usersById: Record, priorityIds?: number[], @@ -189,13 +189,10 @@ export function getSortedUserIds( const now = Date.now() / 1000; if (priorityIds && priorityIds.includes(id)) { - /* - ** Assuming that online status expiration date can't be as far as two days from now, - ** this should place priorityIds on top of the list. - ** - ** We then subtract index of `id` in `priorityIds` to preserve selected order - */ - return now + (48 * 60 * 60) - priorityIds.indexOf(id); + // Assuming that online status expiration date can't be as far as two days from now, + // this should place prioritized on top of the list. + // Then we subtract index of `id` in `priorityIds` to preserve selected order + return now + (48 * 60 * 60) - (priorityIds.length - priorityIds.indexOf(id)); } const user = usersById[id];