-
Notifications
You must be signed in to change notification settings - Fork 1
/
Player.tsx
91 lines (76 loc) · 2.69 KB
/
Player.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
* @module common/components
*/
import createStyles from "@material-ui/core/styles/createStyles";
import withStyles, {WithStyles} from "@material-ui/core/styles/withStyles";
import {Plyr} from "dolos/plyr";
import * as React from "react";
import * as ReactDOM from "react-dom";
/** @ignore */
const styles = () => createStyles({
plyrContainer: {
"& .plyr": {
height: "100%",
width: "100%",
},
"height": "100%",
"width": "100%",
},
});
export interface PlayerSource {
url: string;
type?: string;
}
export type PlyrEvents = Plyr.StandardEvent | Plyr.Html5Event;
export interface PlayerProps extends WithStyles<typeof styles> {
options?: any;
eventListener?: Partial<{ [key in PlyrEvents]: (event: CustomEvent) => any }>;
poster?: string;
sources: PlayerSource[];
}
// tslint:disable-next-line:variable-name
export const Player = withStyles(styles)(
class extends React.Component<PlayerProps> {
public player?: Plyr;
public componentDidMount() {
const {eventListener, options} = this.props;
// normal autoplay only works when muted and doesn't fire "ended" event!
const autoplay = options.autoplay;
options.autoplay = false;
const domNode = ReactDOM.findDOMNode(this);
if (!(domNode && domNode.firstChild))
throw new Error("Couldn't find dom node");
this.player = new Plyr(domNode.firstChild as HTMLElement, options);
if (eventListener) {
for (const [event, handler] of Object.entries(eventListener)) {
if (!handler) continue;
this.player.on(event as PlyrEvents, handler);
}
}
if (autoplay) Promise.resolve(this.player.play()).catch();
}
public componentWillUnmount() {
if (this.player) this.player.destroy();
}
public renderSource(): Array<React.ReactElement<any>> {
// currently plyr breaks when not supplying a video type, this defaulting to video/mp4
return this.props.sources.map((source, index) => (
<source
key={index}
src={source.url}
type={source.type || "video/mp4"}
/>
));
}
public render() {
const {classes} = this.props;
return (
<div className={classes.plyrContainer}>
<video poster={this.props.poster} playsInline controls>
{this.renderSource()}
</video>
</div>
);
}
},
);