UNPKG

3.21 kBPlain TextView Raw
1import { UnavailabilityError } from '@unimodules/core';
2import { NativeEventEmitter } from 'react-native';
3
4import ExponentSpeech from './ExponentSpeech';
5import { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice } from './Speech.types';
6
7const SpeechEventEmitter = ExponentSpeech && new NativeEventEmitter(ExponentSpeech);
8
9export { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice };
10
11const _CALLBACKS = {};
12let _nextCallbackId = 1;
13let _didSetListeners = false;
14
15function _unregisterListenersIfNeeded() {
16 if (Object.keys(_CALLBACKS).length === 0) {
17 removeSpeakingListener('Exponent.speakingStarted');
18 removeSpeakingListener('Exponent.speakingDone');
19 removeSpeakingListener('Exponent.speakingStopped');
20 removeSpeakingListener('Exponent.speakingError');
21 _didSetListeners = false;
22 }
23}
24
25function _registerListenersIfNeeded() {
26 if (_didSetListeners) return;
27 _didSetListeners = true;
28 setSpeakingListener('Exponent.speakingStarted', ({ id }) => {
29 const options = _CALLBACKS[id];
30 if (options && options.onStart) {
31 options.onStart();
32 }
33 });
34 setSpeakingListener('Exponent.speakingDone', ({ id }) => {
35 const options = _CALLBACKS[id];
36 if (options && options.onDone) {
37 options.onDone();
38 }
39 delete _CALLBACKS[id];
40 _unregisterListenersIfNeeded();
41 });
42 setSpeakingListener('Exponent.speakingStopped', ({ id }) => {
43 const options = _CALLBACKS[id];
44 if (options && options.onStopped) {
45 options.onStopped();
46 }
47 delete _CALLBACKS[id];
48 _unregisterListenersIfNeeded();
49 });
50 setSpeakingListener('Exponent.speakingError', ({ id, error }) => {
51 const options = _CALLBACKS[id];
52 if (options && options.onError) {
53 options.onError(new Error(error));
54 }
55 delete _CALLBACKS[id];
56 _unregisterListenersIfNeeded();
57 });
58}
59
60export function speak(text: string, options: SpeechOptions = {}) {
61 const id = _nextCallbackId++;
62 _CALLBACKS[id] = options;
63 _registerListenersIfNeeded();
64 ExponentSpeech.speak(String(id), text, options);
65}
66
67export async function getAvailableVoicesAsync(): Promise<Voice[]> {
68 if (!ExponentSpeech.getVoices) {
69 throw new UnavailabilityError('Speech', 'getVoices');
70 }
71 return ExponentSpeech.getVoices();
72}
73
74export async function isSpeakingAsync(): Promise<boolean> {
75 return ExponentSpeech.isSpeaking();
76}
77
78export async function stop(): Promise<void> {
79 return ExponentSpeech.stop();
80}
81
82export async function pause(): Promise<void> {
83 if (!ExponentSpeech.pause) {
84 throw new UnavailabilityError('Speech', 'pause');
85 }
86 return ExponentSpeech.pause();
87}
88
89export async function resume(): Promise<void> {
90 if (!ExponentSpeech.resume) {
91 throw new UnavailabilityError('Speech', 'resume');
92 }
93
94 return ExponentSpeech.resume();
95}
96
97function setSpeakingListener(eventName, callback) {
98 if (SpeechEventEmitter.listeners(eventName).length > 0) {
99 SpeechEventEmitter.removeAllListeners(eventName);
100 }
101 SpeechEventEmitter.addListener(eventName, callback);
102}
103
104function removeSpeakingListener(eventName) {
105 SpeechEventEmitter.removeAllListeners(eventName);
106}
107
108export const maxSpeechInputLength: number = ExponentSpeech.maxSpeechInputLength || Number.MAX_VALUE;