Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
67 changes: 39 additions & 28 deletions example/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { StyleSheet, View, Text, TouchableOpacity, Alert, Platform, Dimensions } from 'react-native';
import { StatusBar } from 'expo-status-bar';

// TEST: This log should show up immediately when the app starts
console.log('🧪 [TEST] App.tsx loaded - Console.log is working!');

console.log('🧪 [TEST] About to import cloudinary-react-native...');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just verifying - you left it on purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes
But I'll take out all the console.log from the sample app as they were for me to see whats going on

import {AdvancedImage, AdvancedVideo} from 'cloudinary-react-native';
console.log('🧪 [TEST] Successfully imported cloudinary-react-native!', {AdvancedVideo: typeof AdvancedVideo});
import {Cloudinary} from '@cloudinary/url-gen';
import {scale} from "@cloudinary/url-gen/actions/resize";
import {cartoonify} from "@cloudinary/url-gen/actions/effect";
Expand All @@ -9,16 +15,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 All @@ -31,6 +35,9 @@ const cld = new Cloudinary({
});

export default function App() {
// TEST: This should show when the App component is created
console.log('🧪 [TEST] App component function called!');

const videoPlayer = useRef<any>(null);
const [analyticsEnabled, setAnalyticsEnabled] = useState(false);
const [autoTracking, setAutoTracking] = useState(false);
Expand All @@ -49,7 +56,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 +124,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 +144,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 +162,40 @@ 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'
}}
/>
{(() => {
console.log('🧪 [TEST] About to render AdvancedVideo component...');
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