Merge pull request #5430 from matrix-org/jryans/fix-encrypted-videos
Fix encrypted video playback in Chrome-based browsers
This commit is contained in:
commit
dea4fd661a
1 changed files with 34 additions and 10 deletions
|
@ -39,6 +39,8 @@ interface IState {
|
|||
}
|
||||
|
||||
export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
||||
private videoRef = React.createRef<HTMLVideoElement>();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -71,7 +73,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
_getContentUrl(): string|null {
|
||||
private getContentUrl(): string|null {
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined) {
|
||||
return this.state.decryptedUrl;
|
||||
|
@ -80,7 +82,12 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
_getThumbUrl(): string|null {
|
||||
private hasContentUrl(): boolean {
|
||||
const url = this.getContentUrl();
|
||||
return url && !url.startsWith("data:");
|
||||
}
|
||||
|
||||
private getThumbUrl(): string|null {
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined) {
|
||||
return this.state.decryptedThumbnailUrl;
|
||||
|
@ -118,7 +125,10 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
} else {
|
||||
console.log("NOT preloading video");
|
||||
this.setState({
|
||||
decryptedUrl: null,
|
||||
// For Chrome and Electron, we need to set some non-empty `src` to
|
||||
// enable the play button. Firefox does not seem to care either
|
||||
// way, so it's fine to do for all browsers.
|
||||
decryptedUrl: `data:${content?.info?.mimetype},`,
|
||||
decryptedThumbnailUrl: thumbnailUrl,
|
||||
decryptedBlob: null,
|
||||
});
|
||||
|
@ -142,8 +152,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
async _videoOnPlay() {
|
||||
if (this._getContentUrl() || this.state.fetchingData || this.state.error) {
|
||||
private videoOnPlay = async () => {
|
||||
if (this.hasContentUrl() || this.state.fetchingData || this.state.error) {
|
||||
// We have the file, we are fetching the file, or there is an error.
|
||||
return;
|
||||
}
|
||||
|
@ -164,6 +174,9 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
decryptedUrl: contentUrl,
|
||||
decryptedBlob: decryptedBlob,
|
||||
fetchingData: false,
|
||||
}, () => {
|
||||
if (!this.videoRef.current) return;
|
||||
this.videoRef.current.play();
|
||||
});
|
||||
this.props.onHeightChanged();
|
||||
}
|
||||
|
@ -195,8 +208,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
const contentUrl = this._getContentUrl();
|
||||
const thumbUrl = this._getThumbUrl();
|
||||
const contentUrl = this.getContentUrl();
|
||||
const thumbUrl = this.getThumbUrl();
|
||||
let height = null;
|
||||
let width = null;
|
||||
let poster = null;
|
||||
|
@ -215,9 +228,20 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
return (
|
||||
<span className="mx_MVideoBody">
|
||||
<video className="mx_MVideoBody" src={contentUrl} title={content.body}
|
||||
controls preload={preload} muted={autoplay} autoPlay={autoplay}
|
||||
height={height} width={width} poster={poster} onPlay={this._videoOnPlay.bind(this)}>
|
||||
<video
|
||||
className="mx_MVideoBody"
|
||||
ref={this.videoRef}
|
||||
src={contentUrl}
|
||||
title={content.body}
|
||||
controls
|
||||
preload={preload}
|
||||
muted={autoplay}
|
||||
autoPlay={autoplay}
|
||||
height={height}
|
||||
width={width}
|
||||
poster={poster}
|
||||
onPlay={this.videoOnPlay}
|
||||
>
|
||||
</video>
|
||||
<MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} />
|
||||
</span>
|
||||
|
|
Loading…
Reference in a new issue