@iternio/react-native-auto-play 0.4.2 → 0.4.3

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 (63) hide show
  1. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAutoPlay.kt +89 -0
  2. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridCluster.kt +0 -1
  3. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VoiceInputManager.kt +20 -276
  4. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/ThreadUtil.kt +13 -6
  5. package/ios/hybrid/HybridAutoPlay.swift +47 -2
  6. package/ios/utils/VoiceInputManager.swift +40 -141
  7. package/lib/hooks/useAndroidAutoTelemetry.js +6 -1
  8. package/lib/index.d.ts +1 -5
  9. package/lib/index.js +1 -4
  10. package/lib/specs/AutoPlay.nitro.d.ts +29 -0
  11. package/nitro.json +0 -10
  12. package/nitrogen/generated/android/ReactNativeAutoPlay+autolinking.cmake +0 -2
  13. package/nitrogen/generated/android/ReactNativeAutoPlayOnLoad.cpp +0 -18
  14. package/nitrogen/generated/android/c++/JHybridAutoPlaySpec.cpp +43 -0
  15. package/nitrogen/generated/android/c++/JHybridAutoPlaySpec.hpp +4 -0
  16. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAutoPlaySpec.kt +17 -0
  17. package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Bridge.cpp +16 -41
  18. package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Bridge.hpp +126 -201
  19. package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Umbrella.hpp +0 -11
  20. package/nitrogen/generated/ios/ReactNativeAutoPlayAutolinking.mm +0 -8
  21. package/nitrogen/generated/ios/ReactNativeAutoPlayAutolinking.swift +0 -12
  22. package/nitrogen/generated/ios/c++/HybridAutoPlaySpecSwift.hpp +34 -0
  23. package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
  24. package/nitrogen/generated/ios/swift/{Func_void_VoiceInputResult.swift → Func_void_std__shared_ptr_ArrayBuffer_.swift} +10 -10
  25. package/nitrogen/generated/ios/swift/HybridAutoPlaySpec.swift +4 -0
  26. package/nitrogen/generated/ios/swift/HybridAutoPlaySpec_cxx.swift +82 -0
  27. package/nitrogen/generated/shared/c++/HybridAutoPlaySpec.cpp +4 -0
  28. package/nitrogen/generated/shared/c++/HybridAutoPlaySpec.hpp +5 -0
  29. package/package.json +1 -1
  30. package/src/hooks/useAndroidAutoTelemetry.ts +13 -8
  31. package/src/index.ts +1 -5
  32. package/src/specs/AutoPlay.nitro.ts +37 -0
  33. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridVoice.kt +0 -95
  34. package/ios/hybrid/HybridVoice.swift +0 -63
  35. package/lib/hybrid/HybridVoice.d.ts +0 -12
  36. package/lib/hybrid/HybridVoice.js +0 -13
  37. package/lib/specs/Voice.nitro.d.ts +0 -51
  38. package/lib/specs/Voice.nitro.js +0 -1
  39. package/lib/types/Voice.d.ts +0 -15
  40. package/lib/types/Voice.js +0 -1
  41. package/nitrogen/generated/android/c++/JFunc_void_VoiceInputChunk.hpp +0 -81
  42. package/nitrogen/generated/android/c++/JHybridVoiceSpec.cpp +0 -104
  43. package/nitrogen/generated/android/c++/JHybridVoiceSpec.hpp +0 -66
  44. package/nitrogen/generated/android/c++/JVoiceInputChunk.hpp +0 -64
  45. package/nitrogen/generated/android/c++/JVoiceInputResult.hpp +0 -64
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Func_void_VoiceInputChunk.kt +0 -80
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridVoiceSpec.kt +0 -72
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/VoiceInputChunk.kt +0 -41
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/VoiceInputResult.kt +0 -41
  50. package/nitrogen/generated/ios/c++/HybridVoiceSpecSwift.cpp +0 -11
  51. package/nitrogen/generated/ios/c++/HybridVoiceSpecSwift.hpp +0 -116
  52. package/nitrogen/generated/ios/swift/Func_void_VoiceInputChunk.swift +0 -46
  53. package/nitrogen/generated/ios/swift/HybridVoiceSpec.swift +0 -58
  54. package/nitrogen/generated/ios/swift/HybridVoiceSpec_cxx.swift +0 -227
  55. package/nitrogen/generated/ios/swift/VoiceInputChunk.swift +0 -60
  56. package/nitrogen/generated/ios/swift/VoiceInputResult.swift +0 -60
  57. package/nitrogen/generated/shared/c++/HybridVoiceSpec.cpp +0 -24
  58. package/nitrogen/generated/shared/c++/HybridVoiceSpec.hpp +0 -73
  59. package/nitrogen/generated/shared/c++/VoiceInputChunk.hpp +0 -89
  60. package/nitrogen/generated/shared/c++/VoiceInputResult.hpp +0 -89
  61. package/src/hybrid/HybridVoice.ts +0 -30
  62. package/src/specs/Voice.nitro.ts +0 -58
  63. package/src/types/Voice.ts +0 -17
