@@ -13,28 +13,148 @@ export class ExpoVideoAdapter implements VideoPlayerAdapter {
1313
1414 private loadExpoVideo ( ) : void {
1515 try {
16+ console . log ( 'ExpoVideoAdapter - Attempting to load expo-video...' ) ;
1617 this . expoVideoModule = require ( 'expo-video' ) ;
18+ console . log ( 'ExpoVideoAdapter - expo-video loaded successfully:' , {
19+ hasVideoView : ! ! this . expoVideoModule ?. VideoView ,
20+ hasCreateVideoPlayer : ! ! this . expoVideoModule ?. createVideoPlayer ,
21+ exports : Object . keys ( this . expoVideoModule || { } )
22+ } ) ;
1723 } catch ( error ) {
24+ console . log ( 'ExpoVideoAdapter - Failed to load expo-video:' , error ) ;
1825 this . expoVideoModule = null ;
1926 }
2027 }
2128
2229 isAvailable ( ) : boolean {
23- // TODO: expo-video support requires architectural changes to support hooks
24- // The current class-based adapter system is incompatible with expo-video's hook-based API
25- // For now, return false to allow clean fallback to expo-av
26- // This maintains the correct priority: try expo-video first, fall back to expo-av
27- return false ;
30+ // Check if expo-video module loaded successfully and has Video component
31+ const available = ! ! ( this . expoVideoModule && this . expoVideoModule . VideoView ) ;
32+ console . log ( 'ExpoVideoAdapter - isAvailable():' , {
33+ hasModule : ! ! this . expoVideoModule ,
34+ hasVideoView : ! ! this . expoVideoModule ?. VideoView ,
35+ result : available
36+ } ) ;
37+ return available ;
2838 }
2939
3040 getAdapterName ( ) : string {
3141 return VideoPlayerType . EXPO_VIDEO ;
3242 }
3343
34- renderVideo ( _props : VideoPlayerProps , _ref : RefObject < VideoPlayerRef | null > ) : ReactElement {
35- // This method should never be called since isAvailable() returns false
36- // expo-video support requires architectural changes for hooks compatibility
37- throw new Error ( 'expo-video is not available - requires architectural redesign for hooks support' ) ;
44+ renderVideo ( props : VideoPlayerProps , ref : RefObject < VideoPlayerRef | null > ) : ReactElement {
45+ console . log ( 'ExpoVideoAdapter - renderVideo() called with:' , {
46+ videoUri : props . videoUri ,
47+ hasStyle : ! ! props . style ,
48+ useNativeControls : props . useNativeControls
49+ } ) ;
50+
51+ if ( ! this . isAvailable ( ) ) {
52+ console . log ( 'ExpoVideoAdapter - renderVideo() failed: not available' ) ;
53+ throw new Error ( 'expo-video is not available' ) ;
54+ }
55+
56+ const { VideoView, createVideoPlayer } = this . expoVideoModule ;
57+ console . log ( 'ExpoVideoAdapter - Using expo-video components:' , {
58+ hasVideoView : ! ! VideoView ,
59+ hasCreateVideoPlayer : ! ! createVideoPlayer
60+ } ) ;
61+
62+ // Create VideoPlayer instance for expo-video
63+ const player = createVideoPlayer ( { uri : props . videoUri } ) ;
64+
65+ // Configure player properties
66+ player . loop = false ;
67+ player . muted = false ;
68+
69+ // Set up event listeners for status updates
70+ if ( props . onPlaybackStatusUpdate ) {
71+ // Listen to various player events and map them to status updates
72+ player . addListener ( 'playingChange' , ( isPlaying : boolean ) => {
73+ const status = {
74+ uri : props . videoUri ,
75+ isLoaded : true ,
76+ shouldPlay : isPlaying ,
77+ isPlaying : isPlaying ,
78+ positionMillis : player . currentTime * 1000 ,
79+ durationMillis : player . duration * 1000 ,
80+ isMuted : player . muted ,
81+ rate : 1.0 ,
82+ volume : player . muted ? 0 : 1.0
83+ } ;
84+ props . onPlaybackStatusUpdate ! ( status ) ;
85+ } ) ;
86+
87+ player . addListener ( 'timeUpdate' , ( ) => {
88+ const status = {
89+ uri : props . videoUri ,
90+ isLoaded : true ,
91+ shouldPlay : player . playing ,
92+ isPlaying : player . playing ,
93+ positionMillis : player . currentTime * 1000 ,
94+ durationMillis : player . duration * 1000 ,
95+ isMuted : player . muted ,
96+ rate : 1.0 ,
97+ volume : player . muted ? 0 : 1.0
98+ } ;
99+ props . onPlaybackStatusUpdate ! ( status ) ;
100+ } ) ;
101+ }
102+
103+ // Handle errors
104+ if ( props . onError ) {
105+ player . addListener ( 'error' , ( error : any ) => {
106+ props . onError ! ( error ) ;
107+ } ) ;
108+ }
109+
110+ return React . createElement ( VideoView , {
111+ ref : ( videoInstance : any ) => {
112+ if ( ref && typeof ref === 'object' && 'current' in ref ) {
113+ // Store the player reference for compatibility with existing code
114+ ref . current = {
115+ ...videoInstance ,
116+ // Add expo-av compatible methods for backward compatibility
117+ setStatusAsync : async ( status : any ) => {
118+ if ( status . shouldPlay !== undefined ) {
119+ if ( status . shouldPlay ) {
120+ player . play ( ) ;
121+ } else {
122+ player . pause ( ) ;
123+ }
124+ }
125+ if ( status . positionMillis !== undefined ) {
126+ player . currentTime = status . positionMillis / 1000 ;
127+ }
128+ if ( status . isMuted !== undefined ) {
129+ player . muted = status . isMuted ;
130+ }
131+ } ,
132+ _currentStatus : {
133+ uri : props . videoUri ,
134+ isLoaded : true ,
135+ shouldPlay : player . playing ,
136+ positionMillis : player . currentTime * 1000 ,
137+ durationMillis : player . duration * 1000 ,
138+ isMuted : player . muted
139+ }
140+ } ;
141+ }
142+ } ,
143+ player : player ,
144+ style : props . style ,
145+ nativeControls : props . useNativeControls || false ,
146+ contentFit : 'contain' ,
147+ onLoad : ( data : any ) => {
148+ if ( props . onLoad ) {
149+ props . onLoad ( data ) ;
150+ }
151+ } ,
152+ onLoadStart : ( data : any ) => {
153+ if ( props . onLoadStart ) {
154+ props . onLoadStart ( data ) ;
155+ }
156+ } ,
157+ } ) ;
38158 }
39159
40160 private processExpoVideoEvents ( videoRef : VideoPlayerRef | null , eventType : string , data : any ) : void {
0 commit comments