# Onairos React Native SDK

A React Native SDK for integrating Onairos authentication and AI model training into your mobile applications. This package provides a complete solution for social media platform connection, secure authentication, and AI model training.

## Features

- Universal onboarding flow with multi-platform support
- Multi-platform OAuth authentication (Pinterest, YouTube, LinkedIn, Gmail, Reddit)
- Real-time AI model training with Socket.io integration
- Secure credential management with biometric authentication
- PIN-based security with validation and encryption
- Deep linking support for OAuth callbacks
- Email verification and account management
- Existing user detection and data confirmation
- Background training optimization
- Comprehensive error handling and retry logic
- Haptic feedback integration
- Customizable UI components
- Full TypeScript support

## Installation

```bash
npm install @onairos/react-native
# or
yarn add @onairos/react-native
```

## 🎯 Example App

A complete example app is available in the `example/` directory demonstrating real-world SDK integration:

```bash
cd example
npm install
npm run ios  # or npm run android
```

The example app showcases:
- ✅ SDK initialization and configuration
- ✅ OnairosButton component integration
- ✅ WelcomeScreen component usage
- ✅ Custom styling options
- ✅ JWT token handling and user data extraction
- ✅ Error handling and debugging

See [`example/README.md`](./example/README.md) for detailed setup instructions.

### TypeScript Support

The package includes full TypeScript declarations. Import types directly:

```typescript
import { OnairosButton, OnairosCredentials, PlatformConfig } from '@onairos/react-native';

// Type your component props
const MyComponent: React.FC<{ credentials: OnairosCredentials }> = ({ credentials }) => {
  // Your component code
};

// Type your handlers
const handleResolved = (apiUrl: string, accessToken: string, loginDetails: any) => {
  console.log('Authentication successful:', { apiUrl, accessToken, loginDetails });
};
```

### Required Dependencies

The package requires the following dependencies:

```bash
# Core dependencies
yarn add @gorhom/bottom-sheet react-native-reanimated react-native-gesture-handler react-native-safe-area-context

# Authentication dependencies
yarn add react-native-webview react-native-keychain 

# UI dependencies
yarn add react-native-vector-icons

# Network and encryption
yarn add @react-native-community/netinfo react-native-rsa-native react-native-crypto-js
```

### iOS Setup

1. Install pods:
```bash
cd ios && pod install
```

2. Add the following to your `Info.plist`:
```xml
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <!-- <string>onairosreact</string> -->
      <string>onairosanime</string>
    </array>
  </dict>
</array>

<!-- Add for biometric authentication -->
<key>NSFaceIDUsageDescription</key>
<string>We use Face ID to securely access your Onairos account</string>
```

3. Configure your OAuth providers in the project settings and register the callback URLs.

### Android Setup

1. Add the following to your `android/app/src/main/AndroidManifest.xml`:
```xml
<activity>
  <!-- ... -->
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <!-- <data android:scheme="onairosreact" /> -->
    <data android:scheme="onairosanime" />
  </intent-filter>
</activity>
```

2. Add biometric permissions:
```xml
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
```

## Usage

📖 **[Quick Integration Guide](./QUICK_INTEGRATION_GUIDE.md) - Start here for immediate copy-paste setup!**

📖 **For comprehensive usage examples in both JavaScript and TypeScript, see [USAGE_EXAMPLES.md](./USAGE_EXAMPLES.md)**

### Important: Setup Portal Host

For modals and overlays to appear properly, you must wrap your app with the `PortalHost` component:

```javascript
import { PortalHost } from '@onairos/react-native';

export default function App() {
  return (
    <PortalHost>
      {/* Your app content goes here */}
      <MainNavigator />
    </PortalHost>
  );
}
```

### Basic Button Integration

1. Import and initialize the SDK:
```javascript
import { OnairosButton, initializeApiKey } from '@onairos/react-native';

// Initialize once at app startup
await initializeApiKey({ apiKey: 'YOUR_API_KEY' });
```

2. Use the component in your app:
```javascript
export default function App() {
  const handleComplete = (result) => {
    console.log('API URL:', result.apiUrl);
    console.log('Token:', result.token);
    console.log('User data:', result.apiResponse);
    console.log('Authorized data:', result.authorizedData);
    // authorizedData = { basic: true, personality: true, preferences: true, ... }
  };

  return (
    <View style={styles.container}>
      <OnairosButton
        AppName="YourApp"
        autoFetch={true}
        onComplete={handleComplete}
        requestData={{
          personality: {
            name: 'Personality Traits',
            description: 'Your personality profile',
          },
          preferences: {
            name: 'Content Analysis',
            description: 'Inference and sentiment',
          },
        }}
      />
    </View>
  );
}
```

