diff options
Diffstat (limited to 'client/src')
5 files changed, 91 insertions, 14 deletions
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 { | |||
642 | const options: PeertubePlayerManagerOptions = { | 642 | const options: PeertubePlayerManagerOptions = { |
643 | common: { | 643 | common: { |
644 | autoplay: this.isAutoplay(), | 644 | autoplay: this.isAutoplay(), |
645 | nextVideo: () => this.zone.run(() => this.autoplayNext()), | ||
645 | 646 | ||
646 | playerElement: this.playerElement, | 647 | playerElement: this.playerElement, |
647 | onPlayerElementChange: (element: HTMLVideoElement) => this.playerElement = element, | 648 | 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 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <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"> | ||
3 | <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> | ||
4 | </svg> \ 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' | |||
8 | import './upnext/upnext-plugin' | 8 | import './upnext/upnext-plugin' |
9 | import './bezels/bezels-plugin' | 9 | import './bezels/bezels-plugin' |
10 | import './peertube-plugin' | 10 | import './peertube-plugin' |
11 | import './videojs-components/next-video-button' | ||
11 | import './videojs-components/peertube-link-button' | 12 | import './videojs-components/peertube-link-button' |
12 | import './videojs-components/resolution-menu-button' | 13 | import './videojs-components/resolution-menu-button' |
13 | import './videojs-components/settings-menu-button' | 14 | import './videojs-components/settings-menu-button' |
@@ -62,6 +63,7 @@ export interface CommonOptions extends CustomizationOptions { | |||
62 | onPlayerElementChange: (element: HTMLVideoElement) => void | 63 | onPlayerElementChange: (element: HTMLVideoElement) => void |
63 | 64 | ||
64 | autoplay: boolean | 65 | autoplay: boolean |
66 | nextVideo?: Function | ||
65 | videoDuration: number | 67 | videoDuration: number |
66 | enableHotkeys: boolean | 68 | enableHotkeys: boolean |
67 | inactivityTimeout: number | 69 | inactivityTimeout: number |
@@ -233,7 +235,8 @@ export class PeertubePlayerManager { | |||
233 | children: this.getControlBarChildren(mode, { | 235 | children: this.getControlBarChildren(mode, { |
234 | captions: commonOptions.captions, | 236 | captions: commonOptions.captions, |
235 | peertubeLink: commonOptions.peertubeLink, | 237 | peertubeLink: commonOptions.peertubeLink, |
236 | theaterButton: commonOptions.theaterButton | 238 | theaterButton: commonOptions.theaterButton, |
239 | nextVideo: commonOptions.nextVideo | ||
237 | }) | 240 | }) |
238 | } | 241 | } |
239 | } | 242 | } |
@@ -329,7 +332,8 @@ export class PeertubePlayerManager { | |||
329 | private static getControlBarChildren (mode: PlayerMode, options: { | 332 | private static getControlBarChildren (mode: PlayerMode, options: { |
330 | peertubeLink: boolean | 333 | peertubeLink: boolean |
331 | theaterButton: boolean, | 334 | theaterButton: boolean, |
332 | captions: boolean | 335 | captions: boolean, |
336 | nextVideo?: Function | ||
333 | }) { | 337 | }) { |
334 | const settingEntries = [] | 338 | const settingEntries = [] |
335 | const loadProgressBar = mode === 'webtorrent' ? 'peerTubeLoadProgressBar' : 'loadProgressBar' | 339 | const loadProgressBar = mode === 'webtorrent' ? 'peerTubeLoadProgressBar' : 'loadProgressBar' |
@@ -340,7 +344,18 @@ export class PeertubePlayerManager { | |||
340 | settingEntries.push('resolutionMenuButton') | 344 | settingEntries.push('resolutionMenuButton') |
341 | 345 | ||
342 | const children = { | 346 | const children = { |
343 | 'playToggle': {}, | 347 | 'playToggle': {} |
348 | } | ||
349 | |||
350 | if (options.nextVideo) { | ||
351 | Object.assign(children, { | ||
352 | 'nextVideoButton': { | ||
353 | handler: options.nextVideo | ||
354 | } | ||
355 | }) | ||
356 | } | ||
357 | |||
358 | Object.assign(children, { | ||
344 | 'currentTimeDisplay': {}, | 359 | 'currentTimeDisplay': {}, |
345 | 'timeDivider': {}, | 360 | 'timeDivider': {}, |
346 | 'durationDisplay': {}, | 361 | 'durationDisplay': {}, |
@@ -370,7 +385,7 @@ export class PeertubePlayerManager { | |||
370 | }, | 385 | }, |
371 | entries: settingEntries | 386 | entries: settingEntries |
372 | } | 387 | } |
373 | } | 388 | }) |
374 | 389 | ||
375 | if (options.peertubeLink === true) { | 390 | if (options.peertubeLink === true) { |
376 | Object.assign(children, { | 391 | 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 @@ | |||
1 | import { VideoJSComponentInterface, videojsUntyped } from '../peertube-videojs-typings' | ||
2 | // FIXME: something weird with our path definition in tsconfig and typings | ||
3 | // @ts-ignore | ||
4 | import { Player } from 'video.js' | ||
5 | |||
6 | const Button: VideoJSComponentInterface = videojsUntyped.getComponent('Button') | ||
7 | |||
8 | class NextVideoButton extends Button { | ||
9 | |||
10 | constructor (player: Player, options: any) { | ||
11 | super(player, options) | ||
12 | } | ||
13 | |||
14 | createEl () { | ||
15 | const button = videojsUntyped.dom.createEl('button', { | ||
16 | className: 'vjs-next-video' | ||
17 | }) | ||
18 | const nextIcon = videojsUntyped.dom.createEl('span', { | ||
19 | className: 'icon icon-next' | ||
20 | }) | ||
21 | button.appendChild(nextIcon) | ||
22 | |||
23 | button.title = this.player_.localize('Next video') | ||
24 | |||
25 | return button | ||
26 | } | ||
27 | |||
28 | handleClick () { | ||
29 | this.options_.handler() | ||
30 | } | ||
31 | |||
32 | } | ||
33 | |||
34 | NextVideoButton.prototype.controlText_ = 'Next video' | ||
35 | |||
36 | 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 { | |||
223 | 223 | ||
224 | cursor: pointer; | 224 | cursor: pointer; |
225 | font-size: $font-size; | 225 | font-size: $font-size; |
226 | margin-right: 5px; | 226 | margin-left: 1em; |
227 | width: 3em; | ||
227 | } | 228 | } |
228 | 229 | ||
229 | .vjs-time-control { | 230 | .vjs-time-control { |
@@ -233,6 +234,7 @@ body { | |||
233 | font-size: $font-size; | 234 | font-size: $font-size; |
234 | display: inline-block; | 235 | display: inline-block; |
235 | padding: 0; | 236 | padding: 0; |
237 | margin-left: .5em; | ||
236 | 238 | ||
237 | .vjs-current-time-display { | 239 | .vjs-current-time-display { |
238 | line-height: calc(#{$control-bar-height} + 1px); | 240 | line-height: calc(#{$control-bar-height} + 1px); |
@@ -262,6 +264,7 @@ body { | |||
262 | width: 100%; | 264 | width: 100%; |
263 | line-height: $control-bar-height; | 265 | line-height: $control-bar-height; |
264 | text-align: right; | 266 | text-align: right; |
267 | margin-right: 6px; | ||
265 | 268 | ||
266 | .vjs-peertube-displayed { | 269 | .vjs-peertube-displayed { |
267 | display: block; | 270 | display: block; |
@@ -280,23 +283,41 @@ body { | |||
280 | } | 283 | } |
281 | 284 | ||
282 | .icon { | 285 | .icon { |
286 | &.icon-download { | ||
287 | background-image: url('#{$assets-path}/player/images/arrow-down.svg'); | ||
288 | } | ||
289 | |||
290 | &.icon-upload { | ||
291 | background-image: url('#{$assets-path}/player/images/arrow-up.svg'); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | .vjs-next-video { | ||
297 | line-height: $control-bar-height; | ||
298 | text-align: right; | ||
299 | |||
300 | .icon { | ||
301 | &.icon-next { | ||
302 | mask-image: url('#{$assets-path}/player/images/next.svg'); | ||
303 | background-color: white; | ||
304 | mask-size: cover; | ||
305 | transform: scale(2.2); | ||
306 | } | ||
307 | } | ||
308 | } | ||
309 | |||
310 | .vjs-peertube, | ||
311 | .vjs-next-video { | ||
312 | .icon { | ||
283 | display: inline-block; | 313 | display: inline-block; |
284 | width: 15px; | 314 | width: 15px; |
285 | height: 15px; | 315 | height: 15px; |
286 | background-size: contain; | 316 | background-size: contain; |
287 | vertical-align: middle; | 317 | vertical-align: middle; |
288 | background-repeat: no-repeat; | 318 | background-repeat: no-repeat; |
289 | margin-right: 6px; | ||
290 | position: relative; | 319 | position: relative; |
291 | top: -1px; | 320 | top: -1px; |
292 | |||
293 | &.icon-download { | ||
294 | background-image: url('#{$assets-path}/player/images/arrow-down.svg'); | ||
295 | } | ||
296 | |||
297 | &.icon-upload { | ||
298 | background-image: url('#{$assets-path}/player/images/arrow-up.svg'); | ||
299 | } | ||
300 | } | 321 | } |
301 | } | 322 | } |
302 | 323 | ||