TeactN: Prevent race condition in async action handlers

This commit is contained in:
Alexander Zinchuk 2022-04-08 20:59:55 +02:00
parent 439e78ad82
commit fbe03b556b
13 changed files with 231 additions and 236 deletions

View File

@ -150,12 +150,12 @@ addActionHandler('restartBot', async (global, actions, payload) => {
addActionHandler('loadTopInlineBots', async (global) => { addActionHandler('loadTopInlineBots', async (global) => {
const { lastRequestedAt } = global.topInlineBots; const { lastRequestedAt } = global.topInlineBots;
if (lastRequestedAt && getServerTime(global.serverTimeOffset) - lastRequestedAt < TOP_PEERS_REQUEST_COOLDOWN) { if (lastRequestedAt && getServerTime(global.serverTimeOffset) - lastRequestedAt < TOP_PEERS_REQUEST_COOLDOWN) {
return undefined; return;
} }
const result = await callApi('fetchTopInlineBots'); const result = await callApi('fetchTopInlineBots');
if (!result) { if (!result) {
return undefined; return;
} }
const { ids, users } = result; const { ids, users } = result;
@ -170,7 +170,7 @@ addActionHandler('loadTopInlineBots', async (global) => {
lastRequestedAt: getServerTime(global.serverTimeOffset), lastRequestedAt: getServerTime(global.serverTimeOffset),
}, },
}; };
return global; setGlobal(global);
}); });
addActionHandler('queryInlineBot', async (global, actions, payload) => { addActionHandler('queryInlineBot', async (global, actions, payload) => {

View File

@ -678,14 +678,14 @@ addActionHandler('updateChatMemberBannedRights', async (global, actions, payload
const user = selectUser(global, userId); const user = selectUser(global, userId);
if (!chat || !user) { if (!chat || !user) {
return undefined; return;
} }
if (isChatBasicGroup(chat)) { if (isChatBasicGroup(chat)) {
chat = await callApi('migrateChat', chat); chat = await callApi('migrateChat', chat);
if (!chat) { if (!chat) {
return undefined; return;
} }
actions.openChat({ id: chat.id }); actions.openChat({ id: chat.id });
@ -698,7 +698,7 @@ addActionHandler('updateChatMemberBannedRights', async (global, actions, payload
const chatAfterUpdate = selectChat(global, chatId); const chatAfterUpdate = selectChat(global, chatId);
if (!chatAfterUpdate || !chatAfterUpdate.fullInfo) { if (!chatAfterUpdate || !chatAfterUpdate.fullInfo) {
return undefined; return;
} }
const { members, kickedMembers } = chatAfterUpdate.fullInfo; const { members, kickedMembers } = chatAfterUpdate.fullInfo;
@ -706,7 +706,7 @@ addActionHandler('updateChatMemberBannedRights', async (global, actions, payload
const isBanned = Boolean(bannedRights.viewMessages); const isBanned = Boolean(bannedRights.viewMessages);
const isUnblocked = !Object.keys(bannedRights).length; const isUnblocked = !Object.keys(bannedRights).length;
return updateChat(global, chatId, { setGlobal(updateChat(global, chatId, {
fullInfo: { fullInfo: {
...chatAfterUpdate.fullInfo, ...chatAfterUpdate.fullInfo,
...(members && isBanned && { ...(members && isBanned && {
@ -723,7 +723,7 @@ addActionHandler('updateChatMemberBannedRights', async (global, actions, payload
kickedMembers: kickedMembers.filter((m) => m.userId !== userId), kickedMembers: kickedMembers.filter((m) => m.userId !== userId),
}), }),
}, },
}); }));
}); });
addActionHandler('updateChatAdmin', async (global, actions, payload) => { addActionHandler('updateChatAdmin', async (global, actions, payload) => {
@ -734,13 +734,13 @@ addActionHandler('updateChatAdmin', async (global, actions, payload) => {
let chat = selectChat(global, chatId); let chat = selectChat(global, chatId);
const user = selectUser(global, userId); const user = selectUser(global, userId);
if (!chat || !user) { if (!chat || !user) {
return undefined; return;
} }
if (isChatBasicGroup(chat)) { if (isChatBasicGroup(chat)) {
chat = await callApi('migrateChat', chat); chat = await callApi('migrateChat', chat);
if (!chat) { if (!chat) {
return undefined; return;
} }
actions.openChat({ id: chat.id }); actions.openChat({ id: chat.id });
@ -752,7 +752,7 @@ addActionHandler('updateChatAdmin', async (global, actions, payload) => {
const chatAfterUpdate = await callApi('fetchFullChat', chat); const chatAfterUpdate = await callApi('fetchFullChat', chat);
if (!chatAfterUpdate?.fullInfo) { if (!chatAfterUpdate?.fullInfo) {
return undefined; return;
} }
const { adminMembers } = chatAfterUpdate.fullInfo; const { adminMembers } = chatAfterUpdate.fullInfo;
@ -760,7 +760,7 @@ addActionHandler('updateChatAdmin', async (global, actions, payload) => {
global = getGlobal(); global = getGlobal();
return updateChat(global, chatId, { setGlobal(updateChat(global, chatId, {
fullInfo: { fullInfo: {
...chatAfterUpdate.fullInfo, ...chatAfterUpdate.fullInfo,
...(adminMembers && isDismissed && { ...(adminMembers && isDismissed && {
@ -774,7 +774,7 @@ addActionHandler('updateChatAdmin', async (global, actions, payload) => {
)), )),
}), }),
}, },
}); }));
}); });
addActionHandler('updateChat', async (global, actions, payload) => { addActionHandler('updateChat', async (global, actions, payload) => {
@ -784,7 +784,7 @@ addActionHandler('updateChat', async (global, actions, payload) => {
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
return undefined; return;
} }
setGlobal(updateManagementProgress(getGlobal(), ManagementProgress.InProgress)); setGlobal(updateManagementProgress(getGlobal(), ManagementProgress.InProgress));
@ -801,7 +801,7 @@ addActionHandler('updateChat', async (global, actions, payload) => {
: undefined, : undefined,
]); ]);
return updateManagementProgress(getGlobal(), ManagementProgress.Complete); setGlobal(updateManagementProgress(getGlobal(), ManagementProgress.Complete));
}); });
addActionHandler('toggleSignatures', (global, actions, payload) => { addActionHandler('toggleSignatures', (global, actions, payload) => {
@ -818,7 +818,7 @@ addActionHandler('toggleSignatures', (global, actions, payload) => {
addActionHandler('loadGroupsForDiscussion', async (global) => { addActionHandler('loadGroupsForDiscussion', async (global) => {
const groups = await callApi('fetchGroupsForDiscussion'); const groups = await callApi('fetchGroupsForDiscussion');
if (!groups) { if (!groups) {
return undefined; return;
} }
const addedById = groups.reduce((result, group) => { const addedById = groups.reduce((result, group) => {
@ -831,13 +831,13 @@ addActionHandler('loadGroupsForDiscussion', async (global) => {
global = getGlobal(); global = getGlobal();
global = addChats(global, addedById); global = addChats(global, addedById);
return { setGlobal({
...global, ...global,
chats: { chats: {
...global.chats, ...global.chats,
forDiscussionIds: Object.keys(addedById), forDiscussionIds: Object.keys(addedById),
}, },
}; });
}); });
addActionHandler('linkDiscussionGroup', async (global, actions, payload) => { addActionHandler('linkDiscussionGroup', async (global, actions, payload) => {
@ -933,24 +933,24 @@ addActionHandler('loadMoreMembers', async (global) => {
const { chatId } = selectCurrentMessageList(global) || {}; const { chatId } = selectCurrentMessageList(global) || {};
const chat = chatId ? selectChat(global, chatId) : undefined; const chat = chatId ? selectChat(global, chatId) : undefined;
if (!chat || isChatBasicGroup(chat)) { if (!chat || isChatBasicGroup(chat)) {
return undefined; return;
} }
const offset = (chat.fullInfo?.members?.length) || undefined; const offset = (chat.fullInfo?.members?.length) || undefined;
const result = await callApi('fetchMembers', chat.id, chat.accessHash!, 'recent', offset); const result = await callApi('fetchMembers', chat.id, chat.accessHash!, 'recent', offset);
if (!result) { if (!result) {
return undefined; return;
} }
const { members, users } = result; const { members, users } = result;
if (!members || !members.length) { if (!members || !members.length) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
global = addUsers(global, buildCollectionByKey(users, 'id')); global = addUsers(global, buildCollectionByKey(users, 'id'));
global = addChatMembers(global, chat, members); global = addChatMembers(global, chat, members);
return global; setGlobal(global);
}); });
addActionHandler('addChatMembers', async (global, actions, payload) => { addActionHandler('addChatMembers', async (global, actions, payload) => {
@ -1008,12 +1008,12 @@ addActionHandler('setChatEnabledReactions', async (global, actions, payload) =>
addActionHandler('loadChatSettings', async (global, actions, payload) => { addActionHandler('loadChatSettings', async (global, actions, payload) => {
const { chatId } = payload!; const { chatId } = payload!;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) return undefined; if (!chat) return;
const settings = await callApi('fetchChatSettings', chat); const settings = await callApi('fetchChatSettings', chat);
if (!settings) return undefined; if (!settings) return;
return updateChat(getGlobal(), chat.id, { settings }); setGlobal(updateChat(getGlobal(), chat.id, { settings }));
}); });
async function loadChats( async function loadChats(

View File

@ -1,4 +1,6 @@
import { addActionHandler, getActions, getGlobal } from '../../index'; import {
addActionHandler, getActions, getGlobal, setGlobal,
} from '../../index';
import { initApi, callApi } from '../../../api/gramjs'; import { initApi, callApi } from '../../../api/gramjs';
@ -165,15 +167,15 @@ addActionHandler('disconnect', () => {
addActionHandler('loadNearestCountry', async (global) => { addActionHandler('loadNearestCountry', async (global) => {
if (global.connectionState !== 'connectionStateReady') { if (global.connectionState !== 'connectionStateReady') {
return undefined; return;
} }
const authNearestCountry = await callApi('fetchNearestCountry'); const authNearestCountry = await callApi('fetchNearestCountry');
return { setGlobal({
...getGlobal(), ...getGlobal(),
authNearestCountry, authNearestCountry,
}; });
}); });
addActionHandler('setDeviceToken', (global, actions, deviceToken) => { addActionHandler('setDeviceToken', (global, actions, deviceToken) => {

View File

@ -9,12 +9,12 @@ import { isChatBasicGroup } from '../../helpers';
addActionHandler('checkPublicLink', async (global, actions, payload) => { addActionHandler('checkPublicLink', async (global, actions, payload) => {
const { chatId } = selectCurrentMessageList(global) || {}; const { chatId } = selectCurrentMessageList(global) || {};
if (!chatId) { if (!chatId) {
return undefined; return;
} }
// No need to check the username if already in progress // No need to check the username if already in progress
if (global.management.progress === ManagementProgress.InProgress) { if (global.management.progress === ManagementProgress.InProgress) {
return undefined; return;
} }
const { username } = payload!; const { username } = payload!;
@ -30,14 +30,14 @@ addActionHandler('checkPublicLink', async (global, actions, payload) => {
global, isUsernameAvailable ? ManagementProgress.Complete : ManagementProgress.Error, global, isUsernameAvailable ? ManagementProgress.Complete : ManagementProgress.Error,
); );
global = updateManagement(global, chatId, { isUsernameAvailable }); global = updateManagement(global, chatId, { isUsernameAvailable });
return global; setGlobal(global);
}); });
addActionHandler('updatePublicLink', async (global, actions, payload) => { addActionHandler('updatePublicLink', async (global, actions, payload) => {
const { chatId } = selectCurrentMessageList(global) || {}; const { chatId } = selectCurrentMessageList(global) || {};
let chat = chatId && selectChat(global, chatId); let chat = chatId && selectChat(global, chatId);
if (!chatId || !chat) { if (!chatId || !chat) {
return undefined; return;
} }
const { username } = payload!; const { username } = payload!;
@ -49,7 +49,7 @@ addActionHandler('updatePublicLink', async (global, actions, payload) => {
chat = await callApi('migrateChat', chat); chat = await callApi('migrateChat', chat);
if (!chat) { if (!chat) {
return undefined; return;
} }
actions.openChat({ id: chat.id }); actions.openChat({ id: chat.id });
@ -60,7 +60,7 @@ addActionHandler('updatePublicLink', async (global, actions, payload) => {
global = getGlobal(); global = getGlobal();
global = updateManagementProgress(global, result ? ManagementProgress.Complete : ManagementProgress.Error); global = updateManagementProgress(global, result ? ManagementProgress.Complete : ManagementProgress.Error);
global = updateManagement(global, chatId, { isUsernameAvailable: undefined }); global = updateManagement(global, chatId, { isUsernameAvailable: undefined });
return global; setGlobal(global);
}); });
addActionHandler('updatePrivateLink', (global) => { addActionHandler('updatePrivateLink', (global) => {
@ -93,18 +93,18 @@ addActionHandler('loadExportedChatInvites', async (global, actions, payload) =>
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
const admin = selectUser(global, adminId || global.currentUserId); const admin = selectUser(global, adminId || global.currentUserId);
if (!peer || !admin) return undefined; if (!peer || !admin) return;
const result = await callApi('fetchExportedChatInvites', { const result = await callApi('fetchExportedChatInvites', {
peer, admin, isRevoked, limit, peer, admin, isRevoked, limit,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
const update = isRevoked ? { revokedInvites: result } : { invites: result }; const update = isRevoked ? { revokedInvites: result } : { invites: result };
return updateManagement(getGlobal(), chatId, update); setGlobal(updateManagement(getGlobal(), chatId, update));
}); });
addActionHandler('editExportedChatInvite', async (global, actions, payload) => { addActionHandler('editExportedChatInvite', async (global, actions, payload) => {
@ -112,7 +112,7 @@ addActionHandler('editExportedChatInvite', async (global, actions, payload) => {
chatId, link, isRevoked, expireDate, usageLimit, isRequestNeeded, title, chatId, link, isRevoked, expireDate, usageLimit, isRequestNeeded, title,
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
if (!peer) return undefined; if (!peer) return;
const result = await callApi('editExportedChatInvite', { const result = await callApi('editExportedChatInvite', {
peer, peer,
@ -124,7 +124,7 @@ addActionHandler('editExportedChatInvite', async (global, actions, payload) => {
title, title,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
const { oldInvite, newInvite } = result; const { oldInvite, newInvite } = result;
@ -140,10 +140,10 @@ addActionHandler('editExportedChatInvite', async (global, actions, payload) => {
invites.push(newInvite); invites.push(newInvite);
} }
return updateManagement(global, chatId, { setGlobal(updateManagement(global, chatId, {
invites, invites,
revokedInvites, revokedInvites,
}); }));
}); });
addActionHandler('exportChatInvite', async (global, actions, payload) => { addActionHandler('exportChatInvite', async (global, actions, payload) => {
@ -151,7 +151,7 @@ addActionHandler('exportChatInvite', async (global, actions, payload) => {
chatId, expireDate, usageLimit, isRequestNeeded, title, chatId, expireDate, usageLimit, isRequestNeeded, title,
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
if (!peer) return undefined; if (!peer) return;
const result = await callApi('exportChatInvite', { const result = await callApi('exportChatInvite', {
peer, peer,
@ -161,14 +161,14 @@ addActionHandler('exportChatInvite', async (global, actions, payload) => {
title, title,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
const invites = global.management.byChatId[chatId].invites || []; const invites = global.management.byChatId[chatId].invites || [];
return updateManagement(global, chatId, { setGlobal(updateManagement(global, chatId, {
invites: [...invites, result], invites: [...invites, result],
}); }));
}); });
addActionHandler('deleteExportedChatInvite', async (global, actions, payload) => { addActionHandler('deleteExportedChatInvite', async (global, actions, payload) => {
@ -176,22 +176,22 @@ addActionHandler('deleteExportedChatInvite', async (global, actions, payload) =>
chatId, link, chatId, link,
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
if (!peer) return undefined; if (!peer) return;
const result = await callApi('deleteExportedChatInvite', { const result = await callApi('deleteExportedChatInvite', {
peer, peer,
link, link,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
const managementState = global.management.byChatId[chatId]; const managementState = global.management.byChatId[chatId];
return updateManagement(global, chatId, { setGlobal(updateManagement(global, chatId, {
invites: managementState?.invites?.filter((invite) => invite.link !== link), invites: managementState?.invites?.filter((invite) => invite.link !== link),
revokedInvites: managementState?.revokedInvites?.filter((invite) => invite.link !== link), revokedInvites: managementState?.revokedInvites?.filter((invite) => invite.link !== link),
}); }));
}); });
addActionHandler('deleteRevokedExportedChatInvites', async (global, actions, payload) => { addActionHandler('deleteRevokedExportedChatInvites', async (global, actions, payload) => {
@ -200,20 +200,20 @@ addActionHandler('deleteRevokedExportedChatInvites', async (global, actions, pay
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
const admin = selectUser(global, adminId || global.currentUserId); const admin = selectUser(global, adminId || global.currentUserId);
if (!peer || !admin) return undefined; if (!peer || !admin) return;
const result = await callApi('deleteRevokedExportedChatInvites', { const result = await callApi('deleteRevokedExportedChatInvites', {
peer, peer,
admin, admin,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
return updateManagement(global, chatId, { setGlobal(updateManagement(global, chatId, {
revokedInvites: [], revokedInvites: [],
}); }));
}); });
addActionHandler('loadChatInviteImporters', async (global, actions, payload) => { addActionHandler('loadChatInviteImporters', async (global, actions, payload) => {
@ -222,7 +222,7 @@ addActionHandler('loadChatInviteImporters', async (global, actions, payload) =>
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
const offsetUser = selectUser(global, offsetUserId); const offsetUser = selectUser(global, offsetUserId);
if (!peer || (offsetUserId && !offsetUser)) return undefined; if (!peer || (offsetUserId && !offsetUser)) return;
const result = await callApi('fetchChatInviteImporters', { const result = await callApi('fetchChatInviteImporters', {
peer, peer,
@ -232,21 +232,21 @@ addActionHandler('loadChatInviteImporters', async (global, actions, payload) =>
limit, limit,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
const currentInviteInfo = global.management.byChatId[chatId]?.inviteInfo; const currentInviteInfo = global.management.byChatId[chatId]?.inviteInfo;
if (!currentInviteInfo?.invite || currentInviteInfo.invite.link !== link) { if (!currentInviteInfo?.invite || currentInviteInfo.invite.link !== link) {
return undefined; return;
} }
return updateManagement(global, chatId, { setGlobal(updateManagement(global, chatId, {
inviteInfo: { inviteInfo: {
...currentInviteInfo, ...currentInviteInfo,
importers: result, importers: result,
}, },
}); }));
}); });
addActionHandler('loadChatInviteRequesters', async (global, actions, payload) => { addActionHandler('loadChatInviteRequesters', async (global, actions, payload) => {
@ -255,7 +255,7 @@ addActionHandler('loadChatInviteRequesters', async (global, actions, payload) =>
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
const offsetUser = selectUser(global, offsetUserId); const offsetUser = selectUser(global, offsetUserId);
if (!peer || (offsetUserId && !offsetUser)) return undefined; if (!peer || (offsetUserId && !offsetUser)) return;
const result = await callApi('fetchChatInviteImporters', { const result = await callApi('fetchChatInviteImporters', {
peer, peer,
@ -266,21 +266,21 @@ addActionHandler('loadChatInviteRequesters', async (global, actions, payload) =>
isRequested: true, isRequested: true,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
const currentInviteInfo = global.management.byChatId[chatId]?.inviteInfo; const currentInviteInfo = global.management.byChatId[chatId]?.inviteInfo;
if (!currentInviteInfo?.invite || currentInviteInfo.invite.link !== link) { if (!currentInviteInfo?.invite || currentInviteInfo.invite.link !== link) {
return undefined; return;
} }
return updateManagement(global, chatId, { setGlobal(updateManagement(global, chatId, {
inviteInfo: { inviteInfo: {
...currentInviteInfo, ...currentInviteInfo,
requesters: result, requesters: result,
}, },
}); }));
}); });
addActionHandler('loadChatJoinRequests', async (global, actions, payload) => { addActionHandler('loadChatJoinRequests', async (global, actions, payload) => {
@ -289,7 +289,7 @@ addActionHandler('loadChatJoinRequests', async (global, actions, payload) => {
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
const offsetUser = selectUser(global, offsetUserId); const offsetUser = selectUser(global, offsetUserId);
if (!peer || (offsetUserId && !offsetUser)) return undefined; if (!peer || (offsetUserId && !offsetUser)) return;
const result = await callApi('fetchChatInviteImporters', { const result = await callApi('fetchChatInviteImporters', {
peer, peer,
@ -299,11 +299,11 @@ addActionHandler('loadChatJoinRequests', async (global, actions, payload) => {
isRequested: true, isRequested: true,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
return updateChat(global, chatId, { joinRequests: result }); setGlobal(updateChat(global, chatId, { joinRequests: result }));
}); });
addActionHandler('hideChatJoinRequest', async (global, actions, payload) => { addActionHandler('hideChatJoinRequest', async (global, actions, payload) => {
@ -312,22 +312,22 @@ addActionHandler('hideChatJoinRequest', async (global, actions, payload) => {
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
const user = selectUser(global, userId); const user = selectUser(global, userId);
if (!peer || !user) return undefined; if (!peer || !user) return;
const result = await callApi('hideChatJoinRequest', { const result = await callApi('hideChatJoinRequest', {
peer, peer,
user, user,
isApproved, isApproved,
}); });
if (!result) return undefined; if (!result) return;
global = getGlobal(); global = getGlobal();
const targetChat = selectChat(global, chatId); const targetChat = selectChat(global, chatId);
if (!targetChat) return undefined; if (!targetChat) return;
return updateChat(global, chatId, { setGlobal(updateChat(global, chatId, {
joinRequests: targetChat.joinRequests?.filter((importer) => importer.userId !== userId), joinRequests: targetChat.joinRequests?.filter((importer) => importer.userId !== userId),
}); }));
}); });
addActionHandler('hideAllChatJoinRequests', async (global, actions, payload) => { addActionHandler('hideAllChatJoinRequests', async (global, actions, payload) => {
@ -335,38 +335,38 @@ addActionHandler('hideAllChatJoinRequests', async (global, actions, payload) =>
chatId, isApproved, link, chatId, isApproved, link,
} = payload!; } = payload!;
const peer = selectChat(global, chatId); const peer = selectChat(global, chatId);
if (!peer) return undefined; if (!peer) return;
const result = await callApi('hideAllChatJoinRequests', { const result = await callApi('hideAllChatJoinRequests', {
peer, peer,
isApproved, isApproved,
link, link,
}); });
if (!result) return undefined; if (!result) return;
global = getGlobal(); global = getGlobal();
const targetChat = selectChat(global, chatId); const targetChat = selectChat(global, chatId);
if (!targetChat) return undefined; if (!targetChat) return;
return updateChat(global, chatId, { setGlobal(updateChat(global, chatId, {
joinRequests: [], joinRequests: [],
fullInfo: { fullInfo: {
...targetChat.fullInfo, ...targetChat.fullInfo,
recentRequesterIds: [], recentRequesterIds: [],
requestsPending: 0, requestsPending: 0,
}, },
}); }));
}); });
addActionHandler('hideChatReportPanel', async (global, actions, payload) => { addActionHandler('hideChatReportPanel', async (global, actions, payload) => {
const { chatId } = payload!; const { chatId } = payload!;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) return undefined; if (!chat) return;
const result = await callApi('hideChatReportPanel', chat); const result = await callApi('hideChatReportPanel', chat);
if (!result) return undefined; if (!result) return;
return updateChat(getGlobal(), chatId, { setGlobal(updateChat(getGlobal(), chatId, {
settings: undefined, settings: undefined,
}); }));
}); });

View File

@ -164,23 +164,21 @@ addActionHandler('loadMessage', async (global, actions, payload) => {
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
return undefined; return;
} }
const message = await loadMessage(chat, messageId, replyOriginForId); const message = await loadMessage(chat, messageId, replyOriginForId);
if (message && threadUpdate) { if (message && threadUpdate) {
const { lastMessageId, isDeleting } = threadUpdate; const { lastMessageId, isDeleting } = threadUpdate;
return updateThreadUnreadFromForwardedMessage( setGlobal(updateThreadUnreadFromForwardedMessage(
getGlobal(), getGlobal(),
message, message,
chatId, chatId,
lastMessageId, lastMessageId,
isDeleting, isDeleting,
); ));
} }
return undefined;
}); });
addActionHandler('sendMessage', (global, actions, payload) => { addActionHandler('sendMessage', (global, actions, payload) => {
@ -961,17 +959,17 @@ addActionHandler('loadSeenBy', async (global, actions, payload) => {
const { chatId, messageId } = payload; const { chatId, messageId } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
return undefined; return;
} }
const result = await callApi('fetchSeenBy', { chat, messageId }); const result = await callApi('fetchSeenBy', { chat, messageId });
if (!result) { if (!result) {
return undefined; return;
} }
return updateChatMessage(getGlobal(), chatId, messageId, { setGlobal(updateChatMessage(getGlobal(), chatId, messageId, {
seenByUserIds: result, seenByUserIds: result,
}); }));
}); });
addActionHandler('saveDefaultSendAs', (global, actions, payload) => { addActionHandler('saveDefaultSendAs', (global, actions, payload) => {
@ -996,21 +994,23 @@ addActionHandler('loadSendAs', async (global, actions, payload) => {
const { chatId } = payload; const { chatId } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
return undefined; return;
} }
const result = await callApi('fetchSendAs', { chat }); const result = await callApi('fetchSendAs', { chat });
if (!result) { if (!result) {
return updateChat(getGlobal(), chatId, { setGlobal(updateChat(getGlobal(), chatId, {
sendAsIds: [], sendAsIds: [],
}); }));
return;
} }
global = getGlobal(); global = getGlobal();
global = addUsers(global, buildCollectionByKey(result.users, 'id')); global = addUsers(global, buildCollectionByKey(result.users, 'id'));
global = addChats(global, buildCollectionByKey(result.chats, 'id')); global = addChats(global, buildCollectionByKey(result.chats, 'id'));
global = updateChat(global, chatId, { sendAsIds: result.ids }); global = updateChat(global, chatId, { sendAsIds: result.ids });
return global; setGlobal(global);
}); });
async function loadPinnedMessages(chat: ApiChat) { async function loadPinnedMessages(chat: ApiChat) {
@ -1053,19 +1053,19 @@ addActionHandler('loadSponsoredMessages', async (global, actions, payload) => {
const { chatId } = payload; const { chatId } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
return undefined; return;
} }
const result = await callApi('fetchSponsoredMessages', { chat }); const result = await callApi('fetchSponsoredMessages', { chat });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
global = updateSponsoredMessage(global, chatId, result.messages[0]); global = updateSponsoredMessage(global, chatId, result.messages[0]);
global = addUsers(global, buildCollectionByKey(result.users, 'id')); global = addUsers(global, buildCollectionByKey(result.users, 'id'));
global = addChats(global, buildCollectionByKey(result.chats, 'id')); global = addChats(global, buildCollectionByKey(result.chats, 'id'));
return global; setGlobal(global);
}); });
addActionHandler('viewSponsoredMessage', (global, actions, payload) => { addActionHandler('viewSponsoredMessage', (global, actions, payload) => {

View File

@ -1,4 +1,4 @@
import { addActionHandler, getGlobal } from '../../index'; import { addActionHandler, getGlobal, setGlobal } from '../../index';
import { callApi } from '../../../api/gramjs'; import { callApi } from '../../../api/gramjs';
import * as mediaLoader from '../../../util/mediaLoader'; import * as mediaLoader from '../../../util/mediaLoader';
import { ApiAppConfig, ApiMediaFormat } from '../../../api/types'; import { ApiAppConfig, ApiMediaFormat } from '../../../api/types';
@ -22,7 +22,7 @@ let interactionLocalId = 0;
addActionHandler('loadAvailableReactions', async () => { addActionHandler('loadAvailableReactions', async () => {
const result = await callApi('getAvailableReactions'); const result = await callApi('getAvailableReactions');
if (!result) { if (!result) {
return undefined; return;
} }
// Preload animations // Preload animations
@ -35,10 +35,10 @@ addActionHandler('loadAvailableReactions', async () => {
} }
}); });
return { setGlobal({
...getGlobal(), ...getGlobal(),
availableReactions: result, availableReactions: result,
}; });
}); });
addActionHandler('interactWithAnimatedEmoji', (global, actions, payload) => { addActionHandler('interactWithAnimatedEmoji', (global, actions, payload) => {
@ -198,16 +198,16 @@ addActionHandler('setDefaultReaction', async (global, actions, payload) => {
const result = await callApi('setDefaultReaction', { reaction }); const result = await callApi('setDefaultReaction', { reaction });
if (!result) { if (!result) {
return undefined; return;
} }
return { setGlobal({
...getGlobal(), ...getGlobal(),
appConfig: { appConfig: {
...global.appConfig, ...global.appConfig,
defaultReaction: reaction, defaultReaction: reaction,
} as ApiAppConfig, } as ApiAppConfig,
}; });
}); });
addActionHandler('stopActiveEmojiInteraction', (global, actions, payload) => { addActionHandler('stopActiveEmojiInteraction', (global, actions, payload) => {
@ -224,7 +224,7 @@ addActionHandler('loadReactors', async (global, actions, payload) => {
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
const message = selectChatMessage(global, chatId, messageId); const message = selectChatMessage(global, chatId, messageId);
if (!chat || !message) { if (!chat || !message) {
return undefined; return;
} }
const offset = message.reactors?.nextOffset; const offset = message.reactors?.nextOffset;
@ -236,7 +236,7 @@ addActionHandler('loadReactors', async (global, actions, payload) => {
}); });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
@ -247,7 +247,7 @@ addActionHandler('loadReactors', async (global, actions, payload) => {
const { nextOffset, count, reactions } = result; const { nextOffset, count, reactions } = result;
return updateChatMessage(global, chatId, messageId, { setGlobal(updateChatMessage(global, chatId, messageId, {
reactors: { reactors: {
nextOffset, nextOffset,
count, count,
@ -256,7 +256,7 @@ addActionHandler('loadReactors', async (global, actions, payload) => {
...reactions, ...reactions,
], ],
}, },
}); }));
}); });
addActionHandler('loadMessageReactions', (global, actions, payload) => { addActionHandler('loadMessageReactions', (global, actions, payload) => {

View File

@ -25,7 +25,7 @@ addActionHandler('updateProfile', async (global, actions, payload) => {
const { currentUserId } = global; const { currentUserId } = global;
if (!currentUserId) { if (!currentUserId) {
return undefined; return;
} }
setGlobal({ setGlobal({
@ -69,12 +69,12 @@ addActionHandler('updateProfile', async (global, actions, payload) => {
} }
} }
return { setGlobal({
...getGlobal(), ...getGlobal(),
profileEdit: { profileEdit: {
progress: ProfileEditProgress.Complete, progress: ProfileEditProgress.Complete,
}, },
}; });
}); });
addActionHandler('checkUsername', async (global, actions, payload) => { addActionHandler('checkUsername', async (global, actions, payload) => {
@ -82,7 +82,7 @@ addActionHandler('checkUsername', async (global, actions, payload) => {
// No need to check the username if profile update is already in progress // No need to check the username if profile update is already in progress
if (global.profileEdit && global.profileEdit.progress === ProfileEditProgress.InProgress) { if (global.profileEdit && global.profileEdit.progress === ProfileEditProgress.InProgress) {
return undefined; return;
} }
setGlobal({ setGlobal({
@ -96,29 +96,29 @@ addActionHandler('checkUsername', async (global, actions, payload) => {
const isUsernameAvailable = await callApi('checkUsername', username); const isUsernameAvailable = await callApi('checkUsername', username);
global = getGlobal(); global = getGlobal();
return { setGlobal({
...global, ...global,
profileEdit: { profileEdit: {
...global.profileEdit!, ...global.profileEdit!,
isUsernameAvailable, isUsernameAvailable,
}, },
}; });
}); });
addActionHandler('loadWallpapers', async () => { addActionHandler('loadWallpapers', async () => {
const result = await callApi('fetchWallpapers'); const result = await callApi('fetchWallpapers');
if (!result) { if (!result) {
return undefined; return;
} }
const global = getGlobal(); const global = getGlobal();
return { setGlobal({
...global, ...global,
settings: { settings: {
...global.settings, ...global.settings,
loadedWallpapers: result.wallpapers, loadedWallpapers: result.wallpapers,
}, },
}; });
}); });
addActionHandler('uploadWallpaper', async (global, actions, payload) => { addActionHandler('uploadWallpaper', async (global, actions, payload) => {
@ -146,19 +146,19 @@ addActionHandler('uploadWallpaper', async (global, actions, payload) => {
const result = await callApi('uploadWallpaper', file); const result = await callApi('uploadWallpaper', file);
if (!result) { if (!result) {
return undefined; return;
} }
const { wallpaper } = result; const { wallpaper } = result;
global = getGlobal(); global = getGlobal();
if (!global.settings.loadedWallpapers) { if (!global.settings.loadedWallpapers) {
return undefined; return;
} }
const firstWallpaper = global.settings.loadedWallpapers[0]; const firstWallpaper = global.settings.loadedWallpapers[0];
if (!firstWallpaper || firstWallpaper.slug !== UPLOADING_WALLPAPER_SLUG) { if (!firstWallpaper || firstWallpaper.slug !== UPLOADING_WALLPAPER_SLUG) {
return undefined; return;
} }
const withLocalMedia = { const withLocalMedia = {
@ -169,7 +169,7 @@ addActionHandler('uploadWallpaper', async (global, actions, payload) => {
}, },
}; };
return { setGlobal({
...global, ...global,
settings: { settings: {
...global.settings, ...global.settings,
@ -178,13 +178,13 @@ addActionHandler('uploadWallpaper', async (global, actions, payload) => {
...global.settings.loadedWallpapers.slice(1), ...global.settings.loadedWallpapers.slice(1),
], ],
}, },
}; });
}); });
addActionHandler('loadBlockedContacts', async (global) => { addActionHandler('loadBlockedContacts', async (global) => {
const result = await callApi('fetchBlockedContacts'); const result = await callApi('fetchBlockedContacts');
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
@ -205,7 +205,7 @@ addActionHandler('loadBlockedContacts', async (global) => {
}, },
}; };
return global; setGlobal(global);
}); });
addActionHandler('blockContact', async (global, actions, payload) => { addActionHandler('blockContact', async (global, actions, payload) => {
@ -213,10 +213,10 @@ addActionHandler('blockContact', async (global, actions, payload) => {
const result = await callApi('blockContact', contactId, accessHash); const result = await callApi('blockContact', contactId, accessHash);
if (!result) { if (!result) {
return undefined; return;
} }
return addBlockedContact(getGlobal(), contactId); setGlobal(addBlockedContact(getGlobal(), contactId));
}); });
addActionHandler('unblockContact', async (global, actions, payload) => { addActionHandler('unblockContact', async (global, actions, payload) => {
@ -227,7 +227,7 @@ addActionHandler('unblockContact', async (global, actions, payload) => {
if (isPrivate) { if (isPrivate) {
const user = selectUser(global, contactId); const user = selectUser(global, contactId);
if (!user) { if (!user) {
return undefined; return;
} }
accessHash = user.accessHash; accessHash = user.accessHash;
@ -235,22 +235,22 @@ addActionHandler('unblockContact', async (global, actions, payload) => {
const result = await callApi('unblockContact', contactId, accessHash); const result = await callApi('unblockContact', contactId, accessHash);
if (!result) { if (!result) {
return undefined; return;
} }
return removeBlockedContact(getGlobal(), contactId); setGlobal(removeBlockedContact(getGlobal(), contactId));
}); });
addActionHandler('loadAuthorizations', async () => { addActionHandler('loadAuthorizations', async () => {
const result = await callApi('fetchAuthorizations'); const result = await callApi('fetchAuthorizations');
if (!result) { if (!result) {
return undefined; return;
} }
return { setGlobal({
...getGlobal(), ...getGlobal(),
activeSessions: result, activeSessions: result,
}; });
}); });
addActionHandler('terminateAuthorization', async (global, actions, payload) => { addActionHandler('terminateAuthorization', async (global, actions, payload) => {
@ -258,29 +258,29 @@ addActionHandler('terminateAuthorization', async (global, actions, payload) => {
const result = await callApi('terminateAuthorization', hash); const result = await callApi('terminateAuthorization', hash);
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
return { setGlobal({
...global, ...global,
activeSessions: global.activeSessions.filter((session) => session.hash !== hash), activeSessions: global.activeSessions.filter((session) => session.hash !== hash),
}; });
}); });
addActionHandler('terminateAllAuthorizations', async (global) => { addActionHandler('terminateAllAuthorizations', async (global) => {
const result = await callApi('terminateAllAuthorizations'); const result = await callApi('terminateAllAuthorizations');
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
return { setGlobal({
...global, ...global,
activeSessions: global.activeSessions.filter((session) => session.isCurrent), activeSessions: global.activeSessions.filter((session) => session.isCurrent),
}; });
}); });
addActionHandler('loadNotificationExceptions', async (global) => { addActionHandler('loadNotificationExceptions', async (global) => {
@ -288,10 +288,10 @@ addActionHandler('loadNotificationExceptions', async (global) => {
const result = await callApi('fetchNotificationExceptions', { serverTimeOffset }); const result = await callApi('fetchNotificationExceptions', { serverTimeOffset });
if (!result) { if (!result) {
return undefined; return;
} }
return addNotifyExceptions(getGlobal(), result); setGlobal(addNotifyExceptions(getGlobal(), result));
}); });
addActionHandler('loadNotificationSettings', async (global) => { addActionHandler('loadNotificationSettings', async (global) => {
@ -300,10 +300,10 @@ addActionHandler('loadNotificationSettings', async (global) => {
serverTimeOffset, serverTimeOffset,
}); });
if (!result) { if (!result) {
return undefined; return;
} }
return replaceSettings(getGlobal(), result); setGlobal(replaceSettings(getGlobal(), result));
}); });
addActionHandler('updateNotificationSettings', async (global, actions, payload) => { addActionHandler('updateNotificationSettings', async (global, actions, payload) => {
@ -311,10 +311,10 @@ addActionHandler('updateNotificationSettings', async (global, actions, payload)
const result = await callApi('updateNotificationSettings', peerType, { isSilent, shouldShowPreviews }); const result = await callApi('updateNotificationSettings', peerType, { isSilent, shouldShowPreviews });
if (!result) { if (!result) {
return undefined; return;
} }
return updateNotifySettings(getGlobal(), peerType, isSilent, shouldShowPreviews); setGlobal(updateNotifySettings(getGlobal(), peerType, isSilent, shouldShowPreviews));
}); });
addActionHandler('updateWebNotificationSettings', (global, actions, payload) => { addActionHandler('updateWebNotificationSettings', (global, actions, payload) => {
@ -333,19 +333,19 @@ addActionHandler('updateContactSignUpNotification', async (global, actions, payl
const result = await callApi('updateContactSignUpNotification', isSilent); const result = await callApi('updateContactSignUpNotification', isSilent);
if (!result) { if (!result) {
return undefined; return;
} }
return replaceSettings(getGlobal(), { hasContactJoinedNotifications: !isSilent }); setGlobal(replaceSettings(getGlobal(), { hasContactJoinedNotifications: !isSilent }));
}); });
addActionHandler('loadLanguages', async () => { addActionHandler('loadLanguages', async () => {
const result = await callApi('fetchLanguages'); const result = await callApi('fetchLanguages');
if (!result) { if (!result) {
return undefined; return;
} }
return replaceSettings(getGlobal(), { languages: result }); setGlobal(replaceSettings(getGlobal(), { languages: result }));
}); });
addActionHandler('loadPrivacySettings', async (global) => { addActionHandler('loadPrivacySettings', async (global) => {
@ -362,18 +362,24 @@ addActionHandler('loadPrivacySettings', async (global) => {
if ( if (
!phoneNumberSettings || !lastSeenSettings || !profilePhotoSettings || !forwardsSettings || !chatInviteSettings !phoneNumberSettings || !lastSeenSettings || !profilePhotoSettings || !forwardsSettings || !chatInviteSettings
) { ) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
setGlobal({
global.settings.privacy.phoneNumber = phoneNumberSettings; ...global,
global.settings.privacy.lastSeen = lastSeenSettings; settings: {
global.settings.privacy.profilePhoto = profilePhotoSettings; ...global.settings,
global.settings.privacy.forwards = forwardsSettings; privacy: {
global.settings.privacy.chatInvite = chatInviteSettings; ...global.settings.privacy,
phoneNumber: phoneNumberSettings,
return global; lastSeen: lastSeenSettings,
profilePhoto: profilePhotoSettings,
forwards: forwardsSettings,
chatInvite: chatInviteSettings,
},
},
});
}); });
addActionHandler('setPrivacyVisibility', async (global, actions, payload) => { addActionHandler('setPrivacyVisibility', async (global, actions, payload) => {
@ -384,7 +390,7 @@ addActionHandler('setPrivacyVisibility', async (global, actions, payload) => {
} = global.settings; } = global.settings;
if (!settings) { if (!settings) {
return undefined; return;
} }
const rules = buildInputPrivacyRules(global, { const rules = buildInputPrivacyRules(global, {
@ -395,12 +401,12 @@ addActionHandler('setPrivacyVisibility', async (global, actions, payload) => {
const result = await callApi('setPrivacySettings', privacyKey, rules); const result = await callApi('setPrivacySettings', privacyKey, rules);
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
return { setGlobal({
...global, ...global,
settings: { settings: {
...global.settings, ...global.settings,
@ -409,7 +415,7 @@ addActionHandler('setPrivacyVisibility', async (global, actions, payload) => {
[privacyKey]: result, [privacyKey]: result,
}, },
}, },
}; });
}); });
addActionHandler('setPrivacySettings', async (global, actions, payload) => { addActionHandler('setPrivacySettings', async (global, actions, payload) => {
@ -419,7 +425,7 @@ addActionHandler('setPrivacySettings', async (global, actions, payload) => {
} = global.settings; } = global.settings;
if (!settings) { if (!settings) {
return undefined; return;
} }
const rules = buildInputPrivacyRules(global, { const rules = buildInputPrivacyRules(global, {
@ -430,12 +436,12 @@ addActionHandler('setPrivacySettings', async (global, actions, payload) => {
const result = await callApi('setPrivacySettings', privacyKey, rules); const result = await callApi('setPrivacySettings', privacyKey, rules);
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
return { setGlobal({
...global, ...global,
settings: { settings: {
...global.settings, ...global.settings,
@ -444,7 +450,7 @@ addActionHandler('setPrivacySettings', async (global, actions, payload) => {
[privacyKey]: result, [privacyKey]: result,
}, },
}, },
}; });
}); });
function buildInputPrivacyRules(global: GlobalState, { function buildInputPrivacyRules(global: GlobalState, {
@ -521,9 +527,9 @@ addActionHandler('updateIsOnline', (global, actions, payload) => {
addActionHandler('loadContentSettings', async () => { addActionHandler('loadContentSettings', async () => {
const result = await callApi('fetchContentSettings'); const result = await callApi('fetchContentSettings');
if (!result) return undefined; if (!result) return;
return replaceSettings(getGlobal(), result); setGlobal(replaceSettings(getGlobal(), result));
}); });
addActionHandler('updateContentSettings', async (global, actions, payload) => { addActionHandler('updateContentSettings', async (global, actions, payload) => {
@ -531,10 +537,8 @@ addActionHandler('updateContentSettings', async (global, actions, payload) => {
const result = await callApi('updateContentSettings', payload); const result = await callApi('updateContentSettings', payload);
if (!result) { if (!result) {
return replaceSettings(getGlobal(), { isSensitiveEnabled: !payload }); setGlobal(replaceSettings(getGlobal(), { isSensitiveEnabled: !payload }));
} }
return undefined;
}); });
addActionHandler('loadCountryList', async (global, actions, payload = {}) => { addActionHandler('loadCountryList', async (global, actions, payload = {}) => {
@ -542,12 +546,12 @@ addActionHandler('loadCountryList', async (global, actions, payload = {}) => {
if (!langCode) langCode = global.settings.byKey.language; if (!langCode) langCode = global.settings.byKey.language;
const countryList = await callApi('fetchCountryList', { langCode }); const countryList = await callApi('fetchCountryList', { langCode });
if (!countryList) return undefined; if (!countryList) return;
return { setGlobal({
...getGlobal(), ...getGlobal(),
countryList, countryList,
}; });
}); });
addActionHandler('ensureTimeFormat', async (global, actions) => { addActionHandler('ensureTimeFormat', async (global, actions) => {
@ -571,10 +575,10 @@ addActionHandler('ensureTimeFormat', async (global, actions) => {
addActionHandler('loadAppConfig', async () => { addActionHandler('loadAppConfig', async () => {
const appConfig = await callApi('fetchAppConfig'); const appConfig = await callApi('fetchAppConfig');
if (!appConfig) return undefined; if (!appConfig) return;
return { setGlobal({
...getGlobal(), ...getGlobal(),
appConfig, appConfig,
}; });
}); });

View File

@ -1,4 +1,4 @@
import { addActionHandler, getGlobal } from '../../index'; import { addActionHandler, getGlobal, setGlobal } from '../../index';
import { ApiChannelStatistics } from '../../../api/types'; import { ApiChannelStatistics } from '../../../api/types';
import { callApi } from '../../../api/gramjs'; import { callApi } from '../../../api/gramjs';
@ -9,12 +9,12 @@ addActionHandler('loadStatistics', async (global, actions, payload) => {
const { chatId, isGroup } = payload; const { chatId, isGroup } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat?.fullInfo) { if (!chat?.fullInfo) {
return undefined; return;
} }
const result = await callApi(isGroup ? 'fetchGroupStatistics' : 'fetchChannelStatistics', { chat }); const result = await callApi(isGroup ? 'fetchGroupStatistics' : 'fetchChannelStatistics', { chat });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
@ -26,9 +26,7 @@ addActionHandler('loadStatistics', async (global, actions, payload) => {
.map((message) => ({ ...message, ...messages[message.msgId] })); .map((message) => ({ ...message, ...messages[message.msgId] }));
} }
global = updateStatistics(global, chatId, result); setGlobal(updateStatistics(global, chatId, result));
return global;
}); });
addActionHandler('loadStatisticsAsyncGraph', async (global, actions, payload) => { addActionHandler('loadStatisticsAsyncGraph', async (global, actions, payload) => {
@ -37,15 +35,15 @@ addActionHandler('loadStatisticsAsyncGraph', async (global, actions, payload) =>
} = payload; } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat?.fullInfo) { if (!chat?.fullInfo) {
return undefined; return;
} }
const dcId = chat.fullInfo!.statisticsDcId; const dcId = chat.fullInfo!.statisticsDcId;
const result = await callApi('fetchStatisticsAsyncGraph', { token, dcId, isPercentage }); const result = await callApi('fetchStatisticsAsyncGraph', { token, dcId, isPercentage });
if (!result) { if (!result) {
return undefined; return;
} }
return updateStatisticsGraph(getGlobal(), chatId, name, result); setGlobal(updateStatisticsGraph(getGlobal(), chatId, name, result));
}); });

View File

@ -60,12 +60,12 @@ addActionHandler('loadGreetingStickers', async (global) => {
const greeting = await callApi('fetchStickersForEmoji', { emoji: '👋⭐️', hash }); const greeting = await callApi('fetchStickersForEmoji', { emoji: '👋⭐️', hash });
if (!greeting) { if (!greeting) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
return { setGlobal({
...global, ...global,
stickers: { stickers: {
...global.stickers, ...global.stickers,
@ -74,7 +74,7 @@ addActionHandler('loadGreetingStickers', async (global) => {
stickers: greeting.stickers.filter((sticker) => sticker.emoji === '👋'), stickers: greeting.stickers.filter((sticker) => sticker.emoji === '👋'),
}, },
}, },
}; });
}); });
addActionHandler('loadFeaturedStickers', (global) => { addActionHandler('loadFeaturedStickers', (global) => {
@ -112,14 +112,14 @@ addActionHandler('saveGif', async (global, actions, payload) => {
const { gif, shouldUnsave } = payload!; const { gif, shouldUnsave } = payload!;
const result = await callApi('saveGif', { gif, shouldUnsave }); const result = await callApi('saveGif', { gif, shouldUnsave });
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
const gifs = global.gifs.saved.gifs?.filter(({ id }) => id !== gif.id) || []; const gifs = global.gifs.saved.gifs?.filter(({ id }) => id !== gif.id) || [];
const newGifs = shouldUnsave ? gifs : [gif, ...gifs]; const newGifs = shouldUnsave ? gifs : [gif, ...gifs];
return { setGlobal({
...global, ...global,
gifs: { gifs: {
...global.gifs, ...global.gifs,
@ -128,7 +128,7 @@ addActionHandler('saveGif', async (global, actions, payload) => {
gifs: newGifs, gifs: newGifs,
}, },
}, },
}; });
}); });
addActionHandler('faveSticker', (global, actions, payload) => { addActionHandler('faveSticker', (global, actions, payload) => {
@ -164,7 +164,7 @@ addActionHandler('loadEmojiKeywords', async (global, actions, payload: { languag
let currentEmojiKeywords = global.emojiKeywords[language]; let currentEmojiKeywords = global.emojiKeywords[language];
if (currentEmojiKeywords?.isLoading) { if (currentEmojiKeywords?.isLoading) {
return undefined; return;
} }
setGlobal({ setGlobal({
@ -187,7 +187,7 @@ addActionHandler('loadEmojiKeywords', async (global, actions, payload: { languag
currentEmojiKeywords = global.emojiKeywords[language]; currentEmojiKeywords = global.emojiKeywords[language];
if (!emojiKeywords) { if (!emojiKeywords) {
return { setGlobal({
...global, ...global,
emojiKeywords: { emojiKeywords: {
...global.emojiKeywords, ...global.emojiKeywords,
@ -196,10 +196,12 @@ addActionHandler('loadEmojiKeywords', async (global, actions, payload: { languag
isLoading: false, isLoading: false,
}, },
}, },
}; });
return;
} }
return { setGlobal({
...global, ...global,
emojiKeywords: { emojiKeywords: {
...global.emojiKeywords, ...global.emojiKeywords,
@ -212,7 +214,7 @@ addActionHandler('loadEmojiKeywords', async (global, actions, payload: { languag
}, },
}, },
}, },
}; });
}); });
async function loadStickerSets(hash?: string) { async function loadStickerSets(hash?: string) {

View File

@ -6,13 +6,13 @@ import { replaceSettings, updateTwoFaSettings } from '../../reducers';
addActionHandler('loadPasswordInfo', async (global) => { addActionHandler('loadPasswordInfo', async (global) => {
const result = await callApi('getPasswordInfo'); const result = await callApi('getPasswordInfo');
if (!result) { if (!result) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
global = replaceSettings(global, { hasPassword: result.hasPassword }); global = replaceSettings(global, { hasPassword: result.hasPassword });
global = updateTwoFaSettings(global, { hint: result.hint }); global = updateTwoFaSettings(global, { hint: result.hint });
return global; setGlobal(global);
}); });
addActionHandler('checkPassword', async (global, actions, payload) => { addActionHandler('checkPassword', async (global, actions, payload) => {

View File

@ -37,25 +37,23 @@ addActionHandler('loadUser', async (global, actions, payload) => {
const { userId } = payload!; const { userId } = payload!;
const user = selectUser(global, userId); const user = selectUser(global, userId);
if (!user) { if (!user) {
return undefined; return;
} }
const result = await callApi('fetchUsers', { users: [user] }); const result = await callApi('fetchUsers', { users: [user] });
if (!result) { if (!result) {
return undefined; return;
} }
const { users, userStatusesById } = result; const { users, userStatusesById } = result;
global = getGlobal(); global = getGlobal();
global = updateUsers(global, buildCollectionByKey(users, 'id')); global = updateUsers(global, buildCollectionByKey(users, 'id'));
global = replaceUserStatuses(global, { global = replaceUserStatuses(global, {
...global.users.statusesById, ...global.users.statusesById,
...userStatusesById, ...userStatusesById,
}); });
setGlobal(global);
return global;
}); });
addActionHandler('loadTopUsers', (global) => { addActionHandler('loadTopUsers', (global) => {
@ -78,13 +76,13 @@ addActionHandler('loadCommonChats', async (global) => {
const { chatId } = selectCurrentMessageList(global) || {}; const { chatId } = selectCurrentMessageList(global) || {};
const user = chatId ? selectUser(global, chatId) : undefined; const user = chatId ? selectUser(global, chatId) : undefined;
if (!user || isUserBot(user) || user.commonChats?.isFullyLoaded) { if (!user || isUserBot(user) || user.commonChats?.isFullyLoaded) {
return undefined; return;
} }
const maxId = user.commonChats?.maxId; const maxId = user.commonChats?.maxId;
const result = await callApi('fetchCommonChats', user.id, user.accessHash!, maxId); const result = await callApi('fetchCommonChats', user.id, user.accessHash!, maxId);
if (!result) { if (!result) {
return undefined; return;
} }
const { chats, chatIds, isFullyLoaded } = result; const { chats, chatIds, isFullyLoaded } = result;
@ -101,7 +99,7 @@ addActionHandler('loadCommonChats', async (global) => {
}, },
}); });
return global; setGlobal(global);
}); });
addActionHandler('updateContact', (global, actions, payload) => { addActionHandler('updateContact', (global, actions, payload) => {
@ -235,12 +233,12 @@ addActionHandler('loadProfilePhotos', async (global, actions, payload) => {
const user = isPrivate ? selectUser(global, profileId) : undefined; const user = isPrivate ? selectUser(global, profileId) : undefined;
const chat = !isPrivate ? selectChat(global, profileId) : undefined; const chat = !isPrivate ? selectChat(global, profileId) : undefined;
if (!user && !chat) { if (!user && !chat) {
return undefined; return;
} }
const result = await callApi('fetchProfilePhotos', user, chat); const result = await callApi('fetchProfilePhotos', user, chat);
if (!result || !result.photos) { if (!result || !result.photos) {
return undefined; return;
} }
global = getGlobal(); global = getGlobal();
@ -252,7 +250,7 @@ addActionHandler('loadProfilePhotos', async (global, actions, payload) => {
global = updateChat(global, profileId, { photos: result.photos }); global = updateChat(global, profileId, { photos: result.photos });
} }
return global; setGlobal(global);
}); });
addActionHandler('setUserSearchQuery', (global, actions, payload) => { addActionHandler('setUserSearchQuery', (global, actions, payload) => {
@ -269,18 +267,17 @@ addActionHandler('importContact', async (global, actions, payload) => {
const { phoneNumber: phone, firstName, lastName } = payload!; const { phoneNumber: phone, firstName, lastName } = payload!;
const result = await callApi('importContact', { phone, firstName, lastName }); const result = await callApi('importContact', { phone, firstName, lastName });
if (!result) {
actions.showNotification({
message: langProvider.getTranslation('Contacts.PhoneNumber.NotRegistred'),
});
if (result) { return;
actions.openChat({ id: result });
return closeNewContactDialog(getGlobal());
} }
actions.showNotification({ actions.openChat({ id: result });
message: langProvider.getTranslation('Contacts.PhoneNumber.NotRegistred'),
});
return undefined; setGlobal(closeNewContactDialog(getGlobal()));
}); });
addActionHandler('reportSpam', (global, actions, payload) => { addActionHandler('reportSpam', (global, actions, payload) => {

View File

@ -203,11 +203,11 @@ addActionHandler('joinVoiceChatByLink', async (global, actions, payload) => {
}); });
addActionHandler('joinGroupCall', async (global, actions, payload) => { addActionHandler('joinGroupCall', async (global, actions, payload) => {
if (!ARE_CALLS_SUPPORTED) return undefined; if (!ARE_CALLS_SUPPORTED) return;
if (global.phoneCall) { if (global.phoneCall) {
actions.toggleGroupCallPanel(); actions.toggleGroupCallPanel();
return undefined; return;
} }
const { const {
@ -222,19 +222,19 @@ addActionHandler('joinGroupCall', async (global, actions, payload) => {
if (groupCall?.id === activeGroupCallId) { if (groupCall?.id === activeGroupCallId) {
actions.toggleGroupCallPanel(); actions.toggleGroupCallPanel();
return undefined; return;
} }
if (activeGroupCallId) { if (activeGroupCallId) {
actions.leaveGroupCall({ actions.leaveGroupCall({
rejoin: payload, rejoin: payload,
}); });
return undefined; return;
} }
if (groupCall && activeGroupCallId === groupCall.id) { if (groupCall && activeGroupCallId === groupCall.id) {
actions.toggleGroupCallPanel(); actions.toggleGroupCallPanel();
return undefined; return;
} }
if (!groupCall && (!id || !accessHash)) { if (!groupCall && (!id || !accessHash)) {
@ -244,7 +244,7 @@ addActionHandler('joinGroupCall', async (global, actions, payload) => {
}); });
} }
if (!groupCall) return undefined; if (!groupCall) return;
global = getGlobal(); global = getGlobal();
global = updateGroupCall( global = updateGroupCall(
@ -265,7 +265,7 @@ addActionHandler('joinGroupCall', async (global, actions, payload) => {
}, },
isCallPanelVisible: false, isCallPanelVisible: false,
}; };
return global; setGlobal(global);
}); });
addActionHandler('playGroupCallSound', (global, actions, payload) => { addActionHandler('playGroupCallSound', (global, actions, payload) => {

View File

@ -29,7 +29,7 @@ type ActionHandler = (
global: GlobalState, global: GlobalState,
actions: Actions, actions: Actions,
payload: any, payload: any,
) => GlobalState | void | Promise<GlobalState | void>; ) => GlobalState | void | Promise<void>;
type MapStateToProps<OwnProps = undefined> = ((global: GlobalState, ownProps: OwnProps) => AnyLiteral); type MapStateToProps<OwnProps = undefined> = ((global: GlobalState, ownProps: OwnProps) => AnyLiteral);
@ -81,19 +81,11 @@ export function getActions() {
function handleAction(name: string, payload?: ActionPayload, options?: ActionOptions) { function handleAction(name: string, payload?: ActionPayload, options?: ActionOptions) {
actionHandlers[name]?.forEach((handler) => { actionHandlers[name]?.forEach((handler) => {
const response = handler(currentGlobal, actions, payload); const response = handler(currentGlobal, actions, payload);
if (!response) { if (!response || typeof response.then === 'function') {
return; return;
} }
if (typeof response.then === 'function') { setGlobal(response, options);
response.then((newGlobal: GlobalState | void) => {
if (newGlobal) {
setGlobal(newGlobal, options);
}
});
} else {
setGlobal(response, options);
}
}); });
} }
@ -254,7 +246,7 @@ export function typify<ProjectGlobalState, ActionPayloads, NonTypedActionNames e
global: ProjectGlobalState, global: ProjectGlobalState,
actions: ProjectActions, actions: ProjectActions,
payload: ProjectActionTypes[ActionName], payload: ProjectActionTypes[ActionName],
) => ProjectGlobalState | void | Promise<ProjectGlobalState | void>; ) => ProjectGlobalState | void | Promise<void>;
}; };
return { return {