@@ -196,6 +196,88 @@ open class HybridAutoPlaySpec_cxx {
196
196
  }
197
197
  }
198
198
 
199
+ @inline(__always)
200
+ public final func hasVoiceInputPermission() -> bridge.Result_bool_ {
201
+ do {
202
+ let __result = try self.__implementation.hasVoiceInputPermission()
203
+ let __resultCpp = __result
204
+ return bridge.create_Result_bool_(__resultCpp)
205
+ } catch (let __error) {
206
+ let __exceptionPtr = __error.toCpp()
207
+ return bridge.create_Result_bool_(__exceptionPtr)
208
+ }
209
+ }
210
+
211
+ @inline(__always)
212
+ public final func requestVoiceInputPermission() -> bridge.Result_std__shared_ptr_Promise_bool___ {
213
+ do {
214
+ let __result = try self.__implementation.requestVoiceInputPermission()
215
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_bool__ in
216
+ let __promise = bridge.create_std__shared_ptr_Promise_bool__()
217
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_bool__(__promise)
218
+ __result
219
+ .then({ __result in __promiseHolder.resolve(__result) })
220
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
221
+ return __promise
222
+ }()
223
+ return bridge.create_Result_std__shared_ptr_Promise_bool___(__resultCpp)
224
+ } catch (let __error) {
225
+ let __exceptionPtr = __error.toCpp()
226
+ return bridge.create_Result_std__shared_ptr_Promise_bool___(__exceptionPtr)
227
+ }
228
+ }
229
+
230
+ @inline(__always)
231
+ public final func startVoiceInput(silenceThresholdMs: bridge.std__optional_double_, maxDurationMs: bridge.std__optional_double_, listeningText: bridge.std__optional_std__string_) -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer____ {
232
+ do {
233
+ let __result = try self.__implementation.startVoiceInput(silenceThresholdMs: { () -> Double? in
234
+ if bridge.has_value_std__optional_double_(silenceThresholdMs) {
235
+ let __unwrapped = bridge.get_std__optional_double_(silenceThresholdMs)
236
+ return __unwrapped
237
+ } else {
238
+ return nil
239
+ }
240
+ }(), maxDurationMs: { () -> Double? in
241
+ if bridge.has_value_std__optional_double_(maxDurationMs) {
242
+ let __unwrapped = bridge.get_std__optional_double_(maxDurationMs)
243
+ return __unwrapped
244
+ } else {
245
+ return nil
246
+ }
247
+ }(), listeningText: { () -> String? in
248
+ if bridge.has_value_std__optional_std__string_(listeningText) {
249
+ let __unwrapped = bridge.get_std__optional_std__string_(listeningText)
250
+ return String(__unwrapped)
251
+ } else {
252
+ return nil
253
+ }
254
+ }())
255
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer___ in
256
+ let __promise = bridge.create_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer___()
257
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer___(__promise)
258
+ __result
259
+ .then({ __result in __promiseHolder.resolve(__result.getArrayBuffer()) })
260
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
261
+ return __promise
262
+ }()
263
+ return bridge.create_Result_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer____(__resultCpp)
264
+ } catch (let __error) {
265
+ let __exceptionPtr = __error.toCpp()
266
+ return bridge.create_Result_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer____(__exceptionPtr)
267
+ }
268
+ }
269
+
270
+ @inline(__always)
271
+ public final func stopVoiceInput() -> bridge.Result_void_ {
272
+ do {
273
+ try self.__implementation.stopVoiceInput()
274
+ return bridge.create_Result_void_()
275
+ } catch (let __error) {
276
+ let __exceptionPtr = __error.toCpp()
277
+ return bridge.create_Result_void_(__exceptionPtr)
278
+ }
279
+ }
280
+
199
281
  @inline(__always)
