Add next video button to the player
authorRigel Kent <sendmemail@rigelk.eu>
Thu, 19 Dec 2019 20:34:45 +0000 (21:34 +0100)
committerRigel Kent <sendmemail@rigelk.eu>
Thu, 19 Dec 2019 20:34:45 +0000 (21:34 +0100)
client/src/app/videos/+video-watch/video-watch.component.ts
client/src/assets/player/images/next.svg [new file with mode: 0644]
client/src/assets/player/peertube-player-manager.ts
client/src/assets/player/videojs-components/next-video-button.ts [new file with mode: 0644]
client/src/sass/player/peertube-skin.scss

index 134af751d4e652493dc0fc619f6bfd7b9f2e8e6a..bad0144bf8c7f91444740083ba1de941fc107aa6 100644 (file)
@@ -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 (file)
index 0000000..af42dd2
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 36 36" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <path fill="white" d="M 12,24 20.5,18 12,12 V 24 z M 22,12 v 12 h 2 V 12 h -2 z"></path>
+</svg>
\ No newline at end of file
index 276f9ec5915a1a878b5a6d9cee4f475eea3cc6d8..d9e02cd7da442f225a4c13a5a5cefda59e738c3b 100644 (file)
@@ -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 (file)
index 0000000..bf5c1ab
--- /dev/null
@@ -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)
index 8230681f6bee00473c561f7e3ad9b825029197fe..e808538611fab7e5d1a1616c53b089c0cf6d8fdc 100644 (file)
@@ -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;
@@ -279,6 +282,33 @@ body {
         margin-right: 15px;
       }
 
+      .icon {
+        &.icon-download {
+          background-image: url('#{$assets-path}/player/images/arrow-down.svg');
+        }
+
+        &.icon-upload {
+          background-image: url('#{$assets-path}/player/images/arrow-up.svg');
+        }
+      }
+    }
+
+    .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;
@@ -286,17 +316,8 @@ body {
         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');
-        }
-
-        &.icon-upload {
-          background-image: url('#{$assets-path}/player/images/arrow-up.svg');
-        }
       }
     }