Skip to content

Commit

Permalink
feat(voice): add locale prop & improve voice speech
Browse files Browse the repository at this point in the history
  • Loading branch information
Darlei Kroth committed May 22, 2020
1 parent 501f3e6 commit 1abd973
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 16 deletions.
92 changes: 82 additions & 10 deletions src/components/SpeechModal.js
Expand Up @@ -14,13 +14,23 @@ import ActionButton from './ActionButton';

type Props = {
background: String;
locale: 'en_us' | 'pt_br';
onRequestClose(results: String): void;
theme: 'light' | 'dark',
visible: Boolean;
}

function Speech(props: Props) {
const lang = helper.lang(props.locale);

const [loaded, setLoaded] = useState(false);
const [results, setResults] = useState('');
const [error, setError] = useState(false);
const [stopped, setStopped] = useState(false);

const listening = getListeningLabel(lang, loaded, error, stopped);
const placeholder = error || !loaded ? '...' : lang.speech_placeholder_label;

const savedResults = useRef('');

const backgroundStyle = { backgroundColor: helper.getModalBackground(props) };
Expand All @@ -31,8 +41,6 @@ function Speech(props: Props) {
fontWeight: results ? 'bold' : 'normal',
};

const lang = helper.lang();

const onRequestClose = () => {
props.onRequestClose && props.onRequestClose(savedResults.current);
};
Expand All @@ -50,14 +58,57 @@ function Speech(props: Props) {

useEffect(() => {
if (props.visible) {
setResults('');
savedResults.current = '';
Voice.start(lang.speech_voice_config);
onStart();
} else {
Voice.stop();
onStop();
}
}, [props.visible]);

const onStart = () => {
setResults('');
savedResults.current = '';

try {
Voice.onSpeechPartialResults = e => {
savedResults.current = e?.value[0]?.toLocaleLowerCase()?.trim();
setResults(savedResults.current);
};
Voice.onSpeechStart = e => {
setError(e.error);
setLoaded(!e.error);
};
Voice.onSpeechEnd = e => {
setStopped(true);
};
Voice.onSpeechError = e => {
setStopped(true);
};

Voice.start(lang.speech_voice_config);
} catch (e) {
setError(true);
}
};

const onStop = async () => {
try {
await Voice.stop();
await Voice.destroy();
Voice.removeAllListeners();
} catch (e) {
return null;
} finally {
setLoaded(false);
setError(false);
setStopped(false);
}
};

const onRestart = () => {
setStopped(false);
Voice.start(lang.speech_voice_config).catch(() => null);
};

const actionButton = () => {
return (
<ActionButton
Expand Down Expand Up @@ -87,11 +138,19 @@ function Speech(props: Props) {
<View style={[styles.card, backgroundStyle]} >
<View style={styles.body} >
<Text style={[styles.listening, titleStyle]} >
{ lang.speech_listening_label }
</Text>
<Text style={[styles.results, speechStyle]} >
{`"${results || lang.speech_placeholder_label}"`}
{ listening }
</Text>

{stopped ? (
<Text onPress={onRestart} style={[styles.results, speechStyle]} >
{`[ ${lang.speech_restart_label} ]`}
</Text>
) : (
<Text style={[styles.results, speechStyle]} >
{`"${results || placeholder}"`}
</Text>
)}

</View>
<View style={styles.button} >
{ actionButton() }
Expand All @@ -103,6 +162,19 @@ function Speech(props: Props) {
);
}

const getListeningLabel = (lng, l, e, s) => {
if (!l) {
return lng.speech_loading_label;
}
if (e) {
return lng.speech_failure_label;
}
if (s) {
return lng.speech_stoped_label;
}
return lng.speech_listening_label;
};

const styles = StyleSheet.create({
flex: {
alignItems: 'center',
Expand Down
4 changes: 2 additions & 2 deletions src/helper/index.js
Expand Up @@ -50,7 +50,7 @@ export default {
},

// Lang
lang() {
return lang(locale);
lang(val) {
return lang(locale, val);
},
};
14 changes: 11 additions & 3 deletions src/helper/lang.js
Expand Up @@ -3,7 +3,11 @@ const lang = {
input_placeholder: 'Search',

speech_listening_label: 'Listening...',
speech_loading_label: 'Starting...',
speech_failure_label: 'Something wrong, try again',
speech_stoped_label: 'Ready',
speech_placeholder_label: 'Say something...',
speech_restart_label: 'START LISTENING',
speech_voice_config: 'en-US',

dialog_remove_message: 'Remove item from history?',
Expand All @@ -14,7 +18,11 @@ const lang = {
input_placeholder: 'Pesquisar',

speech_listening_label: 'Ouvindo...',
speech_loading_label: 'Carregando...',
speech_failure_label: 'Algo deu errado, tente novamente',
speech_stoped_label: 'Pronto',
speech_placeholder_label: 'Fale alguma coisa...',
speech_restart_label: 'INICIAR NOVAMENTE',
speech_voice_config: 'pt-BR',

dialog_remove_message: 'Remover item do histórico?',
Expand All @@ -23,9 +31,9 @@ const lang = {
},
};

export default function(locale) {
const key = locale?.replace('-', '_')?.toLowerCase();
switch (key) {
export default function(locale, val) {
const key = val || locale;
switch (key.replace('-', '_')?.toLowerCase()) {
case 'pt_br':
return Object.freeze(Object.assign({}, lang.en_us, lang.pt_br));
case 'pt_us':
Expand Down
7 changes: 6 additions & 1 deletion src/index.js
Expand Up @@ -38,6 +38,10 @@ type Props = {
* Default value: `56`, considering a header with height `56`.
*/
historyTopOffset: Number;
/**
* The default value comes from the device system settings.
*/
locale: 'en_us' | 'pt_br';
/**
* Use this to save multiple saves of history. Default value: `default`.
*/
Expand Down Expand Up @@ -70,7 +74,7 @@ function SearchBar(props: Props) {
const searchTimeout = useRef(-1);

const storeKey = `searchbar:history:${props.storageSuffix}`;
const lang = helper.lang();
const lang = helper.lang(props.locale);

useEffect(() => {
AsyncStorage.getItem(storeKey)
Expand Down Expand Up @@ -381,6 +385,7 @@ function SearchBar(props: Props) {

<SpeechModal
background={props.background}
locale={props.locale}
onRequestClose={onSpeechResults}
theme={props.theme}
visible={speech}
Expand Down

0 comments on commit 1abd973

Please sign in to comment.