From 50ad3fee78b520891a0b2b3c2c1d922bf40f7b8f Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Wed, 5 Jul 2023 13:16:33 +0200 Subject: [PATCH] GramJS: Fix request errors on init (#3517) --- src/components/auth/AuthPhoneNumber.tsx | 11 ++++++----- src/components/auth/AuthQrCode.tsx | 12 +++++++----- src/hooks/useLangString.ts | 23 +++++++++-------------- src/lib/gramjs/network/MTProtoState.js | 12 ++++++++---- src/util/langProvider.ts | 13 ++++++++++--- 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/components/auth/AuthPhoneNumber.tsx b/src/components/auth/AuthPhoneNumber.tsx index 278616dca..0f791bfa2 100644 --- a/src/components/auth/AuthPhoneNumber.tsx +++ b/src/components/auth/AuthPhoneNumber.tsx @@ -71,7 +71,8 @@ const AuthPhoneNumber: FC = ({ const inputRef = useRef(null); const suggestedLanguage = getSuggestedLanguage(); - const continueText = useLangString(suggestedLanguage, 'ContinueOnThisLanguage', true); + const isConnected = connectionState === 'connectionStateReady'; + const continueText = useLangString(isConnected ? suggestedLanguage : undefined, 'ContinueOnThisLanguage', true); const [country, setCountry] = useState(); const [phoneNumber, setPhoneNumber] = useState(); const [isTouched, setIsTouched] = useState(false); @@ -88,16 +89,16 @@ const AuthPhoneNumber: FC = ({ }, [country]); useEffect(() => { - if (connectionState === 'connectionStateReady' && !authNearestCountry) { + if (isConnected && !authNearestCountry) { loadNearestCountry(); } - }, [connectionState, authNearestCountry, loadNearestCountry]); + }, [isConnected, authNearestCountry]); useEffect(() => { - if (connectionState === 'connectionStateReady') { + if (isConnected) { loadCountryList({ langCode: language }); } - }, [connectionState, language, loadCountryList]); + }, [isConnected, language]); useEffect(() => { if (authNearestCountry && phoneCodeList && !country && !isTouched) { diff --git a/src/components/auth/AuthQrCode.tsx b/src/components/auth/AuthQrCode.tsx index ffa07ba4c..8ac82d09b 100644 --- a/src/components/auth/AuthQrCode.tsx +++ b/src/components/auth/AuthQrCode.tsx @@ -60,7 +60,9 @@ const AuthCode: FC = ({ const lang = useLang(); // eslint-disable-next-line no-null/no-null const qrCodeRef = useRef(null); - const continueText = useLangString(suggestedLanguage, 'ContinueOnThisLanguage', true); + + const isConnected = connectionState === 'connectionStateReady'; + const continueText = useLangString(isConnected ? suggestedLanguage : undefined, 'ContinueOnThisLanguage', true); const [isLoading, markIsLoading, unmarkIsLoading] = useFlag(); const [isQrMounted, markQrMounted, unmarkQrMounted] = useFlag(); @@ -97,7 +99,7 @@ const AuthCode: FC = ({ }; } - if (connectionState !== 'connectionStateReady') { + if (!isConnected) { return undefined; } @@ -120,13 +122,13 @@ const AuthCode: FC = ({ }, QR_CODE_MUTATION_DURATION); return undefined; - }, [connectionState, authQrCode, isQrMounted, markQrMounted, unmarkQrMounted, qrCode]); + }, [isConnected, authQrCode, isQrMounted, markQrMounted, unmarkQrMounted, qrCode]); useEffect(() => { - if (connectionState === 'connectionStateReady') { + if (isConnected) { void setLanguage(DEFAULT_LANG_CODE); } - }, [connectionState]); + }, [isConnected]); const handleLangChange = useCallback(() => { markIsLoading(); diff --git a/src/hooks/useLangString.ts b/src/hooks/useLangString.ts index b2d4d1b01..79e249df0 100644 --- a/src/hooks/useLangString.ts +++ b/src/hooks/useLangString.ts @@ -1,26 +1,21 @@ import * as langProvider from '../util/langProvider'; -import { useState } from '../lib/teact/teact'; +import useAsync from './useAsync'; const useLangString = ( langCode: string | undefined, key: string, shouldIgnoreSameValue = false, ): string | undefined => { - const [translation, setTranslation] = useState(); + const defaultValue = shouldIgnoreSameValue ? undefined : key; + const { result } = useAsync(() => { + if (langCode) { + return langProvider.getTranslationForLangString(langCode, key); + } - if (langCode) { - langProvider - .getTranslationForLangString(langCode, key) - .then((value) => { - // The string is not translated, maybe the language pack was not loaded due to network errors or a timeout - if (shouldIgnoreSameValue && value === key) { - return; - } - setTranslation(value); - }); - } + return Promise.resolve(); + }, [langCode, key], defaultValue); - return translation; + return result || defaultValue; }; export default useLangString; diff --git a/src/lib/gramjs/network/MTProtoState.js b/src/lib/gramjs/network/MTProtoState.js index a7a4c1300..f8c6b1100 100644 --- a/src/lib/gramjs/network/MTProtoState.js +++ b/src/lib/gramjs/network/MTProtoState.js @@ -269,7 +269,7 @@ class MTProtoState { if (this.msgIds.length > 500) { this.msgIds.shift(); } - this.msgIds.push(remoteMsgId.toString()); + const remoteSequence = reader.readInt(); const containerLen = reader.readInt(); // msgLen for the inner object, padding ignored const diff = body.length - containerLen; @@ -282,10 +282,9 @@ class MTProtoState { // We could read msg_len bytes and use those in a new reader to read // the next TLObject without including the padding, but since the // reader isn't used for anything else after this, it's unnecessary. - const obj = reader.tgReadObject(); - + const obj = await reader.tgReadObject(); // We only check for objects that telegram has returned to us (Updates) not ones we send. - if (obj?.constructor.name.startsWith('Update')) { + if (obj?.className?.startsWith('Update')) { const now = Math.floor(Date.now() / 1000); const msgLocalTime = this.getMsgIdTimeLocal(remoteMsgId); @@ -294,6 +293,11 @@ class MTProtoState { throw new SecurityError('The message time is incorrect.'); } } + + if (obj && !('errorCode' in obj)) { + this.msgIds.push(remoteMsgId.toString()); + } + return new TLMessage(remoteMsgId, remoteSequence, obj); } } diff --git a/src/util/langProvider.ts b/src/util/langProvider.ts index 197875405..2870c6d37 100644 --- a/src/util/langProvider.ts +++ b/src/util/langProvider.ts @@ -148,13 +148,16 @@ export function getTranslationFn(): LangFn { } export async function getTranslationForLangString(langCode: string, key: string) { - let translateString: ApiLangString | undefined = await cacheApi.fetch( + let translateString: ApiLangString | undefined; + const cachedValue = await cacheApi.fetch( LANG_CACHE_NAME, `${DEFAULT_LANG_PACK}_${langCode}_${key}`, cacheApi.Type.Json, ); - if (!translateString) { + if (cachedValue) { + translateString = cachedValue.value; + } else { translateString = await fetchRemoteString(DEFAULT_LANG_PACK, langCode, key); } @@ -243,7 +246,11 @@ async function fetchRemoteString( }); if (remote?.length) { - await cacheApi.save(LANG_CACHE_NAME, `${remoteLangPack}_${langCode}_${key}`, remote[0] || ''); + const wrappedString = JSON.stringify({ + value: remote[0], + }); + + await cacheApi.save(LANG_CACHE_NAME, `${remoteLangPack}_${langCode}_${key}`, wrappedString); return remote[0]; }