@@ -18,7 +18,7 @@ import {
1818} from './components' ;
1919import Recognition from './recognition' ;
2020import { ChatIcon , CloseIcon , SubmitIcon , MicIcon } from './icons' ;
21- import { isMobile } from './utils' ;
21+ import { isMobile , speakFn } from './utils' ;
2222
2323class ChatBot extends Component {
2424 /* istanbul ignore next */
@@ -39,7 +39,7 @@ class ChatBot extends Component {
3939 recognitionEnable : props . recognitionEnable && Recognition . isSupported ( ) ,
4040 defaultUserSettings : { } ,
4141 } ;
42-
42+ this . speak = speakFn ( props . speechSynthesis ) ;
4343 this . renderStep = this . renderStep . bind ( this ) ;
4444 this . getTriggeredStep = this . getTriggeredStep . bind ( this ) ;
4545 this . generateRenderedStepsById = this . generateRenderedStepsById . bind ( this ) ;
@@ -95,24 +95,22 @@ class ChatBot extends Component {
9595 steps [ firstStep . id ] . message = firstStep . message ;
9696 }
9797
98- const {
99- currentStep,
100- previousStep,
101- previousSteps,
102- renderedSteps,
103- } = storage . getData ( {
104- cacheName,
105- cache,
106- firstStep,
107- steps,
108- } , ( ) => {
109- // focus input if last step cached is a user step
110- this . setState ( { disabled : false } , ( ) => {
111- if ( enableMobileAutoFocus || ! isMobile ( ) ) {
112- this . input . focus ( ) ;
113- }
114- } ) ;
115- } ) ;
98+ const { currentStep, previousStep, previousSteps, renderedSteps } = storage . getData (
99+ {
100+ cacheName,
101+ cache,
102+ firstStep,
103+ steps,
104+ } ,
105+ ( ) => {
106+ // focus input if last step cached is a user step
107+ this . setState ( { disabled : false } , ( ) => {
108+ if ( enableMobileAutoFocus || ! isMobile ( ) ) {
109+ this . input . focus ( ) ;
110+ }
111+ } ) ;
112+ } ,
113+ ) ;
116114
117115 this . setState ( {
118116 currentStep,
@@ -210,12 +208,7 @@ class ChatBot extends Component {
210208
211209 triggerNextStep ( data ) {
212210 const { enableMobileAutoFocus } = this . props ;
213- const {
214- defaultUserSettings,
215- previousSteps,
216- renderedSteps,
217- steps,
218- } = this . state ;
211+ const { defaultUserSettings, previousSteps, renderedSteps, steps } = this . state ;
219212 let { currentStep, previousStep } = this . state ;
220213 const isEnd = currentStep . end ;
221214
@@ -406,15 +399,18 @@ class ChatBot extends Component {
406399 renderedSteps . push ( currentStep ) ;
407400 previousSteps . push ( currentStep ) ;
408401
409- this . setState ( {
410- currentStep,
411- renderedSteps,
412- previousSteps,
413- disabled : true ,
414- inputValue : '' ,
415- } , ( ) => {
416- this . input . blur ( ) ;
417- } ) ;
402+ this . setState (
403+ {
404+ currentStep,
405+ renderedSteps,
406+ previousSteps,
407+ disabled : true ,
408+ inputValue : '' ,
409+ } ,
410+ ( ) => {
411+ this . input . blur ( ) ;
412+ } ,
413+ ) ;
418414 }
419415 }
420416
@@ -425,23 +421,29 @@ class ChatBot extends Component {
425421 const value = inputValue ;
426422
427423 if ( typeof result !== 'boolean' || ! result ) {
428- this . setState ( {
429- inputValue : result . toString ( ) ,
430- inputInvalid : true ,
431- disabled : true ,
432- } , ( ) => {
433- setTimeout ( ( ) => {
434- this . setState ( {
435- inputValue : value ,
436- inputInvalid : false ,
437- disabled : false ,
438- } , ( ) => {
439- if ( enableMobileAutoFocus || ! isMobile ( ) ) {
440- this . input . focus ( ) ;
441- }
442- } ) ;
443- } , 2000 ) ;
444- } ) ;
424+ this . setState (
425+ {
426+ inputValue : result . toString ( ) ,
427+ inputInvalid : true ,
428+ disabled : true ,
429+ } ,
430+ ( ) => {
431+ setTimeout ( ( ) => {
432+ this . setState (
433+ {
434+ inputValue : value ,
435+ inputInvalid : false ,
436+ disabled : false ,
437+ } ,
438+ ( ) => {
439+ if ( enableMobileAutoFocus || ! isMobile ( ) ) {
440+ this . input . focus ( ) ;
441+ }
442+ } ,
443+ ) ;
444+ } , 2000 ) ;
445+ } ,
446+ ) ;
445447
446448 return true ;
447449 }
@@ -466,6 +468,7 @@ class ChatBot extends Component {
466468 customStyle,
467469 hideBotAvatar,
468470 hideUserAvatar,
471+ speechSynthesis,
469472 } = this . props ;
470473 const { options, component, asMessage } = step ;
471474 const steps = this . generateRenderedStepsById ( ) ;
@@ -475,10 +478,12 @@ class ChatBot extends Component {
475478 return (
476479 < CustomStep
477480 key = { index }
481+ speak = { this . speak }
478482 step = { step }
479483 steps = { steps }
480484 style = { customStyle }
481485 previousStep = { previousStep }
486+ previousValue = { previousStep . value }
482487 triggerNextStep = { this . triggerNextStep }
483488 />
484489 ) ;
@@ -489,6 +494,8 @@ class ChatBot extends Component {
489494 < OptionsStep
490495 key = { index }
491496 step = { step }
497+ speak = { this . speak }
498+ previousValue = { previousStep . value }
492499 triggerNextStep = { this . triggerNextStep }
493500 bubbleOptionStyle = { bubbleOptionStyle }
494501 />
@@ -500,13 +507,15 @@ class ChatBot extends Component {
500507 key = { index }
501508 step = { step }
502509 steps = { steps }
510+ speak = { this . speak }
503511 previousStep = { previousStep }
504512 previousValue = { previousStep . value }
505513 triggerNextStep = { this . triggerNextStep }
506514 avatarStyle = { avatarStyle }
507515 bubbleStyle = { bubbleStyle }
508516 hideBotAvatar = { hideBotAvatar }
509517 hideUserAvatar = { hideUserAvatar }
518+ speechSynthesis = { speechSynthesis }
510519 isFirst = { this . isFirstPosition ( step ) }
511520 isLast = { this . isLastPosition ( step ) }
512521 />
@@ -558,8 +567,9 @@ class ChatBot extends Component {
558567 const icon =
559568 ( _ . isEmpty ( inputValue ) || speaking ) && recognitionEnable ? < MicIcon /> : < SubmitIcon /> ;
560569
561- const inputPlaceholder = speaking ? recognitionPlaceholder :
562- currentStep . placeholder || placeholder ;
570+ const inputPlaceholder = speaking
571+ ? recognitionPlaceholder
572+ : currentStep . placeholder || placeholder ;
563573
564574 const inputAttributesOverride = currentStep . inputAttributes || inputAttributes ;
565575
@@ -613,18 +623,19 @@ class ChatBot extends Component {
613623 { ...inputAttributesOverride }
614624 />
615625 ) }
616- { ! currentStep . hideInput && ! hideSubmitButton && (
617- < SubmitButton
618- className = "rsc-submit-button"
619- style = { submitButtonStyle }
620- onClick = { this . handleSubmitButton }
621- invalid = { inputInvalid }
622- disabled = { disabled }
623- speaking = { speaking }
624- >
625- { icon }
626- </ SubmitButton >
627- ) }
626+ { ! currentStep . hideInput &&
627+ ! hideSubmitButton && (
628+ < SubmitButton
629+ className = "rsc-submit-button"
630+ style = { submitButtonStyle }
631+ onClick = { this . handleSubmitButton }
632+ invalid = { inputInvalid }
633+ disabled = { disabled }
634+ speaking = { speaking }
635+ >
636+ { icon }
637+ </ SubmitButton >
638+ ) }
628639 </ Footer >
629640 </ ChatBotContainer >
630641 </ div >
@@ -670,6 +681,11 @@ ChatBot.propTypes = {
670681 userDelay : PropTypes . number ,
671682 width : PropTypes . string ,
672683 height : PropTypes . string ,
684+ speechSynthesis : PropTypes . shape ( {
685+ enable : PropTypes . bool ,
686+ lang : PropTypes . string ,
687+ voice : PropTypes . instanceOf ( window . SpeechSynthesisVoice ) ,
688+ } ) ,
673689} ;
674690
675691ChatBot . defaultProps = {
@@ -701,6 +717,11 @@ ChatBot.defaultProps = {
701717 recognitionEnable : false ,
702718 recognitionLang : 'en' ,
703719 recognitionPlaceholder : 'Listening ...' ,
720+ speechSynthesis : {
721+ enable : false ,
722+ lang : 'en' ,
723+ voice : null ,
724+ } ,
704725 style : { } ,
705726 submitButtonStyle : { } ,
706727 toggleFloating : undefined ,
0 commit comments