1- import { StyleSheet , View } from 'react-native' ;
1+ import { StyleSheet , View , Text , TouchableOpacity , Alert , Platform , Dimensions } from 'react-native' ;
2+ import { StatusBar } from 'expo-status-bar' ;
23import { AdvancedImage , AdvancedVideo } from 'cloudinary-react-native' ;
34import { Cloudinary } from '@cloudinary/url-gen' ;
45import { scale } from "@cloudinary/url-gen/actions/resize" ;
56import { cartoonify } from "@cloudinary/url-gen/actions/effect" ;
67import { max } from "@cloudinary/url-gen/actions/roundCorners" ;
7- import React , { useRef } from "react" ;
8- import { streamingProfile } from '@cloudinary/url-gen/actions/transcode' ;
9- import { Video } from 'expo-av' ;
10- import { } from 'cloudinary-react-native' ;
8+ import React , { useRef , useState } from "react" ;
9+
10+ const { height : screenHeight , width : screenWidth } = Dimensions . get ( 'window' ) ;
11+
12+ // Calculate safe area padding based on screen dimensions
13+ const getTopPadding = ( ) => {
14+ if ( Platform . OS === 'ios' ) {
15+ // For iPhone X and newer (with notch), screen height is typically 812+ or width 390+
16+ if ( screenHeight >= 812 || screenWidth >= 390 ) {
17+ return 60 ; // Devices with notch
18+ }
19+ return 40 ; // Older devices
20+ }
21+ return 35 ; // Android
22+ } ;
1123
1224const cld = new Cloudinary ( {
1325 cloud : {
@@ -17,40 +29,212 @@ const cld = new Cloudinary({
1729 secure : true
1830 }
1931} ) ;
32+
2033export default function App ( ) {
34+ const videoPlayer = useRef < any > ( null ) ;
35+ const [ analyticsEnabled , setAnalyticsEnabled ] = useState ( false ) ;
36+ const [ autoTracking , setAutoTracking ] = useState ( false ) ;
2137
22- const videoPlayer = useRef < Video > ( null ) ;
2338 function createMyImage ( ) {
2439 var myImage = cld . image ( 'sample' ) . resize ( scale ( ) . width ( 300 ) ) . effect ( cartoonify ( ) ) . roundCorners ( max ( ) ) ;
2540 return myImage
2641 }
2742
2843 function createMyVideoObject ( ) {
29- const myVideo = cld . video ( 'sea_turtle.m3u8' ) . transcode ( streamingProfile ( "auto" ) )
44+ const myVideo = cld . video ( 'sea_turtle' )
3045 return myVideo
3146 } ;
3247
48+ const toggleAnalytics = ( ) => {
49+ const newAnalyticsState = ! analyticsEnabled ;
50+ setAnalyticsEnabled ( newAnalyticsState ) ;
51+
52+ // Auto-enable tracking when analytics are enabled for better UX
53+ if ( newAnalyticsState && ! autoTracking ) {
54+ setAutoTracking ( true ) ;
55+ }
56+
57+ Alert . alert (
58+ 'Analytics' ,
59+ `Analytics ${ newAnalyticsState ? 'enabled' : 'disabled' } .${ newAnalyticsState && ! autoTracking ? ' Auto tracking also enabled.' : '' } Reload the video to see changes.`
60+ ) ;
61+ } ;
62+
63+ const toggleAutoTracking = ( ) => {
64+ setAutoTracking ( ! autoTracking ) ;
65+ Alert . alert (
66+ 'Auto Tracking' ,
67+ `Auto tracking ${ ! autoTracking ? 'enabled' : 'disabled' } . Reload the video to see changes.`
68+ ) ;
69+ } ;
70+
71+ const startManualTracking = ( ) => {
72+ if ( videoPlayer . current && videoPlayer . current . startAnalyticsTracking ) {
73+ videoPlayer . current . startAnalyticsTracking (
74+ {
75+ publicId : 'jnwczzoacujqb4r4loj1' ,
76+ cloudName : 'mobiledemoapp' ,
77+ type : 'video'
78+ } ,
79+ {
80+ customData : {
81+ userId : 'test-user-123' ,
82+ sessionId : 'test-session-456' ,
83+ category : 'demo-video'
84+ }
85+ }
86+ ) ;
87+ Alert . alert ( 'Manual Tracking' , 'Manual analytics tracking started!' ) ;
88+ } else {
89+ Alert . alert ( 'Error' , 'Video ref not available or analytics not enabled' ) ;
90+ }
91+ } ;
92+
93+ const stopManualTracking = ( ) => {
94+ if ( videoPlayer . current && videoPlayer . current . stopAnalyticsTracking ) {
95+ videoPlayer . current . stopAnalyticsTracking ( ) ;
96+ Alert . alert ( 'Manual Tracking' , 'Manual analytics tracking stopped!' ) ;
97+ } else {
98+ Alert . alert ( 'Error' , 'Video ref not available' ) ;
99+ }
100+ } ;
101+
102+ const startAutoTrackingManually = ( ) => {
103+ if ( videoPlayer . current && videoPlayer . current . startAutoAnalyticsTracking ) {
104+ videoPlayer . current . startAutoAnalyticsTracking ( {
105+ customData : {
106+ userId : 'test-user-123' ,
107+ source : 'manual-trigger'
108+ }
109+ } ) ;
110+ Alert . alert ( 'Auto Tracking' , 'Auto analytics tracking started manually!' ) ;
111+ } else {
112+ Alert . alert ( 'Error' , 'Video ref not available or analytics not enabled' ) ;
113+ }
114+ } ;
115+
116+ const addCustomEventToVideo = ( ) => {
117+ if ( videoPlayer . current && videoPlayer . current . addCustomEvent ) {
118+ videoPlayer . current . addCustomEvent ( 'user_interaction' , {
119+ action : 'button_clicked' ,
120+ buttonName : 'share' ,
121+ videoPosition : 30.5 , // seconds
122+ customData : {
123+ userId : 'demo-user-123' ,
124+ sessionId : 'session-456'
125+ }
126+ } ) ;
127+ Alert . alert ( 'Custom Event' , 'Custom analytics event sent!' ) ;
128+ } else {
129+ Alert . alert ( 'Error' , 'Custom events not available' ) ;
130+ }
131+ } ;
132+
33133 return (
34- < View style = { styles . container } >
35- < View >
36- < AdvancedImage cldImg = { createMyImage ( ) } style = { { backgroundColor :"black" , width :300 , height :200 } } />
37- </ View >
38- < View style = { styles . videoContainer } >
39- < AdvancedVideo
40- ref = { videoPlayer }
41- videoStyle = { styles . video }
42- cldVideo = { createMyVideoObject ( ) }
43- />
134+ < View style = { styles . safeArea } >
135+ < StatusBar style = "auto" />
136+ < View style = { styles . container } >
137+ < View >
138+ < AdvancedImage cldImg = { createMyImage ( ) } style = { { backgroundColor :"black" , width :300 , height :200 } } />
139+ </ View >
140+
141+ { /* Analytics Controls */ }
142+ < View style = { styles . controlsContainer } >
143+ < Text style = { styles . title } > Analytics Testing</ Text >
144+
145+ < TouchableOpacity style = { styles . button } onPress = { toggleAnalytics } >
146+ < Text style = { styles . buttonText } >
147+ { analyticsEnabled ? 'Disable Analytics' : 'Enable Analytics' }
148+ </ Text >
149+ </ TouchableOpacity >
150+
151+ < TouchableOpacity style = { styles . button } onPress = { toggleAutoTracking } >
152+ < Text style = { styles . buttonText } >
153+ { autoTracking ? 'Disable Auto Tracking' : 'Enable Auto Tracking' }
154+ </ Text >
155+ </ TouchableOpacity >
156+
157+ < TouchableOpacity style = { styles . button } onPress = { addCustomEventToVideo } >
158+ < Text style = { styles . buttonText } > Send Custom Event</ Text >
159+ </ TouchableOpacity >
160+ </ View >
161+
162+ < View style = { styles . videoContainer } >
163+ < AdvancedVideo
164+ ref = { videoPlayer }
165+ videoStyle = { styles . video }
166+ cldVideo = { createMyVideoObject ( ) }
167+ enableAnalytics = { analyticsEnabled }
168+ autoTrackAnalytics = { autoTracking }
169+ analyticsOptions = { {
170+ customData : {
171+ userId : 'demo-user-123' ,
172+ appVersion : '1.0.0' ,
173+ platform : 'react-native'
174+ } ,
175+ videoPlayerType : 'expo-av' ,
176+ videoPlayerVersion : '14.0.0'
177+ } }
178+ />
179+ </ View >
180+
181+ { /* Status Display */ }
182+ < View style = { styles . statusContainer } >
183+ < Text style = { styles . statusText } >
184+ Analytics: { analyticsEnabled ? '✅ Enabled' : '❌ Disabled' }
185+ </ Text >
186+ < Text style = { styles . statusText } >
187+ Auto Tracking: { autoTracking ? '✅ Enabled' : '❌ Disabled' }
188+ </ Text >
189+ </ View >
44190 </ View >
45191 </ View >
46192 ) ;
47193}
48194
49195const styles = StyleSheet . create ( {
196+ safeArea : {
197+ flex : 1 ,
198+ backgroundColor : '#fff' ,
199+ paddingTop : getTopPadding ( ) ,
200+ } ,
50201 container : {
51202 flex : 1 ,
52203 alignItems : 'center' ,
53204 justifyContent : 'center' ,
205+ paddingHorizontal : 20 ,
206+ } ,
207+ controlsContainer : {
208+ width : '90%' ,
209+ alignItems : 'center' ,
210+ marginVertical : 20 ,
211+ } ,
212+ title : {
213+ fontSize : 18 ,
214+ fontWeight : 'bold' ,
215+ marginBottom : 15 ,
216+ } ,
217+ button : {
218+ backgroundColor : '#007AFF' ,
219+ paddingHorizontal : 20 ,
220+ paddingVertical : 10 ,
221+ borderRadius : 8 ,
222+ marginVertical : 5 ,
223+ minWidth : 200 ,
224+ alignItems : 'center' ,
225+ } ,
226+ smallButton : {
227+ minWidth : 90 ,
228+ marginHorizontal : 5 ,
229+ } ,
230+ buttonRow : {
231+ flexDirection : 'row' ,
232+ justifyContent : 'center' ,
233+ } ,
234+ buttonText : {
235+ color : 'white' ,
236+ fontSize : 14 ,
237+ fontWeight : '600' ,
54238 } ,
55239 videoContainer : {
56240 width : '100%' ,
@@ -62,4 +246,12 @@ const styles = StyleSheet.create({
62246 width : 400 ,
63247 height : 220 ,
64248 } ,
249+ statusContainer : {
250+ marginTop : 20 ,
251+ alignItems : 'center' ,
252+ } ,
253+ statusText : {
254+ fontSize : 14 ,
255+ marginVertical : 2 ,
256+ } ,
65257} ) ;
0 commit comments