import React, { useEffect, useRef, memo, useCallback, useLayoutEffect, } from '../../lib/teact/teact'; import { disableStrict, enableStrict } from '../../lib/fasterdom/stricterdom'; import { getActions, withGlobal } from '../../global'; import type { FC } from '../../lib/teact/teact'; import type { GlobalState } from '../../global/types'; import type { LangCode } from '../../types'; import { DEFAULT_LANG_CODE } from '../../config'; import { LOCAL_TGS_URLS } from '../common/helpers/animatedAssets'; import { setLanguage } from '../../util/langProvider'; import buildClassName from '../../util/buildClassName'; import renderText from '../common/helpers/renderText'; import { getSuggestedLanguage } from './helpers/getSuggestedLanguage'; import useLangString from '../../hooks/useLangString'; import useFlag from '../../hooks/useFlag'; import useLang from '../../hooks/useLang'; import useMediaTransition from '../../hooks/useMediaTransition'; import useAsync from '../../hooks/useAsync'; import Loading from '../ui/Loading'; import Button from '../ui/Button'; import AnimatedIcon from '../common/AnimatedIcon'; import blankUrl from '../../assets/blank.png'; type StateProps = Pick & { language?: LangCode }; const DATA_PREFIX = 'tg://login?token='; const QR_SIZE = 280; const QR_PLANE_SIZE = 54; const QR_CODE_MUTATION_DURATION = 50; // The library is asynchronous and we need to wait for its mutation code let qrCodeStylingPromise: Promise; function ensureQrCodeStyling() { if (!qrCodeStylingPromise) { qrCodeStylingPromise = import('qr-code-styling'); } return qrCodeStylingPromise; } const AuthCode: FC = ({ connectionState, authState, authQrCode, language, }) => { const { returnToAuthPhoneNumber, setSettingOption, } = getActions(); const suggestedLanguage = getSuggestedLanguage(); const lang = useLang(); // eslint-disable-next-line no-null/no-null const qrCodeRef = useRef(null); const continueText = useLangString(suggestedLanguage, 'ContinueOnThisLanguage', true); const [isLoading, markIsLoading, unmarkIsLoading] = useFlag(); const [isQrMounted, markQrMounted, unmarkQrMounted] = useFlag(); const { result: qrCode } = useAsync(async () => { const QrCodeStyling = (await ensureQrCodeStyling()).default; return new QrCodeStyling({ width: QR_SIZE, height: QR_SIZE, image: blankUrl, margin: 10, type: 'svg', dotsOptions: { type: 'rounded', }, cornersSquareOptions: { type: 'extra-rounded', }, imageOptions: { imageSize: 0.4, margin: 8, }, qrOptions: { errorCorrectionLevel: 'M', }, }); }, []); const transitionClassNames = useMediaTransition(isQrMounted); useLayoutEffect(() => { if (!authQrCode || !qrCode) { return () => { unmarkQrMounted(); }; } if (connectionState !== 'connectionStateReady') { return undefined; } const container = qrCodeRef.current!; const data = `${DATA_PREFIX}${authQrCode.token}`; disableStrict(); qrCode.update({ data, }); if (!isQrMounted) { qrCode.append(container); markQrMounted(); } setTimeout(() => { enableStrict(); }, QR_CODE_MUTATION_DURATION); return undefined; }, [connectionState, authQrCode, isQrMounted, markQrMounted, unmarkQrMounted, qrCode]); useEffect(() => { if (connectionState === 'connectionStateReady') { void setLanguage(DEFAULT_LANG_CODE); } }, [connectionState]); const handleLangChange = useCallback(() => { markIsLoading(); void setLanguage(suggestedLanguage, () => { unmarkIsLoading(); setSettingOption({ language: suggestedLanguage }); }); }, [markIsLoading, setSettingOption, suggestedLanguage, unmarkIsLoading]); const habdleReturnToAuthPhoneNumber = useCallback(() => { returnToAuthPhoneNumber(); }, [returnToAuthPhoneNumber]); const isAuthReady = authState === 'authorizationStateWaitQrCode'; return (
{!isQrMounted &&
}

{lang('Login.QR.Title')}

  1. {lang('Login.QR.Help1')}
  2. {renderText(lang('Login.QR2.Help2'), ['simple_markdown'])}
  3. {lang('Login.QR.Help3')}
{isAuthReady && ( )} {suggestedLanguage && suggestedLanguage !== language && continueText && ( )}
); }; export default memo(withGlobal( (global): StateProps => { const { connectionState, authState, authQrCode, settings: { byKey: { language } }, } = global; return { connectionState, authState, authQrCode, language, }; }, )(AuthCode));