mirror of https://github.com/Chocobozzz/PeerTube
156 lines
3.8 KiB
TypeScript
156 lines
3.8 KiB
TypeScript
import videojs from 'video.js'
|
|
import { VideoPlaylistElement } from '@peertube/peertube-models'
|
|
import { PlaylistPluginOptions } from '../../types'
|
|
import { PlaylistMenuItem } from './playlist-menu-item'
|
|
|
|
const Component = videojs.getComponent('Component')
|
|
|
|
class PlaylistMenu extends Component {
|
|
private menuItems: PlaylistMenuItem[] = []
|
|
|
|
private readonly userInactiveHandler: () => void
|
|
private readonly onMouseEnter: () => void
|
|
private readonly onMouseLeave: () => void
|
|
|
|
private readonly onPlayerCick: (event: Event) => void
|
|
|
|
options_: PlaylistPluginOptions & videojs.ComponentOptions
|
|
|
|
constructor (player: videojs.Player, options?: PlaylistPluginOptions & videojs.ComponentOptions) {
|
|
super(player, options)
|
|
|
|
this.userInactiveHandler = () => {
|
|
this.close()
|
|
}
|
|
|
|
this.onMouseEnter = () => {
|
|
this.player().off('userinactive', this.userInactiveHandler)
|
|
}
|
|
|
|
this.onMouseLeave = () => {
|
|
this.player().one('userinactive', this.userInactiveHandler)
|
|
}
|
|
|
|
this.onPlayerCick = 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()
|
|
}
|
|
|
|
this.el().addEventListener('mouseenter', this.onMouseEnter)
|
|
this.el().addEventListener('mouseleave', this.onMouseLeave)
|
|
|
|
this.player().on('click', this.onPlayerCick)
|
|
}
|
|
|
|
dispose () {
|
|
this.el().removeEventListener('mouseenter', this.onMouseEnter)
|
|
this.el().removeEventListener('mouseleave', this.onMouseLeave)
|
|
|
|
this.player().off('userinactive', this.userInactiveHandler)
|
|
this.player().off('click', this.onPlayerCick)
|
|
|
|
for (const item of this.menuItems) {
|
|
item.dispose()
|
|
}
|
|
|
|
super.dispose()
|
|
}
|
|
|
|
createEl () {
|
|
this.menuItems = []
|
|
|
|
const menu = super.createEl('div', {
|
|
className: 'vjs-playlist-menu',
|
|
tabIndex: -1
|
|
})
|
|
|
|
const header = super.createEl('div', {
|
|
className: 'header'
|
|
})
|
|
|
|
const headerLeft = super.createEl('div')
|
|
|
|
const leftTitle = super.createEl('div', {
|
|
innerText: this.options_.playlist.displayName,
|
|
className: 'title'
|
|
})
|
|
|
|
const playlistChannel = this.options_.playlist.videoChannel
|
|
const leftSubtitle = super.createEl('div', {
|
|
innerText: playlistChannel
|
|
? this.player().localize('By {1}', [ playlistChannel.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 this.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)
|
|
|
|
this.update()
|
|
|
|
return menu
|
|
}
|
|
|
|
update () {
|
|
this.updateSelected(this.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 onItemClicked (element: VideoPlaylistElement) {
|
|
this.options_.onItemClicked(element)
|
|
}
|
|
}
|
|
|
|
Component.registerComponent('PlaylistMenu', PlaylistMenu)
|
|
|
|
export { PlaylistMenu }
|