mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-06 03:50:26 +02:00
Improve NSFW warning in player
This commit is contained in:
parent
f2556d80e3
commit
ee96cf3a19
10 changed files with 249 additions and 138 deletions
|
@ -13,6 +13,7 @@ my-select-checkbox {
|
||||||
.playlists {
|
.playlists {
|
||||||
.pt-badge {
|
.pt-badge {
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
|
||||||
@include ellipsis;
|
@include ellipsis;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,9 @@
|
||||||
--header-fg: #{pvar(--fg)};
|
--header-fg: #{pvar(--fg)};
|
||||||
--header-bg: #{pvar(--bg)};
|
--header-bg: #{pvar(--bg)};
|
||||||
|
|
||||||
|
--player-overlay-fg: #{pvar(--fg-400)};
|
||||||
|
--player-overlay-bg: #{pvar(--bg-secondary-400)};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
--tmp-header-height: #{$header-height};
|
--tmp-header-height: #{$header-height};
|
||||||
|
|
|
@ -204,7 +204,9 @@ $variables: (
|
||||||
--alert-primary-bg: var(--alert-primary-bg),
|
--alert-primary-bg: var(--alert-primary-bg),
|
||||||
--alert-primary-border-color: var(--alert-primary-border-color),
|
--alert-primary-border-color: var(--alert-primary-border-color),
|
||||||
--embed-fg: var(--embed-fg),
|
--embed-fg: var(--embed-fg),
|
||||||
--embed-big-play-bg: var(--embed-big-play-bg)
|
--embed-big-play-bg: var(--embed-big-play-bg),
|
||||||
|
--player-overlay-fg: var(--player-overlay-fg),
|
||||||
|
--player-overlay-bg: var(--player-overlay-bg)
|
||||||
);
|
);
|
||||||
|
|
||||||
// SASS type check our CSS variables
|
// SASS type check our CSS variables
|
||||||
|
|
|
@ -20,7 +20,7 @@ import './shared/control-bar/theater-button'
|
||||||
import './shared/control-bar/time-tooltip'
|
import './shared/control-bar/time-tooltip'
|
||||||
import './shared/dock/peertube-dock-component'
|
import './shared/dock/peertube-dock-component'
|
||||||
import './shared/dock/peertube-dock-plugin'
|
import './shared/dock/peertube-dock-plugin'
|
||||||
import './shared/nsfw/peertube-nsfw-component'
|
import './shared/nsfw/peertube-nsfw-info-component'
|
||||||
import './shared/nsfw/peertube-nsfw-plugin'
|
import './shared/nsfw/peertube-nsfw-plugin'
|
||||||
import './shared/hotkeys/peertube-hotkeys-plugin'
|
import './shared/hotkeys/peertube-hotkeys-plugin'
|
||||||
import './shared/metrics/metrics-plugin'
|
import './shared/metrics/metrics-plugin'
|
||||||
|
|
|
@ -1,49 +1,54 @@
|
||||||
@use 'sass:math';
|
@use "sass:math";
|
||||||
@use '_variables' as *;
|
@use "_variables" as *;
|
||||||
@use '_mixins' as *;
|
@use "_mixins" as *;
|
||||||
@use '_icons' as *;
|
@use "_icons" as *;
|
||||||
@use './_player-variables' as *;
|
@use "./_player-variables" as *;
|
||||||
|
|
||||||
.video-js.vjs-peertube-skin {
|
.video-js.vjs-peertube-skin {
|
||||||
--container-margin-x: 20px;
|
--nsfw-info-margin-x: 20px;
|
||||||
--container-margin-y: 20px;
|
--nsfw-info-margin-y: 20px;
|
||||||
|
--nsfw-font-size: 13px;
|
||||||
|
|
||||||
&.vjs-size-570 {
|
&.vjs-size-570 {
|
||||||
--container-margin-x: 10px;
|
--nsfw-info-margin-x: 10px;
|
||||||
--container-margin-y: 10px;
|
--nsfw-info-margin-y: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nsfw-container {
|
button {
|
||||||
font-size: 14px;
|
cursor: pointer;
|
||||||
position: absolute;
|
}
|
||||||
top: var(--container-margin-y);
|
|
||||||
right: var(--container-margin-x);
|
.nsfw-info,
|
||||||
|
.nsfw-details {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
background-color: pvar(--bg-secondary-500);
|
background-color: pvar(--player-overlay-bg);
|
||||||
color: pvar(--fg-400);
|
color: pvar(--player-overlay-fg);
|
||||||
max-width: calc(40% - 2 * var(--container-margin-x));
|
max-width: calc(40% - 2 * var(--nsfw-info-margin-x));
|
||||||
max-height: calc(100% - 2 * var(--container-margin-y));
|
padding: 1rem;
|
||||||
padding: 1rem;;
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// NSFW info
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.nsfw-info {
|
||||||
|
position: absolute;
|
||||||
|
top: var(--nsfw-info-margin-y);
|
||||||
|
right: var(--nsfw-info-margin-x);
|
||||||
|
max-height: calc(100% - 2 * var(--nsfw-info-margin-y));
|
||||||
|
|
||||||
|
font-size: var(--nsfw-font-size);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
.nsfw-title {
|
strong {
|
||||||
font-size: 1.25rem;
|
display: block;
|
||||||
font-weight: $font-bold;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
.nsfw-more-flags,
|
|
||||||
.nsfw-more-summary {
|
|
||||||
margin-top: 0.75rem;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
margin-top: 0.75rem;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color: pvar(--fg-450);
|
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -55,20 +60,63 @@
|
||||||
@include margin-left(5px);
|
@include margin-left(5px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nsfw-more-content {
|
|
||||||
strong {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.peertube-dock {
|
&.peertube-dock {
|
||||||
.nsfw-container {
|
.nsfw-info {
|
||||||
top: unset;
|
top: unset;
|
||||||
bottom: var(--container-margin-y);
|
bottom: var(--nsfw-info-margin-y);
|
||||||
max-width: 90%;
|
max-width: 90%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// NSFW details
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.nsfw-details-container {
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nsfw-details {
|
||||||
|
margin-left: auto;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.nsfw-details-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.5;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nsfw-details-flags + .nsfw-details-summary {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nsfw-details-close {
|
||||||
|
mask-image: url("./svg/x.svg");
|
||||||
|
-webkit-mask-image: url("./svg/x.svg");
|
||||||
|
mask-size: cover;
|
||||||
|
-webkit-mask-size: cover;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: pvar(--player-overlay-fg);
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
@include margin-left(auto);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
import { NSFWFlag } from '@peertube/peertube-models'
|
|
||||||
import videojs from 'video.js'
|
|
||||||
import { type PeerTubeNSFWPluginOptions } from './peertube-nsfw-plugin'
|
|
||||||
|
|
||||||
const Component = videojs.getComponent('Component')
|
|
||||||
|
|
||||||
class PeerTubeNSFWComponent extends Component {
|
|
||||||
declare options_: videojs.ComponentOptions & PeerTubeNSFWPluginOptions
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
||||||
constructor (player: videojs.Player, options: videojs.ComponentOptions & PeerTubeNSFWPluginOptions) {
|
|
||||||
super(player, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
createEl () {
|
|
||||||
const el = super.createEl('div', { className: 'nsfw-container' })
|
|
||||||
|
|
||||||
const title = super.createEl('div', { className: 'nsfw-title' })
|
|
||||||
title.textContent = this.player().localize('Sensitive content')
|
|
||||||
|
|
||||||
const content = super.createEl('div', { className: 'nsfw-content' })
|
|
||||||
content.textContent = this.player().localize('This video contains sensitive content.')
|
|
||||||
|
|
||||||
el.appendChild(title)
|
|
||||||
el.appendChild(content)
|
|
||||||
|
|
||||||
if (this.options_.flags || this.options_.summary) {
|
|
||||||
const moreButton = super.createEl(
|
|
||||||
'button',
|
|
||||||
{ textContent: this.player().localize('Learn more') },
|
|
||||||
{ type: 'button' }
|
|
||||||
) as HTMLButtonElement
|
|
||||||
|
|
||||||
el.appendChild(moreButton)
|
|
||||||
|
|
||||||
moreButton.addEventListener('click', () => {
|
|
||||||
this.appendMoreContent()
|
|
||||||
|
|
||||||
moreButton.style.display = 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return el
|
|
||||||
}
|
|
||||||
|
|
||||||
private appendMoreContent () {
|
|
||||||
const moreContentEl = super.createEl('div', { className: 'nsfw-more-content' })
|
|
||||||
|
|
||||||
if (this.options_.flags) {
|
|
||||||
const moreContentFlags = super.createEl('div', { className: 'nsfw-more-flags' })
|
|
||||||
moreContentFlags.appendChild(super.createEl('strong', { textContent: this.player().localize('Content warning') }))
|
|
||||||
moreContentFlags.appendChild(super.createEl('div', { textContent: this.buildFlagStrings().join(' - ') }))
|
|
||||||
|
|
||||||
moreContentEl.appendChild(moreContentFlags)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.options_.summary) {
|
|
||||||
const moreContentSummary = super.createEl('div', { className: 'nsfw-more-summary' })
|
|
||||||
moreContentSummary.appendChild(super.createEl('strong', { textContent: `Author note` }))
|
|
||||||
moreContentSummary.appendChild(super.createEl('div', { textContent: this.options_.summary }))
|
|
||||||
|
|
||||||
moreContentEl.appendChild(moreContentSummary)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.el().appendChild(moreContentEl)
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildFlagStrings () {
|
|
||||||
const flags = this.options_.flags
|
|
||||||
const flagStrings: string[] = []
|
|
||||||
|
|
||||||
if ((flags & NSFWFlag.VIOLENT) === NSFWFlag.VIOLENT) {
|
|
||||||
flagStrings.push(this.player().localize(`Violence`))
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & NSFWFlag.EXPLICIT_SEX) === NSFWFlag.EXPLICIT_SEX) {
|
|
||||||
flagStrings.push(this.player().localize(`Explicit Sex`))
|
|
||||||
}
|
|
||||||
|
|
||||||
return flagStrings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
videojs.registerComponent('PeerTubeNSFWComponent', PeerTubeNSFWComponent)
|
|
||||||
|
|
||||||
export {
|
|
||||||
PeerTubeNSFWComponent
|
|
||||||
}
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
import { NSFWFlag } from '@peertube/peertube-models'
|
||||||
|
import videojs from 'video.js'
|
||||||
|
import { type PeerTubeNSFWPluginOptions } from './peertube-nsfw-plugin'
|
||||||
|
|
||||||
|
const Component = videojs.getComponent('Component')
|
||||||
|
|
||||||
|
class PeerTubeNSFWDetailsComponent extends Component {
|
||||||
|
declare options_: videojs.ComponentOptions & PeerTubeNSFWPluginOptions
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
constructor (player: videojs.Player, options: videojs.ComponentOptions & PeerTubeNSFWPluginOptions) {
|
||||||
|
super(player, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
createEl () {
|
||||||
|
// Overlay
|
||||||
|
const el = super.createEl('div', { className: 'nsfw-details-container' })
|
||||||
|
|
||||||
|
const nsfwDetails = super.createEl('div', { className: 'nsfw-details' })
|
||||||
|
el.appendChild(nsfwDetails)
|
||||||
|
|
||||||
|
const closeButton = super.createEl('button', {
|
||||||
|
className: 'nsfw-details-close',
|
||||||
|
title: this.player().localize('Close details'),
|
||||||
|
type: 'button'
|
||||||
|
}) as HTMLButtonElement
|
||||||
|
|
||||||
|
closeButton.addEventListener('click', () => {
|
||||||
|
this.trigger('hideDetails')
|
||||||
|
})
|
||||||
|
|
||||||
|
nsfwDetails.appendChild(closeButton)
|
||||||
|
|
||||||
|
const content = super.createEl('div', { className: 'nsfw-details-content' })
|
||||||
|
nsfwDetails.appendChild(content)
|
||||||
|
|
||||||
|
if (this.options_.flags) {
|
||||||
|
const flags = super.createEl('div', { className: 'nsfw-details-flags' })
|
||||||
|
|
||||||
|
const label = super.createEl('strong', { textContent: this.player().localize('This video contains sensitive content, including:') })
|
||||||
|
flags.appendChild(label)
|
||||||
|
|
||||||
|
flags.appendChild(super.createEl('div', { textContent: this.buildFlagStrings().join(' - ') }))
|
||||||
|
|
||||||
|
content.appendChild(flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options_.summary) {
|
||||||
|
const summary = super.createEl('div', { className: 'nsfw-details-summary' })
|
||||||
|
|
||||||
|
const label = super.createEl('strong', { textContent: this.player().localize('Uploader note:') })
|
||||||
|
summary.appendChild(label)
|
||||||
|
|
||||||
|
summary.appendChild(super.createEl('div', { textContent: this.options_.summary }))
|
||||||
|
|
||||||
|
content.appendChild(summary)
|
||||||
|
}
|
||||||
|
|
||||||
|
return el
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildFlagStrings () {
|
||||||
|
const flags = this.options_.flags
|
||||||
|
const flagStrings: string[] = []
|
||||||
|
|
||||||
|
if ((flags & NSFWFlag.VIOLENT) === NSFWFlag.VIOLENT) {
|
||||||
|
flagStrings.push(this.player().localize(`Potentially violent content`))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & NSFWFlag.EXPLICIT_SEX) === NSFWFlag.EXPLICIT_SEX) {
|
||||||
|
flagStrings.push(this.player().localize(`Potentially sexually explicit content`))
|
||||||
|
}
|
||||||
|
|
||||||
|
return flagStrings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
videojs.registerComponent('PeerTubeNSFWDetailsComponent', PeerTubeNSFWDetailsComponent)
|
||||||
|
|
||||||
|
export {
|
||||||
|
PeerTubeNSFWDetailsComponent
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
import videojs from 'video.js'
|
||||||
|
import { type PeerTubeNSFWPluginOptions } from './peertube-nsfw-plugin'
|
||||||
|
|
||||||
|
const Component = videojs.getComponent('Component')
|
||||||
|
|
||||||
|
class PeerTubeNSFWInfoComponent extends Component {
|
||||||
|
declare options_: videojs.ComponentOptions & PeerTubeNSFWPluginOptions
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
constructor (player: videojs.Player, options: videojs.ComponentOptions & PeerTubeNSFWPluginOptions) {
|
||||||
|
super(player, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
createEl () {
|
||||||
|
const el = super.createEl('div', { className: 'nsfw-info' })
|
||||||
|
|
||||||
|
const content = super.createEl('strong')
|
||||||
|
content.textContent = this.player().localize('This video contains sensitive content.')
|
||||||
|
el.appendChild(content)
|
||||||
|
|
||||||
|
if (this.options_.flags || this.options_.summary) {
|
||||||
|
const moreButton = super.createEl(
|
||||||
|
'button',
|
||||||
|
{ textContent: this.player().localize('Learn more') },
|
||||||
|
{ type: 'button' }
|
||||||
|
) as HTMLButtonElement
|
||||||
|
|
||||||
|
el.appendChild(moreButton)
|
||||||
|
|
||||||
|
moreButton.addEventListener('click', () => {
|
||||||
|
this.trigger('showDetails')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return el
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
videojs.registerComponent('PeerTubeNSFWInfoComponent', PeerTubeNSFWInfoComponent)
|
||||||
|
|
||||||
|
export {
|
||||||
|
PeerTubeNSFWInfoComponent
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import videojs from 'video.js'
|
import videojs from 'video.js'
|
||||||
import { PeerTubeNSFWComponent } from './peertube-nsfw-component'
|
import { PeerTubeNSFWInfoComponent } from './peertube-nsfw-info-component'
|
||||||
|
import { PeerTubeNSFWDetailsComponent } from './peertube-nsfw-details-component'
|
||||||
|
|
||||||
const Plugin = videojs.getPlugin('plugin')
|
const Plugin = videojs.getPlugin('plugin')
|
||||||
|
|
||||||
|
@ -9,7 +10,8 @@ export type PeerTubeNSFWPluginOptions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
class PeerTubeNSFWPlugin extends Plugin {
|
class PeerTubeNSFWPlugin extends Plugin {
|
||||||
declare private nsfwComponent: PeerTubeNSFWComponent
|
declare private nsfwInfoComponent: PeerTubeNSFWInfoComponent
|
||||||
|
declare private nsfwDetailsComponent: PeerTubeNSFWDetailsComponent
|
||||||
|
|
||||||
constructor (player: videojs.Player, options: videojs.PlayerOptions & PeerTubeNSFWPluginOptions) {
|
constructor (player: videojs.Player, options: videojs.PlayerOptions & PeerTubeNSFWPluginOptions) {
|
||||||
super(player, options)
|
super(player, options)
|
||||||
|
@ -17,18 +19,33 @@ class PeerTubeNSFWPlugin extends Plugin {
|
||||||
player.ready(() => {
|
player.ready(() => {
|
||||||
player.addClass('peertube-nsfw')
|
player.addClass('peertube-nsfw')
|
||||||
|
|
||||||
this.nsfwComponent = new PeerTubeNSFWComponent(player, options)
|
this.nsfwInfoComponent = new PeerTubeNSFWInfoComponent(player, options)
|
||||||
player.addChild(this.nsfwComponent)
|
player.addChild(this.nsfwInfoComponent)
|
||||||
|
|
||||||
|
this.nsfwDetailsComponent = new PeerTubeNSFWDetailsComponent(player, options)
|
||||||
|
this.nsfwDetailsComponent.hide()
|
||||||
|
player.addChild(this.nsfwDetailsComponent)
|
||||||
|
|
||||||
|
this.nsfwInfoComponent.on('showDetails', () => {
|
||||||
|
this.nsfwDetailsComponent.show()
|
||||||
|
this.nsfwInfoComponent.hide()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.nsfwDetailsComponent.on('hideDetails', () => {
|
||||||
|
this.nsfwInfoComponent.show()
|
||||||
|
this.nsfwDetailsComponent.hide()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
player.one('play', () => {
|
player.one('play', () => {
|
||||||
this.nsfwComponent.hide()
|
this.nsfwInfoComponent.hide()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose () {
|
dispose () {
|
||||||
this.nsfwComponent?.dispose()
|
this.nsfwInfoComponent?.dispose()
|
||||||
this.player.removeChild(this.nsfwComponent)
|
this.player.removeChild(this.nsfwInfoComponent)
|
||||||
|
this.player.removeChild(this.nsfwDetailsComponent)
|
||||||
this.player.removeClass('peertube-nsfw')
|
this.player.removeClass('peertube-nsfw')
|
||||||
|
|
||||||
super.dispose()
|
super.dispose()
|
||||||
|
|
|
@ -87,13 +87,16 @@ const playerKeys = {
|
||||||
'Audio only': 'Audio only',
|
'Audio only': 'Audio only',
|
||||||
'Sensitive content': 'Sensitive content',
|
'Sensitive content': 'Sensitive content',
|
||||||
'This video contains sensitive content.': 'This video contains sensitive content.',
|
'This video contains sensitive content.': 'This video contains sensitive content.',
|
||||||
|
'This video contains sensitive content, including:': 'This video contains sensitive content, including:',
|
||||||
'Learn more': 'Learn more',
|
'Learn more': 'Learn more',
|
||||||
'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:',
|
'Upload speed:': 'Upload speed:',
|
||||||
'Download speed:': 'Download speed:'
|
'Download speed:': 'Download speed:',
|
||||||
|
'Uploader note:': 'Uploader note:',
|
||||||
|
'Close': 'Close'
|
||||||
}
|
}
|
||||||
Object.assign(playerKeys, videojs)
|
Object.assign(playerKeys, videojs)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue