mirror of
https://github.com/danog/telegram-tt.git
synced 2025-01-22 05:11:55 +01:00
Left Search, New Chat, Forward Picker: Order chats by last message, check rights to post, add archived
This commit is contained in:
parent
79cde7292b
commit
1984318297
@ -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;
|
||||
}
|
||||
|
@ -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<OwnProps & StateProps & DispatchProps> = ({
|
||||
typingStatus,
|
||||
avatarSize = 'medium',
|
||||
withMediaViewer,
|
||||
withHandle,
|
||||
withUsername,
|
||||
withFullInfo,
|
||||
withUpdatingStatus,
|
||||
withChatType,
|
||||
@ -102,7 +102,7 @@ const GroupChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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<OwnProps & StateProps & DispatchProps> = ({
|
||||
avatarSize = 'medium',
|
||||
status,
|
||||
withMediaViewer,
|
||||
withHandle,
|
||||
withUsername,
|
||||
withFullInfo,
|
||||
withUpdatingStatus,
|
||||
noStatusOrTyping,
|
||||
@ -103,7 +103,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
|
||||
return (
|
||||
<div className={`status ${isUserOnline(user) ? 'online' : ''}`}>
|
||||
{withHandle && user.username && <span className="handle">{user.username}</span>}
|
||||
{withUsername && user.username && <span className="handle">{user.username}</span>}
|
||||
<span className="user-status">{getUserStatus(user, lang)}</span>
|
||||
</div>
|
||||
);
|
||||
@ -129,7 +129,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
{user && user.isVerified && <VerifiedIcon />}
|
||||
</div>
|
||||
)}
|
||||
{!isSavedMessages && !noStatusOrTyping && renderStatusOrTyping()}
|
||||
{(status || (!isSavedMessages && !noStatusOrTyping)) && renderStatusOrTyping()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -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<OwnProps & StateProps & DispatchProps> = ({
|
||||
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));
|
||||
|
@ -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<number, ApiUser>;
|
||||
chatsById: Record<number, ApiChat>;
|
||||
localContactIds?: number[];
|
||||
searchQuery?: string;
|
||||
isSearching?: boolean;
|
||||
localUsers?: ApiUser[];
|
||||
globalUsers?: ApiUser[];
|
||||
localUserIds?: number[];
|
||||
globalUserIds?: number[];
|
||||
};
|
||||
|
||||
type DispatchProps = Pick<GlobalActions, 'loadContactList' | 'setGlobalSearchQuery'>;
|
||||
@ -46,11 +47,12 @@ const NewChatStep1: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
onReset,
|
||||
currentUserId,
|
||||
usersById,
|
||||
chatsById,
|
||||
localContactIds,
|
||||
searchQuery,
|
||||
isSearching,
|
||||
localUsers,
|
||||
globalUsers,
|
||||
localUserIds,
|
||||
globalUserIds,
|
||||
loadContactList,
|
||||
setGlobalSearchQuery,
|
||||
}) => {
|
||||
@ -67,13 +69,15 @@ const NewChatStep1: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
}, [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<OwnProps & StateProps & DispatchProps> = ({
|
||||
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<OwnProps>(
|
||||
(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<OwnProps>(
|
||||
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']),
|
||||
|
@ -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<number, { byId: Record<number, ApiMessage> }>;
|
||||
chatsById: Record<number, ApiChat>;
|
||||
@ -55,12 +55,11 @@ type DispatchProps = Pick<GlobalActions, (
|
||||
const MIN_QUERY_LENGTH_FOR_GLOBAL_SEARCH = 4;
|
||||
const LESS_LIST_ITEMS_AMOUNT = 3;
|
||||
|
||||
const sortSearchResults = (a: ApiChat | ApiUser, b: ApiChat | ApiUser) => Number(b.isVerified) - Number(a.isVerified);
|
||||
const runThrottled = throttle((cb) => cb(), 500, true);
|
||||
|
||||
const ChatResults: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
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<OwnProps & StateProps & DispatchProps> = ({
|
||||
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<OwnProps & StateProps & DispatchProps> = ({
|
||||
|
||||
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<OwnProps & StateProps & DispatchProps> = ({
|
||||
return (
|
||||
<LeftSearchResultChat
|
||||
chatId={id}
|
||||
withHandle
|
||||
withUsername
|
||||
onClick={handleChatClick}
|
||||
/>
|
||||
);
|
||||
@ -283,21 +282,18 @@ export default memo(withGlobal<OwnProps>(
|
||||
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,
|
||||
|
@ -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<OwnProps & StateProps> = ({
|
||||
chat,
|
||||
privateChatUser,
|
||||
isPinned,
|
||||
withHandle,
|
||||
withUsername,
|
||||
onClick,
|
||||
}) => {
|
||||
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useFlag();
|
||||
@ -53,9 +53,9 @@ const LeftSearchResultChat: FC<OwnProps & StateProps> = ({
|
||||
contextActions={contextActions}
|
||||
>
|
||||
{isChatPrivate(chatId) ? (
|
||||
<PrivateChatInfo userId={chatId} withHandle={withHandle} avatarSize="large" />
|
||||
<PrivateChatInfo userId={chatId} withUsername={withUsername} avatarSize="large" />
|
||||
) : (
|
||||
<GroupChatInfo chatId={chatId} withHandle={withHandle} avatarSize="large" />
|
||||
<GroupChatInfo chatId={chatId} withUsername={withUsername} avatarSize="large" />
|
||||
)}
|
||||
<DeleteChatModal
|
||||
isOpen={isDeleteModalOpen}
|
||||
|
@ -4,11 +4,12 @@ import React, {
|
||||
import { withGlobal } from '../../lib/teact/teactn';
|
||||
|
||||
import { GlobalActions } from '../../global/types';
|
||||
import { ApiChat, ApiUser } from '../../api/types';
|
||||
import { ApiChat, MAIN_THREAD_ID } from '../../api/types';
|
||||
|
||||
import { IS_MOBILE_SCREEN } from '../../util/environment';
|
||||
import { getChatTitle, prepareChatList, isChatPrivate } from '../../modules/helpers';
|
||||
import { selectUser } from '../../modules/selectors';
|
||||
import {
|
||||
getCanPostInChat, getChatTitle, isChatPrivate, sortChatIds,
|
||||
} from '../../modules/helpers';
|
||||
import searchWords from '../../util/searchWords';
|
||||
import { pick } from '../../util/iteratees';
|
||||
import useInfiniteScroll from '../../hooks/useInfiniteScroll';
|
||||
@ -31,9 +32,10 @@ export type OwnProps = {
|
||||
|
||||
type StateProps = {
|
||||
chatsById: Record<number, ApiChat>;
|
||||
listIds?: number[];
|
||||
activeListIds?: number[];
|
||||
archivedListIds?: number[];
|
||||
orderedPinnedIds?: number[];
|
||||
currentUser?: ApiUser;
|
||||
currentUserId?: number;
|
||||
};
|
||||
|
||||
type DispatchProps = Pick<GlobalActions, 'setForwardChatId' | 'exitForwardMode' | 'loadMoreChats'>;
|
||||
@ -44,9 +46,9 @@ const MODAL_HIDE_DELAY_MS = 300;
|
||||
|
||||
const ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
chatsById,
|
||||
listIds,
|
||||
orderedPinnedIds,
|
||||
currentUser,
|
||||
activeListIds,
|
||||
archivedListIds,
|
||||
currentUserId,
|
||||
isOpen,
|
||||
setForwardChatId,
|
||||
exitForwardMode,
|
||||
@ -78,30 +80,31 @@ const ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
}
|
||||
}, [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<OwnProps & StateProps & DispatchProps> = ({
|
||||
onClick={() => setForwardChatId({ id })}
|
||||
>
|
||||
{isChatPrivate(id) ? (
|
||||
<PrivateChatInfo userId={id} />
|
||||
<PrivateChatInfo status={id === currentUserId ? lang('SavedMessagesInfo') : undefined} userId={id} />
|
||||
) : (
|
||||
<GroupChatInfo chatId={id} />
|
||||
)}
|
||||
@ -174,16 +177,15 @@ export default memo(withGlobal<OwnProps>(
|
||||
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']),
|
||||
|
@ -152,7 +152,7 @@ const MentionMenu: FC<OwnProps> = ({
|
||||
<PrivateChatInfo
|
||||
userId={userId}
|
||||
avatarSize="small"
|
||||
withHandle
|
||||
withUsername
|
||||
/>
|
||||
</ListItem>
|
||||
))}
|
||||
|
@ -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(
|
||||
|
@ -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<OwnProps & StateProps & DispatchProps> = ({
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return getSortedUserIds(members.map(({ userId }) => userId), usersById);
|
||||
return sortUserIds(members.map(({ userId }) => userId), usersById);
|
||||
}, [members, usersById]);
|
||||
|
||||
const handleMemberClick = useCallback((id: number) => {
|
||||
|
@ -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<OwnProps & StateProps> = ({
|
||||
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) => {
|
||||
|
@ -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);
|
||||
|
@ -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<Record<ApiGlobalMessageSearchType, {
|
||||
totalCount?: number;
|
||||
|
@ -65,7 +65,7 @@ addReducer('searchMessagesGlobal', (global, actions, payload) => {
|
||||
});
|
||||
|
||||
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),
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -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<number, ApiChat>,
|
||||
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');
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ export function isUserBot(user: ApiUser) {
|
||||
return user.type === 'userTypeBot';
|
||||
}
|
||||
|
||||
export function getSortedUserIds(
|
||||
export function sortUserIds(
|
||||
userIds: number[],
|
||||
usersById: Record<number, ApiUser>,
|
||||
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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user