import PropTypes from 'prop-types'; import React from 'react'; import { TextInput } from 'react-native'; import Prompt from 'react-native-prompt'; import { connect } from 'react-redux'; import { translate } from '../../i18n'; import AbstractDialog from './AbstractDialog'; /** * Implements AbstractDialog on react-native using Prompt. */ class Dialog extends AbstractDialog { /** * AbstractDialog's React Component prop types. * * @static */ static propTypes = { ...AbstractDialog.propTypes, /** * I18n key to put as body title. */ bodyKey: PropTypes.string }; /** * Implements React's {@link Component#render()}. * * @inheritdoc * @returns {ReactElement} */ render() { const { bodyKey, cancelDisabled, cancelTitleKey = 'dialog.Cancel', children, okDisabled, okTitleKey = 'dialog.Ok', t, titleKey, titleString } = this.props; /* eslint-disable react/jsx-wrap-multilines */ let element = ; /* eslint-enable react/jsx-wrap-multilines */ if (React.Children.count(children)) { // XXX The following implements a workaround with knowledge of the // implementation of react-native-prompt. element = this._replaceFirstElementOfType( // eslint-disable-next-line no-extra-parens, new-cap (new (element.type)(element.props)).render(), TextInput, children); } return element; } /** * Creates a deep clone of a specific ReactElement with the results * of calling a specific function on every node of a specific * ReactElement tree. * * @param {ReactElement} element - The ReactElement to clone and * call the specified f on. * @param {Function} f - The function to call on every node of the * ReactElement tree represented by the specified element. * @private * @returns {ReactElement} */ _mapReactElement(element, f) { if (!element || !element.props || !element.type) { return element; } let mapped = f(element); if (mapped === element) { mapped = React.cloneElement( element, /* props */ undefined, ...React.Children.toArray(React.Children.map( element.props.children, function(element) { // eslint-disable-line no-shadow // eslint-disable-next-line no-invalid-this return this._mapReactElement(element, f); }, this))); } return mapped; } /** * Replaces the first ReactElement of a specific type found in a * specific ReactElement tree with a specific replacement * ReactElement. * * @param {ReactElement} element - The ReactElement tree to search * through and replace in. * @param {*} type - The type of the ReactElement to be replaced. * @param {ReactElement} replacement - The ReactElement to replace * the first ReactElement in element of the specified * type. * @private * @returns {ReactElement} */ _replaceFirstElementOfType(element, type, replacement) { // eslint-disable-next-line no-shadow return this._mapReactElement(element, element => { if (replacement && element.type === type) { /* eslint-disable no-param-reassign */ element = replacement; replacement = undefined; /* eslint-enable no-param-reassign */ } return element; }); } } export default translate(connect()(Dialog));