/* Предрейсовые осмотры - мобильное приложение Компонент модального окна с полем ввода */ //--------------------- //Подключение библиотек //--------------------- const React = require('react'); //React const { Modal, View, TextInput, Pressable, Platform, StyleSheet, BackHandler } = require('react-native'); //Базовые компоненты const AppText = require('./AppText'); //Общий текстовый компонент const AppButton = require('./AppButton'); //Кнопка const styles = require('../../styles/common/InputDialog.styles'); //Стили диалога const OVERLAY_Z = 9999; //----------- //Тело модуля //----------- //Модальное окно с полем ввода function InputDialog( { visible, title = 'Ввод данных', label, value = '', placeholder, keyboardType = 'default', autoCapitalize = 'none', confirmText = 'Сохранить', cancelText = 'Отмена', onConfirm, onCancel, validator, errorMessage }, ref ) { //Локальное значение для редактирования const [inputValue, setInputValue] = React.useState(value); const inputRef = React.useRef(null); //На Android поле ввода изначально не фокусируемо, чтобы нативный слой видел «нет фокуса» и перехватывал сканер с первого символа (как на остальных экранах) const [inputFocusable, setInputFocusable] = React.useState(Platform.OS !== 'android'); const focusFirstEditableInput = React.useCallback(() => { if (inputRef.current && typeof inputRef.current.focus === 'function') { inputRef.current.focus(); } }, []); React.useImperativeHandle( ref, function exposeScannerApi() { return { setValueFromScanner(val) { setInputValue(val != null ? String(val) : ''); if (Platform.OS === 'android') setInputFocusable(true); focusFirstEditableInput(); } }; }, [focusFirstEditableInput] ); //После включения фокусируемости на Android — ставим фокус на поле (после setValueFromScanner) React.useEffect( function focusWhenFocusable() { if (Platform.OS !== 'android' || !inputFocusable) return; focusFirstEditableInput(); }, [inputFocusable, focusFirstEditableInput] ); const [error, setError] = React.useState(''); const [isFocused, setIsFocused] = React.useState(false); //Сброс значения и фокусируемости только при открытии диалога const prevVisibleRef = React.useRef(false); React.useEffect(() => { const justOpened = visible && !prevVisibleRef.current; prevVisibleRef.current = visible; if (justOpened) { setInputValue(value); setError(''); if (Platform.OS === 'android') setInputFocusable(false); } }, [visible, value]); //Кнопка «Назад» на Android при overlay (без Modal) закрывает диалог React.useEffect( function backHandler() { if (Platform.OS !== 'android' || !visible) return; const sub = BackHandler.addEventListener('hardwareBackPress', function onBack() { handleCancel(); return true; }); return function remove() { sub.remove(); }; }, [visible, handleCancel] ); //Обработчик фокуса const handleFocus = React.useCallback(() => { setIsFocused(true); }, []); //Обработчик потери фокуса const handleBlur = React.useCallback(() => { setIsFocused(false); }, []); //Обработчик изменения текста const handleChangeText = React.useCallback(text => { setInputValue(text); setError(''); }, []); //Валидация введённого значения const validateInput = React.useCallback(() => { if (typeof validator === 'function') { const validationResult = validator(inputValue); if (validationResult !== true) { setError(validationResult || errorMessage || 'Некорректное значение'); return false; } } return true; }, [inputValue, validator, errorMessage]); //Обработчик подтверждения const handleConfirm = React.useCallback(() => { if (!validateInput()) { return; } if (typeof onConfirm === 'function') { onConfirm(inputValue.trim()); } }, [inputValue, validateInput, onConfirm]); //Обработчик отмены const handleCancel = React.useCallback(() => { if (typeof onCancel === 'function') { onCancel(); } }, [onCancel]); //Обработчик закрытия по кнопке "Назад" (Android) const handleRequestClose = React.useCallback(() => { handleCancel(); }, [handleCancel]); const preventKeyActions = Platform.OS === 'android'; const closePressableProps = preventKeyActions ? { focusable: false } : {}; const cancelButtonFocusable = preventKeyActions ? false : undefined; const confirmButtonFocusable = preventKeyActions ? false : undefined; const dialogContent = ( {title} × {label ? ( {label} ) : null} {error ? ( {error} ) : null} ); if (!visible) return null; if (Platform.OS === 'android') { return ( {dialogContent} ); } return ( {dialogContent} ); } //---------------- //Интерфейс модуля //---------------- module.exports = React.forwardRef(InputDialog);