@iternio/react-native-auto-play 0.4.12 → 0.5.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/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VoiceInputManager.kt +16 -8
- package/ios/utils/VoiceInputManager.swift +8 -2
- package/package.json +1 -1
- package/lib/HybridAutoPlay.d.ts +0 -2
- package/lib/HybridAutoPlay.js +0 -2
- package/lib/components/OnAppearedChildRenderer.d.ts +0 -10
- package/lib/components/OnAppearedChildRenderer.js +0 -26
- package/lib/hooks/useIsAutoPlayFocused.d.ts +0 -7
- package/lib/hooks/useIsAutoPlayFocused.js +0 -20
- package/lib/hybrid.d.ts +0 -2
- package/lib/hybrid.js +0 -2
- package/lib/specs/AutomotivePermissionRequestTemplate.d.ts +0 -11
- package/lib/specs/AutomotivePermissionRequestTemplate.js +0 -1
- package/lib/specs/AutomotivePermissionRequestTemplate.nitro.d.ts +0 -11
- package/lib/specs/AutomotivePermissionRequestTemplate.nitro.js +0 -1
- package/lib/templates/AutomotivePermissionRequestTemplate.d.ts +0 -23
- package/lib/templates/AutomotivePermissionRequestTemplate.js +0 -18
- package/lib/types/Glyphmap.d.ts +0 -4105
- package/lib/types/Glyphmap.js +0 -4105
package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VoiceInputManager.kt
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package com.margelo.nitro.swe.iternio.reactnativeautoplay
|
|
2
2
|
|
|
3
|
+
import android.Manifest
|
|
3
4
|
import android.annotation.SuppressLint
|
|
5
|
+
import android.content.Context
|
|
4
6
|
import android.content.Intent
|
|
5
7
|
import android.content.pm.PackageManager
|
|
6
8
|
import android.media.AudioAttributes
|
|
@@ -91,7 +93,7 @@ class VoiceInputManager(
|
|
|
91
93
|
// MARK: - STT path (SpeechRecognizer owns the mic)
|
|
92
94
|
|
|
93
95
|
private suspend fun startSTT(
|
|
94
|
-
context:
|
|
96
|
+
context: Context,
|
|
95
97
|
onChunk: ((chunk: VoiceInputChunk) -> Unit)?,
|
|
96
98
|
language: String?
|
|
97
99
|
): VoiceInputResult = suspendCancellableCoroutine { cont ->
|
|
@@ -110,8 +112,7 @@ class VoiceInputManager(
|
|
|
110
112
|
override fun onError(error: Int) {
|
|
111
113
|
activeSpeechRecognizer = null
|
|
112
114
|
recognizer.destroy()
|
|
113
|
-
|
|
114
|
-
cont.resume(VoiceInputResult(transcription = null, audio = null))
|
|
115
|
+
cont.resumeWithException(RuntimeException("SpeechRecognizer error $error"))
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
override fun onPartialResults(partialResults: Bundle?) {
|
|
@@ -173,12 +174,14 @@ class VoiceInputManager(
|
|
|
173
174
|
}.getOrThrow()
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
var pcmBytes: ByteArray
|
|
176
178
|
try {
|
|
177
|
-
recordPCM(silenceThresholdMs, maxDurationMs) { chunk ->
|
|
179
|
+
pcmBytes = recordPCM(silenceThresholdMs, maxDurationMs) { chunk ->
|
|
178
180
|
chunk.audio?.let { ab ->
|
|
179
181
|
try {
|
|
180
182
|
pipeOut.write(ab.toByteArray())
|
|
181
183
|
} catch (_: Exception) {
|
|
184
|
+
isRecording = false
|
|
182
185
|
}
|
|
183
186
|
}
|
|
184
187
|
}
|
|
@@ -193,12 +196,17 @@ class VoiceInputManager(
|
|
|
193
196
|
}
|
|
194
197
|
}
|
|
195
198
|
|
|
196
|
-
return
|
|
199
|
+
return try {
|
|
200
|
+
sttDeferred.await()
|
|
201
|
+
} catch (_: Exception) {
|
|
202
|
+
val directBuffer = ByteBuffer.allocateDirect(pcmBytes.size).put(pcmBytes).rewind() as ByteBuffer
|
|
203
|
+
VoiceInputResult(transcription = null, audio = ArrayBuffer.wrap(directBuffer))
|
|
204
|
+
}
|
|
197
205
|
}
|
|
198
206
|
|
|
199
207
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|
200
208
|
private suspend fun startSTTWithSource(
|
|
201
|
-
context:
|
|
209
|
+
context: Context,
|
|
202
210
|
audioSource: ParcelFileDescriptor,
|
|
203
211
|
silenceThresholdMs: Long,
|
|
204
212
|
onChunk: ((chunk: VoiceInputChunk) -> Unit)?,
|
|
@@ -223,7 +231,7 @@ class VoiceInputManager(
|
|
|
223
231
|
override fun onError(error: Int) {
|
|
224
232
|
activeSpeechRecognizer = null
|
|
225
233
|
recognizer.destroy()
|
|
226
|
-
cont.
|
|
234
|
+
cont.resumeWithException(RuntimeException("SpeechRecognizer error $error"))
|
|
227
235
|
}
|
|
228
236
|
|
|
229
237
|
override fun onPartialResults(partialResults: Bundle?) {
|
|
@@ -473,7 +481,7 @@ class VoiceInputManager(
|
|
|
473
481
|
fun hasVoiceInputPermission(): Boolean {
|
|
474
482
|
val context = NitroModules.applicationContext ?: return false
|
|
475
483
|
return ContextCompat.checkSelfPermission(
|
|
476
|
-
context,
|
|
484
|
+
context, Manifest.permission.RECORD_AUDIO
|
|
477
485
|
) == PackageManager.PERMISSION_GRANTED
|
|
478
486
|
}
|
|
479
487
|
}
|
|
@@ -103,6 +103,7 @@ class VoiceInputManager {
|
|
|
103
103
|
}
|
|
104
104
|
isStopping = true
|
|
105
105
|
let wasSTTMode = isSTTMode
|
|
106
|
+
let capturedRequest = recognitionRequest
|
|
106
107
|
let box = resultBox
|
|
107
108
|
let capturedSamples = samples
|
|
108
109
|
resultBox = nil
|
|
@@ -112,7 +113,7 @@ class VoiceInputManager {
|
|
|
112
113
|
if wasSTTMode {
|
|
113
114
|
// endAudio() causes the recognition task to fire its final result,
|
|
114
115
|
// which resumes the box. Engine teardown happens there too.
|
|
115
|
-
|
|
116
|
+
capturedRequest?.endAudio()
|
|
116
117
|
}
|
|
117
118
|
else {
|
|
118
119
|
cleanup(interfaceController: interfaceController)
|
|
@@ -161,6 +162,7 @@ class VoiceInputManager {
|
|
|
161
162
|
if error != nil {
|
|
162
163
|
// STT failed — fall back to whatever PCM was accumulated
|
|
163
164
|
self.stopLock.lock()
|
|
165
|
+
self.isStopping = true
|
|
164
166
|
let capturedSamples = self.samples
|
|
165
167
|
self.samples = []
|
|
166
168
|
self.stopLock.unlock()
|
|
@@ -233,7 +235,11 @@ class VoiceInputManager {
|
|
|
233
235
|
|
|
234
236
|
let frameCount = Int(outputBuffer.frameLength)
|
|
235
237
|
let newSamples = Array(UnsafeBufferPointer(start: int16Data[0], count: frameCount))
|
|
236
|
-
self.
|
|
238
|
+
self.stopLock.lock()
|
|
239
|
+
if !self.isStopping {
|
|
240
|
+
self.samples.append(contentsOf: newSamples)
|
|
241
|
+
}
|
|
242
|
+
self.stopLock.unlock()
|
|
237
243
|
|
|
238
244
|
// PCM chunk callback
|
|
239
245
|
if activeRecognitionRequest == nil, let onChunk {
|
package/package.json
CHANGED
package/lib/HybridAutoPlay.d.ts
DELETED
package/lib/HybridAutoPlay.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
type Props = {
|
|
2
|
-
children: React.ReactNode;
|
|
3
|
-
moduleName: string;
|
|
4
|
-
};
|
|
5
|
-
/**
|
|
6
|
-
* renders the passed children when the specified scene/screen appeared
|
|
7
|
-
* this makes sure child hooks are executed only when the map template is ready
|
|
8
|
-
*/
|
|
9
|
-
export default function OnAppearedChildRenderer({ children, moduleName }: Props): import("react").ReactNode;
|
|
10
|
-
export {};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import { HybridAutoPlay } from '../hybrid/HybridAutoPlay';
|
|
3
|
-
/**
|
|
4
|
-
* renders the passed children when the specified scene/screen appeared
|
|
5
|
-
* this makes sure child hooks are executed only when the map template is ready
|
|
6
|
-
*/
|
|
7
|
-
export default function OnAppearedChildRenderer({ children, moduleName }) {
|
|
8
|
-
const [didAppear, setDidAppear] = useState(false);
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
let remove = HybridAutoPlay.addListenerRenderState(moduleName, (renderState) => {
|
|
11
|
-
if (renderState === 'didAppear') {
|
|
12
|
-
remove?.();
|
|
13
|
-
remove = null;
|
|
14
|
-
setDidAppear(true);
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
return () => {
|
|
18
|
-
remove?.();
|
|
19
|
-
remove = null;
|
|
20
|
-
};
|
|
21
|
-
}, [moduleName]);
|
|
22
|
-
if (didAppear) {
|
|
23
|
-
return children;
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A hook to determine if the CarPlay/Android Auto screen is currently focused (visible).
|
|
3
|
-
*
|
|
4
|
-
* @param moduleName The name of the module to listen to.
|
|
5
|
-
* @returns `true` if the screen is focused, `false` otherwise.
|
|
6
|
-
*/
|
|
7
|
-
export declare function useIsAutoPlayFocused(moduleName: string): boolean;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import { HybridAutoPlay } from '..';
|
|
3
|
-
/**
|
|
4
|
-
* A hook to determine if the CarPlay/Android Auto screen is currently focused (visible).
|
|
5
|
-
*
|
|
6
|
-
* @param moduleName The name of the module to listen to.
|
|
7
|
-
* @returns `true` if the screen is focused, `false` otherwise.
|
|
8
|
-
*/
|
|
9
|
-
export function useIsAutoPlayFocused(moduleName) {
|
|
10
|
-
const [isFocused, setIsFocused] = useState(false);
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
const remove = HybridAutoPlay.addListenerRenderState(moduleName, (state) => {
|
|
13
|
-
setIsFocused(state === 'didAppear');
|
|
14
|
-
});
|
|
15
|
-
return () => {
|
|
16
|
-
remove();
|
|
17
|
-
};
|
|
18
|
-
}, [moduleName]);
|
|
19
|
-
return isFocused;
|
|
20
|
-
}
|
package/lib/hybrid.d.ts
DELETED
package/lib/hybrid.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
-
import type { NitroAutomotivePermissionRequestTemplateConfig } from '../templates/AutomotivePermissionRequestTemplate';
|
|
3
|
-
import type { NitroTemplateConfig } from './AutoPlay.nitro';
|
|
4
|
-
interface AutomotivePermissionRequestTemplateConfig extends NitroTemplateConfig, NitroAutomotivePermissionRequestTemplateConfig {
|
|
5
|
-
}
|
|
6
|
-
export interface AutomotivePermissionRequestTemplate extends HybridObject<{
|
|
7
|
-
android: 'kotlin';
|
|
8
|
-
}> {
|
|
9
|
-
createAutomotivePermissionRequestTemplate(config: AutomotivePermissionRequestTemplateConfig): void;
|
|
10
|
-
}
|
|
11
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
-
import type { NitroAutomotivePermissionRequestTemplateConfig } from '../templates/AutomotivePermissionRequestTemplate';
|
|
3
|
-
import type { NitroTemplateConfig } from './AutoPlay.nitro';
|
|
4
|
-
interface AutomotivePermissionRequestTemplateConfig extends NitroTemplateConfig, NitroAutomotivePermissionRequestTemplateConfig {
|
|
5
|
-
}
|
|
6
|
-
export interface AutomotivePermissionRequestTemplate extends HybridObject<{
|
|
7
|
-
android: 'kotlin';
|
|
8
|
-
}> {
|
|
9
|
-
createAutomotivePermissionRequestTemplate(config: AutomotivePermissionRequestTemplateConfig): void;
|
|
10
|
-
}
|
|
11
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { CustomActionButtonAndroid } from '../types/Button';
|
|
2
|
-
import type { AutoText } from '../types/Text';
|
|
3
|
-
import { type NitroAction } from '../utils/NitroAction';
|
|
4
|
-
import { type HeaderActions, Template, type TemplateConfig } from './Template';
|
|
5
|
-
export interface NitroAutomotivePermissionRequestTemplateConfig extends TemplateConfig {
|
|
6
|
-
headerActions?: Array<NitroAction>;
|
|
7
|
-
title: AutoText;
|
|
8
|
-
actions: Array<NitroAction>;
|
|
9
|
-
}
|
|
10
|
-
export type AutomotivePermissionRequestTemplateConfig = Omit<NitroAutomotivePermissionRequestTemplateConfig, 'headerActions' | 'buttons'> & {
|
|
11
|
-
/**
|
|
12
|
-
* action buttons, usually at the the top right on Android and a top bar on iOS
|
|
13
|
-
*/
|
|
14
|
-
headerActions?: HeaderActions<AutomotivePermissionRequestTemplate>;
|
|
15
|
-
actions: [CustomActionButtonAndroid<AutomotivePermissionRequestTemplate>] | [
|
|
16
|
-
CustomActionButtonAndroid<AutomotivePermissionRequestTemplate>,
|
|
17
|
-
CustomActionButtonAndroid<AutomotivePermissionRequestTemplate>
|
|
18
|
-
];
|
|
19
|
-
};
|
|
20
|
-
export declare class AutomotivePermissionRequestTemplate extends Template<AutomotivePermissionRequestTemplateConfig, HeaderActions<AutomotivePermissionRequestTemplate>> {
|
|
21
|
-
private template;
|
|
22
|
-
constructor(config: AutomotivePermissionRequestTemplateConfig);
|
|
23
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { NitroModules } from 'react-native-nitro-modules';
|
|
2
|
-
import { NitroActionUtil } from '../utils/NitroAction';
|
|
3
|
-
import { Template, } from './Template';
|
|
4
|
-
const HybridAutomotivePermissionRequestTemplate = NitroModules.createHybridObject('AutomotivePermissionRequestTemplate');
|
|
5
|
-
export class AutomotivePermissionRequestTemplate extends Template {
|
|
6
|
-
template = this;
|
|
7
|
-
constructor(config) {
|
|
8
|
-
super(config);
|
|
9
|
-
const { headerActions, actions, ...rest } = config;
|
|
10
|
-
const nitroConfig = {
|
|
11
|
-
...rest,
|
|
12
|
-
id: this.id,
|
|
13
|
-
headerActions: NitroActionUtil.convert(this.template, headerActions),
|
|
14
|
-
actions: NitroActionUtil.convert(this.template, actions),
|
|
15
|
-
};
|
|
16
|
-
HybridAutomotivePermissionRequestTemplate.createAutomotivePermissionRequestTemplate(nitroConfig);
|
|
17
|
-
}
|
|
18
|
-
}
|