]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/assets/player/manager-options/manager-options-builder.ts
Reorganize player manager options builder
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / manager-options / manager-options-builder.ts
1 import videojs from 'video.js'
2 import { buildVideoLink, decorateVideoLink } from '@shared/core-utils'
3 import { isDefaultLocale } from '@shared/core-utils/i18n'
4 import { copyToClipboard } from '../../../root-helpers/utils'
5 import { VideoJSPluginOptions } from '../peertube-videojs-typings'
6 import { buildVideoOrPlaylistEmbed, isIOS, isSafari } from '../utils'
7 import { ControlBarOptionsBuilder } from './control-bar-options-builder'
8 import { HLSOptionsBuilder } from './hls-options-builder'
9 import { CommonOptions, PeertubePlayerManagerOptions, PlayerMode } from './manager-options.model'
10 import { WebTorrentOptionsBuilder } from './webtorrent-options-builder'
11
12 export class ManagerOptionsBuilder {
13
14 constructor (
15 private mode: PlayerMode,
16 private options: PeertubePlayerManagerOptions,
17 private p2pMediaLoaderModule?: any
18 ) {
19
20 }
21
22 getVideojsOptions (alreadyPlayed: boolean): videojs.PlayerOptions {
23 const commonOptions = this.options.common
24
25 let autoplay = this.getAutoPlayValue(commonOptions.autoplay, alreadyPlayed)
26 const html5 = {
27 preloadTextTracks: false
28 }
29
30 const plugins: VideoJSPluginOptions = {
31 peertube: {
32 mode: this.mode,
33 autoplay, // Use peertube plugin autoplay because we could get the file by webtorrent
34 videoViewUrl: commonOptions.videoViewUrl,
35 videoDuration: commonOptions.videoDuration,
36 userWatching: commonOptions.userWatching,
37 subtitle: commonOptions.subtitle,
38 videoCaptions: commonOptions.videoCaptions,
39 stopTime: commonOptions.stopTime,
40 isLive: commonOptions.isLive,
41 videoUUID: commonOptions.videoUUID
42 }
43 }
44
45 if (commonOptions.playlist) {
46 plugins.playlist = commonOptions.playlist
47 }
48
49 if (this.mode === 'p2p-media-loader') {
50 const hlsOptionsBuilder = new HLSOptionsBuilder(this.options, this.p2pMediaLoaderModule)
51
52 Object.assign(plugins, hlsOptionsBuilder.getPluginOptions())
53 } else if (this.mode === 'webtorrent') {
54 const webtorrentOptionsBuilder = new WebTorrentOptionsBuilder(this.options, this.getAutoPlayValue(autoplay, alreadyPlayed))
55
56 Object.assign(plugins, webtorrentOptionsBuilder.getPluginOptions())
57
58 // WebTorrent plugin handles autoplay, because we do some hackish stuff in there
59 autoplay = false
60 }
61
62 const controlBarOptionsBuilder = new ControlBarOptionsBuilder(this.options, this.mode)
63
64 const videojsOptions = {
65 html5,
66
67 // We don't use text track settings for now
68 textTrackSettings: false as any, // FIXME: typings
69 controls: commonOptions.controls !== undefined ? commonOptions.controls : true,
70 loop: commonOptions.loop !== undefined ? commonOptions.loop : false,
71
72 muted: commonOptions.muted !== undefined
73 ? commonOptions.muted
74 : undefined, // Undefined so the player knows it has to check the local storage
75
76 autoplay: this.getAutoPlayValue(autoplay, alreadyPlayed),
77
78 poster: commonOptions.poster,
79 inactivityTimeout: commonOptions.inactivityTimeout,
80 playbackRates: [ 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2 ],
81
82 plugins,
83
84 controlBar: {
85 children: controlBarOptionsBuilder.getChildrenOptions() as any // FIXME: typings
86 }
87 }
88
89 if (commonOptions.language && !isDefaultLocale(commonOptions.language)) {
90 Object.assign(videojsOptions, { language: commonOptions.language })
91 }
92
93 return videojsOptions
94 }
95
96 private getAutoPlayValue (autoplay: any, alreadyPlayed: boolean) {
97 if (autoplay !== true) return autoplay
98
99 // On first play, disable autoplay to avoid issues
100 // But if the player already played videos, we can safely autoplay next ones
101 if (isIOS() || isSafari()) {
102 return alreadyPlayed ? 'play' : false
103 }
104
105 return 'play'
106 }
107
108 getContextMenuOptions (player: videojs.Player, commonOptions: CommonOptions) {
109 const content = () => {
110 const isLoopEnabled = player.options_['loop']
111
112 const items = [
113 {
114 icon: 'repeat',
115 label: player.localize('Play in loop') + (isLoopEnabled ? '<span class="vjs-icon-tick-white"></span>' : ''),
116 listener: function () {
117 player.options_['loop'] = !isLoopEnabled
118 }
119 },
120 {
121 label: player.localize('Copy the video URL'),
122 listener: function () {
123 copyToClipboard(buildVideoLink({ shortUUID: commonOptions.videoShortUUID }))
124 }
125 },
126 {
127 label: player.localize('Copy the video URL at the current time'),
128 listener: function (this: videojs.Player) {
129 const url = buildVideoLink({ shortUUID: commonOptions.videoShortUUID })
130
131 copyToClipboard(decorateVideoLink({ url, startTime: this.currentTime() }))
132 }
133 },
134 {
135 icon: 'code',
136 label: player.localize('Copy embed code'),
137 listener: () => {
138 copyToClipboard(buildVideoOrPlaylistEmbed(commonOptions.embedUrl, commonOptions.embedTitle))
139 }
140 }
141 ]
142
143 if (this.mode === 'webtorrent') {
144 items.push({
145 label: player.localize('Copy magnet URI'),
146 listener: function (this: videojs.Player) {
147 copyToClipboard(this.webtorrent().getCurrentVideoFile().magnetUri)
148 }
149 })
150 }
151
152 items.push({
153 icon: 'info',
154 label: player.localize('Stats for nerds'),
155 listener: () => {
156 player.stats().show()
157 }
158 })
159
160 return items.map(i => ({
161 ...i,
162 label: `<span class="vjs-icon-${i.icon || 'link-2'}"></span>` + i.label
163 }))
164 }
165
166 return { content }
167 }
168 }