this.loadRouteParams()
this.loadRouteQuery()
- this.initHotkeys()
-
this.theaterEnabled = getStoredTheater()
this.hooks.runAction('action:video-watch.init', 'video-watch')
if (res === false) return this.location.back()
}
+ this.buildHotkeysHelp(video)
+
this.buildPlayer({ urlOptions, loggedInOrAnonymousUser, forceAutoplay })
.catch(err => logger.error('Cannot build the player', err))
this.video.viewers = newViewers
}
- private initHotkeys () {
+ private buildHotkeysHelp (video: Video) {
+ if (this.hotkeys.length !== 0) {
+ this.hotkeysService.remove(this.hotkeys)
+ }
+
this.hotkeys = [
// These hotkeys are managed by the player
new Hotkey('f', e => e, undefined, $localize`Enter/exit fullscreen`),
new Hotkey('space', e => e, undefined, $localize`Play/Pause the video`),
new Hotkey('m', e => e, undefined, $localize`Mute/unmute the video`),
- new Hotkey('0-9', e => e, undefined, $localize`Skip to a percentage of the video: 0 is 0% and 9 is 90%`),
-
new Hotkey('up', e => e, undefined, $localize`Increase the volume`),
new Hotkey('down', e => e, undefined, $localize`Decrease the volume`),
- new Hotkey('right', e => e, undefined, $localize`Seek the video forward`),
- new Hotkey('left', e => e, undefined, $localize`Seek the video backward`),
-
- new Hotkey('>', e => e, undefined, $localize`Increase playback rate`),
- new Hotkey('<', e => e, undefined, $localize`Decrease playback rate`),
-
- new Hotkey(',', e => e, undefined, $localize`Navigate in the video to the previous frame`),
- new Hotkey('.', e => e, undefined, $localize`Navigate in the video to the next frame`),
-
new Hotkey('t', e => {
this.theaterEnabled = !this.theaterEnabled
return false
}, undefined, $localize`Toggle theater mode`)
]
+ if (!video.isLive) {
+ this.hotkeys = this.hotkeys.concat([
+ // These hotkeys are also managed by the player but only for VOD
+
+ new Hotkey('0-9', e => e, undefined, $localize`Skip to a percentage of the video: 0 is 0% and 9 is 90%`),
+
+ new Hotkey('right', e => e, undefined, $localize`Seek the video forward`),
+ new Hotkey('left', e => e, undefined, $localize`Seek the video backward`),
+
+ new Hotkey('>', e => e, undefined, $localize`Increase playback rate`),
+ new Hotkey('<', e => e, undefined, $localize`Decrease playback rate`),
+
+ new Hotkey(',', e => e, undefined, $localize`Navigate in the video to the previous frame`),
+ new Hotkey('.', e => e, undefined, $localize`Navigate in the video to the next frame`)
+ ])
+ }
+
if (this.isUserLoggedIn()) {
this.hotkeys = this.hotkeys.concat([
new Hotkey('shift+s', () => {
const Plugin = videojs.getPlugin('plugin')
+export type HotkeysOptions = {
+ isLive: boolean
+}
+
class PeerTubeHotkeysPlugin extends Plugin {
private static readonly VOLUME_STEP = 0.1
private static readonly SEEK_STEP = 5
private readonly handlers: KeyHandler[]
- constructor (player: videojs.Player, options: videojs.PlayerOptions) {
+ private readonly isLive: boolean
+
+ constructor (player: videojs.Player, options: videojs.PlayerOptions & HotkeysOptions) {
super(player, options)
+ this.isLive = options.isLive
+
this.handlers = this.buildHandlers()
this.handleKeyFunction = (event: KeyboardEvent) => this.onKeyDown(event)
}
},
- // Rewind
- {
- accept: e => this.isNaked(e, 'ArrowLeft') || this.isNaked(e, 'MediaRewind'),
- cb: e => {
- e.preventDefault()
-
- const target = Math.max(0, this.player.currentTime() - PeerTubeHotkeysPlugin.SEEK_STEP)
- this.player.currentTime(target)
- }
- },
-
- // Forward
- {
- accept: e => this.isNaked(e, 'ArrowRight') || this.isNaked(e, 'MediaForward'),
- cb: e => {
- e.preventDefault()
-
- const target = Math.min(this.player.duration(), this.player.currentTime() + PeerTubeHotkeysPlugin.SEEK_STEP)
- this.player.currentTime(target)
- }
- },
-
// Fullscreen
{
// f key or Ctrl + Enter
{
accept: e => e.key === '>',
cb: () => {
+ if (this.isLive) return
+
const target = Math.min(this.player.playbackRate() + 0.1, 5)
this.player.playbackRate(parseFloat(target.toFixed(2)))
{
accept: e => e.key === '<',
cb: () => {
+ if (this.isLive) return
+
const target = Math.max(this.player.playbackRate() - 0.1, 0.10)
this.player.playbackRate(parseFloat(target.toFixed(2)))
{
accept: e => e.key === ',',
cb: () => {
+ if (this.isLive) return
+
this.player.pause()
// Calculate movement distance (assuming 30 fps)
{
accept: e => e.key === '.',
cb: () => {
+ if (this.isLive) return
+
this.player.pause()
// Calculate movement distance (assuming 30 fps)
}
]
+ if (this.isLive) return handlers
+
+ return handlers.concat(this.buildVODHandlers())
+ }
+
+ private buildVODHandlers () {
+ const handlers: KeyHandler[] = [
+ // Rewind
+ {
+ accept: e => this.isNaked(e, 'ArrowLeft') || this.isNaked(e, 'MediaRewind'),
+ cb: e => {
+ if (this.isLive) return
+
+ e.preventDefault()
+
+ const target = Math.max(0, this.player.currentTime() - PeerTubeHotkeysPlugin.SEEK_STEP)
+ this.player.currentTime(target)
+ }
+ },
+
+ // Forward
+ {
+ accept: e => this.isNaked(e, 'ArrowRight') || this.isNaked(e, 'MediaForward'),
+ cb: e => {
+ if (this.isLive) return
+
+ e.preventDefault()
+
+ const target = Math.min(this.player.duration(), this.player.currentTime() + PeerTubeHotkeysPlugin.SEEK_STEP)
+ this.player.currentTime(target)
+ }
+ }
+ ]
+
// 0-9 key handlers
for (let i = 0; i < 10; i++) {
handlers.push({
accept: e => this.isNakedOrShift(e, i + ''),
cb: e => {
+ if (this.isLive) return
+
e.preventDefault()
this.player.currentTime(this.player.duration() * i * 0.1)