X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=client%2Fsrc%2Fassets%2Fplayer%2Fmobile%2Fpeertube-mobile-plugin.ts;h=3c0365e5b2c6ea03be73692f9d0ef3795613d6ef;hb=2dd0a8a8fd2fc85180fa3b45c5a6a56d07320ed3;hp=2ce6b4b334f1bba9fd236024d3aae99a3ce5d3f1;hpb=e98ef69d1c8d4e39e45a52b04b3abf5fd1af3b2c;p=github%2FChocobozzz%2FPeerTube.git diff --git a/client/src/assets/player/mobile/peertube-mobile-plugin.ts b/client/src/assets/player/mobile/peertube-mobile-plugin.ts index 2ce6b4b33..3c0365e5b 100644 --- a/client/src/assets/player/mobile/peertube-mobile-plugin.ts +++ b/client/src/assets/player/mobile/peertube-mobile-plugin.ts @@ -1,18 +1,43 @@ -import './peertube-mobile-buttons' +import { PeerTubeMobileButtons } from './peertube-mobile-buttons' import videojs from 'video.js' +import debug from 'debug' + +const logger = debug('peertube:player:mobile') const Plugin = videojs.getPlugin('plugin') class PeerTubeMobilePlugin extends Plugin { + private static readonly DOUBLE_TAP_DELAY_MS = 250 + private static readonly SET_CURRENT_TIME_DELAY = 1000 + + private peerTubeMobileButtons: PeerTubeMobileButtons + + private seekAmount = 0 + + private lastTapEvent: TouchEvent + private tapTimeout: NodeJS.Timeout + private newActiveState: boolean + + private setCurrentTimeTimeout: NodeJS.Timeout constructor (player: videojs.Player, options: videojs.PlayerOptions) { super(player, options) - player.addChild('PeerTubeMobileButtons') + this.peerTubeMobileButtons = player.addChild('PeerTubeMobileButtons') as PeerTubeMobileButtons if (videojs.browser.IS_ANDROID && screen.orientation) { this.handleFullscreenRotation() } + + if (!this.player.options_.userActions) this.player.options_.userActions = {}; + + // FIXME: typings + (this.player.options_.userActions as any).click = false + this.player.options_.userActions.doubleClick = false + + this.player.one('play', () => { + this.initTouchStartEvents() + }) } private handleFullscreenRotation () { @@ -27,6 +52,92 @@ class PeerTubeMobilePlugin extends Plugin { private isPortraitVideo () { return this.player.videoWidth() < this.player.videoHeight() } + + private initTouchStartEvents () { + this.player.on('touchstart', (event: TouchEvent) => { + event.stopPropagation() + + if (this.tapTimeout) { + clearTimeout(this.tapTimeout) + this.tapTimeout = undefined + } + + if (this.lastTapEvent && event.timeStamp - this.lastTapEvent.timeStamp < PeerTubeMobilePlugin.DOUBLE_TAP_DELAY_MS) { + logger('Detected double tap') + + this.lastTapEvent = undefined + this.onDoubleTap(event) + return + } + + this.newActiveState = !this.player.userActive() + + this.tapTimeout = setTimeout(() => { + logger('No double tap detected, set user active state to %s.', this.newActiveState) + + this.player.userActive(this.newActiveState) + }, PeerTubeMobilePlugin.DOUBLE_TAP_DELAY_MS) + + this.lastTapEvent = event + }) + } + + private onDoubleTap (event: TouchEvent) { + const playerWidth = this.player.currentWidth() + + const rect = this.findPlayerTarget((event.target as HTMLElement)).getBoundingClientRect() + const offsetX = event.targetTouches[0].pageX - rect.left + + logger('Calculating double tap zone (player width: %d, offset X: %d)', playerWidth, offsetX) + + if (offsetX > 0.66 * playerWidth) { + if (this.seekAmount < 0) this.seekAmount = 0 + + this.seekAmount += 10 + + logger('Will forward %d seconds', this.seekAmount) + } else if (offsetX < 0.33 * playerWidth) { + if (this.seekAmount > 0) this.seekAmount = 0 + + this.seekAmount -= 10 + logger('Will rewind %d seconds', this.seekAmount) + } + + this.peerTubeMobileButtons.displayFastSeek(this.seekAmount) + + this.scheduleSetCurrentTime() + + } + + private findPlayerTarget (target: HTMLElement): HTMLElement { + if (target.classList.contains('video-js')) return target + + return this.findPlayerTarget(target.parentElement) + } + + private scheduleSetCurrentTime () { + this.player.pause() + this.player.addClass('vjs-fast-seeking') + + if (this.setCurrentTimeTimeout) clearTimeout(this.setCurrentTimeTimeout) + + this.setCurrentTimeTimeout = setTimeout(() => { + let newTime = this.player.currentTime() + this.seekAmount + this.seekAmount = 0 + + newTime = Math.max(0, newTime) + newTime = Math.min(this.player.duration(), newTime) + + this.player.currentTime(newTime) + this.seekAmount = 0 + this.peerTubeMobileButtons.displayFastSeek(0) + + this.player.removeClass('vjs-fast-seeking') + this.player.userActive(false) + + this.player.play() + }, PeerTubeMobilePlugin.SET_CURRENT_TIME_DELAY) + } } videojs.registerPlugin('peertubeMobile', PeerTubeMobilePlugin)