X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=client%2Fsrc%2Fassets%2Fplayer%2Fpeertube-player.ts;h=2c16c87eca0a37452b21291918341dcc5747c40f;hb=5363a766d95ed8654ad3e1b94538f085c2a3a101;hp=2e77a973fa7f5a2122c84309a9d0e9447e1f71d1;hpb=cd4d7a2ca868209fb1e2dbd790c1e5d6cca77e86;p=github%2FChocobozzz%2FPeerTube.git diff --git a/client/src/assets/player/peertube-player.ts b/client/src/assets/player/peertube-player.ts index 2e77a973f..2c16c87ec 100644 --- a/client/src/assets/player/peertube-player.ts +++ b/client/src/assets/player/peertube-player.ts @@ -1,32 +1,25 @@ import { VideoFile } from '../../../../shared/models/videos' -import 'core-js/es6/symbol'; -import 'core-js/es6/object'; -import 'core-js/es6/function'; -import 'core-js/es6/parse-int'; -import 'core-js/es6/parse-float'; -import 'core-js/es6/number'; -import 'core-js/es6/math'; -import 'core-js/es6/string'; -import 'core-js/es6/date'; -import 'core-js/es6/array'; -import 'core-js/es6/regexp'; -import 'core-js/es6/map'; -import 'core-js/es6/weak-map'; -import 'core-js/es6/set'; -import 'core-js/es7/object'; - import 'videojs-hotkeys' import 'videojs-dock' +import 'videojs-contextmenu-ui' import './peertube-link-button' import './resolution-menu-button' import './settings-menu-button' import './webtorrent-info-button' import './peertube-videojs-plugin' -import { videojsUntyped } from './peertube-videojs-typings' +import './peertube-load-progress-bar' +import './theater-button' +import { VideoJSCaption, videojsUntyped } from './peertube-videojs-typings' +import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils' +import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n' // Change 'Playback Rate' to 'Speed' (smaller for our settings menu) videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed' +// Change Captions to Subtitles/CC +videojsUntyped.getComponent('CaptionsButton').prototype.controlText_ = 'Subtitles/CC' +// We just want to display 'Off' instead of 'captions off', keep a space so the variable == true (hacky I know) +videojsUntyped.getComponent('CaptionsButton').prototype.label_ = ' ' function getVideojsOptions (options: { autoplay: boolean, @@ -38,17 +31,28 @@ function getVideojsOptions (options: { inactivityTimeout: number, peertubeLink: boolean, poster: string, - startTime: number + startTime: number | string + theaterMode: boolean, + videoCaptions: VideoJSCaption[], + language?: string, + controls?: boolean, + muted?: boolean, + loop?: boolean }) { const videojsOptions = { - controls: true, + // We don't use text track settings for now + textTrackSettings: false, + controls: options.controls !== undefined ? options.controls : true, + muted: options.controls !== undefined ? options.muted : false, + loop: options.loop !== undefined ? options.loop : false, poster: options.poster, autoplay: false, inactivityTimeout: options.inactivityTimeout, - playbackRates: [ 0.5, 1, 1.5, 2 ], + playbackRates: [ 0.5, 0.75, 1, 1.25, 1.5, 2 ], plugins: { peertube: { autoplay: options.autoplay, // Use peertube plugin autoplay because we get the file by webtorrent + videoCaptions: options.videoCaptions, videoFiles: options.videoFiles, playerElement: options.playerElement, videoViewUrl: options.videoViewUrl, @@ -64,17 +68,49 @@ function getVideojsOptions (options: { if (options.enableHotkeys === true) { Object.assign(videojsOptions.plugins, { hotkeys: { - enableVolumeScroll: false + enableVolumeScroll: false, + enableModifiersForNumbers: false, + customKeys: { + increasePlaybackRateKey: { + key: function (event) { + return event.key === '>' + }, + handler: function (player) { + player.playbackRate((player.playbackRate() + 0.1).toFixed(2)) + } + }, + decreasePlaybackRateKey: { + key: function (event) { + return event.key === '<' + }, + handler: function (player) { + player.playbackRate((player.playbackRate() - 0.1).toFixed(2)) + } + } + } } }) } + if (options.language && !isDefaultLocale(options.language)) { + Object.assign(videojsOptions, { language: options.language }) + } + return videojsOptions } function getControlBarChildren (options: { peertubeLink: boolean + theaterMode: boolean, + videoCaptions: VideoJSCaption[] }) { + const settingEntries = [] + + // Keep an order + settingEntries.push('playbackRateMenuButton') + if (options.videoCaptions.length !== 0) settingEntries.push('captionsButton') + settingEntries.push('resolutionMenuButton') + const children = { 'playToggle': {}, 'currentTimeDisplay': {}, @@ -83,7 +119,17 @@ function getControlBarChildren (options: { 'liveDisplay': {}, 'flexibleWidthSpacer': {}, - 'progressControl': {}, + 'progressControl': { + children: { + 'seekBar': { + children: { + 'peerTubeLoadProgressBar': {}, + 'mouseTimeDisplay': {}, + 'playProgressBar': {} + } + } + } + }, 'webTorrentButton': {}, @@ -94,10 +140,7 @@ function getControlBarChildren (options: { setup: { maxHeightOffset: 40 }, - entries: [ - 'resolutionMenuButton', - 'playbackRateMenuButton' - ] + entries: settingEntries } } @@ -107,6 +150,12 @@ function getControlBarChildren (options: { }) } + if (options.theaterMode === true) { + Object.assign(children, { + 'theaterButton': {} + }) + } + Object.assign(children, { 'fullscreenToggle': {} }) @@ -114,4 +163,88 @@ function getControlBarChildren (options: { return children } -export { getVideojsOptions } +function addContextMenu (player: any, videoEmbedUrl: string) { + player.contextmenuUI({ + content: [ + { + label: player.localize('Copy the video URL'), + listener: function () { + copyToClipboard(buildVideoLink()) + } + }, + { + label: player.localize('Copy the video URL at the current time'), + listener: function () { + const player = this + copyToClipboard(buildVideoLink(player.currentTime())) + } + }, + { + label: player.localize('Copy embed code'), + listener: () => { + copyToClipboard(buildVideoEmbed(videoEmbedUrl)) + } + }, + { + label: player.localize('Copy magnet URI'), + listener: function () { + const player = this + copyToClipboard(player.peertube().getCurrentVideoFile().magnetUri) + } + } + ] + }) +} + +function loadLocaleInVideoJS (serverUrl: string, videojs: any, locale: string) { + const path = getLocalePath(serverUrl, locale) + // It is the default locale, nothing to translate + if (!path) return Promise.resolve(undefined) + + let p: Promise + + if (loadLocaleInVideoJS.cache[path]) { + p = Promise.resolve(loadLocaleInVideoJS.cache[path]) + } else { + p = fetch(path + '/player.json') + .then(res => res.json()) + .then(json => { + loadLocaleInVideoJS.cache[path] = json + return json + }) + } + + const completeLocale = getCompleteLocale(locale) + return p.then(json => videojs.addLanguage(getShortLocale(completeLocale), json)) +} +namespace loadLocaleInVideoJS { + export const cache: { [ path: string ]: any } = {} +} + +function getServerTranslations (serverUrl: string, locale: string) { + const path = getLocalePath(serverUrl, locale) + // It is the default locale, nothing to translate + if (!path) return Promise.resolve(undefined) + + return fetch(path + '/server.json') + .then(res => res.json()) +} + +// ############################################################################ + +export { + getServerTranslations, + loadLocaleInVideoJS, + getVideojsOptions, + addContextMenu +} + +// ############################################################################ + +function getLocalePath (serverUrl: string, locale: string) { + const completeLocale = getCompleteLocale(locale) + + if (!is18nLocale(completeLocale) || isDefaultLocale(completeLocale)) return undefined + + return serverUrl + '/client/locales/' + completeLocale +}