1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge pull request #6070 from dmitrylyzo/fix-hotkeys

Make hotkeys strict and prevent default actions for handled ones
This commit is contained in:
Bill Thornton 2024-09-20 14:47:33 -04:00 committed by GitHub
commit 37c8370d57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 108 additions and 42 deletions

View file

@ -1195,9 +1195,13 @@ export default function (view) {
function onKeyDown(e) { function onKeyDown(e) {
clickedElement = e.target; clickedElement = e.target;
const key = keyboardnavigation.getKeyName(e);
const isKeyModified = e.ctrlKey || e.altKey || e.metaKey; const isKeyModified = e.ctrlKey || e.altKey || e.metaKey;
// Skip modified keys
if (isKeyModified) return;
const key = keyboardnavigation.getKeyName(e);
const btnPlayPause = osdBottomElement.querySelector('.btnPause'); const btnPlayPause = osdBottomElement.querySelector('.btnPause');
if (e.keyCode === 32) { if (e.keyCode === 32) {
@ -1219,8 +1223,10 @@ export default function (view) {
switch (key) { switch (key) {
case 'ArrowLeft': case 'ArrowLeft':
case 'ArrowRight': case 'ArrowRight':
if (!e.shiftKey) {
showOsd(nowPlayingPositionSlider); showOsd(nowPlayingPositionSlider);
nowPlayingPositionSlider.dispatchEvent(new KeyboardEvent(e.type, e)); nowPlayingPositionSlider.dispatchEvent(new KeyboardEvent(e.type, e));
}
return; return;
case 'Enter': case 'Enter':
playbackManager.playPause(currentPlayer); playbackManager.playPause(currentPlayer);
@ -1230,7 +1236,7 @@ export default function (view) {
} }
if (layoutManager.tv && keyboardnavigation.isNavigationKey(key)) { if (layoutManager.tv && keyboardnavigation.isNavigationKey(key)) {
showOsd(); if (!e.shiftKey) showOsd();
return; return;
} }
@ -1248,50 +1254,71 @@ export default function (view) {
break; break;
case 'k': case 'k':
case 'K': case 'K':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.playPause(currentPlayer); playbackManager.playPause(currentPlayer);
showOsd(btnPlayPause); showOsd(btnPlayPause);
}
break; break;
case 'ArrowUp': case 'ArrowUp':
case 'Up': case 'Up':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.volumeUp(currentPlayer); playbackManager.volumeUp(currentPlayer);
}
break; break;
case 'ArrowDown': case 'ArrowDown':
case 'Down': case 'Down':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.volumeDown(currentPlayer); playbackManager.volumeDown(currentPlayer);
}
break; break;
case 'l': case 'l':
case 'L': case 'L':
case 'ArrowRight': case 'ArrowRight':
case 'Right': case 'Right':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.fastForward(currentPlayer); playbackManager.fastForward(currentPlayer);
showOsd(btnFastForward); showOsd(btnFastForward);
}
break; break;
case 'j': case 'j':
case 'J': case 'J':
case 'ArrowLeft': case 'ArrowLeft':
case 'Left': case 'Left':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.rewind(currentPlayer); playbackManager.rewind(currentPlayer);
showOsd(btnRewind); showOsd(btnRewind);
}
break; break;
case 'f': case 'f':
case 'F': case 'F':
if (!e.ctrlKey && !e.metaKey) { if (!e.shiftKey) {
e.preventDefault();
playbackManager.toggleFullscreen(currentPlayer); playbackManager.toggleFullscreen(currentPlayer);
} }
break; break;
case 'm': case 'm':
case 'M': case 'M':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.toggleMute(currentPlayer); playbackManager.toggleMute(currentPlayer);
}
break; break;
case 'p': case 'p':
case 'P': case 'P':
if (e.shiftKey) { if (e.shiftKey) {
e.preventDefault();
playbackManager.previousTrack(currentPlayer); playbackManager.previousTrack(currentPlayer);
} }
break; break;
case 'n': case 'n':
case 'N': case 'N':
if (e.shiftKey) { if (e.shiftKey) {
e.preventDefault();
playbackManager.nextTrack(currentPlayer); playbackManager.nextTrack(currentPlayer);
} }
break; break;
@ -1314,10 +1341,16 @@ export default function (view) {
} }
break; break;
case 'Home': case 'Home':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.seekPercent(0, currentPlayer); playbackManager.seekPercent(0, currentPlayer);
}
break; break;
case 'End': case 'End':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.seekPercent(100, currentPlayer); playbackManager.seekPercent(100, currentPlayer);
}
break; break;
case '0': case '0':
case '1': case '1':
@ -1328,32 +1361,45 @@ export default function (view) {
case '6': case '6':
case '7': case '7':
case '8': case '8':
case '9': { case '9': { // no Shift
if (!isKeyModified) { e.preventDefault();
const percent = parseInt(key, 10) * 10; const percent = parseInt(key, 10) * 10;
playbackManager.seekPercent(percent, currentPlayer); playbackManager.seekPercent(percent, currentPlayer);
}
break; break;
} }
case '>': case '>': // Shift+.
e.preventDefault();
playbackManager.increasePlaybackRate(currentPlayer); playbackManager.increasePlaybackRate(currentPlayer);
break; break;
case '<': case '<': // Shift+,
e.preventDefault();
playbackManager.decreasePlaybackRate(currentPlayer); playbackManager.decreasePlaybackRate(currentPlayer);
break; break;
case 'PageUp': case 'PageUp':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.nextChapter(currentPlayer); playbackManager.nextChapter(currentPlayer);
}
break; break;
case 'PageDown': case 'PageDown':
if (!e.shiftKey) {
e.preventDefault();
playbackManager.previousChapter(currentPlayer); playbackManager.previousChapter(currentPlayer);
}
break; break;
case 'g': case 'g':
case 'G': case 'G':
if (!e.shiftKey) {
e.preventDefault();
subtitleSyncOverlay?.decrementOffset(); subtitleSyncOverlay?.decrementOffset();
}
break; break;
case 'h': case 'h':
case 'H': case 'H':
if (!e.shiftKey) {
e.preventDefault();
subtitleSyncOverlay?.incrementOffset(); subtitleSyncOverlay?.incrementOffset();
}
break; break;
} }
} }

