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/hotkeys | |
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/hotkeys')
-rw-r--r-- | client/src/assets/player/hotkeys/peertube-hotkeys-plugin.ts | 196 |
1 files changed, 0 insertions, 196 deletions
diff --git a/client/src/assets/player/hotkeys/peertube-hotkeys-plugin.ts b/client/src/assets/player/hotkeys/peertube-hotkeys-plugin.ts deleted file mode 100644 index 5920450bd..000000000 --- a/client/src/assets/player/hotkeys/peertube-hotkeys-plugin.ts +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | import videojs from 'video.js' | ||
2 | |||
3 | type KeyHandler = { accept: (event: KeyboardEvent) => boolean, cb: (e: KeyboardEvent) => void } | ||
4 | |||
5 | const Plugin = videojs.getPlugin('plugin') | ||
6 | |||
7 | class PeerTubeHotkeysPlugin extends Plugin { | ||
8 | private static readonly VOLUME_STEP = 0.1 | ||
9 | private static readonly SEEK_STEP = 5 | ||
10 | |||
11 | private readonly handleKeyFunction: (event: KeyboardEvent) => void | ||
12 | |||
13 | private readonly handlers: KeyHandler[] | ||
14 | |||
15 | constructor (player: videojs.Player, options: videojs.PlayerOptions) { | ||
16 | super(player, options) | ||
17 | |||
18 | this.handlers = this.buildHandlers() | ||
19 | |||
20 | this.handleKeyFunction = (event: KeyboardEvent) => this.onKeyDown(event) | ||
21 | document.addEventListener('keydown', this.handleKeyFunction) | ||
22 | } | ||
23 | |||
24 | dispose () { | ||
25 | document.removeEventListener('keydown', this.handleKeyFunction) | ||
26 | } | ||
27 | |||
28 | private onKeyDown (event: KeyboardEvent) { | ||
29 | if (!this.isValidKeyTarget(event.target as HTMLElement)) return | ||
30 | |||
31 | for (const handler of this.handlers) { | ||
32 | if (handler.accept(event)) { | ||
33 | handler.cb(event) | ||
34 | return | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | |||
39 | private buildHandlers () { | ||
40 | const handlers: KeyHandler[] = [ | ||
41 | // Play | ||
42 | { | ||
43 | accept: e => (e.key === ' ' || e.key === 'MediaPlayPause'), | ||
44 | cb: e => { | ||
45 | e.preventDefault() | ||
46 | e.stopPropagation() | ||
47 | |||
48 | if (this.player.paused()) this.player.play() | ||
49 | else this.player.pause() | ||
50 | } | ||
51 | }, | ||
52 | |||
53 | // Increase volume | ||
54 | { | ||
55 | accept: e => this.isNaked(e, 'ArrowUp'), | ||
56 | cb: e => { | ||
57 | e.preventDefault() | ||
58 | this.player.volume(this.player.volume() + PeerTubeHotkeysPlugin.VOLUME_STEP) | ||
59 | } | ||
60 | }, | ||
61 | |||
62 | // Decrease volume | ||
63 | { | ||
64 | accept: e => this.isNaked(e, 'ArrowDown'), | ||
65 | cb: e => { | ||
66 | e.preventDefault() | ||
67 | this.player.volume(this.player.volume() - PeerTubeHotkeysPlugin.VOLUME_STEP) | ||
68 | } | ||
69 | }, | ||
70 | |||
71 | // Rewind | ||
72 | { | ||
73 | accept: e => this.isNaked(e, 'ArrowLeft') || this.isNaked(e, 'MediaRewind'), | ||
74 | cb: e => { | ||
75 | e.preventDefault() | ||
76 | |||
77 | const target = Math.max(0, this.player.currentTime() - PeerTubeHotkeysPlugin.SEEK_STEP) | ||
78 | this.player.currentTime(target) | ||
79 | } | ||
80 | }, | ||
81 | |||
82 | // Forward | ||
83 | { | ||
84 | accept: e => this.isNaked(e, 'ArrowRight') || this.isNaked(e, 'MediaForward'), | ||
85 | cb: e => { | ||
86 | e.preventDefault() | ||
87 | |||
88 | const target = Math.min(this.player.duration(), this.player.currentTime() + PeerTubeHotkeysPlugin.SEEK_STEP) | ||
89 | this.player.currentTime(target) | ||
90 | } | ||
91 | }, | ||
92 | |||
93 | // Fullscreen | ||
94 | { | ||
95 | // f key or Ctrl + Enter | ||
96 | accept: e => this.isNaked(e, 'f') || (!e.altKey && e.ctrlKey && e.key === 'Enter'), | ||
97 | cb: e => { | ||
98 | e.preventDefault() | ||
99 | |||
100 | if (this.player.isFullscreen()) this.player.exitFullscreen() | ||
101 | else this.player.requestFullscreen() | ||
102 | } | ||
103 | }, | ||
104 | |||
105 | // Mute | ||
106 | { | ||
107 | accept: e => this.isNaked(e, 'm'), | ||
108 | cb: e => { | ||
109 | e.preventDefault() | ||
110 | |||
111 | this.player.muted(!this.player.muted()) | ||
112 | } | ||
113 | }, | ||
114 | |||
115 | // Increase playback rate | ||
116 | { | ||
117 | accept: e => e.key === '>', | ||
118 | cb: () => { | ||
119 | const target = Math.min(this.player.playbackRate() + 0.1, 5) | ||
120 | |||
121 | this.player.playbackRate(parseFloat(target.toFixed(2))) | ||
122 | } | ||
123 | }, | ||
124 | |||
125 | // Decrease playback rate | ||
126 | { | ||
127 | accept: e => e.key === '<', | ||
128 | cb: () => { | ||
129 | const target = Math.max(this.player.playbackRate() - 0.1, 0.10) | ||
130 | |||
131 | this.player.playbackRate(parseFloat(target.toFixed(2))) | ||
132 | } | ||
133 | }, | ||
134 | |||
135 | // Previous frame | ||
136 | { | ||
137 | accept: e => e.key === ',', | ||
138 | cb: () => { | ||
139 | this.player.pause() | ||
140 | |||
141 | // Calculate movement distance (assuming 30 fps) | ||
142 | const dist = 1 / 30 | ||
143 | this.player.currentTime(this.player.currentTime() - dist) | ||
144 | } | ||
145 | }, | ||
146 | |||
147 | // Next frame | ||
148 | { | ||
149 | accept: e => e.key === '.', | ||
150 | cb: () => { | ||
151 | this.player.pause() | ||
152 | |||
153 | // Calculate movement distance (assuming 30 fps) | ||
154 | const dist = 1 / 30 | ||
155 | this.player.currentTime(this.player.currentTime() + dist) | ||
156 | } | ||
157 | } | ||
158 | ] | ||
159 | |||
160 | // 0-9 key handlers | ||
161 | for (let i = 0; i < 10; i++) { | ||
162 | handlers.push({ | ||
163 | accept: e => e.key === i + '', | ||
164 | cb: e => { | ||
165 | e.preventDefault() | ||
166 | |||
167 | this.player.currentTime(this.player.duration() * i * 0.1) | ||
168 | } | ||
169 | }) | ||
170 | } | ||
171 | |||
172 | return handlers | ||
173 | } | ||
174 | |||
175 | private isValidKeyTarget (eventEl: HTMLElement) { | ||
176 | const playerEl = this.player.el() | ||
177 | const activeEl = document.activeElement | ||
178 | const currentElTagName = eventEl.tagName.toLowerCase() | ||
179 | |||
180 | return ( | ||
181 | activeEl === playerEl || | ||
182 | activeEl === playerEl.querySelector('.vjs-tech') || | ||
183 | activeEl === playerEl.querySelector('.vjs-control-bar') || | ||
184 | eventEl.id === 'content' || | ||
185 | currentElTagName === 'body' || | ||
186 | currentElTagName === 'video' | ||
187 | ) | ||
188 | } | ||
189 | |||
190 | private isNaked (event: KeyboardEvent, key: string) { | ||
191 | return (!event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey && event.key === key) | ||
192 | } | ||
193 | } | ||
194 | |||
195 | videojs.registerPlugin('peerTubeHotkeysPlugin', PeerTubeHotkeysPlugin) | ||
196 | export { PeerTubeHotkeysPlugin } | ||