Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
engine-strict=false
fund=false
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ This Readme provides basic installation and usage information.
Transform and optimize assets. Visit our documentation to learn more about [media optimization](https://cloudinary.com/documentation/media_optimization) and [transformations](https://cloudinary.com/documentation/image_transformations).

## Version Support
| SDK Version | React Native Version |
|-------------|----------------------|
| 1.x.x | > 0.6 |
| SDK Version | React Native Version | Expo SDK Version | Video Library |
|-------------|----------------------|------------------|---------------|
| 1.x.x | >= 0.72 | 50-53 | expo-av / expo-video |

## Installation
### Install using your favorite package manager (yarn, npm)
Expand All @@ -37,16 +37,20 @@ yarn add cloudinary-react-native --save
```

### For Video Player functionality
If you want to use the video player features, you need to install `expo-av`:
The SDK supports both `expo-av` and `expo-video` libraries. The appropriate library will be automatically detected and used:

**For Expo SDK 50-51 (expo-av):**
```bash
npm install expo-av
```
Or

**For Expo SDK 52+ (expo-video - recommended):**
```bash
yarn add expo-av
npm install expo-video
```

**Note:** `expo-av` is deprecated in SDK 52 and removed in SDK 53. For newer Expo versions, use `expo-video`.

## Usage
### Setup
The `Cloudinary` class is the main entry point for using the library. Your `cloud_name` is required to create an instance of this class. Your `api_key` and `api_secret` are also needed to perform secure API calls to Cloudinary (e.g., image and video uploads). Setting the configuration parameters can be done either programmatically using an appropriate constructor of the Cloudinary class or globally using an environment variable. You can find your account-specific configuration parameters in the **Dashboard** page of your [account console](https://cloudinary.com/console).
Expand Down Expand Up @@ -83,7 +87,7 @@ export default function App() {
```

### Video Player
The `AdvancedVideo` component provides video playback capabilities with optional analytics tracking. **Note: This requires `expo-av` to be installed.**
The `AdvancedVideo` component provides video playback capabilities with optional analytics tracking. **Note: This requires either `expo-av` (SDK 50-51) or `expo-video` (SDK 52+) to be installed.**

```tsx
import { AdvancedVideo } from 'cloudinary-react-native';
Expand Down
4 changes: 4 additions & 0 deletions example/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
engine-strict=false
fund=false
audit=false
update-notifier=false
58 changes: 30 additions & 28 deletions example/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { StyleSheet, View, Text, TouchableOpacity, Alert, Platform, Dimensions } from 'react-native';
import { StatusBar } from 'expo-status-bar';

import {AdvancedImage, AdvancedVideo} from 'cloudinary-react-native';
import {Cloudinary} from '@cloudinary/url-gen';
import {scale} from "@cloudinary/url-gen/actions/resize";
Expand All @@ -9,16 +10,14 @@ import React, {useRef, useState} from "react";

const { height: screenHeight, width: screenWidth } = Dimensions.get('window');

// Calculate safe area padding based on screen dimensions
const getTopPadding = () => {
if (Platform.OS === 'ios') {
// For iPhone X and newer (with notch), screen height is typically 812+ or width 390+
if (screenHeight >= 812 || screenWidth >= 390) {
return 60; // Devices with notch
return 60;
}
return 40; // Older devices
return 40;
}
return 35; // Android
return 35;
};

const cld = new Cloudinary({
Expand Down Expand Up @@ -49,7 +48,6 @@ export default function App() {
const newAnalyticsState = !analyticsEnabled;
setAnalyticsEnabled(newAnalyticsState);

// Auto-enable tracking when analytics are enabled for better UX
if (newAnalyticsState && !autoTracking) {
setAutoTracking(true);
}
Expand Down Expand Up @@ -118,7 +116,7 @@ export default function App() {
videoPlayer.current.addCustomEvent('user_interaction', {
action: 'button_clicked',
buttonName: 'share',
videoPosition: 30.5, // seconds
videoPosition: 30.5,
customData: {
userId: 'demo-user-123',
sessionId: 'session-456'
Expand All @@ -138,7 +136,6 @@ export default function App() {
<AdvancedImage cldImg={createMyImage()} style={{backgroundColor:"black", width:300, height:200}}/>
</View>

{/* Analytics Controls */}
<View style={styles.controlsContainer}>
<Text style={styles.title}>Analytics Testing</Text>

Expand All @@ -157,34 +154,39 @@ export default function App() {
<TouchableOpacity style={styles.button} onPress={addCustomEventToVideo}>
<Text style={styles.buttonText}>Send Custom Event</Text>
</TouchableOpacity>


</View>

<View style={styles.videoContainer}>
<AdvancedVideo
ref={videoPlayer}
videoStyle={styles.video}
cldVideo={createMyVideoObject()}
enableAnalytics={analyticsEnabled}
autoTrackAnalytics={autoTracking}
analyticsOptions={{
customData: {
userId: 'demo-user-123',
appVersion: '1.0.0',
platform: 'react-native'
},
videoPlayerType: 'expo-av',
videoPlayerVersion: '14.0.0'
}}
/>
{(() => {
return (
<AdvancedVideo
ref={videoPlayer}
videoStyle={styles.video}
cldVideo={createMyVideoObject()}
enableAnalytics={analyticsEnabled}
autoTrackAnalytics={autoTracking}
analyticsOptions={{
customData: {
userId: 'demo-user-123',
appVersion: '1.0.0',
platform: 'react-native'
},
videoPlayerType: 'auto-detected',
videoPlayerVersion: 'auto-detected'
}}
/>
);
})()}
</View>

{/* Status Display */}

<View style={styles.statusContainer}>
<Text style={styles.statusText}>
Analytics: {analyticsEnabled ? 'Enabled' : 'Disabled'}
Analytics: {analyticsEnabled ? 'Enabled' : 'Disabled'}
</Text>
<Text style={styles.statusText}>
Auto Tracking: {autoTracking ? 'Enabled' : 'Disabled'}
Auto Tracking: {autoTracking ? 'Enabled' : 'Disabled'}
</Text>
</View>
</View>
Expand Down
Loading