Sync: Fix missing chats in folders, refactor and simplify

This commit is contained in:
Alexander Zinchuk 2022-02-11 15:13:02 +01:00
parent 57dd323b78
commit 0e7f5658c4
14 changed files with 119 additions and 326 deletions

View File

@ -28,7 +28,7 @@ export type OwnProps = {
filterRef: RefObject<HTMLInputElement>;
filterPlaceholder: string;
filter: string;
loadMore: NoneToVoidFunction;
loadMore?: NoneToVoidFunction;
onFilterChange: (filter: string) => void;
onSelectChatOrUser: (chatOrUserId: string) => void;
onClose: NoneToVoidFunction;

View File

@ -1,5 +1,5 @@
import React, {
FC, memo, useMemo, useCallback, useEffect,
FC, memo, useMemo, useEffect,
} from '../../../lib/teact/teact';
import { getDispatch } from '../../../lib/teact/teactn';
@ -7,7 +7,6 @@ import { SettingsScreens } from '../../../types';
import { FolderEditDispatch } from '../../../hooks/reducers/useFoldersReducer';
import {
ALL_CHATS_PRELOAD_DISABLED,
ALL_FOLDER_ID,
ARCHIVED_FOLDER_ID,
CHAT_HEIGHT_PX,
@ -39,17 +38,10 @@ const ChatList: FC<OwnProps> = ({
folderType,
folderId,
isActive,
lastSyncTime,
foldersDispatch,
onScreenSelect,
}) => {
const {
loadMoreChats,
preloadTopChatMessages,
preloadArchivedChats,
openChat,
openNextChat,
} = getDispatch();
const { openChat, openNextChat } = getDispatch();
const resolvedFolderId = (
folderType === 'all' ? ALL_FOLDER_ID : folderType === 'archived' ? ARCHIVED_FOLDER_ID : folderId!
@ -80,24 +72,7 @@ const ChatList: FC<OwnProps> = ({
});
}, [orderById, prevOrderById]);
const loadMoreOfType = useCallback(() => {
loadMoreChats({ listType: folderType === 'archived' ? 'archived' : 'active' });
}, [loadMoreChats, folderType]);
const [viewportIds, getMore] = useInfiniteScroll(
lastSyncTime ? loadMoreOfType : undefined,
orderedIds,
undefined,
CHAT_LIST_SLICE,
folderType === 'all' && !ALL_CHATS_PRELOAD_DISABLED,
);
useEffect(() => {
if (lastSyncTime && folderType === 'all') {
preloadTopChatMessages();
preloadArchivedChats();
}
}, [lastSyncTime, folderType, preloadTopChatMessages, preloadArchivedChats]);
const [viewportIds, getMore] = useInfiniteScroll(undefined, orderedIds, undefined, CHAT_LIST_SLICE);
// Support <Cmd>+<Digit> and <Alt>+<Up/Down> to navigate between chats
useEffect(() => {

View File

@ -1,7 +1,7 @@
import React, {
FC, memo, useMemo, useCallback,
} from '../../../../lib/teact/teact';
import { getDispatch, getGlobal } from '../../../../lib/teact/teactn';
import { getGlobal } from '../../../../lib/teact/teactn';
import { SettingsScreens } from '../../../../types';
@ -38,8 +38,6 @@ const SettingsFoldersChatFilters: FC<OwnProps> = ({
onScreenSelect,
onReset,
}) => {
const { loadMoreChats } = getDispatch();
const { chatFilter } = state;
const { selectedChatIds, selectedChatTypes } = selectChatFilters(state, mode, true);
@ -124,7 +122,6 @@ const SettingsFoldersChatFilters: FC<OwnProps> = ({
onSelectedIdsChange={handleSelectedIdsChange}
onSelectedChatTypesChange={handleSelectedChatTypesChange}
onFilterChange={handleFilterChange}
onLoadMore={loadMoreChats}
/>
);
};

View File

@ -32,7 +32,6 @@ type OwnProps = {
onSelectedIdsChange: (ids: string[]) => void;
onSelectedChatTypesChange: (types: string[]) => void;
onFilterChange: (value: string) => void;
onLoadMore: () => void;
};
// Focus slows down animation, also it breaks transition layout in Chrome
@ -51,7 +50,6 @@ const SettingsFoldersChatsPicker: FC<OwnProps> = ({
onSelectedIdsChange,
onSelectedChatTypesChange,
onFilterChange,
onLoadMore,
}) => {
// eslint-disable-next-line no-null/no-null
const inputRef = useRef<HTMLInputElement>(null);
@ -156,7 +154,7 @@ const SettingsFoldersChatsPicker: FC<OwnProps> = ({
);
}
const [viewportIds, getMore] = useInfiniteScroll(onLoadMore, chatIds, Boolean(filterValue));
const [viewportIds, getMore] = useInfiniteScroll(undefined, chatIds, Boolean(filterValue));
return (
<div className="Picker SettingsFoldersChatsPicker">

View File

@ -66,7 +66,6 @@ const SettingsFoldersEdit: FC<OwnProps & StateProps> = ({
const {
editChatFolder,
addChatFolder,
loadMoreChats,
} = getDispatch();
const [animationData, setAnimationData] = useState<string>();
@ -119,21 +118,6 @@ const SettingsFoldersEdit: FC<OwnProps & StateProps> = ({
loadedActiveChatIds, loadedArchivedChatIds,
]);
useEffect(() => {
if (
visibleIncludedChatIds.length < includedChatIds.length
|| visibleExcludedChatIds.length < excludedChatIds.length
) {
loadMoreChats({ listType: 'active' });
}
}, [
loadMoreChats,
excludedChatIds.length,
includedChatIds.length,
visibleExcludedChatIds.length,
visibleIncludedChatIds.length,
]);
const lang = useLang();
useHistoryBack(isActive, onBack, onScreenSelect, state.mode === 'edit'

View File

@ -43,7 +43,6 @@ const ForwardPicker: FC<OwnProps & StateProps> = ({
const {
setForwardChatId,
exitForwardMode,
loadMoreChats,
} = getDispatch();
const lang = useLang();
@ -105,7 +104,6 @@ const ForwardPicker: FC<OwnProps & StateProps> = ({
filterPlaceholder={lang('ForwardTo')}
filter={filter}
onFilterChange={setFilter}
loadMore={loadMoreChats}
onSelectChatOrUser={handleSelectUser}
onClose={exitForwardMode}
onCloseAnimationEnd={unmarkIsShown}

View File

@ -4,7 +4,7 @@ import React, {
import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { LangCode } from '../../types';
import { ApiMessage } from '../../api/types';
import { ApiMessage, ApiUpdateAuthorizationStateType, ApiUpdateConnectionStateType } from '../../api/types';
import '../../modules/actions/all';
import {
@ -52,6 +52,8 @@ import CallFallbackConfirm from '../calls/CallFallbackConfirm.async';
import './Main.scss';
type StateProps = {
connectionState?: ApiUpdateConnectionStateType;
authState?: ApiUpdateAuthorizationStateType;
lastSyncTime?: number;
isLeftColumnShown: boolean;
isRightColumnShown: boolean;
@ -81,6 +83,8 @@ let notificationInterval: number | undefined;
let DEBUG_isLogged = false;
const Main: FC<StateProps> = ({
connectionState,
authState,
lastSyncTime,
isLeftColumnShown,
isRightColumnShown,
@ -102,6 +106,7 @@ const Main: FC<StateProps> = ({
addedSetIds,
}) => {
const {
sync,
loadAnimatedEmojis,
loadNotificationSettings,
loadNotificationExceptions,
@ -125,6 +130,12 @@ const Main: FC<StateProps> = ({
console.log('>>> RENDER MAIN');
}
useEffect(() => {
if (connectionState === 'connectionStateReady' && authState === 'authorizationStateReady') {
sync();
}
}, [connectionState, authState, sync]);
// Initial API calls
useEffect(() => {
if (lastSyncTime) {
@ -356,6 +367,8 @@ export default memo(withGlobal(
: undefined;
return {
connectionState: global.connectionState,
authState: global.authState,
lastSyncTime: global.lastSyncTime,
isLeftColumnShown: global.isLeftColumnShown,
isRightColumnShown: selectIsRightColumnShown(global),

View File

@ -61,7 +61,6 @@ export const GROUP_CALL_PARTICIPANTS_LIMIT = 100;
export const REACTION_LIST_LIMIT = 100;
export const TOP_CHAT_MESSAGES_PRELOAD_LIMIT = 20;
export const ALL_CHATS_PRELOAD_DISABLED = false;
export const SPONSORED_MESSAGE_CACHE_MS = 300000; // 5 min

View File

@ -503,7 +503,7 @@ export type GlobalState = {
export type ActionTypes = (
// system
'init' | 'reset' | 'disconnect' | 'initApi' | 'apiUpdate' | 'sync' | 'saveSession' | 'afterSync' |
'init' | 'reset' | 'disconnect' | 'initApi' | 'apiUpdate' | 'sync' | 'saveSession' |
'showNotification' | 'dismissNotification' | 'showDialog' | 'dismissDialog' |
// ui
'toggleChatInfo' | 'setIsUiReady' | 'addRecentEmoji' | 'addRecentSticker' | 'toggleLeftColumn' |
@ -515,8 +515,7 @@ export type ActionTypes = (
'setAuthPhoneNumber' | 'setAuthCode' | 'setAuthPassword' | 'signUp' | 'returnToAuthPhoneNumber' | 'signOut' |
'setAuthRememberMe' | 'clearAuthError' | 'uploadProfilePhoto' | 'goToAuthQrCode' | 'clearCache' |
// chats
'preloadTopChatMessages' | 'preloadArchivedChats' | 'loadChats' | 'loadMoreChats' | 'openChat' |
'openChatWithInfo' | 'openLinkedChat' |
'preloadTopChatMessages' | 'loadAllChats' | 'openChat' | 'openChatWithInfo' | 'openLinkedChat' |
'openSupportChat' | 'openTipsChat' | 'focusMessageInComments' |
'loadFullChat' | 'loadTopChats' | 'requestChatUpdate' | 'updateChatMutedState' |
'joinChannel' | 'leaveChannel' | 'deleteChannel' | 'toggleChatPinned' | 'toggleChatArchived' | 'toggleChatUnread' |

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect, useRef } from '../lib/teact/teact';
import { useCallback, useRef } from '../lib/teact/teact';
import { LoadMoreDirection } from '../types';
import { areSortedArraysEqual } from '../util/iteratees';
@ -15,7 +15,6 @@ const useInfiniteScroll = <ListId extends string | number>(
listIds?: ListId[],
isDisabled = false,
listSlice = DEFAULT_LIST_SLICE,
forceFullPreload = false,
): [ListId[]?, GetMore?] => {
const lastParamsRef = useRef<{
direction?: LoadMoreDirection;
@ -49,13 +48,6 @@ const useInfiniteScroll = <ListId extends string | number>(
}
}
useEffect(() => {
if (listIds && !isDisabled && loadMoreBackwards && forceFullPreload) {
const viewportIds = viewportIdsRef.current!;
loadMoreBackwards({ offsetId: viewportIds[viewportIds.length - 1] });
}
}, [listIds, isDisabled, loadMoreBackwards, forceFullPreload]);
const getMore: GetMore = useCallback(({
direction,
noScroll,

View File

@ -20,28 +20,16 @@ import {
} from '../../../config';
import { callApi } from '../../../api/gramjs';
import {
addChats,
addUsers,
addUserStatuses,
replaceThreadParam,
updateChatListIds,
updateChats,
updateChat,
updateChatListSecondaryInfo,
updateManagementProgress,
leaveChat,
addChats, addUsers, addUserStatuses, replaceThreadParam,
updateChatListIds, updateChats, updateChat, updateChatListSecondaryInfo,
updateManagementProgress, leaveChat, replaceUsers, replaceUserStatuses,
replaceChats, replaceChatListIds,
} from '../../reducers';
import {
selectChat,
selectUser,
selectChatListType,
selectIsChatPinned,
selectChatFolder,
selectSupportChat,
selectChatByUsername,
selectThreadTopMessageId,
selectCurrentMessageList,
selectThreadInfo, selectCurrentChat, selectLastServiceNotification,
selectChat, selectUser, selectChatListType, selectIsChatPinned,
selectChatFolder, selectSupportChat, selectChatByUsername, selectThreadTopMessageId,
selectCurrentMessageList, selectThreadInfo, selectCurrentChat, selectLastServiceNotification,
selectThreadParam, selectChatMessage,
} from '../../selectors';
import { buildCollectionByKey, omit } from '../../../util/iteratees';
import { debounce, pause, throttle } from '../../../util/schedulers';
@ -54,9 +42,7 @@ import { selectGroupCall } from '../../selectors/calls';
import { getOrderedIds } from '../../../util/folderManager';
const TOP_CHAT_MESSAGES_PRELOAD_INTERVAL = 100;
const CHATS_PRELOAD_INTERVAL = 300;
const runThrottledForLoadChats = throttle((cb) => cb(), CHATS_PRELOAD_INTERVAL, true);
const runThrottledForLoadTopChats = throttle((cb) => cb(), 3000, true);
const runDebouncedForLoadFullChat = debounce((cb) => cb(), 500, false, true);
@ -179,43 +165,30 @@ addReducer('openTipsChat', (global, actions, payload) => {
actions.openChatByUsername({ username: `${TIPS_USERNAME}${usernamePostfix}` });
});
addReducer('loadMoreChats', (global, actions, payload) => {
const { listType = 'active' } = payload!;
const listIds = global.chats.listIds[listType as ('active' | 'archived')];
const isFullyLoaded = global.chats.isFullyLoaded[listType as ('active' | 'archived')];
addReducer('loadAllChats', (global, actions, payload) => {
const listType = payload.listType as 'active' | 'archived';
let { shouldReplace, onReplace } = payload;
if (isFullyLoaded) {
return;
}
const oldestChat = listIds
? listIds
.map((id) => global.chats.byId[id])
.filter((chat) => Boolean(chat?.lastMessage) && !selectIsChatPinned(global, chat.id))
.sort((chat1, chat2) => (chat1.lastMessage!.date - chat2.lastMessage!.date))[0]
: undefined;
if (oldestChat) {
runThrottledForLoadChats(() => loadChats(listType, oldestChat.id, oldestChat.lastMessage!.date));
} else {
runThrottledForLoadChats(() => loadChats(listType));
}
});
addReducer('preloadArchivedChats', () => {
(async () => {
while (!getGlobal().chats.isFullyLoaded.archived) {
const currentGlobal = getGlobal();
const listIds = currentGlobal.chats.listIds.archived;
while (shouldReplace || !global.chats.isFullyLoaded[listType]) {
const listIds = !shouldReplace && global.chats.listIds[listType];
const oldestChat = listIds
? listIds
.map((id) => currentGlobal.chats.byId[id])
.filter((chat) => Boolean(chat?.lastMessage) && !selectIsChatPinned(currentGlobal, chat.id))
/* eslint-disable @typescript-eslint/no-loop-func */
.map((id) => global.chats.byId[id])
.filter((chat) => Boolean(chat?.lastMessage) && !selectIsChatPinned(global, chat.id))
/* eslint-enable @typescript-eslint/no-loop-func */
.sort((chat1, chat2) => (chat1.lastMessage!.date - chat2.lastMessage!.date))[0]
: undefined;
await loadChats('archived', oldestChat?.id, oldestChat?.lastMessage!.date);
await pause(CHATS_PRELOAD_INTERVAL);
await loadChats(listType, oldestChat?.id, oldestChat?.lastMessage!.date, shouldReplace);
if (shouldReplace) {
onReplace?.();
}
global = getGlobal();
shouldReplace = false;
}
})();
});
@ -1011,14 +984,16 @@ addReducer('setChatEnabledReactions', (global, actions, payload) => {
})();
});
async function loadChats(listType: 'active' | 'archived', offsetId?: string, offsetDate?: number) {
async function loadChats(
listType: 'active' | 'archived', offsetId?: string, offsetDate?: number, shouldReplace = false,
) {
let global = getGlobal();
const result = await callApi('fetchChats', {
limit: CHAT_LIST_LOAD_SLICE,
offsetDate,
archived: listType === 'archived',
withPinned: global.chats.orderedPinnedIds[listType] === undefined,
withPinned: shouldReplace,
serverTimeOffset: global.serverTimeOffset,
lastLocalServiceMessage: selectLastServiceNotification(global)?.message,
});
@ -1035,11 +1010,44 @@ async function loadChats(listType: 'active' | 'archived', offsetId?: string, off
global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
global = addUserStatuses(global, result.userStatusesById);
if (shouldReplace && listType === 'active') {
const visibleChats = [];
const visibleUsers = [];
const currentChat = selectCurrentChat(global);
if (currentChat) {
const { threadId } = selectCurrentMessageList(global)!;
visibleChats.push(currentChat);
const messageIds = selectThreadParam(global, currentChat.id, threadId, 'viewportIds');
const messageSenders = messageIds ? messageIds
.map((messageId) => {
const { senderId } = selectChatMessage(global, currentChat.id, messageId) || {};
return senderId ? selectUser(global, senderId) : undefined;
})
.filter(Boolean) : [];
visibleUsers.push(...messageSenders);
}
if (global.currentUserId && global.users.byId[global.currentUserId]) {
visibleUsers.push(global.users.byId[global.currentUserId]);
}
global = replaceUsers(global, buildCollectionByKey(visibleUsers.concat(result.users), 'id'));
global = replaceUserStatuses(global, result.userStatusesById);
global = replaceChats(global, buildCollectionByKey(visibleChats.concat(result.chats), 'id'));
global = replaceChatListIds(global, listType, chatIds);
} else if (shouldReplace && listType === 'archived') {
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
global = addUserStatuses(global, result.userStatusesById);
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
global = replaceChatListIds(global, listType, chatIds);
} else {
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
global = addUserStatuses(global, result.userStatusesById);
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
global = updateChatListIds(global, listType, chatIds);
}
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
global = updateChatListIds(global, listType, chatIds);
global = updateChatListSecondaryInfo(global, listType, result);
Object.keys(result.draftsById).forEach((chatId) => {

View File

@ -3,23 +3,17 @@ import {
} from '../../../lib/teact/teactn';
import {
ApiChat, ApiFormattedText, ApiMessage, ApiUser, MAIN_THREAD_ID,
ApiChat, ApiFormattedText, ApiMessage, MAIN_THREAD_ID,
} from '../../../api/types';
import {
CHAT_LIST_LOAD_SLICE, DEBUG, MESSAGE_LIST_SLICE, SERVICE_NOTIFICATIONS_USER_ID,
DEBUG, MESSAGE_LIST_SLICE, SERVICE_NOTIFICATIONS_USER_ID,
} from '../../../config';
import { callApi } from '../../../api/gramjs';
import { buildCollectionByKey } from '../../../util/iteratees';
import {
replaceChatListIds,
replaceChats,
replaceUsers,
replaceUserStatuses,
updateUsers,
addUserStatuses,
updateChats,
updateChatListSecondaryInfo,
updateThreadInfos,
replaceThreadParam,
updateListedIds,
@ -27,29 +21,18 @@ import {
addChatMessagesById,
} from '../../reducers';
import {
selectUser,
selectChat,
selectCurrentMessageList,
selectDraft,
selectChatMessage,
selectThreadInfo,
selectLastServiceNotification,
} from '../../selectors';
import { isUserId } from '../../helpers';
addReducer('sync', (global, actions) => {
void sync(actions.afterSync);
});
addReducer('afterSync', () => {
void afterSync();
});
import { init as initFolderManager } from '../../../util/folderManager';
const RELEASE_STATUS_TIMEOUT = 15000; // 10 sec;
let releaseStatusTimeout: number | undefined;
async function sync(afterSyncCallback: () => void) {
addReducer('sync', () => {
if (DEBUG) {
// eslint-disable-next-line no-console
console.log('>>> START SYNC');
@ -67,149 +50,35 @@ async function sync(afterSyncCallback: () => void) {
releaseStatusTimeout = undefined;
}, RELEASE_STATUS_TIMEOUT);
await callApi('fetchCurrentUser');
const { loadAllChats, preloadTopChatMessages } = getDispatch();
// This fetches only active chats and clears archived chats, which will be fetched in `afterSync`
const savedUsers = await loadAndReplaceChats();
await loadAndReplaceMessages(savedUsers);
loadAllChats({
listType: 'active',
shouldReplace: true,
onReplace: async () => {
await loadAndReplaceMessages();
setGlobal({
...getGlobal(),
lastSyncTime: Date.now(),
isSyncing: false,
});
setGlobal({
...getGlobal(),
lastSyncTime: Date.now(),
isSyncing: false,
});
if (DEBUG) {
// eslint-disable-next-line no-console
console.log('>>> FINISH SYNC');
}
afterSyncCallback();
}
async function afterSync() {
if (DEBUG) {
// eslint-disable-next-line no-console
console.log('>>> START AFTER-SYNC');
}
await Promise.all([
loadAndUpdateUsers(),
loadAndReplaceArchivedChats(),
]);
await callApi('fetchCurrentUser');
if (DEBUG) {
// eslint-disable-next-line no-console
console.log('>>> FINISH AFTER-SYNC');
}
}
async function loadAndReplaceChats() {
let global = getGlobal();
const result = await callApi('fetchChats', {
limit: CHAT_LIST_LOAD_SLICE,
withPinned: true,
serverTimeOffset: global.serverTimeOffset,
lastLocalServiceMessage: selectLastServiceNotification(global)?.message,
});
if (!result) {
return undefined;
}
global = getGlobal();
const { recentlyFoundChatIds } = global.globalSearch;
const { userIds: contactIds } = global.contactList || {};
const { currentUserId } = global;
const savedPrivateChatIds = [
...(recentlyFoundChatIds || []),
...(contactIds || []),
...(currentUserId ? [currentUserId] : []),
];
const savedUsers = savedPrivateChatIds
.map((id) => selectUser(global, id))
.filter<ApiUser>(Boolean as any);
const savedChats = savedPrivateChatIds
.map((id) => selectChat(global, id))
.filter<ApiChat>(Boolean as any);
const { chatId: currentChatId } = selectCurrentMessageList(global) || {};
if (currentChatId) {
const selectedChat = selectChat(global, currentChatId);
if (selectedChat && !savedPrivateChatIds.includes(currentChatId)) {
savedChats.push(selectedChat);
}
if (isUserId(currentChatId)) {
const selectedChatUser = selectUser(global, currentChatId);
if (selectedChatUser && !savedPrivateChatIds.includes(currentChatId)) {
savedUsers.push(selectedChatUser);
if (DEBUG) {
// eslint-disable-next-line no-console
console.log('>>> FINISH SYNC');
}
}
}
savedUsers.push(...result.users);
savedChats.push(...result.chats);
global = replaceUserStatuses(global, result.userStatusesById);
global = replaceChats(global, buildCollectionByKey(savedChats, 'id'));
global = replaceChatListIds(global, 'active', result.chatIds);
global = updateChatListSecondaryInfo(global, 'active', result);
Object.keys(result.draftsById).forEach((chatId) => {
global = replaceThreadParam(global, chatId, MAIN_THREAD_ID, 'draft', result.draftsById[chatId]);
initFolderManager();
loadAllChats({ listType: 'archived', shouldReplace: true });
void callApi('fetchCurrentUser');
preloadTopChatMessages();
},
});
});
Object.keys(result.replyingToById).forEach((chatId) => {
global = replaceThreadParam(
global, chatId, MAIN_THREAD_ID, 'replyingToId', result.replyingToById[chatId],
);
});
setGlobal(global);
if (currentChatId && !global.chats.byId[currentChatId]) {
getDispatch().openChat({ id: undefined });
}
return savedUsers;
}
async function loadAndReplaceArchivedChats() {
const result = await callApi('fetchChats', {
limit: CHAT_LIST_LOAD_SLICE,
archived: true,
withPinned: true,
serverTimeOffset: getGlobal().serverTimeOffset,
});
if (!result) {
return;
}
let global = getGlobal();
global = updateUsers(global, buildCollectionByKey(result.users, 'id'));
global = addUserStatuses(global, result.userStatusesById);
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
global = replaceChatListIds(global, 'archived', result.chatIds);
global = updateChatListSecondaryInfo(global, 'archived', result);
setGlobal(global);
}
async function loadAndReplaceMessages(savedUsers?: ApiUser[]) {
async function loadAndReplaceMessages() {
let areMessagesLoaded = false;
let users = savedUsers || [];
let global = getGlobal();
const { chatId: currentChatId, threadId: currentThreadId } = selectCurrentMessageList(global) || {};
@ -294,10 +163,10 @@ async function loadAndReplaceMessages(savedUsers?: ApiUser[]) {
}
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
global = updateUsers(global, buildCollectionByKey(result.users, 'id'));
global = updateThreadInfos(global, currentChatId, result.threadInfos);
areMessagesLoaded = true;
users = Array.prototype.concat(users, result.users);
}
}
@ -316,13 +185,6 @@ async function loadAndReplaceMessages(savedUsers?: ApiUser[]) {
global = replaceThreadParam(global, chatId, MAIN_THREAD_ID, 'draft', draftsByChatId[chatId]);
});
if (savedUsers) {
global = replaceUsers(global, buildCollectionByKey(users, 'id'));
} else if (users) {
// If `fetchChats` has failed for some reason, we don't have saved chats, thus we can not replace
global = updateUsers(global, buildCollectionByKey(users, 'id'));
}
setGlobal(global);
const { chatId: audioChatId, messageId: audioMessageId } = global.audioPlayer;
@ -331,35 +193,6 @@ async function loadAndReplaceMessages(savedUsers?: ApiUser[]) {
}
}
async function loadAndUpdateUsers() {
let global = getGlobal();
const { recentlyFoundChatIds } = global.globalSearch;
const { userIds: contactIds } = global.contactList || {};
if (
(!contactIds || !contactIds.length)
&& (!recentlyFoundChatIds || !recentlyFoundChatIds.length)
) {
return;
}
const users = [
...(recentlyFoundChatIds || []),
...(contactIds || []),
].map((id) => selectUser(global, id)).filter<ApiUser>(Boolean as any);
const result = await callApi('fetchUsers', { users });
if (!result) {
return;
}
const { users: updatedUsers, userStatusesById } = result;
global = getGlobal();
global = updateUsers(global, buildCollectionByKey(updatedUsers, 'id'));
global = addUserStatuses(global, userStatusesById);
setGlobal(global);
}
function loadTopMessages(chat: ApiChat) {
return callApi('fetchMessages', {
chat,

View File

@ -134,7 +134,6 @@ function onUpdateAuthorizationState(update: ApiUpdateAuthorizationState) {
setGlobal({
...global,
isLoggingOut: false,
lastSyncTime: Date.now(),
});
break;
@ -162,9 +161,7 @@ function onUpdateConnectionState(update: ApiUpdateConnectionState) {
connectionState,
});
if (connectionState === 'connectionStateReady' && global.authState === 'authorizationStateReady') {
getDispatch().sync();
} else if (connectionState === 'connectionStateBroken') {
if (connectionState === 'connectionStateBroken') {
getDispatch().signOut();
}
}

View File

@ -93,7 +93,9 @@ const updateFolderManagerThrottled = throttle(() => {
let inited = false;
function init() {
/* Getters */
export function init() {
inited = true;
addCallback(updateFolderManagerThrottled);
@ -102,8 +104,6 @@ function init() {
updateFolderManager(getGlobal());
}
/* Getters */
export function getOrderedIds(folderId: number) {
if (!inited) init();