[Refactoring] Optimize fetching notify exceptions (#1277)

This commit is contained in:
Alexander Zinchuk 2021-07-15 21:50:29 +03:00
parent ed0eda57f1
commit e374122d85
10 changed files with 89 additions and 36 deletions

View File

@ -4,6 +4,7 @@ import { ApiSession, ApiWallpaper } from '../../types';
import { ApiPrivacySettings, ApiPrivacyKey, PrivacyVisibility } from '../../../types'; import { ApiPrivacySettings, ApiPrivacyKey, PrivacyVisibility } from '../../../types';
import { buildApiDocument } from './messages'; import { buildApiDocument } from './messages';
import { getApiChatIdFromMtpPeer } from './chats';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
export function buildApiWallpaper(wallpaper: GramJs.TypeWallPaper): ApiWallpaper | undefined { export function buildApiWallpaper(wallpaper: GramJs.TypeWallPaper): ApiWallpaper | undefined {
@ -96,3 +97,18 @@ export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySe
blockChatIds: blockChatIds || [], blockChatIds: blockChatIds || [],
}; };
} }
export function buildApiNotifyException(
notifySettings: GramJs.TypePeerNotifySettings, peer: GramJs.TypePeer, serverTimeOffset: number,
) {
const {
silent, muteUntil, showPreviews, sound,
} = notifySettings;
return {
chatId: getApiChatIdFromMtpPeer(peer),
isMuted: silent || (typeof muteUntil === 'number' && Date.now() + serverTimeOffset * 1000 < muteUntil * 1000),
...(sound === '' && { isSilent: true }),
...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }),
};
}

View File

