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

Merge pull request #702 from dmitrylyzo/playback_remote

Add playback control from TV remote
This commit is contained in:
dkanada 2020-01-27 22:34:59 +09:00 committed by GitHub
commit 7af58a03dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 169 additions and 31 deletions

View file

@ -1,36 +1,133 @@
define(['inputManager', 'focusManager'], function(inputManager, focusManager) {
'use strict';
define(["inputManager", "layoutManager"], function (inputManager, layoutManager) {
"use strict";
console.log("keyboardnavigation");
/**
* Key name mapping.
*/
// Add more to support old browsers
var KeyNames = {
13: "Enter",
19: "Pause",
27: "Escape",
32: "Space",
37: "ArrowLeft",
38: "ArrowUp",
39: "ArrowRight",
40: "ArrowDown",
// MediaRewind (Tizen/WebOS)
412: "MediaRewind",
// MediaStop (Tizen/WebOS)
413: "MediaStop",
// MediaPlay (Tizen/WebOS)
415: "MediaPlay",
// MediaFastForward (Tizen/WebOS)
417: "MediaFastForward",
// Back (WebOS)
461: "Back",
// Back (Tizen)
10009: "Back",
// MediaTrackPrevious (Tizen)
10232: "MediaTrackPrevious",
// MediaTrackNext (Tizen)
10233: "MediaTrackNext",
// MediaPlayPause (Tizen)
10252: "MediaPlayPause"
};
var hasFieldKey = false;
try {
hasFieldKey = "key" in new KeyboardEvent("keydown");
} catch (e) {
console.log("error checking 'key' field");
}
if (!hasFieldKey) {
// Add [a..z]
for (var i = 65; i <= 90; i++) {
KeyNames[i] = String.fromCharCode(i).toLowerCase();
}
}
/**
* Returns key name from event.
*
* @param {KeyboardEvent} keyboard event
* @return {string} key name
*/
function getKeyName(event) {
return KeyNames[event.keyCode] || event.key;
}
function enable() {
document.addEventListener('keydown', function(e) {
document.addEventListener("keydown", function (e) {
var capture = true;
switch (e.keyCode) {
case 37: // ArrowLeft
inputManager.handle('left');
switch (getKeyName(e)) {
case "ArrowLeft":
inputManager.handle("left");
break;
case 38: // ArrowUp
inputManager.handle('up');
case "ArrowUp":
inputManager.handle("up");
break;
case 39: // ArrowRight
inputManager.handle('right');
case "ArrowRight":
inputManager.handle("right");
break;
case 40: // ArrowDown
inputManager.handle('down');
case "ArrowDown":
inputManager.handle("down");
break;
case "Back":
inputManager.handle("back");
break;
case "Escape":
if (layoutManager.tv) {
inputManager.handle("back");
} else {
capture = false;
}
break;
case "MediaPlay":
inputManager.handle("play");
break;
case "Pause":
inputManager.handle("pause");
break;
case "MediaPlayPause":
inputManager.handle("playpause");
break;
case "MediaRewind":
inputManager.handle("rewind");
break;
case "MediaFastForward":
inputManager.handle("fastforward");
break;
case "MediaStop":
inputManager.handle("stop");
break;
case "MediaTrackPrevious":
inputManager.handle("previoustrack");
break;
case "MediaTrackNext":
inputManager.handle("nexttrack");
break;
default:
capture = false;
}
if (capture) {
console.log("Disabling default event handling");
e.preventDefault();
}
});
}
return {
enable: enable
enable: enable,
getKeyName: getKeyName
};
});

View file

@ -1,4 +1,4 @@
define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "mediaInfo", "focusManager", "imageLoader", "scrollHelper", "events", "connectionManager", "browser", "globalize", "apphost", "layoutManager", "userSettings", "scrollStyles", "emby-slider", "paper-icon-button-light", "css!assets/css/videoosd"], function (playbackManager, dom, inputManager, datetime, itemHelper, mediaInfo, focusManager, imageLoader, scrollHelper, events, connectionManager, browser, globalize, appHost, layoutManager, userSettings) {
define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "mediaInfo", "focusManager", "imageLoader", "scrollHelper", "events", "connectionManager", "browser", "globalize", "apphost", "layoutManager", "userSettings", "keyboardnavigation", "scrollStyles", "emby-slider", "paper-icon-button-light", "css!assets/css/videoosd"], function (playbackManager, dom, inputManager, datetime, itemHelper, mediaInfo, focusManager, imageLoader, scrollHelper, events, connectionManager, browser, globalize, appHost, layoutManager, userSettings, keyboardnavigation) {
"use strict";
function seriesImageUrl(item, options) {
@ -437,6 +437,11 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med
});
currentVisibleMenu = null;
toggleSubtitleSync("hide");
// Firefox does not blur by itself
if (document.activeElement) {
document.activeElement.blur();
}
}
}
@ -1087,50 +1092,66 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med
*/
var NavigationKeys = ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"];
/**
* Clicked element.
* To skip 'click' handling on Firefox/Edge.
*/
var clickedElement;
function onWindowKeyDown(e) {
clickedElement = e.srcElement;
var key = keyboardnavigation.getKeyName(e);
if (!currentVisibleMenu && 32 === e.keyCode) {
playbackManager.playPause(currentPlayer);
showOsd();
return;
}
if (layoutManager.tv && NavigationKeys.indexOf(e.key) != -1) {
if (layoutManager.tv && NavigationKeys.indexOf(key) != -1) {
showOsd();
return;
}
switch (e.key) {
switch (key) {
case "Enter":
showOsd();
break;
case "Escape":
case "Back":
// Ignore key when some dialog is opened
if (currentVisibleMenu === "osd" && !document.querySelector(".dialogContainer")) {
hideOsd();
e.stopPropagation();
}
break;
case "k":
playbackManager.playPause(currentPlayer);
showOsd();
break;
case "l":
case "ArrowRight":
case "Right":
playbackManager.fastForward(currentPlayer);
showOsd();
break;
case "j":
case "ArrowLeft":
case "Left":
playbackManager.rewind(currentPlayer);
showOsd();
break;
case "f":
if (!e.ctrlKey && !e.metaKey) {
playbackManager.toggleFullscreen(currentPlayer);
showOsd();
}
break;
case "m":
playbackManager.toggleMute(currentPlayer);
showOsd();
break;
case "NavigationLeft":
case "GamepadDPadLeft":
case "GamepadLeftThumbstickLeft":
@ -1140,7 +1161,6 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med
showOsd();
}
break;
case "NavigationRight":
case "GamepadDPadRight":
case "GamepadLeftThumbstickRight":
@ -1152,6 +1172,14 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med
}
}
function onWindowMouseDown(e) {
clickedElement = e.srcElement;
}
function onWindowTouchStart(e) {
clickedElement = e.srcElement;
}
function getImgUrl(item, chapter, index, maxWidth, apiClient) {
if (chapter.ImageTag) {
return apiClient.getScaledImageUrl(item.Id, {
@ -1280,6 +1308,12 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med
showOsd();
inputManager.on(window, onInputCommand);
dom.addEventListener(window, "keydown", onWindowKeyDown, {
capture: true
});
dom.addEventListener(window, window.PointerEvent ? "pointerdown" : "mousedown", onWindowMouseDown, {
passive: true
});
dom.addEventListener(window, "touchstart", onWindowTouchStart, {
passive: true
});
} catch (e) {
@ -1294,6 +1328,12 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med
}
dom.removeEventListener(window, "keydown", onWindowKeyDown, {
capture: true
});
dom.removeEventListener(window, window.PointerEvent ? "pointerdown" : "mousedown", onWindowMouseDown, {
passive: true
});
dom.removeEventListener(window, "touchstart", onWindowTouchStart, {
passive: true
});
stopOsdHideTimer();
@ -1465,7 +1505,10 @@ define(["playbackManager", "dom", "inputManager", "datetime", "itemHelper", "med
playbackManager.previousTrack(currentPlayer);
});
view.querySelector(".btnPause").addEventListener("click", function () {
// Ignore 'click' if another element was originally clicked (Firefox/Edge issue)
if (this.contains(clickedElement)) {
playbackManager.playPause(currentPlayer);
}
});
view.querySelector(".btnNextTrack").addEventListener("click", function () {
playbackManager.nextTrack(currentPlayer);

View file

@ -1,4 +1,4 @@
define(['browser', 'dom', 'layoutManager', 'css!./emby-slider', 'registerElement', 'emby-input'], function (browser, dom, layoutManager) {
define(['browser', 'dom', 'layoutManager', 'keyboardnavigation', 'css!./emby-slider', 'registerElement', 'emby-input'], function (browser, dom, layoutManager, keyboardnavigation) {
'use strict';
var EmbySliderPrototype = Object.create(HTMLInputElement.prototype);
@ -250,7 +250,7 @@ define(['browser', 'dom', 'layoutManager', 'css!./emby-slider', 'registerElement
* Handle KeyDown event
*/
function onKeyDown(e) {
switch (e.key) {
switch (keyboardnavigation.getKeyName(e)) {
case 'ArrowLeft':
case 'Left':
stepKeyboard(this, -this.keyboardStepDown || -1);

View file

@ -22,9 +22,7 @@ define(['playbackManager', 'focusManager', 'appRouter', 'dom'], function (playba
var eventListenerCount = 0;
function on(scope, fn) {
if (eventListenerCount) {
eventListenerCount++;
}
dom.addEventListener(scope, 'command', fn, {});
}