expo-speech 11.4.0 → 11.6.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,26 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 11.6.0 — 2023-10-17
14
+
15
+ ### 🛠 Breaking changes
16
+
17
+ - Dropped support for Android SDK 21 and 22. ([#24201](https://github.com/expo/expo/pull/24201) by [@behenate](https://github.com/behenate))
18
+
19
+ ## 11.5.0 — 2023-09-04
20
+
21
+ ### 🎉 New features
22
+
23
+ - Added support for React Native 0.73. ([#24018](https://github.com/expo/expo/pull/24018) by [@kudo](https://github.com/kudo))
24
+
25
+ ### 🐛 Bug fixes
26
+
27
+ - Use new `EventEmitter` instead of `NativeEventEmitter`. ([#24221](https://github.com/expo/expo/pull/24221) by [@alanjhughes](https://github.com/alanjhughes))
28
+
29
+ ### 💡 Others
30
+
31
+ - Migrated Android codebase to use Expo modules API. ([#23862](https://github.com/expo/expo/pull/23862) by [@lukmccall](https://github.com/lukmccall))
32
+
13
33
  ## 11.4.0 — 2023-08-02
14
34
 
15
35
  _This version does not introduce any user-facing changes._
@@ -3,15 +3,20 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '11.4.0'
6
+ version = '11.6.0'
7
7
 
8
- buildscript {
9
- def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
10
- if (expoModulesCorePlugin.exists()) {
11
- apply from: expoModulesCorePlugin
12
- applyKotlinExpoModulesCorePlugin()
8
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
9
+ if (expoModulesCorePlugin.exists()) {
10
+ apply from: expoModulesCorePlugin
11
+ applyKotlinExpoModulesCorePlugin()
12
+ // Remove this check, but keep the contents after SDK49 support is dropped
13
+ if (safeExtGet("expoProvidesDefaultConfig", false)) {
14
+ useExpoPublishing()
15
+ useCoreDependencies()
13
16
  }
17
+ }
14
18
 
19
+ buildscript {
15
20
  // Simple helper that allows the root project to override versions declared by this library.
16
21
  ext.safeExtGet = { prop, fallback ->
17
22
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
@@ -35,52 +40,68 @@ buildscript {
35
40
  }
36
41
  }
37
42
 
38
- afterEvaluate {
39
- publishing {
40
- publications {
41
- release(MavenPublication) {
42
- from components.release
43
+ // Remove this if and it's contents, when support for SDK49 is dropped
44
+ if (!safeExtGet("expoProvidesDefaultConfig", false)) {
45
+ afterEvaluate {
46
+ publishing {
47
+ publications {
48
+ release(MavenPublication) {
49
+ from components.release
50
+ }
43
51
  }
44
- }
45
- repositories {
46
- maven {
47
- url = mavenLocal().url
52
+ repositories {
53
+ maven {
54
+ url = mavenLocal().url
55
+ }
48
56
  }
49
57
  }
50
58
  }
51
59
  }
52
60
 
53
61
  android {
54
- compileSdkVersion safeExtGet("compileSdkVersion", 33)
62
+ // Remove this if and it's contents, when support for SDK49 is dropped
63
+ if (!safeExtGet("expoProvidesDefaultConfig", false)) {
64
+ compileSdkVersion safeExtGet("compileSdkVersion", 33)
65
+
66
+ defaultConfig {
67
+ minSdkVersion safeExtGet("minSdkVersion", 23)
68
+ targetSdkVersion safeExtGet("targetSdkVersion", 33)
69
+ }
70
+
71
+ publishing {
72
+ singleVariant("release") {
73
+ withSourcesJar()
74
+ }
75
+ }
55
76
 
56
- compileOptions {
57
- sourceCompatibility JavaVersion.VERSION_11
58
- targetCompatibility JavaVersion.VERSION_11
77
+ lintOptions {
78
+ abortOnError false
79
+ }
59
80
  }
60
81
 
61
- kotlinOptions {
62
- jvmTarget = JavaVersion.VERSION_11.majorVersion
82
+ def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
83
+ if (agpVersion.tokenize('.')[0].toInteger() < 8) {
84
+ compileOptions {
85
+ sourceCompatibility JavaVersion.VERSION_11
86
+ targetCompatibility JavaVersion.VERSION_11
87
+ }
88
+
89
+ kotlinOptions {
90
+ jvmTarget = JavaVersion.VERSION_11.majorVersion
91
+ }
63
92
  }
64
93
 
65
94
  namespace "expo.modules.speech"
66
95
  defaultConfig {
67
- minSdkVersion safeExtGet("minSdkVersion", 21)
68
- targetSdkVersion safeExtGet("targetSdkVersion", 33)
69
96
  versionCode 18
70
- versionName "11.4.0"
71
- }
72
- lintOptions {
73
- abortOnError false
74
- }
75
- publishing {
76
- singleVariant("release") {
77
- withSourcesJar()
78
- }
97
+ versionName "11.6.0"
79
98
  }
80
99
  }
81
100
 
82
101
  dependencies {
83
- implementation project(':expo-modules-core')
84
-
85
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
102
+ // Remove this if and it's contents, when support for SDK49 is dropped
103
+ if (!safeExtGet("expoProvidesDefaultConfig", false)) {
104
+ implementation project(':expo-modules-core')
105
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
106
+ }
86
107
  }
@@ -5,16 +5,16 @@ import java.util.*
5
5
  // Lazy load the ISO codes into a Map then transform the codes to match other localization patterns in Expo
6
6
  object LanguageUtils {
7
7
  private val countryISOCodes: Map<String, Locale> by lazy {
8
- Locale.getISOCountries().map { country ->
8
+ Locale.getISOCountries().associate { country ->
9
9
  val locale = Locale("", country)
10
- locale.getISO3Country().toUpperCase(locale) to locale
11
- }.toMap()
10
+ locale.isO3Country.uppercase(locale) to locale
11
+ }
12
12
  }
13
13
  private val languageISOCodes: Map<String, Locale> by lazy {
14
- Locale.getISOLanguages().map { language ->
14
+ Locale.getISOLanguages().associate { language ->
15
15
  val locale = Locale(language)
16
- locale.getISO3Language() to locale
17
- }.toMap()
16
+ locale.isO3Language to locale
17
+ }
18
18
  }
19
19
 
20
20
  // NOTE: These helpers are null-unsafe and should be called ONLY with codes
@@ -23,8 +23,8 @@ object LanguageUtils {
23
23
  private fun transformLanguageISO(code: String) = languageISOCodes[code]!!.language
24
24
 
25
25
  fun getISOCode(locale: Locale): String {
26
- var language = transformLanguageISO(locale.getISO3Language())
27
- val country = locale.getISO3Country()
26
+ var language = transformLanguageISO(locale.isO3Language)
27
+ val country = locale.isO3Country
28
28
  if (country != "") {
29
29
  val countryCode = transformCountryISO(country)
30
30
  language += "-$countryCode"
@@ -0,0 +1,8 @@
1
+ package expo.modules.speech
2
+
3
+ import android.speech.tts.TextToSpeech
4
+ import expo.modules.kotlin.exception.CodedException
5
+
6
+ class SpeechInputIsToLongException : CodedException(
7
+ message = "Speech input text is too long! Limit of input length is: ${TextToSpeech.getMaxSpeechInputLength()}"
8
+ )
@@ -1,94 +1,87 @@
1
1
  package expo.modules.speech
2
2
 
3
- import android.content.Context
4
3
  import android.os.Bundle
5
4
  import android.speech.tts.TextToSpeech
6
5
  import android.speech.tts.UtteranceProgressListener
7
6
  import android.speech.tts.Voice
8
- import expo.modules.core.ExportedModule
9
- import expo.modules.core.ModuleRegistry
10
- import expo.modules.core.ModuleRegistryDelegate
11
- import expo.modules.core.Promise
12
- import expo.modules.core.interfaces.ExpoMethod
13
- import expo.modules.core.interfaces.LifecycleEventListener
14
- import expo.modules.core.interfaces.services.EventEmitter
15
- import expo.modules.core.interfaces.services.UIManager
16
- import java.util.*
17
-
18
- class SpeechModule(
19
- context: Context,
20
- private val moduleRegistryDelegate: ModuleRegistryDelegate = ModuleRegistryDelegate()
21
- ) : ExportedModule(context), LifecycleEventListener {
22
-
23
- private inline fun <reified T> moduleRegistry() =
24
- moduleRegistryDelegate.getFromModuleRegistry<T>()
25
-
26
- private val uiManager: UIManager by moduleRegistry()
7
+ import expo.modules.kotlin.modules.Module
8
+ import expo.modules.kotlin.modules.ModuleDefinition
9
+ import java.util.ArrayDeque
10
+ import java.util.Locale
11
+ import java.util.Queue
12
+
13
+ const val speakingStartedEvent = "Exponent.speakingStarted"
14
+ const val speakingWillSayNextStringEvent = "Exponent.speakingWillSayNextString"
15
+ const val speakingDoneEvent = "Exponent.speakingDone"
16
+ const val speakingStoppedEvent = "Exponent.speakingStopped"
17
+ const val speakingErrorEvent = "Exponent.speakingError"
18
+
19
+ class SpeechModule : Module() {
27
20
  private val delayedUtterances: Queue<Utterance> = ArrayDeque()
28
21
 
29
- // Module basic definitions
30
- override fun getName() = "ExpoSpeech"
31
- override fun getConstants() = mapOf(
32
- "maxSpeechInputLength" to TextToSpeech.getMaxSpeechInputLength()
33
- )
34
-
35
- // Module methods
22
+ override fun definition() = ModuleDefinition {
23
+ Name("ExpoSpeech")
36
24
 
37
- @ExpoMethod
38
- fun isSpeaking(promise: Promise) = promise.resolve(textToSpeech.isSpeaking)
25
+ Events(
26
+ speakingStartedEvent,
27
+ speakingWillSayNextStringEvent,
28
+ speakingDoneEvent,
29
+ speakingStoppedEvent,
30
+ speakingErrorEvent
31
+ )
39
32
 
40
- @ExpoMethod
41
- fun getVoices(promise: Promise) {
42
- var nativeVoices: List<Voice> = emptyList()
43
- try {
44
- nativeVoices = textToSpeech.voices.toList()
45
- } catch (e: Exception) {}
33
+ Constants("maxSpeechInputLength" to TextToSpeech.getMaxSpeechInputLength())
46
34
 
47
- val voices = nativeVoices.map {
48
- val quality = if (it.quality > Voice.QUALITY_NORMAL) {
49
- "Enhanced"
50
- } else {
51
- "Default"
52
- }
35
+ OnActivityDestroys {
36
+ textToSpeech.shutdown()
37
+ }
53
38
 
54
- Bundle().apply {
55
- putString("identifier", it.name)
56
- putString("name", it.name)
57
- putString("quality", quality)
58
- putString("language", LanguageUtils.getISOCode(it.locale))
59
- }
39
+ AsyncFunction("isSpeaking") {
40
+ textToSpeech.isSpeaking
60
41
  }
61
42
 
62
- promise.resolve(voices)
63
- }
43
+ AsyncFunction("getVoices") {
44
+ val nativeVoices = try {
45
+ textToSpeech.voices.toList()
46
+ } catch (_: Exception) {
47
+ emptyList()
48
+ }
64
49
 
65
- @ExpoMethod
66
- fun stop(promise: Promise) {
67
- textToSpeech.stop()
68
- promise.resolve(null)
69
- }
50
+ return@AsyncFunction nativeVoices.map {
51
+ val quality = if (it.quality > Voice.QUALITY_NORMAL) {
52
+ VoiceQuality.ENHANCED
53
+ } else {
54
+ VoiceQuality.DEFAULT
55
+ }
70
56
 
71
- @ExpoMethod
72
- fun speak(id: String, text: String, options: Map<String, Any>?, promise: Promise) {
73
- val speechOptions = SpeechOptions.optionsFromMap(options, promise) ?: return
57
+ VoiceRecord(
58
+ identifier = it.name,
59
+ name = it.name,
60
+ quality = quality,
61
+ language = LanguageUtils.getISOCode(it.locale)
62
+ )
63
+ }
64
+ }
74
65
 
75
- if (text.length > TextToSpeech.getMaxSpeechInputLength()) {
76
- promise.reject(
77
- "ERR_SPEECH_INPUT_LENGTH",
78
- "Speech input text is too long! Limit of input length is: " + TextToSpeech.getMaxSpeechInputLength()
79
- )
80
- return
66
+ AsyncFunction("stop") {
67
+ textToSpeech.stop()
81
68
  }
82
69
 
83
- if (isTextToSpeechReady) {
84
- speakOut(id, text, speechOptions)
85
- } else {
86
- delayedUtterances.add(Utterance(id, text, speechOptions))
70
+ AsyncFunction("speak") { id: String, text: String, options: SpeechOptions ->
71
+ if (text.length > TextToSpeech.getMaxSpeechInputLength()) {
72
+ throw SpeechInputIsToLongException()
73
+ }
74
+
75
+ if (isTextToSpeechReady) {
76
+ speakOut(id, text, options)
77
+ } else {
78
+ delayedUtterances.add(Utterance(id, text, options))
87
79
 
88
- // init TTS, speaking will be available only after onInit
89
- textToSpeech
80
+ // init TTS, speaking will be available only after onInit
81
+ textToSpeech
82
+ }
83
+ Unit
90
84
  }
91
- promise.resolve(null)
92
85
  }
93
86
 
94
87
  private fun speakOut(id: String, text: String, options: SpeechOptions) {
@@ -129,37 +122,36 @@ class SpeechModule(
129
122
  get() = _ttsReady
130
123
 
131
124
  private val textToSpeech: TextToSpeech by lazy {
132
- val newTtsInstance = TextToSpeech(context) { status: Int ->
125
+ val newTtsInstance = TextToSpeech(appContext.reactContext) { status: Int ->
133
126
  if (status == TextToSpeech.SUCCESS) {
134
127
  // synchronize because in some cases this runs on another thread and _textToSpeech is null
135
128
  synchronized(this@SpeechModule) {
136
129
  _ttsReady = true
137
130
  _textToSpeech!!.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
138
- private val emitter by moduleRegistry<EventEmitter>()
139
131
 
140
132
  override fun onStart(utteranceId: String) {
141
- emitter.emit("Exponent.speakingStarted", idToMap(utteranceId))
133
+ sendEvent(speakingStartedEvent, idToMap(utteranceId))
142
134
  }
143
135
 
144
136
  override fun onRangeStart(utteranceId: String, start: Int, end: Int, frame: Int) {
145
- var map = Bundle().apply {
137
+ val map = Bundle().apply {
146
138
  putString("id", utteranceId)
147
139
  putInt("charIndex", start)
148
140
  putInt("charLength", end - start)
149
141
  }
150
- emitter.emit("Exponent.speakingWillSayNextString", map)
142
+ sendEvent(speakingWillSayNextStringEvent, map)
151
143
  }
152
144
 
153
145
  override fun onDone(utteranceId: String) {
154
- emitter.emit("Exponent.speakingDone", idToMap(utteranceId))
146
+ sendEvent(speakingDoneEvent, idToMap(utteranceId))
155
147
  }
156
148
 
157
149
  override fun onStop(utteranceId: String, interrupted: Boolean) {
158
- emitter.emit("Exponent.speakingStopped", idToMap(utteranceId))
150
+ sendEvent(speakingStoppedEvent, idToMap(utteranceId))
159
151
  }
160
152
 
161
153
  override fun onError(utteranceId: String) {
162
- emitter.emit("Exponent.speakingError", idToMap(utteranceId))
154
+ sendEvent(speakingErrorEvent, idToMap(utteranceId))
163
155
  }
164
156
  })
165
157
  for ((id, text, options) in delayedUtterances) {
@@ -172,17 +164,6 @@ class SpeechModule(
172
164
  newTtsInstance
173
165
  }
174
166
 
175
- // Lifecycle methods
176
- override fun onCreate(moduleRegistry: ModuleRegistry) {
177
- moduleRegistryDelegate.onCreate(moduleRegistry)
178
- uiManager.registerLifecycleEventListener(this)
179
- }
180
- override fun onHostPause() {}
181
- override fun onHostResume() {}
182
- override fun onHostDestroy() {
183
- textToSpeech.shutdown()
184
- }
185
-
186
167
  // Helpers
187
168
  private fun idToMap(id: String) = Bundle().apply {
188
169
  putString("id", id)
@@ -1,58 +1,11 @@
1
1
  package expo.modules.speech
2
2
 
3
- import expo.modules.core.Promise
4
- import java.util.*
3
+ import expo.modules.kotlin.records.Field
4
+ import expo.modules.kotlin.records.Record
5
5
 
6
6
  data class SpeechOptions(
7
- val language: String?,
8
- val pitch: Float?,
9
- val rate: Float?,
10
- val voice: String?
11
- ) {
12
- companion object {
13
- fun optionsFromMap(options: Map<String, Any?>?, promise: Promise): SpeechOptions? {
14
-
15
- if (options == null) {
16
- return SpeechOptions(null, null, null, null)
17
- }
18
-
19
- val language = options["language"]?.let {
20
- if (it is String) {
21
- return@let it
22
- }
23
-
24
- promise.reject("ERR_INVALID_OPTION", "Language must be a string")
25
- return null
26
- }
27
-
28
- val pitch = options["pitch"]?.let {
29
- if (it is Number) {
30
- return@let it.toFloat()
31
- }
32
-
33
- promise.reject("ERR_INVALID_OPTION", "Pitch must be a number")
34
- return null
35
- }
36
-
37
- val rate = options["rate"]?.let {
38
- if (it is Number) {
39
- return@let it.toFloat()
40
- }
41
-
42
- promise.reject("ERR_INVALID_OPTION", "Rate must be a number")
43
- return null
44
- }
45
-
46
- val voice = options["voice"]?.let {
47
- if (it is String) {
48
- return@let it
49
- }
50
-
51
- promise.reject("ERR_INVALID_OPTION", "Voice name must be a string")
52
- return null
53
- }
54
-
55
- return SpeechOptions(language, pitch, rate, voice)
56
- }
57
- }
58
- }
7
+ @Field val language: String?,
8
+ @Field val pitch: Float?,
9
+ @Field val rate: Float?,
10
+ @Field val voice: String?
11
+ ) : Record
@@ -0,0 +1,17 @@
1
+ package expo.modules.speech
2
+
3
+ import expo.modules.kotlin.records.Field
4
+ import expo.modules.kotlin.records.Record
5
+ import expo.modules.kotlin.types.Enumerable
6
+
7
+ enum class VoiceQuality(val value: String) : Enumerable {
8
+ ENHANCED("Enhanced"),
9
+ DEFAULT("Default")
10
+ }
11
+
12
+ data class VoiceRecord(
13
+ @Field val identifier: String,
14
+ @Field val name: String,
15
+ @Field val quality: VoiceQuality,
16
+ @Field val language: String
17
+ ) : Record
@@ -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;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"}
1
+ {"version":3,"file":"Speech.d.ts","sourceRoot":"","sources":["../src/Speech/Speech.ts"],"names":[],"mappings":"AAGA,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;AAeD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAgE,CAAC"}
package/build/Speech.js CHANGED
@@ -1,8 +1,7 @@
1
- import { UnavailabilityError } from 'expo-modules-core';
2
- import { NativeEventEmitter } from 'react-native';
1
+ import { UnavailabilityError, EventEmitter } from 'expo-modules-core';
3
2
  import ExponentSpeech from './ExponentSpeech';
4
3
  import { VoiceQuality } from './Speech.types';
5
- const SpeechEventEmitter = ExponentSpeech && new NativeEventEmitter(ExponentSpeech);
4
+ const SpeechEventEmitter = new EventEmitter(ExponentSpeech);
6
5
  export { VoiceQuality };
7
6
  const _CALLBACKS = {};
8
7
  let _nextCallbackId = 1;
@@ -123,12 +122,7 @@ export async function resume() {
123
122
  return ExponentSpeech.resume();
124
123
  }
125
124
  function setSpeakingListener(eventName, callback) {
126
- // @ts-ignore: the EventEmitter interface has been changed in react-native@0.64.0
127
- const listenerCount = SpeechEventEmitter.listenerCount
128
- ? // @ts-ignore: this is available since 0.64
129
- SpeechEventEmitter.listenerCount(eventName)
130
- : // @ts-ignore: this is available in older versions
131
- SpeechEventEmitter.listeners(eventName).length;
125
+ const listenerCount = SpeechEventEmitter._listenerCount;
132
126
  if (listenerCount > 0) {
133
127
  SpeechEventEmitter.removeAllListeners(eventName);
134
128
  }
@@ -1 +1 @@
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
+ {"version":3,"file":"Speech.js","sourceRoot":"","sources":["../src/Speech/Speech.ts"],"names":[],"mappings":"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","sourcesContent":["import { UnavailabilityError, EventEmitter } from 'expo-modules-core';\n\nimport ExponentSpeech from './ExponentSpeech';\nimport { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice } from './Speech.types';\n\nconst SpeechEventEmitter = new EventEmitter(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 const listenerCount = SpeechEventEmitter._listenerCount;\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"]}
@@ -3,5 +3,8 @@
3
3
  "platforms": ["ios", "android"],
4
4
  "ios": {
5
5
  "modules": ["SpeechModule"]
6
+ },
7
+ "android": {
8
+ "modules": ["expo.modules.speech.SpeechModule"]
6
9
  }
7
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-speech",
3
- "version": "11.4.0",
3
+ "version": "11.6.0",
4
4
  "description": "Provides text-to-speech functionality.",
5
5
  "main": "build/Speech.js",
6
6
  "types": "build/Speech.d.ts",
@@ -42,5 +42,5 @@
42
42
  "peerDependencies": {
43
43
  "expo": "*"
44
44
  },
45
- "gitHead": "2240630a92eb79a4e4bf73e1439916c394876478"
45
+ "gitHead": "da25937e2a99661cbe5eb60ca1d8d6245fc96a50"
46
46
  }
@@ -1,10 +1,9 @@
1
- import { UnavailabilityError } from 'expo-modules-core';
2
- import { NativeEventEmitter } from 'react-native';
1
+ import { UnavailabilityError, EventEmitter } from 'expo-modules-core';
3
2
 
4
3
  import ExponentSpeech from './ExponentSpeech';
5
4
  import { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice } from './Speech.types';
6
5
 
7
- const SpeechEventEmitter = ExponentSpeech && new NativeEventEmitter(ExponentSpeech);
6
+ const SpeechEventEmitter = new EventEmitter(ExponentSpeech);
8
7
 
9
8
  export { SpeechOptions, SpeechEventCallback, VoiceQuality, Voice, WebVoice };
10
9
 
@@ -136,12 +135,7 @@ export async function resume(): Promise<void> {
136
135
  }
137
136
 
138
137
  function setSpeakingListener(eventName, callback) {
139
- // @ts-ignore: the EventEmitter interface has been changed in react-native@0.64.0
140
- const listenerCount = SpeechEventEmitter.listenerCount
141
- ? // @ts-ignore: this is available since 0.64
142
- SpeechEventEmitter.listenerCount(eventName)
143
- : // @ts-ignore: this is available in older versions
144
- SpeechEventEmitter.listeners(eventName).length;
138
+ const listenerCount = SpeechEventEmitter._listenerCount;
145
139
  if (listenerCount > 0) {
146
140
  SpeechEventEmitter.removeAllListeners(eventName);
147
141
  }
@@ -1,8 +0,0 @@
1
- package expo.modules.speech
2
-
3
- import android.content.Context
4
- import expo.modules.core.BasePackage
5
-
6
- class SpeechPackage : BasePackage() {
7
- override fun createExportedModules(context: Context) = listOf(SpeechModule(context))
8
- }