react-native-davoice-tts 1.0.210 → 1.0.212

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.
Files changed (17) hide show
  1. package/TTSRNBridge.podspec +1 -1
  2. package/ios/SpeechBridge/SpeechBridge.m +7 -7
  3. package/ios/TTSRNBridge/DavoiceTTS.xcframework/Info.plist +5 -5
  4. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/DavoiceTTS +0 -0
  5. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios.abi.json +4 -4
  6. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/DavoiceTTS +0 -0
  7. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.abi.json +2193 -2193
  8. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +28 -28
  9. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftinterface +28 -28
  10. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json +2193 -2193
  11. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +28 -28
  12. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +28 -28
  13. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeDirectory +0 -0
  14. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeRequirements-1 +0 -0
  15. package/ios/TTSRNBridge/DavoiceTTS.xcframework/ios-arm64_x86_64-simulator/DavoiceTTS.framework/_CodeSignature/CodeResources +24 -24
  16. package/package.json +1 -1
  17. package/speech/index.ts +58 -13
@@ -14,6 +14,34 @@ import _StringProcessing
14
14
  import _SwiftConcurrencyShims
15
15
  import onnxruntime_objc
16
16
  import phonemes
17
+ @objc @_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers final public class SwiftSoundQueue : ObjectiveC.NSObject, AVFAudio.AVAudioPlayerDelegate {
18
+ @objc deinit
19
+ public static let shared: DavoiceTTS.SwiftSoundQueue
20
+ final public func notifyWhenURLFinishes(_ url: Foundation.URL, _ cb: @escaping () -> Swift.Void)
21
+ final public var onItemDone: ((Foundation.URL) -> Swift.Void)?
22
+ final public var onQueueEmpty: (() -> Swift.Void)?
23
+ final public func enqueue(_ source: DavoiceTTS.SwiftSoundQueue.Source)
24
+ final public func enqueueMany(_ sources: [DavoiceTTS.SwiftSoundQueue.Source])
25
+ final public func stop()
26
+ public enum Source {
27
+ case fileURL(Foundation.URL)
28
+ case named(Swift.String)
29
+ }
30
+ @objc final public func audioPlayerDidFinishPlaying(_ p: AVFAudio.AVAudioPlayer, successfully ok: Swift.Bool)
31
+ final public func activateSpeaker()
32
+ }
33
+ @objc @objcMembers final public class DaVoiceTTS : ObjectiveC.NSObject {
34
+ public struct Config {
35
+ }
36
+ @objc final public var onLastUtteranceFinished: (() -> Swift.Void)?
37
+ @objc deinit
38
+ @objc public init(model: Foundation.URL) throws
39
+ @objc final public func stopSpeaking()
40
+ @objc final public func destroy()
41
+ @objc final public func speak(_ txt: Swift.String, sid: Swift.Int32 = 0)
42
+ final public func synthesize(_ text: Swift.String, speakerId: Swift.Int32 = 0, token: Foundation.UUID, terminal: Swift.Character? = nil) throws -> (AVFAudio.AVAudioPCMBuffer, Swift.Int)
43
+ @objc final public func synthesize_top(_ text: Swift.String, speakerId: Swift.Int32 = 0, token: Foundation.UUID) throws -> AVFAudio.AVAudioPCMBuffer
44
+ }
17
45
  @objc public protocol STTDelegate {
18
46
  @objc func stt(_ stt: DavoiceTTS.STT, didEmitEvent name: Swift.String, body: [Swift.String : Any]?)
19
47
  }
@@ -44,31 +72,3 @@ public enum AudioPlaybackHook {
44
72
  public static var useOnlyEnginePlayback: DavoiceTTS.useOnlyEnginePlayback?
45
73
  public static var stopEnginePlayback: DavoiceTTS.StopEnginePlayback?
46
74
  }
47
- @objc @_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers final public class SwiftSoundQueue : ObjectiveC.NSObject, AVFAudio.AVAudioPlayerDelegate {
48
- @objc deinit
49
- public static let shared: DavoiceTTS.SwiftSoundQueue
50
- final public func notifyWhenURLFinishes(_ url: Foundation.URL, _ cb: @escaping () -> Swift.Void)
51
- final public var onItemDone: ((Foundation.URL) -> Swift.Void)?
52
- final public var onQueueEmpty: (() -> Swift.Void)?
53
- final public func enqueue(_ source: DavoiceTTS.SwiftSoundQueue.Source)
54
- final public func enqueueMany(_ sources: [DavoiceTTS.SwiftSoundQueue.Source])
55
- final public func stop()
56
- public enum Source {
57
- case fileURL(Foundation.URL)
58
- case named(Swift.String)
59
- }
60
- @objc final public func audioPlayerDidFinishPlaying(_ p: AVFAudio.AVAudioPlayer, successfully ok: Swift.Bool)
61
- final public func activateSpeaker()
62
- }
63
- @objc @objcMembers final public class DaVoiceTTS : ObjectiveC.NSObject {
64
- public struct Config {
65
- }
66
- @objc final public var onLastUtteranceFinished: (() -> Swift.Void)?
67
- @objc deinit
68
- @objc public init(model: Foundation.URL) throws
69
- @objc final public func stopSpeaking()
70
- @objc final public func destroy()
71
- @objc final public func speak(_ txt: Swift.String, sid: Swift.Int32 = 0)
72
- final public func synthesize(_ text: Swift.String, speakerId: Swift.Int32 = 0, token: Foundation.UUID, terminal: Swift.Character? = nil) throws -> (AVFAudio.AVAudioPCMBuffer, Swift.Int)
73
- @objc final public func synthesize_top(_ text: Swift.String, speakerId: Swift.Int32 = 0, token: Foundation.UUID) throws -> AVFAudio.AVAudioPCMBuffer
74
- }
@@ -14,6 +14,34 @@ import _StringProcessing
14
14
  import _SwiftConcurrencyShims
15
15
  import onnxruntime_objc
16
16
  import phonemes
17
+ @objc @_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers final public class SwiftSoundQueue : ObjectiveC.NSObject, AVFAudio.AVAudioPlayerDelegate {
18
+ @objc deinit
19
+ public static let shared: DavoiceTTS.SwiftSoundQueue
20
+ final public func notifyWhenURLFinishes(_ url: Foundation.URL, _ cb: @escaping () -> Swift.Void)
21
+ final public var onItemDone: ((Foundation.URL) -> Swift.Void)?
22
+ final public var onQueueEmpty: (() -> Swift.Void)?
23
+ final public func enqueue(_ source: DavoiceTTS.SwiftSoundQueue.Source)
24
+ final public func enqueueMany(_ sources: [DavoiceTTS.SwiftSoundQueue.Source])
25
+ final public func stop()
26
+ public enum Source {
27
+ case fileURL(Foundation.URL)
28
+ case named(Swift.String)
29
+ }
30
+ @objc final public func audioPlayerDidFinishPlaying(_ p: AVFAudio.AVAudioPlayer, successfully ok: Swift.Bool)
31
+ final public func activateSpeaker()
32
+ }
33
+ @objc @objcMembers final public class DaVoiceTTS : ObjectiveC.NSObject {
34
+ public struct Config {
35
+ }
36
+ @objc final public var onLastUtteranceFinished: (() -> Swift.Void)?
37
+ @objc deinit
38
+ @objc public init(model: Foundation.URL) throws
39
+ @objc final public func stopSpeaking()
40
+ @objc final public func destroy()
41
+ @objc final public func speak(_ txt: Swift.String, sid: Swift.Int32 = 0)
42
+ final public func synthesize(_ text: Swift.String, speakerId: Swift.Int32 = 0, token: Foundation.UUID, terminal: Swift.Character? = nil) throws -> (AVFAudio.AVAudioPCMBuffer, Swift.Int)
43
+ @objc final public func synthesize_top(_ text: Swift.String, speakerId: Swift.Int32 = 0, token: Foundation.UUID) throws -> AVFAudio.AVAudioPCMBuffer
44
+ }
17
45
  @objc public protocol STTDelegate {
18
46
  @objc func stt(_ stt: DavoiceTTS.STT, didEmitEvent name: Swift.String, body: [Swift.String : Any]?)
19
47
  }
@@ -44,31 +72,3 @@ public enum AudioPlaybackHook {
44
72
  public static var useOnlyEnginePlayback: DavoiceTTS.useOnlyEnginePlayback?
45
73
  public static var stopEnginePlayback: DavoiceTTS.StopEnginePlayback?
46
74
  }
47
- @objc @_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers final public class SwiftSoundQueue : ObjectiveC.NSObject, AVFAudio.AVAudioPlayerDelegate {
48
- @objc deinit
49
- public static let shared: DavoiceTTS.SwiftSoundQueue
50
- final public func notifyWhenURLFinishes(_ url: Foundation.URL, _ cb: @escaping () -> Swift.Void)
51
- final public var onItemDone: ((Foundation.URL) -> Swift.Void)?
52
- final public var onQueueEmpty: (() -> Swift.Void)?
53
- final public func enqueue(_ source: DavoiceTTS.SwiftSoundQueue.Source)
54
- final public func enqueueMany(_ sources: [DavoiceTTS.SwiftSoundQueue.Source])
55
- final public func stop()
56
- public enum Source {
57
- case fileURL(Foundation.URL)
58
- case named(Swift.String)
59
- }
60
- @objc final public func audioPlayerDidFinishPlaying(_ p: AVFAudio.AVAudioPlayer, successfully ok: Swift.Bool)
61
- final public func activateSpeaker()
62
- }
63
- @objc @objcMembers final public class DaVoiceTTS : ObjectiveC.NSObject {
64
- public struct Config {
65
- }
66
- @objc final public var onLastUtteranceFinished: (() -> Swift.Void)?
67
- @objc deinit
68
- @objc public init(model: Foundation.URL) throws
69
- @objc final public func stopSpeaking()
70
- @objc final public func destroy()
71
- @objc final public func speak(_ txt: Swift.String, sid: Swift.Int32 = 0)
72
- final public func synthesize(_ text: Swift.String, speakerId: Swift.Int32 = 0, token: Foundation.UUID, terminal: Swift.Character? = nil) throws -> (AVFAudio.AVAudioPCMBuffer, Swift.Int)
73
- @objc final public func synthesize_top(_ text: Swift.String, speakerId: Swift.Int32 = 0, token: Foundation.UUID) throws -> AVFAudio.AVAudioPCMBuffer
74
- }
@@ -34,11 +34,11 @@
34
34
  </data>
35
35
  <key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.abi.json</key>
36
36
  <data>
37
- F8MIF0UKeVSebEFF9bySG2FSFzM=
37
+ Dj7FA9guOc89KNZkxI6lLLvU8Pk=
38
38
  </data>
39
39
  <key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface</key>
40
40
  <data>
41
- LCtrLnxF8otfJXum8IpNmX+aEbY=
41
+ j98wNI33l5BDEWyGVnm+dfwXBXA=
42
42
  </data>
43
43
  <key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftdoc</key>
44
44
  <data>
@@ -46,19 +46,19 @@
46
46
  </data>
47
47
  <key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftinterface</key>
48
48
  <data>
49
- LCtrLnxF8otfJXum8IpNmX+aEbY=
49
+ j98wNI33l5BDEWyGVnm+dfwXBXA=
50
50
  </data>
51
51
  <key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftmodule</key>
52
52
  <data>
53
- LdxCLmWuLM10E4UzlwjizBQpMls=
53
+ K1i4tUi70DoJw5M0vzjwBQ7VgIs=
54
54
  </data>
55
55
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
56
56
  <data>
57
- F8MIF0UKeVSebEFF9bySG2FSFzM=
57
+ Dj7FA9guOc89KNZkxI6lLLvU8Pk=
58
58
  </data>
59
59
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
60
60
  <data>
61
- i4666v/hYRnv7SImcavXDYdHsDE=
61
+ XMAwfgaL6XQ+HCsqsQ2qFV1JFyk=
62
62
  </data>
63
63
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
64
64
  <data>
@@ -66,11 +66,11 @@
66
66
  </data>
67
67
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
68
68
  <data>
69
- i4666v/hYRnv7SImcavXDYdHsDE=
69
+ XMAwfgaL6XQ+HCsqsQ2qFV1JFyk=
70
70
  </data>
71
71
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
72
72
  <data>
73
- ZcDmlDfffd5PUPw52EOSrrwUI10=
73
+ UBGFzgrLXWDX5MDXh3T3lJJ4Pqg=
74
74
  </data>
75
75
  <key>Modules/module.modulemap</key>
76
76
  <data>
@@ -149,22 +149,22 @@
149
149
  <dict>
150
150
  <key>hash</key>
151
151
  <data>
152
- F8MIF0UKeVSebEFF9bySG2FSFzM=
152
+ Dj7FA9guOc89KNZkxI6lLLvU8Pk=
153
153
  </data>
154
154
  <key>hash2</key>
155
155
  <data>
156
- AqBo8mhy1RSctfMTSruj1J8vjfIJFAcsWfx1qv3Eljs=
156
+ SZb5LkY99hH8Ma0A6dxSxPftktT7Joco1UIx2DDJ+CI=
157
157
  </data>
158
158
  </dict>
159
159
  <key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface</key>
160
160
  <dict>
161
161
  <key>hash</key>
162
162
  <data>
163
- LCtrLnxF8otfJXum8IpNmX+aEbY=
163
+ j98wNI33l5BDEWyGVnm+dfwXBXA=
164
164
  </data>
165
165
  <key>hash2</key>
166
166
  <data>
167
- aq0DqyxISdQboUj4T9omt+7XNCDPP2jU3jwHX+k8RpE=
167
+ Acow3eYRx9Qc+IAIg0founlfTysFcmDO7NswshOQSnU=
168
168
  </data>
169
169
  </dict>
170
170
  <key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftdoc</key>
@@ -182,44 +182,44 @@
182
182
  <dict>
183
183
  <key>hash</key>
184
184
  <data>
185
- LCtrLnxF8otfJXum8IpNmX+aEbY=
185
+ j98wNI33l5BDEWyGVnm+dfwXBXA=
186
186
  </data>
187
187
  <key>hash2</key>
188
188
  <data>
189
- aq0DqyxISdQboUj4T9omt+7XNCDPP2jU3jwHX+k8RpE=
189
+ Acow3eYRx9Qc+IAIg0founlfTysFcmDO7NswshOQSnU=
190
190
  </data>
191
191
  </dict>
192
192
  <key>Modules/DavoiceTTS.swiftmodule/arm64-apple-ios-simulator.swiftmodule</key>
193
193
  <dict>
194
194
  <key>hash</key>
195
195
  <data>
196
- LdxCLmWuLM10E4UzlwjizBQpMls=
196
+ K1i4tUi70DoJw5M0vzjwBQ7VgIs=
197
197
  </data>
198
198
  <key>hash2</key>
199
199
  <data>
200
- O79/UyApCROOBvfpA6GUztKOVwKZ6Mbc3XQXZ29erGo=
200
+ 2Ke0oiQDwazWBpTpIZKfiUOvkeTx8iQeU4I3xVUx0Ho=
201
201
  </data>
202
202
  </dict>
203
203
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
204
204
  <dict>
205
205
  <key>hash</key>
206
206
  <data>
207
- F8MIF0UKeVSebEFF9bySG2FSFzM=
207
+ Dj7FA9guOc89KNZkxI6lLLvU8Pk=
208
208
  </data>
209
209
  <key>hash2</key>
210
210
  <data>
211
- AqBo8mhy1RSctfMTSruj1J8vjfIJFAcsWfx1qv3Eljs=
211
+ SZb5LkY99hH8Ma0A6dxSxPftktT7Joco1UIx2DDJ+CI=
212
212
  </data>
