import { ChangeEvent } from 'react'; // @ts-ignore import monkeyPath from '../../assets/monkey.svg'; import { GlobalActions, GlobalState } from '../../global/types'; import React, { FC, memo, useCallback, useEffect, useLayoutEffect, useRef, useState, } from '../../lib/teact/teact'; import { withGlobal } from '../../lib/teact/teactn'; import { IS_SAFARI, IS_TOUCH_ENV, } from '../../util/environment'; import { preloadImage } from '../../util/files'; import preloadFonts from '../../util/fonts'; import { pick } from '../../util/iteratees'; import { formatPhoneNumber, getCountryById, getCountryFromPhoneNumber } from '../../util/phoneNumber'; import Button from '../ui/Button'; import Checkbox from '../ui/Checkbox'; import InputText from '../ui/InputText'; import Loading from '../ui/Loading'; import CountryCodeInput from './CountryCodeInput'; type StateProps = Pick; type DispatchProps = Pick; const MIN_NUMBER_LENGTH = 7; let isPreloadInitiated = false; const AuthPhoneNumber: FC = ({ connectionState, authState, authPhoneNumber, authIsLoading, authIsLoadingQrCode, authError, authRememberMe, authNearestCountry, setAuthPhoneNumber, setAuthRememberMe, loadNearestCountry, clearAuthError, goToAuthQrCode, }) => { // eslint-disable-next-line no-null/no-null const inputRef = useRef(null); const [country, setCountry] = useState(); const [phoneNumber, setPhoneNumber] = useState(); const [isTouched, setIsTouched] = useState(false); const [lastSelection, setLastSelection] = useState<[number, number] | undefined>(); const fullNumber = country ? `${country.code} ${phoneNumber || ''}` : phoneNumber; const canSubmit = fullNumber && fullNumber.replace(/[^\d]+/g, '').length >= MIN_NUMBER_LENGTH; useEffect(() => { if (!IS_TOUCH_ENV) { inputRef.current!.focus(); } }, [country]); useEffect(() => { if (connectionState === 'connectionStateReady' && !authNearestCountry) { loadNearestCountry(); } }, [connectionState, authNearestCountry, loadNearestCountry]); useEffect(() => { if (authNearestCountry && !country && !isTouched) { setCountry(getCountryById(authNearestCountry)); } }, [country, authNearestCountry, isTouched]); const parseFullNumber = useCallback((newFullNumber: string) => { if (!newFullNumber.length) { setPhoneNumber(''); } const suggestedCountry = getCountryFromPhoneNumber(newFullNumber); const selectedCountry = !country || (suggestedCountry && suggestedCountry.id !== country.id) ? suggestedCountry : country; if (!country || (selectedCountry && selectedCountry.code !== country.code)) { setCountry(selectedCountry); } setPhoneNumber(formatPhoneNumber(newFullNumber, selectedCountry)); }, [country]); useEffect(() => { if (phoneNumber === undefined && authPhoneNumber) { parseFullNumber(authPhoneNumber); } }, [authPhoneNumber, phoneNumber, parseFullNumber]); useLayoutEffect(() => { if (inputRef.current && lastSelection) { inputRef.current.setSelectionRange(...lastSelection); } }, [lastSelection]); const isJustPastedRef = useRef(false); const handlePaste = useCallback(() => { isJustPastedRef.current = true; requestAnimationFrame(() => { isJustPastedRef.current = false; }); }, []); const handlePhoneNumberChange = useCallback((e: ChangeEvent) => { if (authError) { clearAuthError(); } // This is for further screens. We delay it until user input to speed up the initial loading. if (!isPreloadInitiated) { isPreloadInitiated = true; preloadFonts(); preloadImage(monkeyPath); } const { value, selectionStart, selectionEnd } = e.target; setLastSelection( selectionStart && selectionEnd && selectionEnd < value.length ? [selectionStart, selectionEnd] : undefined, ); setIsTouched(true); const shouldFixSafariAutoComplete = ( IS_SAFARI && country && fullNumber !== undefined && value.length - fullNumber.length > 1 && !isJustPastedRef.current ); parseFullNumber(shouldFixSafariAutoComplete ? `${country!.code} ${value}` : value); }, [authError, clearAuthError, country, fullNumber, parseFullNumber]); const handleKeepSessionChange = useCallback((e: ChangeEvent) => { setAuthRememberMe(e.target.checked); }, [setAuthRememberMe]); function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (authIsLoading) { return; } if (canSubmit) { setAuthPhoneNumber({ phoneNumber: fullNumber }); } } const isAuthReady = authState === 'authorizationStateWaitPhoneNumber'; return (
); }; export default memo(withGlobal( (global): StateProps => pick(global, [ 'connectionState', 'authState', 'authPhoneNumber', 'authIsLoading', 'authIsLoadingQrCode', 'authError', 'authRememberMe', 'authNearestCountry', ]), (setGlobal, actions): DispatchProps => pick(actions, [ 'setAuthPhoneNumber', 'setAuthRememberMe', 'clearAuthError', 'loadNearestCountry', 'goToAuthQrCode', ]), )(AuthPhoneNumber));