@@ -34,13 +34,15 @@ interface IState {
3434 decryptedUrl : string | null ,
3535 decryptedThumbnailUrl : string | null ,
3636 decryptedBlob : Blob | null ,
37- error : string | null ,
37+ error : any | null ,
38+ fetchingData : boolean ,
3839}
3940
4041export default class MVideoBody extends React . PureComponent < IProps , IState > {
4142 constructor ( props ) {
4243 super ( props ) ;
4344 this . state = {
45+ fetchingData : false ,
4446 decryptedUrl : null ,
4547 decryptedThumbnailUrl : null ,
4648 decryptedBlob : null ,
@@ -69,7 +71,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
6971 }
7072 }
7173
72- _getContentUrl ( ) : string {
74+ _getContentUrl ( ) : string | null {
7375 const content = this . props . mxEvent . getContent ( ) ;
7476 if ( content . file !== undefined ) {
7577 return this . state . decryptedUrl ;
@@ -89,7 +91,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
8991 }
9092 }
9193
92- componentDidMount ( ) {
94+ async componentDidMount ( ) {
95+ const autoplay = SettingsStore . getValue ( "autoplayGifsAndVideos" ) as boolean ;
9396 const content = this . props . mxEvent . getContent ( ) ;
9497 if ( content . file !== undefined && this . state . decryptedUrl === null ) {
9598 let thumbnailPromise = Promise . resolve ( null ) ;
@@ -100,26 +103,33 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
100103 return URL . createObjectURL ( blob ) ;
101104 } ) ;
102105 }
103- let decryptedBlob ;
104- thumbnailPromise . then ( ( thumbnailUrl ) => {
105- return decryptFile ( content . file ) . then ( function ( blob ) {
106- decryptedBlob = blob ;
107- return URL . createObjectURL ( blob ) ;
108- } ) . then ( ( contentUrl ) => {
106+ try {
107+ const thumbnailUrl = await thumbnailPromise ;
108+ if ( autoplay ) {
109+ console . log ( "Preloading video" ) ;
110+ const decryptedBlob = await decryptFile ( content . file ) ;
111+ const contentUrl = URL . createObjectURL ( decryptedBlob ) ;
109112 this . setState ( {
110113 decryptedUrl : contentUrl ,
111114 decryptedThumbnailUrl : thumbnailUrl ,
112115 decryptedBlob : decryptedBlob ,
113116 } ) ;
114117 this . props . onHeightChanged ( ) ;
115- } ) ;
116- } ) . catch ( ( err ) => {
118+ } else {
119+ console . log ( "NOT preloading video" ) ;
120+ this . setState ( {
121+ decryptedUrl : null ,
122+ decryptedThumbnailUrl : thumbnailUrl ,
123+ decryptedBlob : null ,
124+ } ) ;
125+ }
126+ } catch ( err ) {
117127 console . warn ( "Unable to decrypt attachment: " , err ) ;
118128 // Set a placeholder image when we can't decrypt the image.
119129 this . setState ( {
120130 error : err ,
121131 } ) ;
122- } ) ;
132+ }
123133 }
124134 }
125135
@@ -132,8 +142,35 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
132142 }
133143 }
134144
145+ async _videoOnPlay ( ) {
146+ const autoplay = SettingsStore . getValue ( "autoplayGifsAndVideos" ) as boolean ;
147+ if ( autoplay || this . state . decryptedUrl || this . state . fetchingData || this . state . error ) {
148+ // The video has or will have the data.
149+ return ;
150+ }
151+ this . setState ( {
152+ // To stop subsequent download attempts
153+ fetchingData : true ,
154+ } ) ;
155+ const content = this . props . mxEvent . getContent ( ) ;
156+ if ( ! content . file ) {
157+ this . setState ( {
158+ error : "No file given in content" ,
159+ } ) ;
160+ return ;
161+ }
162+ const decryptedBlob = await decryptFile ( content . file ) ;
163+ const contentUrl = URL . createObjectURL ( decryptedBlob ) ;
164+ this . setState ( {
165+ decryptedUrl : contentUrl ,
166+ decryptedBlob : decryptedBlob ,
167+ } ) ;
168+ this . props . onHeightChanged ( ) ;
169+ }
170+
135171 render ( ) {
136172 const content = this . props . mxEvent . getContent ( ) ;
173+ const autoplay = SettingsStore . getValue ( "autoplayGifsAndVideos" ) ;
137174
138175 if ( this . state . error !== null ) {
139176 return (
@@ -144,7 +181,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
144181 ) ;
145182 }
146183
147- if ( content . file !== undefined && this . state . decryptedUrl === null ) {
184+ // Important: If we aren't autoplaying and we haven't decrypred it yet, show a video with a poster.
185+ if ( content . file !== undefined && this . state . decryptedUrl === null && autoplay ) {
148186 // Need to decrypt the attachment
149187 // The attachment is decrypted in componentDidMount.
150188 // For now add an img tag with a spinner.
@@ -159,7 +197,6 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
159197
160198 const contentUrl = this . _getContentUrl ( ) ;
161199 const thumbUrl = this . _getThumbUrl ( ) ;
162- const autoplay = SettingsStore . getValue ( "autoplayGifsAndVideos" ) ;
163200 let height = null ;
164201 let width = null ;
165202 let poster = null ;
@@ -180,7 +217,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
180217 < span className = "mx_MVideoBody" >
181218 < video className = "mx_MVideoBody" src = { contentUrl } alt = { content . body }
182219 controls preload = { preload } muted = { autoplay } autoPlay = { autoplay }
183- height = { height } width = { width } poster = { poster } >
220+ height = { height } width = { width } poster = { poster } onPlay = { this . _videoOnPlay . bind ( this ) } >
184221 </ video >
185222 < MFileBody { ...this . props } decryptedBlob = { this . state . decryptedBlob } />
186223 </ span >
0 commit comments