@ -414,7 +414,7 @@ export async function updateChatMutedState({
onUpdate({ onUpdate({
'@type': 'updateNotifyExceptions', '@type': 'updateNotifyExceptions',
id: chat.id, chatId: chat.id,
isMuted, isMuted,
}); });

View File

@ -2,12 +2,14 @@ import BigInt from 'big-integer';
import { Api as GramJs } from '../../../lib/gramjs'; import { Api as GramJs } from '../../../lib/gramjs';
import { import {
ApiChat, ApiLangString, ApiLanguage, ApiUser, ApiWallpaper, ApiChat, ApiLangString, ApiLanguage, ApiNotifyException, ApiUser, ApiWallpaper,
} from '../../types'; } from '../../types';
import { ApiPrivacyKey, IInputPrivacyRules } from '../../../types'; import { ApiPrivacyKey, IInputPrivacyRules } from '../../../types';
import { BLOCKED_LIST_LIMIT, DEFAULT_LANG_PACK } from '../../../config'; import { BLOCKED_LIST_LIMIT, DEFAULT_LANG_PACK } from '../../../config';
import { buildApiWallpaper, buildApiSession, buildPrivacyRules } from '../apiBuilders/misc'; import {
buildApiWallpaper, buildApiSession, buildPrivacyRules, buildApiNotifyException,
} from '../apiBuilders/misc';
import { buildApiUser } from '../apiBuilders/users'; import { buildApiUser } from '../apiBuilders/users';
import { buildApiChatFromPreview, getApiChatIdFromMtpPeer } from '../apiBuilders/chats'; import { buildApiChatFromPreview, getApiChatIdFromMtpPeer } from '../apiBuilders/chats';
@ -156,12 +158,26 @@ export function terminateAllAuthorizations() {
return invokeRequest(new GramJs.auth.ResetAuthorizations()); return invokeRequest(new GramJs.auth.ResetAuthorizations());
} }
export async function fetchNotificationExceptions() { export async function fetchNotificationExceptions({
const result = await invokeRequest(new GramJs.account.GetNotifyExceptions({ compareSound: true }), true); serverTimeOffset,
}: { serverTimeOffset: number }) {
const result = await invokeRequest(new GramJs.account.GetNotifyExceptions({ compareSound: true }));
if (result instanceof GramJs.Updates || result instanceof GramJs.UpdatesCombined) { if (!(result instanceof GramJs.Updates || result instanceof GramJs.UpdatesCombined)) {
updateLocalDb(result); return undefined;
} }
updateLocalDb(result);
return result.updates.reduce((acc, update) => {
if (!(update instanceof GramJs.UpdateNotifySettings && update.peer instanceof GramJs.NotifyPeer)) {
return acc;
}
acc.push(buildApiNotifyException(update.notifySettings, update.peer.peer, serverTimeOffset));
return acc;
}, [] as ApiNotifyException[]);
} }
export async function fetchNotificationSettings({ export async function fetchNotificationSettings({

View File

@ -33,7 +33,7 @@ import localDb from './localDb';
import { omitVirtualClassFields } from './apiBuilders/helpers'; import { omitVirtualClassFields } from './apiBuilders/helpers';
import { DEBUG } from '../../config'; import { DEBUG } from '../../config';
import { addMessageToLocalDb, addPhotoToLocalDb, resolveMessageApiChatId } from './helpers'; import { addMessageToLocalDb, addPhotoToLocalDb, resolveMessageApiChatId } from './helpers';
import { buildPrivacyKey, buildPrivacyRules } from './apiBuilders/misc'; import { buildApiNotifyException, buildPrivacyKey, buildPrivacyRules } from './apiBuilders/misc';
import { buildApiPhoto } from './apiBuilders/common'; import { buildApiPhoto } from './apiBuilders/common';
type Update = ( type Update = (
@ -548,19 +548,9 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
update instanceof GramJs.UpdateNotifySettings update instanceof GramJs.UpdateNotifySettings
&& update.peer instanceof GramJs.NotifyPeer && update.peer instanceof GramJs.NotifyPeer
) { ) {
const {
silent, muteUntil, showPreviews, sound,
} = update.notifySettings;
const isMuted = silent
|| (typeof muteUntil === 'number' && Date.now() + serverTimeOffset * 1000 < muteUntil * 1000);
onUpdate({ onUpdate({
'@type': 'updateNotifyExceptions', '@type': 'updateNotifyExceptions',
id: getApiChatIdFromMtpPeer(update.peer.peer), ...buildApiNotifyException(update.notifySettings, update.peer.peer, serverTimeOffset),
isMuted,
...(sound === '' && { isSilent: true }),
...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }),
}); });
} else if ( } else if (
update instanceof GramJs.UpdateUserTyping update instanceof GramJs.UpdateUserTyping

View File

@ -60,3 +60,10 @@ export interface ApiSessionData {
keys: Record<number, string | number[]>; keys: Record<number, string | number[]>;
hashes: Record<number, string | number[]>; hashes: Record<number, string | number[]>;
} }
export type ApiNotifyException = {
chatId: number;
isMuted: boolean;
isSilent?: boolean;
shouldShowPreviews?: boolean;
};

View File

@ -9,7 +9,7 @@ import {
ApiFormattedText, ApiMessage, ApiPhoto, ApiPoll, ApiStickerSet, ApiThreadInfo, ApiFormattedText, ApiMessage, ApiPhoto, ApiPoll, ApiStickerSet, ApiThreadInfo,
} from './messages'; } from './messages';
import { ApiUser, ApiUserFullInfo, ApiUserStatus } from './users'; import { ApiUser, ApiUserFullInfo, ApiUserStatus } from './users';
import { ApiSessionData } from './misc'; import { ApiNotifyException, ApiSessionData } from './misc';
export type ApiUpdateReady = { export type ApiUpdateReady = {
'@type': 'updateApiReady'; '@type': 'updateApiReady';
@ -358,11 +358,7 @@ export type ApiUpdateNotifySettings = {
export type ApiUpdateNotifyExceptions = { export type ApiUpdateNotifyExceptions = {
'@type': 'updateNotifyExceptions'; '@type': 'updateNotifyExceptions';
id: number; } & ApiNotifyException;
isMuted: boolean;
isSilent?: boolean;
shouldShowPreviews?: boolean;
};
export type updateTwoFaStateWaitCode = { export type updateTwoFaStateWaitCode = {
'@type': 'updateTwoFaStateWaitCode'; '@type': 'updateTwoFaStateWaitCode';

View File

@ -11,6 +11,7 @@ import { buildCollectionByKey } from '../../../util/iteratees';
import { selectUser } from '../../selectors'; import { selectUser } from '../../selectors';
import { import {
addUsers, addBlockedContact, updateChats, updateUser, removeBlockedContact, replaceSettings, updateNotifySettings, addUsers, addBlockedContact, updateChats, updateUser, removeBlockedContact, replaceSettings, updateNotifySettings,
addNotifyExceptions,
} from '../../reducers'; } from '../../reducers';
import { isChatPrivate } from '../../helpers'; import { isChatPrivate } from '../../helpers';
@ -304,8 +305,17 @@ addReducer('terminateAllAuthorizations', () => {
})(); })();
}); });
addReducer('loadNotificationExceptions', () => { addReducer('loadNotificationExceptions', (global) => {
callApi('fetchNotificationExceptions'); const { serverTimeOffset } = global;
(async () => {
const result = await callApi('fetchNotificationExceptions', { serverTimeOffset });
if (!result) {
return;
}
setGlobal(addNotifyExceptions(getGlobal(), result));
})();
}); });
addReducer('loadNotificationSettings', (global) => { addReducer('loadNotificationSettings', (global) => {

View File

@ -12,15 +12,15 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate): GlobalState | unde
case 'updateNotifyExceptions': { case 'updateNotifyExceptions': {
const { const {
id, isMuted, isSilent, shouldShowPreviews, chatId, isMuted, isSilent, shouldShowPreviews,
} = update; } = update;
const chat = global.chats.byId[id]; const chat = global.chats.byId[chatId];
if (chat) { if (chat) {
global = updateChat(global, id, { isMuted }); global = updateChat(global, chatId, { isMuted });
} }
setGlobal(addNotifyException(global, id, { isMuted, isSilent, shouldShowPreviews })); setGlobal(addNotifyException(global, chatId, { isMuted, isSilent, shouldShowPreviews }));
break; break;
} }
} }

View File

@ -2,6 +2,7 @@ import { GlobalState } from '../../global/types';
import { import {
ISettings, IThemeSettings, ThemeKey, NotifyException, ISettings, IThemeSettings, ThemeKey, NotifyException,
} from '../../types'; } from '../../types';
import { ApiNotifyException } from '../../api/types';
export function replaceSettings(global: GlobalState, newSettings?: Partial<ISettings>): GlobalState { export function replaceSettings(global: GlobalState, newSettings?: Partial<ISettings>): GlobalState {
return { return {
@ -34,6 +35,17 @@ export function replaceThemeSettings(
}; };
} }
export function addNotifyExceptions(
global: GlobalState, notifyExceptions: ApiNotifyException[],
): GlobalState {
notifyExceptions.forEach((notifyException) => {
const { chatId, ...exceptionData } = notifyException;
global = addNotifyException(global, chatId, exceptionData);
});
return global;
}
export function addNotifyException( export function addNotifyException(
global: GlobalState, id: number, notifyException: NotifyException, global: GlobalState, id: number, notifyException: NotifyException,
): GlobalState { ): GlobalState {

View File

@ -14,7 +14,7 @@ import {
selectIsChatMuted, selectIsChatMuted,
} from '../modules/helpers'; } from '../modules/helpers';
import { getTranslation } from './langProvider'; import { getTranslation } from './langProvider';
import { replaceSettings } from '../modules/reducers'; import { addNotifyExceptions, replaceSettings } from '../modules/reducers';
import { import {
selectChatMessage, selectNotifyExceptions, selectNotifySettings, selectUser, selectChatMessage, selectNotifyExceptions, selectNotifySettings, selectUser,
} from '../modules/selectors'; } from '../modules/selectors';
@ -132,15 +132,21 @@ let areSettingsLoaded = false;
// Load notification settings from the api // Load notification settings from the api
async function loadNotificationSettings() { async function loadNotificationSettings() {
if (areSettingsLoaded) return; if (areSettingsLoaded) return;
const [result] = await Promise.all([ const [resultSettings, resultExceptions] = await Promise.all([
callApi('fetchNotificationSettings', { callApi('fetchNotificationSettings', {
serverTimeOffset: getGlobal().serverTimeOffset, serverTimeOffset: getGlobal().serverTimeOffset,
}), }),
callApi('fetchNotificationExceptions'), callApi('fetchNotificationExceptions', {
serverTimeOffset: getGlobal().serverTimeOffset,
}),
]); ]);
if (!result) return; if (!resultSettings) return;
setGlobal(replaceSettings(getGlobal(), result)); let global = replaceSettings(getGlobal(), resultSettings);
if (resultExceptions) {
global = addNotifyExceptions(global, resultExceptions);
}
setGlobal(global);
areSettingsLoaded = true; areSettingsLoaded = true;
} }