diff options
author | Chocobozzz <me@florianbigard.com> | 2022-03-14 14:28:20 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2022-03-14 14:36:35 +0100 |
commit | 57d6503286b114fee61b5e4725825e2490dcac29 (patch) | |
tree | 2d3d23f697b2986d7e41bb443754394296b66ec3 /client/src/assets/player/mobile | |
parent | 9597920ee3d4ac99803e7107983ddf98a9dfb3c4 (diff) | |
download | PeerTube-57d6503286b114fee61b5e4725825e2490dcac29.tar.gz PeerTube-57d6503286b114fee61b5e4725825e2490dcac29.tar.zst PeerTube-57d6503286b114fee61b5e4725825e2490dcac29.zip |
Reorganize player files
Diffstat (limited to 'client/src/assets/player/mobile')
-rw-r--r-- | client/src/assets/player/mobile/peertube-mobile-buttons.ts | 94 | ||||
-rw-r--r-- | client/src/assets/player/mobile/peertube-mobile-plugin.ts | 155 |
2 files changed, 0 insertions, 249 deletions
diff --git a/client/src/assets/player/mobile/peertube-mobile-buttons.ts b/client/src/assets/player/mobile/peertube-mobile-buttons.ts deleted file mode 100644 index 09cb98f2e..000000000 --- a/client/src/assets/player/mobile/peertube-mobile-buttons.ts +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | import videojs from 'video.js' | ||
2 | |||
3 | const Component = videojs.getComponent('Component') | ||
4 | class PeerTubeMobileButtons extends Component { | ||
5 | |||
6 | private rewind: Element | ||
7 | private forward: Element | ||
8 | private rewindText: Element | ||
9 | private forwardText: Element | ||
10 | |||
11 | createEl () { | ||
12 | const container = super.createEl('div', { | ||
13 | className: 'vjs-mobile-buttons-overlay' | ||
14 | }) as HTMLDivElement | ||
15 | |||
16 | const mainButton = super.createEl('div', { | ||
17 | className: 'main-button' | ||
18 | }) as HTMLDivElement | ||
19 | |||
20 | mainButton.addEventListener('touchstart', e => { | ||
21 | e.stopPropagation() | ||
22 | |||
23 | if (this.player_.paused() || this.player_.ended()) { | ||
24 | this.player_.play() | ||
25 | return | ||
26 | } | ||
27 | |||
28 | this.player_.pause() | ||
29 | }) | ||
30 | |||
31 | this.rewind = super.createEl('div', { className: 'rewind-button vjs-hidden' }) | ||
32 | this.forward = super.createEl('div', { className: 'forward-button vjs-hidden' }) | ||
33 | |||
34 | for (let i = 0; i < 3; i++) { | ||
35 | this.rewind.appendChild(super.createEl('span', { className: 'icon' })) | ||
36 | this.forward.appendChild(super.createEl('span', { className: 'icon' })) | ||
37 | } | ||
38 | |||
39 | this.rewindText = this.rewind.appendChild(super.createEl('div', { className: 'text' })) | ||
40 | this.forwardText = this.forward.appendChild(super.createEl('div', { className: 'text' })) | ||
41 | |||
42 | container.appendChild(this.rewind) | ||
43 | container.appendChild(mainButton) | ||
44 | container.appendChild(this.forward) | ||
45 | |||
46 | return container | ||
47 | } | ||
48 | |||
49 | displayFastSeek (amount: number) { | ||
50 | if (amount === 0) { | ||
51 | this.hideRewind() | ||
52 | this.hideForward() | ||
53 | return | ||
54 | } | ||
55 | |||
56 | if (amount > 0) { | ||
57 | this.hideRewind() | ||
58 | this.displayForward(amount) | ||
59 | return | ||
60 | } | ||
61 | |||
62 | if (amount < 0) { | ||
63 | this.hideForward() | ||
64 | this.displayRewind(amount) | ||
65 | return | ||
66 | } | ||
67 | } | ||
68 | |||
69 | private hideRewind () { | ||
70 | this.rewind.classList.add('vjs-hidden') | ||
71 | this.rewindText.textContent = '' | ||
72 | } | ||
73 | |||
74 | private displayRewind (amount: number) { | ||
75 | this.rewind.classList.remove('vjs-hidden') | ||
76 | this.rewindText.textContent = this.player().localize('{1} seconds', [ amount + '' ]) | ||
77 | } | ||
78 | |||
79 | private hideForward () { | ||
80 | this.forward.classList.add('vjs-hidden') | ||
81 | this.forwardText.textContent = '' | ||
82 | } | ||
83 | |||
84 | private displayForward (amount: number) { | ||
85 | this.forward.classList.remove('vjs-hidden') | ||
86 | this.forwardText.textContent = this.player().localize('{1} seconds', [ amount + '' ]) | ||
87 | } | ||
88 | } | ||
89 | |||
90 | videojs.registerComponent('PeerTubeMobileButtons', PeerTubeMobileButtons) | ||
91 | |||
92 | export { | ||
93 | PeerTubeMobileButtons | ||
94 | } | ||
diff --git a/client/src/assets/player/mobile/peertube-mobile-plugin.ts b/client/src/assets/player/mobile/peertube-mobile-plugin.ts deleted file mode 100644 index 91dda7f94..000000000 --- a/client/src/assets/player/mobile/peertube-mobile-plugin.ts +++ /dev/null | |||
@@ -1,155 +0,0 @@ | |||
1 | import { PeerTubeMobileButtons } from './peertube-mobile-buttons' | ||
2 | import videojs from 'video.js' | ||
3 | import debug from 'debug' | ||
4 | |||
5 | const logger = debug('peertube:player:mobile') | ||
6 | |||
7 | const Plugin = videojs.getPlugin('plugin') | ||
8 | |||
9 | class PeerTubeMobilePlugin extends Plugin { | ||
10 | private static readonly DOUBLE_TAP_DELAY_MS = 250 | ||
11 | private static readonly SET_CURRENT_TIME_DELAY = 1000 | ||
12 | |||
13 | private peerTubeMobileButtons: PeerTubeMobileButtons | ||
14 | |||
15 | private seekAmount = 0 | ||
16 | |||
17 | private lastTapEvent: TouchEvent | ||
18 | private tapTimeout: ReturnType<typeof setTimeout> | ||
19 | private newActiveState: boolean | ||
20 | |||
21 | private setCurrentTimeTimeout: ReturnType<typeof setTimeout> | ||
22 | |||
23 | constructor (player: videojs.Player, options: videojs.PlayerOptions) { | ||
24 | super(player, options) | ||
25 | |||
26 | this.peerTubeMobileButtons = player.addChild('PeerTubeMobileButtons', { reportTouchActivity: false }) as PeerTubeMobileButtons | ||
27 | |||
28 | if (videojs.browser.IS_ANDROID && screen.orientation) { | ||
29 | this.handleFullscreenRotation() | ||
30 | } | ||
31 | |||
32 | if (!this.player.options_.userActions) this.player.options_.userActions = {}; | ||
33 | |||
34 | // FIXME: typings | ||
35 | (this.player.options_.userActions as any).click = false | ||
36 | this.player.options_.userActions.doubleClick = false | ||
37 | |||
38 | this.player.one('play', () => { | ||
39 | this.initTouchStartEvents() | ||
40 | }) | ||
41 | } | ||
42 | |||
43 | private handleFullscreenRotation () { | ||
44 | this.player.on('fullscreenchange', () => { | ||
45 | if (!this.player.isFullscreen() || this.isPortraitVideo()) return | ||
46 | |||
47 | screen.orientation.lock('landscape') | ||
48 | .catch(err => console.error('Cannot lock screen to landscape.', err)) | ||
49 | }) | ||
50 | } | ||
51 | |||
52 | private isPortraitVideo () { | ||
53 | return this.player.videoWidth() < this.player.videoHeight() | ||
54 | } | ||
55 | |||
56 | private initTouchStartEvents () { | ||
57 | const handleTouchStart = (event: TouchEvent) => { | ||
58 | if (this.tapTimeout) { | ||
59 | clearTimeout(this.tapTimeout) | ||
60 | this.tapTimeout = undefined | ||
61 | } | ||
62 | |||
63 | if (this.lastTapEvent && event.timeStamp - this.lastTapEvent.timeStamp < PeerTubeMobilePlugin.DOUBLE_TAP_DELAY_MS) { | ||
64 | logger('Detected double tap') | ||
65 | |||
66 | this.lastTapEvent = undefined | ||
67 | this.onDoubleTap(event) | ||
68 | return | ||
69 | } | ||
70 | |||
71 | this.newActiveState = !this.player.userActive() | ||
72 | |||
73 | this.tapTimeout = setTimeout(() => { | ||
74 | logger('No double tap detected, set user active state to %s.', this.newActiveState) | ||
75 | |||
76 | this.player.userActive(this.newActiveState) | ||
77 | }, PeerTubeMobilePlugin.DOUBLE_TAP_DELAY_MS) | ||
78 | |||
79 | this.lastTapEvent = event | ||
80 | } | ||
81 | |||
82 | this.player.on('touchstart', (event: TouchEvent) => { | ||
83 | // Only enable user active on player touch, we listen event on peertube mobile buttons to disable it | ||
84 | if (this.player.userActive()) return | ||
85 | |||
86 | handleTouchStart(event) | ||
87 | }) | ||
88 | |||
89 | this.peerTubeMobileButtons.el().addEventListener('touchstart', (event: TouchEvent) => { | ||
90 | // Prevent mousemove/click events firing on the player, that conflict with our user active logic | ||
91 | event.preventDefault() | ||
92 | |||
93 | handleTouchStart(event) | ||
94 | }, { passive: false }) | ||
95 | } | ||
96 | |||
97 | private onDoubleTap (event: TouchEvent) { | ||
98 | const playerWidth = this.player.currentWidth() | ||
99 | |||
100 | const rect = this.findPlayerTarget((event.target as HTMLElement)).getBoundingClientRect() | ||
101 | const offsetX = event.targetTouches[0].pageX - rect.left | ||
102 | |||
103 | logger('Calculating double tap zone (player width: %d, offset X: %d)', playerWidth, offsetX) | ||
104 | |||
105 | if (offsetX > 0.66 * playerWidth) { | ||
106 | if (this.seekAmount < 0) this.seekAmount = 0 | ||
107 | |||
108 | this.seekAmount += 10 | ||
109 | |||
110 | logger('Will forward %d seconds', this.seekAmount) | ||
111 | } else if (offsetX < 0.33 * playerWidth) { | ||
112 | if (this.seekAmount > 0) this.seekAmount = 0 | ||
113 | |||
114 | this.seekAmount -= 10 | ||
115 | logger('Will rewind %d seconds', this.seekAmount) | ||
116 | } | ||
117 | |||
118 | this.peerTubeMobileButtons.displayFastSeek(this.seekAmount) | ||
119 | |||
120 | this.scheduleSetCurrentTime() | ||
121 | } | ||
122 | |||
123 | private findPlayerTarget (target: HTMLElement): HTMLElement { | ||
124 | if (target.classList.contains('video-js')) return target | ||
125 | |||
126 | return this.findPlayerTarget(target.parentElement) | ||
127 | } | ||
128 | |||
129 | private scheduleSetCurrentTime () { | ||
130 | this.player.pause() | ||
131 | this.player.addClass('vjs-fast-seeking') | ||
132 | |||
133 | if (this.setCurrentTimeTimeout) clearTimeout(this.setCurrentTimeTimeout) | ||
134 | |||
135 | this.setCurrentTimeTimeout = setTimeout(() => { | ||
136 | let newTime = this.player.currentTime() + this.seekAmount | ||
137 | this.seekAmount = 0 | ||
138 | |||
139 | newTime = Math.max(0, newTime) | ||
140 | newTime = Math.min(this.player.duration(), newTime) | ||
141 | |||
142 | this.player.currentTime(newTime) | ||
143 | this.seekAmount = 0 | ||
144 | this.peerTubeMobileButtons.displayFastSeek(0) | ||
145 | |||
146 | this.player.removeClass('vjs-fast-seeking') | ||
147 | this.player.userActive(false) | ||
148 | |||
149 | this.player.play() | ||
150 | }, PeerTubeMobilePlugin.SET_CURRENT_TIME_DELAY) | ||
151 | } | ||
152 | } | ||
153 | |||
154 | videojs.registerPlugin('peertubeMobile', PeerTubeMobilePlugin) | ||
155 | export { PeerTubeMobilePlugin } | ||