import type { FC } from '../../lib/teact/teact'; import React, { memo, useCallback, useRef, useState, } from '../../lib/teact/teact'; import { withGlobal } from '../../global'; import type { ApiCountryCode } from '../../api/types'; import { ANIMATION_END_DELAY } from '../../config'; import buildClassName from '../../util/buildClassName'; import { isoToEmoji } from '../../util/emoji/emoji'; import { prepareSearchWordsForNeedle } from '../../util/searchWords'; import renderText from '../common/helpers/renderText'; import useOldLang from '../../hooks/useOldLang'; import useSyncEffect from '../../hooks/useSyncEffect'; import DropdownMenu from '../ui/DropdownMenu'; import MenuItem from '../ui/MenuItem'; import Spinner from '../ui/Spinner'; import './CountryCodeInput.scss'; type StateProps = { phoneCodeList: ApiCountryCode[]; }; type OwnProps = { id: string; value?: ApiCountryCode; isLoading?: boolean; onChange: (value: ApiCountryCode) => void; }; const MENU_HIDING_DURATION = 200 + ANIMATION_END_DELAY; const SELECT_TIMEOUT = 50; const CountryCodeInput: FC = ({ id, value, isLoading, onChange, phoneCodeList, }) => { const lang = useOldLang(); // eslint-disable-next-line no-null/no-null const inputRef = useRef(null); const [filter, setFilter] = useState(); const [filteredList, setFilteredList] = useState([]); const updateFilter = useCallback((filterValue?: string) => { setFilter(filterValue); setFilteredList(getFilteredList(phoneCodeList, filterValue)); }, [phoneCodeList]); useSyncEffect(([prevPhoneCodeList]) => { if (!prevPhoneCodeList?.length && phoneCodeList.length) { setFilteredList(getFilteredList(phoneCodeList, filter)); } }, [phoneCodeList, filter]); const handleChange = useCallback((country: ApiCountryCode) => { onChange(country); setTimeout(() => updateFilter(undefined), MENU_HIDING_DURATION); }, [onChange, updateFilter]); const handleInput = useCallback((e: React.FormEvent) => { updateFilter(e.currentTarget.value); }, [updateFilter]); const handleInputKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.keyCode !== 8) { return; } const target = e.currentTarget; if (value && filter === undefined) { target.value = ''; } updateFilter(target.value); }, [filter, updateFilter, value]); const CodeInput: FC<{ onTrigger: () => void; isOpen?: boolean }> = useCallback(({ onTrigger, isOpen }) => { const handleTrigger = () => { if (isOpen) { return; } setTimeout(() => { inputRef.current!.select(); }, SELECT_TIMEOUT); onTrigger(); const formEl = document.getElementById('auth-phone-number-form')!; formEl.scrollTo({ top: formEl.scrollHeight, behavior: 'smooth' }); }; const handleCodeInput = (e: React.FormEvent) => { handleInput(e); handleTrigger(); }; const inputValue = filter ?? (value?.name || value?.defaultName || ''); return (
{isLoading ? ( ) : ( )}
); }, [filter, handleInput, handleInputKeyDown, id, isLoading, lang, value]); return ( {filteredList .map((country: ApiCountryCode) => ( handleChange(country)} > {renderText(isoToEmoji(country.iso2), ['hq_emoji'])} {country.name || country.defaultName} +{country.countryCode} ))} {!filteredList.length && ( {lang('lng_country_none')} )} ); }; function getFilteredList(countryList: ApiCountryCode[], filter = ''): ApiCountryCode[] { if (!filter.length) { return countryList; } const searchWords = prepareSearchWordsForNeedle(filter); return countryList.filter((country) => ( searchWords(country.defaultName) || (country.name && searchWords(country.name)) )); } export default memo(withGlobal( (global): StateProps => { const { countryList: { phoneCodes: phoneCodeList } } = global; return { phoneCodeList, }; }, )(CountryCodeInput));