diff --git a/src/controllers/user/controls/index.html b/src/controllers/user/controls/index.html new file mode 100644 index 0000000000..8c54db4bd9 --- /dev/null +++ b/src/controllers/user/controls/index.html @@ -0,0 +1,24 @@ +
+
+
+
+

+ ${Controls} +

+ +
+ +
${EnableGamepadHelp}
+
${LabelPleaseRestart}
+
+
+ + +
+
+
diff --git a/src/controllers/user/controls/index.js b/src/controllers/user/controls/index.js new file mode 100644 index 0000000000..d53cd07738 --- /dev/null +++ b/src/controllers/user/controls/index.js @@ -0,0 +1,28 @@ +import { Events } from 'jellyfin-apiclient'; +import toast from '../../../components/toast/toast'; +import globalize from '../../../scripts/globalize'; +import appSettings from '../../../scripts/settings/appSettings'; + +export default function (view, params) { + function submit(e) { + appSettings.enableGamepad(view.querySelector('.chkEnableGamepad').checked); + + toast(globalize.translate('SettingsSaved')); + + Events.trigger(view, 'saved'); + + if (e) e.preventDefault(); + + return false; + } + + view.addEventListener('viewshow', function () { + view.querySelector('.chkEnableGamepad').checked = appSettings.enableGamepad(); + view.querySelector('form').addEventListener('submit', submit); + view.querySelector('.btnSave').classList.remove('hide'); + + import('../../../components/autoFocuser').then(({default: autoFocuser}) => { + autoFocuser.autoFocus(view); + }); + }); +} diff --git a/src/controllers/user/menu/index.html b/src/controllers/user/menu/index.html index 7af9be4785..2fa5ffe867 100644 --- a/src/controllers/user/menu/index.html +++ b/src/controllers/user/menu/index.html @@ -66,6 +66,15 @@ + + +
+ +
+
${Controls}
+
+
+

${HeaderAdmin}

diff --git a/src/controllers/user/menu/index.js b/src/controllers/user/menu/index.js index 1872b9f018..215573f518 100644 --- a/src/controllers/user/menu/index.js +++ b/src/controllers/user/menu/index.js @@ -28,6 +28,7 @@ export default function (view, params) { page.querySelector('.lnkPlaybackPreferences').setAttribute('href', '#!/mypreferencesplayback.html?userId=' + userId); page.querySelector('.lnkSubtitlePreferences').setAttribute('href', '#!/mypreferencessubtitles.html?userId=' + userId); page.querySelector('.lnkQuickConnectPreferences').setAttribute('href', '#!/mypreferencesquickconnect.html'); + page.querySelector('.lnkControlsPreferences').setAttribute('href', '#!/mypreferencescontrols.html?userId=' + userId); const supportsClientSettings = appHost.supports('clientsettings'); page.querySelector('.clientSettings').classList.toggle('hide', !supportsClientSettings); @@ -35,6 +36,8 @@ export default function (view, params) { const supportsMultiServer = appHost.supports('multiserver'); page.querySelector('.selectServer').classList.toggle('hide', !supportsMultiServer); + page.querySelector('.lnkControlsPreferences').classList.toggle('hide', layoutManager.mobile); + ApiClient.getQuickConnect('Status') .then(status => { if (status !== 'Unavailable') { diff --git a/src/scripts/keyboardNavigation.js b/src/scripts/keyboardNavigation.js index ff011f387c..f175bc2524 100644 --- a/src/scripts/keyboardNavigation.js +++ b/src/scripts/keyboardNavigation.js @@ -5,6 +5,7 @@ import inputManager from './inputManager'; import layoutManager from '../components/layoutManager'; +import appSettings from './settings/appSettings'; /** * Key name mapping. @@ -160,7 +161,7 @@ function attachGamepadScript() { } // No need to check for gamepads manually at load time, the eventhandler will be fired for that -if (navigator.getGamepads) { /* eslint-disable-line compat/compat */ +if (navigator.getGamepads && appSettings.enableGamepad()) { /* eslint-disable-line compat/compat */ window.addEventListener('gamepadconnected', attachGamepadScript); } diff --git a/src/scripts/routes.js b/src/scripts/routes.js index 388c2a83e5..41497be0f7 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -84,6 +84,13 @@ import { appRouter } from '../components/appRouter'; controller: 'user/profile/index' }); + defineRoute({ + alias: '/mypreferencescontrols.html', + path: 'user/controls/index.html', + autoFocus: false, + controller: 'user/controls/index' + }); + defineRoute({ alias: '/mypreferencesdisplay.html', path: 'user/display/index.html', diff --git a/src/scripts/settings/appSettings.js b/src/scripts/settings/appSettings.js index 784df48feb..7b59c35f3c 100644 --- a/src/scripts/settings/appSettings.js +++ b/src/scripts/settings/appSettings.js @@ -18,6 +18,19 @@ class AppSettings { return this.get('enableAutoLogin') !== 'false'; } + /** + * Get or set 'Enable Gamepad' state. + * @param {boolean|undefined} val - Flag to enable 'Enable Gamepad' or undefined. + * @return {boolean} 'Enable Gamepad' state. + */ + enableGamepad(val) { + if (val !== undefined) { + return this.set('enableGamepad', val.toString()); + } + + return this.get('enableGamepad') === 'true'; + } + enableSystemExternalPlayers(val) { if (val !== undefined) { this.set('enableSystemExternalPlayers', val.toString()); diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 0915ec57a0..30eecc707d 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1507,5 +1507,8 @@ "MessagePlaybackError": "There was an error playing this file on your Google Cast receiver.", "EnableEnhancedNvdecDecoder": "Enable enhanced NVDEC decoder", "EnableVppTonemapping": "Enable VPP Tone mapping", - "AllowVppTonemappingHelp": "Full hardware based tone mapping without using OpenCL filter. Currently works only when transcoding videos with embedded HDR10 metadata." + "AllowVppTonemappingHelp": "Full hardware based tone mapping without using OpenCL filter. Currently works only when transcoding videos with embedded HDR10 metadata.", + "Controls": "Controls", + "LabelEnableGamepad": "Enable Gamepad", + "EnableGamepadHelp": "Listen for input from any connected controllers." }