213
213
  </dict>
214
214
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
215
215
  <dict>
216
216
  <key>hash</key>
217
217
  <data>
218
- i4666v/hYRnv7SImcavXDYdHsDE=
218
+ XMAwfgaL6XQ+HCsqsQ2qFV1JFyk=
219
219
  </data>
220
220
  <key>hash2</key>
221
221
  <data>
222
- FtzosyddTwqpDBy5fQ41lM61kmGY6IR4xlKO2feiEdA=
222
+ hmr1LXCD49br3IWuNduuFQ3lc9GrWcHbA5PeDKEqe6U=
223
223
  </data>
224
224
  </dict>
225
225
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
@@ -237,22 +237,22 @@
237
237
  <dict>
238
238
  <key>hash</key>
239
239
  <data>
240
- i4666v/hYRnv7SImcavXDYdHsDE=
240
+ XMAwfgaL6XQ+HCsqsQ2qFV1JFyk=
241
241
  </data>
242
242
  <key>hash2</key>
243
243
  <data>
244
- FtzosyddTwqpDBy5fQ41lM61kmGY6IR4xlKO2feiEdA=
244
+ hmr1LXCD49br3IWuNduuFQ3lc9GrWcHbA5PeDKEqe6U=
245
245
  </data>
246
246
  </dict>
247
247
  <key>Modules/DavoiceTTS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
248
248
  <dict>
249
249
  <key>hash</key>
250
250
  <data>
251
- ZcDmlDfffd5PUPw52EOSrrwUI10=
251
+ UBGFzgrLXWDX5MDXh3T3lJJ4Pqg=
252
252
  </data>
253
253
  <key>hash2</key>
254
254
  <data>
255
- Sk/PFg9S/9Uj66kCnI0DcWxN/l4AWKeR2PyXiuLXsfU=
255
+ w31harTp0Vd3GwP0jUmvvQ83F+6Omk1e926HWKQ3vs8=
256
256
  </data>
257
257
  </dict>
258
258
  <key>Modules/module.modulemap</key>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-davoice-tts",
3
- "version": "1.0.210",
3
+ "version": "1.0.212",
4
4
  "description": "tts library for React Native",
5
5
  "main": "tts/index.js",
6
6
  "types": "tts/index.d.ts",
