1- import { useCallback , useRef , useState } from 'react' ;
1+ import { useCallback , useEffect , useState } from 'react' ;
22import { Alert , Platform , SafeAreaView , ScrollView , StyleSheet , Text , TouchableOpacity , View } from 'react-native' ;
33import {
4- type PlayerControls ,
5- type PlayerInfo ,
64 PlayerState ,
7- type ProgressData ,
8- type YouTubeError ,
9- YoutubePlayer ,
5+ YoutubeView ,
6+ useYouTubeEvent ,
7+ useYouTubePlayer ,
108 useYoutubeOEmbed ,
119} from 'react-native-youtube-bridge' ;
1210
@@ -17,22 +15,89 @@ const formatTime = (seconds: number): string => {
1715} ;
1816
1917function App ( ) {
20- const playerRef = useRef < PlayerControls > ( null ) ;
2118 const [ isPlaying , setIsPlaying ] = useState ( false ) ;
22- const [ currentTime , setCurrentTime ] = useState ( 0 ) ;
23- const [ duration , setDuration ] = useState ( 0 ) ;
24- const [ loadedFraction , setLoadedFraction ] = useState ( 0 ) ;
25- const [ playbackRate , setPlaybackRate ] = useState ( 1 ) ;
2619 const [ availableRates , setAvailableRates ] = useState < number [ ] > ( [ 1 ] ) ;
2720 const [ volume , setVolume ] = useState ( 100 ) ;
2821 const [ isMuted , setIsMuted ] = useState ( false ) ;
2922 const [ videoId , setVideoId ] = useState ( 'AbZH7XWDW_k' ) ;
3023 const [ progressInterval , setProgressInterval ] = useState ( 1000 ) ;
3124 const { oEmbed, isLoading, error } = useYoutubeOEmbed ( `https://www.youtube.com/watch?v=${ videoId } ` ) ;
3225
33- console . log ( 'oEmbed' , oEmbed , isLoading , error ) ;
26+ const player = useYouTubePlayer ( videoId , {
27+ autoplay : true ,
28+ controls : true ,
29+ playsinline : true ,
30+ rel : false ,
31+ muted : true ,
32+ } ) ;
3433
35- const handleReady = useCallback ( ( playerInfo : PlayerInfo ) => {
34+ const changePlaybackRate = ( rate : number ) => {
35+ player . setPlaybackRate ( rate ) ;
36+ } ;
37+
38+ const changeVolume = ( newVolume : number ) => {
39+ player . setVolume ( newVolume ) ;
40+ setVolume ( newVolume ) ;
41+ } ;
42+
43+ const toggleMute = useCallback ( ( ) => {
44+ if ( isMuted ) {
45+ player . unMute ( ) ;
46+ setIsMuted ( false ) ;
47+ return ;
48+ }
49+
50+ player . mute ( ) ;
51+ setIsMuted ( true ) ;
52+ } , [ player , isMuted ] ) ;
53+
54+ const onPlay = useCallback ( ( ) => {
55+ if ( isPlaying ) {
56+ player . pause ( ) ;
57+ return ;
58+ }
59+
60+ player . play ( ) ;
61+ } , [ player , isPlaying ] ) ;
62+
63+ const getPlayerInfo = async ( ) => {
64+ const [ currentTime , duration , url , state , loaded ] = await Promise . all ( [
65+ player . getCurrentTime ( ) ,
66+ player . getDuration ( ) ,
67+ player . getVideoUrl ( ) ,
68+ player . getPlayerState ( ) ,
69+ player . getVideoLoadedFraction ( ) ,
70+ ] ) ;
71+
72+ console . log (
73+ `
74+ currentTime: ${ currentTime }
75+ duration: ${ duration }
76+ url: ${ url }
77+ state: ${ state }
78+ loaded: ${ loaded }
79+ ` ,
80+ ) ;
81+
82+ Alert . alert (
83+ 'Player info' ,
84+ `Current time: ${ formatTime ( currentTime || 0 ) } \n` +
85+ `duration: ${ formatTime ( duration || 0 ) } \n` +
86+ `state: ${ state } \n` +
87+ `loaded: ${ ( ( loaded || 0 ) * 100 ) . toFixed ( 1 ) } %\n` +
88+ `url: ${ url || 'N/A' } ` ,
89+ ) ;
90+ } ;
91+
92+ const playbackRate = useYouTubeEvent ( player , 'playbackRateChange' , 1 ) ;
93+ const playbackQuality = useYouTubeEvent ( player , 'playbackQualityChange' ) ;
94+ const progress = useYouTubeEvent ( player , 'progress' , progressInterval ) ;
95+
96+ const currentTime = progress ?. currentTime ?? 0 ;
97+ const duration = progress ?. duration ?? 0 ;
98+ const loadedFraction = progress ?. loadedFraction ?? 0 ;
99+
100+ useYouTubeEvent ( player , 'ready' , ( playerInfo ) => {
36101 console . log ( 'Player is ready!' ) ;
37102 Alert . alert ( 'Alert' , 'YouTube player is ready!' ) ;
38103
@@ -51,9 +116,9 @@ function App() {
51116 if ( playerInfo ?. muted !== undefined ) {
52117 setIsMuted ( playerInfo . muted ) ;
53118 }
54- } , [ ] ) ;
119+ } ) ;
55120
56- const handleStateChange = useCallback ( ( state : PlayerState ) => {
121+ useYouTubeEvent ( player , 'stateChange' , ( state ) => {
57122 console . log ( 'Player state changed:' , state ) ;
58123 setIsPlaying ( state === PlayerState . PLAYING ) ;
59124
@@ -77,93 +142,21 @@ function App() {
77142 console . log ( 'Video is cued' ) ;
78143 break ;
79144 }
80- } , [ ] ) ;
145+ } ) ;
81146
82- const handleProgress = useCallback ( ( progress : ProgressData ) => {
83- setCurrentTime ( progress . currentTime ) ;
84- setDuration ( progress . duration ) ;
85- setLoadedFraction ( progress . loadedFraction ) ;
86- } , [ ] ) ;
147+ useYouTubeEvent ( player , 'autoplayBlocked' , ( ) => {
148+ console . log ( 'Autoplay was blocked' ) ;
149+ } ) ;
87150
88- const handleError = useCallback ( ( error : YouTubeError ) => {
151+ useYouTubeEvent ( player , 'error' , ( error ) => {
89152 console . error ( 'Player error:' , error ) ;
90153 Alert . alert ( 'Error' , `Player error (${ error . code } ): ${ error . message } ` ) ;
91- } , [ ] ) ;
154+ } ) ;
92155
93- const handlePlaybackRateChange = useCallback ( ( rate : number ) => {
94- console . log ( 'Playback rate changed:' , rate ) ;
95- setPlaybackRate ( rate ) ;
96- } , [ ] ) ;
97-
98- const handlePlaybackQualityChange = useCallback ( ( quality : string ) => {
99- console . log ( 'Playback quality changed:' , quality ) ;
100- } , [ ] ) ;
101-
102- const handleAutoplayBlocked = useCallback ( ( ) => {
103- console . log ( 'Autoplay was blocked' ) ;
104- } , [ ] ) ;
105-
106- const changePlaybackRate = ( rate : number ) => {
107- playerRef . current ?. setPlaybackRate ( rate ) ;
108- } ;
109-
110- const changeVolume = ( newVolume : number ) => {
111- playerRef . current ?. setVolume ( newVolume ) ;
112- setVolume ( newVolume ) ;
113- } ;
114-
115- const toggleMute = useCallback ( ( ) => {
116- if ( isMuted ) {
117- playerRef . current ?. unMute ( ) ;
118- setIsMuted ( false ) ;
119- return ;
120- }
121-
122- playerRef . current ?. mute ( ) ;
123- setIsMuted ( true ) ;
124- } , [ isMuted ] ) ;
125-
126- const onPlay = useCallback ( ( ) => {
127- if ( isPlaying ) {
128- playerRef . current ?. pause ( ) ;
129- return ;
130- }
131-
132- playerRef . current ?. play ( ) ;
133- } , [ isPlaying ] ) ;
134-
135- const getPlayerInfo = async ( ) => {
136- try {
137- const [ currentTime , duration , url , state , loaded ] = await Promise . all ( [
138- playerRef . current ?. getCurrentTime ( ) ,
139- playerRef . current ?. getDuration ( ) ,
140- playerRef . current ?. getVideoUrl ( ) ,
141- playerRef . current ?. getPlayerState ( ) ,
142- playerRef . current ?. getVideoLoadedFraction ( ) ,
143- ] ) ;
144-
145- console . log (
146- `
147- currentTime: ${ currentTime }
148- duration: ${ duration }
149- url: ${ url }
150- state: ${ state }
151- loaded: ${ loaded }
152- ` ,
153- ) ;
154-
155- Alert . alert (
156- 'Player info' ,
157- `Current time: ${ formatTime ( currentTime || 0 ) } \n` +
158- `duration: ${ formatTime ( duration || 0 ) } \n` +
159- `state: ${ state } \n` +
160- `loaded: ${ ( ( loaded || 0 ) * 100 ) . toFixed ( 1 ) } %\n` +
161- `url: ${ url || 'N/A' } ` ,
162- ) ;
163- } catch ( error ) {
164- console . error ( 'Error getting player info:' , error ) ;
165- }
166- } ;
156+ useEffect ( ( ) => {
157+ console . log ( 'oEmbed' , oEmbed , isLoading , error ) ;
158+ console . log ( 'playbackQuality' , playbackQuality ) ;
159+ } , [ oEmbed , isLoading , error , playbackQuality ] ) ;
167160
168161 return (
169162 < SafeAreaView style = { styles . container } >
@@ -173,30 +166,13 @@ function App() {
173166 < Text style = { styles . subtitle } > Video ID: { videoId } </ Text >
174167 < Text style = { styles . subtitle } > Playback rate: { playbackRate } x</ Text >
175168 </ View >
176-
177- < YoutubePlayer
178- ref = { playerRef }
179- source = { videoId }
169+ < YoutubeView
170+ useInlineHtml
171+ player = { player }
180172 height = { Platform . OS === 'web' ? 'auto' : undefined }
181- useInlineHtml = { false }
182- playerVars = { {
183- autoplay : true ,
184- controls : true ,
185- playsinline : true ,
186- rel : false ,
187- muted : true ,
188- } }
189173 webViewProps = { {
190174 renderToHardwareTextureAndroid : true ,
191175 } }
192- progressInterval = { progressInterval }
193- onReady = { handleReady }
194- onStateChange = { handleStateChange }
195- onProgress = { handleProgress }
196- onError = { handleError }
197- onPlaybackRateChange = { handlePlaybackRateChange }
198- onPlaybackQualityChange = { handlePlaybackQualityChange }
199- onAutoplayBlocked = { handleAutoplayBlocked }
200176 style = { {
201177 maxHeight : 400 ,
202178 } }
@@ -235,7 +211,7 @@ function App() {
235211 < View style = { styles . controls } >
236212 < TouchableOpacity
237213 style = { [ styles . button , styles . seekButton ] }
238- onPress = { ( ) => playerRef . current ? .seekTo ( currentTime > 10 ? currentTime - 10 : 0 ) }
214+ onPress = { ( ) => player . seekTo ( currentTime > 10 ? currentTime - 10 : 0 ) }
239215 >
240216 < Text style = { styles . buttonText } > ⏪ -10s</ Text >
241217 </ TouchableOpacity >
@@ -244,13 +220,13 @@ function App() {
244220 < Text style = { styles . buttonText } > { isPlaying ? '⏸️ Pause' : '▶️ Play' } </ Text >
245221 </ TouchableOpacity >
246222
247- < TouchableOpacity style = { [ styles . button , styles . stopButton ] } onPress = { ( ) => playerRef . current ? .stop ( ) } >
223+ < TouchableOpacity style = { [ styles . button , styles . stopButton ] } onPress = { ( ) => player . stop ( ) } >
248224 < Text style = { styles . buttonText } > ⏹️ Stop</ Text >
249225 </ TouchableOpacity >
250226
251227 < TouchableOpacity
252228 style = { [ styles . button , styles . seekButton ] }
253- onPress = { ( ) => playerRef . current ? .seekTo ( currentTime + 10 , true ) }
229+ onPress = { ( ) => player . seekTo ( currentTime + 10 , true ) }
254230 >
255231 < Text style = { styles . buttonText } > ⏭️ +10s</ Text >
256232 </ TouchableOpacity >
0 commit comments