mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-03 01:39:37 +02:00
Merge branch 'release/7.2.0' into develop
This commit is contained in:
commit
037197a7e9
16 changed files with 138 additions and 96 deletions
|
@ -1,10 +1,9 @@
|
||||||
@use 'sass:math';
|
@use "sass:math";
|
||||||
@use '_variables' as *;
|
@use "_variables" as *;
|
||||||
@use '_mixins' as *;
|
@use "_mixins" as *;
|
||||||
@use './_player-variables' as *;
|
@use "./_player-variables" as *;
|
||||||
|
|
||||||
.video-js.vjs-peertube-skin {
|
.video-js.vjs-peertube-skin {
|
||||||
|
|
||||||
.peertube-dock {
|
.peertube-dock {
|
||||||
--dock-avatar-size: 48px;
|
--dock-avatar-size: 48px;
|
||||||
|
|
||||||
|
@ -18,9 +17,8 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
font-size: 23px;
|
|
||||||
padding: $dock-padding;
|
padding: $dock-padding;
|
||||||
background: linear-gradient(to bottom, rgba(20, 20, 20, .7) 0, rgba(20, 20, 20, 0));
|
background: linear-gradient(to bottom, rgba(20, 20, 20, 0.7) 0, rgba(20, 20, 20, 0));
|
||||||
|
|
||||||
@include padding-right(60px);
|
@include padding-right(60px);
|
||||||
}
|
}
|
||||||
|
@ -44,11 +42,13 @@
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 23px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.peertube-dock-title,
|
.peertube-dock-title,
|
||||||
.peertube-dock-description {
|
.peertube-dock-description {
|
||||||
text-shadow: 0 1px 3px rgba(0, 0, 0, .5);
|
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
|
||||||
|
|
||||||
@include ellipsis;
|
@include ellipsis;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
--dock-avatar-size: 40px;
|
--dock-avatar-size: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.peertube-dock {
|
.peertube-dock-title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,13 +82,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.video-js.vjs-peertube-skin.vjs-size-570 {
|
.video-js.vjs-peertube-skin.vjs-size-570 {
|
||||||
.peertube-dock-avatar {
|
.peertube-dock-avatar {
|
||||||
--dock-avatar-size: 35px;
|
--dock-avatar-size: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.peertube-dock {
|
.peertube-dock-title {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +97,7 @@
|
||||||
--dock-avatar-size: 30px;
|
--dock-avatar-size: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.peertube-dock {
|
.peertube-dock-title {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { bytes } from '../common'
|
||||||
|
|
||||||
const Button = videojs.getComponent('Button')
|
const Button = videojs.getComponent('Button')
|
||||||
class P2PInfoButton extends Button {
|
class P2PInfoButton extends Button {
|
||||||
|
|
||||||
createEl () {
|
createEl () {
|
||||||
const div = videojs.dom.createEl('div', { className: 'vjs-peertube' })
|
const div = videojs.dom.createEl('div', { className: 'vjs-peertube' })
|
||||||
const subDivP2P = videojs.dom.createEl('div', {
|
const subDivP2P = videojs.dom.createEl('div', {
|
||||||
|
@ -12,7 +11,10 @@ class P2PInfoButton extends Button {
|
||||||
}) as HTMLDivElement
|
}) as HTMLDivElement
|
||||||
div.appendChild(subDivP2P)
|
div.appendChild(subDivP2P)
|
||||||
|
|
||||||
const downloadIcon = videojs.dom.createEl('span', { className: 'icon icon-download' })
|
const downloadIcon = videojs.dom.createEl('span', { className: 'icon icon-download' }, {
|
||||||
|
role: 'img',
|
||||||
|
ariaLabel: this.player().localize('Download speed:')
|
||||||
|
})
|
||||||
subDivP2P.appendChild(downloadIcon)
|
subDivP2P.appendChild(downloadIcon)
|
||||||
|
|
||||||
const downloadSpeedText = videojs.dom.createEl('span', { className: 'download-speed-text' })
|
const downloadSpeedText = videojs.dom.createEl('span', { className: 'download-speed-text' })
|
||||||
|
@ -22,7 +24,10 @@ class P2PInfoButton extends Button {
|
||||||
downloadSpeedText.appendChild(downloadSpeedUnit)
|
downloadSpeedText.appendChild(downloadSpeedUnit)
|
||||||
subDivP2P.appendChild(downloadSpeedText)
|
subDivP2P.appendChild(downloadSpeedText)
|
||||||
|
|
||||||
const uploadIcon = videojs.dom.createEl('span', { className: 'icon icon-upload' })
|
const uploadIcon = videojs.dom.createEl('span', { className: 'icon icon-upload' }, {
|
||||||
|
role: 'img',
|
||||||
|
ariaLabel: this.player().localize('Upload speed:')
|
||||||
|
})
|
||||||
subDivP2P.appendChild(uploadIcon)
|
subDivP2P.appendChild(uploadIcon)
|
||||||
|
|
||||||
const uploadSpeedText = videojs.dom.createEl('span', { className: 'upload-speed-text' })
|
const uploadSpeedText = videojs.dom.createEl('span', { className: 'upload-speed-text' })
|
||||||
|
@ -64,8 +69,7 @@ class P2PInfoButton extends Button {
|
||||||
const downloadedFromServer = bytes(httpStats.downloaded).join(' ')
|
const downloadedFromServer = bytes(httpStats.downloaded).join(' ')
|
||||||
const downloadedFromPeers = bytes(p2pStats.downloaded).join(' ')
|
const downloadedFromPeers = bytes(p2pStats.downloaded).join(' ')
|
||||||
|
|
||||||
subDivP2P.title +=
|
subDivP2P.title += ' * ' + this.player().localize('From servers: ') + downloadedFromServer + '\n' +
|
||||||
' * ' + this.player().localize('From servers: ') + downloadedFromServer + '\n' +
|
|
||||||
' * ' + this.player().localize('From peers: ') + downloadedFromPeers + '\n'
|
' * ' + this.player().localize('From peers: ') + downloadedFromPeers + '\n'
|
||||||
}
|
}
|
||||||
subDivP2P.title += this.player().localize('Total uploaded: ') + totalUploaded.join(' ')
|
subDivP2P.title += this.player().localize('Total uploaded: ') + totalUploaded.join(' ')
|
||||||
|
|
|
@ -23,7 +23,7 @@ class PeerTubeDockComponent extends Component {
|
||||||
const avatar = videojs.dom.createEl('img', {
|
const avatar = videojs.dom.createEl('img', {
|
||||||
className: 'peertube-dock-avatar',
|
className: 'peertube-dock-avatar',
|
||||||
src: this.options_.avatarUrl
|
src: this.options_.avatarUrl
|
||||||
})
|
}, { alt: '' })
|
||||||
|
|
||||||
el.appendChild(avatar)
|
el.appendChild(avatar)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class PeerTubeDockComponent extends Component {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (this.options_.title) {
|
if (this.options_.title) {
|
||||||
const title = videojs.dom.createEl('div', {
|
const title = videojs.dom.createEl('h2', {
|
||||||
className: 'peertube-dock-title',
|
className: 'peertube-dock-title',
|
||||||
title: this.options_.title,
|
title: this.options_.title,
|
||||||
innerText: this.options_.title
|
innerText: this.options_.title
|
||||||
|
|
|
@ -254,6 +254,7 @@ class PeerTubePlugin extends Plugin {
|
||||||
if (isMobile()) this.player.addClass('vjs-is-mobile')
|
if (isMobile()) this.player.addClass('vjs-is-mobile')
|
||||||
|
|
||||||
this.initSmoothProgressBar()
|
this.initSmoothProgressBar()
|
||||||
|
this.patchMenuEscapeKey()
|
||||||
|
|
||||||
this.player.ready(() => {
|
this.player.ready(() => {
|
||||||
this.listenControlBarMouse()
|
this.listenControlBarMouse()
|
||||||
|
@ -654,6 +655,36 @@ class PeerTubePlugin extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private patchMenuEscapeKey () {
|
||||||
|
const Menu = videojs.getComponent('Menu') as any
|
||||||
|
|
||||||
|
const fn = Menu.prototype.handleKeyDown
|
||||||
|
Menu.prototype.handleKeyDown = function handleKeyDown (event: KeyboardEvent) {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
this.trigger('escaped-key')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === 'ArrowRight') {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
this.trigger('arrow-right', event.target)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === 'ArrowLeft') {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
this.trigger('arrow-left')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fn.call(this, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getCaptionsButton () {
|
private getCaptionsButton () {
|
||||||
const settingsButton = this.player.controlBar.getDescendant([ 'settingsButton' ]) as SettingsButton
|
const settingsButton = this.player.controlBar.getDescendant([ 'settingsButton' ]) as SettingsButton
|
||||||
|
|
||||||
|
|
|
@ -8,20 +8,6 @@ const Component = videojs.getComponent('Component')
|
||||||
class MenuFocusFixed extends Menu {
|
class MenuFocusFixed extends Menu {
|
||||||
declare private focusedChild_: number
|
declare private focusedChild_: number
|
||||||
|
|
||||||
handleKeyDown (event: KeyboardEvent) {
|
|
||||||
if (event.key === 'Escape') {
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
this.trigger('escaped-key')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: super misses handleKeyDown
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-expect-error
|
|
||||||
return super.handleKeyDown(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
stepForward () {
|
stepForward () {
|
||||||
let stepChild = 0
|
let stepChild = 0
|
||||||
|
|
||||||
|
@ -40,7 +26,17 @@ class MenuFocusFixed extends Menu {
|
||||||
this.focus(stepChild)
|
this.focus(stepChild)
|
||||||
}
|
}
|
||||||
|
|
||||||
focus (item = 0): void {
|
focus (item?: number): void {
|
||||||
|
// Reset focus
|
||||||
|
if (item === undefined) {
|
||||||
|
this.focusedChild_ = -1
|
||||||
|
item = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
this._focus(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
private _focus (item: number) {
|
||||||
const children = this.children().slice()
|
const children = this.children().slice()
|
||||||
const haveTitle = children.length && children[0].hasClass('vjs-menu-title')
|
const haveTitle = children.length && children[0].hasClass('vjs-menu-title')
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import videojs from 'video.js'
|
||||||
const Component = videojs.getComponent('Component')
|
const Component = videojs.getComponent('Component')
|
||||||
|
|
||||||
class SettingsDialog extends Component {
|
class SettingsDialog extends Component {
|
||||||
|
|
||||||
constructor (player: videojs.Player) {
|
constructor (player: videojs.Player) {
|
||||||
super(player)
|
super(player)
|
||||||
|
|
||||||
|
@ -12,15 +11,15 @@ class SettingsDialog extends Component {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the component's DOM element
|
* Create the component's DOM element
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
createEl () {
|
createEl () {
|
||||||
const uniqueId = this.id()
|
const uniqueId = this.player().id()
|
||||||
const dialogLabelId = 'TTsettingsDialogLabel-' + uniqueId
|
const dialogLabelId = 'TTsettingsDialogLabel-' + uniqueId
|
||||||
const dialogDescriptionId = 'TTsettingsDialogDescription-' + uniqueId
|
const dialogDescriptionId = 'TTsettingsDialogDescription-' + uniqueId
|
||||||
|
|
||||||
return super.createEl('div', {
|
return super.createEl('div', {
|
||||||
className: 'vjs-settings-dialog vjs-modal-overlay',
|
className: 'vjs-settings-dialog vjs-modal-overlay',
|
||||||
|
id: 'vjs-settings-dialog-' + uniqueId,
|
||||||
tabIndex: -1
|
tabIndex: -1
|
||||||
}, {
|
}, {
|
||||||
'role': 'dialog',
|
'role': 'dialog',
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
|
import debug from 'debug'
|
||||||
import videojs from 'video.js'
|
import videojs from 'video.js'
|
||||||
import { toTitleCase } from '../common'
|
import { toTitleCase } from '../common'
|
||||||
|
import { MenuFocusFixed } from './menu-focus-fixed'
|
||||||
import { SettingsDialog } from './settings-dialog'
|
import { SettingsDialog } from './settings-dialog'
|
||||||
import { SettingsMenuItem } from './settings-menu-item'
|
import { SettingsMenuItem } from './settings-menu-item'
|
||||||
import { SettingsPanel } from './settings-panel'
|
import { SettingsPanel } from './settings-panel'
|
||||||
import { SettingsPanelChild } from './settings-panel-child'
|
import { SettingsPanelChild } from './settings-panel-child'
|
||||||
import { MenuFocusFixed } from './menu-focus-fixed'
|
|
||||||
|
const debugLogger = debug('peertube:player:settings')
|
||||||
|
|
||||||
const Button = videojs.getComponent('Button')
|
const Button = videojs.getComponent('Button')
|
||||||
const Component = videojs.getComponent('Component')
|
const Component = videojs.getComponent('Component')
|
||||||
|
@ -44,6 +47,7 @@ class SettingsButton extends Button {
|
||||||
this.panelChild = this.panel.addChild('settingsPanelChild')
|
this.panelChild = this.panel.addChild('settingsPanelChild')
|
||||||
|
|
||||||
this.addClass('vjs-settings')
|
this.addClass('vjs-settings')
|
||||||
|
this.setAttribute('aria-controls', 'vjs-settings-dialog-' + this.player().id())
|
||||||
|
|
||||||
// Event handlers
|
// Event handlers
|
||||||
this.addSettingsItemHandler = this.onAddSettingsItem.bind(this)
|
this.addSettingsItemHandler = this.onAddSettingsItem.bind(this)
|
||||||
|
@ -145,7 +149,6 @@ class SettingsButton extends Button {
|
||||||
|
|
||||||
showDialog () {
|
showDialog () {
|
||||||
this.player().peertube().onMenuOpened()
|
this.player().peertube().onMenuOpened()
|
||||||
|
|
||||||
;(this.menu.el() as HTMLElement).style.opacity = '1'
|
;(this.menu.el() as HTMLElement).style.opacity = '1'
|
||||||
|
|
||||||
this.dialog.show()
|
this.dialog.show()
|
||||||
|
@ -214,6 +217,12 @@ class SettingsButton extends Button {
|
||||||
this.focus()
|
this.focus()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.menu.on('arrow-right', (_, el) => {
|
||||||
|
debugLogger('Detected arrow right on menu item', el)
|
||||||
|
|
||||||
|
el.click()
|
||||||
|
})
|
||||||
|
|
||||||
this.menu.addClass('vjs-main-menu')
|
this.menu.addClass('vjs-main-menu')
|
||||||
const entries = this.settingsButtonOptions.entries
|
const entries = this.settingsButtonOptions.entries
|
||||||
|
|
||||||
|
@ -252,6 +261,11 @@ class SettingsButton extends Button {
|
||||||
|
|
||||||
// Whether to add or remove selected class on the settings sub menu element
|
// Whether to add or remove selected class on the settings sub menu element
|
||||||
settingsMenuItem.on('click', openSubMenu)
|
settingsMenuItem.on('click', openSubMenu)
|
||||||
|
|
||||||
|
settingsMenuItem.on('escaped-key', () => {
|
||||||
|
this.hideDialog()
|
||||||
|
this.focus()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
resetChildren () {
|
resetChildren () {
|
||||||
|
|
|
@ -81,6 +81,10 @@ class SettingsMenuItem extends MenuItem {
|
||||||
// Update on rate change
|
// Update on rate change
|
||||||
if (subMenuName === 'PlaybackRateMenuButton') {
|
if (subMenuName === 'PlaybackRateMenuButton') {
|
||||||
player.on('ratechange', this.submenuClickHandler)
|
player.on('ratechange', this.submenuClickHandler)
|
||||||
|
|
||||||
|
player.on('playbackrateschange', () => {
|
||||||
|
setTimeout(() => this.rebuildAfterMenuChange())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subMenuName === 'CaptionsButton') {
|
if (subMenuName === 'CaptionsButton') {
|
||||||
|
@ -139,7 +143,6 @@ class SettingsMenuItem extends MenuItem {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the component's DOM element
|
* Create the component's DOM element
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
createEl () {
|
createEl () {
|
||||||
const el = videojs.dom.createEl('li', {
|
const el = videojs.dom.createEl('li', {
|
||||||
|
@ -176,9 +179,8 @@ class SettingsMenuItem extends MenuItem {
|
||||||
// Remove open class to ensure only the open submenu gets this class
|
// Remove open class to ensure only the open submenu gets this class
|
||||||
videojs.dom.removeClass(this.el(), 'open')
|
videojs.dom.removeClass(this.el(), 'open')
|
||||||
|
|
||||||
super.handleClick(event);
|
super.handleClick(event)
|
||||||
|
;(this.mainMenu.el() as HTMLElement).style.opacity = '0'
|
||||||
(this.mainMenu.el() as HTMLElement).style.opacity = '0'
|
|
||||||
// Whether to add or remove vjs-hidden class on the settingsSubMenuEl element
|
// Whether to add or remove vjs-hidden class on the settingsSubMenuEl element
|
||||||
if (videojs.dom.hasClass(this.settingsSubMenuEl_, 'vjs-hidden')) {
|
if (videojs.dom.hasClass(this.settingsSubMenuEl_, 'vjs-hidden')) {
|
||||||
videojs.dom.removeClass(this.settingsSubMenuEl_, 'vjs-hidden')
|
videojs.dom.removeClass(this.settingsSubMenuEl_, 'vjs-hidden')
|
||||||
|
@ -206,9 +208,8 @@ class SettingsMenuItem extends MenuItem {
|
||||||
const button = this.subMenu.menu.addChild('MenuItem', {}, 0)
|
const button = this.subMenu.menu.addChild('MenuItem', {}, 0)
|
||||||
|
|
||||||
button.setAttribute('aria-label', this.player().localize('Go back'))
|
button.setAttribute('aria-label', this.player().localize('Go back'))
|
||||||
button.addClass('vjs-back-button');
|
button.addClass('vjs-back-button')
|
||||||
|
;(button.el() as HTMLElement).innerHTML = this.player().localize(this.subMenu.controlText())
|
||||||
(button.el() as HTMLElement).innerHTML = this.player().localize(this.subMenu.controlText())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onTransitionEnd (event: any) {
|
onTransitionEnd (event: any) {
|
||||||
|
@ -265,6 +266,7 @@ class SettingsMenuItem extends MenuItem {
|
||||||
this.createBackButton()
|
this.createBackButton()
|
||||||
this.setSize()
|
this.setSize()
|
||||||
this.bindClickEvents()
|
this.bindClickEvents()
|
||||||
|
this.bindKeyEvents()
|
||||||
|
|
||||||
this.settingsSubMenuEl_.addEventListener('transitionend', this.transitionEndHandler, false)
|
this.settingsSubMenuEl_.addEventListener('transitionend', this.transitionEndHandler, false)
|
||||||
}
|
}
|
||||||
|
@ -284,7 +286,6 @@ class SettingsMenuItem extends MenuItem {
|
||||||
|
|
||||||
const subMenuItemExtended = subMenuItem as MenuItemExtended
|
const subMenuItemExtended = subMenuItem as MenuItemExtended
|
||||||
if (subMenuItemExtended.isSelected_) {
|
if (subMenuItemExtended.isSelected_) {
|
||||||
|
|
||||||
// Prefer to use the function
|
// Prefer to use the function
|
||||||
if (typeof subMenuItemExtended.getLabel === 'function') {
|
if (typeof subMenuItemExtended.getLabel === 'function') {
|
||||||
this.settingsSubMenuValueEl_.innerHTML = subMenuItemExtended.getLabel()
|
this.settingsSubMenuValueEl_.innerHTML = subMenuItemExtended.getLabel()
|
||||||
|
@ -310,13 +311,24 @@ class SettingsMenuItem extends MenuItem {
|
||||||
|
|
||||||
bindClickEvents () {
|
bindClickEvents () {
|
||||||
for (const item of this.subMenu.menu.children()) {
|
for (const item of this.subMenu.menu.children()) {
|
||||||
if (!(item instanceof Component)) {
|
if (!(item instanceof Component)) continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
item.on([ 'tap', 'click' ], this.submenuClickHandler)
|
item.on([ 'tap', 'click' ], this.submenuClickHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindKeyEvents () {
|
||||||
|
this.subMenu.menu.on('escaped-key', () => {
|
||||||
|
this.trigger('escaped-key')
|
||||||
|
})
|
||||||
|
|
||||||
|
this.subMenu.menu.on('arrow-left', () => {
|
||||||
|
debugLogger('Detected arrow left on sub menu ' + this.subMenu.name())
|
||||||
|
|
||||||
|
this.loadMainMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// save size of submenus on first init
|
// save size of submenus on first init
|
||||||
// if number of submenu items change dynamically more logic will be needed
|
// if number of submenu items change dynamically more logic will be needed
|
||||||
setSize () {
|
setSize () {
|
||||||
|
@ -360,11 +372,11 @@ class SettingsMenuItem extends MenuItem {
|
||||||
this.createBackButton()
|
this.createBackButton()
|
||||||
this.setSize()
|
this.setSize()
|
||||||
this.bindClickEvents()
|
this.bindClickEvents()
|
||||||
|
this.bindKeyEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(SettingsMenuItem as any).prototype.contentElType = 'button'
|
;(SettingsMenuItem as any).prototype.contentElType = 'button'
|
||||||
videojs.registerComponent('SettingsMenuItem', SettingsMenuItem)
|
videojs.registerComponent('SettingsMenuItem', SettingsMenuItem)
|
||||||
|
|
||||||
export { SettingsMenuItem }
|
export { SettingsMenuItem }
|
||||||
|
|
|
@ -382,7 +382,7 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
|
||||||
handler: (result, params) => {
|
handler: (result, params) => {
|
||||||
return {
|
return {
|
||||||
allowed: false,
|
allowed: false,
|
||||||
html: 'Lu Bu'
|
html: 'Lu Bu ' + params.req.params.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -392,7 +392,7 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
|
||||||
handler: (result, params) => {
|
handler: (result, params) => {
|
||||||
return {
|
return {
|
||||||
allowed: false,
|
allowed: false,
|
||||||
html: 'Diao Chan'
|
html: 'Diao Chan ' + params.req.params.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -49,7 +49,7 @@ describe('Test plugin filter hooks', function () {
|
||||||
await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() })
|
await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() })
|
||||||
await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
|
await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
|
||||||
{
|
{
|
||||||
({ uuid: videoPlaylistUUID } = await servers[0].playlists.create({
|
;({ uuid: videoPlaylistUUID } = await servers[0].playlists.create({
|
||||||
attributes: {
|
attributes: {
|
||||||
displayName: 'my super playlist',
|
displayName: 'my super playlist',
|
||||||
privacy: VideoPlaylistPrivacy.PUBLIC,
|
privacy: VideoPlaylistPrivacy.PUBLIC,
|
||||||
|
@ -100,7 +100,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Videos', function () {
|
describe('Videos', function () {
|
||||||
|
|
||||||
it('Should run filter:api.videos.list.params', async function () {
|
it('Should run filter:api.videos.list.params', async function () {
|
||||||
const { data } = await servers[0].videos.list({ start: 0, count: 2 })
|
const { data } = await servers[0].videos.list({ start: 0, count: 2 })
|
||||||
|
|
||||||
|
@ -198,7 +197,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Video/live/import accept', function () {
|
describe('Video/live/import accept', function () {
|
||||||
|
|
||||||
it('Should run filter:api.video.upload.accept.result', async function () {
|
it('Should run filter:api.video.upload.accept.result', async function () {
|
||||||
const options = { attributes: { name: 'video with bad word' }, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
|
const options = { attributes: { name: 'video with bad word' }, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
|
||||||
await servers[0].videos.upload({ mode: 'legacy', ...options })
|
await servers[0].videos.upload({ mode: 'legacy', ...options })
|
||||||
|
@ -312,7 +310,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Video comments accept', function () {
|
describe('Video comments accept', function () {
|
||||||
|
|
||||||
it('Should run filter:api.video-thread.create.accept.result', async function () {
|
it('Should run filter:api.video-thread.create.accept.result', async function () {
|
||||||
await servers[0].comments.createThread({
|
await servers[0].comments.createThread({
|
||||||
videoId: videoUUID,
|
videoId: videoUUID,
|
||||||
|
@ -386,7 +383,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Video comments', function () {
|
describe('Video comments', function () {
|
||||||
|
|
||||||
it('Should run filter:api.video-threads.list.params', async function () {
|
it('Should run filter:api.video-threads.list.params', async function () {
|
||||||
const { data } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
|
const { data } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
|
||||||
|
|
||||||
|
@ -419,7 +415,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('filter:video.auto-blacklist.result', function () {
|
describe('filter:video.auto-blacklist.result', function () {
|
||||||
|
|
||||||
async function checkIsBlacklisted (id: number | string, value: boolean) {
|
async function checkIsBlacklisted (id: number | string, value: boolean) {
|
||||||
const video = await servers[0].videos.getWithToken({ id })
|
const video = await servers[0].videos.getWithToken({ id })
|
||||||
expect(video.blacklisted).to.equal(value)
|
expect(video.blacklisted).to.equal(value)
|
||||||
|
@ -483,7 +478,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Should run filter:api.user.signup.allowed.result', function () {
|
describe('Should run filter:api.user.signup.allowed.result', function () {
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
await servers[0].config.updateExistingConfig({ newConfig: { signup: { requiresApproval: false } } })
|
await servers[0].config.updateExistingConfig({ newConfig: { signup: { requiresApproval: false } } })
|
||||||
})
|
})
|
||||||
|
@ -508,7 +502,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Should run filter:api.user.request-signup.allowed.result', function () {
|
describe('Should run filter:api.user.request-signup.allowed.result', function () {
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
await servers[0].config.updateExistingConfig({ newConfig: { signup: { requiresApproval: true } } })
|
await servers[0].config.updateExistingConfig({ newConfig: { signup: { requiresApproval: true } } })
|
||||||
})
|
})
|
||||||
|
@ -635,12 +628,12 @@ describe('Test plugin filter hooks', function () {
|
||||||
|
|
||||||
it('Should run filter:html.embed.video.allowed.result', async function () {
|
it('Should run filter:html.embed.video.allowed.result', async function () {
|
||||||
const res = await makeGetRequest({ url: servers[0].url, path: embedVideos[0].embedPath, expectedStatus: HttpStatusCode.OK_200 })
|
const res = await makeGetRequest({ url: servers[0].url, path: embedVideos[0].embedPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||||
expect(res.text).to.equal('Lu Bu')
|
expect(res.text).to.equal('Lu Bu ' + embedVideos[0].uuid)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:html.embed.video-playlist.allowed.result', async function () {
|
it('Should run filter:html.embed.video-playlist.allowed.result', async function () {
|
||||||
const res = await makeGetRequest({ url: servers[0].url, path: embedPlaylists[0].embedPath, expectedStatus: HttpStatusCode.OK_200 })
|
const res = await makeGetRequest({ url: servers[0].url, path: embedPlaylists[0].embedPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||||
expect(res.text).to.equal('Diao Chan')
|
expect(res.text).to.equal('Diao Chan ' + embedPlaylists[0].uuid)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -666,7 +659,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Search filters', function () {
|
describe('Search filters', function () {
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
await servers[0].config.updateExistingConfig({
|
await servers[0].config.updateExistingConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
|
@ -758,7 +750,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Upload/import/live attributes filters', function () {
|
describe('Upload/import/live attributes filters', function () {
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
await servers[0].config.enableLive({ transcoding: false, allowReplay: false })
|
await servers[0].config.enableLive({ transcoding: false, allowReplay: false })
|
||||||
await servers[0].config.enableVideoImports()
|
await servers[0].config.enableVideoImports()
|
||||||
|
@ -827,13 +818,11 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Stats filters', function () {
|
describe('Stats filters', function () {
|
||||||
|
|
||||||
it('Should run filter:api.server.stats.get.result', async function () {
|
it('Should run filter:api.server.stats.get.result', async function () {
|
||||||
const data = await servers[0].stats.get()
|
const data = await servers[0].stats.get()
|
||||||
|
|
||||||
expect((data as any).customStats).to.equal(14)
|
expect((data as any).customStats).to.equal(14)
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Job queue filters', function () {
|
describe('Job queue filters', function () {
|
||||||
|
@ -883,7 +872,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Transcoding filters', async function () {
|
describe('Transcoding filters', async function () {
|
||||||
|
|
||||||
it('Should run filter:transcoding.auto.resolutions-to-transcode.result', async function () {
|
it('Should run filter:transcoding.auto.resolutions-to-transcode.result', async function () {
|
||||||
const { uuid } = await servers[0].videos.quickUpload({ name: 'transcode-filter' })
|
const { uuid } = await servers[0].videos.quickUpload({ name: 'transcode-filter' })
|
||||||
|
|
||||||
|
@ -896,7 +884,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Video channel filters', async function () {
|
describe('Video channel filters', async function () {
|
||||||
|
|
||||||
it('Should run filter:api.video-channels.list.params', async function () {
|
it('Should run filter:api.video-channels.list.params', async function () {
|
||||||
const { data } = await servers[0].channels.list({ start: 0, count: 0 })
|
const { data } = await servers[0].channels.list({ start: 0, count: 0 })
|
||||||
|
|
||||||
|
@ -918,7 +905,6 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Activity Pub', function () {
|
describe('Activity Pub', function () {
|
||||||
|
|
||||||
it('Should run filter:activity-pub.activity.context.build.result', async function () {
|
it('Should run filter:activity-pub.activity.context.build.result', async function () {
|
||||||
const { body } = await makeActivityPubGetRequest(servers[0].url, '/w/' + videoUUID)
|
const { body } = await makeActivityPubGetRequest(servers[0].url, '/w/' + videoUUID)
|
||||||
expect(body.type).to.equal('Video')
|
expect(body.type).to.equal('Video')
|
||||||
|
|
|
@ -91,7 +91,9 @@ const playerKeys = {
|
||||||
'Content warning': 'Content warning',
|
'Content warning': 'Content warning',
|
||||||
'Violence': 'Violence',
|
'Violence': 'Violence',
|
||||||
'Shocking Content': 'Shocking Content',
|
'Shocking Content': 'Shocking Content',
|
||||||
'Explicit Sex': 'Explicit Sex'
|
'Explicit Sex': 'Explicit Sex',
|
||||||
|
'Upload speed:': 'Upload speed:',
|
||||||
|
'Download speed:': 'Download speed:'
|
||||||
}
|
}
|
||||||
Object.assign(playerKeys, videojs)
|
Object.assign(playerKeys, videojs)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@peertube/peertube-core-utils'
|
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@peertube/peertube-core-utils'
|
||||||
import { HttpStatusCode } from '@peertube/peertube-models'
|
import { HttpStatusCode } from '@peertube/peertube-models'
|
||||||
import { currentDir, root } from '@peertube/peertube-node-utils'
|
import { currentDir, root } from '@peertube/peertube-node-utils'
|
||||||
|
import { toCompleteUUID } from '@server/helpers/custom-validators/misc.js'
|
||||||
import { logger } from '@server/helpers/logger.js'
|
import { logger } from '@server/helpers/logger.js'
|
||||||
import { CONFIG } from '@server/initializers/config.js'
|
import { CONFIG } from '@server/initializers/config.js'
|
||||||
import { Hooks } from '@server/lib/plugins/hooks.js'
|
import { Hooks } from '@server/lib/plugins/hooks.js'
|
||||||
|
@ -120,6 +121,8 @@ function serveServerTranslations (req: express.Request, res: express.Response) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateVideoEmbedHtmlPage (req: express.Request, res: express.Response) {
|
async function generateVideoEmbedHtmlPage (req: express.Request, res: express.Response) {
|
||||||
|
req.params.id = toCompleteUUID(req.params.id)
|
||||||
|
|
||||||
const allowParameters = { req }
|
const allowParameters = { req }
|
||||||
|
|
||||||
const allowedResult = await Hooks.wrapFun(
|
const allowedResult = await Hooks.wrapFun(
|
||||||
|
@ -140,6 +143,8 @@ async function generateVideoEmbedHtmlPage (req: express.Request, res: express.Re
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateVideoPlaylistEmbedHtmlPage (req: express.Request, res: express.Response) {
|
async function generateVideoPlaylistEmbedHtmlPage (req: express.Request, res: express.Response) {
|
||||||
|
req.params.id = toCompleteUUID(req.params.id)
|
||||||
|
|
||||||
const allowParameters = { req }
|
const allowParameters = { req }
|
||||||
|
|
||||||
const allowedResult = await Hooks.wrapFun(
|
const allowedResult = await Hooks.wrapFun(
|
||||||
|
@ -167,12 +172,16 @@ async function generateWatchHtmlPage (req: express.Request, res: express.Respons
|
||||||
const threadIdIndex = videoId.indexOf(';threadId')
|
const threadIdIndex = videoId.indexOf(';threadId')
|
||||||
if (threadIdIndex !== -1) videoId = videoId.substring(0, threadIdIndex)
|
if (threadIdIndex !== -1) videoId = videoId.substring(0, threadIdIndex)
|
||||||
|
|
||||||
|
videoId = toCompleteUUID(videoId)
|
||||||
|
|
||||||
const html = await ClientHtml.getWatchHTMLPage(videoId, req, res)
|
const html = await ClientHtml.getWatchHTMLPage(videoId, req, res)
|
||||||
|
|
||||||
return sendHTML(html, res, true)
|
return sendHTML(html, res, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateWatchPlaylistHtmlPage (req: express.Request, res: express.Response) {
|
async function generateWatchPlaylistHtmlPage (req: express.Request, res: express.Response) {
|
||||||
|
req.params.id = toCompleteUUID(req.params.id)
|
||||||
|
|
||||||
const html = await ClientHtml.getWatchPlaylistHTMLPage(req.params.id + '', req, res)
|
const html = await ClientHtml.getWatchPlaylistHTMLPage(req.params.id + '', req, res)
|
||||||
|
|
||||||
return sendHTML(html, res, true)
|
return sendHTML(html, res, true)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'multer'
|
import { isShortUUID, shortToUUID } from '@peertube/peertube-node-utils'
|
||||||
import { UploadFilesForCheck } from 'express'
|
import { UploadFilesForCheck } from 'express'
|
||||||
|
import 'multer'
|
||||||
import { sep } from 'path'
|
import { sep } from 'path'
|
||||||
import validator from 'validator'
|
import validator from 'validator'
|
||||||
import { isShortUUID, shortToUUID } from '@peertube/peertube-node-utils'
|
|
||||||
|
|
||||||
export function exists (value: any) {
|
export function exists (value: any) {
|
||||||
return value !== undefined && value !== null
|
return value !== undefined && value !== null
|
||||||
|
|
|
@ -18,22 +18,22 @@ class ClientHtml {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
static getWatchHTMLPage (videoIdArg: string, req: express.Request, res: express.Response) {
|
static getWatchHTMLPage (videoId: string, req: express.Request, res: express.Response) {
|
||||||
return VideoHtml.getWatchVideoHTML(videoIdArg, req, res)
|
return VideoHtml.getWatchVideoHTML(videoId, req, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
static getVideoEmbedHTML (videoIdArg: string) {
|
static getVideoEmbedHTML (videoId: string) {
|
||||||
return VideoHtml.getEmbedVideoHTML(videoIdArg)
|
return VideoHtml.getEmbedVideoHTML(videoId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
static getWatchPlaylistHTMLPage (videoPlaylistIdArg: string, req: express.Request, res: express.Response) {
|
static getWatchPlaylistHTMLPage (videoPlaylistId: string, req: express.Request, res: express.Response) {
|
||||||
return PlaylistHtml.getWatchPlaylistHTML(videoPlaylistIdArg, req, res)
|
return PlaylistHtml.getWatchPlaylistHTML(videoPlaylistId, req, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
static getVideoPlaylistEmbedHTML (playlistIdArg: string) {
|
static getVideoPlaylistEmbedHTML (playlistId: string) {
|
||||||
return PlaylistHtml.getEmbedPlaylistHTML(playlistIdArg)
|
return PlaylistHtml.getEmbedPlaylistHTML(playlistId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { addQueryParams, escapeHTML, getDefaultRSSFeeds } from '@peertube/peertube-core-utils'
|
import { addQueryParams, escapeHTML, getDefaultRSSFeeds } from '@peertube/peertube-core-utils'
|
||||||
import { HttpStatusCode, VideoPlaylistPrivacy } from '@peertube/peertube-models'
|
import { HttpStatusCode, VideoPlaylistPrivacy } from '@peertube/peertube-models'
|
||||||
import { toCompleteUUID } from '@server/helpers/custom-validators/misc.js'
|
|
||||||
import { Memoize } from '@server/helpers/memoize.js'
|
import { Memoize } from '@server/helpers/memoize.js'
|
||||||
import { VideoPlaylistModel } from '@server/models/video/video-playlist.js'
|
import { VideoPlaylistModel } from '@server/models/video/video-playlist.js'
|
||||||
import { MVideoPlaylist, MVideoPlaylistFull } from '@server/types/models/index.js'
|
import { MVideoPlaylist, MVideoPlaylistFull } from '@server/types/models/index.js'
|
||||||
|
@ -13,9 +12,7 @@ import { PageHtml } from './page-html.js'
|
||||||
import { TagsHtml } from './tags-html.js'
|
import { TagsHtml } from './tags-html.js'
|
||||||
|
|
||||||
export class PlaylistHtml {
|
export class PlaylistHtml {
|
||||||
static async getWatchPlaylistHTML (videoPlaylistIdArg: string, req: express.Request, res: express.Response) {
|
static async getWatchPlaylistHTML (videoPlaylistId: string, req: express.Request, res: express.Response) {
|
||||||
const videoPlaylistId = toCompleteUUID(videoPlaylistIdArg)
|
|
||||||
|
|
||||||
// Let Angular application handle errors
|
// Let Angular application handle errors
|
||||||
if (!validator.default.isInt(videoPlaylistId) && !validator.default.isUUID(videoPlaylistId, 4)) {
|
if (!validator.default.isInt(videoPlaylistId) && !validator.default.isUUID(videoPlaylistId, 4)) {
|
||||||
res.status(HttpStatusCode.NOT_FOUND_404)
|
res.status(HttpStatusCode.NOT_FOUND_404)
|
||||||
|
@ -46,9 +43,7 @@ export class PlaylistHtml {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Memoize({ maxAge: MEMOIZE_TTL.EMBED_HTML })
|
@Memoize({ maxAge: MEMOIZE_TTL.EMBED_HTML })
|
||||||
static async getEmbedPlaylistHTML (playlistIdArg: string) {
|
static async getEmbedPlaylistHTML (playlistId: string) {
|
||||||
const playlistId = toCompleteUUID(playlistIdArg)
|
|
||||||
|
|
||||||
const playlistPromise: Promise<MVideoPlaylistFull> = validator.default.isInt(playlistId) || validator.default.isUUID(playlistId, 4)
|
const playlistPromise: Promise<MVideoPlaylistFull> = validator.default.isInt(playlistId) || validator.default.isUUID(playlistId, 4)
|
||||||
? VideoPlaylistModel.loadWithAccountAndChannel(playlistId, null)
|
? VideoPlaylistModel.loadWithAccountAndChannel(playlistId, null)
|
||||||
: Promise.resolve(undefined)
|
: Promise.resolve(undefined)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { addQueryParams, escapeHTML, getVideoWatchRSSFeeds } from '@peertube/peertube-core-utils'
|
import { addQueryParams, escapeHTML, getVideoWatchRSSFeeds } from '@peertube/peertube-core-utils'
|
||||||
import { HttpStatusCode, VideoPrivacy } from '@peertube/peertube-models'
|
import { HttpStatusCode, VideoPrivacy } from '@peertube/peertube-models'
|
||||||
import { toCompleteUUID } from '@server/helpers/custom-validators/misc.js'
|
|
||||||
import { Memoize } from '@server/helpers/memoize.js'
|
import { Memoize } from '@server/helpers/memoize.js'
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import validator from 'validator'
|
import validator from 'validator'
|
||||||
|
@ -15,9 +14,7 @@ import { PageHtml } from './page-html.js'
|
||||||
import { TagsHtml } from './tags-html.js'
|
import { TagsHtml } from './tags-html.js'
|
||||||
|
|
||||||
export class VideoHtml {
|
export class VideoHtml {
|
||||||
static async getWatchVideoHTML (videoIdArg: string, req: express.Request, res: express.Response) {
|
static async getWatchVideoHTML (videoId: string, req: express.Request, res: express.Response) {
|
||||||
const videoId = toCompleteUUID(videoIdArg)
|
|
||||||
|
|
||||||
// Let Angular application handle errors
|
// Let Angular application handle errors
|
||||||
if (!validator.default.isInt(videoId) && !validator.default.isUUID(videoId, 4)) {
|
if (!validator.default.isInt(videoId) && !validator.default.isUUID(videoId, 4)) {
|
||||||
res.status(HttpStatusCode.NOT_FOUND_404)
|
res.status(HttpStatusCode.NOT_FOUND_404)
|
||||||
|
@ -47,9 +44,7 @@ export class VideoHtml {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Memoize({ maxAge: MEMOIZE_TTL.EMBED_HTML })
|
@Memoize({ maxAge: MEMOIZE_TTL.EMBED_HTML })
|
||||||
static async getEmbedVideoHTML (videoIdArg: string) {
|
static async getEmbedVideoHTML (videoId: string) {
|
||||||
const videoId = toCompleteUUID(videoIdArg)
|
|
||||||
|
|
||||||
const videoPromise: Promise<MVideoThumbnailBlacklist> = validator.default.isInt(videoId) || validator.default.isUUID(videoId, 4)
|
const videoPromise: Promise<MVideoThumbnailBlacklist> = validator.default.isInt(videoId) || validator.default.isUUID(videoId, 4)
|
||||||
? VideoModel.loadWithBlacklist(videoId)
|
? VideoModel.loadWithBlacklist(videoId)
|
||||||
: Promise.resolve(undefined)
|
: Promise.resolve(undefined)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue