import { memo, useLayoutEffect, useRef, } from '../../lib/teact/teact'; import { getActions, withGlobal } from '../../global'; import type { GlobalState } from '../../global/types'; import { STRICTERDOM_ENABLED } from '../../config'; import { disableStrict, enableStrict } from '../../lib/fasterdom/stricterdom'; import { selectSharedSettings } from '../../global/selectors/sharedState'; import buildClassName from '../../util/buildClassName'; import { oldSetLanguage } from '../../util/oldLangProvider'; import { LOCAL_TGS_URLS } from '../common/helpers/animatedAssets'; import { navigateBack } from './helpers/backNavigation'; import { getSuggestedLanguage } from './helpers/getSuggestedLanguage'; import useAsync from '../../hooks/useAsync'; import useFlag from '../../hooks/useFlag'; import useLang from '../../hooks/useLang'; import useLangString from '../../hooks/useLangString'; import useLastCallback from '../../hooks/useLastCallback'; import useMediaTransitionDeprecated from '../../hooks/useMediaTransitionDeprecated'; import useMultiaccountInfo from '../../hooks/useMultiaccountInfo'; import AnimatedIcon from '../common/AnimatedIcon'; import Icon from '../common/icons/Icon'; import Button from '../ui/Button'; import Loading from '../ui/Loading'; import blankUrl from '../../assets/blank.png'; type StateProps = Pick & { language?: string; }; 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 | undefined; function ensureQrCodeStyling() { if (!qrCodeStylingPromise) { qrCodeStylingPromise = import('qr-code-styling'); } return qrCodeStylingPromise; } const AuthCode = ({ connectionState, authState, authQrCode, language, }: StateProps) => { const { returnToAuthPhoneNumber, setSharedSettingOption, } = getActions(); const suggestedLanguage = getSuggestedLanguage(); const lang = useLang(); const qrCodeRef = useRef(); const isConnected = connectionState === 'connectionStateReady'; const continueText = useLangString('AuthContinueOnThisLanguage', suggestedLanguage); const [isLoading, markIsLoading, unmarkIsLoading] = useFlag(); const [isQrMounted, markQrMounted, unmarkQrMounted] = useFlag(); const accountsInfo = useMultiaccountInfo(); const hasActiveAccount = Object.values(accountsInfo).length > 0; 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 = useMediaTransitionDeprecated(isQrMounted); useLayoutEffect(() => { if (!authQrCode || !qrCode) { return () => { unmarkQrMounted(); }; } if (!isConnected) { return undefined; } const container = qrCodeRef.current!; const data = `${DATA_PREFIX}${authQrCode.token}`; if (STRICTERDOM_ENABLED) { disableStrict(); } qrCode.update({ data, }); if (!isQrMounted) { qrCode.append(container); markQrMounted(); } if (STRICTERDOM_ENABLED) { setTimeout(() => { enableStrict(); }, QR_CODE_MUTATION_DURATION); } return undefined; }, [isConnected, authQrCode, isQrMounted, qrCode]); const handleBackNavigation = useLastCallback(() => { navigateBack(); }); const handleLangChange = useLastCallback(() => { markIsLoading(); void oldSetLanguage(suggestedLanguage, () => { unmarkIsLoading(); setSharedSettingOption({ language: suggestedLanguage }); }); }); const handleReturnToAuthPhoneNumber = useLastCallback(() => { returnToAuthPhoneNumber(); }); const isAuthReady = authState === 'authorizationStateWaitQrCode'; return (
{hasActiveAccount && ( )}
{!isQrMounted &&
}

{lang('LoginQRTitle')}

  1. {lang('LoginQRHelp1')}
  2. {lang('LoginQRHelp2', undefined, { withNodes: true, withMarkdown: true })}
  3. {lang('LoginQRHelp3')}
{isAuthReady && ( )} {suggestedLanguage && suggestedLanguage !== language && continueText && ( )}
); }; export default memo(withGlobal( (global): Complete => { const { connectionState, authState, authQrCode, } = global; const { language } = selectSharedSettings(global); return { connectionState, authState, authQrCode, language, }; }, )(AuthCode));