200
282
  public final func setRootTemplate(templateId: std.string) -> bridge.Result_std__shared_ptr_Promise_void___ {
201
283
  do {
@@ -17,6 +17,10 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
17
17
  prototype.registerHybridMethod("addListener", &HybridAutoPlaySpec::addListener);
18
18
  prototype.registerHybridMethod("addListenerRenderState", &HybridAutoPlaySpec::addListenerRenderState);
19
19
  prototype.registerHybridMethod("addListenerVoiceInput", &HybridAutoPlaySpec::addListenerVoiceInput);
20
+ prototype.registerHybridMethod("hasVoiceInputPermission", &HybridAutoPlaySpec::hasVoiceInputPermission);
21
+ prototype.registerHybridMethod("requestVoiceInputPermission", &HybridAutoPlaySpec::requestVoiceInputPermission);
22
+ prototype.registerHybridMethod("startVoiceInput", &HybridAutoPlaySpec::startVoiceInput);
23
+ prototype.registerHybridMethod("stopVoiceInput", &HybridAutoPlaySpec::stopVoiceInput);
20
24
  prototype.registerHybridMethod("setRootTemplate", &HybridAutoPlaySpec::setRootTemplate);
21
25
  prototype.registerHybridMethod("pushTemplate", &HybridAutoPlaySpec::pushTemplate);
22
26
  prototype.registerHybridMethod("popTemplate", &HybridAutoPlaySpec::popTemplate);
@@ -31,6 +31,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { struct NitroAction
31
31
  #include "Location.hpp"
32
32
  #include <optional>
33
33
  #include <NitroModules/Promise.hpp>
34
+ #include <NitroModules/ArrayBuffer.hpp>
34
35
  #include "SafeAreaInsets.hpp"
35
36
  #include "NitroAction.hpp"
36
37
  #include <vector>
@@ -69,6 +70,10 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
69
70
  virtual std::function<void()> addListener(EventName eventType, const std::function<void()>& callback) = 0;
70
71
  virtual std::function<void()> addListenerRenderState(const std::string& moduleName, const std::function<void(VisibilityState /* payload */)>& callback) = 0;
71
72
  virtual std::function<void()> addListenerVoiceInput(const std::function<void(const std::optional<Location>& /* coordinates */, const std::optional<std::string>& /* query */)>& callback) = 0;
73
+ virtual bool hasVoiceInputPermission() = 0;
74
+ virtual std::shared_ptr<Promise<bool>> requestVoiceInputPermission() = 0;
75
+ virtual std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> startVoiceInput(std::optional<double> silenceThresholdMs, std::optional<double> maxDurationMs, const std::optional<std::string>& listeningText) = 0;
76
+ virtual void stopVoiceInput() = 0;
72
77
  virtual std::shared_ptr<Promise<void>> setRootTemplate(const std::string& templateId) = 0;
73
78
  virtual std::shared_ptr<Promise<void>> pushTemplate(const std::string& templateId) = 0;
74
79
  virtual std::shared_ptr<Promise<void>> popTemplate(std::optional<bool> animate) = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iternio/react-native-auto-play",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Android Auto and Apple CarPlay for react-native",
5
5
  "main": "lib/index",
6
6
  "module": "lib/index",
@@ -131,14 +131,19 @@ export const useAndroidAutoTelemetry = ({
131
131
  automotivePermissionRequest.message,
132
132
  automotivePermissionRequest.grantButtonText,
133
133
  automotivePermissionRequest.cancelButtonText
134
- ).then(({ granted, denied }) => {
135
- const isGranted = granted.length === requiredPermissions.length;
136
- setPermissionsGranted(isGranted);
137
-
138
- if (!isGranted) {
139
- setError(`Android Automotive permissions denied: [${denied.join(',')}]`);
140
- }
141
- });
134
+ )
135
+ .then(({ granted, denied }) => {
136
+ const isGranted = granted.length === requiredPermissions.length;
137
+ setPermissionsGranted(isGranted);
138
+
139
+ if (!isGranted) {
140
+ setError(`Android Automotive permissions denied: [${denied.join(',')}]`);
141
+ }
142
+ })
143
+ .catch((e) => {
144
+ const message = e instanceof Error ? e.message : String(e);
145
+ setError(message);
146
+ });
142
147
  return;
143
148
  }
144
149
 
package/src/index.ts CHANGED
@@ -3,14 +3,11 @@ import { NitroModules } from 'react-native-nitro-modules';
3
3
  import AutoPlayHeadlessJsTask from './AutoPlayHeadlessJsTask';
4
4
  import { HybridAndroidAutoTelemetry } from './hybrid/HybridAndroidAutoTelemetry';
5
5
  import { HybridAutoPlay } from './hybrid/HybridAutoPlay';
6
- import { HybridVoice } from './hybrid/HybridVoice';
7
6
  import type { AndroidAutomotive } from './specs/AndroidAutomotive.nitro';
8
7
 
9
8
  AutoPlayHeadlessJsTask.registerHeadlessTask(HybridAutoPlay);
10
9
 
11
- export { HybridAutoPlay };
12
- export { HybridVoice };
13
- export { HybridAndroidAutoTelemetry };
10
+ export { HybridAndroidAutoTelemetry, HybridAutoPlay };
14
11
 
15
12
  export const HybridAndroidAutomotive =
16
13
  Platform.OS === 'android'
@@ -57,7 +54,6 @@ export * from './types/SignInMethod';
57
54
  export * from './types/Telemetry';
58
55
  export * from './types/Text';
59
56
  export * from './types/Trip';
60
- export type { VoiceInputChunk, VoiceInputOptions, VoiceInputResult } from './types/Voice';
61
57
  export type {
62
58
  AlertPriority,
63
59
  NavigationAlert as Alert,
@@ -44,6 +44,43 @@ export interface AutoPlay extends HybridObject<{ android: 'kotlin'; ios: 'swift'
44
44
  callback: (coordinates: Location | undefined, query: string | undefined) => void
45
45
  ): CleanupCallback;
46
46
 
47
+ /**
48
+ * Returns true if microphone permission has already been granted.
49
+ */
50
+ hasVoiceInputPermission(): boolean;
51
+
52
+ /**
53
+ * Request microphone permission from the user.
54
+ * On Android: uses the car context when Android Auto is connected, otherwise
55
+ * falls back to the React Native application context.
56
+ * On iOS: uses AVAudioApplication (iOS 17+) or AVAudioSession (iOS 15–16).
57
+ * Returns true if permission was granted, false if denied.
58
+ */
59
+ requestVoiceInputPermission(): Promise<boolean>;
60
+
61
+ /**
62
+ * Start an in-app voice recording session.
63
+ * On Android: acquires audio focus and captures via CarAudioRecord when
64
+ * Android Auto is connected, otherwise uses standard AudioRecord.
65
+ * On iOS: presents CPVoiceControlTemplate (when a car is connected) and
66
+ * captures audio via AVAudioEngine.
67
+ * Resolves with the complete raw PCM buffer (16 kHz, 16-bit, mono) when
68
+ * silence is detected, the max duration is reached, or stopVoiceInput() is called.
69
+ * Rejects if microphone permission has not been granted or recording fails to start.
70
+ */
71
+ startVoiceInput(
72
+ silenceThresholdMs?: number,
73
+ maxDurationMs?: number,
74
+ listeningText?: string
75
+ ): Promise<ArrayBuffer>;
76
+
77
+ /**
78
+ * Stop the active voice recording session early. Causes the Promise returned
79
+ * by startVoiceInput() to resolve with the audio captured so far.
80
+ * No-op if no recording is in progress.
81
+ */
82
+ stopVoiceInput(): void;
83
+
47
84
  /**
48
85
  * sets the specified template as root template, initializes a new stack
49
86
  * Promise might contain an error message in case setting root template failed
@@ -1,95 +0,0 @@
1
- package com.margelo.nitro.swe.iternio.reactnativeautoplay
2
-
3
- import android.content.pm.PackageManager
4
- import android.os.Build
5
- import androidx.core.content.ContextCompat
6
- import com.facebook.react.modules.core.PermissionAwareActivity
7
- import com.facebook.react.modules.core.PermissionListener
8
- import com.margelo.nitro.NitroModules
9
- import com.margelo.nitro.core.Promise
10
- import kotlinx.coroutines.suspendCancellableCoroutine
11
- import kotlin.coroutines.resume
12
-
13
- class HybridVoice : HybridVoiceSpec() {
14
- @Volatile
15
- private var voiceInputManager: VoiceInputManager? = null
16
-
17
- override fun hasVoiceInputPermission(): Boolean {
18
- return VoiceInputManager.hasVoiceInputPermission()
19
- }
20
-
21
- override fun requestVoiceInputPermission(): Promise<Boolean> {
22
- return Promise.async {
23
- if (hasVoiceInputPermission()) {
24
- return@async true
25
- }
26
-
27
- val carContext = AndroidAutoSession.getRootContext()
28
-
29
- if (carContext != null) {
30
- suspendCancellableCoroutine { cont ->
31
- carContext.requestPermissions(
32
- listOf(android.Manifest.permission.RECORD_AUDIO)
33
- ) { approved, _ ->
34
- cont.resume(approved.contains(android.Manifest.permission.RECORD_AUDIO))
35
- }
36
- }
37
- } else {
38
- val context = NitroModules.applicationContext ?: return@async false
39
- val activity =
40
- context.currentActivity as? PermissionAwareActivity ?: return@async false
41
- val code = (Math.random() * 10000).toInt()
42
-
43
- suspendCancellableCoroutine { cont ->
44
- activity.requestPermissions(
45
- arrayOf(android.Manifest.permission.RECORD_AUDIO),
46
- code,
47
- PermissionListener { requestCode, _, grantResults ->
48
- if (requestCode != code) {
49
- return@PermissionListener false
50
- }
51
- cont.resume(
52
- grantResults.isNotEmpty() &&
53
- grantResults.first() == PackageManager.PERMISSION_GRANTED
54
- )
55
- true
56
- }
57
- )
58
- }
59
- }
60
- }
61
- }
62
-
63
- override fun startVoiceInput(
64
- silenceThresholdMs: Double?,
65
- maxDurationMs: Double?,
66
- listeningText: String?,
67
- preferSpeechToText: Boolean?,
68
- onChunk: ((chunk: VoiceInputChunk) -> Unit)?,
69
- ): Promise<VoiceInputResult> {
70
- return Promise.async {
71
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
72
- throw UnsupportedOperationException("startVoiceInput requires at least API level ${Build.VERSION_CODES.O}")
73
- }
74
-
75
- val manager = VoiceInputManager(AndroidAutoSession.getRootContext())
76
- voiceInputManager = manager
77
-
78
- try {
79
- manager.start(
80
- silenceThresholdMs = silenceThresholdMs?.toLong() ?: 1_500L,
81
- maxDurationMs = maxDurationMs?.toLong() ?: 10_000L,
82
- preferSpeechToText = preferSpeechToText ?: false,
83
- onChunk = onChunk,
84
- )
85
- } finally {
86
- voiceInputManager = null
87
- manager.dispose()
88
- }
89
- }
90
- }
91
-
92
- override fun stopVoiceInput() {
93
- voiceInputManager?.stop()
94
- }
95
- }
@@ -1,63 +0,0 @@
1
- import AVFoundation
2
- import NitroModules
3
- import Speech
4
-
5
- class HybridVoice: HybridVoiceSpec {
6
- private var voiceInputManager: VoiceInputManager?
7
-
8
- func hasVoiceInputPermission() throws -> Bool {
9
- let micGranted = AVAudioSession.sharedInstance().recordPermission == .granted
10
- let speechGranted = SFSpeechRecognizer.authorizationStatus() == .authorized
11
- return micGranted && speechGranted
12
- }
13
-
14
- func requestVoiceInputPermission() throws -> Promise<Bool> {
15
- return Promise.async {
16
- let micGranted = await withCheckedContinuation { cont in
17
- AVAudioSession.sharedInstance().requestRecordPermission { granted in
18
- cont.resume(returning: granted)
19
- }
20
- }
21
- guard micGranted else { return false }
22
-
23
- return await withCheckedContinuation { cont in
24
- SFSpeechRecognizer.requestAuthorization { status in
25
- cont.resume(returning: status == .authorized)
26
- }
27
- }
28
- }
29
- }
30
-
31
- func startVoiceInput(
32
- silenceThresholdMs: Double?,
33
- maxDurationMs: Double?,
34
- listeningText: String?,
35
- preferSpeechToText: Bool?,
36
- onChunk: ((_ chunk: VoiceInputChunk) -> Void)?
37
- ) throws -> Promise<VoiceInputResult> {
38
- return Promise.async {
39
- let interfaceController = try? await RootModule.withInterfaceController { $0 }
40
-
41
- let manager = VoiceInputManager()
42
- self.voiceInputManager = manager
43
-
44
- defer { self.voiceInputManager = nil }
45
-
46
- return try await manager.start(
47
- interfaceController: interfaceController,
48
- silenceThresholdMs: silenceThresholdMs ?? 1_500,
49
- maxDurationMs: maxDurationMs ?? 10_000,
50
- listeningText: listeningText ?? "Listening...",
51
- preferSpeechToText: preferSpeechToText ?? false,
52
- onChunk: onChunk
53
- )
54
- }
55
- }
56
-
57
- func stopVoiceInput() throws {
58
- Task { @MainActor in
59
- let interfaceController = try? await RootModule.withInterfaceController { $0 }
60
- self.voiceInputManager?.stop(interfaceController: interfaceController)
61
- }
62
- }
63
- }
@@ -1,12 +0,0 @@
1
- import type { VoiceInputOptions, VoiceInputResult } from '../types/Voice';
2
- type StartVoiceInput = {
3
- (options: VoiceInputOptions & Required<Pick<VoiceInputOptions, 'onChunk'>>): Promise<void>;
4
- (options?: Omit<VoiceInputOptions, 'onChunk'>): Promise<VoiceInputResult>;
5
- };
6
- export declare const HybridVoice: {
7
- hasVoiceInputPermission: () => boolean;
8
- requestVoiceInputPermission: () => Promise<boolean>;
9
- startVoiceInput: StartVoiceInput;
10
- stopVoiceInput: () => void;
11
- };
12
- export {};
@@ -1,13 +0,0 @@
1
- import { NitroModules } from 'react-native-nitro-modules';
2
- const _native = NitroModules.createHybridObject('Voice');
3
- const startVoiceInput = (async (options) => {
4
- const { onChunk, silenceThresholdMs, maxDurationMs, listeningText, preferSpeechToText } = options ?? {};
5
- const result = await _native.startVoiceInput(silenceThresholdMs, maxDurationMs, listeningText, preferSpeechToText, onChunk);
6
- return onChunk !== undefined ? undefined : result;
7
- });
8
- export const HybridVoice = {
9
- hasVoiceInputPermission: () => _native.hasVoiceInputPermission(),
10
- requestVoiceInputPermission: () => _native.requestVoiceInputPermission(),
11
- startVoiceInput,
12
- stopVoiceInput: () => _native.stopVoiceInput(),
13
- };
@@ -1,51 +0,0 @@
1
- import type { HybridObject } from 'react-native-nitro-modules';
2
- import type { VoiceInputChunk, VoiceInputResult } from '../types/Voice';
3
- export interface Voice extends HybridObject<{
4
- android: 'kotlin';
5
- ios: 'swift';
6
- }> {
7
- /**
8
- * Returns true if all permissions required for voice input are granted.
9
- * On iOS: checks both microphone and speech recognition authorization.
10
- * On Android: checks RECORD_AUDIO permission.
11
- */
12
- hasVoiceInputPermission(): boolean;
13
- /**
14
- * Request all permissions required for voice input.
15
- * On iOS: requests microphone permission then speech recognition authorization.
16
- * On Android: requests RECORD_AUDIO via car context when connected, otherwise
17
- * via the React Native application context.
18
- * Returns true only if all required permissions were granted.
19
- */
20
- requestVoiceInputPermission(): Promise<boolean>;
21
- /**
22
- * Start an in-app voice session.
23
- *
24
- * When preferSpeechToText is true:
25
- * iOS — streams audio buffers into SFSpeechRecognizer during recording;
26
- * onChunk fires with partial transcription results; resolves with
27
- * { transcription } or falls back to { audio } if unavailable.
28
- * Android — checks SpeechRecognizer availability upfront; if available it
29
- * owns the mic and streams partial results via onChunk; if not
30
- * available falls back to PCM recording.
31
- *
32
- * When preferSpeechToText is false (default):
33
- * Both platforms record raw PCM; onChunk fires with audio chunks;
34
- * resolves with { audio }.
35
- *
36
- * @param silenceThresholdMs ms of silence before auto-stop (default 1500)
37
- * @param maxDurationMs hard cap on recording duration (default 10000)
38
- * @param listeningText iOS only — text shown on CPVoiceControlTemplate
39
- * @param preferSpeechToText request STT transcription instead of raw PCM
40
- * @param onChunk optional streaming callback; when set the
41
- * promise resolves with an empty VoiceInputResult
42
- */
43
- startVoiceInput(silenceThresholdMs?: number, maxDurationMs?: number, listeningText?: string, preferSpeechToText?: boolean, onChunk?: (chunk: VoiceInputChunk) => void): Promise<VoiceInputResult>;
44
- /**
45
- * Stop the active voice session early.
46
- * For PCM mode: resolves startVoiceInput with audio captured so far.
47
- * For STT mode: finalises the recognition request.
48
- * No-op if no session is active.
49
- */
50
- stopVoiceInput(): void;
51
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,15 +0,0 @@
1
- export interface VoiceInputChunk {
2
- partial?: string;
3
- audio?: ArrayBuffer;
4
- }
5
- export interface VoiceInputResult {
6
- transcription?: string;
7
- audio?: ArrayBuffer;
8
- }
9
- export interface VoiceInputOptions {
10
- silenceThresholdMs?: number;
11
- maxDurationMs?: number;
12
- listeningText?: string;
13
- preferSpeechToText?: boolean;
14
- onChunk?: (chunk: VoiceInputChunk) => void;
15
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,81 +0,0 @@
1
- ///
2
- /// JFunc_void_VoiceInputChunk.hpp
3
- /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
- /// https://github.com/mrousavy/nitro
5
- /// Copyright © Marc Rousavy @ Margelo
6
- ///
7
-
8
- #pragma once
9
-
10
- #include <fbjni/fbjni.h>
11
- #include <functional>
12
-
13
- #include "VoiceInputChunk.hpp"
14
- #include <functional>
15
- #include <NitroModules/JNICallable.hpp>
16
- #include "JVoiceInputChunk.hpp"
17
- #include <string>
18
- #include <optional>
19
- #include <NitroModules/ArrayBuffer.hpp>
20
- #include <NitroModules/JArrayBuffer.hpp>
21
-
22
- namespace margelo::nitro::swe::iternio::reactnativeautoplay {
23
-
24
- using namespace facebook;
25
-
26
- /**
27
- * Represents the Java/Kotlin callback `(chunk: VoiceInputChunk) -> Unit`.
28
- * This can be passed around between C++ and Java/Kotlin.
29
- */
30
- struct JFunc_void_VoiceInputChunk: public jni::JavaClass<JFunc_void_VoiceInputChunk> {
31
- public:
32
- static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/swe/iternio/reactnativeautoplay/Func_void_VoiceInputChunk;";
33
-
34
- public:
35
- /**
36
- * Invokes the function this `JFunc_void_VoiceInputChunk` instance holds through JNI.
37
- */
38
- void invoke(const VoiceInputChunk& chunk) const {
39
- static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JVoiceInputChunk> /* chunk */)>("invoke");
40
- method(self(), JVoiceInputChunk::fromCpp(chunk));
41
- }
42
- };
43
-
44
- /**
45
- * An implementation of Func_void_VoiceInputChunk that is backed by a C++ implementation (using `std::function<...>`)
46
- */
47
- class JFunc_void_VoiceInputChunk_cxx final: public jni::HybridClass<JFunc_void_VoiceInputChunk_cxx, JFunc_void_VoiceInputChunk> {
48
- public:
49
- static jni::local_ref<JFunc_void_VoiceInputChunk::javaobject> fromCpp(const std::function<void(const VoiceInputChunk& /* chunk */)>& func) {
50
- return JFunc_void_VoiceInputChunk_cxx::newObjectCxxArgs(func);
51
- }
52
-
53
- public:
54
- /**
55
- * Invokes the C++ `std::function<...>` this `JFunc_void_VoiceInputChunk_cxx` instance holds.
56
- */
57
- void invoke_cxx(jni::alias_ref<JVoiceInputChunk> chunk) {
58
- _func(chunk->toCpp());
59
- }
60
-
61
- public:
62
- [[nodiscard]]
63
- inline const std::function<void(const VoiceInputChunk& /* chunk */)>& getFunction() const {
64
- return _func;
65
- }
66
-
67
- public:
68
- static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/swe/iternio/reactnativeautoplay/Func_void_VoiceInputChunk_cxx;";
69
- static void registerNatives() {
70
- registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_VoiceInputChunk_cxx::invoke_cxx)});
71
- }
72
-
73
- private:
74
- explicit JFunc_void_VoiceInputChunk_cxx(const std::function<void(const VoiceInputChunk& /* chunk */)>& func): _func(func) { }
75
-
76
- private:
77
- friend HybridBase;
78
- std::function<void(const VoiceInputChunk& /* chunk */)> _func;
79
- };
80
-
81
- } // namespace margelo::nitro::swe::iternio::reactnativeautoplay