Add caption button to player control bar
This commit is contained in:
parent
7b86b9b458
commit
c97b8fd2ea
|
@ -55,6 +55,8 @@ function getAverageBandwidthInStore () {
|
|||
return undefined
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function saveLastSubtitle (language: string) {
|
||||
return setLocalStorage('last-subtitle', language)
|
||||
}
|
||||
|
@ -63,6 +65,16 @@ function getStoredLastSubtitle () {
|
|||
return getLocalStorage('last-subtitle')
|
||||
}
|
||||
|
||||
function savePreferredSubtitle (language: string) {
|
||||
return setLocalStorage('preferred-subtitle', language)
|
||||
}
|
||||
|
||||
function getStoredPreferredSubtitle () {
|
||||
return getLocalStorage('preferred-subtitle')
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function saveVideoWatchHistory (videoUUID: string, duration: number) {
|
||||
return setLocalStorage(`video-watch-history`, JSON.stringify({
|
||||
...getStoredVideoWatchHistory(),
|
||||
|
@ -128,7 +140,9 @@ export {
|
|||
getStoredLastSubtitle,
|
||||
saveVideoWatchHistory,
|
||||
getStoredVideoWatchHistory,
|
||||
cleanupVideoWatch
|
||||
cleanupVideoWatch,
|
||||
savePreferredSubtitle,
|
||||
getStoredPreferredSubtitle
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -6,6 +6,7 @@ import './shared/stats/stats-plugin'
|
|||
import './shared/bezels/bezels-plugin'
|
||||
import './shared/peertube/peertube-plugin'
|
||||
import './shared/resolutions/peertube-resolutions-plugin'
|
||||
import './shared/control-bar/caption-toggle-button'
|
||||
import './shared/control-bar/storyboard-plugin'
|
||||
import './shared/control-bar/chapters-plugin'
|
||||
import './shared/control-bar/time-tooltip'
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
import videojs from 'video.js'
|
||||
import { TheaterButtonOptions } from '../../types'
|
||||
import { getStoredPreferredSubtitle } from '../../peertube-player-local-storage'
|
||||
|
||||
const Button = videojs.getComponent('Button')
|
||||
class CaptionToggleButton extends Button {
|
||||
|
||||
constructor (player: videojs.Player, options: TheaterButtonOptions & videojs.ComponentOptions) {
|
||||
super(player, options)
|
||||
|
||||
player.on('texttrackchange', () => this.update())
|
||||
}
|
||||
|
||||
buildCSSClass () {
|
||||
// Inherits vjs-captions-button for the icon
|
||||
return `vjs-caption-toggle-control vjs-captions-button ${super.buildCSSClass()}`
|
||||
}
|
||||
|
||||
handleClick (event: any) {
|
||||
super.handleClick(event)
|
||||
|
||||
const toEnable = this.getShowing()
|
||||
? undefined
|
||||
: this.getCaptionToEnable()?.id
|
||||
|
||||
for (const track of this.player_.textTracks().tracks_) {
|
||||
if (toEnable && track.id === toEnable) track.mode = 'showing'
|
||||
else track.mode = 'disabled'
|
||||
}
|
||||
}
|
||||
|
||||
private update () {
|
||||
if (this.getShowing()) {
|
||||
this.controlText('Disable subtitles')
|
||||
this.addClass('enabled')
|
||||
return
|
||||
}
|
||||
|
||||
this.controlText(this.player_.localize('Enable {1} subtitle', [ this.getCaptionToEnable()?.label ]))
|
||||
this.removeClass('enabled')
|
||||
}
|
||||
|
||||
private getShowing () {
|
||||
return this.listCaptions().find(t => t.mode === 'showing')
|
||||
}
|
||||
|
||||
private getCaptionToEnable () {
|
||||
const captionToEnable = getStoredPreferredSubtitle() || this.listCaptions()[0]?.id
|
||||
const captions = this.listCaptions()
|
||||
|
||||
return captions.find(t => t.id === captionToEnable) || captions[0]
|
||||
}
|
||||
|
||||
private listCaptions () {
|
||||
return this.player_.textTracks().tracks_.filter(t => t.kind === 'captions')
|
||||
}
|
||||
}
|
||||
|
||||
videojs.registerComponent('CaptionToggleButton', CaptionToggleButton)
|
|
@ -1,3 +1,4 @@
|
|||
export * from './caption-toggle-button'
|
||||
export * from './chapters-plugin'
|
||||
export * from './next-previous-video-button'
|
||||
export * from './p2p-info-button'
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
getStoredVolume,
|
||||
saveLastSubtitle,
|
||||
saveMuteInStore,
|
||||
savePreferredSubtitle,
|
||||
saveVideoWatchHistory,
|
||||
saveVolumeInStore
|
||||
} from '../../peertube-player-local-storage'
|
||||
|
@ -113,6 +114,7 @@ class PeerTubePlugin extends Plugin {
|
|||
|
||||
this.currentSubtitle = showing.language
|
||||
saveLastSubtitle(showing.language)
|
||||
savePreferredSubtitle(showing.language)
|
||||
})
|
||||
|
||||
this.player.on('video-change', () => {
|
||||
|
@ -382,6 +384,8 @@ class PeerTubePlugin extends Plugin {
|
|||
|
||||
this.player.tech(true).clearTracks('text')
|
||||
|
||||
this.player.removeClass('vjs-has-captions')
|
||||
|
||||
for (const caption of this.options.videoCaptions()) {
|
||||
this.player.addRemoteTextTrack({
|
||||
kind: 'captions',
|
||||
|
@ -391,6 +395,8 @@ class PeerTubePlugin extends Plugin {
|
|||
src: caption.src,
|
||||
default: this.currentSubtitle === caption.language
|
||||
}, true)
|
||||
|
||||
this.player.addClass('vjs-has-captions')
|
||||
}
|
||||
|
||||
this.player.trigger('captions-changed')
|
||||
|
|
|
@ -34,9 +34,12 @@ export class ControlBarOptionsBuilder {
|
|||
...this.getProgressControl(),
|
||||
|
||||
p2PInfoButton: {},
|
||||
|
||||
muteToggle: {},
|
||||
volumeControl: {},
|
||||
|
||||
captionToggleButton: {},
|
||||
|
||||
...this.getSettingsButton(),
|
||||
|
||||
...this.getPeerTubeLinkButton(),
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
.vjs-fullscreen-control,
|
||||
.vjs-peertube-link,
|
||||
.vjs-theater-control,
|
||||
.vjs-caption-toggle-control,
|
||||
.vjs-settings {
|
||||
color: pvar(--embedForegroundColor) !important;
|
||||
|
||||
|
@ -297,7 +298,7 @@
|
|||
.vjs-volume-control {
|
||||
@include margin(0, 5px, 0, 5px);
|
||||
|
||||
width: $control-bar-icon-size;
|
||||
width: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
@ -369,7 +370,7 @@
|
|||
@include disable-outline;
|
||||
|
||||
cursor: pointer;
|
||||
width: $control-bar-button-width;
|
||||
width: $control-bar-button-width - 5px;
|
||||
|
||||
.vjs-icon-placeholder {
|
||||
display: inline-block;
|
||||
|
@ -418,6 +419,31 @@
|
|||
}
|
||||
}
|
||||
|
||||
.vjs-caption-toggle-control {
|
||||
// Redefined if the player parent has captions class
|
||||
display: none;
|
||||
width: $control-bar-button-width - 4px;
|
||||
|
||||
&,
|
||||
&:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&.enabled,
|
||||
&.enabled:hover {
|
||||
opacity: $primary-foreground-opacity;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
> .vjs-icon-placeholder::before {
|
||||
font-size: 2.3em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
}
|
||||
|
||||
.vjs-fullscreen-control {
|
||||
@include disable-outline;
|
||||
|
||||
|
@ -456,6 +482,10 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.vjs-mute-control {
|
||||
@include margin(0, 5px, 0, 5px);
|
||||
}
|
||||
|
||||
.vjs-peertube {
|
||||
padding: 0 !important;
|
||||
|
||||
|
@ -519,3 +549,7 @@
|
|||
height: 100%;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.vjs-peertube-skin.vjs-has-captions .vjs-caption-toggle-control {
|
||||
display: block !important;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,9 @@ const playerKeys = {
|
|||
'Cancel': 'Cancel',
|
||||
'Up Next': 'Up Next',
|
||||
'Autoplay is suspended': 'Autoplay is suspended',
|
||||
'{1} (from edge: {2})': '{1} (from edge: {2})'
|
||||
'{1} (from edge: {2})': '{1} (from edge: {2})',
|
||||
'Disable subtitles': 'Disable subtitles',
|
||||
'Enable {1} subtitle': 'Enable {1} subtitle'
|
||||
}
|
||||
Object.assign(playerKeys, videojs)
|
||||
|
||||
|
|
Loading…
Reference in New Issue