Handle unavailable videos in embed playlists
This commit is contained in:
parent
a950e4c82b
commit
56674bb9f8
4 changed files with 71 additions and 26 deletions
|
@ -26,24 +26,47 @@ class PlaylistMenuItem extends Component {
|
||||||
innerHTML: ''
|
innerHTML: ''
|
||||||
}) as HTMLElement
|
}) as HTMLElement
|
||||||
|
|
||||||
|
if (!options.element.video) {
|
||||||
|
li.classList.add('vjs-disabled')
|
||||||
|
}
|
||||||
|
|
||||||
const positionBlock = super.createEl('div', {
|
const positionBlock = super.createEl('div', {
|
||||||
className: 'item-position-block'
|
className: 'item-position-block'
|
||||||
})
|
}) as HTMLElement
|
||||||
|
|
||||||
const position = super.createEl('div', {
|
const position = super.createEl('div', {
|
||||||
className: 'item-position',
|
className: 'item-position',
|
||||||
innerHTML: options.element.position
|
innerHTML: options.element.position
|
||||||
})
|
})
|
||||||
|
|
||||||
|
positionBlock.appendChild(position)
|
||||||
|
li.appendChild(positionBlock)
|
||||||
|
|
||||||
|
if (options.element.video) {
|
||||||
|
this.buildAvailableVideo(li, positionBlock, options)
|
||||||
|
} else {
|
||||||
|
this.buildUnavailableVideo(li)
|
||||||
|
}
|
||||||
|
|
||||||
|
return li
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelected (selected: boolean) {
|
||||||
|
if (selected) this.addClass('vjs-selected')
|
||||||
|
else this.removeClass('vjs-selected')
|
||||||
|
}
|
||||||
|
|
||||||
|
getElement () {
|
||||||
|
return this.element
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildAvailableVideo (li: HTMLElement, positionBlock: HTMLElement, options: PlaylistItemOptions) {
|
||||||
const player = super.createEl('div', {
|
const player = super.createEl('div', {
|
||||||
className: 'item-player'
|
className: 'item-player'
|
||||||
})
|
})
|
||||||
|
|
||||||
positionBlock.appendChild(position)
|
|
||||||
positionBlock.appendChild(player)
|
positionBlock.appendChild(player)
|
||||||
|
|
||||||
li.appendChild(positionBlock)
|
|
||||||
|
|
||||||
const thumbnail = super.createEl('img', {
|
const thumbnail = super.createEl('img', {
|
||||||
src: window.location.origin + options.element.video.thumbnailPath
|
src: window.location.origin + options.element.video.thumbnailPath
|
||||||
})
|
})
|
||||||
|
@ -67,17 +90,15 @@ class PlaylistMenuItem extends Component {
|
||||||
|
|
||||||
li.append(thumbnail)
|
li.append(thumbnail)
|
||||||
li.append(infoBlock)
|
li.append(infoBlock)
|
||||||
|
|
||||||
return li
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelected (selected: boolean) {
|
private buildUnavailableVideo (li: HTMLElement) {
|
||||||
if (selected) this.addClass('vjs-selected')
|
const block = super.createEl('div', {
|
||||||
else this.removeClass('vjs-selected')
|
className: 'item-unavailable',
|
||||||
}
|
innerHTML: this.player().localize('Unavailable video')
|
||||||
|
})
|
||||||
|
|
||||||
getElement () {
|
li.appendChild(block)
|
||||||
return this.element
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleKeyDown (event: KeyboardEvent) {
|
private handleKeyDown (event: KeyboardEvent) {
|
||||||
|
|
|
@ -11,8 +11,18 @@ class PlaylistMenu extends Component {
|
||||||
constructor (player: videojs.Player, options?: PlaylistPluginOptions) {
|
constructor (player: videojs.Player, options?: PlaylistPluginOptions) {
|
||||||
super(player, options as any)
|
super(player, options as any)
|
||||||
|
|
||||||
this.player().on('userinactive', () => {
|
const self = this
|
||||||
this.close()
|
|
||||||
|
function userInactiveHandler () {
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.el().addEventListener('mouseenter', () => {
|
||||||
|
this.player().off('userinactive', userInactiveHandler)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.el().addEventListener('mouseleave', () => {
|
||||||
|
this.player().one('userinactive', userInactiveHandler)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.player().on('click', event => {
|
this.player().on('click', event => {
|
||||||
|
|
|
@ -24,17 +24,17 @@ $playlist-menu-width: 350px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
@include ellipsis;
|
||||||
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel {
|
.channel {
|
||||||
|
@include ellipsis;
|
||||||
|
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #bfbfbf;
|
color: #bfbfbf;
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cross {
|
.cross {
|
||||||
|
@ -106,9 +106,13 @@ $playlist-menu-width: 350px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vjs-playlist-menu-item {
|
.vjs-playlist-menu-item {
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
|
height: 60px;
|
||||||
|
|
||||||
|
&:not(.vjs-disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.item-position-block {
|
.item-position-block {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -116,6 +120,14 @@ $playlist-menu-width: 350px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-unavailable {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-player {
|
.item-player {
|
||||||
|
@ -136,7 +148,7 @@ $playlist-menu-width: 350px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover:not(.vjs-disabled) {
|
||||||
background-color: rgba(150, 150, 150, 0.2);
|
background-color: rgba(150, 150, 150, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,20 +158,21 @@ $playlist-menu-width: 350px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-block {
|
.info-block {
|
||||||
margin-left: 10px;
|
margin: 0 10px;
|
||||||
|
min-width: 1px;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
@include ellipsis;
|
||||||
|
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel {
|
.channel {
|
||||||
|
@include ellipsis;
|
||||||
|
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #bfbfbf;
|
color: #bfbfbf;
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,8 @@ values(VIDEO_CATEGORIES)
|
||||||
'This playlist does not exist',
|
'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}',
|
'Playlist: {1}',
|
||||||
'By {1}'
|
'By {1}',
|
||||||
|
'Unavailable video'
|
||||||
])
|
])
|
||||||
.forEach(v => { serverKeys[v] = v })
|
.forEach(v => { serverKeys[v] = v })
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue