mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2024-09-11 13:37:10 +03:00
Handle basic playlist in embed
This commit is contained in:
parent
5abc96fca2
commit
4572c3d0d9
@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
|
||||
<g id="Artboard-4" transform="translate(-356.000000, -115.000000)" stroke="#fff" stroke-width="2">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
|
||||
<g transform="translate(-356.000000, -115.000000)" stroke="#fff" stroke-width="2">
|
||||
<g id="8" transform="translate(356.000000, 115.000000)">
|
||||
<path d="M21,6 L9,18" id="Path-14"></path>
|
||||
<path d="M9,13 L4,18" id="Path-14" transform="translate(6.500000, 15.500000) scale(-1, 1) translate(-6.500000, -15.500000) "></path>
|
||||
|
Before Width: | Height: | Size: 738 B After Width: | Height: | Size: 692 B |
@ -18,14 +18,21 @@ import './videojs-components/settings-menu-item'
|
||||
import './videojs-components/settings-panel'
|
||||
import './videojs-components/settings-panel-child'
|
||||
import './videojs-components/theater-button'
|
||||
import './playlist/playlist-plugin'
|
||||
import videojs from 'video.js'
|
||||
import { VideoFile } from '@shared/models'
|
||||
import { isDefaultLocale } from '@shared/core-utils/i18n'
|
||||
import { VideoFile } from '@shared/models'
|
||||
import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager'
|
||||
import { segmentUrlBuilderFactory } from './p2p-media-loader/segment-url-builder'
|
||||
import { segmentValidatorFactory } from './p2p-media-loader/segment-validator'
|
||||
import { getStoredP2PEnabled } from './peertube-player-local-storage'
|
||||
import { P2PMediaLoaderPluginOptions, UserWatching, VideoJSCaption, VideoJSPluginOptions } from './peertube-videojs-typings'
|
||||
import {
|
||||
P2PMediaLoaderPluginOptions,
|
||||
PlaylistPluginOptions,
|
||||
UserWatching,
|
||||
VideoJSCaption,
|
||||
VideoJSPluginOptions
|
||||
} from './peertube-videojs-typings'
|
||||
import { TranslationsManager } from './translations-manager'
|
||||
import { buildVideoEmbed, buildVideoLink, copyToClipboard, getRtcConfig, isIOS, isSafari } from './utils'
|
||||
|
||||
@ -71,6 +78,9 @@ export interface CommonOptions extends CustomizationOptions {
|
||||
|
||||
autoplay: boolean
|
||||
nextVideo?: Function
|
||||
|
||||
playlist?: PlaylistPluginOptions
|
||||
|
||||
videoDuration: number
|
||||
enableHotkeys: boolean
|
||||
inactivityTimeout: number
|
||||
@ -203,6 +213,10 @@ export class PeertubePlayerManager {
|
||||
}
|
||||
}
|
||||
|
||||
if (commonOptions.playlist) {
|
||||
plugins.playlist = commonOptions.playlist
|
||||
}
|
||||
|
||||
if (commonOptions.enableHotkeys === true) {
|
||||
PeertubePlayerManager.addHotkeysOptions(plugins)
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Config, Level } from 'hls.js'
|
||||
import videojs from 'video.js'
|
||||
import { VideoFile } from '@shared/models'
|
||||
import { VideoFile, VideoPlaylist, VideoPlaylistElement } from '@shared/models'
|
||||
import { P2pMediaLoaderPlugin } from './p2p-media-loader/p2p-media-loader-plugin'
|
||||
import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager'
|
||||
import { PlayerMode } from './peertube-player-manager'
|
||||
import { PeerTubePlugin } from './peertube-plugin'
|
||||
import { PlaylistPlugin } from './playlist/playlist-plugin'
|
||||
import { EndCardOptions } from './upnext/end-card'
|
||||
import { WebTorrentPlugin } from './webtorrent/webtorrent-plugin'
|
||||
|
||||
@ -45,6 +46,8 @@ declare module 'video.js' {
|
||||
dock (options: { title: string, description: string }): void
|
||||
|
||||
upnext (options: Partial<EndCardOptions>): void
|
||||
|
||||
playlist (): PlaylistPlugin
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,6 +108,16 @@ type PeerTubePluginOptions = {
|
||||
stopTime: number | string
|
||||
}
|
||||
|
||||
type PlaylistPluginOptions = {
|
||||
elements: VideoPlaylistElement[]
|
||||
|
||||
playlist: VideoPlaylist
|
||||
|
||||
getCurrentPosition: () => number
|
||||
|
||||
onItemClicked: (element: VideoPlaylistElement) => void
|
||||
}
|
||||
|
||||
type WebtorrentPluginOptions = {
|
||||
playerElement: HTMLVideoElement
|
||||
|
||||
@ -125,6 +138,8 @@ type P2PMediaLoaderPluginOptions = {
|
||||
}
|
||||
|
||||
type VideoJSPluginOptions = {
|
||||
playlist?: PlaylistPluginOptions
|
||||
|
||||
peertube: PeerTubePluginOptions
|
||||
|
||||
webtorrent?: WebtorrentPluginOptions
|
||||
@ -170,10 +185,18 @@ type PlayerNetworkInfo = {
|
||||
}
|
||||
}
|
||||
|
||||
type PlaylistItemOptions = {
|
||||
element: VideoPlaylistElement
|
||||
|
||||
onClicked: Function
|
||||
}
|
||||
|
||||
export {
|
||||
PlayerNetworkInfo,
|
||||
PlaylistItemOptions,
|
||||
ResolutionUpdateData,
|
||||
AutoResolutionUpdateData,
|
||||
PlaylistPluginOptions,
|
||||
VideoJSCaption,
|
||||
UserWatching,
|
||||
PeerTubePluginOptions,
|
||||
|
61
client/src/assets/player/playlist/playlist-button.ts
Normal file
61
client/src/assets/player/playlist/playlist-button.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import videojs from 'video.js'
|
||||
import { PlaylistPluginOptions } from '../peertube-videojs-typings'
|
||||
import { PlaylistMenu } from './playlist-menu'
|
||||
|
||||
const ClickableComponent = videojs.getComponent('ClickableComponent')
|
||||
|
||||
class PlaylistButton extends ClickableComponent {
|
||||
private playlistInfoElement: HTMLElement
|
||||
private wrapper: HTMLElement
|
||||
|
||||
constructor (player: videojs.Player, options?: PlaylistPluginOptions & { playlistMenu: PlaylistMenu }) {
|
||||
super(player, options as any)
|
||||
}
|
||||
|
||||
createEl () {
|
||||
this.wrapper = super.createEl('div', {
|
||||
className: 'vjs-playlist-button',
|
||||
innerHTML: '',
|
||||
tabIndex: -1
|
||||
}) as HTMLElement
|
||||
|
||||
const icon = super.createEl('div', {
|
||||
className: 'vjs-playlist-icon',
|
||||
innerHTML: '',
|
||||
tabIndex: -1
|
||||
})
|
||||
|
||||
this.playlistInfoElement = super.createEl('div', {
|
||||
className: 'vjs-playlist-info',
|
||||
innerHTML: '',
|
||||
tabIndex: -1
|
||||
}) as HTMLElement
|
||||
|
||||
this.wrapper.appendChild(icon)
|
||||
this.wrapper.appendChild(this.playlistInfoElement)
|
||||
|
||||
this.update()
|
||||
|
||||
return this.wrapper
|
||||
}
|
||||
|
||||
update () {
|
||||
const options = this.options_ as PlaylistPluginOptions
|
||||
|
||||
this.playlistInfoElement.innerHTML = options.getCurrentPosition() + '/' + options.playlist.videosLength
|
||||
this.wrapper.title = this.player().localize('Playlist: {1}', [ options.playlist.displayName ])
|
||||
}
|
||||
|
||||
handleClick () {
|
||||
const playlistMenu = this.getPlaylistMenu()
|
||||
playlistMenu.open()
|
||||
}
|
||||
|
||||
private getPlaylistMenu () {
|
||||
return (this.options_ as any).playlistMenu as PlaylistMenu
|
||||
}
|
||||
}
|
||||
|
||||
videojs.registerComponent('PlaylistButton', PlaylistButton)
|
||||
|
||||
export { PlaylistButton }
|
98
client/src/assets/player/playlist/playlist-menu-item.ts
Normal file
98
client/src/assets/player/playlist/playlist-menu-item.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import videojs from 'video.js'
|
||||
import { VideoPlaylistElement } from '@shared/models'
|
||||
import { PlaylistItemOptions } from '../peertube-videojs-typings'
|
||||
|
||||
const Component = videojs.getComponent('Component')
|
||||
|
||||
class PlaylistMenuItem extends Component {
|
||||
private element: VideoPlaylistElement
|
||||
|
||||
constructor (player: videojs.Player, options?: PlaylistItemOptions) {
|
||||
super(player, options as any)
|
||||
|
||||
this.emitTapEvents()
|
||||
|
||||
this.element = options.element
|
||||
|
||||
this.on([ 'click', 'tap' ], () => this.switchPlaylistItem())
|
||||
this.on('keydown', event => this.handleKeyDown(event))
|
||||
}
|
||||
|
||||
createEl () {
|
||||
const options = this.options_ as PlaylistItemOptions
|
||||
|
||||
const li = super.createEl('li', {
|
||||
className: 'vjs-playlist-menu-item',
|
||||
innerHTML: ''
|
||||
}) as HTMLElement
|
||||
|
||||
const positionBlock = super.createEl('div', {
|
||||
className: 'item-position-block'
|
||||
})
|
||||
|
||||
const position = super.createEl('div', {
|
||||
className: 'item-position',
|
||||
innerHTML: options.element.position
|
||||
})
|
||||
|
||||
const player = super.createEl('div', {
|
||||
className: 'item-player'
|
||||
})
|
||||
|
||||
positionBlock.appendChild(position)
|
||||
positionBlock.appendChild(player)
|
||||
|
||||
li.appendChild(positionBlock)
|
||||
|
||||
const thumbnail = super.createEl('img', {
|
||||
src: window.location.origin + options.element.video.thumbnailPath
|
||||
})
|
||||
|
||||
const infoBlock = super.createEl('div', {
|
||||
className: 'info-block'
|
||||
})
|
||||
|
||||
const title = super.createEl('div', {
|
||||
innerHTML: options.element.video.name,
|
||||
className: 'title'
|
||||
})
|
||||
|
||||
const channel = super.createEl('div', {
|
||||
innerHTML: options.element.video.channel.displayName,
|
||||
className: 'channel'
|
||||
})
|
||||
|
||||
infoBlock.appendChild(title)
|
||||
infoBlock.appendChild(channel)
|
||||
|
||||
li.append(thumbnail)
|
||||
li.append(infoBlock)
|
||||
|
||||
return li
|
||||
}
|
||||
|
||||
setSelected (selected: boolean) {
|
||||
if (selected) this.addClass('vjs-selected')
|
||||
else this.removeClass('vjs-selected')
|
||||
}
|
||||
|
||||
getElement () {
|
||||
return this.element
|
||||
}
|
||||
|
||||
private handleKeyDown (event: KeyboardEvent) {
|
||||
if (event.code === 'Space' || event.code === 'Enter') {
|
||||
this.switchPlaylistItem()
|
||||
}
|
||||
}
|
||||
|
||||
private switchPlaylistItem () {
|
||||
const options = this.options_ as PlaylistItemOptions
|
||||
|
||||
options.onClicked()
|
||||
}
|
||||
}
|
||||
|
||||
Component.registerComponent('PlaylistMenuItem', PlaylistMenuItem)
|
||||
|
||||
export { PlaylistMenuItem }
|
124
client/src/assets/player/playlist/playlist-menu.ts
Normal file
124
client/src/assets/player/playlist/playlist-menu.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import videojs from 'video.js'
|
||||
import { VideoPlaylistElement } from '@shared/models'
|
||||
import { PlaylistPluginOptions } from '../peertube-videojs-typings'
|
||||
import { PlaylistMenuItem } from './playlist-menu-item'
|
||||
|
||||
const Component = videojs.getComponent('Component')
|
||||
|
||||
class PlaylistMenu extends Component {
|
||||
private menuItems: PlaylistMenuItem[]
|
||||
|
||||
constructor (player: videojs.Player, options?: PlaylistPluginOptions) {
|
||||
super(player, options as any)
|
||||
|
||||
this.player().on('userinactive', () => {
|
||||
this.close()
|
||||
})
|
||||
|
||||
this.player().on('click', event => {
|
||||
let current = event.target as HTMLElement
|
||||
|
||||
do {
|
||||
if (
|
||||
current.classList.contains('vjs-playlist-menu') ||
|
||||
current.classList.contains('vjs-playlist-button')
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
current = current.parentElement
|
||||
} while (current)
|
||||
|
||||
this.close()
|
||||
})
|
||||
}
|
||||
|
||||
createEl () {
|
||||
this.menuItems = []
|
||||
|
||||
const options = this.getOptions()
|
||||
|
||||
const menu = super.createEl('div', {
|
||||
className: 'vjs-playlist-menu',
|
||||
innerHTML: '',
|
||||
tabIndex: -1
|
||||
})
|
||||
|
||||
const header = super.createEl('div', {
|
||||
className: 'header'
|
||||
})
|
||||
|
||||
const headerLeft = super.createEl('div')
|
||||
|
||||
const leftTitle = super.createEl('div', {
|
||||
innerHTML: options.playlist.displayName,
|
||||
className: 'title'
|
||||
})
|
||||
|
||||
const leftSubtitle = super.createEl('div', {
|
||||
innerHTML: this.player().localize('By {1}', [ options.playlist.videoChannel.displayName ]),
|
||||
className: 'channel'
|
||||
})
|
||||
|
||||
headerLeft.appendChild(leftTitle)
|
||||
headerLeft.appendChild(leftSubtitle)
|
||||
|
||||
const tick = super.createEl('div', {
|
||||
className: 'cross'
|
||||
})
|
||||
tick.addEventListener('click', () => this.close())
|
||||
|
||||
header.appendChild(headerLeft)
|
||||
header.appendChild(tick)
|
||||
|
||||
const list = super.createEl('ol')
|
||||
|
||||
for (const playlistElement of options.elements) {
|
||||
const item = new PlaylistMenuItem(this.player(), {
|
||||
element: playlistElement,
|
||||
onClicked: () => this.onItemClicked(playlistElement)
|
||||
})
|
||||
|
||||
list.appendChild(item.el())
|
||||
|
||||
this.menuItems.push(item)
|
||||
}
|
||||
|
||||
menu.appendChild(header)
|
||||
menu.appendChild(list)
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
update () {
|
||||
const options = this.getOptions()
|
||||
|
||||
this.updateSelected(options.getCurrentPosition())
|
||||
}
|
||||
|
||||
open () {
|
||||
this.player().addClass('playlist-menu-displayed')
|
||||
}
|
||||
|
||||
close () {
|
||||
this.player().removeClass('playlist-menu-displayed')
|
||||
}
|
||||
|
||||
updateSelected (newPosition: number) {
|
||||
for (const item of this.menuItems) {
|
||||
item.setSelected(item.getElement().position === newPosition)
|
||||
}
|
||||
}
|
||||
|
||||
private getOptions () {
|
||||
return this.options_ as PlaylistPluginOptions
|
||||
}
|
||||
|
||||
private onItemClicked (element: VideoPlaylistElement) {
|
||||
this.getOptions().onItemClicked(element)
|
||||
}
|
||||
}
|
||||
|
||||
Component.registerComponent('PlaylistMenu', PlaylistMenu)
|
||||
|
||||
export { PlaylistMenu }
|
35
client/src/assets/player/playlist/playlist-plugin.ts
Normal file
35
client/src/assets/player/playlist/playlist-plugin.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import videojs from 'video.js'
|
||||
import { PlaylistPluginOptions } from '../peertube-videojs-typings'
|
||||
import { PlaylistButton } from './playlist-button'
|
||||
import { PlaylistMenu } from './playlist-menu'
|
||||
|
||||
const Plugin = videojs.getPlugin('plugin')
|
||||
|
||||
class PlaylistPlugin extends Plugin {
|
||||
private playlistMenu: PlaylistMenu
|
||||
private playlistButton: PlaylistButton
|
||||
private options: PlaylistPluginOptions
|
||||
|
||||
constructor (player: videojs.Player, options?: PlaylistPluginOptions) {
|
||||
super(player, options)
|
||||
|
||||
this.options = options
|
||||
|
||||
this.player.ready(() => {
|
||||
player.addClass('vjs-playlist')
|
||||
})
|
||||
|
||||
this.playlistMenu = new PlaylistMenu(player, options)
|
||||
this.playlistButton = new PlaylistButton(player, Object.assign({}, options, { playlistMenu: this.playlistMenu }))
|
||||
|
||||
player.addChild(this.playlistMenu, options)
|
||||
player.addChild(this.playlistButton, options)
|
||||
}
|
||||
|
||||
updateSelected () {
|
||||
this.playlistMenu.updateSelected(this.options.getCurrentPosition())
|
||||
}
|
||||
}
|
||||
|
||||
videojs.registerPlugin('playlist', PlaylistPlugin)
|
||||
export { PlaylistPlugin }
|
@ -52,18 +52,7 @@ $play-overlay-width: 18px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%) scale(0.5);
|
||||
|
||||
border-top: ($play-overlay-height / 2) solid transparent;
|
||||
border-bottom: ($play-overlay-height / 2) solid transparent;
|
||||
|
||||
border-left: $play-overlay-width solid rgba(255, 255, 255, 0.95);
|
||||
@include play-icon($play-overlay-height, $play-overlay-width);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1019,3 +1019,18 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin play-icon ($width, $height) {
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%) scale(0.5);
|
||||
|
||||
border-top: ($height / 2) solid transparent;
|
||||
border-bottom: ($height / 2) solid transparent;
|
||||
|
||||
border-left: $width solid rgba(255, 255, 255, 0.95);
|
||||
}
|
||||
|
@ -4,4 +4,5 @@
|
||||
@import './settings-menu';
|
||||
@import './spinner';
|
||||
@import './upnext';
|
||||
@import './bezels.scss';
|
||||
@import './bezels.scss';
|
||||
@import './playlist.scss';
|
||||
|
165
client/src/sass/player/playlist.scss
Normal file
165
client/src/sass/player/playlist.scss
Normal file
@ -0,0 +1,165 @@
|
||||
$playlist-menu-width: 350px;
|
||||
|
||||
.vjs-playlist-menu {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
width: $playlist-menu-width;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
z-index: 101;
|
||||
transition: right 0.2s;
|
||||
|
||||
// Hidden
|
||||
right: -$playlist-menu-width;
|
||||
|
||||
ol {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
border-bottom: 1px solid $header-border-color;
|
||||
padding: 20px 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.channel {
|
||||
font-size: 11px;
|
||||
color: #bfbfbf;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.cross {
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
mask-image: url('#{$assets-path}/images/feather/x.svg');
|
||||
-webkit-mask-image: url('#{$assets-path}/images/feather/x.svg');
|
||||
background-color: white;
|
||||
mask-size: cover;
|
||||
-webkit-mask-size: cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.playlist-menu-displayed {
|
||||
|
||||
.vjs-playlist-menu {
|
||||
right: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.vjs-playlist-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $playlist-menu-width) {
|
||||
.vjs-playlist-menu {
|
||||
width: 100%;
|
||||
min-width: unset;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.playlist-menu-displayed .vjs-playlist-menu {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.vjs-playlist-button {
|
||||
font-size: 15px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
padding: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vjs-playlist-icon {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
mask-image: url('#{$assets-path}/images/feather/list.svg');
|
||||
-webkit-mask-image: url('#{$assets-path}/images/feather/list.svg');
|
||||
background-color: white;
|
||||
mask-size: cover;
|
||||
-webkit-mask-size: cover;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.vjs-playing.vjs-user-inactive .vjs-playlist-button {
|
||||
opacity: 0;
|
||||
|
||||
transition: opacity 1s;
|
||||
}
|
||||
|
||||
.vjs-playing.vjs-no-flex.vjs-user-inactive .vjs-playlist-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.vjs-playlist-menu-item {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
|
||||
.item-position-block {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.item-player {
|
||||
display: none;
|
||||
|
||||
@include play-icon(20px, 16px);
|
||||
}
|
||||
|
||||
&.vjs-selected {
|
||||
background-color: rgba(150, 150, 150, 0.3);
|
||||
|
||||
.item-position {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.item-player {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(150, 150, 150, 0.2);
|
||||
}
|
||||
|
||||
img {
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.info-block {
|
||||
margin-left: 10px;
|
||||
|
||||
.title {
|
||||
font-size: 13px;
|
||||
margin-bottom: 5px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.channel {
|
||||
font-size: 11px;
|
||||
color: #bfbfbf;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
@ -324,7 +324,11 @@ export class PeerTubeEmbed {
|
||||
|
||||
this.currentPlaylistElement = next
|
||||
|
||||
const res = await this.loadVideo(this.currentPlaylistElement.video.uuid)
|
||||
return this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
|
||||
}
|
||||
|
||||
private async loadVideoAndBuildPlayer (uuid: string) {
|
||||
const res = await this.loadVideo(uuid)
|
||||
if (res === undefined) return
|
||||
|
||||
return this.buildVideoPlayer(res.videoResponse, res.captionsPromise)
|
||||
@ -386,6 +390,22 @@ export class PeerTubeEmbed {
|
||||
|
||||
this.loadParams(videoInfo)
|
||||
|
||||
const playlistPlugin = this.currentPlaylistElement
|
||||
? {
|
||||
elements: this.playlistElements,
|
||||
playlist: this.playlist,
|
||||
|
||||
getCurrentPosition: () => this.currentPlaylistElement.position,
|
||||
|
||||
onItemClicked: (videoPlaylistElement: VideoPlaylistElement) => {
|
||||
this.currentPlaylistElement = videoPlaylistElement
|
||||
|
||||
this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
|
||||
.catch(err => console.error(err))
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
|
||||
const options: PeertubePlayerManagerOptions = {
|
||||
common: {
|
||||
// Autoplay in playlist mode
|
||||
@ -399,6 +419,7 @@ export class PeerTubeEmbed {
|
||||
subtitle: this.subtitle,
|
||||
|
||||
nextVideo: () => this.autoplayNext(),
|
||||
playlist: playlistPlugin,
|
||||
|
||||
videoCaptions,
|
||||
inactivityTimeout: 2500,
|
||||
@ -452,6 +473,7 @@ export class PeerTubeEmbed {
|
||||
|
||||
if (this.isPlaylistEmbed()) {
|
||||
await this.buildPlaylistManager()
|
||||
this.player.playlist().updateSelected()
|
||||
}
|
||||
}
|
||||
|
||||
@ -480,10 +502,7 @@ export class PeerTubeEmbed {
|
||||
videoId = this.getResourceId()
|
||||
}
|
||||
|
||||
const res = await this.loadVideo(videoId)
|
||||
if (res === undefined) return
|
||||
|
||||
return this.buildVideoPlayer(res.videoResponse, res.captionsPromise)
|
||||
return this.loadVideoAndBuildPlayer(videoId)
|
||||
}
|
||||
|
||||
private handleError (err: Error, translations?: { [ id: string ]: string }) {
|
||||
|
@ -50,7 +50,9 @@ values(VIDEO_CATEGORIES)
|
||||
'Sorry',
|
||||
'This video is not available because the remote instance is not responding.',
|
||||
'This playlist does not exist',
|
||||
'We cannot fetch the playlist. Please try again later.'
|
||||
'We cannot fetch the playlist. Please try again later.',
|
||||
'Playlist: {1}',
|
||||
'By {1}'
|
||||
])
|
||||
.forEach(v => { serverKeys[v] = v })
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user