From 1dc240a9488c66ad38205d08fcfdb32d35efceaa Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Thu, 19 Dec 2019 21:34:45 +0100 Subject: [PATCH] Add next video button to the player --- .../+video-watch/video-watch.component.ts | 1 + client/src/assets/player/images/next.svg | 4 ++ .../assets/player/peertube-player-manager.ts | 23 ++++++++-- .../videojs-components/next-video-button.ts | 36 ++++++++++++++++ client/src/sass/player/peertube-skin.scss | 43 ++++++++++++++----- 5 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 client/src/assets/player/images/next.svg create mode 100644 client/src/assets/player/videojs-components/next-video-button.ts diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index 134af751d..bad0144bf 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -642,6 +642,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { const options: PeertubePlayerManagerOptions = { common: { autoplay: this.isAutoplay(), + nextVideo: () => this.zone.run(() => this.autoplayNext()), playerElement: this.playerElement, onPlayerElementChange: (element: HTMLVideoElement) => this.playerElement = element, diff --git a/client/src/assets/player/images/next.svg b/client/src/assets/player/images/next.svg new file mode 100644 index 000000000..af42dd270 --- /dev/null +++ b/client/src/assets/player/images/next.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/client/src/assets/player/peertube-player-manager.ts b/client/src/assets/player/peertube-player-manager.ts index 276f9ec59..d9e02cd7d 100644 --- a/client/src/assets/player/peertube-player-manager.ts +++ b/client/src/assets/player/peertube-player-manager.ts @@ -8,6 +8,7 @@ import 'videojs-contrib-quality-levels' import './upnext/upnext-plugin' import './bezels/bezels-plugin' import './peertube-plugin' +import './videojs-components/next-video-button' import './videojs-components/peertube-link-button' import './videojs-components/resolution-menu-button' import './videojs-components/settings-menu-button' @@ -62,6 +63,7 @@ export interface CommonOptions extends CustomizationOptions { onPlayerElementChange: (element: HTMLVideoElement) => void autoplay: boolean + nextVideo?: Function videoDuration: number enableHotkeys: boolean inactivityTimeout: number @@ -233,7 +235,8 @@ export class PeertubePlayerManager { children: this.getControlBarChildren(mode, { captions: commonOptions.captions, peertubeLink: commonOptions.peertubeLink, - theaterButton: commonOptions.theaterButton + theaterButton: commonOptions.theaterButton, + nextVideo: commonOptions.nextVideo }) } } @@ -329,7 +332,8 @@ export class PeertubePlayerManager { private static getControlBarChildren (mode: PlayerMode, options: { peertubeLink: boolean theaterButton: boolean, - captions: boolean + captions: boolean, + nextVideo?: Function }) { const settingEntries = [] const loadProgressBar = mode === 'webtorrent' ? 'peerTubeLoadProgressBar' : 'loadProgressBar' @@ -340,7 +344,18 @@ export class PeertubePlayerManager { settingEntries.push('resolutionMenuButton') const children = { - 'playToggle': {}, + 'playToggle': {} + } + + if (options.nextVideo) { + Object.assign(children, { + 'nextVideoButton': { + handler: options.nextVideo + } + }) + } + + Object.assign(children, { 'currentTimeDisplay': {}, 'timeDivider': {}, 'durationDisplay': {}, @@ -370,7 +385,7 @@ export class PeertubePlayerManager { }, entries: settingEntries } - } + }) if (options.peertubeLink === true) { Object.assign(children, { diff --git a/client/src/assets/player/videojs-components/next-video-button.ts b/client/src/assets/player/videojs-components/next-video-button.ts new file mode 100644 index 000000000..bf5c1aba4 --- /dev/null +++ b/client/src/assets/player/videojs-components/next-video-button.ts @@ -0,0 +1,36 @@ +import { VideoJSComponentInterface, videojsUntyped } from '../peertube-videojs-typings' +// FIXME: something weird with our path definition in tsconfig and typings +// @ts-ignore +import { Player } from 'video.js' + +const Button: VideoJSComponentInterface = videojsUntyped.getComponent('Button') + +class NextVideoButton extends Button { + + constructor (player: Player, options: any) { + super(player, options) + } + + createEl () { + const button = videojsUntyped.dom.createEl('button', { + className: 'vjs-next-video' + }) + const nextIcon = videojsUntyped.dom.createEl('span', { + className: 'icon icon-next' + }) + button.appendChild(nextIcon) + + button.title = this.player_.localize('Next video') + + return button + } + + handleClick () { + this.options_.handler() + } + +} + +NextVideoButton.prototype.controlText_ = 'Next video' + +NextVideoButton.registerComponent('NextVideoButton', NextVideoButton) diff --git a/client/src/sass/player/peertube-skin.scss b/client/src/sass/player/peertube-skin.scss index 8230681f6..e80853861 100644 --- a/client/src/sass/player/peertube-skin.scss +++ b/client/src/sass/player/peertube-skin.scss @@ -223,7 +223,8 @@ body { cursor: pointer; font-size: $font-size; - margin-right: 5px; + margin-left: 1em; + width: 3em; } .vjs-time-control { @@ -233,6 +234,7 @@ body { font-size: $font-size; display: inline-block; padding: 0; + margin-left: .5em; .vjs-current-time-display { line-height: calc(#{$control-bar-height} + 1px); @@ -262,6 +264,7 @@ body { width: 100%; line-height: $control-bar-height; text-align: right; + margin-right: 6px; .vjs-peertube-displayed { display: block; @@ -280,16 +283,6 @@ body { } .icon { - display: inline-block; - width: 15px; - height: 15px; - background-size: contain; - vertical-align: middle; - background-repeat: no-repeat; - margin-right: 6px; - position: relative; - top: -1px; - &.icon-download { background-image: url('#{$assets-path}/player/images/arrow-down.svg'); } @@ -300,6 +293,34 @@ body { } } + .vjs-next-video { + line-height: $control-bar-height; + text-align: right; + + .icon { + &.icon-next { + mask-image: url('#{$assets-path}/player/images/next.svg'); + background-color: white; + mask-size: cover; + transform: scale(2.2); + } + } + } + + .vjs-peertube, + .vjs-next-video { + .icon { + display: inline-block; + width: 15px; + height: 15px; + background-size: contain; + vertical-align: middle; + background-repeat: no-repeat; + position: relative; + top: -1px; + } + } + .vjs-playback-rate { font-size: 10px; width: 37px !important;