aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/assets/player/control-bar
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/assets/player/control-bar')
-rw-r--r--client/src/assets/player/control-bar/next-previous-video-button.ts50
-rw-r--r--client/src/assets/player/control-bar/p2p-info-button.ts124
-rw-r--r--client/src/assets/player/control-bar/peertube-link-button.ts45
-rw-r--r--client/src/assets/player/control-bar/peertube-load-progress-bar.ts33
-rw-r--r--client/src/assets/player/control-bar/theater-button.ts53
5 files changed, 305 insertions, 0 deletions
diff --git a/client/src/assets/player/control-bar/next-previous-video-button.ts b/client/src/assets/player/control-bar/next-previous-video-button.ts
new file mode 100644
index 000000000..fe17ce2ce
--- /dev/null
+++ b/client/src/assets/player/control-bar/next-previous-video-button.ts
@@ -0,0 +1,50 @@
1import videojs from 'video.js'
2import { NextPreviousVideoButtonOptions } from '../peertube-videojs-typings'
3
4const Button = videojs.getComponent('Button')
5
6class NextPreviousVideoButton extends Button {
7 private readonly nextPreviousVideoButtonOptions: NextPreviousVideoButtonOptions
8
9 constructor (player: videojs.Player, options?: NextPreviousVideoButtonOptions) {
10 super(player, options as any)
11
12 this.nextPreviousVideoButtonOptions = options
13
14 this.update()
15 }
16
17 createEl () {
18 const type = (this.options_ as NextPreviousVideoButtonOptions).type
19
20 const button = videojs.dom.createEl('button', {
21 className: 'vjs-' + type + '-video'
22 }) as HTMLButtonElement
23 const nextIcon = videojs.dom.createEl('span', {
24 className: 'icon icon-' + type
25 })
26 button.appendChild(nextIcon)
27
28 if (type === 'next') {
29 button.title = this.player_.localize('Next video')
30 } else {
31 button.title = this.player_.localize('Previous video')
32 }
33
34 return button
35 }
36
37 handleClick () {
38 this.nextPreviousVideoButtonOptions.handler()
39 }
40
41 update () {
42 const disabled = this.nextPreviousVideoButtonOptions.isDisabled()
43
44 if (disabled) this.addClass('vjs-disabled')
45 else this.removeClass('vjs-disabled')
46 }
47}
48
49videojs.registerComponent('NextVideoButton', NextPreviousVideoButton)
50videojs.registerComponent('PreviousVideoButton', NextPreviousVideoButton)
diff --git a/client/src/assets/player/control-bar/p2p-info-button.ts b/client/src/assets/player/control-bar/p2p-info-button.ts
new file mode 100644
index 000000000..081dee1d3
--- /dev/null
+++ b/client/src/assets/player/control-bar/p2p-info-button.ts
@@ -0,0 +1,124 @@
1import videojs from 'video.js'
2import { PeerTubeP2PInfoButtonOptions, PlayerNetworkInfo } from '../peertube-videojs-typings'
3import { bytes } from '../utils'
4
5const Button = videojs.getComponent('Button')
6class P2pInfoButton extends Button {
7
8 constructor (player: videojs.Player, options?: PeerTubeP2PInfoButtonOptions) {
9 super(player, options as any)
10 }
11
12 createEl () {
13 const div = videojs.dom.createEl('div', {
14 className: 'vjs-peertube'
15 })
16 const subDivWebtorrent = videojs.dom.createEl('div', {
17 className: 'vjs-peertube-hidden' // Hide the stats before we get the info
18 }) as HTMLDivElement
19 div.appendChild(subDivWebtorrent)
20
21 // Stop here if P2P is not enabled
22 const p2pEnabled = (this.options_ as PeerTubeP2PInfoButtonOptions).p2pEnabled
23 if (!p2pEnabled) return div as HTMLButtonElement
24
25 const downloadIcon = videojs.dom.createEl('span', {
26 className: 'icon icon-download'
27 })
28 subDivWebtorrent.appendChild(downloadIcon)
29
30 const downloadSpeedText = videojs.dom.createEl('span', {
31 className: 'download-speed-text'
32 })
33 const downloadSpeedNumber = videojs.dom.createEl('span', {
34 className: 'download-speed-number'
35 })
36 const downloadSpeedUnit = videojs.dom.createEl('span')
37 downloadSpeedText.appendChild(downloadSpeedNumber)
38 downloadSpeedText.appendChild(downloadSpeedUnit)
39 subDivWebtorrent.appendChild(downloadSpeedText)
40
41 const uploadIcon = videojs.dom.createEl('span', {
42 className: 'icon icon-upload'
43 })
44 subDivWebtorrent.appendChild(uploadIcon)
45
46 const uploadSpeedText = videojs.dom.createEl('span', {
47 className: 'upload-speed-text'
48 })
49 const uploadSpeedNumber = videojs.dom.createEl('span', {
50 className: 'upload-speed-number'
51 })
52 const uploadSpeedUnit = videojs.dom.createEl('span')
53 uploadSpeedText.appendChild(uploadSpeedNumber)
54 uploadSpeedText.appendChild(uploadSpeedUnit)
55 subDivWebtorrent.appendChild(uploadSpeedText)
56
57 const peersText = videojs.dom.createEl('span', {
58 className: 'peers-text'
59 })
60 const peersNumber = videojs.dom.createEl('span', {
61 className: 'peers-number'
62 })
63 subDivWebtorrent.appendChild(peersNumber)
64 subDivWebtorrent.appendChild(peersText)
65
66 const subDivHttp = videojs.dom.createEl('div', {
67 className: 'vjs-peertube-hidden'
68 })
69 const subDivHttpText = videojs.dom.createEl('span', {
70 className: 'http-fallback',
71 textContent: 'HTTP'
72 })
73
74 subDivHttp.appendChild(subDivHttpText)
75 div.appendChild(subDivHttp)
76
77 this.player_.on('p2pInfo', (event: any, data: PlayerNetworkInfo) => {
78 // We are in HTTP fallback
79 if (!data) {
80 subDivHttp.className = 'vjs-peertube-displayed'
81 subDivWebtorrent.className = 'vjs-peertube-hidden'
82
83 return
84 }
85
86 const p2pStats = data.p2p
87 const httpStats = data.http
88
89 const downloadSpeed = bytes(p2pStats.downloadSpeed + httpStats.downloadSpeed)
90 const uploadSpeed = bytes(p2pStats.uploadSpeed + httpStats.uploadSpeed)
91 const totalDownloaded = bytes(p2pStats.downloaded + httpStats.downloaded)
92 const totalUploaded = bytes(p2pStats.uploaded + httpStats.uploaded)
93 const numPeers = p2pStats.numPeers
94
95 subDivWebtorrent.title = this.player().localize('Total downloaded: ') + totalDownloaded.join(' ') + '\n'
96
97 if (data.source === 'p2p-media-loader') {
98 const downloadedFromServer = bytes(httpStats.downloaded).join(' ')
99 const downloadedFromPeers = bytes(p2pStats.downloaded).join(' ')
100
101 subDivWebtorrent.title +=
102 ' * ' + this.player().localize('From servers: ') + downloadedFromServer + '\n' +
103 ' * ' + this.player().localize('From peers: ') + downloadedFromPeers + '\n'
104 }
105 subDivWebtorrent.title += this.player().localize('Total uploaded: ') + totalUploaded.join(' ')
106
107 downloadSpeedNumber.textContent = downloadSpeed[0]
108 downloadSpeedUnit.textContent = ' ' + downloadSpeed[1]
109
110 uploadSpeedNumber.textContent = uploadSpeed[0]
111 uploadSpeedUnit.textContent = ' ' + uploadSpeed[1]
112
113 peersNumber.textContent = numPeers.toString()
114 peersText.textContent = ' ' + (numPeers > 1 ? this.player().localize('peers') : this.player_.localize('peer'))
115
116 subDivHttp.className = 'vjs-peertube-hidden'
117 subDivWebtorrent.className = 'vjs-peertube-displayed'
118 })
119
120 return div as HTMLButtonElement
121 }
122}
123
124videojs.registerComponent('P2PInfoButton', P2pInfoButton)
diff --git a/client/src/assets/player/control-bar/peertube-link-button.ts b/client/src/assets/player/control-bar/peertube-link-button.ts
new file mode 100644
index 000000000..c49cee566
--- /dev/null
+++ b/client/src/assets/player/control-bar/peertube-link-button.ts
@@ -0,0 +1,45 @@
1import videojs from 'video.js'
2import { buildVideoLink, decorateVideoLink } from '@shared/core-utils'
3import { PeerTubeLinkButtonOptions } from '../peertube-videojs-typings'
4
5const Button = videojs.getComponent('Button')
6class PeerTubeLinkButton extends Button {
7
8 constructor (player: videojs.Player, options?: PeerTubeLinkButtonOptions) {
9 super(player, options as any)
10 }
11
12 createEl () {
13 return this.buildElement()
14 }
15
16 updateHref () {
17 this.el().setAttribute('href', this.buildLink())
18 }
19
20 handleClick () {
21 this.player().pause()
22 }
23
24 private buildElement () {
25 const el = videojs.dom.createEl('a', {
26 href: this.buildLink(),
27 innerHTML: 'PeerTube',
28 title: this.player().localize('Video page (new window)'),
29 className: 'vjs-peertube-link',
30 target: '_blank'
31 })
32
33 el.addEventListener('mouseenter', () => this.updateHref())
34
35 return el as HTMLButtonElement
36 }
37
38 private buildLink () {
39 const url = buildVideoLink({ shortUUID: (this.options_ as PeerTubeLinkButtonOptions).shortUUID })
40
41 return decorateVideoLink({ url, startTime: this.player().currentTime() })
42 }
43}
44
45videojs.registerComponent('PeerTubeLinkButton', PeerTubeLinkButton)
diff --git a/client/src/assets/player/control-bar/peertube-load-progress-bar.ts b/client/src/assets/player/control-bar/peertube-load-progress-bar.ts
new file mode 100644
index 000000000..623e70eb2
--- /dev/null
+++ b/client/src/assets/player/control-bar/peertube-load-progress-bar.ts
@@ -0,0 +1,33 @@
1import videojs from 'video.js'
2
3const Component = videojs.getComponent('Component')
4
5class PeerTubeLoadProgressBar extends Component {
6
7 constructor (player: videojs.Player, options?: videojs.ComponentOptions) {
8 super(player, options)
9
10 this.on(player, 'progress', this.update)
11 }
12
13 createEl () {
14 return super.createEl('div', {
15 className: 'vjs-load-progress',
16 innerHTML: `<span class="vjs-control-text"><span>${this.localize('Loaded')}</span>: 0%</span>`
17 })
18 }
19
20 dispose () {
21 super.dispose()
22 }
23
24 update () {
25 const torrent = this.player().webtorrent().getTorrent()
26 if (!torrent) return
27
28 (this.el() as HTMLElement).style.width = (torrent.progress * 100) + '%'
29 }
30
31}
32
33Component.registerComponent('PeerTubeLoadProgressBar', PeerTubeLoadProgressBar)
diff --git a/client/src/assets/player/control-bar/theater-button.ts b/client/src/assets/player/control-bar/theater-button.ts
new file mode 100644
index 000000000..f862ee224
--- /dev/null
+++ b/client/src/assets/player/control-bar/theater-button.ts
@@ -0,0 +1,53 @@
1import videojs from 'video.js'
2import { saveTheaterInStore, getStoredTheater } from '../peertube-player-local-storage'
3
4const Button = videojs.getComponent('Button')
5class TheaterButton extends Button {
6
7 private static readonly THEATER_MODE_CLASS = 'vjs-theater-enabled'
8
9 constructor (player: videojs.Player, options: videojs.ComponentOptions) {
10 super(player, options)
11
12 const enabled = getStoredTheater()
13 if (enabled === true) {
14 this.player().addClass(TheaterButton.THEATER_MODE_CLASS)
15
16 this.handleTheaterChange()
17 }
18
19 this.controlText('Theater mode')
20
21 this.player().theaterEnabled = enabled
22 }
23
24 buildCSSClass () {
25 return `vjs-theater-control ${super.buildCSSClass()}`
26 }
27
28 handleTheaterChange () {
29 const theaterEnabled = this.isTheaterEnabled()
30
31 if (theaterEnabled) {
32 this.controlText('Normal mode')
33 } else {
34 this.controlText('Theater mode')
35 }
36
37 saveTheaterInStore(theaterEnabled)
38
39 this.player_.trigger('theaterChange', theaterEnabled)
40 }
41
42 handleClick () {
43 this.player_.toggleClass(TheaterButton.THEATER_MODE_CLASS)
44
45 this.handleTheaterChange()
46 }
47
48 private isTheaterEnabled () {
49 return this.player_.hasClass(TheaterButton.THEATER_MODE_CLASS)
50 }
51}
52
53videojs.registerComponent('TheaterButton', TheaterButton)