[Memory] Fixes and optimizations (#3453)
This commit is contained in:
parent
a136a66e61
commit
23eef3034d
@ -1,17 +1,17 @@
|
|||||||
import { Api as GramJs } from '../../../lib/gramjs';
|
import { Api as GramJs } from '../../../lib/gramjs';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiConfig,
|
ApiConfig, ApiCountry, ApiSession, ApiUrlAuthResult, ApiWallpaper, ApiWebSession, ApiLangString,
|
||||||
ApiCountry, ApiSession, ApiUrlAuthResult, ApiWallpaper, ApiWebSession,
|
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
import type { ApiPrivacySettings, ApiPrivacyKey, PrivacyVisibility } from '../../../types';
|
import type { ApiPrivacySettings, ApiPrivacyKey, PrivacyVisibility } from '../../../types';
|
||||||
|
|
||||||
import { buildApiDocument, buildApiReaction } from './messages';
|
import { buildApiDocument, buildApiReaction } from './messages';
|
||||||
import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers';
|
import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers';
|
||||||
import { pick } from '../../../util/iteratees';
|
import { omit, pick } from '../../../util/iteratees';
|
||||||
import { getServerTime } from '../../../util/serverTime';
|
import { getServerTime } from '../../../util/serverTime';
|
||||||
import { buildApiUser } from './users';
|
import { buildApiUser } from './users';
|
||||||
import { addUserToLocalDb } from '../helpers';
|
import { addUserToLocalDb } from '../helpers';
|
||||||
|
import { omitVirtualClassFields } from './helpers';
|
||||||
|
|
||||||
export function buildApiWallpaper(wallpaper: GramJs.TypeWallPaper): ApiWallpaper | undefined {
|
export function buildApiWallpaper(wallpaper: GramJs.TypeWallPaper): ApiWallpaper | undefined {
|
||||||
if (wallpaper instanceof GramJs.WallPaperNoFile) {
|
if (wallpaper instanceof GramJs.WallPaperNoFile) {
|
||||||
@ -253,3 +253,18 @@ export function buildApiConfig(config: GramJs.Config): ApiConfig {
|
|||||||
autologinToken: config.autologinToken,
|
autologinToken: config.autologinToken,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildLangPack(mtpLangPack: GramJs.LangPackDifference) {
|
||||||
|
return mtpLangPack.strings.reduce<Record<string, ApiLangString | undefined>>((acc, mtpString) => {
|
||||||
|
acc[mtpString.key] = buildLangPackString(mtpString);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildLangPackString(mtpString: GramJs.TypeLangPackString) {
|
||||||
|
return mtpString instanceof GramJs.LangPackString
|
||||||
|
? mtpString.value
|
||||||
|
: mtpString instanceof GramJs.LangPackStringPluralized
|
||||||
|
? omit(omitVirtualClassFields(mtpString), ['key'])
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
|||||||
@ -5,9 +5,10 @@ import type {
|
|||||||
ApiAppConfig,
|
ApiAppConfig,
|
||||||
ApiConfig,
|
ApiConfig,
|
||||||
ApiError,
|
ApiError,
|
||||||
ApiLangString,
|
|
||||||
ApiLanguage,
|
ApiLanguage,
|
||||||
ApiNotifyException, ApiPhoto, ApiUser,
|
ApiNotifyException,
|
||||||
|
ApiPhoto,
|
||||||
|
ApiUser,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
import type { ApiPrivacyKey, InputPrivacyRules, LangCode } from '../../../types';
|
import type { ApiPrivacyKey, InputPrivacyRules, LangCode } from '../../../types';
|
||||||
import type { LANG_PACKS } from '../../../config';
|
import type { LANG_PACKS } from '../../../config';
|
||||||
@ -20,7 +21,7 @@ import {
|
|||||||
buildApiNotifyException,
|
buildApiNotifyException,
|
||||||
buildApiSession,
|
buildApiSession,
|
||||||
buildApiWallpaper,
|
buildApiWallpaper,
|
||||||
buildApiWebSession,
|
buildApiWebSession, buildLangPack, buildLangPackString,
|
||||||
buildPrivacyRules,
|
buildPrivacyRules,
|
||||||
} from '../apiBuilders/misc';
|
} from '../apiBuilders/misc';
|
||||||
|
|
||||||
@ -426,12 +427,7 @@ export async function fetchLangPack({ sourceLangPacks, langCode }: {
|
|||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const collections = results
|
const collections = results.filter(Boolean).map(buildLangPack);
|
||||||
.filter(Boolean)
|
|
||||||
.map((result) => {
|
|
||||||
return buildCollectionByKey(result.strings.map<ApiLangString>(omitVirtualClassFields), 'key');
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!collections.length) {
|
if (!collections.length) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -452,7 +448,7 @@ export async function fetchLangStrings({ langPack, langCode, keys }: {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.map(omitVirtualClassFields);
|
return result.map(buildLangPackString);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchPrivacySettings(privacyKey: ApiPrivacyKey) {
|
export async function fetchPrivacySettings(privacyKey: ApiPrivacyKey) {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import type { TypedBroadcastChannel } from '../../../util/multitab';
|
|||||||
|
|
||||||
import { IS_MULTITAB_SUPPORTED } from '../../../util/windowEnvironment';
|
import { IS_MULTITAB_SUPPORTED } from '../../../util/windowEnvironment';
|
||||||
import { DATA_BROADCAST_CHANNEL_NAME, DEBUG } from '../../../config';
|
import { DATA_BROADCAST_CHANNEL_NAME, DEBUG } from '../../../config';
|
||||||
import generateIdFor from '../../../util/generateIdFor';
|
import generateUniqueId from '../../../util/generateUniqueId';
|
||||||
import { pause } from '../../../util/schedulers';
|
import { pause } from '../../../util/schedulers';
|
||||||
import { getCurrentTabId, subscribeToMasterChange } from '../../../util/establishMultitabRole';
|
import { getCurrentTabId, subscribeToMasterChange } from '../../../util/establishMultitabRole';
|
||||||
import Deferred from '../../../util/Deferred';
|
import Deferred from '../../../util/Deferred';
|
||||||
@ -284,7 +284,7 @@ function makeRequestToMaster(message: {
|
|||||||
args: MethodArgs<keyof Methods>;
|
args: MethodArgs<keyof Methods>;
|
||||||
withCallback?: boolean;
|
withCallback?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const messageId = generateIdFor(requestStates);
|
const messageId = generateUniqueId();
|
||||||
const payload = {
|
const payload = {
|
||||||
messageId,
|
messageId,
|
||||||
...message,
|
...message,
|
||||||
@ -323,7 +323,7 @@ function makeRequestToMaster(message: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function makeRequest(message: OriginRequest) {
|
function makeRequest(message: OriginRequest) {
|
||||||
const messageId = generateIdFor(requestStates);
|
const messageId = generateUniqueId();
|
||||||
const payload: OriginRequest = {
|
const payload: OriginRequest = {
|
||||||
messageId,
|
messageId,
|
||||||
...message,
|
...message,
|
||||||
|
|||||||
@ -12,15 +12,13 @@ export interface ApiLanguage {
|
|||||||
translationsUrl: string;
|
translationsUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiLangString {
|
export type ApiLangString = string | {
|
||||||
key: string;
|
|
||||||
value?: string;
|
|
||||||
zeroValue?: string;
|
zeroValue?: string;
|
||||||
oneValue?: string;
|
oneValue?: string;
|
||||||
twoValue?: string;
|
twoValue?: string;
|
||||||
fewValue?: string;
|
fewValue?: string;
|
||||||
manyValue?: string;
|
manyValue?: string;
|
||||||
otherValue?: string;
|
otherValue?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type ApiLangPack = Record<string, ApiLangString>;
|
export type ApiLangPack = Record<string, ApiLangString | undefined>;
|
||||||
|
|||||||
@ -5,12 +5,12 @@ import { requestMeasure } from '../../lib/fasterdom/fasterdom';
|
|||||||
import { ensureRLottie, getRLottie } from '../../lib/rlottie/RLottie.async';
|
import { ensureRLottie, getRLottie } from '../../lib/rlottie/RLottie.async';
|
||||||
|
|
||||||
import React, {
|
import React, {
|
||||||
useEffect, useRef, memo, useState, useMemo,
|
useEffect, useRef, memo, useState,
|
||||||
} from '../../lib/teact/teact';
|
} from '../../lib/teact/teact';
|
||||||
|
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import buildStyle from '../../util/buildStyle';
|
import buildStyle from '../../util/buildStyle';
|
||||||
import generateIdFor from '../../util/generateIdFor';
|
import generateUniqueId from '../../util/generateUniqueId';
|
||||||
import { hexToRgb } from '../../util/switchTheme';
|
import { hexToRgb } from '../../util/switchTheme';
|
||||||
|
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
@ -23,6 +23,7 @@ import useSharedIntersectionObserver from '../../hooks/useSharedIntersectionObse
|
|||||||
import useThrottledCallback from '../../hooks/useThrottledCallback';
|
import useThrottledCallback from '../../hooks/useThrottledCallback';
|
||||||
import useColorFilter from '../../hooks/stickers/useColorFilter';
|
import useColorFilter from '../../hooks/stickers/useColorFilter';
|
||||||
import useSyncEffect from '../../hooks/useSyncEffect';
|
import useSyncEffect from '../../hooks/useSyncEffect';
|
||||||
|
import useUniqueId from '../../hooks/useUniqueId';
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
ref?: RefObject<HTMLDivElement>;
|
ref?: RefObject<HTMLDivElement>;
|
||||||
@ -49,7 +50,6 @@ export type OwnProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const THROTTLE_MS = 150;
|
const THROTTLE_MS = 150;
|
||||||
const ID_STORE = {};
|
|
||||||
|
|
||||||
const AnimatedSticker: FC<OwnProps> = ({
|
const AnimatedSticker: FC<OwnProps> = ({
|
||||||
ref,
|
ref,
|
||||||
@ -80,7 +80,7 @@ const AnimatedSticker: FC<OwnProps> = ({
|
|||||||
containerRef = ref;
|
containerRef = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewId = useMemo(() => generateIdFor(ID_STORE, true), []);
|
const viewId = useUniqueId();
|
||||||
|
|
||||||
const [animation, setAnimation] = useState<RLottieInstance>();
|
const [animation, setAnimation] = useState<RLottieInstance>();
|
||||||
const animationRef = useRef<RLottieInstance>();
|
const animationRef = useRef<RLottieInstance>();
|
||||||
@ -129,7 +129,7 @@ const AnimatedSticker: FC<OwnProps> = ({
|
|||||||
const newAnimation = getRLottie().init(
|
const newAnimation = getRLottie().init(
|
||||||
tgsUrl,
|
tgsUrl,
|
||||||
container,
|
container,
|
||||||
renderId || generateIdFor(ID_STORE, true),
|
renderId || generateUniqueId(),
|
||||||
{
|
{
|
||||||
size,
|
size,
|
||||||
noLoop,
|
noLoop,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type { FC } from '../../lib/teact/teact';
|
import type { FC } from '../../lib/teact/teact';
|
||||||
import React, { memo, useMemo } from '../../lib/teact/teact';
|
import React, { memo, useMemo } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import generateIdFor from '../../util/generateIdFor';
|
import generateUniqueId from '../../util/generateUniqueId';
|
||||||
|
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
|
|
||||||
@ -9,7 +9,6 @@ import './PremiumIcon.scss';
|
|||||||
|
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
const PREMIUM_ICON = { __html: '<svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M6.63869 12.1902L3.50621 14.1092C3.18049 14.3087 2.75468 14.2064 2.55515 13.8807C2.45769 13.7216 2.42864 13.5299 2.47457 13.3491L2.95948 11.4405C3.13452 10.7515 3.60599 10.1756 4.24682 9.86791L7.6642 8.22716C7.82352 8.15067 7.89067 7.95951 7.81418 7.80019C7.75223 7.67116 7.61214 7.59896 7.47111 7.62338L3.66713 8.28194C2.89387 8.41581 2.1009 8.20228 1.49941 7.69823L0.297703 6.69116C0.00493565 6.44581 -0.0335059 6.00958 0.211842 5.71682C0.33117 5.57442 0.502766 5.48602 0.687982 5.47153L4.35956 5.18419C4.61895 5.16389 4.845 4.99974 4.94458 4.75937L6.36101 1.3402C6.5072 0.987302 6.91179 0.819734 7.26469 0.965925C7.43413 1.03612 7.56876 1.17075 7.63896 1.3402L9.05539 4.75937C9.15496 4.99974 9.38101 5.16389 9.6404 5.18419L13.3322 5.47311C13.713 5.50291 13.9975 5.83578 13.9677 6.2166C13.9534 6.39979 13.8667 6.56975 13.7269 6.68896L10.9114 9.08928C10.7131 9.25826 10.6267 9.52425 10.6876 9.77748L11.5532 13.3733C11.6426 13.7447 11.414 14.1182 11.0427 14.2076C10.8642 14.2506 10.676 14.2208 10.5195 14.1249L7.36128 12.1902C7.13956 12.0544 6.8604 12.0544 6.63869 12.1902Z" fill="var(--color-fill)"/></svg>' };
|
const PREMIUM_ICON = { __html: '<svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M6.63869 12.1902L3.50621 14.1092C3.18049 14.3087 2.75468 14.2064 2.55515 13.8807C2.45769 13.7216 2.42864 13.5299 2.47457 13.3491L2.95948 11.4405C3.13452 10.7515 3.60599 10.1756 4.24682 9.86791L7.6642 8.22716C7.82352 8.15067 7.89067 7.95951 7.81418 7.80019C7.75223 7.67116 7.61214 7.59896 7.47111 7.62338L3.66713 8.28194C2.89387 8.41581 2.1009 8.20228 1.49941 7.69823L0.297703 6.69116C0.00493565 6.44581 -0.0335059 6.00958 0.211842 5.71682C0.33117 5.57442 0.502766 5.48602 0.687982 5.47153L4.35956 5.18419C4.61895 5.16389 4.845 4.99974 4.94458 4.75937L6.36101 1.3402C6.5072 0.987302 6.91179 0.819734 7.26469 0.965925C7.43413 1.03612 7.56876 1.17075 7.63896 1.3402L9.05539 4.75937C9.15496 4.99974 9.38101 5.16389 9.6404 5.18419L13.3322 5.47311C13.713 5.50291 13.9975 5.83578 13.9677 6.2166C13.9534 6.39979 13.8667 6.56975 13.7269 6.68896L10.9114 9.08928C10.7131 9.25826 10.6267 9.52425 10.6876 9.77748L11.5532 13.3733C11.6426 13.7447 11.414 14.1182 11.0427 14.2076C10.8642 14.2506 10.676 14.2208 10.5195 14.1249L7.36128 12.1902C7.13956 12.0544 6.8604 12.0544 6.63869 12.1902Z" fill="var(--color-fill)"/></svg>' };
|
||||||
const store: Record<string, boolean> = {};
|
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
withGradient?: boolean;
|
withGradient?: boolean;
|
||||||
@ -41,7 +40,7 @@ const PremiumIcon: FC<OwnProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
function getPremiumIconGradient() {
|
function getPremiumIconGradient() {
|
||||||
const id = generateIdFor(store);
|
const id = generateUniqueId();
|
||||||
return {
|
return {
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
__html: `<svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="${id}" x1="3" y1="63.5001" x2="84.1475" y2="-1.32262" gradientUnits="userSpaceOnUse"><stop stop-color="#6B93FF"/><stop offset="0.439058" stop-color="#976FFF"/><stop offset="1" stop-color="#E46ACE"/></linearGradient></defs><path fill-rule="evenodd" clip-rule="evenodd" d="M6.63869 12.1902L3.50621 14.1092C3.18049 14.3087 2.75468 14.2064 2.55515 13.8807C2.45769 13.7216 2.42864 13.5299 2.47457 13.3491L2.95948 11.4405C3.13452 10.7515 3.60599 10.1756 4.24682 9.86791L7.6642 8.22716C7.82352 8.15067 7.89067 7.95951 7.81418 7.80019C7.75223 7.67116 7.61214 7.59896 7.47111 7.62338L3.66713 8.28194C2.89387 8.41581 2.1009 8.20228 1.49941 7.69823L0.297703 6.69116C0.00493565 6.44581 -0.0335059 6.00958 0.211842 5.71682C0.33117 5.57442 0.502766 5.48602 0.687982 5.47153L4.35956 5.18419C4.61895 5.16389 4.845 4.99974 4.94458 4.75937L6.36101 1.3402C6.5072 0.987302 6.91179 0.819734 7.26469 0.965925C7.43413 1.03612 7.56876 1.17075 7.63896 1.3402L9.05539 4.75937C9.15496 4.99974 9.38101 5.16389 9.6404 5.18419L13.3322 5.47311C13.713 5.50291 13.9975 5.83578 13.9677 6.2166C13.9534 6.39979 13.8667 6.56975 13.7269 6.68896L10.9114 9.08928C10.7131 9.25826 10.6267 9.52425 10.6876 9.77748L11.5532 13.3733C11.6426 13.7447 11.414 14.1182 11.0427 14.2076C10.8642 14.2506 10.676 14.2208 10.5195 14.1249L7.36128 12.1902C7.13956 12.0544 6.8604 12.0544 6.63869 12.1902Z" fill="url(#${id})"/></svg>`,
|
__html: `<svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="${id}" x1="3" y1="63.5001" x2="84.1475" y2="-1.32262" gradientUnits="userSpaceOnUse"><stop stop-color="#6B93FF"/><stop offset="0.439058" stop-color="#976FFF"/><stop offset="1" stop-color="#E46ACE"/></linearGradient></defs><path fill-rule="evenodd" clip-rule="evenodd" d="M6.63869 12.1902L3.50621 14.1092C3.18049 14.3087 2.75468 14.2064 2.55515 13.8807C2.45769 13.7216 2.42864 13.5299 2.47457 13.3491L2.95948 11.4405C3.13452 10.7515 3.60599 10.1756 4.24682 9.86791L7.6642 8.22716C7.82352 8.15067 7.89067 7.95951 7.81418 7.80019C7.75223 7.67116 7.61214 7.59896 7.47111 7.62338L3.66713 8.28194C2.89387 8.41581 2.1009 8.20228 1.49941 7.69823L0.297703 6.69116C0.00493565 6.44581 -0.0335059 6.00958 0.211842 5.71682C0.33117 5.57442 0.502766 5.48602 0.687982 5.47153L4.35956 5.18419C4.61895 5.16389 4.845 4.99974 4.94458 4.75937L6.36101 1.3402C6.5072 0.987302 6.91179 0.819734 7.26469 0.965925C7.43413 1.03612 7.56876 1.17075 7.63896 1.3402L9.05539 4.75937C9.15496 4.99974 9.38101 5.16389 9.6404 5.18419L13.3322 5.47311C13.713 5.50291 13.9975 5.83578 13.9677 6.2166C13.9534 6.39979 13.8667 6.56975 13.7269 6.68896L10.9114 9.08928C10.7131 9.25826 10.6267 9.52425 10.6876 9.77748L11.5532 13.3733C11.6426 13.7447 11.414 14.1182 11.0427 14.2076C10.8642 14.2506 10.676 14.2208 10.5195 14.1249L7.36128 12.1902C7.13956 12.0544 6.8604 12.0544 6.63869 12.1902Z" fill="url(#${id})"/></svg>`,
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
import React, {
|
import React, { memo } from '../../lib/teact/teact';
|
||||||
memo, useMemo,
|
|
||||||
} from '../../lib/teact/teact';
|
|
||||||
import { getGlobal } from '../../global';
|
import { getGlobal } from '../../global';
|
||||||
|
|
||||||
import type { FC } from '../../lib/teact/teact';
|
import type { FC } from '../../lib/teact/teact';
|
||||||
@ -10,7 +8,6 @@ import type { ApiSticker } from '../../api/types';
|
|||||||
import { IS_ANDROID, IS_WEBM_SUPPORTED } from '../../util/windowEnvironment';
|
import { IS_ANDROID, IS_WEBM_SUPPORTED } from '../../util/windowEnvironment';
|
||||||
import * as mediaLoader from '../../util/mediaLoader';
|
import * as mediaLoader from '../../util/mediaLoader';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import generateIdFor from '../../util/generateIdFor';
|
|
||||||
import { getStickerPreviewHash } from '../../global/helpers';
|
import { getStickerPreviewHash } from '../../global/helpers';
|
||||||
import { selectIsAlwaysHighPriorityEmoji } from '../../global/selectors';
|
import { selectIsAlwaysHighPriorityEmoji } from '../../global/selectors';
|
||||||
|
|
||||||
@ -22,6 +19,7 @@ import useFlag from '../../hooks/useFlag';
|
|||||||
import useCoordsInSharedCanvas from '../../hooks/useCoordsInSharedCanvas';
|
import useCoordsInSharedCanvas from '../../hooks/useCoordsInSharedCanvas';
|
||||||
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
|
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
|
||||||
import useColorFilter from '../../hooks/stickers/useColorFilter';
|
import useColorFilter from '../../hooks/stickers/useColorFilter';
|
||||||
|
import useUniqueId from '../../hooks/useUniqueId';
|
||||||
|
|
||||||
import AnimatedSticker from './AnimatedSticker';
|
import AnimatedSticker from './AnimatedSticker';
|
||||||
import OptimizedVideo from '../ui/OptimizedVideo';
|
import OptimizedVideo from '../ui/OptimizedVideo';
|
||||||
@ -54,7 +52,6 @@ type OwnProps = {
|
|||||||
|
|
||||||
const SHARED_PREFIX = 'shared';
|
const SHARED_PREFIX = 'shared';
|
||||||
const STICKER_SIZE = 24;
|
const STICKER_SIZE = 24;
|
||||||
const ID_STORE = {};
|
|
||||||
|
|
||||||
const StickerView: FC<OwnProps> = ({
|
const StickerView: FC<OwnProps> = ({
|
||||||
containerRef,
|
containerRef,
|
||||||
@ -127,7 +124,7 @@ const StickerView: FC<OwnProps> = ({
|
|||||||
// Preload preview for Message Input and local message
|
// Preload preview for Message Input and local message
|
||||||
useMedia(previewMediaHash, !shouldLoad || !shouldPreloadPreview);
|
useMedia(previewMediaHash, !shouldLoad || !shouldPreloadPreview);
|
||||||
|
|
||||||
const randomIdPrefix = useMemo(() => generateIdFor(ID_STORE, true), []);
|
const randomIdPrefix = useUniqueId();
|
||||||
const renderId = [
|
const renderId = [
|
||||||
(withSharedAnimation ? SHARED_PREFIX : randomIdPrefix),
|
(withSharedAnimation ? SHARED_PREFIX : randomIdPrefix),
|
||||||
id,
|
id,
|
||||||
|
|||||||
@ -11,11 +11,10 @@ import useLastCallback from '../../../hooks/useLastCallback';
|
|||||||
import useEnsureCustomEmoji from '../../../hooks/useEnsureCustomEmoji';
|
import useEnsureCustomEmoji from '../../../hooks/useEnsureCustomEmoji';
|
||||||
|
|
||||||
export default function useCustomEmoji(documentId?: string) {
|
export default function useCustomEmoji(documentId?: string) {
|
||||||
const global = getGlobal();
|
|
||||||
const [customEmoji, setCustomEmoji] = useState<ApiSticker | undefined>(
|
const [customEmoji, setCustomEmoji] = useState<ApiSticker | undefined>(
|
||||||
documentId ? global.customEmojis.byId[documentId] : undefined,
|
documentId ? getGlobal().customEmojis.byId[documentId] : undefined,
|
||||||
);
|
);
|
||||||
const [canPlay, setCanPlay] = useState(selectCanPlayAnimatedEmojis(global));
|
const [canPlay, setCanPlay] = useState(selectCanPlayAnimatedEmojis(getGlobal()));
|
||||||
|
|
||||||
useEnsureCustomEmoji(documentId);
|
useEnsureCustomEmoji(documentId);
|
||||||
|
|
||||||
|
|||||||
@ -122,13 +122,10 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const global = getGlobal();
|
|
||||||
|
|
||||||
return displayedFolders.map((folder, i) => {
|
return displayedFolders.map((folder, i) => {
|
||||||
const { id, title } = folder;
|
const { id, title } = folder;
|
||||||
const isBlocked = id !== ALL_FOLDER_ID && i > maxFolders - 1;
|
const isBlocked = id !== ALL_FOLDER_ID && i > maxFolders - 1;
|
||||||
const canShareFolder = selectCanShareFolder(global, id);
|
const canShareFolder = selectCanShareFolder(getGlobal(), id);
|
||||||
|
|
||||||
const contextActions = [];
|
const contextActions = [];
|
||||||
|
|
||||||
if (canShareFolder) {
|
if (canShareFolder) {
|
||||||
|
|||||||
@ -322,12 +322,13 @@ addActionHandler('loadAllChats', async (global, actions, payload): Promise<void>
|
|||||||
.sort((chat1, chat2) => getOrderDate(chat1)! - getOrderDate(chat2)!)[0]
|
.sort((chat1, chat2) => getOrderDate(chat1)! - getOrderDate(chat2)!)[0]
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
await loadChats(global,
|
await loadChats(
|
||||||
listType,
|
listType,
|
||||||
oldestChat?.id,
|
oldestChat?.id,
|
||||||
oldestChat ? getOrderDate(oldestChat) : undefined,
|
oldestChat ? getOrderDate(oldestChat) : undefined,
|
||||||
shouldReplace,
|
shouldReplace,
|
||||||
true);
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
if (shouldReplace) {
|
if (shouldReplace) {
|
||||||
onReplace?.();
|
onReplace?.();
|
||||||
@ -352,10 +353,10 @@ addActionHandler('loadFullChat', (global, actions, payload): ActionReturnType =>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('loadTopChats', (global): ActionReturnType => {
|
addActionHandler('loadTopChats', (): ActionReturnType => {
|
||||||
runThrottledForLoadTopChats(() => {
|
runThrottledForLoadTopChats(() => {
|
||||||
loadChats(global, 'active');
|
loadChats('active');
|
||||||
loadChats(global, 'archived');
|
loadChats('archived');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2157,15 +2158,15 @@ addActionHandler('openDeleteChatFolderModal', async (global, actions, payload):
|
|||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadChats<T extends GlobalState>(
|
async function loadChats(
|
||||||
global: T,
|
|
||||||
listType: 'active' | 'archived',
|
listType: 'active' | 'archived',
|
||||||
offsetId?: string,
|
offsetId?: string,
|
||||||
offsetDate?: number,
|
offsetDate?: number,
|
||||||
shouldReplace = false,
|
shouldReplace = false,
|
||||||
isFullDraftSync?: boolean,
|
isFullDraftSync?: boolean,
|
||||||
) {
|
) {
|
||||||
global = getGlobal();
|
// eslint-disable-next-line eslint-multitab-tt/no-immediate-global
|
||||||
|
let global = getGlobal();
|
||||||
let lastLocalServiceMessage = selectLastServiceNotification(global)?.message;
|
let lastLocalServiceMessage = selectLastServiceNotification(global)?.message;
|
||||||
const result = await callApi('fetchChats', {
|
const result = await callApi('fetchChats', {
|
||||||
limit: CHAT_LIST_LOAD_SLICE,
|
limit: CHAT_LIST_LOAD_SLICE,
|
||||||
|
|||||||
@ -604,7 +604,6 @@ addActionHandler('setStickerSearchQuery', (global, actions, payload): ActionRetu
|
|||||||
if (query) {
|
if (query) {
|
||||||
void searchThrottled(async () => {
|
void searchThrottled(async () => {
|
||||||
const result = await callApi('searchStickers', { query });
|
const result = await callApi('searchStickers', { query });
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -643,6 +642,7 @@ addActionHandler('setGifSearchQuery', (global, actions, payload): ActionReturnTy
|
|||||||
|
|
||||||
if (typeof query === 'string') {
|
if (typeof query === 'string') {
|
||||||
void searchThrottled(() => {
|
void searchThrottled(() => {
|
||||||
|
global = getGlobal();
|
||||||
searchGifs(global, query, global.config?.gifSearchUsername, undefined, tabId);
|
searchGifs(global, query, global.config?.gifSearchUsername, undefined, tabId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -654,6 +654,7 @@ addActionHandler('searchMoreGifs', (global, actions, payload): ActionReturnType
|
|||||||
|
|
||||||
if (typeof query === 'string') {
|
if (typeof query === 'string') {
|
||||||
void searchThrottled(() => {
|
void searchThrottled(() => {
|
||||||
|
global = getGlobal();
|
||||||
searchGifs(global, query, global.config?.gifSearchUsername, offset, tabId);
|
searchGifs(global, query, global.config?.gifSearchUsername, offset, tabId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import {
|
|||||||
selectIsTrustedBot,
|
selectIsTrustedBot,
|
||||||
selectTabState,
|
selectTabState,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import generateIdFor from '../../../util/generateIdFor';
|
import generateUniqueId from '../../../util/generateUniqueId';
|
||||||
import { compact, unique } from '../../../util/iteratees';
|
import { compact, unique } from '../../../util/iteratees';
|
||||||
import { getAllMultitabTokens, getCurrentTabId, reestablishMasterToSelf } from '../../../util/establishMultitabRole';
|
import { getAllMultitabTokens, getCurrentTabId, reestablishMasterToSelf } from '../../../util/establishMultitabRole';
|
||||||
import { getAllNotificationsCount } from '../../../util/folderManager';
|
import { getAllNotificationsCount } from '../../../util/folderManager';
|
||||||
@ -273,7 +273,7 @@ addActionHandler('reorderStickerSets', (global, actions, payload): ActionReturnT
|
|||||||
|
|
||||||
addActionHandler('showNotification', (global, actions, payload): ActionReturnType => {
|
addActionHandler('showNotification', (global, actions, payload): ActionReturnType => {
|
||||||
const { tabId = getCurrentTabId(), ...notification } = payload;
|
const { tabId = getCurrentTabId(), ...notification } = payload;
|
||||||
notification.localId = generateIdFor({});
|
notification.localId = generateUniqueId();
|
||||||
|
|
||||||
const newNotifications = [...selectTabState(global, tabId).notifications];
|
const newNotifications = [...selectTabState(global, tabId).notifications];
|
||||||
const existingNotificationIndex = newNotifications.findIndex((n) => n.message === notification.message);
|
const existingNotificationIndex = newNotifications.findIndex((n) => n.message === notification.message);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { IS_IOS } from '../util/windowEnvironment';
|
|||||||
|
|
||||||
import useSyncEffect from './useSyncEffect';
|
import useSyncEffect from './useSyncEffect';
|
||||||
import useEffectOnce from './useEffectOnce';
|
import useEffectOnce from './useEffectOnce';
|
||||||
|
import useLastCallback from './useLastCallback';
|
||||||
|
|
||||||
const PATH_BASE = `${window.location.pathname}${window.location.search}`;
|
const PATH_BASE = `${window.location.pathname}${window.location.search}`;
|
||||||
// Carefully selected by swiping and observing visual changes
|
// Carefully selected by swiping and observing visual changes
|
||||||
@ -241,6 +242,8 @@ export default function useHistoryBack({
|
|||||||
shouldResetUrlHash?: boolean;
|
shouldResetUrlHash?: boolean;
|
||||||
onBack: VoidFunction;
|
onBack: VoidFunction;
|
||||||
}) {
|
}) {
|
||||||
|
const lastOnBack = useLastCallback(onBack);
|
||||||
|
|
||||||
// Active index of the record
|
// Active index of the record
|
||||||
const indexRef = useRef<number>();
|
const indexRef = useRef<number>();
|
||||||
const wasReplaced = useRef(false);
|
const wasReplaced = useRef(false);
|
||||||
@ -262,7 +265,7 @@ export default function useHistoryBack({
|
|||||||
|
|
||||||
historyState[indexRef.current] = {
|
historyState[indexRef.current] = {
|
||||||
index: indexRef.current,
|
index: indexRef.current,
|
||||||
onBack,
|
onBack: lastOnBack,
|
||||||
shouldBeReplaced,
|
shouldBeReplaced,
|
||||||
markReplaced: () => {
|
markReplaced: () => {
|
||||||
wasReplaced.current = true;
|
wasReplaced.current = true;
|
||||||
@ -283,7 +286,7 @@ export default function useHistoryBack({
|
|||||||
// Space is a hack to make the browser completely remove the hash
|
// Space is a hack to make the browser completely remove the hash
|
||||||
hash: hash ? `#${hash}` : (shouldResetUrlHash ? ' ' : undefined),
|
hash: hash ? `#${hash}` : (shouldResetUrlHash ? ' ' : undefined),
|
||||||
});
|
});
|
||||||
}, [hash, onBack, shouldBeReplaced, shouldResetUrlHash]);
|
}, [hash, shouldBeReplaced, shouldResetUrlHash]);
|
||||||
|
|
||||||
const processBack = useCallback(() => {
|
const processBack = useCallback(() => {
|
||||||
// Only process back on open records
|
// Only process back on open records
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
import * as langProvider from '../util/langProvider';
|
import * as langProvider from '../util/langProvider';
|
||||||
|
|
||||||
import useForceUpdate from './useForceUpdate';
|
import useForceUpdate from './useForceUpdate';
|
||||||
import useSyncEffect from './useSyncEffect';
|
import useEffectOnce from './useEffectOnce';
|
||||||
|
|
||||||
export type LangFn = langProvider.LangFn;
|
export type LangFn = langProvider.LangFn;
|
||||||
|
|
||||||
const useLang = (): LangFn => {
|
const useLang = (): LangFn => {
|
||||||
const forceUpdate = useForceUpdate();
|
const forceUpdate = useForceUpdate();
|
||||||
|
|
||||||
useSyncEffect(() => {
|
useEffectOnce(() => {
|
||||||
return langProvider.addCallback(forceUpdate);
|
return langProvider.addCallback(forceUpdate);
|
||||||
}, [forceUpdate]);
|
});
|
||||||
|
|
||||||
return langProvider.getTranslationFn();
|
return langProvider.getTranslationFn();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,10 +1,22 @@
|
|||||||
import usePrevious from './usePrevious';
|
import usePrevious from './usePrevious';
|
||||||
|
import { useRef } from '../lib/teact/teact';
|
||||||
|
import useEffectOnce from './useEffectOnce';
|
||||||
|
|
||||||
const useSyncEffect = <const T extends readonly any[]>(cb: (args: T | readonly []) => void, dependencies: T) => {
|
export default function useSyncEffect<const T extends readonly any[]>(
|
||||||
|
effect: (args: T | readonly []) => NoneToVoidFunction | void,
|
||||||
|
dependencies: T,
|
||||||
|
) {
|
||||||
const prevDeps = usePrevious<T>(dependencies);
|
const prevDeps = usePrevious<T>(dependencies);
|
||||||
if (!prevDeps || dependencies.some((d, i) => d !== prevDeps[i])) {
|
const cleanupRef = useRef<NoneToVoidFunction>();
|
||||||
cb(prevDeps || []);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useSyncEffect;
|
if (!prevDeps || dependencies.some((d, i) => d !== prevDeps[i])) {
|
||||||
|
cleanupRef.current?.();
|
||||||
|
cleanupRef.current = effect(prevDeps || []) ?? undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffectOnce(() => {
|
||||||
|
return () => {
|
||||||
|
cleanupRef.current?.();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -1,17 +1,12 @@
|
|||||||
import { useRef } from '../lib/teact/teact';
|
import { useRef } from '../lib/teact/teact';
|
||||||
import generateIdFor from '../util/generateIdFor';
|
import generateUniqueId from '../util/generateUniqueId';
|
||||||
|
|
||||||
const store: Record<string, boolean> = {};
|
export default function useUniqueId() {
|
||||||
|
|
||||||
const useUniqueId = () => {
|
|
||||||
const idRef = useRef<string>();
|
const idRef = useRef<string>();
|
||||||
|
|
||||||
if (!idRef.current) {
|
if (!idRef.current) {
|
||||||
idRef.current = generateIdFor(store);
|
idRef.current = generateUniqueId();
|
||||||
store[idRef.current] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return idRef.current;
|
return idRef.current;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default useUniqueId;
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import {
|
|||||||
} from '../../util/windowEnvironment';
|
} from '../../util/windowEnvironment';
|
||||||
import { animate } from '../../util/animation';
|
import { animate } from '../../util/animation';
|
||||||
import cycleRestrict from '../../util/cycleRestrict';
|
import cycleRestrict from '../../util/cycleRestrict';
|
||||||
import generateIdFor from '../../util/generateIdFor';
|
import generateUniqueId from '../../util/generateUniqueId';
|
||||||
import launchMediaWorkers, { MAX_WORKERS } from '../../util/launchMediaWorkers';
|
import launchMediaWorkers, { MAX_WORKERS } from '../../util/launchMediaWorkers';
|
||||||
|
|
||||||
interface Params {
|
interface Params {
|
||||||
@ -27,7 +27,6 @@ const LOW_PRIORITY_QUALITY = IS_ANDROID ? 0.5 : 0.75;
|
|||||||
const LOW_PRIORITY_QUALITY_SIZE_THRESHOLD = 24;
|
const LOW_PRIORITY_QUALITY_SIZE_THRESHOLD = 24;
|
||||||
const HIGH_PRIORITY_CACHE_MODULO = IS_SAFARI ? 2 : 4;
|
const HIGH_PRIORITY_CACHE_MODULO = IS_SAFARI ? 2 : 4;
|
||||||
const LOW_PRIORITY_CACHE_MODULO = 0;
|
const LOW_PRIORITY_CACHE_MODULO = 0;
|
||||||
const ID_STORE = {};
|
|
||||||
|
|
||||||
const workers = launchMediaWorkers().map(({ connector }) => connector);
|
const workers = launchMediaWorkers().map(({ connector }) => connector);
|
||||||
const instancesByRenderId = new Map<string, RLottie>();
|
const instancesByRenderId = new Map<string, RLottie>();
|
||||||
@ -92,7 +91,7 @@ class RLottie {
|
|||||||
, canvas,
|
, canvas,
|
||||||
renderId,
|
renderId,
|
||||||
params,
|
params,
|
||||||
viewId = generateIdFor(ID_STORE, true), ,
|
viewId = generateUniqueId(), ,
|
||||||
onLoad,
|
onLoad,
|
||||||
] = args;
|
] = args;
|
||||||
let instance = instancesByRenderId.get(renderId);
|
let instance = instancesByRenderId.get(renderId);
|
||||||
@ -113,7 +112,7 @@ class RLottie {
|
|||||||
private container: HTMLDivElement | HTMLCanvasElement,
|
private container: HTMLDivElement | HTMLCanvasElement,
|
||||||
private renderId: string,
|
private renderId: string,
|
||||||
private params: Params,
|
private params: Params,
|
||||||
viewId: string = generateIdFor(ID_STORE, true),
|
viewId: string = generateUniqueId(),
|
||||||
private customColor?: [number, number, number],
|
private customColor?: [number, number, number],
|
||||||
private onLoad?: NoneToVoidFunction | undefined,
|
private onLoad?: NoneToVoidFunction | undefined,
|
||||||
private onEnded?: (isDestroyed?: boolean) => void,
|
private onEnded?: (isDestroyed?: boolean) => void,
|
||||||
|
|||||||
@ -397,7 +397,7 @@ export function renderComponent(componentInstance: ComponentInstance) {
|
|||||||
DEBUG_components[componentName] = {
|
DEBUG_components[componentName] = {
|
||||||
componentName,
|
componentName,
|
||||||
renderCount: 0,
|
renderCount: 0,
|
||||||
renderTimes: [],
|
avgRenderTime: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +420,9 @@ export function renderComponent(componentInstance: ComponentInstance) {
|
|||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.warn(`[Teact] Slow component render: ${componentName}, ${Math.round(duration)} ms`);
|
console.warn(`[Teact] Slow component render: ${componentName}, ${Math.round(duration)} ms`);
|
||||||
}
|
}
|
||||||
DEBUG_components[componentName].renderTimes.push(duration);
|
|
||||||
|
const { renderCount, avgRenderTime } = DEBUG_components[componentName];
|
||||||
|
DEBUG_components[componentName].avgRenderTime = (avgRenderTime * renderCount + duration) / (renderCount + 1);
|
||||||
DEBUG_components[componentName].renderCount++;
|
DEBUG_components[componentName].renderCount++;
|
||||||
DEBUG_components.TOTAL.renderCount++;
|
DEBUG_components.TOTAL.renderCount++;
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
/* eslint-disable eslint-multitab-tt/set-global-only-variable */
|
/* eslint-disable eslint-multitab-tt/set-global-only-variable */
|
||||||
import type { FC, FC_withDebug, Props } from './teact';
|
import type { FC, FC_withDebug, Props } from './teact';
|
||||||
import React, { useEffect, useState } from './teact';
|
import React, { useEffect } from './teact';
|
||||||
import { requestMeasure } from '../fasterdom/fasterdom';
|
import { requestMeasure } from '../fasterdom/fasterdom';
|
||||||
|
|
||||||
import { DEBUG, DEBUG_MORE } from '../../config';
|
import { DEBUG, DEBUG_MORE } from '../../config';
|
||||||
import useForceUpdate from '../../hooks/useForceUpdate';
|
|
||||||
import generateIdFor from '../../util/generateIdFor';
|
|
||||||
import { throttleWithTickEnd } from '../../util/schedulers';
|
import { throttleWithTickEnd } from '../../util/schedulers';
|
||||||
import arePropsShallowEqual, { getUnequalProps } from '../../util/arePropsShallowEqual';
|
import arePropsShallowEqual, { getUnequalProps } from '../../util/arePropsShallowEqual';
|
||||||
import { orderBy } from '../../util/iteratees';
|
import { orderBy } from '../../util/iteratees';
|
||||||
import { handleError } from '../../util/handleError';
|
import { handleError } from '../../util/handleError';
|
||||||
|
|
||||||
|
import useForceUpdate from '../../hooks/useForceUpdate';
|
||||||
|
import useUniqueId from '../../hooks/useUniqueId';
|
||||||
import { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
|
import { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
|
||||||
|
|
||||||
export default React;
|
export default React;
|
||||||
@ -252,7 +253,7 @@ export function withGlobal<OwnProps extends AnyLiteral>(
|
|||||||
return function TeactNContainer(props: OwnProps) {
|
return function TeactNContainer(props: OwnProps) {
|
||||||
(TeactNContainer as FC_withDebug).DEBUG_contentComponentName = Component.name;
|
(TeactNContainer as FC_withDebug).DEBUG_contentComponentName = Component.name;
|
||||||
|
|
||||||
const [id] = useState(generateIdFor(containers));
|
const id = useUniqueId();
|
||||||
const forceUpdate = useForceUpdate();
|
const forceUpdate = useForceUpdate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import generateIdFor from '../../util/generateIdFor';
|
import generateUniqueId from '../../util/generateUniqueId';
|
||||||
import { pause } from '../../util/schedulers';
|
import { pause } from '../../util/schedulers';
|
||||||
|
|
||||||
declare const self: WorkerGlobalScope;
|
declare const self: WorkerGlobalScope;
|
||||||
@ -15,7 +15,7 @@ const PART_TIMEOUT = 30000;
|
|||||||
const requestStates = new Map<string, RequestStates>();
|
const requestStates = new Map<string, RequestStates>();
|
||||||
|
|
||||||
export function requestPart(params: RequestPartParams): Promise<ArrayBuffer | undefined> {
|
export function requestPart(params: RequestPartParams): Promise<ArrayBuffer | undefined> {
|
||||||
const messageId = generateIdFor(requestStates);
|
const messageId = generateUniqueId();
|
||||||
const requestState = {} as RequestStates;
|
const requestState = {} as RequestStates;
|
||||||
|
|
||||||
let isResolved = false;
|
let isResolved = false;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { pause } from '../util/schedulers';
|
import { pause } from '../util/schedulers';
|
||||||
import generateIdFor from '../util/generateIdFor';
|
import generateUniqueId from '../util/generateUniqueId';
|
||||||
import {
|
import {
|
||||||
DEBUG,
|
DEBUG,
|
||||||
MEDIA_CACHE_MAX_BYTES,
|
MEDIA_CACHE_MAX_BYTES,
|
||||||
@ -149,7 +149,7 @@ export async function requestPart(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageId = generateIdFor(requestStates);
|
const messageId = generateUniqueId();
|
||||||
const requestState = {} as RequestStates;
|
const requestState = {} as RequestStates;
|
||||||
|
|
||||||
let isResolved = false;
|
let isResolved = false;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import generateIdFor from './generateIdFor';
|
import generateUniqueId from './generateUniqueId';
|
||||||
|
|
||||||
export interface CancellableCallback {
|
export interface CancellableCallback {
|
||||||
(
|
(
|
||||||
@ -108,7 +108,7 @@ class ConnectorClass<T extends InputRequestTypes> {
|
|||||||
request(messageData: RequestTypes<T>) {
|
request(messageData: RequestTypes<T>) {
|
||||||
const { requestStates, requestStatesByCallback } = this;
|
const { requestStates, requestStatesByCallback } = this;
|
||||||
|
|
||||||
const messageId = generateIdFor(requestStates);
|
const messageId = generateUniqueId();
|
||||||
const payload: CallMethodData = {
|
const payload: CallMethodData = {
|
||||||
type: 'callMethod',
|
type: 'callMethod',
|
||||||
messageId,
|
messageId,
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { selectCanPlayAnimatedEmojis } from '../global/selectors';
|
|||||||
import { getStickerPreviewHash } from '../global/helpers';
|
import { getStickerPreviewHash } from '../global/helpers';
|
||||||
import * as mediaLoader from './mediaLoader';
|
import * as mediaLoader from './mediaLoader';
|
||||||
import { throttle } from './schedulers';
|
import { throttle } from './schedulers';
|
||||||
import generateIdFor from './generateIdFor';
|
import generateUniqueId from './generateUniqueId';
|
||||||
import { IS_WEBM_SUPPORTED } from './windowEnvironment';
|
import { IS_WEBM_SUPPORTED } from './windowEnvironment';
|
||||||
import { createCallbackManager } from './callbacks';
|
import { createCallbackManager } from './callbacks';
|
||||||
|
|
||||||
@ -20,7 +20,6 @@ import blankSrc from '../assets/blank.png';
|
|||||||
type CustomEmojiLoadCallback = (customEmojis: GlobalState['customEmojis']) => void;
|
type CustomEmojiLoadCallback = (customEmojis: GlobalState['customEmojis']) => void;
|
||||||
type CustomEmojiInputRenderCallback = (emojiId: string) => void;
|
type CustomEmojiInputRenderCallback = (emojiId: string) => void;
|
||||||
|
|
||||||
const ID_STORE = {};
|
|
||||||
const DOM_PROCESS_THROTTLE = 500;
|
const DOM_PROCESS_THROTTLE = 500;
|
||||||
|
|
||||||
const INPUT_WAITING_CUSTOM_EMOJI_IDS: Set<string> = new Set();
|
const INPUT_WAITING_CUSTOM_EMOJI_IDS: Set<string> = new Set();
|
||||||
@ -120,7 +119,7 @@ export function getInputCustomEmojiParams(customEmoji?: ApiSticker) {
|
|||||||
const isUsingSharedCanvas = customEmoji.isLottie || (customEmoji.isVideo && !shouldUseStaticFallback);
|
const isUsingSharedCanvas = customEmoji.isLottie || (customEmoji.isVideo && !shouldUseStaticFallback);
|
||||||
if (isUsingSharedCanvas) {
|
if (isUsingSharedCanvas) {
|
||||||
fetchAndProcess(`sticker${customEmoji.id}`);
|
fetchAndProcess(`sticker${customEmoji.id}`);
|
||||||
return [false, blankSrc, generateIdFor(ID_STORE, true)];
|
return [false, blankSrc, generateUniqueId()];
|
||||||
}
|
}
|
||||||
|
|
||||||
const mediaData = getCustomEmojiMediaDataForInput(customEmoji.id, shouldUseStaticFallback);
|
const mediaData = getCustomEmojiMediaDataForInput(customEmoji.id, shouldUseStaticFallback);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -3,112 +3,31 @@
|
|||||||
import type { ApiLangPack } from '../api/types';
|
import type { ApiLangPack } from '../api/types';
|
||||||
|
|
||||||
export const fallbackLangPackInitial = {
|
export const fallbackLangPackInitial = {
|
||||||
WrongNumber: {
|
WrongNumber: 'Wrong number?',
|
||||||
key: 'WrongNumber',
|
SentAppCode: 'We\'ve sent the code to the **Telegram** app on your other device.',
|
||||||
value: 'Wrong number?',
|
'Login.JustSentSms': 'We have sent you a code via SMS. Please enter it above.',
|
||||||
},
|
'Login.Header.Password': 'Enter Password',
|
||||||
SentAppCode: {
|
'Login.EnterPasswordDescription': 'You have Two-Step Verification enabled, so your account is protected with an additional password.',
|
||||||
key: 'SentAppCode',
|
StartText: 'Please confirm your country code and enter your phone number.',
|
||||||
value: 'We\'ve sent the code to the **Telegram** app on your other device.',
|
'Login.PhonePlaceholder': 'Your phone number',
|
||||||
},
|
'Login.Next': 'Next',
|
||||||
'Login.JustSentSms': {
|
'Login.QR.Login': 'Log in by QR Code',
|
||||||
key: 'Login.JustSentSms',
|
'Login.QR.Title': 'Log in to Telegram by QR Code',
|
||||||
value: 'We have sent you a code via SMS. Please enter it above.',
|
'Login.QR.Help1': 'Open Telegram on your phone',
|
||||||
},
|
'Login.QR.Help2': 'Go to **Settings** > **Devices** > **Link Desktop Device**',
|
||||||
'Login.Header.Password': {
|
'Login.QR2.Help2': 'Go to **Settings** → **Devices** → **Link Desktop Device**',
|
||||||
key: 'Login.Header.Password',
|
'Login.QR.Help3': 'Point your phone at this screen to confirm login',
|
||||||
value: 'Enter Password',
|
'Login.QR.Cancel': 'Log in by phone Number',
|
||||||
},
|
YourName: 'Your Name',
|
||||||
'Login.EnterPasswordDescription': {
|
'Login.Register.Desc': 'Enter your name and add a profile picture.',
|
||||||
key: 'Login.EnterPasswordDescription',
|
'Login.Register.FirstName.Placeholder': 'First Name',
|
||||||
value: 'You have Two-Step Verification enabled, so your account is protected with an additional password.',
|
'Login.Register.LastName.Placeholder': 'Last Name',
|
||||||
},
|
'Login.SelectCountry.Title': 'Country',
|
||||||
StartText: {
|
lng_country_none: 'Country not found',
|
||||||
key: 'StartText',
|
PleaseEnterPassword: 'Enter your new password',
|
||||||
value: 'Please confirm your country code and enter your phone number.',
|
PHONE_NUMBER_INVALID: 'Invalid phone number',
|
||||||
},
|
PHONE_CODE_INVALID: 'Invalid code',
|
||||||
'Login.PhonePlaceholder': {
|
PASSWORD_HASH_INVALID: 'Incorrect password',
|
||||||
key: 'Login.PhonePlaceholder',
|
PHONE_PASSWORD_FLOOD: 'Limit exceeded. Please try again later.',
|
||||||
value: 'Your phone number',
|
PHONE_NUMBER_BANNED: 'This phone number is banned.',
|
||||||
},
|
|
||||||
'Login.Next': {
|
|
||||||
key: 'Login.Next',
|
|
||||||
value: 'Next',
|
|
||||||
},
|
|
||||||
'Login.QR.Login': {
|
|
||||||
key: 'Login.QR.Login',
|
|
||||||
value: 'Log in by QR Code',
|
|
||||||
},
|
|
||||||
'Login.QR.Title': {
|
|
||||||
key: 'Login.QR.Title',
|
|
||||||
value: 'Log in to Telegram by QR Code',
|
|
||||||
},
|
|
||||||
'Login.QR.Help1': {
|
|
||||||
key: 'Login.QR.Help1',
|
|
||||||
value: 'Open Telegram on your phone',
|
|
||||||
},
|
|
||||||
'Login.QR.Help2': {
|
|
||||||
key: 'Login.QR.Help2',
|
|
||||||
value: 'Go to **Settings** > **Devices** > **Link Desktop Device**',
|
|
||||||
},
|
|
||||||
'Login.QR2.Help2': {
|
|
||||||
key: 'Login.QR.Help2',
|
|
||||||
value: 'Go to **Settings** → **Devices** → **Link Desktop Device**',
|
|
||||||
},
|
|
||||||
'Login.QR.Help3': {
|
|
||||||
key: 'Login.QR.Help3',
|
|
||||||
value: 'Point your phone at this screen to confirm login',
|
|
||||||
},
|
|
||||||
'Login.QR.Cancel': {
|
|
||||||
key: 'Login.QR.Cancel',
|
|
||||||
value: 'Log in by phone Number',
|
|
||||||
},
|
|
||||||
YourName: {
|
|
||||||
key: 'YourName',
|
|
||||||
value: 'Your Name',
|
|
||||||
},
|
|
||||||
'Login.Register.Desc': {
|
|
||||||
key: 'Login.Register.Desc',
|
|
||||||
value: 'Enter your name and add a profile picture.',
|
|
||||||
},
|
|
||||||
'Login.Register.FirstName.Placeholder': {
|
|
||||||
key: 'Login.Register.FirstName.Placeholder',
|
|
||||||
value: 'First Name',
|
|
||||||
},
|
|
||||||
'Login.Register.LastName.Placeholder': {
|
|
||||||
key: 'Login.Register.LastName.Placeholder',
|
|
||||||
value: 'Last Name',
|
|
||||||
},
|
|
||||||
'Login.SelectCountry.Title': {
|
|
||||||
key: 'Login.SelectCountry.Title',
|
|
||||||
value: 'Country',
|
|
||||||
},
|
|
||||||
lng_country_none: {
|
|
||||||
key: 'lng_country_none',
|
|
||||||
value: 'Country not found',
|
|
||||||
},
|
|
||||||
PleaseEnterPassword: {
|
|
||||||
key: 'PleaseEnterPassword',
|
|
||||||
value: 'Enter your new password',
|
|
||||||
},
|
|
||||||
PHONE_NUMBER_INVALID: {
|
|
||||||
key: 'PHONE_NUMBER_INVALID',
|
|
||||||
value: 'Invalid phone number',
|
|
||||||
},
|
|
||||||
PHONE_CODE_INVALID: {
|
|
||||||
key: 'PHONE_CODE_INVALID',
|
|
||||||
value: 'Invalid code',
|
|
||||||
},
|
|
||||||
PASSWORD_HASH_INVALID: {
|
|
||||||
key: 'PASSWORD_HASH_INVALID',
|
|
||||||
value: 'Incorrect password',
|
|
||||||
},
|
|
||||||
PHONE_PASSWORD_FLOOD: {
|
|
||||||
key: 'PHONE_PASSWORD_FLOOD',
|
|
||||||
value: 'Limit exceeded. Please try again later.',
|
|
||||||
},
|
|
||||||
PHONE_NUMBER_BANNED: {
|
|
||||||
key: 'PHONE_NUMBER_BANNED',
|
|
||||||
value: 'This phone number is banned.',
|
|
||||||
},
|
|
||||||
} as ApiLangPack;
|
} as ApiLangPack;
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
export default function generateIdFor(store: AnyLiteral, withAutoUpdate = false) {
|
|
||||||
let id;
|
|
||||||
|
|
||||||
do {
|
|
||||||
id = String(Math.random()).replace('0.', 'id');
|
|
||||||
} while (store[id]);
|
|
||||||
|
|
||||||
if (withAutoUpdate) {
|
|
||||||
store[id] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
3
src/util/generateUniqueId.ts
Normal file
3
src/util/generateUniqueId.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default function generateUniqueId() {
|
||||||
|
return Date.now().toString(36) + Math.random().toString(36).slice(2);
|
||||||
|
}
|
||||||
@ -29,7 +29,10 @@ const PLURAL_RULES = {
|
|||||||
en: (n: number) => (n !== 1 ? 6 : 2),
|
en: (n: number) => (n !== 1 ? 6 : 2),
|
||||||
ar: (n: number) => (n === 0 ? 1 : n === 1 ? 2 : n === 2 ? 3 : n % 100 >= 3 && n % 100 <= 10 ? 4 : n % 100 >= 11 ? 5 : 6),
|
ar: (n: number) => (n === 0 ? 1 : n === 1 ? 2 : n === 2 ? 3 : n % 100 >= 3 && n % 100 <= 10 ? 4 : n % 100 >= 11 ? 5 : 6),
|
||||||
be: (n: number) => {
|
be: (n: number) => {
|
||||||
const s = String(n).split('.'); const t0 = Number(s[0]) === n; const n10 = t0 ? Number(s[0].slice(-1)) : 0; const n100 = t0 ? Number(s[0].slice(-2)) : 0;
|
const s = String(n).split('.');
|
||||||
|
const t0 = Number(s[0]) === n;
|
||||||
|
const n10 = t0 ? Number(s[0].slice(-1)) : 0;
|
||||||
|
const n100 = t0 ? Number(s[0].slice(-2)) : 0;
|
||||||
return n10 === 1 && n100 !== 11 ? 2
|
return n10 === 1 && n100 !== 11 ? 2
|
||||||
: (n10 >= 2 && n10 <= 4) && (n100 < 12 || n100 > 14) ? 4
|
: (n10 >= 2 && n10 <= 4) && (n100 < 12 || n100 > 14) ? 4
|
||||||
: (t0 && n10 === 0) || (n10 >= 5 && n10 <= 9) || (n100 >= 11 && n100 <= 14) ? 5
|
: (t0 && n10 === 0) || (n10 >= 5 && n10 <= 9) || (n100 >= 11 && n100 <= 14) ? 5
|
||||||
@ -37,7 +40,9 @@ const PLURAL_RULES = {
|
|||||||
},
|
},
|
||||||
ca: (n: number) => (n !== 1 ? 6 : 2),
|
ca: (n: number) => (n !== 1 ? 6 : 2),
|
||||||
cs: (n: number) => {
|
cs: (n: number) => {
|
||||||
const s = String(n).split('.'); const i = Number(s[0]); const v0 = !s[1];
|
const s = String(n).split('.');
|
||||||
|
const i = Number(s[0]);
|
||||||
|
const v0 = !s[1];
|
||||||
return n === 1 && v0 ? 2 : (i >= 2 && i <= 4) && v0 ? 4 : !v0 ? 5 : 6;
|
return n === 1 && v0 ? 2 : (i >= 2 && i <= 4) && v0 ? 4 : !v0 ? 5 : 6;
|
||||||
},
|
},
|
||||||
de: (n: number) => (n !== 1 ? 6 : 2),
|
de: (n: number) => (n !== 1 ? 6 : 2),
|
||||||
@ -48,8 +53,14 @@ const PLURAL_RULES = {
|
|||||||
id: () => 0,
|
id: () => 0,
|
||||||
it: (n: number) => (n !== 1 ? 6 : 2),
|
it: (n: number) => (n !== 1 ? 6 : 2),
|
||||||
hr: (n: number) => {
|
hr: (n: number) => {
|
||||||
const s = String(n).split('.'); const i = s[0]; const f = s[1] || ''; const v0 = !s[1]; const i10 = Number(i.slice(-1));
|
const s = String(n).split('.');
|
||||||
const i100 = Number(i.slice(-2)); const f10 = Number(f.slice(-1)); const f100 = Number(f.slice(-2));
|
const i = s[0];
|
||||||
|
const f = s[1] || '';
|
||||||
|
const v0 = !s[1];
|
||||||
|
const i10 = Number(i.slice(-1));
|
||||||
|
const i100 = Number(i.slice(-2));
|
||||||
|
const f10 = Number(f.slice(-1));
|
||||||
|
const f100 = Number(f.slice(-2));
|
||||||
return (v0 && i10 === 1 && i100 !== 11) || (f10 === 1 && f100 !== 11) ? 2
|
return (v0 && i10 === 1 && i100 !== 11) || (f10 === 1 && f100 !== 11) ? 2
|
||||||
: (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 || i100 > 14)) || ((f10 >= 2 && f10 <= 4) && (f100 < 12 || f100 > 14)) ? 4
|
: (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 || i100 > 14)) || ((f10 >= 2 && f10 <= 4) && (f100 < 12 || f100 > 14)) ? 4
|
||||||
: 6;
|
: 6;
|
||||||
@ -63,12 +74,20 @@ const PLURAL_RULES = {
|
|||||||
'pt-br': (n: number) => (n > 1 ? 6 : 2),
|
'pt-br': (n: number) => (n > 1 ? 6 : 2),
|
||||||
ru: (n: number) => (n % 10 === 1 && n % 100 !== 11 ? 2 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 4 : 5),
|
ru: (n: number) => (n % 10 === 1 && n % 100 !== 11 ? 2 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 4 : 5),
|
||||||
sk: (n: number) => {
|
sk: (n: number) => {
|
||||||
const s = String(n).split('.'); const i = Number(s[0]); const v0 = !s[1];
|
const s = String(n).split('.');
|
||||||
|
const i = Number(s[0]);
|
||||||
|
const v0 = !s[1];
|
||||||
return n === 1 && v0 ? 2 : (i >= 2 && i <= 4) && v0 ? 4 : !v0 ? 5 : 6;
|
return n === 1 && v0 ? 2 : (i >= 2 && i <= 4) && v0 ? 4 : !v0 ? 5 : 6;
|
||||||
},
|
},
|
||||||
sr: (n: number) => {
|
sr: (n: number) => {
|
||||||
const s = String(n).split('.'); const i = s[0]; const f = s[1] || ''; const v0 = !s[1]; const i10 = Number(i.slice(-1));
|
const s = String(n).split('.');
|
||||||
const i100 = Number(i.slice(-2)); const f10 = Number(f.slice(-1)); const f100 = Number(f.slice(-2));
|
const i = s[0];
|
||||||
|
const f = s[1] || '';
|
||||||
|
const v0 = !s[1];
|
||||||
|
const i10 = Number(i.slice(-1));
|
||||||
|
const i100 = Number(i.slice(-2));
|
||||||
|
const f10 = Number(f.slice(-1));
|
||||||
|
const f100 = Number(f.slice(-2));
|
||||||
return (v0 && i10 === 1 && i100 !== 11) || (f10 === 1 && f100 !== 11) ? 2
|
return (v0 && i10 === 1 && i100 !== 11) || (f10 === 1 && f100 !== 11) ? 2
|
||||||
: (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 || i100 > 14)) || ((f10 >= 2 && f10 <= 4) && (f100 < 12 || f100 > 14)) ? 4
|
: (v0 && (i10 >= 2 && i10 <= 4) && (i100 < 12 || i100 > 14)) || ((f10 >= 2 && f10 <= 4) && (f100 < 12 || f100 > 14)) ? 4
|
||||||
: 6;
|
: 6;
|
||||||
@ -224,7 +243,7 @@ async function fetchRemoteString(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (remote?.length) {
|
if (remote?.length) {
|
||||||
await cacheApi.save(LANG_CACHE_NAME, `${remoteLangPack}_${langCode}_${key}`, remote[0]);
|
await cacheApi.save(LANG_CACHE_NAME, `${remoteLangPack}_${langCode}_${key}`, remote[0] || '');
|
||||||
|
|
||||||
return remote[0];
|
return remote[0];
|
||||||
}
|
}
|
||||||
@ -257,10 +276,16 @@ function processTranslation(
|
|||||||
const preferredPluralOption = typeof value === 'number' || pluralValue !== undefined
|
const preferredPluralOption = typeof value === 'number' || pluralValue !== undefined
|
||||||
? getPluralOption(pluralValue ?? value)
|
? getPluralOption(pluralValue ?? value)
|
||||||
: 'value';
|
: 'value';
|
||||||
const template = langString ? (
|
const template = typeof langString === 'string'
|
||||||
langString[preferredPluralOption] || langString.otherValue || langString.value
|
? langString
|
||||||
) : undefined;
|
: preferredPluralOption === 'value'
|
||||||
if (!template || !template.trim()) {
|
// Support cached older `langString` interface
|
||||||
|
? (typeof langString === 'object' ? (langString as any).value : langString)
|
||||||
|
: typeof langString === 'object'
|
||||||
|
? langString[preferredPluralOption] || langString.otherValue
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (!template?.trim()) {
|
||||||
const parts = key.split('.');
|
const parts = key.split('.');
|
||||||
|
|
||||||
return parts[parts.length - 1];
|
return parts[parts.length - 1];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user