diff --git a/.gitignore b/.gitignore index 16871cc8..f63fe0df 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ local.properties # Visual Studio Code .vscode/ +.gradle diff --git a/README.md b/README.md index 40d3dabe..38c21934 100644 --- a/README.md +++ b/README.md @@ -1,263 +1,207 @@ -![CircleCI branch][circle-ci-badge] -[![npm][npm]][npm-url] +# React Native Voice -

React Native Voice

-

A speech-to-text library for React Native.

+[![npm](https://img.shields.io/npm/v/@dev-amirzubair/react-native-voice.svg?style=flat-square)](https://npmjs.com/package/@dev-amirzubair/react-native-voice) - -chat on Discord +A speech-to-text library for [React Native](https://reactnative.dev/) with **New Architecture (Fabric/TurboModules)** and **Bridgeless mode** support. -```sh -yarn add @react-native-voice/voice - -# or - -npm i @react-native-voice/voice --save -``` - -Link the iOS package - -```sh -npx pod-install -``` +> **Note:** This library is a fork of [@react-native-voice/voice](https://github.com/react-native-voice/voice) with custom fixes for React Native 0.76+ and the New Architecture. [View source on GitHub](https://github.com/dev-amirzubair/voice) -## Table of contents +## What's Different? -- [Linking](#linking) - - [Manually Link Android](#manually-link-android) - - [Manually Link iOS](#manually-link-ios) -- [Prebuild Plugin](#prebuild-plugin) -- [Usage](#usage) - - [Example](#example) -- [API](#api) -- [Events](#events) -- [Permissions](#permissions) - - [Android](#android) - - [iOS](#ios) -- [Contributors](#contributors) +This fork includes the following improvements over the original library: -

Linking

+- ✅ **New Architecture Support** - Works with Fabric and TurboModules +- ✅ **Bridgeless Mode** - Full support for React Native's Bridgeless mode +- ✅ **React Native 0.76+** - Tested and working with the latest RN versions +- ✅ **Fixed Android Event Emission** - Events properly reach JavaScript in new architecture +- ✅ **Fixed iOS TurboModule Registration** - Proper fallback handling for iOS +- ✅ **Improved Locale Handling** - Better support for Indo-Pak region languages +- ✅ **Clean TypeScript Types** - Updated type definitions -

Manually or automatically link the NativeModule

+## Installation ```sh -react-native link @react-native-voice/voice -``` - -### Manually Link Android +yarn add @dev-amirzubair/react-native-voice -- In `android/setting.gradle` +# or -```gradle -... -include ':@react-native-voice_voice', ':app' -project(':@react-native-voice_voice').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-voice/voice/android') +npm install @dev-amirzubair/react-native-voice --save ``` -- In `android/app/build.gradle` +### iOS Setup -```gradle -... -dependencies { - ... - compile project(':@react-native-voice_voice') -} +```sh +cd ios && pod install ``` -- In `MainApplication.java` - -```java - -import android.app.Application; -import com.facebook.react.ReactApplication; -import com.facebook.react.ReactPackage; -... -import com.wenkesj.voice.VoicePackage; // <------ Add this! -... - -public class MainActivity extends Activity implements ReactApplication { -... - @Override - protected List getPackages() { - return Arrays.asList( - new MainReactPackage(), - new VoicePackage() // <------ Add this! - ); - } -} -``` +### Android Setup -### Manually Link iOS +No additional setup required - autolinking handles everything. -- Drag the Voice.xcodeproj from the @react-native-voice/voice/ios folder to the Libraries group on Xcode in your poject. [Manual linking](https://reactnative.dev/docs/linking-libraries-ios.html) +## Usage -- Click on your main project file (the one that represents the .xcodeproj) select Build Phases and drag the static library, lib.Voice.a, from the Libraries/Voice.xcodeproj/Products folder to Link Binary With Libraries +```javascript +import Voice from '@dev-amirzubair/react-native-voice'; -

Prebuild Plugin

+// Set up event handlers +Voice.onSpeechStart = () => console.log('Speech started'); +Voice.onSpeechEnd = () => console.log('Speech ended'); +Voice.onSpeechResults = (e) => console.log('Results:', e.value); +Voice.onSpeechPartialResults = (e) => console.log('Partial:', e.value); +Voice.onSpeechError = (e) => console.log('Error:', e.error); -> This package cannot be used in the "Expo Go" app because [it requires custom native code](https://docs.expo.io/workflow/customizing/). +// Start listening +await Voice.start('en-US'); -After installing this npm package, add the [config plugin](https://docs.expo.io/guides/config-plugins/) to the [`plugins`](https://docs.expo.io/versions/latest/config/app/#plugins) array of your `app.json` or `app.config.js`: +// Stop listening +await Voice.stop(); -```json -{ - "expo": { - "plugins": ["@react-native-voice/voice"] - } -} +// Clean up +await Voice.destroy(); ``` -Next, rebuild your app as described in the ["Adding custom native code"](https://docs.expo.io/workflow/customizing/) guide. - -### Props - -The plugin provides props for extra customization. Every time you change the props or plugins, you'll need to rebuild (and `prebuild`) the native app. If no extra properties are added, defaults will be used. +### Full Example -- `speechRecognition` (_string | false_): Sets the message for the `NSSpeechRecognitionUsageDescription` key in the `Info.plist` message. When undefined, a default permission message will be used. When `false`, the permission will be skipped. -- `microphone` (_string | false_): Sets the message for the `NSMicrophoneUsageDescription` key in the `Info.plist`. When undefined, a default permission message will be used. When `false`, the `android.permission.RECORD_AUDIO` will not be added to the `AndroidManifest.xml` and the iOS permission will be skipped. - -### Example +```javascript +import React, { useEffect, useState, useCallback } from 'react'; +import { View, Text, Button } from 'react-native'; +import Voice from '@dev-amirzubair/react-native-voice'; + +function SpeechToText() { + const [results, setResults] = useState([]); + const [isListening, setIsListening] = useState(false); + + useEffect(() => { + Voice.onSpeechStart = () => setIsListening(true); + Voice.onSpeechEnd = () => setIsListening(false); + Voice.onSpeechResults = (e) => setResults(e.value ?? []); + Voice.onSpeechError = (e) => console.error(e.error); + + return () => { + Voice.destroy().then(Voice.removeAllListeners); + }; + }, []); + + const startListening = async () => { + try { + await Voice.start('en-US'); + } catch (e) { + console.error(e); + } + }; -```json -{ - "plugins": [ - [ - "@react-native-voice/voice", - { - "microphonePermission": "CUSTOM: Allow $(PRODUCT_NAME) to access the microphone", - "speechRecognitionPermission": "CUSTOM: Allow $(PRODUCT_NAME) to securely recognize user speech" - } - ] - ] + const stopListening = async () => { + try { + await Voice.stop(); + } catch (e) { + console.error(e); + } + }; + + return ( + + {isListening ? '🎤 Listening...' : 'Press Start'} + {results.join(' ')} +