diff options
author | Chocobozzz <me@florianbigard.com> | 2020-01-28 17:29:50 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2020-01-29 11:48:15 +0100 |
commit | f5fcd9f72514d6c4044a9c904d0ce610033bcba5 (patch) | |
tree | 241b7f0dd4435fa4451b1bd70a2103e092369c8c /client/src/assets/player/upnext/end-card.ts | |
parent | 0374b6b5cd685316f924874b2a3068bb345eb0dd (diff) | |
download | PeerTube-f5fcd9f72514d6c4044a9c904d0ce610033bcba5.tar.gz PeerTube-f5fcd9f72514d6c4044a9c904d0ce610033bcba5.tar.zst PeerTube-f5fcd9f72514d6c4044a9c904d0ce610033bcba5.zip |
Correctly type videojs player
Diffstat (limited to 'client/src/assets/player/upnext/end-card.ts')
-rw-r--r-- | client/src/assets/player/upnext/end-card.ts | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/client/src/assets/player/upnext/end-card.ts b/client/src/assets/player/upnext/end-card.ts new file mode 100644 index 000000000..d121a83a9 --- /dev/null +++ b/client/src/assets/player/upnext/end-card.ts | |||
@@ -0,0 +1,155 @@ | |||
1 | import videojs, { VideoJsPlayer } from 'video.js' | ||
2 | |||
3 | function getMainTemplate (options: any) { | ||
4 | return ` | ||
5 | <div class="vjs-upnext-top"> | ||
6 | <span class="vjs-upnext-headtext">${options.headText}</span> | ||
7 | <div class="vjs-upnext-title"></div> | ||
8 | </div> | ||
9 | <div class="vjs-upnext-autoplay-icon"> | ||
10 | <svg height="100%" version="1.1" viewbox="0 0 98 98" width="100%"> | ||
11 | <circle class="vjs-upnext-svg-autoplay-circle" cx="49" cy="49" fill="#000" fill-opacity="0.8" r="48"></circle> | ||
12 | <circle class="vjs-upnext-svg-autoplay-ring" cx="-49" cy="49" fill-opacity="0" r="46.5" stroke="#FFFFFF" stroke-width="4" transform="rotate(-90)"></circle> | ||
13 | <polygon class="vjs-upnext-svg-autoplay-triangle" fill="#fff" points="32,27 72,49 32,71"></polygon></svg> | ||
14 | </div> | ||
15 | <span class="vjs-upnext-bottom"> | ||
16 | <span class="vjs-upnext-cancel"> | ||
17 | <button class="vjs-upnext-cancel-button" tabindex="0" aria-label="Cancel autoplay">${options.cancelText}</button> | ||
18 | </span> | ||
19 | <span class="vjs-upnext-suspended">${options.suspendedText}</span> | ||
20 | </span> | ||
21 | ` | ||
22 | } | ||
23 | |||
24 | export interface EndCardOptions extends videojs.ComponentOptions { | ||
25 | next: Function, | ||
26 | getTitle: () => string | ||
27 | timeout: number | ||
28 | cancelText: string | ||
29 | headText: string | ||
30 | suspendedText: string | ||
31 | condition: () => boolean | ||
32 | suspended: () => boolean | ||
33 | } | ||
34 | |||
35 | const Component = videojs.getComponent('Component') | ||
36 | class EndCard extends Component { | ||
37 | options_: EndCardOptions | ||
38 | |||
39 | dashOffsetTotal = 586 | ||
40 | dashOffsetStart = 293 | ||
41 | interval = 50 | ||
42 | upNextEvents = new videojs.EventTarget() | ||
43 | ticks = 0 | ||
44 | totalTicks: number | ||
45 | |||
46 | container: HTMLDivElement | ||
47 | title: HTMLElement | ||
48 | autoplayRing: HTMLElement | ||
49 | cancelButton: HTMLElement | ||
50 | suspendedMessage: HTMLElement | ||
51 | nextButton: HTMLElement | ||
52 | |||
53 | constructor (player: VideoJsPlayer, options: EndCardOptions) { | ||
54 | super(player, options) | ||
55 | |||
56 | this.totalTicks = this.options_.timeout / this.interval | ||
57 | |||
58 | player.on('ended', (_: any) => { | ||
59 | if (!this.options_.condition()) return | ||
60 | |||
61 | player.addClass('vjs-upnext--showing') | ||
62 | this.showCard((canceled: boolean) => { | ||
63 | player.removeClass('vjs-upnext--showing') | ||
64 | this.container.style.display = 'none' | ||
65 | if (!canceled) { | ||
66 | this.options_.next() | ||
67 | } | ||
68 | }) | ||
69 | }) | ||
70 | |||
71 | player.on('playing', () => { | ||
72 | this.upNextEvents.trigger('playing') | ||
73 | }) | ||
74 | } | ||
75 | |||
76 | createEl () { | ||
77 | const container = super.createEl('div', { | ||
78 | className: 'vjs-upnext-content', | ||
79 | innerHTML: getMainTemplate(this.options_) | ||
80 | }) as HTMLDivElement | ||
81 | |||
82 | this.container = container | ||
83 | container.style.display = 'none' | ||
84 | |||
85 | this.autoplayRing = container.getElementsByClassName('vjs-upnext-svg-autoplay-ring')[0] as HTMLElement | ||
86 | this.title = container.getElementsByClassName('vjs-upnext-title')[0] as HTMLElement | ||
87 | this.cancelButton = container.getElementsByClassName('vjs-upnext-cancel-button')[0] as HTMLElement | ||
88 | this.suspendedMessage = container.getElementsByClassName('vjs-upnext-suspended')[0] as HTMLElement | ||
89 | this.nextButton = container.getElementsByClassName('vjs-upnext-autoplay-icon')[0] as HTMLElement | ||
90 | |||
91 | this.cancelButton.onclick = () => { | ||
92 | this.upNextEvents.trigger('cancel') | ||
93 | } | ||
94 | |||
95 | this.nextButton.onclick = () => { | ||
96 | this.upNextEvents.trigger('next') | ||
97 | } | ||
98 | |||
99 | return container | ||
100 | } | ||
101 | |||
102 | showCard (cb: Function) { | ||
103 | let timeout: any | ||
104 | |||
105 | this.autoplayRing.setAttribute('stroke-dasharray', '' + this.dashOffsetStart) | ||
106 | this.autoplayRing.setAttribute('stroke-dashoffset', '' + -this.dashOffsetStart) | ||
107 | |||
108 | this.title.innerHTML = this.options_.getTitle() | ||
109 | |||
110 | this.upNextEvents.one('cancel', () => { | ||
111 | clearTimeout(timeout) | ||
112 | cb(true) | ||
113 | }) | ||
114 | |||
115 | this.upNextEvents.one('playing', () => { | ||
116 | clearTimeout(timeout) | ||
117 | cb(true) | ||
118 | }) | ||
119 | |||
120 | this.upNextEvents.one('next', () => { | ||
121 | clearTimeout(timeout) | ||
122 | cb(false) | ||
123 | }) | ||
124 | |||
125 | const goToPercent = (percent: number) => { | ||
126 | const newOffset = Math.max(-this.dashOffsetTotal, - this.dashOffsetStart - percent * this.dashOffsetTotal / 2 / 100) | ||
127 | this.autoplayRing.setAttribute('stroke-dashoffset', '' + newOffset) | ||
128 | } | ||
129 | |||
130 | const tick = () => { | ||
131 | goToPercent((this.ticks++) * 100 / this.totalTicks) | ||
132 | } | ||
133 | |||
134 | const update = () => { | ||
135 | if (this.options_.suspended()) { | ||
136 | this.suspendedMessage.innerText = this.options_.suspendedText | ||
137 | goToPercent(0) | ||
138 | this.ticks = 0 | ||
139 | timeout = setTimeout(update.bind(this), 300) // checks once supsended can be a bit longer | ||
140 | } else if (this.ticks >= this.totalTicks) { | ||
141 | clearTimeout(timeout) | ||
142 | cb(false) | ||
143 | } else { | ||
144 | this.suspendedMessage.innerText = '' | ||
145 | tick() | ||
146 | timeout = setTimeout(update.bind(this), this.interval) | ||
147 | } | ||
148 | } | ||
149 | |||
150 | this.container.style.display = 'block' | ||
151 | timeout = setTimeout(update.bind(this), this.interval) | ||
152 | } | ||
153 | } | ||
154 | |||
155 | videojs.registerComponent('EndCard', EndCard) | ||