Fix some user loading problems (#1868)

This commit is contained in:
Alexander Zinchuk 2022-05-16 13:34:09 +02:00
parent 69fbf47d7a
commit e4b2b0911f
11 changed files with 52 additions and 57 deletions

View File

@ -12,6 +12,7 @@ import {
ApiChatBannedRights,
ApiChatAdminRights,
ApiGroupCall,
ApiUserStatus,
} from '../../types';
import {
@ -338,6 +339,7 @@ export function clearDraft(chat: ApiChat) {
async function getFullChatInfo(chatId: string): Promise<{
fullInfo: ApiChatFullInfo;
users?: ApiUser[];
userStatusesById?: { [userId: string]: ApiUserStatus };
groupCall?: Partial<ApiGroupCall>;
membersCount?: number;
} | undefined> {
@ -365,6 +367,7 @@ async function getFullChatInfo(chatId: string): Promise<{
const members = buildChatMembers(participants);
const adminMembers = members ? members.filter(({ isAdmin, isOwner }) => isAdmin || isOwner) : undefined;
const botCommands = botInfo ? buildApiChatBotCommands(botInfo) : undefined;
const { users, userStatusesById } = buildApiUsersAndStatuses(result.users);
return {
fullInfo: {
@ -381,7 +384,8 @@ async function getFullChatInfo(chatId: string): Promise<{
requestsPending,
recentRequesterIds: recentRequesters?.map((userId) => buildApiPeerId(userId, 'user')),
},
users: result.users.map(buildApiUser).filter<ApiUser>(Boolean as any),
users,
userStatusesById,
groupCall: call ? {
chatId,
isLoaded: false,
@ -403,6 +407,7 @@ async function getFullChannelInfo(
): Promise<{
fullInfo: ApiChatFullInfo;
users?: ApiUser[];
userStatusesById: { [userId: string]: ApiUserStatus };
groupCall?: Partial<ApiGroupCall>;
membersCount?: number;
} | undefined> {
@ -440,11 +445,11 @@ async function getFullChannelInfo(
? exportedInvite.link
: undefined;
const { members, users } = (canViewParticipants && await fetchMembers(id, accessHash)) || {};
const { members: kickedMembers, users: bannedUsers } = (
const { members, users, userStatusesById } = (canViewParticipants && await fetchMembers(id, accessHash)) || {};
const { members: kickedMembers, users: bannedUsers, userStatusesById: bannedStatusesById } = (
canViewParticipants && adminRights && await fetchMembers(id, accessHash, 'kicked')
) || {};
const { members: adminMembers, users: adminUsers } = (
const { members: adminMembers, users: adminUsers, userStatusesById: adminStatusesById } = (
canViewParticipants && adminRights && await fetchMembers(id, accessHash, 'admin')
) || {};
const botCommands = botInfo ? buildApiChatBotCommands(botInfo) : undefined;
@ -463,6 +468,12 @@ async function getFullChannelInfo(
}
}
const statusesById = {
...userStatusesById,
...bannedStatusesById,
...adminStatusesById,
};
return {
fullInfo: {
about,
@ -492,6 +503,7 @@ async function getFullChannelInfo(
statisticsDcId: statsDc,
},
users: [...(users || []), ...(bannedUsers || []), ...(adminUsers || [])],
userStatusesById: statusesById,
groupCall: call ? {
chatId: id,
isLoaded: false,

View File

@ -118,8 +118,11 @@ export async function fetchContactList() {
}
});
const { users, userStatusesById } = buildApiUsersAndStatuses(result.users);
return {
users: result.users.map(buildApiUser).filter<ApiUser>(Boolean as any),
users,
userStatusesById,
chats: result.users.map((user) => buildApiChatFromPreview(user)).filter<ApiChat>(Boolean as any),
};
}

View File

@ -1,12 +1,11 @@
import React, {
FC, useEffect, useCallback, useMemo, memo,
FC, useCallback, useMemo, memo,
} from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import { ApiUser, ApiUserStatus } from '../../../api/types';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { throttle } from '../../../util/schedulers';
import { filterUsersByName, sortUserIds } from '../../../global/helpers';
import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
import useHistoryBack from '../../../hooks/useHistoryBack';
@ -31,8 +30,6 @@ type StateProps = {
serverTimeOffset: number;
};
const runThrottled = throttle((cb) => cb(), 60000, true);
const ContactList: FC<OwnProps & StateProps> = ({
isActive,
filter,
@ -43,21 +40,12 @@ const ContactList: FC<OwnProps & StateProps> = ({
onReset,
}) => {
const {
loadContactList,
openChat,
openNewContactDialog,
} = getActions();
const lang = useLang();
// Due to the parent Transition, this component never gets unmounted,
// that's why we use throttled API call on every update.
useEffect(() => {
runThrottled(() => {
loadContactList();
});
});
useHistoryBack({
isActive,
onBack: onReset,

View File

@ -1,12 +1,11 @@
import React, {
FC, useCallback, useEffect, useMemo, memo,
FC, useCallback, useMemo, memo,
} from '../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../global';
import { ApiChat } from '../../../api/types';
import { unique } from '../../../util/iteratees';
import { throttle } from '../../../util/schedulers';
import { filterUsersByName, isUserBot, sortChatIds } from '../../../global/helpers';
import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack';
@ -33,8 +32,6 @@ type StateProps = {
globalUserIds?: string[];
};
const runThrottled = throttle((cb) => cb(), 60000, true);
const NewChatStep1: FC<OwnProps & StateProps> = ({
isChannel,
isActive,
@ -50,18 +47,9 @@ const NewChatStep1: FC<OwnProps & StateProps> = ({
globalUserIds,
}) => {
const {
loadContactList,
setGlobalSearchQuery,
} = getActions();
// Due to the parent Transition, this component never gets unmounted,
// that's why we use throttled API call on every update.
useEffect(() => {
runThrottled(() => {
loadContactList();
});
});
const lang = useLang();
useHistoryBack({

View File

@ -37,7 +37,7 @@ const RecentContacts: FC<OwnProps & StateProps> = ({
onReset,
}) => {
const {
loadTopUsers, loadContactList, openChat,
loadTopUsers, openChat,
addRecentlyFoundChatId, clearRecentlyFoundChats,
} = getActions();
@ -49,10 +49,8 @@ const RecentContacts: FC<OwnProps & StateProps> = ({
useEffect(() => {
runThrottled(() => {
loadTopUsers();
// Loading full contact list for quick local search before user enters the query
loadContactList();
});
}, [loadTopUsers, loadContactList]);
}, [loadTopUsers]);
useHorizontalScroll(topUsersRef.current, !topUserIds);

View File

@ -34,7 +34,6 @@ const BlockUserModal: FC<OwnProps & StateProps> = ({
onClose,
}) => {
const {
loadContactList,
setUserSearchQuery,
blockContact,
} = getActions();
@ -82,7 +81,6 @@ const BlockUserModal: FC<OwnProps & StateProps> = ({
filterPlaceholder={lang('BlockedUsers.BlockUser')}
filter={filter}
onFilterChange={setFilter}
loadMore={loadContactList}
onSelectChatOrUser={handleRemoveUser}
onClose={onClose}
/>

View File

@ -152,6 +152,7 @@ const Main: FC<StateProps> = ({
checkVersionNotification,
loadAppConfig,
loadAttachMenuBots,
loadContactList,
} = getActions();
if (DEBUG && !DEBUG_isLogged) {
@ -178,10 +179,11 @@ const Main: FC<StateProps> = ({
loadTopInlineBots();
loadEmojiKeywords({ language: BASE_EMOJI_KEYWORD_LANG });
loadAttachMenuBots();
loadContactList();
}
}, [
lastSyncTime, loadAnimatedEmojis, loadEmojiKeywords, loadNotificationExceptions, loadNotificationSettings,
loadTopInlineBots, updateIsOnline, loadAvailableReactions, loadAppConfig, loadAttachMenuBots,
loadTopInlineBots, updateIsOnline, loadAvailableReactions, loadAppConfig, loadAttachMenuBots, loadContactList,
]);
// Language-based API calls

View File

@ -1,10 +1,10 @@
import React, {
FC, useCallback, useMemo, memo, useState, useEffect,
FC, useCallback, useMemo, memo, useState,
} from '../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../global';
import {
ApiChat, ApiChatMember, ApiUpdateConnectionStateType,
ApiChat, ApiChatMember,
} from '../../api/types';
import { NewChatMembersProgress } from '../../types';
@ -31,7 +31,6 @@ export type OwnProps = {
};
type StateProps = {
connectionState?: ApiUpdateConnectionStateType;
isChannel?: boolean;
members?: ApiChatMember[];
currentUserId?: string;
@ -46,7 +45,6 @@ type StateProps = {
const AddChatMembers: FC<OwnProps & StateProps> = ({
isChannel,
connectionState,
members,
onNextStep,
currentUserId,
@ -60,19 +58,13 @@ const AddChatMembers: FC<OwnProps & StateProps> = ({
onClose,
isActive,
}) => {
const { setUserSearchQuery, loadContactList } = getActions();
const { setUserSearchQuery } = getActions();
const lang = useLang();
const [selectedMemberIds, setSelectedMemberIds] = useState<string[]>([]);
const prevSelectedMemberIds = usePrevious(selectedMemberIds);
const noPickerScrollRestore = prevSelectedMemberIds === selectedMemberIds;
useEffect(() => {
if (isActive && connectionState === 'connectionStateReady') {
loadContactList();
}
}, [connectionState, isActive, loadContactList]);
useHistoryBack({
isActive,
onBack: onClose,
@ -160,7 +152,7 @@ export default memo(withGlobal<OwnProps>(
const chat = selectChat(global, chatId);
const { userIds: localContactIds } = global.contactList || {};
const { byId: chatsById } = global.chats;
const { currentUserId, newChatMembersProgress, connectionState } = global;
const { currentUserId, newChatMembersProgress } = global;
const isChannel = chat && isChatChannel(chat);
const {
@ -181,7 +173,6 @@ export default memo(withGlobal<OwnProps>(
isLoading: newChatMembersProgress === NewChatMembersProgress.Loading,
globalUserIds,
localUserIds,
connectionState,
};
},
)(AddChatMembers));

View File

@ -62,7 +62,7 @@ const ManageGroupMembers: FC<OwnProps & StateProps> = ({
onScreenSelect,
onChatMemberSelect,
}) => {
const { openChat, setUserSearchQuery, loadContactList } = getActions();
const { openChat, setUserSearchQuery, closeManagement } = getActions();
const lang = useLang();
// eslint-disable-next-line no-null/no-null
const inputRef = useRef<HTMLInputElement>(null);
@ -119,16 +119,17 @@ const ManageGroupMembers: FC<OwnProps & StateProps> = ({
);
}, [memberIds, localContactIds, searchQuery, localUserIds, globalUserIds, isChannel, noAdmins, adminIds]);
const [viewportIds, getMore] = useInfiniteScroll(loadContactList, displayedIds, Boolean(searchQuery));
const [viewportIds, getMore] = useInfiniteScroll(undefined, displayedIds, Boolean(searchQuery));
const handleMemberClick = useCallback((id: string) => {
if (noAdmins) {
onChatMemberSelect!(id, false);
onScreenSelect!(ManagementScreens.ChatNewAdminRights);
} else {
closeManagement();
openChat({ id });
}
}, [noAdmins, onChatMemberSelect, onScreenSelect, openChat]);
}, [closeManagement, noAdmins, onChatMemberSelect, onScreenSelect, openChat]);
const handleFilterChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setUserSearchQuery({ query: e.target.value });

View File

@ -1105,7 +1105,7 @@ export async function loadFullChat(chat: ApiChat) {
}
const {
users, fullInfo, groupCall, membersCount,
users, userStatusesById, fullInfo, groupCall, membersCount,
} = result;
let global = getGlobal();
@ -1113,6 +1113,10 @@ export async function loadFullChat(chat: ApiChat) {
global = addUsers(global, buildCollectionByKey(users, 'id'));
}
if (userStatusesById) {
global = addUserStatuses(global, userStatusesById);
}
if (groupCall) {
const existingGroupCall = selectGroupCall(global, groupCall.id!);
global = updateGroupCall(

View File

@ -11,8 +11,17 @@ import { isUserBot, isUserId } from '../../helpers';
import { callApi } from '../../../api/gramjs';
import { selectChat, selectCurrentMessageList, selectUser } from '../../selectors';
import {
addChats, addUsers, closeNewContactDialog, replaceUserStatuses, updateChat, updateManagementProgress, updateUser,
updateUsers, updateUserSearch, updateUserSearchFetchingStatus,
addChats,
addUsers,
addUserStatuses,
closeNewContactDialog,
replaceUserStatuses,
updateChat,
updateManagementProgress,
updateUser,
updateUsers,
updateUserSearch,
updateUserSearchFetchingStatus,
} from '../../reducers';
import { getServerTime } from '../../../util/serverTime';
import * as langProvider from '../../../util/langProvider';
@ -145,6 +154,7 @@ async function loadContactList() {
let global = addUsers(getGlobal(), buildCollectionByKey(contactList.users, 'id'));
global = addChats(global, buildCollectionByKey(contactList.chats, 'id'));
global = addUserStatuses(global, contactList.userStatusesById);
// Sort contact list by Last Name (or First Name), with latin names being placed first
const getCompareString = (user: ApiUser) => (user.lastName || user.firstName || '');