@ -1,12 +1,31 @@
import PropTypes from 'prop-types' ;
import React from 'react' ;
import { TextInput } from 'react-native' ;
import { StyleSheet , TextInput } from 'react-native' ;
import Prompt from 'react-native-prompt' ;
import { connect } from 'react-redux' ;
import { translate } from '../../i18n' ;
import { LoadingIndicator } from '../../react' ;
import { set } from '../../redux' ;
import AbstractDialog from './AbstractDialog' ;
import styles from './styles' ;
/ * *
* The value of the style property { @ link _TAG _KEY } which identifies the
* OK / submit button of < tt > Prompt < / t t > .
* /
const _SUBMIT _TEXT _TAG _VALUE = '_SUBMIT_TEXT_TAG_VALUE' ;
/ * *
* The name of the style property which identifies ancestors of < tt > Prompt < / t t >
* such as its OK / submit button for the purposes of workarounds implemented by
* < tt > Dialog < / t t > .
*
* XXX The value may trigger a react - native warning in the Debug configuration
* but , unfortunately , I couldn 't find a value that wouldn' t .
* /
const _TAG _KEY = '_TAG_KEY' ;
/ * *
* Implements < tt > AbstractDialog < / t t > o n r e a c t - n a t i v e u s i n g < t t > P r o m p t < / t t > .
@ -37,7 +56,6 @@ class Dialog extends AbstractDialog {
bodyKey ,
cancelDisabled ,
cancelTitleKey = 'dialog.Cancel' ,
children ,
okDisabled ,
okTitleKey = 'dialog.Ok' ,
t ,
@ -45,30 +63,82 @@ class Dialog extends AbstractDialog {
titleString
} = this . props ;
/* eslint-disable react/jsx-wrap-multilines */
let element
= < Prompt
cancelText = { cancelDisabled ? undefined : t ( cancelTitleKey ) }
const cancelButtonTextStyle
= cancelDisabled ? styles . disabledButtonText : styles . buttonText ;
let submitButtonTextStyle
= okDisabled ? styles . disabledButtonText : styles . buttonText ;
submitButtonTextStyle = {
... submitButtonTextStyle ,
[ _TAG _KEY ] : _SUBMIT _TEXT _TAG _VALUE
} ;
// eslint-disable-next-line no-extra-parens
let element = (
< Prompt
cancelButtonTextStyle = { cancelButtonTextStyle }
cancelText = { t ( cancelTitleKey ) }
onCancel = { this . _onCancel }
onSubmit = { this . _onSubmit }
placeholder = { t ( bodyKey ) }
submitText = { okDisabled ? undefined : t ( okTitleKey ) }
submitButtonTextStyle = { submitButtonTextStyle }
submitText = { t ( okTitleKey ) }
title = { titleString || t ( titleKey ) }
visible = { true } / > ;
/* 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 ) ;
}
visible = { true } / >
) ;
// XXX The following implements workarounds with knowledge of
// react-native-prompt/Prompt's implementation.
// eslint-disable-next-line no-extra-parens, new-cap
element = ( new ( element . type ) ( element . props ) ) . render ( ) ;
let { children } = this . props ;
children = React . Children . count ( children ) ? children : undefined ;
// eslint-disable-next-line no-shadow
element = this . _mapReactElement ( element , element => {
// * If this Dialog has children, they are to be rendered instead of
// Prompt's TextInput.
if ( element . type === TextInput ) {
if ( children ) {
element = children ; // eslint-disable-line no-param-reassign
children = undefined ;
}
} else {
let { style } = element . props ;
if ( style
&& ( style = StyleSheet . flatten ( style ) )
&& _TAG _KEY in style ) {
switch ( style [ _TAG _KEY ] ) {
case _SUBMIT _TEXT _TAG _VALUE :
if ( this . state . submitting ) {
// * If this Dialog is submitting, render a
// LoadingIndicator.
return (
< LoadingIndicator
color = { submitButtonTextStyle . color }
size = { 'small' } / >
) ;
}
break ;
}
// eslint-disable-next-line no-param-reassign
element
= React . cloneElement (
element ,
/* props */ {
style : set ( style , _TAG _KEY , undefined )
} ,
... React . Children . toArray ( element . props . children ) ) ;
}
}
return element ;
} ) ;
return element ;
}
@ -108,36 +178,6 @@ class Dialog extends AbstractDialog {
return mapped ;
}
/ * *
* Replaces the first < tt > ReactElement < / t t > o f a s p e c i f i c t y p e f o u n d i n a
* specific < tt > ReactElement < / t t > t r e e w i t h a s p e c i f i c r e p l a c e m e n t
* < tt > ReactElement < / t t > .
*
* @ param { ReactElement } element - The < tt > ReactElement < / t t > t r e e t o s e a r c h
* through and replace in .
* @ param { * } type - The type of the < tt > ReactElement < / t t > t o b e r e p l a c e d .
* @ param { ReactElement } replacement - The < tt > ReactElement < / t t > t o r e p l a c e
* the first < tt > ReactElement < / t t > i n < t t > e l e m e n t < / t t > o f t h e s p e c i f i e d
* < tt > type < / t t > .
* @ 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 ) ) ;