feat: add expo-two-way-audio module to workspace

This commit is contained in:
Mohamed Boudra
2026-03-14 16:46:35 +07:00
parent fc7369384b
commit cad4110e24
74 changed files with 48803 additions and 354 deletions
@@ -0,0 +1,5 @@
import { requireNativeModule } from "expo-modules-core";
// It loads the native module object from the JSI or falls back to
// the bridge module (from NativeModulesProxy) if the remote debugger is on.
export default requireNativeModule("ExpoTwoWayAudio");
+62
View File
@@ -0,0 +1,62 @@
import { type PermissionResponse, createPermissionHook } from "expo-modules-core";
import ExpoTwoWayAudioModule from "./ExpoTwoWayAudioModule";
export async function initialize() {
return await ExpoTwoWayAudioModule.initialize();
}
export function playPCMData(audioData: Uint8Array) {
return ExpoTwoWayAudioModule.playPCMData(audioData);
}
export function bypassVoiceProcessing(bypass: boolean) {
return ExpoTwoWayAudioModule.bypassVoiceProcessing(bypass);
}
export function toggleRecording(val: boolean): boolean {
return ExpoTwoWayAudioModule.toggleRecording(val);
}
export function isRecording(): boolean {
return ExpoTwoWayAudioModule.isRecording();
}
export function tearDown() {
return ExpoTwoWayAudioModule.tearDown();
}
export function restart() {
return ExpoTwoWayAudioModule.restart();
}
export async function getMicrophonePermissionsAsync(): Promise<PermissionResponse> {
return ExpoTwoWayAudioModule.getMicrophonePermissionsAsync();
}
export async function requestMicrophonePermissionsAsync(): Promise<PermissionResponse> {
return ExpoTwoWayAudioModule.requestMicrophonePermissionsAsync();
}
export function getMicrophoneModeIOS() {
return ExpoTwoWayAudioModule.getMicrophoneModeIOS();
}
export function setMicrophoneModeIOS() {
return ExpoTwoWayAudioModule.setMicrophoneModeIOS();
}
export function isPlaying(): boolean {
return ExpoTwoWayAudioModule.isPlaying();
}
export function stopPlayback() {
return ExpoTwoWayAudioModule.stopPlayback();
}
export function pausePlayback() {
return ExpoTwoWayAudioModule.pausePlayback();
}
export function resumePlayback() {
return ExpoTwoWayAudioModule.resumePlayback();
}
+38
View File
@@ -0,0 +1,38 @@
import ExpoTwoWayAudioModule from "./ExpoTwoWayAudioModule";
export type MicrophoneDataEvent = {
data: Uint8Array;
};
export type VolumeLevelEvent = {
data: number;
};
export type RecordingChangeEvent = {
data: boolean;
};
export type AudioInterruptionEvent = {
data: string;
};
export interface ExpoTwoWayAudioEventMap {
onMicrophoneData: MicrophoneDataEvent;
onInputVolumeLevelData: VolumeLevelEvent;
onOutputVolumeLevelData: VolumeLevelEvent;
onRecordingChange: RecordingChangeEvent;
onAudioInterruption: AudioInterruptionEvent;
}
// These are useful for defining `useCallback` types inline
export type MicrophoneDataCallback = (event: MicrophoneDataEvent) => void;
export type VolumeLevelCallback = (event: VolumeLevelEvent) => void;
export type RecordingChangeCallback = (event: RecordingChangeEvent) => void;
export type AudioInterruptionCallback = (event: AudioInterruptionEvent) => void;
export function addExpoTwoWayAudioEventListener<K extends keyof ExpoTwoWayAudioEventMap>(
eventName: K,
handler: (ev: ExpoTwoWayAudioEventMap[K]) => void,
) {
return ExpoTwoWayAudioModule.addListener(eventName, handler);
}
+34
View File
@@ -0,0 +1,34 @@
import { createPermissionHook } from "expo-modules-core";
import { useEffect, useSyncExternalStore } from "react";
import {
getMicrophonePermissionsAsync,
isRecording,
requestMicrophonePermissionsAsync,
} from "./core";
import { ExpoTwoWayAudioEventMap, addExpoTwoWayAudioEventListener } from "./events";
export const useMicrophonePermissions = createPermissionHook({
getMethod: getMicrophonePermissionsAsync,
requestMethod: requestMicrophonePermissionsAsync,
});
export function useIsRecording() {
const subscribe = (cb: () => void) => {
const sub = addExpoTwoWayAudioEventListener("onRecordingChange", cb);
return () => sub.remove();
};
const getSnapshot = () => isRecording();
const getServerSnapshot = () => false;
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
}
export function useExpoTwoWayAudioEventListener<K extends keyof ExpoTwoWayAudioEventMap>(
eventName: K,
listener: (ev: ExpoTwoWayAudioEventMap[K]) => void,
) {
useEffect(() => {
const sub = addExpoTwoWayAudioEventListener(eventName, listener);
return () => sub.remove();
}, [listener]);
}
+3
View File
@@ -0,0 +1,3 @@
export * from "./core";
export * from "./events";
export * from "./hooks";