diff options
Diffstat (limited to 'client/src/assets/player')
-rw-r--r-- | client/src/assets/player/images/theater.svg | 13 | ||||
-rw-r--r-- | client/src/assets/player/peertube-player.ts | 9 | ||||
-rw-r--r-- | client/src/assets/player/peertube-videojs-plugin.ts | 30 | ||||
-rw-r--r-- | client/src/assets/player/theater-button.ts | 46 | ||||
-rw-r--r-- | client/src/assets/player/utils.ts | 13 |
5 files changed, 99 insertions, 12 deletions
diff --git a/client/src/assets/player/images/theater.svg b/client/src/assets/player/images/theater.svg new file mode 100644 index 000000000..d7086c214 --- /dev/null +++ b/client/src/assets/player/images/theater.svg | |||
@@ -0,0 +1,13 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
3 | <!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch --> | ||
4 | <title>theater</title> | ||
5 | <defs></defs> | ||
6 | <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> | ||
7 | <g id="Artboard-4" transform="translate(-576.000000, -159.000000)" stroke="#fff" stroke-width="2"> | ||
8 | <g id="33" transform="translate(576.000000, 159.000000)"> | ||
9 | <rect id="Rectangle-433" x="1" y="6" width="22" height="12"></rect> | ||
10 | </g> | ||
11 | </g> | ||
12 | </g> | ||
13 | </svg> | ||
diff --git a/client/src/assets/player/peertube-player.ts b/client/src/assets/player/peertube-player.ts index eb75091de..afc8e0881 100644 --- a/client/src/assets/player/peertube-player.ts +++ b/client/src/assets/player/peertube-player.ts | |||
@@ -10,6 +10,7 @@ import './settings-menu-button' | |||
10 | import './webtorrent-info-button' | 10 | import './webtorrent-info-button' |
11 | import './peertube-videojs-plugin' | 11 | import './peertube-videojs-plugin' |
12 | import './peertube-load-progress-bar' | 12 | import './peertube-load-progress-bar' |
13 | import './theater-button' | ||
13 | import { videojsUntyped } from './peertube-videojs-typings' | 14 | import { videojsUntyped } from './peertube-videojs-typings' |
14 | import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils' | 15 | import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils' |
15 | import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n' | 16 | import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n' |
@@ -28,6 +29,7 @@ function getVideojsOptions (options: { | |||
28 | peertubeLink: boolean, | 29 | peertubeLink: boolean, |
29 | poster: string, | 30 | poster: string, |
30 | startTime: number | 31 | startTime: number |
32 | theaterMode: boolean | ||
31 | }) { | 33 | }) { |
32 | const videojsOptions = { | 34 | const videojsOptions = { |
33 | controls: true, | 35 | controls: true, |
@@ -63,6 +65,7 @@ function getVideojsOptions (options: { | |||
63 | 65 | ||
64 | function getControlBarChildren (options: { | 66 | function getControlBarChildren (options: { |
65 | peertubeLink: boolean | 67 | peertubeLink: boolean |
68 | theaterMode: boolean | ||
66 | }) { | 69 | }) { |
67 | const children = { | 70 | const children = { |
68 | 'playToggle': {}, | 71 | 'playToggle': {}, |
@@ -105,6 +108,12 @@ function getControlBarChildren (options: { | |||
105 | }) | 108 | }) |
106 | } | 109 | } |
107 | 110 | ||
111 | if (options.theaterMode === true) { | ||
112 | Object.assign(children, { | ||
113 | 'theaterButton': {} | ||
114 | }) | ||
115 | } | ||
116 | |||
108 | Object.assign(children, { | 117 | Object.assign(children, { |
109 | 'fullscreenToggle': {} | 118 | 'fullscreenToggle': {} |
110 | }) | 119 | }) |
diff --git a/client/src/assets/player/peertube-videojs-plugin.ts b/client/src/assets/player/peertube-videojs-plugin.ts index 47288c842..d3ae7b137 100644 --- a/client/src/assets/player/peertube-videojs-plugin.ts +++ b/client/src/assets/player/peertube-videojs-plugin.ts | |||
@@ -55,6 +55,7 @@ class PeerTubePlugin extends Plugin { | |||
55 | private player: any | 55 | private player: any |
56 | private currentVideoFile: VideoFile | 56 | private currentVideoFile: VideoFile |
57 | private torrent: WebTorrent.Torrent | 57 | private torrent: WebTorrent.Torrent |
58 | private fakeRenderer | ||
58 | private autoResolution = true | 59 | private autoResolution = true |
59 | private isAutoResolutionObservation = false | 60 | private isAutoResolutionObservation = false |
60 | 61 | ||
@@ -123,6 +124,8 @@ class PeerTubePlugin extends Plugin { | |||
123 | 124 | ||
124 | // Don't need to destroy renderer, video player will be destroyed | 125 | // Don't need to destroy renderer, video player will be destroyed |
125 | this.flushVideoFile(this.currentVideoFile, false) | 126 | this.flushVideoFile(this.currentVideoFile, false) |
127 | |||
128 | this.destroyFakeRenderer() | ||
126 | } | 129 | } |
127 | 130 | ||
128 | getCurrentResolutionId () { | 131 | getCurrentResolutionId () { |
@@ -185,7 +188,6 @@ class PeerTubePlugin extends Plugin { | |||
185 | console.log('Adding ' + magnetOrTorrentUrl + '.') | 188 | console.log('Adding ' + magnetOrTorrentUrl + '.') |
186 | 189 | ||
187 | const oldTorrent = this.torrent | 190 | const oldTorrent = this.torrent |
188 | let fakeRenderer | ||
189 | const torrentOptions = { | 191 | const torrentOptions = { |
190 | store: (chunkLength, storeOpts) => new CacheChunkStore(new PeertubeChunkStore(chunkLength, storeOpts), { | 192 | store: (chunkLength, storeOpts) => new CacheChunkStore(new PeertubeChunkStore(chunkLength, storeOpts), { |
191 | max: 100 | 193 | max: 100 |
@@ -205,7 +207,7 @@ class PeerTubePlugin extends Plugin { | |||
205 | if (options.delay) { | 207 | if (options.delay) { |
206 | const fakeVideoElem = document.createElement('video') | 208 | const fakeVideoElem = document.createElement('video') |
207 | renderVideo(torrent.files[0], fakeVideoElem, { autoplay: false, controls: false }, (err, renderer) => { | 209 | renderVideo(torrent.files[0], fakeVideoElem, { autoplay: false, controls: false }, (err, renderer) => { |
208 | fakeRenderer = renderer | 210 | this.fakeRenderer = renderer |
209 | 211 | ||
210 | if (err) console.error('Cannot render new torrent in fake video element.', err) | 212 | if (err) console.error('Cannot render new torrent in fake video element.', err) |
211 | 213 | ||
@@ -217,16 +219,7 @@ class PeerTubePlugin extends Plugin { | |||
217 | 219 | ||
218 | // Render the video in a few seconds? (on resolution change for example, we wait some seconds of the new video resolution) | 220 | // Render the video in a few seconds? (on resolution change for example, we wait some seconds of the new video resolution) |
219 | this.addTorrentDelay = setTimeout(() => { | 221 | this.addTorrentDelay = setTimeout(() => { |
220 | if (fakeRenderer) { | 222 | this.destroyFakeRenderer() |
221 | if (fakeRenderer.destroy) { | ||
222 | try { | ||
223 | fakeRenderer.destroy() | ||
224 | } catch (err) { | ||
225 | console.log('Cannot destroy correctly fake renderer.', err) | ||
226 | } | ||
227 | } | ||
228 | fakeRenderer = undefined | ||
229 | } | ||
230 | 223 | ||
231 | const paused = this.player.paused() | 224 | const paused = this.player.paused() |
232 | 225 | ||
@@ -567,6 +560,19 @@ class PeerTubePlugin extends Plugin { | |||
567 | return this.videoFiles[Math.floor(this.videoFiles.length / 2)] | 560 | return this.videoFiles[Math.floor(this.videoFiles.length / 2)] |
568 | } | 561 | } |
569 | 562 | ||
563 | private destroyFakeRenderer () { | ||
564 | if (this.fakeRenderer) { | ||
565 | if (this.fakeRenderer.destroy) { | ||
566 | try { | ||
567 | this.fakeRenderer.destroy() | ||
568 | } catch (err) { | ||
569 | console.log('Cannot destroy correctly fake renderer.', err) | ||
570 | } | ||
571 | } | ||
572 | this.fakeRenderer = undefined | ||
573 | } | ||
574 | } | ||
575 | |||
570 | // Thanks: https://github.com/videojs/video.js/issues/4460#issuecomment-312861657 | 576 | // Thanks: https://github.com/videojs/video.js/issues/4460#issuecomment-312861657 |
571 | private initSmoothProgressBar () { | 577 | private initSmoothProgressBar () { |
572 | const SeekBar = videojsUntyped.getComponent('SeekBar') | 578 | const SeekBar = videojsUntyped.getComponent('SeekBar') |
diff --git a/client/src/assets/player/theater-button.ts b/client/src/assets/player/theater-button.ts new file mode 100644 index 000000000..1d330e08f --- /dev/null +++ b/client/src/assets/player/theater-button.ts | |||
@@ -0,0 +1,46 @@ | |||
1 | import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' | ||
2 | import { getStoredTheater, saveTheaterInStore } from './utils' | ||
3 | |||
4 | const Button: VideoJSComponentInterface = videojsUntyped.getComponent('Button') | ||
5 | class TheaterButton extends Button { | ||
6 | |||
7 | private static readonly THEATER_MODE_CLASS = 'vjs-theater-enabled' | ||
8 | |||
9 | constructor (player, options) { | ||
10 | super(player, options) | ||
11 | |||
12 | const enabled = getStoredTheater() | ||
13 | if (enabled === true) { | ||
14 | this.player_.addClass(TheaterButton.THEATER_MODE_CLASS) | ||
15 | this.handleTheaterChange() | ||
16 | } | ||
17 | } | ||
18 | |||
19 | buildCSSClass () { | ||
20 | return `vjs-theater-control ${super.buildCSSClass()}` | ||
21 | } | ||
22 | |||
23 | handleTheaterChange () { | ||
24 | if (this.isTheaterEnabled()) { | ||
25 | this.controlText('Normal mode') | ||
26 | } else { | ||
27 | this.controlText('Theater mode') | ||
28 | } | ||
29 | |||
30 | saveTheaterInStore(this.isTheaterEnabled()) | ||
31 | } | ||
32 | |||
33 | handleClick () { | ||
34 | this.player_.toggleClass(TheaterButton.THEATER_MODE_CLASS) | ||
35 | |||
36 | this.handleTheaterChange() | ||
37 | } | ||
38 | |||
39 | private isTheaterEnabled () { | ||
40 | return this.player_.hasClass(TheaterButton.THEATER_MODE_CLASS) | ||
41 | } | ||
42 | } | ||
43 | |||
44 | TheaterButton.prototype.controlText_ = 'Theater mode' | ||
45 | |||
46 | TheaterButton.registerComponent('TheaterButton', TheaterButton) | ||
diff --git a/client/src/assets/player/utils.ts b/client/src/assets/player/utils.ts index 4eaf53720..b7cd40aa2 100644 --- a/client/src/assets/player/utils.ts +++ b/client/src/assets/player/utils.ts | |||
@@ -51,6 +51,13 @@ function getAverageBandwidth () { | |||
51 | return undefined | 51 | return undefined |
52 | } | 52 | } |
53 | 53 | ||
54 | function getStoredTheater () { | ||
55 | const value = getLocalStorage('theater-enabled') | ||
56 | if (value !== null && value !== undefined) return value === 'true' | ||
57 | |||
58 | return undefined | ||
59 | } | ||
60 | |||
54 | function saveVolumeInStore (value: number) { | 61 | function saveVolumeInStore (value: number) { |
55 | return setLocalStorage('volume', value.toString()) | 62 | return setLocalStorage('volume', value.toString()) |
56 | } | 63 | } |
@@ -59,6 +66,10 @@ function saveMuteInStore (value: boolean) { | |||
59 | return setLocalStorage('mute', value.toString()) | 66 | return setLocalStorage('mute', value.toString()) |
60 | } | 67 | } |
61 | 68 | ||
69 | function saveTheaterInStore (enabled: boolean) { | ||
70 | return setLocalStorage('theater-enabled', enabled.toString()) | ||
71 | } | ||
72 | |||
62 | function saveAverageBandwidth (value: number) { | 73 | function saveAverageBandwidth (value: number) { |
63 | return setLocalStorage('average-bandwidth', value.toString()) | 74 | return setLocalStorage('average-bandwidth', value.toString()) |
64 | } | 75 | } |
@@ -133,6 +144,8 @@ export { | |||
133 | videoFileMaxByResolution, | 144 | videoFileMaxByResolution, |
134 | videoFileMinByResolution, | 145 | videoFileMinByResolution, |
135 | copyToClipboard, | 146 | copyToClipboard, |
147 | getStoredTheater, | ||
148 | saveTheaterInStore, | ||
136 | isMobile, | 149 | isMobile, |
137 | bytes | 150 | bytes |
138 | } | 151 | } |