@@ -39,6 +39,8 @@ interface IState {
3939}
4040
4141export default class MVideoBody extends React . PureComponent < IProps , IState > {
42+ private videoRef = React . createRef < HTMLVideoElement > ( ) ;
43+
4244 constructor ( props ) {
4345 super ( props ) ;
4446 this . state = {
@@ -71,7 +73,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
7173 }
7274 }
7375
74- _getContentUrl ( ) : string | null {
76+ private getContentUrl ( ) : string | null {
7577 const content = this . props . mxEvent . getContent ( ) ;
7678 if ( content . file !== undefined ) {
7779 return this . state . decryptedUrl ;
@@ -80,7 +82,12 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
8082 }
8183 }
8284
83- _getThumbUrl ( ) : string | null {
85+ private hasContentUrl ( ) : boolean {
86+ const url = this . getContentUrl ( ) ;
87+ return url && ! url . startsWith ( "data:" ) ;
88+ }
89+
90+ private getThumbUrl ( ) : string | null {
8491 const content = this . props . mxEvent . getContent ( ) ;
8592 if ( content . file !== undefined ) {
8693 return this . state . decryptedThumbnailUrl ;
@@ -118,7 +125,10 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
118125 } else {
119126 console . log ( "NOT preloading video" ) ;
120127 this . setState ( {
121- decryptedUrl : null ,
128+ // For Chrome and Electron, we need to set some non-empty `src` to
129+ // enable the play button. Firefox does not seem to care either
130+ // way, so it's fine to do for all browsers.
131+ decryptedUrl : `data:${ content ?. info ?. mimetype } ,` ,
122132 decryptedThumbnailUrl : thumbnailUrl ,
123133 decryptedBlob : null ,
124134 } ) ;
@@ -142,8 +152,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
142152 }
143153 }
144154
145- async _videoOnPlay ( ) {
146- if ( this . _getContentUrl ( ) || this . state . fetchingData || this . state . error ) {
155+ private videoOnPlay = async ( ) => {
156+ if ( this . hasContentUrl ( ) || this . state . fetchingData || this . state . error ) {
147157 // We have the file, we are fetching the file, or there is an error.
148158 return ;
149159 }
@@ -164,6 +174,9 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
164174 decryptedUrl : contentUrl ,
165175 decryptedBlob : decryptedBlob ,
166176 fetchingData : false ,
177+ } , ( ) => {
178+ if ( ! this . videoRef . current ) return ;
179+ this . videoRef . current . play ( ) ;
167180 } ) ;
168181 this . props . onHeightChanged ( ) ;
169182 }
@@ -195,8 +208,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
195208 ) ;
196209 }
197210
198- const contentUrl = this . _getContentUrl ( ) ;
199- const thumbUrl = this . _getThumbUrl ( ) ;
211+ const contentUrl = this . getContentUrl ( ) ;
212+ const thumbUrl = this . getThumbUrl ( ) ;
200213 let height = null ;
201214 let width = null ;
202215 let poster = null ;
@@ -215,9 +228,20 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
215228 }
216229 return (
217230 < span className = "mx_MVideoBody" >
218- < video className = "mx_MVideoBody" src = { contentUrl } title = { content . body }
219- controls preload = { preload } muted = { autoplay } autoPlay = { autoplay }
220- height = { height } width = { width } poster = { poster } onPlay = { this . _videoOnPlay . bind ( this ) } >
231+ < video
232+ className = "mx_MVideoBody"
233+ ref = { this . videoRef }
234+ src = { contentUrl }
235+ title = { content . body }
236+ controls
237+ preload = { preload }
238+ muted = { autoplay }
239+ autoPlay = { autoplay }
240+ height = { height }
241+ width = { width }
242+ poster = { poster }
243+ onPlay = { this . videoOnPlay }
244+ >
221245 </ video >
222246 < MFileBody { ...this . props } decryptedBlob = { this . state . decryptedBlob } />
223247 </ span >
0 commit comments