2020-08-05 09:44:58 +02:00
|
|
|
import videojs from 'video.js'
|
2023-07-31 14:34:36 +02:00
|
|
|
import { secondsToTime } from '@peertube/peertube-core-utils'
|
|
|
|
import { VideoPlaylistElement } from '@peertube/peertube-models'
|
2022-03-14 14:28:20 +01:00
|
|
|
import { PlaylistItemOptions } from '../../types'
|
2020-08-05 09:44:58 +02:00
|
|
|
|
|
|
|
const Component = videojs.getComponent('Component')
|
|
|
|
|
|
|
|
class PlaylistMenuItem extends Component {
|
|
|
|
private element: VideoPlaylistElement
|
|
|
|
|
2023-06-29 15:55:00 +02:00
|
|
|
private clickHandler: () => void
|
|
|
|
private keyDownHandler: (event: KeyboardEvent) => void
|
|
|
|
|
|
|
|
options_: videojs.ComponentOptions & PlaylistItemOptions
|
|
|
|
|
2020-08-05 09:44:58 +02:00
|
|
|
constructor (player: videojs.Player, options?: PlaylistItemOptions) {
|
|
|
|
super(player, options as any)
|
|
|
|
|
|
|
|
this.emitTapEvents()
|
|
|
|
|
|
|
|
this.element = options.element
|
|
|
|
|
2023-06-29 15:55:00 +02:00
|
|
|
this.clickHandler = () => this.switchPlaylistItem()
|
|
|
|
this.keyDownHandler = event => this.handleKeyDown(event)
|
|
|
|
|
|
|
|
this.on([ 'click', 'tap' ], this.clickHandler)
|
|
|
|
this.on('keydown', this.keyDownHandler)
|
2020-08-05 09:44:58 +02:00
|
|
|
}
|
|
|
|
|
2023-06-29 15:55:00 +02:00
|
|
|
dispose () {
|
|
|
|
this.off([ 'click', 'tap' ], this.clickHandler)
|
|
|
|
this.off('keydown', this.keyDownHandler)
|
2020-08-05 09:44:58 +02:00
|
|
|
|
2023-06-29 15:55:00 +02:00
|
|
|
super.dispose()
|
|
|
|
}
|
|
|
|
|
|
|
|
createEl () {
|
2020-08-05 09:44:58 +02:00
|
|
|
const li = super.createEl('li', {
|
2024-04-04 13:24:41 +02:00
|
|
|
className: 'vjs-playlist-menu-item'
|
2020-08-05 09:44:58 +02:00
|
|
|
}) as HTMLElement
|
|
|
|
|
2023-06-29 15:55:00 +02:00
|
|
|
if (!this.options_.element.video) {
|
2020-08-05 11:41:22 +02:00
|
|
|
li.classList.add('vjs-disabled')
|
|
|
|
}
|
|
|
|
|
2020-08-05 09:44:58 +02:00
|
|
|
const positionBlock = super.createEl('div', {
|
|
|
|
className: 'item-position-block'
|
2020-08-05 11:41:22 +02:00
|
|
|
}) as HTMLElement
|
2020-08-05 09:44:58 +02:00
|
|
|
|
|
|
|
const position = super.createEl('div', {
|
|
|
|
className: 'item-position',
|
2024-04-04 13:24:41 +02:00
|
|
|
innerText: this.options_.element.position
|
2020-08-05 09:44:58 +02:00
|
|
|
})
|
|
|
|
|
2020-08-05 11:41:22 +02:00
|
|
|
positionBlock.appendChild(position)
|
|
|
|
li.appendChild(positionBlock)
|
|
|
|
|
2023-06-29 15:55:00 +02:00
|
|
|
if (this.options_.element.video) {
|
|
|
|
this.buildAvailableVideo(li, positionBlock, this.options_)
|
2020-08-05 11:41:22 +02:00
|
|
|
} 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) {
|
2020-08-05 11:57:38 +02:00
|
|
|
const videoElement = options.element
|
|
|
|
|
2020-08-05 09:44:58 +02:00
|
|
|
const player = super.createEl('div', {
|
|
|
|
className: 'item-player'
|
|
|
|
})
|
|
|
|
|
|
|
|
positionBlock.appendChild(player)
|
|
|
|
|
|
|
|
const thumbnail = super.createEl('img', {
|
2020-08-05 11:57:38 +02:00
|
|
|
src: window.location.origin + videoElement.video.thumbnailPath
|
2020-08-05 09:44:58 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
const infoBlock = super.createEl('div', {
|
|
|
|
className: 'info-block'
|
|
|
|
})
|
|
|
|
|
|
|
|
const title = super.createEl('div', {
|
2024-04-04 13:24:41 +02:00
|
|
|
innerText: videoElement.video.name,
|
2020-08-05 09:44:58 +02:00
|
|
|
className: 'title'
|
|
|
|
})
|
|
|
|
|
|
|
|
const channel = super.createEl('div', {
|
2024-04-04 13:24:41 +02:00
|
|
|
innerText: videoElement.video.channel.displayName,
|
2020-08-05 09:44:58 +02:00
|
|
|
className: 'channel'
|
|
|
|
})
|
|
|
|
|
|
|
|
infoBlock.appendChild(title)
|
|
|
|
infoBlock.appendChild(channel)
|
|
|
|
|
2020-08-05 11:57:38 +02:00
|
|
|
if (videoElement.startTimestamp || videoElement.stopTimestamp) {
|
|
|
|
let html = ''
|
|
|
|
|
|
|
|
if (videoElement.startTimestamp) html += secondsToTime(videoElement.startTimestamp)
|
|
|
|
if (videoElement.stopTimestamp) html += ' - ' + secondsToTime(videoElement.stopTimestamp)
|
|
|
|
|
|
|
|
const timestamps = super.createEl('div', {
|
2024-04-04 13:24:41 +02:00
|
|
|
innerText: html,
|
2020-08-05 11:57:38 +02:00
|
|
|
className: 'timestamps'
|
|
|
|
})
|
|
|
|
|
|
|
|
infoBlock.append(timestamps)
|
|
|
|
}
|
|
|
|
|
2020-08-05 09:44:58 +02:00
|
|
|
li.append(thumbnail)
|
|
|
|
li.append(infoBlock)
|
|
|
|
}
|
|
|
|
|
2020-08-05 11:41:22 +02:00
|
|
|
private buildUnavailableVideo (li: HTMLElement) {
|
|
|
|
const block = super.createEl('div', {
|
|
|
|
className: 'item-unavailable',
|
2024-04-04 13:24:41 +02:00
|
|
|
innerTExt: this.player().localize('Unavailable video')
|
2020-08-05 11:41:22 +02:00
|
|
|
})
|
2020-08-05 09:44:58 +02:00
|
|
|
|
2020-08-05 11:41:22 +02:00
|
|
|
li.appendChild(block)
|
2020-08-05 09:44:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private handleKeyDown (event: KeyboardEvent) {
|
|
|
|
if (event.code === 'Space' || event.code === 'Enter') {
|
|
|
|
this.switchPlaylistItem()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private switchPlaylistItem () {
|
2023-06-29 15:55:00 +02:00
|
|
|
this.options_.onClicked()
|
2020-08-05 09:44:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component.registerComponent('PlaylistMenuItem', PlaylistMenuItem)
|
|
|
|
|
|
|
|
export { PlaylistMenuItem }
|