View file

@ -45,7 +45,7 @@ export class BookPlayer {
this.decreaseFontSize = this.decreaseFontSize.bind(this); this.decreaseFontSize = this.decreaseFontSize.bind(this);
this.previous = this.previous.bind(this); this.previous = this.previous.bind(this);
this.next = this.next.bind(this); this.next = this.next.bind(this);
this.onWindowKeyUp = this.onWindowKeyUp.bind(this); this.onWindowKeyDown = this.onWindowKeyDown.bind(this);
this.addSwipeGestures = this.addSwipeGestures.bind(this); this.addSwipeGestures = this.addSwipeGestures.bind(this);
} }
@ -130,7 +130,10 @@ export class BookPlayer {
return true; return true;
} }
onWindowKeyUp(e) { onWindowKeyDown(e) {
// Skip modified keys
if (e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) return;
const key = keyboardnavigation.getKeyName(e); const key = keyboardnavigation.getKeyName(e);
if (!this.loaded) return; if (!this.loaded) return;
@ -138,14 +141,17 @@ export class BookPlayer {
case 'l': case 'l':
case 'ArrowRight': case 'ArrowRight':
case 'Right': case 'Right':
e.preventDefault();
this.next(); this.next();
break; break;
case 'j': case 'j':
case 'ArrowLeft': case 'ArrowLeft':
case 'Left': case 'Left':
e.preventDefault();
this.previous(); this.previous();
break; break;
case 'Escape': case 'Escape':
e.preventDefault();
if (this.tocElement) { if (this.tocElement) {
// Close table of contents on ESC if it is open // Close table of contents on ESC if it is open
this.tocElement.destroy(); this.tocElement.destroy();
@ -184,8 +190,8 @@ export class BookPlayer {
bindEvents() { bindEvents() {
this.bindMediaElementEvents(); this.bindMediaElementEvents();
document.addEventListener('keyup', this.onWindowKeyUp); document.addEventListener('keydown', this.onWindowKeyDown);
this.rendition?.on('keyup', this.onWindowKeyUp); this.rendition?.on('keydown', this.onWindowKeyDown);
if (browser.safari) { if (browser.safari) {
const player = document.getElementById('bookPlayerContainer'); const player = document.getElementById('bookPlayerContainer');
@ -214,8 +220,8 @@ export class BookPlayer {
this.unbindMediaElementEvents(); this.unbindMediaElementEvents();
} }
document.removeEventListener('keyup', this.onWindowKeyUp); document.removeEventListener('keydown', this.onWindowKeyDown);
this.rendition?.off('keyup', this.onWindowKeyUp); this.rendition?.off('keydown', this.onWindowKeyDown);
if (!browser.safari) { if (!browser.safari) {
this.rendition?.off('rendered', (e, i) => this.addSwipeGestures(i.document.documentElement)); this.rendition?.off('rendered', (e, i) => this.addSwipeGestures(i.document.documentElement));

View file

@ -23,7 +23,7 @@ export class ComicsPlayer {
this.imageMap = new Map(); this.imageMap = new Map();
this.onDialogClosed = this.onDialogClosed.bind(this); this.onDialogClosed = this.onDialogClosed.bind(this);
this.onWindowKeyUp = this.onWindowKeyUp.bind(this); this.onWindowKeyDown = this.onWindowKeyDown.bind(this);
} }
play(options) { play(options) {
@ -177,9 +177,13 @@ export class ComicsPlayer {
this.swiperInstance.update(); this.swiperInstance.update();
} }
onWindowKeyUp(e) { onWindowKeyDown(e) {
// Skip modified keys
if (e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) return;
const key = keyboardnavigation.getKeyName(e); const key = keyboardnavigation.getKeyName(e);
if (key === 'Escape') { if (key === 'Escape') {
e.preventDefault();
this.stop(); this.stop();
} }
} }
@ -196,7 +200,7 @@ export class ComicsPlayer {
bindEvents() { bindEvents() {
this.bindMediaElementEvents(); this.bindMediaElementEvents();
document.addEventListener('keyup', this.onWindowKeyUp); document.addEventListener('keydown', this.onWindowKeyDown);
} }
unbindMediaElementEvents() { unbindMediaElementEvents() {
@ -211,7 +215,7 @@ export class ComicsPlayer {
unbindEvents() { unbindEvents() {
this.unbindMediaElementEvents(); this.unbindMediaElementEvents();
document.removeEventListener('keyup', this.onWindowKeyUp); document.removeEventListener('keydown', this.onWindowKeyDown);
} }
createMediaElement() { createMediaElement() {

View file

@ -18,7 +18,7 @@ export class PdfPlayer {
this.priority = 1; this.priority = 1;
this.onDialogClosed = this.onDialogClosed.bind(this); this.onDialogClosed = this.onDialogClosed.bind(this);
this.onWindowKeyUp = this.onWindowKeyUp.bind(this); this.onWindowKeyDown = this.onWindowKeyDown.bind(this);
this.onTouchStart = this.onTouchStart.bind(this); this.onTouchStart = this.onTouchStart.bind(this);
} }
@ -88,22 +88,29 @@ export class PdfPlayer {
return true; return true;
} }
onWindowKeyUp(e) { onWindowKeyDown(e) {
if (!this.loaded) return;
// Skip modified keys
if (e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) return;
const key = keyboardnavigation.getKeyName(e); const key = keyboardnavigation.getKeyName(e);
if (!this.loaded) return;
switch (key) { switch (key) {
case 'l': case 'l':
case 'ArrowRight': case 'ArrowRight':
case 'Right': case 'Right':
e.preventDefault();
this.next(); this.next();
break; break;
case 'j': case 'j':
case 'ArrowLeft': case 'ArrowLeft':
case 'Left': case 'Left':
e.preventDefault();
this.previous(); this.previous();
break; break;
case 'Escape': case 'Escape':
e.preventDefault();
this.stop(); this.stop();
break; break;
} }
@ -132,7 +139,7 @@ export class PdfPlayer {
bindEvents() { bindEvents() {
this.bindMediaElementEvents(); this.bindMediaElementEvents();
document.addEventListener('keyup', this.onWindowKeyUp); document.addEventListener('keydown', this.onWindowKeyDown);
document.addEventListener('touchstart', this.onTouchStart); document.addEventListener('touchstart', this.onTouchStart);
} }
@ -148,7 +155,7 @@ export class PdfPlayer {
this.unbindMediaElementEvents(); this.unbindMediaElementEvents();
} }
document.removeEventListener('keyup', this.onWindowKeyUp); document.removeEventListener('keydown', this.onWindowKeyDown);
document.removeEventListener('touchstart', this.onTouchStart); document.removeEventListener('touchstart', this.onTouchStart);
} }

View file

@ -125,6 +125,9 @@ export function isInteractiveElement(element) {
export function enable() { export function enable() {
const hasMediaSession = 'mediaSession' in navigator; const hasMediaSession = 'mediaSession' in navigator;
window.addEventListener('keydown', function (e) { window.addEventListener('keydown', function (e) {
// Skip modified keys
if (e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) return;
const key = getKeyName(e); const key = getKeyName(e);
// Ignore navigation keys for non-TV // Ignore navigation keys for non-TV