package/speech/index.ts CHANGED
@@ -46,6 +46,10 @@ class Speech {
46
46
  private unifiedEmitter: NativeEventEmitter | null = null;
47
47
  private subs: Array<{ remove: () => void }> = [];
48
48
  private handlers: Required<UnifiedEvents>;
49
+ // top of file (new state)
50
+ private lastLocale: string | null = null;
51
+ private lastModel: string | null = null;
52
+ private iosTtsOnly = false; // when true, use NativeTTS directly on iOS
49
53
 
50
54
  constructor() {
51
55
  this.handlers = {
@@ -77,14 +81,37 @@ class Speech {
77
81
  }
78
82
  }
79
83
 
84
+ // NEW: tiny helper to (re)wire listeners depending on mode
85
+ private rewireListenersForMode() {
86
+ this.teardownListeners();
87
+ // if iOS unified + NOT tts-only -> use unified emitter
88
+ if (Platform.OS === 'ios' && NativeSpeech && !this.iosTtsOnly) {
89
+ this.unifiedEmitter = new NativeEventEmitter(NativeSpeech);
90
+ // unified handles both STT + TTS events
91
+ } else {
92
+ // fallback: separate emitters
93
+ if (NativeSTT) this.sttEmitter = new NativeEventEmitter(NativeSTT);
94
+ if (Platform.OS === 'android') this.ttsEmitter = DeviceEventEmitter;
95
+ else if (NativeTTS) this.ttsEmitter = new NativeEventEmitter(NativeTTS);
96
+ }
97
+ this.ensureListeners();
98
+ }
99
+
80
100
  // ---------- Init / Destroy ----------
81
101
  /**
82
102
  * iOS: initialize STT then TTS via native SpeechBridge if available.
83
103
  * Android: no special init needed; optionally preload TTS (if you want).
84
104
  */
85
105
  async initAll(opts: { locale: string; model: string; timeoutMs?: number }) {
106
+ this.lastLocale = opts.locale;
107
+ this.lastModel = opts.model;
108
+
86
109
  if (Platform.OS === 'ios' && NativeSpeech?.initAll) {
87
- return NativeSpeech.initAll(opts);
110
+ this.iosTtsOnly = false; // full unified mode
111
+ this.teardownListeners(); // re-wire listeners for unified
112
+ const r = await NativeSpeech.initAll(opts);
113
+ this.ensureListeners();
114
+ return r;
88
115
  }
89
116
 
90
117
  // Fallback (Android or iOS w/o SpeechBridge):
@@ -135,6 +162,8 @@ class Speech {
135
162
  // iOS unified
136
163
  if (Platform.OS === 'ios' && NativeSpeech?.destroyAll) {
137
164
  const r = await NativeSpeech.destroyAll();
165
+ this.iosTtsOnly = false;
166
+ this.lastLocale = this.lastLocale ?? null;
138
167
  this.teardownListeners();
139
168
  return r;
140
169
  }
@@ -190,13 +219,20 @@ class Speech {
190
219
  }
191
220
 
192
221
  /** Pause mic/STT (Android native; iOS unified if present) */
193
- pauseMicrophone(): Promise<void> {
222
+ async pauseMicrophone(): Promise<void> {
194
223
  // Prefer unified iOS if available (safe even if you add iOS later)
195
- if (Platform.OS === 'ios' && (NativeSpeech as any)?.pauseMicrophone) {
196
- return new Promise((resolve, reject) => {
197
- try { (NativeSpeech as any).pauseMicrophone(() => resolve()); }
198
- catch (e) { reject(e as any); }
199
- });
224
+ if (Platform.OS === 'ios' && NativeSpeech) {
225
+ // 1) destroy unified stack (STT+TTS)
226
+ try { await NativeSpeech.destroyAll?.(); } catch {}
227
+
228
+ // 2) init TTS-only using cached model
229
+ if (!this.lastModel) return;
230
+ await NativeTTS.initTTS({ model: this.lastModel });
231
+
232
+ // 3) switch to TTS-only mode and rewire events
233
+ this.iosTtsOnly = true;
234
+ this.rewireListenersForMode();
235
+ return;
200
236
  }
201
237
  // Android
202
238
  if (!(NativeSTT as any)?.pauseMicrophone) return Promise.resolve();
@@ -207,13 +243,22 @@ class Speech {
207
243
  }
208
244
 
209
245
  /** Resume mic/STT (Android native; iOS unified if present) */
210
- unPauseMicrophone(): Promise<void> {
211
- if (Platform.OS === 'ios' && (NativeSpeech as any)?.unPauseMicrophone) {
212
- return new Promise((resolve, reject) => {
213
- try { (NativeSpeech as any).unPauseMicrophone(() => resolve()); }
214
- catch (e) { reject(e as any); }
215
- });
246
+ async unPauseMicrophone(): Promise<void> {
247
+ if (Platform.OS === 'ios' && NativeSpeech) {
248
+ // 1) stop/destroy TTS-only (ignore errors if not present)
249
+ try { await NativeTTS?.stopSpeaking?.(); } catch {}
250
+ try { await NativeTTS?.destroy?.(); } catch {}
251
+
252
+ // 2) re-init full unified stack with cached opts
253
+ if (!this.lastLocale || !this.lastModel) return;
254
+ await NativeSpeech.initAll({ locale: this.lastLocale, model: this.lastModel });
255
+
256
+ // 3) switch back to unified mode and rewire events
257
+ this.iosTtsOnly = false;
258
+ this.rewireListenersForMode();
259
+ return;
216
260
  }
261
+
217
262
  if (!(NativeSTT as any)?.unPauseMicrophone) return Promise.resolve();
218
263
  return new Promise((resolve, reject) => {
219
264
  try { (NativeSTT as any).unPauseMicrophone(() => resolve()); }