123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- import React, { Component, setState } from 'react';
- import { Text, TouchableOpacity, Alert, View, StyleSheet } from 'react-native';
- import Voice from '@react-native-community/voice';
- import Icon from 'react-native-vector-icons/FontAwesome';
- import { tr } from 'date-fns/locale';
- import Modal from 'react-native-modalbox';
- import { Icons } from '../globals';
- import { MapContext } from '../contexts/MapContext'
- import RNLocation from 'react-native-location';
- import { alternatives } from 'joi';
- class VoiceView extends Component {
- static contextType = MapContext;
- constructor(props) {
- super(props);
- Voice.onSpeechStart = this.onSpeechStart;
- Voice.onSpeechResults = this.onSpeechResults;
- Voice.onSpeechRecognized = this.onSpeechRecognized;
- Voice.onSpeechPartialResults = this.onSpeechPartialResults;
- Voice.onSpeechError = this.onSpeechError;
- Voice.onSpeechEnd = this.onSpeechEnd;
- this.modalRef = React.createRef();
- this.state = {
- recognized: false,
- started: false,
- ended: false,
- actionText: '',
- action: null,
- results: [],
- partialResults: [],
- error: ''
- }
- }
- addLandmark = (type) => {
- this.modalRef.current.close();
- console.log(this.context.mapState.location.latitude)
- console.log(this.context.mapState.location.longitude)
- this.props.changeSelectedLandmark({icon: type, title: 'New landmark', latitude: this.context.mapState.location.latitude, longitude: this.context.mapState.location.longitude,});
- this.props.editLandmark();
- }
- open() {
- this.modalRef.current.open();
- this._startRecognizing();
- }
- close() {
- this.modalRef.current.close();
- this._stopRecognizing();
- }
- stop() {
- this._stopRecognizing()
- }
- componentWillUnmount() {
- this._stopRecognizing();
- }
-
- onSpeechStart = (e) => {
- this.setState({
- started: true
- });
- };
- onSpeechRecognized = (e) => {
- this.setState({
- recognized: true
- });
- };
- onSpeechResults = (e) => {
- this.setState({
- results: e.value
- });
- let requestedAction = '';
- if ((e.value[0].includes("add") || e.value[0].includes("ad") || e.value[0].includes("had"))) {
- if (e.value[0].includes('landmark')) {
- requestedAction = 'Add Landmark'
- this.state.action = () => this.addLandmark();
- }
- if (Object.keys(Icons).some(icon => {return e.value[0].includes(icon)})) {
- const requestedTypes = Object.keys(Icons).filter(icon => {return e.value[0].includes(icon)})
- requestedAction = 'Add ' + requestedTypes[0].toString();
- this.state.action = () => this.addLandmark(requestedTypes[0]);
- }
- if (e.value[0].includes('road') && e.value[0].includes('block')) {
- requestedAction = 'Add ' + 'roadblock';
- this.state.action = () => this.addLandmark('roadblock');
- }
- }
- if (e.value) {
-
- }
- this.setState({
- actionText: requestedAction
- });
- };
- onSpeechPartialResults = (e) => {
- this.setState({
- partialResults: e.value
- });
- };
- onSpeechError = (e) => {
- this.setState({
- error: e.value
- })
- };
- onSpeechEnd = (e) => {
- this.setState({
- ended: true
- })
- }
- _startRecognizing = async (e) => {
- this.setState({
- started: false,
- ended: false,
- recognized: false,
- error: '',
- results: [],
- partialResults: [],
- })
- try {
- await Voice.start('en-US')
- } catch (error) {
- }
- }
- _stopRecognizing = async (e) => {
- Voice.destroy().then(Voice.removeAllListeners);
- }
- render() {
- return (
- <Modal position='bottom' style={styles.voiceModal} ref={this.modalRef} onClosed={() => Voice.destroy().then(Voice.removeAllListeners)}>
- <TouchableOpacity style={{alignSelf: 'flex-end', margin: 10}} onPress={() => this.modalRef.current.close()}><Icon size={20} color='white' name='times'/></TouchableOpacity>
- {this.state.started && !this.state.ended ? <Text style={{fontSize: 20, margin: 20, color: 'white'}}>Listening...</Text> : null}
- {this.state.results.length ? <Text style={{fontSize: 20, margin: 20, color: 'white'}}>We heard: {this.state.results[0]}</Text> : null}
- {this.state.partialResults.length > 0 && !this.state.ended ? <Text style={{fontSize: 15, marginHorizontal: 20, color: 'white'}}>{this.state.partialResults[0]}</Text> : null}
- {this.state.ended ?
- <View style={styles.btnContainer}>
- <TouchableOpacity onPress={this._startRecognizing}><Icon size={20} color='white' name='refresh'/></TouchableOpacity>
- {this.state.actionText ?
- <TouchableOpacity onPress={this.state.action}><Text style={{color: 'white', fontSize: 20}}>{this.state.actionText} - Confirm?</Text></TouchableOpacity> :
- <Text style={{fontSize: 20,color: 'white'}}>No valid action was percieved.</Text>}
- </View>
- : null}
- </Modal>
- )
- }
- }
- const styles = StyleSheet.create({
- voiceModal: {
- backgroundColor: '#df3f3f',
- height: 200,
- },
- btnContainer: {
- paddingTop: 20,
- borderTopWidth: 1,
- borderColor: 'lightgrey',
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- position: 'absolute',
- width: 300,
- bottom: 30,
- right: 30,
- }
- })
- export default VoiceView;
|