Reactions: Fix quick reactions, refetch configs (#2178)

Co-authored-by: undrfined <undrfined@gmail.com>
This commit is contained in:
Alexander Zinchuk 2022-12-15 19:19:30 +01:00
parent 2a0ad055f1
commit 15e586d772
20 changed files with 112 additions and 35 deletions

View File

@ -22,7 +22,6 @@ interface GramJsAppConfig extends LimitsConfig {
}>;
emojies_send_dice: string[];
groupcall_video_participants_max: number;
reactions_default: string;
reactions_uniq_max: number;
chat_read_mark_size_threshold: number;
chat_read_mark_expire_period: number;
@ -66,7 +65,6 @@ export function buildAppConfig(json: GramJs.TypeJSONValue): ApiAppConfig {
const appConfig = buildJson(json) as GramJsAppConfig;
return {
defaultReaction: appConfig.reactions_default,
emojiSounds: buildEmojiSounds(appConfig),
seenByMaxChatMembers: appConfig.chat_read_mark_size_threshold,
seenByExpiresAt: appConfig.chat_read_mark_expire_period,

View File

@ -1,6 +1,7 @@
import { Api as GramJs } from '../../../lib/gramjs';
import type {
ApiConfig,
ApiCountry, ApiSession, ApiUrlAuthResult, ApiWallpaper, ApiWebSession,
} from '../../types';
import type { ApiPrivacySettings, ApiPrivacyKey, PrivacyVisibility } from '../../../types';
@ -221,3 +222,14 @@ export function buildApiUrlAuthResult(result: GramJs.TypeUrlAuthResult): ApiUrlA
}
return undefined;
}
export function buildApiConfig(config: GramJs.Config): ApiConfig {
const defaultReaction = config.reactionsDefault
&& 'emoticon' in config.reactionsDefault ? config.reactionsDefault.emoticon : undefined;
return {
expiresAt: config.expires,
gifSearchUsername: config.gifSearchUsername,
defaultReaction,
maxGroupSize: config.chatSizeMax,
};
}

View File

@ -60,7 +60,7 @@ export {
fetchNotificationExceptions, fetchNotificationSettings, updateContactSignUpNotification, updateNotificationSettings,
fetchLanguages, fetchLangPack, fetchPrivacySettings, setPrivacySettings, registerDevice, unregisterDevice,
updateIsOnline, fetchContentSettings, updateContentSettings, fetchLangStrings, fetchCountryList, fetchAppConfig,
fetchGlobalPrivacySettings, updateGlobalPrivacySettings, toggleUsername, reorderUsernames,
fetchGlobalPrivacySettings, updateGlobalPrivacySettings, toggleUsername, reorderUsernames, fetchConfig,
} from './settings';
export {

View File

@ -3,6 +3,7 @@ import { Api as GramJs } from '../../../lib/gramjs';
import type {
ApiAppConfig,
ApiConfig,
ApiError,
ApiLangString,
ApiLanguage,
@ -14,6 +15,7 @@ import type { LANG_PACKS } from '../../../config';
import { BLOCKED_LIST_LIMIT, DEFAULT_LANG_PACK } from '../../../config';
import { ACCEPTABLE_USERNAME_ERRORS } from './management';
import {
buildApiConfig,
buildApiCountryList,
buildApiNotifyException,
buildApiSession,
@ -507,6 +509,13 @@ export async function fetchAppConfig(): Promise<ApiAppConfig | undefined> {
return buildAppConfig(result);
}
export async function fetchConfig(): Promise<ApiConfig | undefined> {
const result = await invokeRequest(new GramJs.help.GetConfig());
if (!result) return undefined;
return buildApiConfig(result);
}
function updateLocalDb(
result: (
GramJs.account.PrivacyRules | GramJs.contacts.Blocked | GramJs.contacts.BlockedSlice |

View File

@ -10,7 +10,7 @@ import {
} from '../apiBuilders/symbols';
import { buildInputStickerSet, buildInputDocument, buildInputStickerSetShortName } from '../gramjsBuilders';
import { buildVideoFromDocument } from '../apiBuilders/messages';
import { RECENT_STICKERS_LIMIT } from '../../../config';
import { DEFAULT_GIF_SEARCH_BOT_USERNAME, RECENT_STICKERS_LIMIT } from '../../../config';
import localDb from '../localDb';
@ -301,15 +301,14 @@ export async function uninstallStickerSet({ stickerSetId, accessHash }: { sticke
let inputGifBot: GramJs.InputUser | undefined;
export async function searchGifs({ query, offset = '' }: { query: string; offset?: string }) {
export async function searchGifs({
query,
offset = '',
username = DEFAULT_GIF_SEARCH_BOT_USERNAME,
}: { query: string; offset?: string; username?: string }) {
if (!inputGifBot) {
const config = await invokeRequest(new GramJs.help.GetConfig());
if (!config) {
return undefined;
}
const resolvedPeer = await invokeRequest(new GramJs.contacts.ResolveUsername({
username: config.gifSearchUsername,
username,
}));
if (!resolvedPeer || !(resolvedPeer.users[0] instanceof GramJs.User)) {
return undefined;

View File

@ -1031,6 +1031,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
addEntitiesWithPhotosToLocalDb(entities);
dispatchUserAndChatUpdates(entities);
}
onUpdate({ '@type': 'updateConfig' });
} else if (DEBUG) {
const params = typeof update === 'object' && 'className' in update ? update.className : update;
log('UNEXPECTED UPDATE', params);

View File

@ -162,7 +162,6 @@ export interface ApiCountryCode extends ApiCountry {
}
export interface ApiAppConfig {
defaultReaction: string;
emojiSounds: Record<string, string>;
seenByMaxChatMembers: number;
seenByExpiresAt: number;
@ -178,6 +177,13 @@ export interface ApiAppConfig {
limits: Record<ApiLimitType, readonly [number, number]>;
}
export interface ApiConfig {
expiresAt: number;
defaultReaction?: string;
gifSearchUsername?: string;
maxGroupSize: number;
}
export interface GramJsEmojiInteraction {
v: number;
a: {

View File

@ -375,6 +375,10 @@ export type ApiUpdateError = {
error: ApiError;
};
export type ApiUpdateConfig = {
'@type': 'updateConfig';
};
export type ApiUpdateResetContacts = {
'@type': 'updateResetContactList';
};
@ -577,7 +581,7 @@ export type ApiUpdate = (
ApiUpdatePendingJoinRequests | ApiUpdatePaymentVerificationNeeded | ApiUpdatePaymentStateCompleted |
ApiUpdatePhoneCall | ApiUpdatePhoneCallSignalingData | ApiUpdatePhoneCallMediaState |
ApiUpdatePhoneCallConnectionState | ApiUpdateBotMenuButton | ApiUpdateTranscribedAudio | ApiUpdateUserEmojiStatus |
ApiUpdateMessageExtendedMedia
ApiUpdateMessageExtendedMedia | ApiUpdateConfig
);
export type OnApiUpdate = (update: ApiUpdate) => void;

View File

@ -27,18 +27,17 @@ export type OwnProps = {
type StateProps = {
creationProgress?: ChatCreationProgress;
creationError?: string;
maxGroupSize?: number;
};
// TODO @implement
const MAX_USERS_FOR_LEGACY_CHAT = 199; // Accounting for current user
const NewChatStep2: FC<OwnProps & StateProps > = ({
isChannel,
isActive,
memberIds,
onReset,
maxGroupSize,
creationProgress,
creationError,
onReset,
}) => {
const {
createGroupChat,
@ -84,7 +83,7 @@ const NewChatStep2: FC<OwnProps & StateProps > = ({
return;
}
if (memberIds.length > MAX_USERS_FOR_LEGACY_CHAT) {
if (maxGroupSize && memberIds.length >= maxGroupSize) {
setError(chatTooManyUsersError);
return;
}
@ -94,7 +93,7 @@ const NewChatStep2: FC<OwnProps & StateProps > = ({
photo,
memberIds,
});
}, [title, memberIds, createGroupChat, photo, chatTitleEmptyError, chatTooManyUsersError]);
}, [title, memberIds, maxGroupSize, createGroupChat, photo]);
const handleCreateChannel = useCallback(() => {
if (!title.length) {
@ -204,6 +203,7 @@ export default memo(withGlobal<OwnProps>(
return {
creationProgress,
creationError,
maxGroupSize: global.config?.maxGroupSize,
};
},
)(NewChatStep2));

View File

@ -63,12 +63,12 @@ const SettingsQuickReaction: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>(
(global) => {
const { availableReactions, appConfig } = global;
const { availableReactions, config } = global;
const isPremium = selectIsCurrentUserPremium(global);
return {
availableReactions,
selectedReaction: appConfig?.defaultReaction,
selectedReaction: config?.defaultReaction,
isPremium,
};
},

View File

@ -148,7 +148,7 @@ export default memo(withGlobal<OwnProps>(
addedSetIds: global.stickers.added.setIds,
customEmojiSetIds: global.customEmojis.added.setIds,
stickerSetsById: global.stickers.setsById,
defaultReaction: global.appConfig?.defaultReaction,
defaultReaction: global.config?.defaultReaction,
};
},
)(SettingsStickers));

View File

@ -186,6 +186,7 @@ const Main: FC<StateProps> = ({
closeStickerSetModal,
closeCustomEmojiSets,
checkVersionNotification,
loadConfig,
loadAppConfig,
loadAttachBots,
loadContactList,
@ -208,6 +209,7 @@ const Main: FC<StateProps> = ({
useEffect(() => {
if (lastSyncTime) {
updateIsOnline(true);
loadConfig();
loadAppConfig();
loadAvailableReactions();
loadAnimatedEmojis();
@ -223,7 +225,7 @@ const Main: FC<StateProps> = ({
}, [
lastSyncTime, loadAnimatedEmojis, loadEmojiKeywords, loadNotificationExceptions, loadNotificationSettings,
loadTopInlineBots, updateIsOnline, loadAvailableReactions, loadAppConfig, loadAttachBots, loadContactList,
loadPremiumGifts, checkAppVersion,
loadPremiumGifts, checkAppVersion, loadConfig,
]);
// Language-based API calls

View File

@ -95,6 +95,8 @@ export const MACOS_DEFAULT_MESSAGE_TEXT_SIZE_PX = 15;
export const DRAFT_DEBOUNCE = 10000; // 10s
export const SEND_MESSAGE_ACTION_INTERVAL = 3000; // 3s
// 10000s from https://corefork.telegram.org/api/url-authorization#automatic-authorization
export const APP_CONFIG_REFETCH_INTERVAL = 10000 * 1000;
export const EDITABLE_INPUT_ID = 'editable-message-text';
export const EDITABLE_INPUT_MODAL_ID = 'editable-message-text-modal';
@ -218,6 +220,7 @@ export const API_CHAT_TYPES = ['bots', 'channels', 'chats', 'users'] as const;
export const SERVICE_NOTIFICATIONS_USER_ID = '777000';
export const REPLIES_USER_ID = '1271266957'; // TODO For Test connection ID must be equal to 708513
export const RESTRICTED_EMOJI_SET_ID = '7173162320003080';
export const DEFAULT_GIF_SEARCH_BOT_USERNAME = 'gif';
export const ALL_FOLDER_ID = 0;
export const ARCHIVED_FOLDER_ID = 1;
export const DELETED_COMMENTS_CHANNEL_ID = '-777';

View File

@ -1,7 +1,6 @@
import { addActionHandler, getGlobal, setGlobal } from '../../index';
import { callApi } from '../../../api/gramjs';
import * as mediaLoader from '../../../util/mediaLoader';
import type { ApiAppConfig } from '../../../api/types';
import { ApiMediaFormat } from '../../../api/types';
import {
selectChat,
@ -180,12 +179,19 @@ addActionHandler('setDefaultReaction', async (global, actions, payload) => {
return;
}
global = getGlobal();
if (!global.config) {
actions.loadConfig(); // Refetch new config, if it is somehow not loaded
return;
}
setGlobal({
...getGlobal(),
appConfig: {
...global.appConfig,
...global,
config: {
...global.config,
defaultReaction: reaction,
} as ApiAppConfig,
},
});
});

View File

@ -10,11 +10,13 @@ import {
UPLOADING_WALLPAPER_SLUG,
} from '../../../types';
import { COUNTRIES_WITH_12H_TIME_FORMAT } from '../../../config';
import { APP_CONFIG_REFETCH_INTERVAL, COUNTRIES_WITH_12H_TIME_FORMAT } from '../../../config';
import { callApi } from '../../../api/gramjs';
import { buildCollectionByKey } from '../../../util/iteratees';
import { subscribe, unsubscribe } from '../../../util/notifications';
import { setTimeFormat } from '../../../util/langProvider';
import requestActionTimeout from '../../../util/requestActionTimeout';
import { getServerTime } from '../../../util/serverTime';
import { selectChat, selectUser } from '../../selectors';
import {
addUsers, addBlockedContact, updateChats, updateUser, removeBlockedContact, replaceSettings, updateNotifySettings,
@ -621,12 +623,27 @@ addActionHandler('loadAppConfig', async () => {
const appConfig = await callApi('fetchAppConfig');
if (!appConfig) return;
requestActionTimeout('loadAppConfig', APP_CONFIG_REFETCH_INTERVAL);
setGlobal({
...getGlobal(),
appConfig,
});
});
addActionHandler('loadConfig', async (global) => {
const config = await callApi('fetchConfig');
if (!config) return;
const timeout = config.expiresAt - getServerTime(global.serverTimeOffset);
requestActionTimeout('loadConfig', timeout * 1000);
setGlobal({
...getGlobal(),
config,
});
});
addActionHandler('loadGlobalPrivacySettings', async () => {
const globalSettings = await callApi('fetchGlobalPrivacySettings');
if (!globalSettings) {

View File

@ -516,7 +516,7 @@ addActionHandler('setGifSearchQuery', (global, actions, payload) => {
if (typeof query === 'string') {
void searchThrottled(() => {
searchGifs(query);
searchGifs(query, global.config?.gifSearchUsername);
});
}
});
@ -526,7 +526,7 @@ addActionHandler('searchMoreGifs', (global) => {
if (typeof query === 'string') {
void searchThrottled(() => {
searchGifs(query, offset);
searchGifs(query, global.config?.gifSearchUsername, offset);
});
}
});
@ -646,8 +646,8 @@ async function searchStickers(query: string, hash?: string) {
));
}
async function searchGifs(query: string, offset?: string) {
const result = await callApi('searchGifs', { query, offset });
async function searchGifs(query: string, botUsername?: string, offset?: string) {
const result = await callApi('searchGifs', { query, offset, username: botUsername });
if (!result) {
return;
}

View File

@ -24,6 +24,10 @@ addActionHandler('apiUpdate', (global, actions, update) => {
});
break;
case 'updateConfig':
actions.loadConfig();
break;
case 'updateFavoriteStickers':
actions.loadFavoriteStickers();
break;

View File

@ -952,7 +952,7 @@ export function selectDefaultReaction(global: GlobalState, chatId: string) {
if (chatId === SERVICE_NOTIFICATIONS_USER_ID) return undefined;
const isPrivate = isUserId(chatId);
const defaultReaction = global.appConfig?.defaultReaction;
const defaultReaction = global.config?.defaultReaction;
const { availableReactions } = global;
if (!defaultReaction || !availableReactions?.some(
(l) => l.reaction === defaultReaction && !l.isInactive,

View File

@ -46,6 +46,7 @@ import type {
ApiChatType,
ApiReceipt,
ApiPaymentCredentials,
ApiConfig,
} from '../api/types';
import type {
FocusDirection,
@ -138,6 +139,7 @@ export type ApiLimitTypeWithModal = Exclude<ApiLimitType, (
)>;
export type GlobalState = {
config?: ApiConfig;
appConfig?: ApiAppConfig;
canInstall?: boolean;
hasWebAuthTokenFailed?: boolean;
@ -1198,6 +1200,8 @@ export interface ActionPayloads {
skipLockOnUnload: never;
// Settings
loadConfig: never;
loadAppConfig: never;
requestNextSettingsScreen: SettingsScreens;
sortChatFolders: { folderIds: number[] };
closeDeleteChatFolderModal: never;
@ -1314,7 +1318,7 @@ export type NonTypedActionNames = (
'updateWebNotificationSettings' | 'loadLanguages' | 'loadPrivacySettings' | 'setPrivacyVisibility' |
'setPrivacySettings' | 'loadNotificationExceptions' | 'setThemeSettings' | 'updateIsOnline' |
'loadContentSettings' | 'updateContentSettings' |
'loadCountryList' | 'ensureTimeFormat' | 'loadAppConfig' |
'loadCountryList' | 'ensureTimeFormat' |
// stickers & GIFs
'setStickerSearchQuery' | 'saveGif' | 'setGifSearchQuery' | 'searchMoreGifs' |
'faveSticker' | 'unfaveSticker' | 'toggleStickerSet' |

View File

@ -0,0 +1,12 @@
import { getActions } from '../global';
import type { GlobalActions } from '../global/types';
const callbacks = new Map<string, NodeJS.Timeout>();
export default function requestActionTimeout(action: keyof GlobalActions, timeout: number) {
clearTimeout(callbacks.get(action));
const timerId = setTimeout(() => {
getActions()[action]();
}, timeout);
callbacks.set(action, timerId);
}