import React from 'react';
import {
Text,
Button,
Platform,
ScrollView,
StyleSheet,
View,
Picker,
} from 'react-native';
import * as Speech from 'expo-speech';
import Touchable from 'react-native-platform-touchable';
import HeadingText from '../components/HeadingText';
import { Colors } from '../constants';
import { TouchableProps } from 'react-native-svg';
const EXAMPLES = [
{ language: 'en', text: 'Hello world' },
{ language: 'es', text: 'Hola mundo' },
{ language: 'en', text: 'Charlie Cheever chased a chortling choosy child' },
{ language: 'en', text: 'Adam Perry ate a pear in pairs in Paris' },
];
const AmountControlButton: React.FunctionComponent<
TouchableProps & { title: string }
> = props => (
{props.title}
);
interface State {
selectedExample: { language: string; text: string };
inProgress: boolean;
paused: boolean;
pitch: number;
rate: number;
voiceList?: Array<{ name: string; identifier: string }>;
voice?: string;
}
export default class TextToSpeechScreen extends React.Component<{}, State> {
static navigationOptions = {
title: 'Speech',
};
readonly state: State = {
selectedExample: EXAMPLES[0],
inProgress: false,
paused: false,
pitch: 1,
rate: 0.75,
};
async componentDidMount() {
if (Platform.OS === 'ios') {
await this._loadAllVoices();
}
}
render() {
return (
Select a phrase
{EXAMPLES.map(this._renderExample)}
{Platform.OS === 'ios' && (
)}
{Platform.OS === 'ios' && this.state.voiceList && (
this.setState({ voice })}
>
{this.state.voiceList.map(voice => (
))}
)}
Pitch: {this.state.pitch.toFixed(2)}
/
Rate: {this.state.rate.toFixed(2)}
/
);
}
_speak = () => {
const start = () => {
this.setState({ inProgress: true });
};
const complete = () => {
this.state.inProgress &&
this.setState({ inProgress: false, paused: false });
};
Speech.speak(this.state.selectedExample.text, {
voice: this.state.voice,
language: this.state.selectedExample.language,
pitch: this.state.pitch,
rate: this.state.rate,
onStart: start,
onDone: complete,
onStopped: complete,
onError: complete,
});
}
_loadAllVoices = async () => {
const availableVoices = await Speech.getAvailableVoicesAsync();
this.setState({
voiceList: availableVoices,
voice: availableVoices[0].identifier,
});
}
_stop = () => {
Speech.stop();
}
_pause = async () => {
await Speech.pause();
this.setState({ paused: true });
}
_resume = () => {
Speech.resume();
this.setState({ paused: false });
}
_increasePitch = () => {
this.setState(state => ({
...state,
pitch: state.pitch + 0.1,
}));
}
_increaseRate = () => {
this.setState(state => ({
...state,
rate: state.rate + 0.1,
}));
}
_decreasePitch = () => {
this.setState(state => ({
...state,
pitch: state.pitch - 0.1,
}));
}
_decreaseRate = () => {
this.setState(state => ({
...state,
rate: state.rate - 0.1,
}));
}
_renderExample = (example: { language: string; text: string }, i: number) => {
const { selectedExample } = this.state;
const isSelected = selectedExample === example;
return (
this._selectExample(example)}
>
{example.text} ({example.language})
);
}
_selectExample = (example: { language: string; text: string }) => {
this.setState({ selectedExample: example });
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 10,
paddingBottom: 24,
},
separator: {
height: 1,
backgroundColor: '#eee',
marginTop: 0,
marginBottom: 15,
},
exampleText: {
fontSize: 15,
color: '#ccc',
marginVertical: 10,
},
examplesContainer: {
paddingTop: 15,
paddingBottom: 10,
paddingHorizontal: 20,
},
selectedExampleText: {
color: 'black',
},
resultText: {
padding: 20,
},
errorResultText: {
padding: 20,
color: 'red',
},
button: {
...Platform.select({
android: {
marginBottom: 10,
},
}),
},
controlText: {
fontSize: 16,
fontWeight: '500',
marginTop: 5,
textAlign: 'center',
},
controlRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 10,
},
});