VoiceView.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import React, { Component, setState } from 'react';
  2. import { Text, TouchableOpacity, Alert, View, StyleSheet } from 'react-native';
  3. import Voice from '@react-native-community/voice';
  4. import Icon from 'react-native-vector-icons/FontAwesome';
  5. import { tr } from 'date-fns/locale';
  6. import Modal from 'react-native-modalbox';
  7. import { Icons } from '../globals';
  8. import { MapContext } from '../contexts/MapContext'
  9. import RNLocation from 'react-native-location';
  10. import { alternatives } from 'joi';
  11. class VoiceView extends Component {
  12. static contextType = MapContext;
  13. constructor(props) {
  14. super(props);
  15. Voice.onSpeechStart = this.onSpeechStart;
  16. Voice.onSpeechResults = this.onSpeechResults;
  17. Voice.onSpeechRecognized = this.onSpeechRecognized;
  18. Voice.onSpeechPartialResults = this.onSpeechPartialResults;
  19. Voice.onSpeechError = this.onSpeechError;
  20. Voice.onSpeechEnd = this.onSpeechEnd;
  21. this.modalRef = React.createRef();
  22. this.state = {
  23. recognized: false,
  24. started: false,
  25. ended: false,
  26. actionText: '',
  27. action: null,
  28. results: [],
  29. partialResults: [],
  30. error: ''
  31. }
  32. }
  33. addLandmark = (type) => {
  34. this.modalRef.current.close();
  35. console.log(this.context.mapState.location.latitude)
  36. console.log(this.context.mapState.location.longitude)
  37. this.props.changeSelectedLandmark({icon: type, title: 'New landmark', latitude: this.context.mapState.location.latitude, longitude: this.context.mapState.location.longitude,});
  38. this.props.editLandmark();
  39. }
  40. open() {
  41. this.modalRef.current.open();
  42. this._startRecognizing();
  43. }
  44. close() {
  45. this.modalRef.current.close();
  46. this._stopRecognizing();
  47. }
  48. stop() {
  49. this._stopRecognizing()
  50. }
  51. componentWillUnmount() {
  52. this._stopRecognizing();
  53. }
  54. onSpeechStart = (e) => {
  55. this.setState({
  56. started: true
  57. });
  58. };
  59. onSpeechRecognized = (e) => {
  60. this.setState({
  61. recognized: true
  62. });
  63. };
  64. onSpeechResults = (e) => {
  65. this.setState({
  66. results: e.value
  67. });
  68. let requestedAction = '';
  69. if ((e.value[0].includes("add") || e.value[0].includes("ad") || e.value[0].includes("had"))) {
  70. if (e.value[0].includes('landmark')) {
  71. requestedAction = 'Add Landmark'
  72. this.state.action = () => this.addLandmark();
  73. }
  74. if (Object.keys(Icons).some(icon => {return e.value[0].includes(icon)})) {
  75. const requestedTypes = Object.keys(Icons).filter(icon => {return e.value[0].includes(icon)})
  76. requestedAction = 'Add ' + requestedTypes[0].toString();
  77. this.state.action = () => this.addLandmark(requestedTypes[0]);
  78. }
  79. if (e.value[0].includes('road') && e.value[0].includes('block')) {
  80. requestedAction = 'Add ' + 'roadblock';
  81. this.state.action = () => this.addLandmark('roadblock');
  82. }
  83. }
  84. if (e.value) {
  85. }
  86. this.setState({
  87. actionText: requestedAction
  88. });
  89. };
  90. onSpeechPartialResults = (e) => {
  91. this.setState({
  92. partialResults: e.value
  93. });
  94. };
  95. onSpeechError = (e) => {
  96. this.setState({
  97. error: e.value
  98. })
  99. };
  100. onSpeechEnd = (e) => {
  101. this.setState({
  102. ended: true
  103. })
  104. }
  105. _startRecognizing = async (e) => {
  106. this.setState({
  107. started: false,
  108. ended: false,
  109. recognized: false,
  110. error: '',
  111. results: [],
  112. partialResults: [],
  113. })
  114. try {
  115. await Voice.start('en-US')
  116. } catch (error) {
  117. }
  118. }
  119. _stopRecognizing = async (e) => {
  120. Voice.destroy().then(Voice.removeAllListeners);
  121. }
  122. render() {
  123. return (
  124. <Modal position='bottom' style={styles.voiceModal} ref={this.modalRef} onClosed={() => Voice.destroy().then(Voice.removeAllListeners)}>
  125. <TouchableOpacity style={{alignSelf: 'flex-end', margin: 10}} onPress={() => this.modalRef.current.close()}><Icon size={20} color='white' name='times'/></TouchableOpacity>
  126. {this.state.started && !this.state.ended ? <Text style={{fontSize: 20, margin: 20, color: 'white'}}>Listening...</Text> : null}
  127. {this.state.results.length ? <Text style={{fontSize: 20, margin: 20, color: 'white'}}>We heard: {this.state.results[0]}</Text> : null}
  128. {this.state.partialResults.length > 0 && !this.state.ended ? <Text style={{fontSize: 15, marginHorizontal: 20, color: 'white'}}>{this.state.partialResults[0]}</Text> : null}
  129. {this.state.ended ?
  130. <View style={styles.btnContainer}>
  131. <TouchableOpacity onPress={this._startRecognizing}><Icon size={20} color='white' name='refresh'/></TouchableOpacity>
  132. {this.state.actionText ?
  133. <TouchableOpacity onPress={this.state.action}><Text style={{color: 'white', fontSize: 20}}>{this.state.actionText} - Confirm?</Text></TouchableOpacity> :
  134. <Text style={{fontSize: 20,color: 'white'}}>No valid action was percieved.</Text>}
  135. </View>
  136. : null}
  137. </Modal>
  138. )
  139. }
  140. }
  141. const styles = StyleSheet.create({
  142. voiceModal: {
  143. backgroundColor: '#df3f3f',
  144. height: 200,
  145. },
  146. btnContainer: {
  147. paddingTop: 20,
  148. borderTopWidth: 1,
  149. borderColor: 'lightgrey',
  150. flexDirection: 'row',
  151. justifyContent: 'space-between',
  152. alignItems: 'center',
  153. position: 'absolute',
  154. width: 300,
  155. bottom: 30,
  156. right: 30,
  157. }
  158. })
  159. export default VoiceView;