// @flow import React, { useCallback, useEffect, useRef, useState } from 'react'; import { View, Text, TextInput, FlatList, Platform } from 'react-native'; import { Divider, TouchableRipple } from 'react-native-paper'; import BaseTheme from '../../../base/ui/components/BaseTheme.native'; import Button from '../../../base/ui/components/native/Button'; import { BUTTON_TYPES } from '../../../base/ui/constants'; import styles from '../../../settings/components/native/styles'; import { ANSWERS_LIMIT, CHAR_LIMIT } from '../../constants'; import AbstractPollCreate from '../AbstractPollCreate'; import type { AbstractProps } from '../AbstractPollCreate'; import { chatStyles, dialogStyles } from './styles'; const PollCreate = (props: AbstractProps) => { const { addAnswer, answers, isSubmitDisabled, onSubmit, question, removeAnswer, setAnswer, setCreateMode, setQuestion, t } = props; const answerListRef = useRef(null); /* * This ref stores the Array of answer input fields, allowing us to focus on them. * This array is maintained by registerFieldRef and the useEffect below. */ const answerInputs = useRef([]); const registerFieldRef = useCallback((i, input) => { if (input === null) { return; } answerInputs.current[i] = input; }, [ answerInputs ] ); useEffect(() => { answerInputs.current = answerInputs.current.slice(0, answers.length); }, [ answers ]); /* * This state allows us to requestFocus asynchronously, without having to worry * about whether a newly created input field has been rendered yet or not. */ const [ lastFocus, requestFocus ] = useState(null); const { PRIMARY, SECONDARY } = BUTTON_TYPES; useEffect(() => { if (lastFocus === null) { return; } const input = answerInputs.current[lastFocus]; if (input === undefined) { return; } input.focus(); }, [ answerInputs, lastFocus ]); const onQuestionKeyDown = useCallback(() => { answerInputs.current[0].focus(); }); // Called on keypress in answer fields const onAnswerKeyDown = useCallback((index: number, ev) => { const { key } = ev.nativeEvent; const currentText = answers[index]; if (key === 'Backspace' && currentText === '' && answers.length > 1) { removeAnswer(index); requestFocus(index > 0 ? index - 1 : 0); } }, [ answers, addAnswer, removeAnswer, requestFocus ]); /* eslint-disable react/no-multi-comp */ const createRemoveOptionButton = onPress => ( { t('polls.create.removeOption') } ); /* eslint-disable react/jsx-no-bind */ const renderListItem = ({ index }: { index: number }) => // padding to take into account the two default options ( { t('polls.create.pollOption', { index: index + 1 }) } setAnswer(index, text) } onKeyPress = { ev => onAnswerKeyDown(index, ev) } placeholder = { t('polls.create.answerPlaceholder', { index: index + 1 }) } placeholderTextColor = { BaseTheme.palette.text03 } ref = { input => registerFieldRef(index, input) } selectionColor = { BaseTheme.palette.action01 } style = { dialogStyles.field } value = { answers[index] } /> { answers.length > 2 && createRemoveOptionButton(() => removeAnswer(index)) } ); const buttonRowStyles = Platform.OS === 'android' ? chatStyles.buttonRowAndroid : chatStyles.buttonRowIos; return ( { t('polls.create.pollQuestion') } index.toString() } ref = { answerListRef } renderItem = { renderListItem } />