[Refactoring] Store users from all responses (#2238)

This commit is contained in:
Alexander Zinchuk 2023-01-10 02:07:39 +01:00
parent c34a03e24a
commit 6807009831
22 changed files with 249 additions and 104 deletions

View File

@ -273,6 +273,7 @@ export async function loadAttachBots({
return { return {
hash: result.hash.toString(), hash: result.hash.toString(),
bots: buildCollectionByKey(result.bots.map(buildApiAttachBot), 'id'), bots: buildCollectionByKey(result.bots.map(buildApiAttachBot), 'id'),
users: result.users.map(buildApiUser).filter(Boolean),
}; };
} }
return undefined; return undefined;

View File

@ -276,7 +276,7 @@ export async function requestCall({
})); }));
if (!result) { if (!result) {
return false; return undefined;
} }
const call = buildPhoneCall(result.phoneCall); const call = buildPhoneCall(result.phoneCall);
@ -286,7 +286,11 @@ export async function requestCall({
call, call,
}); });
return true; addEntitiesWithPhotosToLocalDb(result.users);
return {
users: result.users.map(buildApiUser).filter(Boolean),
};
} }
export function setCallRating({ export function setCallRating({
@ -323,7 +327,7 @@ export async function acceptCall({
})); }));
if (!result) { if (!result) {
return; return undefined;
} }
call = buildPhoneCall(result.phoneCall); call = buildPhoneCall(result.phoneCall);
@ -332,6 +336,12 @@ export async function acceptCall({
'@type': 'updatePhoneCall', '@type': 'updatePhoneCall',
call, call,
}); });
addEntitiesWithPhotosToLocalDb(result.users);
return {
users: result.users.map(buildApiUser).filter(Boolean),
};
} }
export async function confirmCall({ export async function confirmCall({
@ -347,7 +357,7 @@ export async function confirmCall({
})); }));
if (!result) { if (!result) {
return; return undefined;
} }
call = buildPhoneCall(result.phoneCall); call = buildPhoneCall(result.phoneCall);
@ -356,6 +366,12 @@ export async function confirmCall({
'@type': 'updatePhoneCall', '@type': 'updatePhoneCall',
call, call,
}); });
addEntitiesWithPhotosToLocalDb(result.users);
return {
users: result.users.map(buildApiUser).filter(Boolean),
};
} }
export function sendSignalingData({ export function sendSignalingData({

View File

@ -215,7 +215,12 @@ export async function fetchChatSettings(chat: ApiChat) {
return undefined; return undefined;
} }
return buildApiChatSettings(result.settings); addEntitiesWithPhotosToLocalDb(result.users);
return {
users: result.users.map(buildApiUser).filter(Boolean),
settings: buildApiChatSettings(result.settings),
};
} }
export async function searchChats({ query }: { query: string }) { export async function searchChats({ query }: { query: string }) {
@ -393,6 +398,7 @@ async function getFullChatInfo(chatId: string): Promise<FullChatData | undefined
const members = buildChatMembers(participants); const members = buildChatMembers(participants);
const adminMembers = members ? members.filter(({ isAdmin, isOwner }) => isAdmin || isOwner) : undefined; const adminMembers = members ? members.filter(({ isAdmin, isOwner }) => isAdmin || isOwner) : undefined;
const botCommands = botInfo ? buildApiChatBotCommands(botInfo) : undefined; const botCommands = botInfo ? buildApiChatBotCommands(botInfo) : undefined;
const inviteLink = exportedInvite instanceof GramJs.ChatInviteExported ? exportedInvite.link : undefined;
const { users, userStatusesById } = buildApiUsersAndStatuses(result.users); const { users, userStatusesById } = buildApiUsersAndStatuses(result.users);
return { return {
@ -403,10 +409,7 @@ async function getFullChatInfo(chatId: string): Promise<FullChatData | undefined
adminMembersById: adminMembers ? buildCollectionByKey(adminMembers, 'userId') : undefined, adminMembersById: adminMembers ? buildCollectionByKey(adminMembers, 'userId') : undefined,
canViewMembers: true, canViewMembers: true,
botCommands, botCommands,
...(exportedInvite instanceof GramJs.ChatInviteExported && { inviteLink,
// TODO Verify Exported Invite logic
inviteLink: exportedInvite.link,
}),
groupCallId: call?.id.toString(), groupCallId: call?.id.toString(),
enabledReactions: buildApiChatReactions(availableReactions), enabledReactions: buildApiChatReactions(availableReactions),
requestsPending, requestsPending,

View File

@ -76,7 +76,6 @@ export async function updatePrivateLink({
expireDate, expireDate,
})); }));
// TODO Verify Exported Invite logic
if (!(result instanceof GramJs.ChatInviteExported)) return undefined; if (!(result instanceof GramJs.ChatInviteExported)) return undefined;
onUpdate({ onUpdate({
@ -102,10 +101,15 @@ export async function fetchExportedChatInvites({
if (!exportedInvites) return undefined; if (!exportedInvites) return undefined;
addEntitiesWithPhotosToLocalDb(exportedInvites.users); addEntitiesWithPhotosToLocalDb(exportedInvites.users);
// TODO Verify Exported Invite logic
return (exportedInvites.invites const invites = (exportedInvites.invites
.filter((invite): invite is GramJs.ChatInviteExported => invite instanceof GramJs.ChatInviteExported)) .filter((invite): invite is GramJs.ChatInviteExported => invite instanceof GramJs.ChatInviteExported))
.map(buildApiExportedInvite); .map(buildApiExportedInvite);
return {
invites,
users: exportedInvites.users.map(buildApiUser).filter(Boolean),
};
} }
export async function editExportedChatInvite({ export async function editExportedChatInvite({
@ -119,7 +123,6 @@ export async function editExportedChatInvite({
isRequestNeeded?: boolean; isRequestNeeded?: boolean;
title?: string; title?: string;
}) { }) {
// TODO Verify Exported Invite logic
const invite = await invokeRequest(new GramJs.messages.EditExportedChatInvite({ const invite = await invokeRequest(new GramJs.messages.EditExportedChatInvite({
link, link,
peer: buildInputPeer(peer.id, peer.accessHash), peer: buildInputPeer(peer.id, peer.accessHash),
@ -138,6 +141,7 @@ export async function editExportedChatInvite({
return { return {
oldInvite: replaceInvite, oldInvite: replaceInvite,
newInvite: replaceInvite, newInvite: replaceInvite,
users: invite.users.map(buildApiUser).filter(Boolean),
}; };
} }
@ -149,6 +153,7 @@ export async function editExportedChatInvite({
return { return {
oldInvite, oldInvite,
newInvite, newInvite,
users: invite.users.map(buildApiUser).filter(Boolean),
}; };
} }
return undefined; return undefined;
@ -171,7 +176,6 @@ export async function exportChatInvite({
title, title,
})); }));
// TODO Verify Exported Invite logic
if (!(invite instanceof GramJs.ChatInviteExported)) return undefined; if (!(invite instanceof GramJs.ChatInviteExported)) return undefined;
return buildApiExportedInvite(invite); return buildApiExportedInvite(invite);
} }

View File

@ -908,8 +908,14 @@ export async function requestThreadInfoUpdate({
}); });
} }
addEntitiesWithPhotosToLocalDb(topMessageResult.users);
addEntitiesWithPhotosToLocalDb(topMessageResult.chats);
const users = topMessageResult.users.map(buildApiUser).filter(Boolean);
return { return {
discussionChatId, discussionChatId,
users,
}; };
} }

View File

@ -126,6 +126,7 @@ export async function getPaymentForm(inputInvoice: ApiRequestInputInvoice) {
return { return {
form: buildApiPaymentForm(result), form: buildApiPaymentForm(result),
invoice: buildApiInvoiceFromForm(result), invoice: buildApiInvoiceFromForm(result),
users: result.users.map(buildApiUser).filter(Boolean),
}; };
} }
@ -139,7 +140,12 @@ export async function getReceipt(chat: ApiChat, msgId: number) {
return undefined; return undefined;
} }
return buildApiReceipt(result); addEntitiesWithPhotosToLocalDb(result.users);
return {
receipt: buildApiReceipt(result),
users: result.users.map(buildApiUser).filter(Boolean),
};
} }
export async function fetchPremiumPromo() { export async function fetchPremiumPromo() {

View File

@ -87,18 +87,36 @@ export async function updateProfilePhoto(photo?: ApiPhoto) {
const result = await invokeRequest(new GramJs.photos.UpdateProfilePhoto({ const result = await invokeRequest(new GramJs.photos.UpdateProfilePhoto({
id: photoId, id: photoId,
})); }));
if (result?.photo instanceof GramJs.Photo) { if (!result) return undefined;
addEntitiesWithPhotosToLocalDb(result.users);
if (result.photo instanceof GramJs.Photo) {
addPhotoToLocalDb(result.photo); addPhotoToLocalDb(result.photo);
return buildApiPhoto(result.photo); return {
users: result.users.map(buildApiUser).filter(Boolean),
photo: buildApiPhoto(result.photo),
};
} }
return undefined; return undefined;
} }
export async function uploadProfilePhoto(file: File) { export async function uploadProfilePhoto(file: File) {
const inputFile = await uploadFile(file); const inputFile = await uploadFile(file);
return invokeRequest(new GramJs.photos.UploadProfilePhoto({ const result = await invokeRequest(new GramJs.photos.UploadProfilePhoto({
file: inputFile, file: inputFile,
}), true); }));
if (!result) return undefined;
addEntitiesWithPhotosToLocalDb(result.users);
if (result.photo instanceof GramJs.Photo) {
addPhotoToLocalDb(result.photo);
return {
users: result.users.map(buildApiUser).filter(Boolean),
photo: buildApiPhoto(result.photo),
};
}
return undefined;
} }
export async function deleteProfilePhotos(photos: ApiPhoto[]) { export async function deleteProfilePhotos(photos: ApiPhoto[]) {
@ -217,8 +235,12 @@ export async function fetchWebAuthorizations() {
if (!result) { if (!result) {
return undefined; return undefined;
} }
addEntitiesWithPhotosToLocalDb(result.users);
return buildCollectionByKey(result.authorizations.map(buildApiWebSession), 'hash'); return {
users: result.users.map(buildApiUser).filter(Boolean),
webAuthorizations: buildCollectionByKey(result.authorizations.map(buildApiWebSession), 'hash'),
};
} }
export function terminateWebAuthorization(hash: string) { export function terminateWebAuthorization(hash: string) {
@ -401,7 +423,10 @@ export async function fetchPrivacySettings(privacyKey: ApiPrivacyKey) {
updateLocalDb(result); updateLocalDb(result);
return buildPrivacyRules(result.rules); return {
users: result.users.map(buildApiUser).filter(Boolean),
rules: buildPrivacyRules(result.rules),
};
} }
export function registerDevice(token: string) { export function registerDevice(token: string) {
@ -476,7 +501,10 @@ export async function setPrivacySettings(
updateLocalDb(result); updateLocalDb(result);
return buildPrivacyRules(result.rules); return {
users: result.users.map(buildApiUser).filter(Boolean),
rules: buildPrivacyRules(result.rules),
};
} }
export async function updateIsOnline(isOnline: boolean) { export async function updateIsOnline(isOnline: boolean) {

View File

@ -2,7 +2,7 @@ import BigInt from 'big-integer';
import { Api as GramJs } from '../../../lib/gramjs'; import { Api as GramJs } from '../../../lib/gramjs';
import type { import type {
ApiChat, ApiChannelStatistics, ApiGroupStatistics, ApiMessageStatistics, ApiMessagePublicForward, StatisticsGraph, ApiChat, ApiMessageStatistics, ApiMessagePublicForward, StatisticsGraph,
} from '../../types'; } from '../../types';
import { invokeRequest } from './client'; import { invokeRequest } from './client';
@ -11,10 +11,11 @@ import { buildInputEntity } from '../gramjsBuilders';
import { import {
buildChannelStatistics, buildGroupStatistics, buildMessageStatistics, buildMessagePublicForwards, buildGraph, buildChannelStatistics, buildGroupStatistics, buildMessageStatistics, buildMessagePublicForwards, buildGraph,
} from '../apiBuilders/statistics'; } from '../apiBuilders/statistics';
import { buildApiUser } from '../apiBuilders/users';
export async function fetchChannelStatistics({ export async function fetchChannelStatistics({
chat, chat,
}: { chat: ApiChat }): Promise<ApiChannelStatistics | undefined> { }: { chat: ApiChat }) {
const result = await invokeRequest(new GramJs.stats.GetBroadcastStats({ const result = await invokeRequest(new GramJs.stats.GetBroadcastStats({
channel: buildInputEntity(chat.id, chat.accessHash) as GramJs.InputChannel, channel: buildInputEntity(chat.id, chat.accessHash) as GramJs.InputChannel,
}), undefined, undefined, undefined, chat.fullInfo!.statisticsDcId); }), undefined, undefined, undefined, chat.fullInfo!.statisticsDcId);
@ -23,12 +24,15 @@ export async function fetchChannelStatistics({
return undefined; return undefined;
} }
return buildChannelStatistics(result); return {
stats: buildChannelStatistics(result),
users: [],
};
} }
export async function fetchGroupStatistics({ export async function fetchGroupStatistics({
chat, chat,
}: { chat: ApiChat }): Promise<ApiGroupStatistics | undefined> { }: { chat: ApiChat }) {
const result = await invokeRequest(new GramJs.stats.GetMegagroupStats({ const result = await invokeRequest(new GramJs.stats.GetMegagroupStats({
channel: buildInputEntity(chat.id, chat.accessHash) as GramJs.InputChannel, channel: buildInputEntity(chat.id, chat.accessHash) as GramJs.InputChannel,
}), undefined, undefined, undefined, chat.fullInfo!.statisticsDcId); }), undefined, undefined, undefined, chat.fullInfo!.statisticsDcId);
@ -37,7 +41,12 @@ export async function fetchGroupStatistics({
return undefined; return undefined;
} }
return buildGroupStatistics(result); addEntitiesWithPhotosToLocalDb(result.users);
return {
users: result.users.map(buildApiUser).filter(Boolean),
stats: buildGroupStatistics(result),
};
} }
export async function fetchMessageStatistics({ export async function fetchMessageStatistics({

View File

@ -252,6 +252,7 @@ export async function fetchProfilePhotos(user?: ApiUser, chat?: ApiChat) {
photos: result.photos photos: result.photos
.filter((photo): photo is GramJs.Photo => photo instanceof GramJs.Photo) .filter((photo): photo is GramJs.Photo => photo instanceof GramJs.Photo)
.map(buildApiPhoto), .map(buildApiPhoto),
users: result.users.map(buildApiUser).filter(Boolean),
}; };
} }
@ -289,4 +290,8 @@ function updateLocalDb(result: (GramJs.photos.Photos | GramJs.photos.PhotosSlice
if ('photos' in result) { if ('photos' in result) {
result.photos.forEach(addPhotoToLocalDb); result.photos.forEach(addPhotoToLocalDb);
} }
if ('users' in result) {
addEntitiesWithPhotosToLocalDb(result.users);
}
} }

View File

@ -29,6 +29,7 @@ const SettingsLanguage: FC<OwnProps & StateProps> = ({
}) => { }) => {
const { const {
loadLanguages, loadLanguages,
loadAttachBots,
setSettingOption, setSettingOption,
} = getActions(); } = getActions();
@ -48,8 +49,10 @@ const SettingsLanguage: FC<OwnProps & StateProps> = ({
unmarkIsLoading(); unmarkIsLoading();
setSettingOption({ language: langCode }); setSettingOption({ language: langCode });
loadAttachBots(); // Should be refetched every language change
}); });
}, [markIsLoading, unmarkIsLoading, setSettingOption]); }, [markIsLoading, unmarkIsLoading, setSettingOption, loadAttachBots]);
const options = useMemo(() => { const options = useMemo(() => {
return languages ? buildOptions(languages) : undefined; return languages ? buildOptions(languages) : undefined;

View File

@ -2,6 +2,8 @@ import { addActionHandler, getGlobal, setGlobal } from '../../index';
import { selectChat } from '../../selectors'; import { selectChat } from '../../selectors';
import { callApi } from '../../../api/gramjs'; import { callApi } from '../../../api/gramjs';
import { getTranslation } from '../../../util/langProvider'; import { getTranslation } from '../../../util/langProvider';
import { addUsers } from '../../reducers';
import { buildCollectionByKey } from '../../../util/iteratees';
addActionHandler('reportPeer', async (global, actions, payload) => { addActionHandler('reportPeer', async (global, actions, payload) => {
const { const {
@ -171,17 +173,21 @@ addActionHandler('changeSessionTtl', async (global, actions, payload) => {
}); });
}); });
addActionHandler('loadWebAuthorizations', async () => { addActionHandler('loadWebAuthorizations', async (global) => {
const result = await callApi('fetchWebAuthorizations'); const result = await callApi('fetchWebAuthorizations');
if (!result) { if (!result) {
return; return;
} }
const { users, webAuthorizations } = result;
global = getGlobal();
global = addUsers(global, buildCollectionByKey(users, 'id'));
setGlobal({ setGlobal({
...getGlobal(), ...global,
activeWebSessions: { activeWebSessions: {
byHash: result, byHash: webAuthorizations,
orderedHashes: Object.keys(result), orderedHashes: Object.keys(webAuthorizations),
}, },
}); });
}); });

View File

@ -579,7 +579,8 @@ async function loadAttachBots(hash?: string) {
return; return;
} }
const global = getGlobal(); let global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal({ setGlobal({
...global, ...global,
attachMenu: { attachMenu: {

View File

@ -20,6 +20,8 @@ import {
} from '../../reducers/calls'; } from '../../reducers/calls';
import { getGroupCallAudioContext, getGroupCallAudioElement, removeGroupCallAudioElement } from '../ui/calls'; import { getGroupCallAudioContext, getGroupCallAudioElement, removeGroupCallAudioElement } from '../ui/calls';
import { loadFullChat } from './chats'; import { loadFullChat } from './chats';
import { addUsers } from '../../reducers';
import { buildCollectionByKey } from '../../../util/iteratees';
addActionHandler('leaveGroupCall', async (global, actions, payload) => { addActionHandler('leaveGroupCall', async (global, actions, payload) => {
const { const {
@ -233,7 +235,11 @@ addActionHandler('connectToActivePhoneCall', async (global, actions) => {
if (!result) { if (!result) {
actions.hangUp(); actions.hangUp();
return;
} }
global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal(global);
}); });
addActionHandler('acceptCall', async (global) => { addActionHandler('acceptCall', async (global) => {
@ -247,7 +253,13 @@ addActionHandler('acceptCall', async (global) => {
await callApi('createPhoneCallState', [false]); await callApi('createPhoneCallState', [false]);
const gB = await callApi('acceptPhoneCall', [dhConfig])!; const gB = await callApi('acceptPhoneCall', [dhConfig])!;
callApi('acceptCall', { call: phoneCall, gB }); const result = await callApi('acceptCall', { call: phoneCall, gB });
if (!result) {
return;
}
global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal(global);
}); });
addActionHandler('sendSignalingData', (global, actions, payload) => { addActionHandler('sendSignalingData', (global, actions, payload) => {

View File

@ -170,6 +170,9 @@ addActionHandler('focusMessageInComments', async (global, actions, payload) => {
if (!result) { if (!result) {
return; return;
} }
global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal(global);
actions.focusMessage({ chatId, threadId, messageId }); actions.focusMessage({ chatId, threadId, messageId });
}); });
@ -1255,10 +1258,14 @@ addActionHandler('loadChatSettings', async (global, actions, payload) => {
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) return; if (!chat) return;
const settings = await callApi('fetchChatSettings', chat); const result = await callApi('fetchChatSettings', chat);
if (!settings) return; if (!result) return;
const { settings, users } = result;
global = getGlobal();
setGlobal(updateChat(getGlobal(), chat.id, { settings })); global = addUsers(global, buildCollectionByKey(users, 'id'));
setGlobal(updateChat(global, chat.id, { settings }));
}); });
addActionHandler('toggleJoinToSend', async (global, actions, payload) => { addActionHandler('toggleJoinToSend', async (global, actions, payload) => {
@ -1981,7 +1988,7 @@ async function openCommentsByUsername(
if (!chat) return; if (!chat) return;
const global = getGlobal(); let global = getGlobal();
const threadInfo = selectThreadInfo(global, chat.id, messageId); const threadInfo = selectThreadInfo(global, chat.id, messageId);
let discussionChatId: string | undefined; let discussionChatId: string | undefined;
@ -1989,6 +1996,9 @@ async function openCommentsByUsername(
if (!threadInfo) { if (!threadInfo) {
const result = await callApi('requestThreadInfoUpdate', { chat, threadId: messageId }); const result = await callApi('requestThreadInfoUpdate', { chat, threadId: messageId });
if (!result) return; if (!result) return;
global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal(global);
discussionChatId = result.discussionChatId; discussionChatId = result.discussionChatId;
} else { } else {

View File

@ -27,10 +27,11 @@ import {
clearLegacySessions, clearLegacySessions,
} from '../../../util/sessions'; } from '../../../util/sessions';
import { forceWebsync } from '../../../util/websync'; import { forceWebsync } from '../../../util/websync';
import { clearGlobalForLockScreen, updatePasscodeSettings } from '../../reducers'; import { addUsers, clearGlobalForLockScreen, updatePasscodeSettings } from '../../reducers';
import { clearEncryptedSession, encryptSession, forgetPasscode } from '../../../util/passcode'; import { clearEncryptedSession, encryptSession, forgetPasscode } from '../../../util/passcode';
import { serializeGlobal } from '../../cache'; import { serializeGlobal } from '../../cache';
import { parseInitialLocationHash } from '../../../util/routing'; import { parseInitialLocationHash } from '../../../util/routing';
import { buildCollectionByKey } from '../../../util/iteratees';
addActionHandler('initApi', async (global, actions) => { addActionHandler('initApi', async (global, actions) => {
if (!IS_TEST) { if (!IS_TEST) {
@ -90,10 +91,15 @@ addActionHandler('setAuthPassword', (global, actions, payload) => {
}; };
}); });
addActionHandler('uploadProfilePhoto', (global, actions, payload) => { addActionHandler('uploadProfilePhoto', async (global, actions, payload) => {
const { file } = payload!; const { file } = payload!;
void callApi('uploadProfilePhoto', file); const result = await callApi('uploadProfilePhoto', file);
if (!result) return;
global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal(global);
}); });
addActionHandler('signUp', (global, actions, payload) => { addActionHandler('signUp', (global, actions, payload) => {

View File

@ -9,6 +9,7 @@ import {
import { selectChat, selectCurrentMessageList, selectUser } from '../../selectors'; import { selectChat, selectCurrentMessageList, selectUser } from '../../selectors';
import { migrateChat } from './chats'; import { migrateChat } from './chats';
import { isChatBasicGroup } from '../../helpers'; import { isChatBasicGroup } from '../../helpers';
import { buildCollectionByKey } from '../../../util/iteratees';
addActionHandler('checkPublicLink', async (global, actions, payload) => { addActionHandler('checkPublicLink', async (global, actions, payload) => {
const { chatId } = selectCurrentMessageList(global) || {}; const { chatId } = selectCurrentMessageList(global) || {};
@ -116,10 +117,13 @@ addActionHandler('loadExportedChatInvites', async (global, actions, payload) =>
if (!result) { if (!result) {
return; return;
} }
global = getGlobal();
const { invites, users } = result;
const update = isRevoked ? { revokedInvites: result } : { invites: result }; global = addUsers(global, buildCollectionByKey(users, 'id'));
setGlobal(updateManagement(getGlobal(), chatId, update)); const update = isRevoked ? { revokedInvites: invites } : { invites };
setGlobal(updateManagement(global, chatId, update));
}); });
addActionHandler('editExportedChatInvite', async (global, actions, payload) => { addActionHandler('editExportedChatInvite', async (global, actions, payload) => {
@ -142,7 +146,7 @@ addActionHandler('editExportedChatInvite', async (global, actions, payload) => {
return; return;
} }
const { oldInvite, newInvite } = result; const { oldInvite, newInvite, users } = result;
global = getGlobal(); global = getGlobal();
const invites = (global.management.byChatId[chatId].invites || []) const invites = (global.management.byChatId[chatId].invites || [])
@ -155,6 +159,8 @@ addActionHandler('editExportedChatInvite', async (global, actions, payload) => {
invites.push(newInvite); invites.push(newInvite);
} }
global = addUsers(global, buildCollectionByKey(users, 'id'));
setGlobal(updateManagement(global, chatId, { setGlobal(updateManagement(global, chatId, {
invites, invites,
revokedInvites, revokedInvites,

View File

@ -751,14 +751,18 @@ addActionHandler('rescheduleMessage', (global, actions, payload) => {
}); });
}); });
addActionHandler('requestThreadInfoUpdate', (global, actions, payload) => { addActionHandler('requestThreadInfoUpdate', async (global, actions, payload) => {
const { chatId, threadId } = payload; const { chatId, threadId } = payload;
const chat = selectThreadOriginChat(global, chatId, threadId); const chat = selectThreadOriginChat(global, chatId, threadId);
if (!chat) { if (!chat) {
return; return;
} }
void callApi('requestThreadInfoUpdate', { chat, threadId }); const result = await callApi('requestThreadInfoUpdate', { chat, threadId });
if (!result) return;
global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal(global);
}); });
addActionHandler('transcribeAudio', async (global, actions, payload) => { addActionHandler('transcribeAudio', async (global, actions, payload) => {

View File

@ -92,10 +92,11 @@ async function getPaymentForm(inputInvoice: ApiRequestInputInvoice): Promise<Api
return undefined; return undefined;
} }
const { form, invoice } = result; const { form, invoice, users } = result;
let global = setPaymentForm(getGlobal(), form); let global = setPaymentForm(getGlobal(), form);
global = setPaymentStep(global, PaymentStep.Checkout); global = setPaymentStep(global, PaymentStep.Checkout);
global = addUsers(global, buildCollectionByKey(users, 'id'));
setGlobal(global); setGlobal(global);
return invoice; return invoice;
@ -119,7 +120,8 @@ async function getReceipt(chat: ApiChat, messageId: number, receiptMessageId: nu
let global = getGlobal(); let global = getGlobal();
const message = selectChatMessage(global, chat.id, messageId); const message = selectChatMessage(global, chat.id, messageId);
global = setReceipt(global, result, message); global = addUsers(global, buildCollectionByKey(result.users, 'id'));
global = setReceipt(global, result.receipt, message);
setGlobal(global); setGlobal(global);
} }

View File

@ -2,9 +2,9 @@ import { addActionHandler, getGlobal, setGlobal } from '../../index';
import type { GlobalState } from '../../types'; import type { GlobalState } from '../../types';
import type { import type {
ApiPrivacyKey, PrivacyVisibility, InputPrivacyRules, InputPrivacyContact, ApiPrivacyKey, PrivacyVisibility, InputPrivacyRules, InputPrivacyContact, ApiPrivacySettings,
} from '../../../types'; } from '../../../types';
import type { ApiUsername } from '../../../api/types'; import type { ApiUser, ApiUsername } from '../../../api/types';
import { import {
ProfileEditProgress, ProfileEditProgress,
UPLOADING_WALLPAPER_SLUG, UPLOADING_WALLPAPER_SLUG,
@ -44,6 +44,8 @@ addActionHandler('updateProfile', async (global, actions, payload) => {
if (photo) { if (photo) {
const result = await callApi('uploadProfilePhoto', photo); const result = await callApi('uploadProfilePhoto', photo);
if (result) { if (result) {
global = getGlobal();
setGlobal(addUsers(global, buildCollectionByKey(result.users, 'id')));
actions.loadProfilePhotos({ profileId: currentUserId }); actions.loadProfilePhotos({ profileId: currentUserId });
} }
} }
@ -106,18 +108,23 @@ addActionHandler('updateProfilePhoto', async (global, actions, payload) => {
profilePhoto: undefined, profilePhoto: undefined,
}, },
})); }));
const newPhoto = await callApi('updateProfilePhoto', photo); const result = await callApi('updateProfilePhoto', photo);
if (newPhoto) { if (!result) return;
setGlobal(updateUser(getGlobal(), currentUserId, {
avatarHash: newPhoto.id, const { photo: newPhoto, users } = result;
fullInfo: { global = getGlobal();
...currentUser.fullInfo, global = addUsers(global, buildCollectionByKey(users, 'id'));
profilePhoto: newPhoto,
}, setGlobal(updateUser(global, currentUserId, {
})); avatarHash: newPhoto.id,
actions.loadFullUser({ userId: currentUserId }); fullInfo: {
actions.loadProfilePhotos({ profileId: currentUserId }); ...currentUser.fullInfo,
} profilePhoto: newPhoto,
},
}));
actions.loadFullUser({ userId: currentUserId });
actions.loadProfilePhotos({ profileId: currentUserId });
}); });
addActionHandler('deleteProfilePhoto', async (global, actions, payload) => { addActionHandler('deleteProfilePhoto', async (global, actions, payload) => {
@ -375,16 +382,7 @@ addActionHandler('loadLanguages', async () => {
}); });
addActionHandler('loadPrivacySettings', async (global) => { addActionHandler('loadPrivacySettings', async (global) => {
const [ const result = await Promise.all([
phoneNumberSettings,
lastSeenSettings,
profilePhotoSettings,
forwardsSettings,
chatInviteSettings,
phoneCallSettings,
phoneP2PSettings,
voiceMessagesSettings,
] = await Promise.all([
callApi('fetchPrivacySettings', 'phoneNumber'), callApi('fetchPrivacySettings', 'phoneNumber'),
callApi('fetchPrivacySettings', 'lastSeen'), callApi('fetchPrivacySettings', 'lastSeen'),
callApi('fetchPrivacySettings', 'profilePhoto'), callApi('fetchPrivacySettings', 'profilePhoto'),
@ -395,34 +393,42 @@ addActionHandler('loadPrivacySettings', async (global) => {
callApi('fetchPrivacySettings', 'voiceMessages'), callApi('fetchPrivacySettings', 'voiceMessages'),
]); ]);
if ( if (result.some((e) => e === undefined)) {
!phoneNumberSettings
|| !lastSeenSettings
|| !profilePhotoSettings
|| !forwardsSettings
|| !chatInviteSettings
|| !phoneCallSettings
|| !phoneP2PSettings
|| !voiceMessagesSettings
) {
return; return;
} }
const [
phoneNumberSettings,
lastSeenSettings,
profilePhotoSettings,
forwardsSettings,
chatInviteSettings,
phoneCallSettings,
phoneP2PSettings,
voiceMessagesSettings,
] = result as {
users: ApiUser[];
rules: ApiPrivacySettings;
}[];
const allUsers = result.flatMap((e) => e!.users);
global = getGlobal(); global = getGlobal();
global = addUsers(global, buildCollectionByKey(allUsers, 'id'));
setGlobal({ setGlobal({
...global, ...global,
settings: { settings: {
...global.settings, ...global.settings,
privacy: { privacy: {
...global.settings.privacy, ...global.settings.privacy,
phoneNumber: phoneNumberSettings, phoneNumber: phoneNumberSettings.rules,
lastSeen: lastSeenSettings, lastSeen: lastSeenSettings.rules,
profilePhoto: profilePhotoSettings, profilePhoto: profilePhotoSettings.rules,
forwards: forwardsSettings, forwards: forwardsSettings.rules,
chatInvite: chatInviteSettings, chatInvite: chatInviteSettings.rules,
phoneCall: phoneCallSettings, phoneCall: phoneCallSettings.rules,
phoneP2P: phoneP2PSettings, phoneP2P: phoneP2PSettings.rules,
voiceMessages: voiceMessagesSettings, voiceMessages: voiceMessagesSettings.rules,
}, },
}, },
}); });
@ -451,14 +457,14 @@ addActionHandler('setPrivacyVisibility', async (global, actions, payload) => {
} }
global = getGlobal(); global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal({ setGlobal({
...global, ...global,
settings: { settings: {
...global.settings, ...global.settings,
privacy: { privacy: {
...global.settings.privacy, ...global.settings.privacy,
[privacyKey]: result, [privacyKey]: result.rules,
}, },
}, },
}); });
@ -486,14 +492,14 @@ addActionHandler('setPrivacySettings', async (global, actions, payload) => {
} }
global = getGlobal(); global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal({ setGlobal({
...global, ...global,
settings: { settings: {
...global.settings, ...global.settings,
privacy: { privacy: {
...global.settings.privacy, ...global.settings.privacy,
[privacyKey]: result, [privacyKey]: result.rules,
}, },
}, },
}); });

View File

@ -1,9 +1,11 @@
import { addActionHandler, getGlobal, setGlobal } from '../../index'; import { addActionHandler, getGlobal, setGlobal } from '../../index';
import type { ApiChannelStatistics } from '../../../api/types';
import { callApi } from '../../../api/gramjs'; import { callApi } from '../../../api/gramjs';
import { updateStatistics, updateMessageStatistics, updateStatisticsGraph } from '../../reducers'; import {
updateStatistics, updateMessageStatistics, updateStatisticsGraph, addUsers,
} from '../../reducers';
import { selectChatMessages, selectChat } from '../../selectors'; import { selectChatMessages, selectChat } from '../../selectors';
import { buildCollectionByKey } from '../../../util/iteratees';
addActionHandler('loadStatistics', async (global, actions, payload) => { addActionHandler('loadStatistics', async (global, actions, payload) => {
const { chatId, isGroup } = payload; const { chatId, isGroup } = payload;
@ -18,15 +20,17 @@ addActionHandler('loadStatistics', async (global, actions, payload) => {
} }
global = getGlobal(); global = getGlobal();
const { stats, users } = result;
if ((result as ApiChannelStatistics).recentTopMessages?.length) { global = addUsers(global, buildCollectionByKey(users, 'id'));
if ('recentTopMessages' in stats && stats.recentTopMessages.length) {
const messages = selectChatMessages(global, chatId); const messages = selectChatMessages(global, chatId);
(result as ApiChannelStatistics).recentTopMessages = (result as ApiChannelStatistics).recentTopMessages stats.recentTopMessages = stats.recentTopMessages.map((message) => ({ ...message, ...messages[message.msgId] }));
.map((message) => ({ ...message, ...messages[message.msgId] }));
} }
setGlobal(updateStatistics(global, chatId, result)); setGlobal(updateStatistics(global, chatId, stats));
}); });
addActionHandler('loadMessageStatistics', async (global, actions, payload) => { addActionHandler('loadMessageStatistics', async (global, actions, payload) => {

View File

@ -252,13 +252,14 @@ addActionHandler('loadProfilePhotos', async (global, actions, payload) => {
global = getGlobal(); global = getGlobal();
const userOrChat = user || chat; const userOrChat = user || chat;
const { photos } = result; const { photos, users } = result;
photos.sort((a) => (a.id === userOrChat?.avatarHash ? -1 : 1)); photos.sort((a) => (a.id === userOrChat?.avatarHash ? -1 : 1));
global = addUsers(global, buildCollectionByKey(users, 'id'));
if (isPrivate) { if (isPrivate) {
global = updateUser(global, profileId, { photos }); global = updateUser(global, profileId, { photos });
} else { } else {
global = addUsers(global, buildCollectionByKey(result.users!, 'id'));
global = updateChat(global, profileId, { photos }); global = updateChat(global, profileId, { photos });
} }

View File

@ -1,7 +1,7 @@
import { addActionHandler, getGlobal, setGlobal } from '../../index'; import { addActionHandler, getGlobal, setGlobal } from '../../index';
import { selectActiveGroupCall, selectGroupCallParticipant, selectPhoneCallUser } from '../../selectors/calls'; import { selectActiveGroupCall, selectGroupCallParticipant, selectPhoneCallUser } from '../../selectors/calls';
import { updateGroupCall, updateGroupCallParticipant } from '../../reducers/calls'; import { updateGroupCall, updateGroupCallParticipant } from '../../reducers/calls';
import { omit } from '../../../util/iteratees'; import { buildCollectionByKey, omit } from '../../../util/iteratees';
import type { ApiCallProtocol } from '../../../lib/secret-sauce'; import type { ApiCallProtocol } from '../../../lib/secret-sauce';
import { import {
handleUpdateGroupCallConnection, handleUpdateGroupCallConnection,
@ -13,6 +13,7 @@ import { ARE_CALLS_SUPPORTED } from '../../../util/environment';
import { callApi } from '../../../api/gramjs'; import { callApi } from '../../../api/gramjs';
import * as langProvider from '../../../util/langProvider'; import * as langProvider from '../../../util/langProvider';
import { EMOJI_DATA, EMOJI_OFFSETS } from '../../../util/phoneCallEmojiConstants'; import { EMOJI_DATA, EMOJI_OFFSETS } from '../../../util/phoneCallEmojiConstants';
import { addUsers } from '../../reducers';
addActionHandler('apiUpdate', (global, actions, update) => { addActionHandler('apiUpdate', (global, actions, update) => {
const { activeGroupCallId } = global.groupCalls; const { activeGroupCallId } = global.groupCalls;
@ -133,9 +134,14 @@ addActionHandler('apiUpdate', (global, actions, update) => {
phoneCall: newCall, phoneCall: newCall,
}); });
callApi('confirmCall', { const result = await callApi('confirmCall', {
call, gA, keyFingerprint, call, gA, keyFingerprint,
}); });
if (result) {
global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal(global);
}
})(); })();
} else if (state === 'active' && connections && phoneCall?.state !== 'active') { } else if (state === 'active' && connections && phoneCall?.state !== 'active') {
if (!isOutgoing) { if (!isOutgoing) {