Ability to programmatically control embeds (#776)
[oweals/peertube.git] / client / src / assets / player / peertube-player.ts
1 import { VideoFile } from '../../../../shared/models/videos'
2
3 import 'videojs-hotkeys'
4 import 'videojs-dock'
5 import 'videojs-contextmenu'
6 import 'videojs-contextmenu-ui'
7 import './peertube-link-button'
8 import './resolution-menu-button'
9 import './settings-menu-button'
10 import './webtorrent-info-button'
11 import './peertube-videojs-plugin'
12 import './peertube-load-progress-bar'
13 import './theater-button'
14 import { videojsUntyped } from './peertube-videojs-typings'
15 import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils'
16 import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n'
17
18 // Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
19 videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed'
20
21 function getVideojsOptions (options: {
22   autoplay: boolean,
23   playerElement: HTMLVideoElement,
24   videoViewUrl: string,
25   videoDuration: number,
26   videoFiles: VideoFile[],
27   enableHotkeys: boolean,
28   inactivityTimeout: number,
29   peertubeLink: boolean,
30   poster: string,
31   startTime: number
32   theaterMode: boolean,
33   controls?: boolean,
34   muted?: boolean,
35   loop?: boolean
36 }) {
37   const videojsOptions = {
38     controls: options.controls !== undefined ? options.controls : true,
39     muted: options.controls !== undefined ? options.muted : false,
40     loop: options.loop !== undefined ? options.loop : false,
41     poster: options.poster,
42     autoplay: false,
43     inactivityTimeout: options.inactivityTimeout,
44     playbackRates: [ 0.5, 1, 1.5, 2 ],
45     plugins: {
46       peertube: {
47         autoplay: options.autoplay, // Use peertube plugin autoplay because we get the file by webtorrent
48         videoFiles: options.videoFiles,
49         playerElement: options.playerElement,
50         videoViewUrl: options.videoViewUrl,
51         videoDuration: options.videoDuration,
52         startTime: options.startTime
53       }
54     },
55     controlBar: {
56       children: getControlBarChildren(options)
57     }
58   }
59
60   if (options.enableHotkeys === true) {
61     Object.assign(videojsOptions.plugins, {
62       hotkeys: {
63         enableVolumeScroll: false,
64         enableModifiersForNumbers: false
65       }
66     })
67   }
68
69   return videojsOptions
70 }
71
72 function getControlBarChildren (options: {
73   peertubeLink: boolean
74   theaterMode: boolean
75 }) {
76   const children = {
77     'playToggle': {},
78     'currentTimeDisplay': {},
79     'timeDivider': {},
80     'durationDisplay': {},
81     'liveDisplay': {},
82
83     'flexibleWidthSpacer': {},
84     'progressControl': {
85       children: {
86         'seekBar': {
87           children: {
88             'peerTubeLoadProgressBar': {},
89             'mouseTimeDisplay': {},
90             'playProgressBar': {}
91           }
92         }
93       }
94     },
95
96     'webTorrentButton': {},
97
98     'muteToggle': {},
99     'volumeControl': {},
100
101     'settingsButton': {
102       setup: {
103         maxHeightOffset: 40
104       },
105       entries: [
106         'resolutionMenuButton',
107         'playbackRateMenuButton'
108       ]
109     }
110   }
111
112   if (options.peertubeLink === true) {
113     Object.assign(children, {
114       'peerTubeLinkButton': {}
115     })
116   }
117
118   if (options.theaterMode === true) {
119     Object.assign(children, {
120       'theaterButton': {}
121     })
122   }
123
124   Object.assign(children, {
125     'fullscreenToggle': {}
126   })
127
128   return children
129 }
130
131 function addContextMenu (player: any, videoEmbedUrl: string) {
132   player.contextmenuUI({
133     content: [
134       {
135         label: player.localize('Copy the video URL'),
136         listener: function () {
137           copyToClipboard(buildVideoLink())
138         }
139       },
140       {
141         label: player.localize('Copy the video URL at the current time'),
142         listener: function () {
143           const player = this
144           copyToClipboard(buildVideoLink(player.currentTime()))
145         }
146       },
147       {
148         label: player.localize('Copy embed code'),
149         listener: () => {
150           copyToClipboard(buildVideoEmbed(videoEmbedUrl))
151         }
152       },
153       {
154         label: player.localize('Copy magnet URI'),
155         listener: function () {
156           const player = this
157           copyToClipboard(player.peertube().getCurrentVideoFile().magnetUri)
158         }
159       }
160     ]
161   })
162 }
163
164 function loadLocale (serverUrl: string, videojs: any, locale: string) {
165   const completeLocale = getCompleteLocale(locale)
166
167   if (!is18nLocale(completeLocale) || isDefaultLocale(completeLocale)) return Promise.resolve(undefined)
168
169   return fetch(serverUrl + '/client/locales/' + completeLocale + '/player.json')
170     .then(res => res.json())
171     .then(json => videojs.addLanguage(getShortLocale(completeLocale), json))
172 }
173
174 export {
175   loadLocale,
176   getVideojsOptions,
177   addContextMenu
178 }