]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/assets/player/shared/upnext/end-card.ts
Reorganize player files
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / shared / upnext / end-card.ts
CommitLineData
512decf3 1import videojs from 'video.js'
f5fcd9f7
C
2
3function 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>
9df52d66
C
12 <circle class="vjs-upnext-svg-autoplay-ring" cx="-49" cy="49" fill-opacity="0" r="46.5"
13 stroke="#FFFFFF" stroke-width="4" transform="rotate(-90)"
14 ></circle>
f5fcd9f7
C
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>
21 <span class="vjs-upnext-suspended">${options.suspendedText}</span>
22 </span>
23 `
24}
25
26export interface EndCardOptions extends videojs.ComponentOptions {
9df52d66 27 next: () => void
f5fcd9f7
C
28 getTitle: () => string
29 timeout: number
30 cancelText: string
31 headText: string
32 suspendedText: string
33 condition: () => boolean
34 suspended: () => boolean
35}
36
37const Component = videojs.getComponent('Component')
38class EndCard extends Component {
39 options_: EndCardOptions
40
41 dashOffsetTotal = 586
42 dashOffsetStart = 293
43 interval = 50
44 upNextEvents = new videojs.EventTarget()
45 ticks = 0
46 totalTicks: number
47
48 container: HTMLDivElement
49 title: HTMLElement
50 autoplayRing: HTMLElement
51 cancelButton: HTMLElement
52 suspendedMessage: HTMLElement
53 nextButton: HTMLElement
54
7e37e111 55 constructor (player: videojs.Player, options: EndCardOptions) {
f5fcd9f7
C
56 super(player, options)
57
58 this.totalTicks = this.options_.timeout / this.interval
59
60 player.on('ended', (_: any) => {
61 if (!this.options_.condition()) return
62
63 player.addClass('vjs-upnext--showing')
64 this.showCard((canceled: boolean) => {
65 player.removeClass('vjs-upnext--showing')
66 this.container.style.display = 'none'
67 if (!canceled) {
68 this.options_.next()
69 }
70 })
71 })
72
73 player.on('playing', () => {
74 this.upNextEvents.trigger('playing')
75 })
76 }
77
78 createEl () {
79 const container = super.createEl('div', {
80 className: 'vjs-upnext-content',
81 innerHTML: getMainTemplate(this.options_)
82 }) as HTMLDivElement
83
84 this.container = container
85 container.style.display = 'none'
86
87 this.autoplayRing = container.getElementsByClassName('vjs-upnext-svg-autoplay-ring')[0] as HTMLElement
88 this.title = container.getElementsByClassName('vjs-upnext-title')[0] as HTMLElement
89 this.cancelButton = container.getElementsByClassName('vjs-upnext-cancel-button')[0] as HTMLElement
90 this.suspendedMessage = container.getElementsByClassName('vjs-upnext-suspended')[0] as HTMLElement
91 this.nextButton = container.getElementsByClassName('vjs-upnext-autoplay-icon')[0] as HTMLElement
92
93 this.cancelButton.onclick = () => {
94 this.upNextEvents.trigger('cancel')
95 }
96
97 this.nextButton.onclick = () => {
98 this.upNextEvents.trigger('next')
99 }
100
101 return container
102 }
103
9df52d66 104 showCard (cb: (value: boolean) => void) {
f5fcd9f7
C
105 let timeout: any
106
9df52d66
C
107 this.autoplayRing.setAttribute('stroke-dasharray', `${this.dashOffsetStart}`)
108 this.autoplayRing.setAttribute('stroke-dashoffset', `${-this.dashOffsetStart}`)
f5fcd9f7
C
109
110 this.title.innerHTML = this.options_.getTitle()
111
112 this.upNextEvents.one('cancel', () => {
113 clearTimeout(timeout)
114 cb(true)
115 })
116
117 this.upNextEvents.one('playing', () => {
118 clearTimeout(timeout)
119 cb(true)
120 })
121
122 this.upNextEvents.one('next', () => {
123 clearTimeout(timeout)
124 cb(false)
125 })
126
127 const goToPercent = (percent: number) => {
9df52d66 128 const newOffset = Math.max(-this.dashOffsetTotal, -this.dashOffsetStart - percent * this.dashOffsetTotal / 2 / 100)
f5fcd9f7
C
129 this.autoplayRing.setAttribute('stroke-dashoffset', '' + newOffset)
130 }
131
132 const tick = () => {
133 goToPercent((this.ticks++) * 100 / this.totalTicks)
134 }
135
136 const update = () => {
137 if (this.options_.suspended()) {
138 this.suspendedMessage.innerText = this.options_.suspendedText
139 goToPercent(0)
140 this.ticks = 0
141 timeout = setTimeout(update.bind(this), 300) // checks once supsended can be a bit longer
142 } else if (this.ticks >= this.totalTicks) {
143 clearTimeout(timeout)
144 cb(false)
145 } else {
146 this.suspendedMessage.innerText = ''
147 tick()
148 timeout = setTimeout(update.bind(this), this.interval)
149 }
150 }
151
152 this.container.style.display = 'block'
153 timeout = setTimeout(update.bind(this), this.interval)
154 }
155}
156
157videojs.registerComponent('EndCard', EndCard)