### External Auth Token Support

If your app already handles authentication, pass the user JWT to SDK APIs:

```javascript
import { setUserToken, clearUserToken } from '@onairos/react-native';

// After your app login succeeds
await setUserToken(userJwtToken);

// Later, when user logs out
await clearUserToken();
```

Security-migrated backend routes (`/sendModel`, `/updateAccountInfo`, `/inferenceUsername`) now require this user JWT and ignore `username` fields sent in request bodies.

### requestData Configuration

The `requestData` prop controls which consent options appear on the DataRequest screen.

**Valid keys:**
| Key | Description | When Shown |
|-----|-------------|------------|
| `basic` | Basic profile info | Always shown |
| `personality` | Personality traits (LLM profile) | If included |
| `preferences` | Inference/sentiment (ML model) | If included |
| `rawMemories` | Raw LLM conversation data | If included AND LLM connected |

**Supported formats:**

```javascript
// Object format (full control)
requestData={{
  personality: { name: 'Personality', description: '...' },
  preferences: { name: 'Content Analysis', description: '...' },
}}

// Array format (uses SDK default descriptions)
requestData={['personality', 'preferences']}
```

**Note:** If `requestData` is not provided, only "Basic Profile" is shown and a warning is logged.

### Initialize OAuth Service

Add this to your app's entry point to handle deep linking for OAuth:

```javascript
import { initializeOAuthService } from '@onairos/react-native';

// In your app's entry point
useEffect(() => {
  // Set up OAuth deep linking
  initializeOAuthService();
  
  // Clean up when component unmounts
  return () => {
    cleanupOAuthService();
  };
}, []);
```

### Working with Secure Storage

```javascript
import { storeCredentials, getCredentials, hasCredentials } from '@onairos/react-native';

// Check if user has stored credentials
const checkAuth = async () => {
  const hasExisting = await hasCredentials();
  
  if (hasExisting) {
    // Get credentials with biometric authentication
    const credentials = await getCredentials({
      useBiometrics: true,
      biometricPrompt: {
        title: 'Authenticate to continue',
        subtitle: 'Please verify your identity'
      }
    });
    
    if (credentials) {
      // User is authenticated
      console.log('User authenticated:', credentials.username);
    }
  } else {
    // Redirect to onboarding flow
    setShowOnboarding(true);
  }
};
```

## API Reference

### Main Components

#### `OnairosButton`

