2021-06-19 11:20:55 +03:00

203 lines
5.2 KiB
TypeScript

import {
addReducer, getDispatch, getGlobal, setGlobal,
} from '../../../lib/teact/teactn';
import { ApiUser } from '../../../api/types';
import { ManagementProgress } from '../../../types';
import { debounce } from '../../../util/schedulers';
import { buildCollectionByKey } from '../../../util/iteratees';
import { isChatPrivate } from '../../helpers';
import { callApi } from '../../../api/gramjs';
import { selectChat, selectUser } from '../../selectors';
import {
addChats, addUsers, updateChat, updateManagementProgress, updateUser, updateUsers,
} from '../../reducers';
const runDebouncedForFetchFullUser = debounce((cb) => cb(), 500, false, true);
const TOP_PEERS_REQUEST_COOLDOWN = 60; // 1 min
addReducer('loadFullUser', (global, actions, payload) => {
const { userId } = payload!;
const user = selectUser(global, userId);
if (!user) {
return;
}
const { id, accessHash } = user;
runDebouncedForFetchFullUser(() => callApi('fetchFullUser', { id, accessHash }));
});
addReducer('loadUser', (global, actions, payload) => {
const { userId } = payload!;
const user = selectUser(global, userId);
if (!user) {
return;
}
(async () => {
const updatedUsers = await callApi('fetchUsers', { users: [user] });
if (!updatedUsers) {
return;
}
global = getGlobal();
global = updateUsers(global, buildCollectionByKey(updatedUsers, 'id'));
setGlobal(global);
})();
});
addReducer('loadTopUsers', (global) => {
const {
serverTimeOffset,
topPeers: {
hash, lastRequestedAt,
},
} = global;
if (!lastRequestedAt || Date.now() / 1000 + serverTimeOffset - lastRequestedAt > TOP_PEERS_REQUEST_COOLDOWN) {
void loadTopUsers(hash);
}
});
addReducer('loadContactList', (global) => {
const { hash } = global.contactList || {};
void loadContactList(hash);
});
addReducer('loadCurrentUser', () => {
void callApi('fetchCurrentUser');
});
addReducer('updateContact', (global, actions, payload) => {
const {
userId, isMuted, firstName, lastName,
} = payload!;
void updateContact(userId, isMuted, firstName, lastName);
});
addReducer('deleteUser', (global, actions, payload) => {
const { userId } = payload!;
void deleteUser(userId);
});
async function loadTopUsers(usersHash?: number) {
const result = await callApi('fetchTopUsers', { hash: usersHash });
if (!result) {
return;
}
const { hash, ids, users } = result;
let global = getGlobal();
global = addUsers(global, buildCollectionByKey(users, 'id'));
global = {
...global,
topPeers: {
...global.topPeers,
hash,
userIds: ids,
lastRequestedAt: Date.now() / 1000 + global.serverTimeOffset,
},
};
setGlobal(global);
}
async function loadContactList(hash?: number) {
const contactList = await callApi('fetchContactList', { hash });
if (!contactList) {
return;
}
let global = addUsers(getGlobal(), buildCollectionByKey(contactList.users, 'id'));
global = addChats(global, buildCollectionByKey(contactList.chats, 'id'));
// Sort contact list by Last Name (or First Name), with latin names being placed first
const getCompareString = (user: ApiUser) => (user.lastName || user.firstName || '');
const collator = new Intl.Collator('en-US');
const sortedUsers = contactList.users.sort((a, b) => (
collator.compare(getCompareString(a), getCompareString(b))
)).filter((user) => !user.isSelf);
setGlobal({
...global,
contactList: {
hash: contactList.hash,
userIds: sortedUsers.map((user) => user.id),
},
});
}
async function updateContact(
userId: number,
isMuted: boolean,
firstName: string,
lastName?: string,
) {
const global = getGlobal();
const user = selectUser(global, userId);
if (!user) {
return;
}
getDispatch().updateChatMutedState({ chatId: userId, isMuted });
setGlobal(updateManagementProgress(getGlobal(), ManagementProgress.InProgress));
const result = await callApi('updateContact', { phone: user.phoneNumber, firstName, lastName });
if (result) {
setGlobal(updateUser(
getGlobal(),
user.id,
{
firstName,
lastName,
},
));
}
setGlobal(updateManagementProgress(getGlobal(), ManagementProgress.Complete));
}
async function deleteUser(userId: number) {
const global = getGlobal();
const user = selectUser(global, userId);
if (!user) {
return;
}
const { id, accessHash } = user;
await callApi('deleteUser', { id, accessHash });
}
addReducer('loadProfilePhotos', (global, actions, payload) => {
const { profileId } = payload!;
const isPrivate = isChatPrivate(profileId);
const user = isPrivate ? selectUser(global, profileId) : undefined;
const chat = !isPrivate ? selectChat(global, profileId) : undefined;
(async () => {
const result = await callApi('fetchProfilePhotos', user, chat);
if (!result || !result.photos) {
return;
}
let newGlobal = getGlobal();
if (isPrivate) {
newGlobal = updateUser(newGlobal, profileId, { photos: result.photos });
} else {
newGlobal = addUsers(newGlobal, buildCollectionByKey(result.users!, 'id'));
newGlobal = updateChat(newGlobal, profileId, { photos: result.photos });
}
setGlobal(newGlobal);
})();
});