]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/assets/player/upnext/upnext-plugin.ts
Fix upnext, refactor avatar menu, add to playlist overflow
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / upnext / upnext-plugin.ts
CommitLineData
3bcb4fd7
RK
1// @ts-ignore
2import * as videojs from 'video.js'
3import { VideoJSComponentInterface } from '../peertube-videojs-typings'
4
5function getMainTemplate (options: any) {
6 return `
7 <div class="vjs-upnext-top">
8 <span class="vjs-upnext-headtext">${options.headText}</span>
9 <div class="vjs-upnext-title"></div>
10 </div>
11 <div class="vjs-upnext-autoplay-icon">
12 <svg height="100%" version="1.1" viewbox="0 0 98 98" width="100%">
13 <circle class="vjs-upnext-svg-autoplay-circle" cx="49" cy="49" fill="#000" fill-opacity="0.8" r="48"></circle>
14 <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>
15 <polygon class="vjs-upnext-svg-autoplay-triangle" fill="#fff" points="32,27 72,49 32,71"></polygon></svg>
16 </div>
17 <span class="vjs-upnext-bottom">
18 <span class="vjs-upnext-cancel">
19 <button class="vjs-upnext-cancel-button" tabindex="0" aria-label="Cancel autoplay">${options.cancelText}</button>
20 </span>
223b24e6 21 <span class="vjs-upnext-suspended">${options.suspendedText}</span>
3bcb4fd7
RK
22 </span>
23 `
24}
25
26// @ts-ignore-start
27const Component = videojs.getComponent('Component')
28class EndCard extends Component {
29 options_: any
3bcb4fd7
RK
30 dashOffsetTotal = 586
31 dashOffsetStart = 293
32 interval = 50
33 upNextEvents = new videojs.EventTarget()
223b24e6
RK
34 ticks = 0
35 totalTicks: number
3bcb4fd7
RK
36
37 container: HTMLElement
38 title: HTMLElement
39 autoplayRing: HTMLElement
40 cancelButton: HTMLElement
223b24e6 41 suspendedMessage: HTMLElement
3bcb4fd7
RK
42 nextButton: HTMLElement
43
44 constructor (player: videojs.Player, options: any) {
45 super(player, options)
3bcb4fd7 46
223b24e6 47 this.totalTicks = this.options_.timeout / this.interval
3bcb4fd7
RK
48
49 player.on('ended', (_: any) => {
223b24e6 50 if (!this.options_.condition()) return
3bcb4fd7
RK
51
52 player.addClass('vjs-upnext--showing')
53 this.showCard((canceled: boolean) => {
54 player.removeClass('vjs-upnext--showing')
55 this.container.style.display = 'none'
56 if (!canceled) {
223b24e6 57 this.options_.next()
3bcb4fd7
RK
58 }
59 })
60 })
61
62 player.on('playing', () => {
63 this.upNextEvents.trigger('playing')
64 })
65 }
66
67 createEl () {
68 const container = super.createEl('div', {
69 className: 'vjs-upnext-content',
70 innerHTML: getMainTemplate(this.options_)
71 })
72
73 this.container = container
74 container.style.display = 'none'
75
76 this.autoplayRing = container.getElementsByClassName('vjs-upnext-svg-autoplay-ring')[0]
77 this.title = container.getElementsByClassName('vjs-upnext-title')[0]
78 this.cancelButton = container.getElementsByClassName('vjs-upnext-cancel-button')[0]
223b24e6 79 this.suspendedMessage = container.getElementsByClassName('vjs-upnext-suspended')[0]
3bcb4fd7
RK
80 this.nextButton = container.getElementsByClassName('vjs-upnext-autoplay-icon')[0]
81
82 this.cancelButton.onclick = () => {
83 this.upNextEvents.trigger('cancel')
84 }
85
86 this.nextButton.onclick = () => {
87 this.upNextEvents.trigger('next')
88 }
89
90 return container
91 }
92
93 showCard (cb: Function) {
94 let timeout: any
3bcb4fd7 95
9f0327ae
C
96 this.autoplayRing.setAttribute('stroke-dasharray', '' + this.dashOffsetStart)
97 this.autoplayRing.setAttribute('stroke-dashoffset', '' + -this.dashOffsetStart)
3bcb4fd7 98
223b24e6 99 this.title.innerHTML = this.options_.getTitle()
3bcb4fd7
RK
100
101 this.upNextEvents.one('cancel', () => {
102 clearTimeout(timeout)
103 cb(true)
104 })
105
106 this.upNextEvents.one('playing', () => {
107 clearTimeout(timeout)
108 cb(true)
109 })
110
111 this.upNextEvents.one('next', () => {
112 clearTimeout(timeout)
113 cb(false)
114 })
115
223b24e6
RK
116 const goToPercent = (percent: number) => {
117 const newOffset = Math.max(-this.dashOffsetTotal, - this.dashOffsetStart - percent * this.dashOffsetTotal / 2 / 100)
118 this.autoplayRing.setAttribute('stroke-dashoffset', '' + newOffset)
119 }
3bcb4fd7 120
223b24e6
RK
121 const tick = () => {
122 goToPercent((this.ticks++) * 100 / this.totalTicks)
123 }
124
125 const update = () => {
126 if (this.options_.suspended()) {
127 this.suspendedMessage.innerText = this.options_.suspendedText
128 goToPercent(0)
129 this.ticks = 0
130 timeout = setTimeout(update.bind(this), 300) // checks once supsended can be a bit longer
131 } else if (this.ticks >= this.totalTicks) {
3bcb4fd7
RK
132 clearTimeout(timeout)
133 cb(false)
134 } else {
223b24e6
RK
135 this.suspendedMessage.innerText = ''
136 tick()
3bcb4fd7
RK
137 timeout = setTimeout(update.bind(this), this.interval)
138 }
3bcb4fd7
RK
139 }
140
141 this.container.style.display = 'block'
3bcb4fd7
RK
142 timeout = setTimeout(update.bind(this), this.interval)
143 }
144}
145// @ts-ignore-end
146
147videojs.registerComponent('EndCard', EndCard)
148
149const Plugin: VideoJSComponentInterface = videojs.getPlugin('plugin')
150class UpNextPlugin extends Plugin {
151 constructor (player: videojs.Player, options: any = {}) {
152 const settings = {
153 next: options.next,
154 getTitle: options.getTitle,
155 timeout: options.timeout || 5000,
156 cancelText: options.cancelText || 'Cancel',
157 headText: options.headText || 'Up Next',
223b24e6
RK
158 suspendedText: options.suspendedText || 'Autoplay is suspended',
159 condition: options.condition,
160 suspended: options.suspended
3bcb4fd7
RK
161 }
162
163 super(player, settings)
164
165 this.player.ready(() => {
166 player.addClass('vjs-upnext')
167 })
168
169 player.addChild('EndCard', settings)
170 }
171}
172
173videojs.registerPlugin('upnext', UpNextPlugin)
174export { UpNextPlugin }