expo-speech 10.3.0 → 11.1.0

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.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,22 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 11.1.0 — 2023-02-03
14
+
15
+ ### 🎉 New features
16
+
17
+ - Added utterance word tracking support for iOS and Android. This allows the ability to highlight each word in an utterance. ([#20726](https://github.com/expo/expo/pull/20726) by [@gabrieljoelc](https://github.com/gabrieljoelc))
18
+
19
+ ### 💡 Others
20
+
21
+ - On Android bump `compileSdkVersion` and `targetSdkVersion` to `33`. ([#20721](https://github.com/expo/expo/pull/20721) by [@lukmccall](https://github.com/lukmccall))
22
+
23
+ ## 11.0.0 — 2022-10-25
24
+
25
+ ### 🛠 Breaking changes
26
+
27
+ - Bumped iOS deployment target to 13.0 and deprecated support for iOS 12. ([#18873](https://github.com/expo/expo/pull/18873) by [@tsapeta](https://github.com/tsapeta))
28
+
13
29
  ## 10.3.0 — 2022-07-07
14
30
 
15
31
  _This version does not introduce any user-facing changes._
package/README.md CHANGED
@@ -4,7 +4,7 @@ Provides text-to-speech functionality.
4
4
 
5
5
  # API documentation
6
6
 
7
- - [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/speech.md)
7
+ - [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/speech.mdx)
8
8
  - [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/speech/)
9
9
 
10
10
  # Installation in managed Expo projects
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '10.3.0'
6
+ version = '11.1.0'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -59,7 +59,7 @@ afterEvaluate {
59
59
  }
60
60
 
61
61
  android {
62
- compileSdkVersion safeExtGet("compileSdkVersion", 31)
62
+ compileSdkVersion safeExtGet("compileSdkVersion", 33)
63
63
 
64
64
  compileOptions {
65
65
  sourceCompatibility JavaVersion.VERSION_11
@@ -72,9 +72,9 @@ android {
72
72
 
73
73
  defaultConfig {
74
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
75
- targetSdkVersion safeExtGet("targetSdkVersion", 31)
75
+ targetSdkVersion safeExtGet("targetSdkVersion", 33)
76
76
  versionCode 18
77
- versionName "10.3.0"
77
+ versionName "11.1.0"
78
78
  }
79
79
  lintOptions {
80
80
  abortOnError false
@@ -141,6 +141,15 @@ class SpeechModule(
141
141
  emitter.emit("Exponent.speakingStarted", idToMap(utteranceId))
142
142
  }
143
143
 
144
+ override fun onRangeStart(utteranceId: String, start: Int, end: Int, frame: Int) {
145
+ var map = Bundle().apply {
146
+ putString("id", utteranceId)
147
+ putInt("charIndex", start)
148
+ putInt("charLength", end - start)
149
+ }
150
+ emitter.emit("Exponent.speakingWillSayNextString", map)
151
+ }
152
+
144
153
  override fun onDone(utteranceId: String) {
145
154
  emitter.emit("Exponent.speakingDone", idToMap(utteranceId))
146
155
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Speech.d.ts","sourceRoot":"","sources":["../src/Speech/Speech.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAInG,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAoD7E;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,QAK9D;AAGD;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAKhE;AAGD;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAExD;AAGD;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1C;AAGD;;GAEG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAK3C;AAGD;;;GAGG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAM5C;AAoBD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAgE,CAAC"}
1
+ {"version":3,"file":"Speech.d.ts","sourceRoot":"","sources":["../src/Speech/Speech.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAInG,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AA8D7E;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,QAK9D;AAGD;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAKhE;AAGD;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAExD;AAGD;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1C;AAGD;;GAEG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAK3C;AAGD;;;GAGG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAM5C;AAoBD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAgE,CAAC"}
package/build/Speech.js CHANGED
@@ -10,6 +10,7 @@ let _didSetListeners = false;
10
10
  function _unregisterListenersIfNeeded() {
11
11
  if (Object.keys(_CALLBACKS).length === 0) {
12
12
  removeSpeakingListener('Exponent.speakingStarted');
13
+ removeSpeakingListener('Exponent.speakingWillSayNextString');
13
14
  removeSpeakingListener('Exponent.speakingDone');
14
15
  removeSpeakingListener('Exponent.speakingStopped');
15
16
  removeSpeakingListener('Exponent.speakingError');
@@ -26,6 +27,15 @@ function _registerListenersIfNeeded() {
26
27
  options.onStart();
27
28
  }
28
29
  });
30
+ setSpeakingListener('Exponent.speakingWillSayNextString', ({ id, charIndex, charLength }) => {
31
+ const options = _CALLBACKS[id];
32
+ if (options && options.onBoundary) {
33
+ options.onBoundary({
34
+ charIndex,
35
+ charLength,
36
+ });
37
+ }
38
+ });
29
39
  setSpeakingListener('Exponent.speakingDone', ({ id }) => {
30
40
  const options = _CALLBACKS[id];
31
41
  if (options && options.onDone) {
@@ -1 +1 @@
1
- {"version":3,"file":"Speech.js","sourceRoot":"","sources":["../src/Speech/Speech.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAsC,YAAY,EAAmB,MAAM,gBAAgB,CAAC;AAEnG,MAAM,kBAAkB,GAAG,cAAc,IAAI,IAAI,kBAAkB,CAAC,cAAc,CAAC,CAAC;AAEpF,OAAO,EAAsC,YAAY,EAAmB,CAAC;AAE7E,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,IAAI,eAAe,GAAG,CAAC,CAAC;AACxB,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAE7B,SAAS,4BAA4B;IACnC,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;QACxC,sBAAsB,CAAC,0BAA0B,CAAC,CAAC;QACnD,sBAAsB,CAAC,uBAAuB,CAAC,CAAC;QAChD,sBAAsB,CAAC,0BAA0B,CAAC,CAAC;QACnD,sBAAsB,CAAC,wBAAwB,CAAC,CAAC;QACjD,gBAAgB,GAAG,KAAK,CAAC;KAC1B;AACH,CAAC;AAED,SAAS,0BAA0B;IACjC,IAAI,gBAAgB;QAAE,OAAO;IAC7B,gBAAgB,GAAG,IAAI,CAAC;IACxB,mBAAmB,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE;YAC9B,OAAO,CAAC,OAAO,EAAE,CAAC;SACnB;IACH,CAAC,CAAC,CAAC;IACH,mBAAmB,CAAC,uBAAuB,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;QACtD,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE;YAC7B,OAAO,CAAC,MAAM,EAAE,CAAC;SAClB;QACD,OAAO,UAAU,CAAC,EAAE,CAAC,CAAC;QACtB,4BAA4B,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IACH,mBAAmB,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE;YAChC,OAAO,CAAC,SAAS,EAAE,CAAC;SACrB;QACD,OAAO,UAAU,CAAC,EAAE,CAAC,CAAC;QACtB,4BAA4B,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IACH,mBAAmB,CAAC,wBAAwB,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAC9D,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE;YAC9B,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;SACnC;QACD,OAAO,UAAU,CAAC,EAAE,CAAC,CAAC;QACtB,4BAA4B,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,UAAyB,EAAE;IAC7D,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAC7B,UAAU,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC;IACzB,0BAA0B,EAAE,CAAC;IAC7B,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,cAAc;AACd;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE;QAC7B,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;KACtD;IACD,OAAO,cAAc,CAAC,SAAS,EAAE,CAAC;AACpC,CAAC;AAED,aAAa;AACb;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO,cAAc,CAAC,UAAU,EAAE,CAAC;AACrC,CAAC;AAED,cAAc;AACd;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,OAAO,cAAc,CAAC,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED,cAAc;AACd;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE;QACzB,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;KAClD;IACD,OAAO,cAAc,CAAC,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,cAAc;AACd;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE;QAC1B,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;KACnD;IAED,OAAO,cAAc,CAAC,MAAM,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAS,EAAE,QAAQ;IAC9C,iFAAiF;IACjF,MAAM,aAAa,GAAG,kBAAkB,CAAC,aAAa;QACpD,CAAC,CAAC,2CAA2C;YAC3C,kBAAkB,CAAC,aAAa,CAAC,SAAS,CAAC;QAC7C,CAAC,CAAC,kDAAkD;YAClD,kBAAkB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACnD,IAAI,aAAa,GAAG,CAAC,EAAE;QACrB,kBAAkB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;KAClD;IACD,kBAAkB,CAAC,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,sBAAsB,CAAC,SAAS;IACvC,kBAAkB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;AACnD,CAAC;AAED,cAAc;AACd;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAW,cAAc,CAAC,oBAAoB,IAAI,MAAM,CAAC,SAAS,CAAC","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\nimport { NativeEventEmitter } from 'react-native';\n\nimport ExponentSpeech from './ExponentSpeech';\nimport { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice } from './Speech.types';\n\nconst SpeechEventEmitter = ExponentSpeech && new NativeEventEmitter(ExponentSpeech);\n\nexport { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice };\n\nconst _CALLBACKS = {};\nlet _nextCallbackId = 1;\nlet _didSetListeners = false;\n\nfunction _unregisterListenersIfNeeded() {\n if (Object.keys(_CALLBACKS).length === 0) {\n removeSpeakingListener('Exponent.speakingStarted');\n removeSpeakingListener('Exponent.speakingDone');\n removeSpeakingListener('Exponent.speakingStopped');\n removeSpeakingListener('Exponent.speakingError');\n _didSetListeners = false;\n }\n}\n\nfunction _registerListenersIfNeeded() {\n if (_didSetListeners) return;\n _didSetListeners = true;\n setSpeakingListener('Exponent.speakingStarted', ({ id }) => {\n const options = _CALLBACKS[id];\n if (options && options.onStart) {\n options.onStart();\n }\n });\n setSpeakingListener('Exponent.speakingDone', ({ id }) => {\n const options = _CALLBACKS[id];\n if (options && options.onDone) {\n options.onDone();\n }\n delete _CALLBACKS[id];\n _unregisterListenersIfNeeded();\n });\n setSpeakingListener('Exponent.speakingStopped', ({ id }) => {\n const options = _CALLBACKS[id];\n if (options && options.onStopped) {\n options.onStopped();\n }\n delete _CALLBACKS[id];\n _unregisterListenersIfNeeded();\n });\n setSpeakingListener('Exponent.speakingError', ({ id, error }) => {\n const options = _CALLBACKS[id];\n if (options && options.onError) {\n options.onError(new Error(error));\n }\n delete _CALLBACKS[id];\n _unregisterListenersIfNeeded();\n });\n}\n\n// @needsAudit\n/**\n * Speak out loud the text given options. Calling this when another text is being spoken adds\n * an utterance to queue.\n * @param text The text to be spoken. Cannot be longer than [`Speech.maxSpeechInputLength`](#speechmaxspeechinputlength).\n * @param options A `SpeechOptions` object.\n */\nexport function speak(text: string, options: SpeechOptions = {}) {\n const id = _nextCallbackId++;\n _CALLBACKS[id] = options;\n _registerListenersIfNeeded();\n ExponentSpeech.speak(String(id), text, options);\n}\n\n// @needsAudit\n/**\n * Returns list of all available voices.\n * @return List of `Voice` objects.\n */\nexport async function getAvailableVoicesAsync(): Promise<Voice[]> {\n if (!ExponentSpeech.getVoices) {\n throw new UnavailabilityError('Speech', 'getVoices');\n }\n return ExponentSpeech.getVoices();\n}\n\n//@needsAudit\n/**\n * Determine whether the Text-to-speech utility is currently speaking. Will return `true` if speaker\n * is paused.\n * @return Returns a Promise that fulfils with a boolean, `true` if speaking, `false` if not.\n */\nexport async function isSpeakingAsync(): Promise<boolean> {\n return ExponentSpeech.isSpeaking();\n}\n\n// @needsAudit\n/**\n * Interrupts current speech and deletes all in queue.\n */\nexport async function stop(): Promise<void> {\n return ExponentSpeech.stop();\n}\n\n// @needsAudit\n/**\n * Pauses current speech. This method is not available on Android.\n */\nexport async function pause(): Promise<void> {\n if (!ExponentSpeech.pause) {\n throw new UnavailabilityError('Speech', 'pause');\n }\n return ExponentSpeech.pause();\n}\n\n// @needsAudit\n/**\n * Resumes speaking previously paused speech or does nothing if there's none. This method is not\n * available on Android.\n */\nexport async function resume(): Promise<void> {\n if (!ExponentSpeech.resume) {\n throw new UnavailabilityError('Speech', 'resume');\n }\n\n return ExponentSpeech.resume();\n}\n\nfunction setSpeakingListener(eventName, callback) {\n // @ts-ignore: the EventEmitter interface has been changed in react-native@0.64.0\n const listenerCount = SpeechEventEmitter.listenerCount\n ? // @ts-ignore: this is available since 0.64\n SpeechEventEmitter.listenerCount(eventName)\n : // @ts-ignore: this is available in older versions\n SpeechEventEmitter.listeners(eventName).length;\n if (listenerCount > 0) {\n SpeechEventEmitter.removeAllListeners(eventName);\n }\n SpeechEventEmitter.addListener(eventName, callback);\n}\n\nfunction removeSpeakingListener(eventName) {\n SpeechEventEmitter.removeAllListeners(eventName);\n}\n\n// @needsAudit\n/**\n * Maximum possible text length acceptable by `Speech.speak()` method. It is platform-dependent.\n * On iOS, this returns `Number.MAX_VALUE`.\n */\nexport const maxSpeechInputLength: number = ExponentSpeech.maxSpeechInputLength || Number.MAX_VALUE;\n"]}
1
+ {"version":3,"file":"Speech.js","sourceRoot":"","sources":["../src/Speech/Speech.ts"],"names":[],"mappings":"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","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\nimport { NativeEventEmitter } from 'react-native';\n\nimport ExponentSpeech from './ExponentSpeech';\nimport { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice } from './Speech.types';\n\nconst SpeechEventEmitter = ExponentSpeech && new NativeEventEmitter(ExponentSpeech);\n\nexport { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice };\n\nconst _CALLBACKS = {};\nlet _nextCallbackId = 1;\nlet _didSetListeners = false;\n\nfunction _unregisterListenersIfNeeded() {\n if (Object.keys(_CALLBACKS).length === 0) {\n removeSpeakingListener('Exponent.speakingStarted');\n removeSpeakingListener('Exponent.speakingWillSayNextString');\n removeSpeakingListener('Exponent.speakingDone');\n removeSpeakingListener('Exponent.speakingStopped');\n removeSpeakingListener('Exponent.speakingError');\n _didSetListeners = false;\n }\n}\n\nfunction _registerListenersIfNeeded() {\n if (_didSetListeners) return;\n _didSetListeners = true;\n setSpeakingListener('Exponent.speakingStarted', ({ id }) => {\n const options = _CALLBACKS[id];\n if (options && options.onStart) {\n options.onStart();\n }\n });\n setSpeakingListener('Exponent.speakingWillSayNextString', ({ id, charIndex, charLength }) => {\n const options = _CALLBACKS[id];\n if (options && options.onBoundary) {\n options.onBoundary({\n charIndex,\n charLength,\n });\n }\n });\n setSpeakingListener('Exponent.speakingDone', ({ id }) => {\n const options = _CALLBACKS[id];\n if (options && options.onDone) {\n options.onDone();\n }\n delete _CALLBACKS[id];\n _unregisterListenersIfNeeded();\n });\n setSpeakingListener('Exponent.speakingStopped', ({ id }) => {\n const options = _CALLBACKS[id];\n if (options && options.onStopped) {\n options.onStopped();\n }\n delete _CALLBACKS[id];\n _unregisterListenersIfNeeded();\n });\n setSpeakingListener('Exponent.speakingError', ({ id, error }) => {\n const options = _CALLBACKS[id];\n if (options && options.onError) {\n options.onError(new Error(error));\n }\n delete _CALLBACKS[id];\n _unregisterListenersIfNeeded();\n });\n}\n\n// @needsAudit\n/**\n * Speak out loud the text given options. Calling this when another text is being spoken adds\n * an utterance to queue.\n * @param text The text to be spoken. Cannot be longer than [`Speech.maxSpeechInputLength`](#speechmaxspeechinputlength).\n * @param options A `SpeechOptions` object.\n */\nexport function speak(text: string, options: SpeechOptions = {}) {\n const id = _nextCallbackId++;\n _CALLBACKS[id] = options;\n _registerListenersIfNeeded();\n ExponentSpeech.speak(String(id), text, options);\n}\n\n// @needsAudit\n/**\n * Returns list of all available voices.\n * @return List of `Voice` objects.\n */\nexport async function getAvailableVoicesAsync(): Promise<Voice[]> {\n if (!ExponentSpeech.getVoices) {\n throw new UnavailabilityError('Speech', 'getVoices');\n }\n return ExponentSpeech.getVoices();\n}\n\n//@needsAudit\n/**\n * Determine whether the Text-to-speech utility is currently speaking. Will return `true` if speaker\n * is paused.\n * @return Returns a Promise that fulfils with a boolean, `true` if speaking, `false` if not.\n */\nexport async function isSpeakingAsync(): Promise<boolean> {\n return ExponentSpeech.isSpeaking();\n}\n\n// @needsAudit\n/**\n * Interrupts current speech and deletes all in queue.\n */\nexport async function stop(): Promise<void> {\n return ExponentSpeech.stop();\n}\n\n// @needsAudit\n/**\n * Pauses current speech. This method is not available on Android.\n */\nexport async function pause(): Promise<void> {\n if (!ExponentSpeech.pause) {\n throw new UnavailabilityError('Speech', 'pause');\n }\n return ExponentSpeech.pause();\n}\n\n// @needsAudit\n/**\n * Resumes speaking previously paused speech or does nothing if there's none. This method is not\n * available on Android.\n */\nexport async function resume(): Promise<void> {\n if (!ExponentSpeech.resume) {\n throw new UnavailabilityError('Speech', 'resume');\n }\n\n return ExponentSpeech.resume();\n}\n\nfunction setSpeakingListener(eventName, callback) {\n // @ts-ignore: the EventEmitter interface has been changed in react-native@0.64.0\n const listenerCount = SpeechEventEmitter.listenerCount\n ? // @ts-ignore: this is available since 0.64\n SpeechEventEmitter.listenerCount(eventName)\n : // @ts-ignore: this is available in older versions\n SpeechEventEmitter.listeners(eventName).length;\n if (listenerCount > 0) {\n SpeechEventEmitter.removeAllListeners(eventName);\n }\n SpeechEventEmitter.addListener(eventName, callback);\n}\n\nfunction removeSpeakingListener(eventName) {\n SpeechEventEmitter.removeAllListeners(eventName);\n}\n\n// @needsAudit\n/**\n * Maximum possible text length acceptable by `Speech.speak()` method. It is platform-dependent.\n * On iOS, this returns `Number.MAX_VALUE`.\n */\nexport const maxSpeechInputLength: number = ExponentSpeech.maxSpeechInputLength || Number.MAX_VALUE;\n"]}
@@ -1,5 +1,15 @@
1
- export declare type SpeechEventCallback = (this: SpeechSynthesisUtterance, ev: SpeechSynthesisEvent) => any;
2
- export declare type SpeechOptions = {
1
+ export type SpeechEventCallback = (this: SpeechSynthesisUtterance, ev: SpeechSynthesisEvent) => any;
2
+ export type NativeBoundaryEvent = {
3
+ charIndex: number;
4
+ charLength: number;
5
+ };
6
+ /**
7
+ * Native-only callback with parameters related to the word about to be uttered.
8
+ * @platform ios
9
+ * @platform android
10
+ */
11
+ export type NativeBoundaryEventCallback = (ev: NativeBoundaryEvent) => void;
12
+ export type SpeechOptions = {
3
13
  /**
4
14
  * The code of a language that should be used to read the `text`, refer to IETF BCP 47 to see
5
15
  * valid codes.
@@ -29,6 +39,7 @@ export declare type SpeechOptions = {
29
39
  * A callback that is invoked when an error occurred while speaking.
30
40
  * @param error
31
41
  * @platform android
42
+ * @platform ios
32
43
  */
33
44
  onError?: (error: Error) => void | SpeechEventCallback;
34
45
  /**
@@ -43,7 +54,10 @@ export declare type SpeechOptions = {
43
54
  */
44
55
  voice?: string;
45
56
  _voiceIndex?: number;
46
- onBoundary?: SpeechEventCallback | null;
57
+ /**
58
+ * A callback that is invoked when the spoken utterance reaches a word.
59
+ */
60
+ onBoundary?: NativeBoundaryEventCallback | SpeechEventCallback | null;
47
61
  onMark?: SpeechEventCallback | null;
48
62
  onPause?: SpeechEventCallback | null;
49
63
  onResume?: SpeechEventCallback | null;
@@ -58,7 +72,7 @@ export declare enum VoiceQuality {
58
72
  /**
59
73
  * Object describing the available voices on the device.
60
74
  */
61
- export declare type Voice = {
75
+ export type Voice = {
62
76
  /**
63
77
  * Voice unique identifier.
64
78
  */
@@ -76,7 +90,7 @@ export declare type Voice = {
76
90
  */
77
91
  language: string;
78
92
  };
79
- export declare type WebVoice = Voice & {
93
+ export type WebVoice = Voice & {
80
94
  isDefault: boolean;
81
95
  localService: boolean;
82
96
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Speech.types.d.ts","sourceRoot":"","sources":["../src/Speech/Speech.types.ts"],"names":[],"mappings":"AAAA,oBAAY,mBAAmB,GAAG,CAAC,IAAI,EAAE,wBAAwB,EAAE,EAAE,EAAE,oBAAoB,KAAK,GAAG,CAAC;AAGpG,oBAAY,aAAa,GAAG;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,mBAAmB,CAAC;IAC3C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,mBAAmB,CAAC;IAC7C;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,GAAG,mBAAmB,CAAC;IAC1C;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,mBAAmB,CAAC;IACvD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACvC,CAAC;AAGF;;GAEG;AACH,oBAAY,YAAY;IACtB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAGD;;GAEG;AACH,oBAAY,KAAK,GAAG;IAClB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IACtB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,oBAAY,QAAQ,GAAG,KAAK,GAAG;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC"}
1
+ {"version":3,"file":"Speech.types.d.ts","sourceRoot":"","sources":["../src/Speech/Speech.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,wBAAwB,EAAE,EAAE,EAAE,oBAAoB,KAAK,GAAG,CAAC;AACpG,MAAM,MAAM,mBAAmB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,EAAE,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAG5E,MAAM,MAAM,aAAa,GAAG;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,mBAAmB,CAAC;IAC3C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,mBAAmB,CAAC;IAC7C;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,GAAG,mBAAmB,CAAC;IAC1C;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,mBAAmB,CAAC;IACvD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,CAAC,EAAE,2BAA2B,GAAG,mBAAmB,GAAG,IAAI,CAAC;IACtE,MAAM,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACvC,CAAC;AAGF;;GAEG;AACH,oBAAY,YAAY;IACtB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAGD;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG;IAClB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IACtB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Speech.types.js","sourceRoot":"","sources":["../src/Speech/Speech.types.ts"],"names":[],"mappings":"AAqDA,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 * A callback that is invoked when an error occurred while speaking.\n * @param error\n * @platform android\n */\n onError?: (error: Error) => void | SpeechEventCallback;\n /**\n * Volume of the voice to speak `text`. A number between `0.0` (muted) and `1.0` (max volume)\n *\n * @default 1.0\n * @platform web\n */\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
+ {"version":3,"file":"Speech.types.js","sourceRoot":"","sources":["../src/Speech/Speech.types.ts"],"names":[],"mappings":"AAkEA,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;\nexport type NativeBoundaryEvent = { charIndex: number; charLength: number };\n\n/**\n * Native-only callback with parameters related to the word about to be uttered.\n * @platform ios\n * @platform android\n */\nexport type NativeBoundaryEventCallback = (ev: NativeBoundaryEvent) => void;\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 * A callback that is invoked when an error occurred while speaking.\n * @param error\n * @platform android\n * @platform ios\n */\n onError?: (error: Error) => void | SpeechEventCallback;\n /**\n * Volume of the voice to speak `text`. A number between `0.0` (muted) and `1.0` (max volume)\n *\n * @default 1.0\n * @platform web\n */\n volume?: number;\n /**\n * Voice identifier.\n */\n voice?: string;\n _voiceIndex?: number;\n\n /**\n * A callback that is invoked when the spoken utterance reaches a word.\n */\n onBoundary?: NativeBoundaryEventCallback | 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"]}
@@ -47,7 +47,7 @@ EX_EXPORT_MODULE(ExponentSpeech)
47
47
 
48
48
  - (NSArray<NSString *> *)supportedEvents
49
49
  {
50
- return @[@"Exponent.speakingStarted", @"Exponent.speakingDone", @"Exponent.speakingStopped", @"Exponent.speakingError"];
50
+ return @[@"Exponent.speakingStarted", @"Exponent.speakingWillSayNextString", @"Exponent.speakingDone", @"Exponent.speakingStopped", @"Exponent.speakingError"];
51
51
  }
52
52
 
53
53
  - (void)startObserving {
@@ -67,6 +67,15 @@ EX_EXPORT_MODULE(ExponentSpeech)
67
67
  }
68
68
  }
69
69
 
70
+ - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
71
+ willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(nonnull AVSpeechUtterance *)utterance
72
+ {
73
+ id<EXEventEmitterService> emitter = [_moduleRegistry getModuleImplementingProtocol:@protocol(EXEventEmitterService)];
74
+ if (emitter != nil) {
75
+ [emitter sendEventWithName:@"Exponent.speakingWillSayNextString" body:@{ @"id": ((EXSpeechUtteranceWithId *) utterance).utteranceId, @"charIndex": @(characterRange.location), @"charLength": @(characterRange.length) }];
76
+ }
77
+ }
78
+
70
79
  - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
71
80
  didCancelSpeechUtterance:(AVSpeechUtterance *)utterance
72
81
  {
@@ -10,7 +10,7 @@ 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, '12.0'
13
+ s.platform = :ios, '13.0'
14
14
  s.source = { git: 'https://github.com/expo/expo.git' }
15
15
  s.static_framework = true
16
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-speech",
3
- "version": "10.3.0",
3
+ "version": "11.1.0",
4
4
  "description": "Provides text-to-speech functionality.",
5
5
  "main": "build/Speech.js",
6
6
  "types": "build/Speech.d.ts",
@@ -37,10 +37,10 @@
37
37
  },
38
38
  "dependencies": {},
39
39
  "devDependencies": {
40
- "expo-module-scripts": "^2.0.0"
40
+ "expo-module-scripts": "^3.0.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "expo": "*"
44
44
  },
45
- "gitHead": "6e131f2da851a47c3a24eb3d6fc971a1a7822086"
45
+ "gitHead": "1815e2eaad8c753588c7b1eb74420174a28e01f4"
46
46
  }
@@ -15,6 +15,7 @@ let _didSetListeners = false;
15
15
  function _unregisterListenersIfNeeded() {
16
16
  if (Object.keys(_CALLBACKS).length === 0) {
17
17
  removeSpeakingListener('Exponent.speakingStarted');
18
+ removeSpeakingListener('Exponent.speakingWillSayNextString');
18
19
  removeSpeakingListener('Exponent.speakingDone');
19
20
  removeSpeakingListener('Exponent.speakingStopped');
20
21
  removeSpeakingListener('Exponent.speakingError');
@@ -31,6 +32,15 @@ function _registerListenersIfNeeded() {
31
32
  options.onStart();
32
33
  }
33
34
  });
35
+ setSpeakingListener('Exponent.speakingWillSayNextString', ({ id, charIndex, charLength }) => {
36
+ const options = _CALLBACKS[id];
37
+ if (options && options.onBoundary) {
38
+ options.onBoundary({
39
+ charIndex,
40
+ charLength,
41
+ });
42
+ }
43
+ });
34
44
  setSpeakingListener('Exponent.speakingDone', ({ id }) => {
35
45
  const options = _CALLBACKS[id];
36
46
  if (options && options.onDone) {
@@ -1,4 +1,12 @@
1
1
  export type SpeechEventCallback = (this: SpeechSynthesisUtterance, ev: SpeechSynthesisEvent) => any;
2
+ export type NativeBoundaryEvent = { charIndex: number; charLength: number };
3
+
4
+ /**
5
+ * Native-only callback with parameters related to the word about to be uttered.
6
+ * @platform ios
7
+ * @platform android
8
+ */
9
+ export type NativeBoundaryEventCallback = (ev: NativeBoundaryEvent) => void;
2
10
 
3
11
  // @needsAudit @docsMissing
4
12
  export type SpeechOptions = {
@@ -31,6 +39,7 @@ export type SpeechOptions = {
31
39
  * A callback that is invoked when an error occurred while speaking.
32
40
  * @param error
33
41
  * @platform android
42
+ * @platform ios
34
43
  */
35
44
  onError?: (error: Error) => void | SpeechEventCallback;
36
45
  /**
@@ -45,7 +54,11 @@ export type SpeechOptions = {
45
54
  */
46
55
  voice?: string;
47
56
  _voiceIndex?: number;
48
- onBoundary?: SpeechEventCallback | null;
57
+
58
+ /**
59
+ * A callback that is invoked when the spoken utterance reaches a word.
60
+ */
61
+ onBoundary?: NativeBoundaryEventCallback | SpeechEventCallback | null;
49
62
  onMark?: SpeechEventCallback | null;
50
63
  onPause?: SpeechEventCallback | null;
51
64
  onResume?: SpeechEventCallback | null;