The main entry point for Onairos authentication with full training flow support.

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| AppName | string | Yes | Your application name |
| requestData | object/array | Yes | Consent options to show (see below) |
| onComplete | function | Yes | Callback with `OnairosResult` object |
| autoFetch | boolean | No | Auto-fetch approved data after consent (default: true) |
| backgroundLoadData | boolean | No | Skip SDK training UI and return training metadata for host-side handling (default: false) |
| trainingScreenMode | 'mock' \| 'fast' \| 'real' \| 'none' | No | Training UI behavior. Defaults to `fast`, or `none` when `backgroundLoadData=true` |
| appIcon | ImageSource | No | Your app icon for onboarding UI |
| buttonType | 'circle' \| 'pill' | No | Button style (default: 'circle') |
| color | string | No | Button color (default: #00BFA5) |
| debug | boolean | No | Enable debug mode (default: false) |

**requestData keys:** `basic` (always shown), `personality`, `preferences`, `rawMemories`

`onComplete(result)` is the primary completion callback. `onResolved(apiUrl, token, userData)` is still supported for older integrations, but new code should use `onComplete`.

When `autoFetch=false`, the SDK returns `apiUrl`, `token`, consent/authorization metadata, and training metadata so the host app can fetch final data itself.

**OnairosResult:**
```typescript
{
  apiUrl: string;
  token: string;
  userData: object;
  apiResponse?: object;       // If autoFetch=true
  authorizedData?: object;    // What user consented to
  training?: { ready: boolean; statusUrl?: string; pollIntervalMs?: number };
}
```

#### `UniversalOnboarding`

The universal onboarding flow component.

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| visible | boolean | Yes | Whether the onboarding is visible |
| onClose | function | Yes | Callback when onboarding is closed |
| AppName | string | Yes | Your application name |
| requestData | object/array | Yes | Consent options: `basic`, `personality`, `preferences`, `rawMemories` |
| onComplete | function | Yes | Callback with (apiUrl, token, userData) |
| autoFetch | boolean | No | Auto-fetch approved data after consent (default: true) |
| backgroundLoadData | boolean | No | Skip SDK training UI and return training metadata for host-side handling (default: false) |
| trainingScreenMode | 'mock' \| 'fast' \| 'real' \| 'none' | No | Training UI behavior. Defaults to `fast`, or `none` when `backgroundLoadData=true` |
| debug | boolean | No | Enable debug mode (default: false) |

#### `TrainingModal`

Email authentication and training progress modal.

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| visible | boolean | Yes | Whether the modal is visible |
| onCancel | function | Yes | Callback when modal is cancelled |
| onComplete | function | Yes | Callback when training is complete |
| modelKey | string | No | Model key for training |
| username | string | No | Username for training |
| isPrimaryAuth | boolean | No | Whether this is primary authentication |
| autoFocusEmailInput | boolean | No | Auto-focus email input on show |

#### `WelcomeScreen`

New welcome flow component with modern UI.

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| visible | boolean | Yes | Whether the screen is visible |
| onClose | function | Yes | Callback when screen is closed |
| onComplete | function | Yes | Callback when flow is complete |

#### `Overlay`

Data request overlay component.

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| visible | boolean | Yes | Whether the overlay is visible |
| onClose | function | Yes | Callback when overlay is closed |
| onAccept | function | Yes | Callback when request is accepted |
| AppName | string | Yes | Your application name |
| requestData | object | Yes | Data being requested |
| biometricType | 'FaceID' \| 'TouchID' \| 'BiometricID' | No | Type of biometric auth to use |

### Utility Functions

#### Secure Storage

- `storeCredentials(credentials, options)`: Store credentials securely
- `getCredentials(options)`: Retrieve credentials with optional biometric auth
- `hasCredentials()`: Check if user has stored credentials
- `deleteCredentials()`: Delete stored credentials
- `updateCredentials(updates, options)`: Update specific fields in credentials
- `generateDeviceUsername()`: Generate a device-specific unique username
- `verifyCredentials(credentials)`: Verify if credentials are valid

#### OAuth Service

- `connectPlatform(platform)`: Initiate OAuth flow for a specific platform
- `disconnectPlatform(platform, credentials)`: Disconnect a platform
- `initializeOAuthService()`: Initialize OAuth service handlers
- `cleanupOAuthService()`: Clean up OAuth service handlers
- `storePlatformConnection(platform, connectionData, credentials)`: Store platform connection

#### API Communication

- `validateCredentials(username, options)`: Validate user credentials with the API
- `createAccount(credentials, options)`: Create a new user account
- `authenticate(credentials, options)`: Authenticate with the API using credentials
- `refreshToken(refreshToken, options)`: Refresh authentication token
- `getPlatformData(accessToken, platform, options)`: Get user's connected platform data
- `getUserProfile(accessToken, options)`: Get user profile information
- `updatePlatformConnections(accessToken, platforms, options)`: Update user platform connections

## Development and Testing

### Setup Development Environment

1. Clone the repository:
```bash
git clone https://github.com/onairos/onairos-react-native.git
cd onairos-react-native
```

2. Install dependencies:
```bash
yarn install
```

3. Run the typecheck:
```bash
yarn typecheck
```

### Building the Package

```bash
npm run build:all
```

### Testing with a Local App

1. Link the package locally:
```bash
# In your package directory
yarn link

# In your app directory
yarn link @onairos/react-native
```

2. Run your app and test the integration.

## Troubleshooting

### OAuth Callback Issues

- Ensure your deep link schemes are properly configured in both iOS and Android
- Check that the callback URLs match what's registered with your OAuth providers
- Ensure all required permissions are enabled in your app configurations

### Biometric Authentication Issues

- Ensure proper permissions are set in Info.plist and AndroidManifest.xml
- Test on physical devices as simulators may not support all biometric features
- For iOS, ensure that Face ID/Touch ID is enabled and set up on the device

### Platform Specific Issues

#### iOS

- For keychain issues, check that the Keychain Sharing capability is enabled
- Ensure the bundle identifier is consistent with your OAuth configuration

#### Android

- For deep linking issues, check the androidManifest.xml configuration
- Ensure that biometric hardware is available on test devices

## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

MIT
