expo-speech 9.2.0 → 10.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,39 @@
1
1
  export declare type SpeechEventCallback = (this: SpeechSynthesisUtterance, ev: SpeechSynthesisEvent) => any;
2
2
  export declare type SpeechOptions = {
3
+ /**
4
+ * The code of a language that should be used to read the `text`, refer to IETF BCP 47 to see
5
+ * valid codes.
6
+ */
3
7
  language?: string;
8
+ /**
9
+ * Pitch of the voice to speak `text`. `1.0` is the normal pitch.
10
+ */
4
11
  pitch?: number;
12
+ /**
13
+ * Rate of the voice to speak `text`. `1.0` is the normal rate.
14
+ */
5
15
  rate?: number;
16
+ /**
17
+ * A callback that is invoked when speaking starts.
18
+ */
6
19
  onStart?: () => void | SpeechEventCallback;
20
+ /**
21
+ * A callback that is invoked when speaking is stopped by calling `Speech.stop()`.
22
+ */
7
23
  onStopped?: () => void | SpeechEventCallback;
24
+ /**
25
+ * A callback that is invoked when speaking finishes.
26
+ */
8
27
  onDone?: () => void | SpeechEventCallback;
28
+ /**
29
+ * __(Android only).__ A callback that is invoked when an error occurred while speaking.
30
+ * @param error
31
+ */
9
32
  onError?: (error: Error) => void | SpeechEventCallback;
10
33
  volume?: number;
34
+ /**
35
+ * Voice identifier.
36
+ */
11
37
  voice?: string;
12
38
  _voiceIndex?: number;
13
39
  onBoundary?: SpeechEventCallback | null;
@@ -15,14 +41,32 @@ export declare type SpeechOptions = {
15
41
  onPause?: SpeechEventCallback | null;
16
42
  onResume?: SpeechEventCallback | null;
17
43
  };
44
+ /**
45
+ * Enum representing the voice quality.
46
+ */
18
47
  export declare enum VoiceQuality {
19
48
  Default = "Default",
20
49
  Enhanced = "Enhanced"
21
50
  }
51
+ /**
52
+ * Object describing the available voices on the device.
53
+ */
22
54
  export declare type Voice = {
55
+ /**
56
+ * Voice unique identifier.
57
+ */
23
58
  identifier: string;
59
+ /**
60
+ * Voice name.
61
+ */
24
62
  name: string;
63
+ /**
64
+ * Voice quality.
65
+ */
25
66
  quality: VoiceQuality;
67
+ /**
68
+ * Voice language.
69
+ */
26
70
  language: string;
27
71
  };
28
72
  export declare type WebVoice = Voice & {
@@ -1,3 +1,7 @@
1
+ // @needsAudit
2
+ /**
3
+ * Enum representing the voice quality.
4
+ */
1
5
  export var VoiceQuality;
2
6
  (function (VoiceQuality) {
3
7
  VoiceQuality["Default"] = "Default";
@@ -1 +1 @@
1
- {"version":3,"file":"Speech.types.js","sourceRoot":"","sources":["../src/Speech/Speech.types.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,mCAAmB,CAAA;IACnB,qCAAqB,CAAA;AACvB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB","sourcesContent":["export type SpeechEventCallback = (this: SpeechSynthesisUtterance, ev: SpeechSynthesisEvent) => any;\n\nexport type SpeechOptions = {\n language?: string;\n pitch?: number;\n rate?: number;\n onStart?: () => void | SpeechEventCallback;\n onStopped?: () => void | SpeechEventCallback;\n onDone?: () => void | SpeechEventCallback;\n onError?: (error: Error) => void | SpeechEventCallback;\n\n volume?: number;\n voice?: string;\n _voiceIndex?: number;\n onBoundary?: SpeechEventCallback | null;\n onMark?: SpeechEventCallback | null;\n onPause?: SpeechEventCallback | null;\n onResume?: SpeechEventCallback | null;\n};\n\nexport enum VoiceQuality {\n Default = 'Default',\n Enhanced = 'Enhanced',\n}\n\nexport type Voice = {\n identifier: string;\n name: string;\n quality: VoiceQuality;\n language: string;\n};\n\nexport type WebVoice = Voice & {\n isDefault: boolean;\n localService: boolean;\n name: string;\n voiceURI: string;\n};\n"]}
1
+ {"version":3,"file":"Speech.types.js","sourceRoot":"","sources":["../src/Speech/Speech.types.ts"],"names":[],"mappings":"AA8CA,cAAc;AACd;;GAEG;AACH,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,mCAAmB,CAAA;IACnB,qCAAqB,CAAA;AACvB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB","sourcesContent":["export type SpeechEventCallback = (this: SpeechSynthesisUtterance, ev: SpeechSynthesisEvent) => any;\n\n// @needsAudit @docsMissing\nexport type SpeechOptions = {\n /**\n * The code of a language that should be used to read the `text`, refer to IETF BCP 47 to see\n * valid codes.\n */\n language?: string;\n /**\n * Pitch of the voice to speak `text`. `1.0` is the normal pitch.\n */\n pitch?: number;\n /**\n * Rate of the voice to speak `text`. `1.0` is the normal rate.\n */\n rate?: number;\n /**\n * A callback that is invoked when speaking starts.\n */\n onStart?: () => void | SpeechEventCallback;\n /**\n * A callback that is invoked when speaking is stopped by calling `Speech.stop()`.\n */\n onStopped?: () => void | SpeechEventCallback;\n /**\n * A callback that is invoked when speaking finishes.\n */\n onDone?: () => void | SpeechEventCallback;\n /**\n * __(Android only).__ A callback that is invoked when an error occurred while speaking.\n * @param error\n */\n onError?: (error: Error) => void | SpeechEventCallback;\n volume?: number;\n /**\n * Voice identifier.\n */\n voice?: string;\n _voiceIndex?: number;\n onBoundary?: SpeechEventCallback | null;\n onMark?: SpeechEventCallback | null;\n onPause?: SpeechEventCallback | null;\n onResume?: SpeechEventCallback | null;\n};\n\n// @needsAudit\n/**\n * Enum representing the voice quality.\n */\nexport enum VoiceQuality {\n Default = 'Default',\n Enhanced = 'Enhanced',\n}\n\n// @needsAudit\n/**\n * Object describing the available voices on the device.\n */\nexport type Voice = {\n /**\n * Voice unique identifier.\n */\n identifier: string;\n /**\n * Voice name.\n */\n name: string;\n /**\n * Voice quality.\n */\n quality: VoiceQuality;\n /**\n * Voice language.\n */\n language: string;\n};\n\n// @docsMissing\nexport type WebVoice = Voice & {\n isDefault: boolean;\n localService: boolean;\n name: string;\n voiceURI: string;\n};\n"]}
@@ -1,9 +1,9 @@
1
1
  // Copyright 2015-present 650 Industries. All rights reserved.
2
2
 
3
- #import <UMCore/UMExportedModule.h>
4
- #import <UMCore/UMModuleRegistryConsumer.h>
5
- #import <UMCore/UMEventEmitter.h>
3
+ #import <ExpoModulesCore/EXExportedModule.h>
4
+ #import <ExpoModulesCore/EXModuleRegistryConsumer.h>
5
+ #import <ExpoModulesCore/EXEventEmitter.h>
6
6
 
7
- @interface EXSpeech : UMExportedModule <UMEventEmitter, UMModuleRegistryConsumer>
7
+ @interface EXSpeech : EXExportedModule <EXEventEmitter, EXModuleRegistryConsumer>
8
8
 
9
9
  @end
@@ -2,7 +2,7 @@
2
2
 
3
3
  #import <AVFoundation/AVFoundation.h>
4
4
 
5
- #import <UMCore/UMEventEmitterService.h>
5
+ #import <ExpoModulesCore/EXEventEmitterService.h>
6
6
  #import <EXSpeech/EXSpeech.h>
7
7
 
8
8
  @interface EXSpeechUtteranceWithId : AVSpeechUtterance
@@ -32,15 +32,15 @@ static NSString *const INVALID_VOICE_ERROR_MSG = @"Cannot find voice with identi
32
32
  @interface EXSpeech () <AVSpeechSynthesizerDelegate>
33
33
 
34
34
  @property (nonatomic, strong) AVSpeechSynthesizer *synthesizer;
35
- @property (nonatomic, weak) UMModuleRegistry *moduleRegistry;
35
+ @property (nonatomic, weak) EXModuleRegistry *moduleRegistry;
36
36
 
37
37
  @end
38
38
 
39
39
  @implementation EXSpeech
40
40
 
41
- UM_EXPORT_MODULE(ExponentSpeech)
41
+ EX_EXPORT_MODULE(ExponentSpeech)
42
42
 
43
- - (void)setModuleRegistry:(UMModuleRegistry *)moduleRegistry
43
+ - (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
44
44
  {
45
45
  _moduleRegistry = moduleRegistry;
46
46
  }
@@ -61,7 +61,7 @@ UM_EXPORT_MODULE(ExponentSpeech)
61
61
  - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
62
62
  didStartSpeechUtterance:(AVSpeechUtterance *)utterance
63
63
  {
64
- id<UMEventEmitterService> emitter = [_moduleRegistry getModuleImplementingProtocol:@protocol(UMEventEmitterService)];
64
+ id<EXEventEmitterService> emitter = [_moduleRegistry getModuleImplementingProtocol:@protocol(EXEventEmitterService)];
65
65
  if (emitter != nil) {
66
66
  [emitter sendEventWithName:@"Exponent.speakingStarted" body:@{ @"id": ((EXSpeechUtteranceWithId *) utterance).utteranceId }];
67
67
  }
@@ -70,7 +70,7 @@ UM_EXPORT_MODULE(ExponentSpeech)
70
70
  - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
71
71
  didCancelSpeechUtterance:(AVSpeechUtterance *)utterance
72
72
  {
73
- id<UMEventEmitterService> emitter = [_moduleRegistry getModuleImplementingProtocol:@protocol(UMEventEmitterService)];
73
+ id<EXEventEmitterService> emitter = [_moduleRegistry getModuleImplementingProtocol:@protocol(EXEventEmitterService)];
74
74
  if (emitter != nil) {
75
75
  [emitter sendEventWithName:@"Exponent.speakingStopped" body:@{ @"id": ((EXSpeechUtteranceWithId *) utterance).utteranceId }];
76
76
  }
@@ -79,19 +79,19 @@ UM_EXPORT_MODULE(ExponentSpeech)
79
79
  - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
80
80
  didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
81
81
  {
82
- id<UMEventEmitterService> emitter = [_moduleRegistry getModuleImplementingProtocol:@protocol(UMEventEmitterService)];
82
+ id<EXEventEmitterService> emitter = [_moduleRegistry getModuleImplementingProtocol:@protocol(EXEventEmitterService)];
83
83
  if (emitter != nil) {
84
84
  [emitter sendEventWithName:@"Exponent.speakingDone" body:@{ @"id": ((EXSpeechUtteranceWithId *) utterance).utteranceId }];
85
85
  }
86
86
  }
87
87
 
88
88
 
89
- UM_EXPORT_METHOD_AS(speak,
89
+ EX_EXPORT_METHOD_AS(speak,
90
90
  speak:(nonnull NSString *)utteranceId
91
91
  text:(nonnull NSString *)text
92
92
  options:(NSDictionary *)options
93
- resolver:(UMPromiseResolveBlock)resolve
94
- rejecter:(UMPromiseRejectBlock)reject) {
93
+ resolver:(EXPromiseResolveBlock)resolve
94
+ rejecter:(EXPromiseRejectBlock)reject) {
95
95
  if (_synthesizer == nil) {
96
96
  _synthesizer = [[AVSpeechSynthesizer alloc] init];
97
97
  _synthesizer.delegate = self;
@@ -125,9 +125,9 @@ UM_EXPORT_METHOD_AS(speak,
125
125
  resolve(nil);
126
126
  }
127
127
 
128
- UM_EXPORT_METHOD_AS(getVoices,
129
- getVoices:(UMPromiseResolveBlock)resolve
130
- rejecter:(UMPromiseRejectBlock)reject) {
128
+ EX_EXPORT_METHOD_AS(getVoices,
129
+ getVoices:(EXPromiseResolveBlock)resolve
130
+ rejecter:(EXPromiseRejectBlock)reject) {
131
131
  NSArray<AVSpeechSynthesisVoice *> *availableVoices = [AVSpeechSynthesisVoice speechVoices];
132
132
  NSMutableArray<NSDictionary *> *availableVoicesResult = [NSMutableArray array];
133
133
  for (AVSpeechSynthesisVoice* voice in availableVoices) {
@@ -146,30 +146,30 @@ UM_EXPORT_METHOD_AS(getVoices,
146
146
  resolve([availableVoicesResult mutableCopy]);
147
147
  }
148
148
 
149
- UM_EXPORT_METHOD_AS(stop,
150
- stop:(UMPromiseResolveBlock)resolve
151
- rejecter:(UMPromiseRejectBlock)reject) {
149
+ EX_EXPORT_METHOD_AS(stop,
150
+ stop:(EXPromiseResolveBlock)resolve
151
+ rejecter:(EXPromiseRejectBlock)reject) {
152
152
  [_synthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
153
153
  resolve(nil);
154
154
  }
155
155
 
156
- UM_EXPORT_METHOD_AS(pause,
157
- pause:(UMPromiseResolveBlock)resolve
158
- rejecter:(UMPromiseRejectBlock)reject) {
156
+ EX_EXPORT_METHOD_AS(pause,
157
+ pause:(EXPromiseResolveBlock)resolve
158
+ rejecter:(EXPromiseRejectBlock)reject) {
159
159
  [_synthesizer pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
160
160
  resolve(nil);
161
161
  }
162
162
 
163
- UM_EXPORT_METHOD_AS(resume,
164
- resume:(UMPromiseResolveBlock)resolve
165
- rejecter:(UMPromiseRejectBlock)reject) {
163
+ EX_EXPORT_METHOD_AS(resume,
164
+ resume:(EXPromiseResolveBlock)resolve
165
+ rejecter:(EXPromiseRejectBlock)reject) {
166
166
  [_synthesizer continueSpeaking];
167
167
  resolve(nil);
168
168
  }
169
169
 
170
- UM_EXPORT_METHOD_AS(isSpeaking,
171
- isSpeaking:(UMPromiseResolveBlock)resolve
172
- rejecter:(UMPromiseRejectBlock)reject) {
170
+ EX_EXPORT_METHOD_AS(isSpeaking,
171
+ isSpeaking:(EXPromiseResolveBlock)resolve
172
+ rejecter:(EXPromiseRejectBlock)reject) {
173
173
  resolve(@([_synthesizer isSpeaking]));
174
174
  }
175
175
 
@@ -10,10 +10,11 @@ Pod::Spec.new do |s|
10
10
  s.license = package['license']
11
11
  s.author = package['author']
12
12
  s.homepage = package['homepage']
13
- s.platform = :ios, '11.0'
13
+ s.platform = :ios, '12.0'
14
14
  s.source = { git: 'https://github.com/expo/expo.git' }
15
+ s.static_framework = true
15
16
 
16
- s.dependency 'UMCore'
17
+ s.dependency 'ExpoModulesCore'
17
18
 
18
19
  if !$ExpoUseSources&.include?(package['name']) && ENV['EXPO_USE_SOURCE'].to_i == 0 && File.exist?("#{s.name}.xcframework") && Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.10.0')
19
20
  s.source_files = "#{s.name}/**/*.h"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-speech",
3
- "version": "9.2.0",
3
+ "version": "10.0.2",
4
4
  "description": "Provides text-to-speech functionality.",
5
5
  "main": "build/Speech.js",
6
6
  "types": "build/Speech.d.ts",
@@ -31,12 +31,15 @@
31
31
  },
32
32
  "author": "650 Industries, Inc.",
33
33
  "license": "MIT",
34
- "homepage": "https://docs.expo.io/versions/latest/sdk/speech/",
34
+ "homepage": "https://docs.expo.dev/versions/latest/sdk/speech/",
35
35
  "jest": {
36
36
  "preset": "expo-module-scripts/ios"
37
37
  },
38
+ "dependencies": {
39
+ "expo-modules-core": "~0.4.3"
40
+ },
38
41
  "devDependencies": {
39
42
  "expo-module-scripts": "^2.0.0"
40
43
  },
41
- "gitHead": "b33f5e224578564c3e4b1b467f258cc119b3b786"
44
+ "gitHead": "d23e1ac491da96b51c25eb2533efcd56499ee287"
42
45
  }
@@ -1,2 +1,2 @@
1
- import { NativeModulesProxy } from '@unimodules/core';
1
+ import { NativeModulesProxy } from 'expo-modules-core';
2
2
  export default NativeModulesProxy.ExponentSpeech;
@@ -1,10 +1,28 @@
1
- import { SyntheticPlatformEmitter, CodedError } from '@unimodules/core';
1
+ import { SyntheticPlatformEmitter, CodedError } from 'expo-modules-core';
2
2
 
3
3
  import { SpeechOptions, WebVoice, VoiceQuality } from './Speech.types';
4
4
 
5
5
  //https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance/text
6
6
  const MAX_SPEECH_INPUT_LENGTH = 32767;
7
7
 
8
+ async function getVoices(): Promise<SpeechSynthesisVoice[]> {
9
+ return new Promise<SpeechSynthesisVoice[]>((resolve) => {
10
+ const voices = window.speechSynthesis.getVoices();
11
+
12
+ if (voices.length > 0) {
13
+ resolve(voices);
14
+ return;
15
+ }
16
+
17
+ // when a page loads it takes some amount of time to populate the voices list
18
+ // see https://stackoverflow.com/a/52005323/4337317
19
+ window.speechSynthesis.onvoiceschanged = function () {
20
+ const voices = window.speechSynthesis.getVoices();
21
+ resolve(voices);
22
+ };
23
+ });
24
+ }
25
+
8
26
  export default {
9
27
  get name(): string {
10
28
  return 'ExponentSpeech';
@@ -32,9 +50,19 @@ export default {
32
50
  message.volume = options.volume;
33
51
  }
34
52
  if ('_voiceIndex' in options && options._voiceIndex != null) {
35
- const voices = window.speechSynthesis.getVoices();
53
+ const voices = await getVoices();
36
54
  message.voice = voices[Math.min(voices.length - 1, Math.max(0, options._voiceIndex))];
37
55
  }
56
+ if (typeof options.voice === 'string') {
57
+ const voices = await getVoices();
58
+ message.voice =
59
+ voices[
60
+ Math.max(
61
+ 0,
62
+ voices.findIndex((voice) => voice.voiceURI === options.voice)
63
+ )
64
+ ];
65
+ }
38
66
  if (typeof options.onResume === 'function') {
39
67
  message.onresume = options.onResume;
40
68
  }
@@ -64,9 +92,9 @@ export default {
64
92
 
65
93
  return message;
66
94
  },
67
- getVoices(): WebVoice[] {
68
- const voices = window.speechSynthesis.getVoices();
69
- return voices.map(voice => ({
95
+ async getVoices(): Promise<WebVoice[]> {
96
+ const voices = await getVoices();
97
+ return voices.map((voice) => ({
70
98
  identifier: voice.voiceURI,
71
99
  quality: VoiceQuality.Default,
72
100
  isDefault: voice.default,
@@ -1,12 +1,12 @@
1
- import { UnavailabilityError } from '@unimodules/core';
1
+ import { UnavailabilityError } from 'expo-modules-core';
2
2
  import { NativeEventEmitter } from 'react-native';
3
3
 
4
4
  import ExponentSpeech from './ExponentSpeech';
5
- import { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice } from './Speech.types';
5
+ import { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice } from './Speech.types';
6
6
 
7
7
  const SpeechEventEmitter = ExponentSpeech && new NativeEventEmitter(ExponentSpeech);
8
8
 
9
- export { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice };
9
+ export { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice };
10
10
 
11
11
  const _CALLBACKS = {};
12
12
  let _nextCallbackId = 1;
@@ -57,6 +57,13 @@ function _registerListenersIfNeeded() {
57
57
  });
58
58
  }
59
59
 
60
+ // @needsAudit
61
+ /**
62
+ * Speak out loud the text given options. Calling this when another text is being spoken adds
63
+ * an utterance to queue.
64
+ * @param text The text to be spoken. Cannot be longer than [`Speech.maxSpeechInputLength`](#speechmaxspeechinputlength).
65
+ * @param options A `SpeechOptions` object.
66
+ */
60
67
  export function speak(text: string, options: SpeechOptions = {}) {
61
68
  const id = _nextCallbackId++;
62
69
  _CALLBACKS[id] = options;
@@ -64,6 +71,11 @@ export function speak(text: string, options: SpeechOptions = {}) {
64
71
  ExponentSpeech.speak(String(id), text, options);
65
72
  }
66
73
 
74
+ // @needsAudit
75
+ /**
76
+ * Returns list of all available voices.
77
+ * @return List of `Voice` objects.
78
+ */
67
79
  export async function getAvailableVoicesAsync(): Promise<Voice[]> {
68
80
  if (!ExponentSpeech.getVoices) {
69
81
  throw new UnavailabilityError('Speech', 'getVoices');
@@ -71,14 +83,28 @@ export async function getAvailableVoicesAsync(): Promise<Voice[]> {
71
83
  return ExponentSpeech.getVoices();
72
84
  }
73
85
 
86
+ //@needsAudit
87
+ /**
88
+ * Determine whether the Text-to-speech utility is currently speaking. Will return `true` if speaker
89
+ * is paused.
90
+ * @return Returns a Promise that fulfils with a boolean, `true` if speaking, `false` if not.
91
+ */
74
92
  export async function isSpeakingAsync(): Promise<boolean> {
75
93
  return ExponentSpeech.isSpeaking();
76
94
  }
77
95
 
96
+ // @needsAudit
97
+ /**
98
+ * Interrupts current speech and deletes all in queue.
99
+ */
78
100
  export async function stop(): Promise<void> {
79
101
  return ExponentSpeech.stop();
80
102
  }
81
103
 
104
+ // @needsAudit
105
+ /**
106
+ * Pauses current speech. This method is not available on Android.
107
+ */
82
108
  export async function pause(): Promise<void> {
83
109
  if (!ExponentSpeech.pause) {
84
110
  throw new UnavailabilityError('Speech', 'pause');
@@ -86,6 +112,11 @@ export async function pause(): Promise<void> {
86
112
  return ExponentSpeech.pause();
87
113
  }
88
114
 
115
+ // @needsAudit
116
+ /**
117
+ * Resumes speaking previously paused speech or does nothing if there's none. This method is not
118
+ * available on Android.
119
+ */
89
120
  export async function resume(): Promise<void> {
90
121
  if (!ExponentSpeech.resume) {
91
122
  throw new UnavailabilityError('Speech', 'resume');
@@ -95,7 +126,13 @@ export async function resume(): Promise<void> {
95
126
  }
96
127
 
97
128
  function setSpeakingListener(eventName, callback) {
98
- if (SpeechEventEmitter.listeners(eventName).length > 0) {
129
+ // @ts-ignore: the EventEmitter interface has been changed in react-native@0.64.0
130
+ const listenerCount = SpeechEventEmitter.listenerCount
131
+ ? // @ts-ignore: this is available since 0.64
132
+ SpeechEventEmitter.listenerCount(eventName)
133
+ : // @ts-ignore: this is available in older versions
134
+ SpeechEventEmitter.listeners(eventName).length;
135
+ if (listenerCount > 0) {
99
136
  SpeechEventEmitter.removeAllListeners(eventName);
100
137
  }
101
138
  SpeechEventEmitter.addListener(eventName, callback);
@@ -105,4 +142,9 @@ function removeSpeakingListener(eventName) {
105
142
  SpeechEventEmitter.removeAllListeners(eventName);
106
143
  }
107
144
 
145
+ // @needsAudit
146
+ /**
147
+ * Maximum possible text length acceptable by `Speech.speak()` method. It is platform-dependent.
148
+ * On iOS, this returns `Number.MAX_VALUE`.
149
+ */
108
150
  export const maxSpeechInputLength: number = ExponentSpeech.maxSpeechInputLength || Number.MAX_VALUE;
@@ -1,15 +1,41 @@
1
1
  export type SpeechEventCallback = (this: SpeechSynthesisUtterance, ev: SpeechSynthesisEvent) => any;
2
2
 
3
+ // @needsAudit @docsMissing
3
4
  export type SpeechOptions = {
5
+ /**
6
+ * The code of a language that should be used to read the `text`, refer to IETF BCP 47 to see
7
+ * valid codes.
8
+ */
4
9
  language?: string;
10
+ /**
11
+ * Pitch of the voice to speak `text`. `1.0` is the normal pitch.
12
+ */
5
13
  pitch?: number;
14
+ /**
15
+ * Rate of the voice to speak `text`. `1.0` is the normal rate.
16
+ */
6
17
  rate?: number;
18
+ /**
19
+ * A callback that is invoked when speaking starts.
20
+ */
7
21
  onStart?: () => void | SpeechEventCallback;
22
+ /**
23
+ * A callback that is invoked when speaking is stopped by calling `Speech.stop()`.
24
+ */
8
25
  onStopped?: () => void | SpeechEventCallback;
26
+ /**
27
+ * A callback that is invoked when speaking finishes.
28
+ */
9
29
  onDone?: () => void | SpeechEventCallback;
30
+ /**
31
+ * __(Android only).__ A callback that is invoked when an error occurred while speaking.
32
+ * @param error
33
+ */
10
34
  onError?: (error: Error) => void | SpeechEventCallback;
11
-
12
35
  volume?: number;
36
+ /**
37
+ * Voice identifier.
38
+ */
13
39
  voice?: string;
14
40
  _voiceIndex?: number;
15
41
  onBoundary?: SpeechEventCallback | null;
@@ -18,18 +44,39 @@ export type SpeechOptions = {
18
44
  onResume?: SpeechEventCallback | null;
19
45
  };
20
46
 
47
+ // @needsAudit
48
+ /**
49
+ * Enum representing the voice quality.
50
+ */
21
51
  export enum VoiceQuality {
22
52
  Default = 'Default',
23
53
  Enhanced = 'Enhanced',
24
54
  }
25
55
 
56
+ // @needsAudit
57
+ /**
58
+ * Object describing the available voices on the device.
59
+ */
26
60
  export type Voice = {
61
+ /**
62
+ * Voice unique identifier.
63
+ */
27
64
  identifier: string;
65
+ /**
66
+ * Voice name.
67
+ */
28
68
  name: string;
69
+ /**
70
+ * Voice quality.
71
+ */
29
72
  quality: VoiceQuality;
73
+ /**
74
+ * Voice language.
75
+ */
30
76
  language: string;
31
77
  };
32
78
 
79
+ // @docsMissing
33
80
  export type WebVoice = Voice & {
34
81
  isDefault: boolean;
35
82
  localService: boolean;
@@ -1,48 +0,0 @@
1
- package expo.modules.speech;
2
-
3
- import java.util.HashMap;
4
- import java.util.Locale;
5
- import java.util.Map;
6
-
7
- // Lazy load the ISO codes into a Map then transform the codes to match other localization patterns in Expo
8
- public class LanguageUtils {
9
-
10
- private static Map<String, Locale> countryISOCodes;
11
-
12
- private static Map<String, Locale> languageISOCodes;
13
-
14
- private static String transformCountryISO(String code) {
15
- if (countryISOCodes == null) {
16
- String[] countries = Locale.getISOCountries();
17
- countryISOCodes = new HashMap<>(countries.length);
18
- for (String country : countries) {
19
- Locale locale = new Locale("", country);
20
- countryISOCodes.put(locale.getISO3Country().toUpperCase(), locale);
21
- }
22
- }
23
- return countryISOCodes.get(code).getCountry();
24
- }
25
-
26
- private static String transformLanguageISO(String code) {
27
- if (languageISOCodes == null) {
28
- String[] languages = Locale.getISOLanguages();
29
- languageISOCodes = new HashMap<>(languages.length);
30
- for (String language : languages) {
31
- Locale locale = new Locale(language);
32
- languageISOCodes.put(locale.getISO3Language(), locale);
33
- }
34
- }
35
- return languageISOCodes.get(code).getLanguage();
36
- }
37
-
38
- static String getISOCode(Locale locale) {
39
- String language = transformLanguageISO(locale.getISO3Language());
40
- String country = locale.getISO3Country();
41
- if (!country.equals("")) {
42
- String countryCode = transformCountryISO(country);
43
- language += "-" + countryCode;
44
- }
45
- return language;
46
- }
47
- }
48
-