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:
commit
37c8370d57
5 changed files with 108 additions and 42 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue