diff --git a/.eslintrc.js b/.eslintrc.js index 7f164227f4..562b457bf7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -72,7 +72,6 @@ module.exports = { 'sonarjs/cognitive-complexity': ['warn'], // TODO: Enable the following rules and fix issues - 'sonarjs/no-collapsible-if': ['off'], 'sonarjs/no-duplicate-string': ['off'], 'sonarjs/no-duplicated-branches': ['off'], 'sonarjs/no-identical-functions': ['off'], diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index 12effcdfc9..d1d061417c 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -18,7 +18,7 @@ jobs: comment-id: ${{ github.event.comment.id }} reactions: '+1' - name: Checkout the latest code - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0 with: token: ${{ secrets.JF_BOT_TOKEN }} fetch-depth: 0 diff --git a/package-lock.json b/package-lock.json index b20ae7206b..a2633a4a5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,8 +66,8 @@ "@types/lodash-es": "4.17.6", "@types/react": "17.0.50", "@types/react-dom": "17.0.17", - "@typescript-eslint/eslint-plugin": "5.38.0", - "@typescript-eslint/parser": "5.38.0", + "@typescript-eslint/eslint-plugin": "5.38.1", + "@typescript-eslint/parser": "5.38.1", "@uupaa/dynamic-import-polyfill": "1.0.2", "autoprefixer": "10.4.12", "babel-loader": "8.2.5", @@ -2972,14 +2972,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.0.tgz", - "integrity": "sha512-GgHi/GNuUbTOeoJiEANi0oI6fF3gBQc3bGFYj40nnAPCbhrtEDf2rjBmefFadweBmO1Du1YovHeDP2h5JLhtTQ==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz", + "integrity": "sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/type-utils": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/type-utils": "5.38.1", + "@typescript-eslint/utils": "5.38.1", "debug": "^4.3.4", "ignore": "^5.2.0", "regexpp": "^3.2.0", @@ -3019,14 +3019,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.0.tgz", - "integrity": "sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.1.tgz", + "integrity": "sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/typescript-estree": "5.38.1", "debug": "^4.3.4" }, "engines": { @@ -3046,13 +3046,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz", - "integrity": "sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz", + "integrity": "sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0" + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/visitor-keys": "5.38.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3063,13 +3063,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.0.tgz", - "integrity": "sha512-iZq5USgybUcj/lfnbuelJ0j3K9dbs1I3RICAJY9NZZpDgBYXmuUlYQGzftpQA9wC8cKgtS6DASTvF3HrXwwozA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz", + "integrity": "sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/typescript-estree": "5.38.1", + "@typescript-eslint/utils": "5.38.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -3090,9 +3090,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.0.tgz", - "integrity": "sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.1.tgz", + "integrity": "sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3103,13 +3103,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz", - "integrity": "sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz", + "integrity": "sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/visitor-keys": "5.38.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3174,15 +3174,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.0.tgz", - "integrity": "sha512-6sdeYaBgk9Fh7N2unEXGz+D+som2QCQGPAf1SxrkEr+Z32gMreQ0rparXTNGRRfYUWk/JzbGdcM8NSSd6oqnTA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.1.tgz", + "integrity": "sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/typescript-estree": "5.38.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -3198,12 +3198,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz", - "integrity": "sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz", + "integrity": "sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", + "@typescript-eslint/types": "5.38.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -20589,14 +20589,14 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.0.tgz", - "integrity": "sha512-GgHi/GNuUbTOeoJiEANi0oI6fF3gBQc3bGFYj40nnAPCbhrtEDf2rjBmefFadweBmO1Du1YovHeDP2h5JLhtTQ==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz", + "integrity": "sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/type-utils": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/type-utils": "5.38.1", + "@typescript-eslint/utils": "5.38.1", "debug": "^4.3.4", "ignore": "^5.2.0", "regexpp": "^3.2.0", @@ -20616,53 +20616,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.0.tgz", - "integrity": "sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.1.tgz", + "integrity": "sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/typescript-estree": "5.38.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz", - "integrity": "sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz", + "integrity": "sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0" + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/visitor-keys": "5.38.1" } }, "@typescript-eslint/type-utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.0.tgz", - "integrity": "sha512-iZq5USgybUcj/lfnbuelJ0j3K9dbs1I3RICAJY9NZZpDgBYXmuUlYQGzftpQA9wC8cKgtS6DASTvF3HrXwwozA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz", + "integrity": "sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/typescript-estree": "5.38.1", + "@typescript-eslint/utils": "5.38.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.0.tgz", - "integrity": "sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.1.tgz", + "integrity": "sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz", - "integrity": "sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz", + "integrity": "sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/visitor-keys": "5.38.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -20702,26 +20702,26 @@ } }, "@typescript-eslint/utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.0.tgz", - "integrity": "sha512-6sdeYaBgk9Fh7N2unEXGz+D+som2QCQGPAf1SxrkEr+Z32gMreQ0rparXTNGRRfYUWk/JzbGdcM8NSSd6oqnTA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.1.tgz", + "integrity": "sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/typescript-estree": "5.38.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/visitor-keys": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz", - "integrity": "sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz", + "integrity": "sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", + "@typescript-eslint/types": "5.38.1", "eslint-visitor-keys": "^3.3.0" }, "dependencies": { diff --git a/package.json b/package.json index 319aca2c94..fb50784f9f 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "@types/lodash-es": "4.17.6", "@types/react": "17.0.50", "@types/react-dom": "17.0.17", - "@typescript-eslint/eslint-plugin": "5.38.0", - "@typescript-eslint/parser": "5.38.0", + "@typescript-eslint/eslint-plugin": "5.38.1", + "@typescript-eslint/parser": "5.38.1", "@uupaa/dynamic-import-polyfill": "1.0.2", "autoprefixer": "10.4.12", "babel-loader": "8.2.5", diff --git a/src/components/appRouter.js b/src/components/appRouter.js index f2bc0e27b0..9bfdc85707 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -87,12 +87,10 @@ class AppRouter { path = path.replace(this.baseUrl(), ''); - if (this.currentRouteInfo && this.currentRouteInfo.path === path) { - // can't use this with home right now due to the back menu - if (this.currentRouteInfo.route.type !== 'home') { - loading.hide(); - return Promise.resolve(); - } + // can't use this with home right now due to the back menu + if (this.currentRouteInfo?.path === path && this.currentRouteInfo.route.type !== 'home') { + loading.hide(); + return Promise.resolve(); } this.promiseShow = new Promise((resolve) => { @@ -351,15 +349,13 @@ class AppRouter { onRequestFail(_e, data) { const apiClient = this; - if (data.status === 403) { - if (data.errorCode === 'ParentalControl') { - const isCurrentAllowed = appRouter.currentRouteInfo ? (appRouter.currentRouteInfo.route.anonymous || appRouter.currentRouteInfo.route.startup) : true; + if (data.status === 403 && data.errorCode === 'ParentalControl') { + const isCurrentAllowed = appRouter.currentRouteInfo ? (appRouter.currentRouteInfo.route.anonymous || appRouter.currentRouteInfo.route.startup) : true; - // Bounce to the login screen, but not if a password entry fails, obviously - if (!isCurrentAllowed) { - appRouter.showForcedLogoutMessage(globalize.translate('AccessRestrictedTryAgainLater')); - appRouter.showLocalLogin(apiClient.serverId()); - } + // Bounce to the login screen, but not if a password entry fails, obviously + if (!isCurrentAllowed) { + appRouter.showForcedLogoutMessage(globalize.translate('AccessRestrictedTryAgainLater')); + appRouter.showLocalLogin(apiClient.serverId()); } } } diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index b5f85c9a57..ebdc250d7a 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -790,10 +790,8 @@ import { appRouter } from '../appRouter'; const showOtherText = isOuterFooter ? !overlayText : overlayText; - if (isOuterFooter && options.cardLayout && layoutManager.mobile) { - if (options.cardFooterAside !== 'none') { - html += ``; - } + if (isOuterFooter && options.cardLayout && layoutManager.mobile && options.cardFooterAside !== 'none') { + html += ``; } const cssClass = options.centerText ? 'cardText cardTextCentered' : 'cardText'; @@ -803,33 +801,31 @@ import { appRouter } from '../appRouter'; const parentTitleUnderneath = item.Type === 'MusicAlbum' || item.Type === 'Audio' || item.Type === 'MusicVideo'; let titleAdded; - if (showOtherText) { - if ((options.showParentTitle || options.showParentTitleOrTitle) && !parentTitleUnderneath) { - if (isOuterFooter && item.Type === 'Episode' && item.SeriesName) { - if (item.SeriesId) { - lines.push(getTextActionButton({ - Id: item.SeriesId, - ServerId: serverId, - Name: item.SeriesName, - Type: 'Series', - IsFolder: true - })); - } else { - lines.push(escapeHtml(item.SeriesName)); + if (showOtherText && (options.showParentTitle || options.showParentTitleOrTitle) && !parentTitleUnderneath) { + if (isOuterFooter && item.Type === 'Episode' && item.SeriesName) { + if (item.SeriesId) { + lines.push(getTextActionButton({ + Id: item.SeriesId, + ServerId: serverId, + Name: item.SeriesName, + Type: 'Series', + IsFolder: true + })); + } else { + lines.push(escapeHtml(item.SeriesName)); + } + } else { + if (isUsingLiveTvNaming(item)) { + lines.push(escapeHtml(item.Name)); + + if (!item.EpisodeTitle && !item.IndexNumber) { + titleAdded = true; } } else { - if (isUsingLiveTvNaming(item)) { - lines.push(escapeHtml(item.Name)); + const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || ''; - if (!item.EpisodeTitle && !item.IndexNumber) { - titleAdded = true; - } - } else { - const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || ''; - - if (parentTitle || showTitle) { - lines.push(escapeHtml(parentTitle)); - } + if (parentTitle || showTitle) { + lines.push(escapeHtml(parentTitle)); } } } @@ -986,10 +982,8 @@ import { appRouter } from '../appRouter'; } } - if (options.showPersonRoleOrType) { - if (item.Role) { - lines.push(globalize.translate('PersonRole', escapeHtml(item.Role))); - } + if (options.showPersonRoleOrType && item.Role) { + lines.push(globalize.translate('PersonRole', escapeHtml(item.Role))); } } @@ -1009,13 +1003,11 @@ import { appRouter } from '../appRouter'; html += progressHtml; } - if (html) { - if (!isOuterFooter || logoUrl || options.cardLayout) { - html = '
' + html; + if (html && (!isOuterFooter || logoUrl || options.cardLayout)) { + html = '
' + html; - //cardFooter - html += '
'; - } + //cardFooter + html += '
'; } return html; diff --git a/src/components/cardbuilder/chaptercardbuilder.js b/src/components/cardbuilder/chaptercardbuilder.js index da8de34f9a..f479fb4c88 100644 --- a/src/components/cardbuilder/chaptercardbuilder.js +++ b/src/components/cardbuilder/chaptercardbuilder.js @@ -34,10 +34,8 @@ import ServerConnections from '../ServerConnections'; let shape = (options.backdropShape || 'backdrop'); - if (videoStream.Width && videoStream.Height) { - if ((videoStream.Width / videoStream.Height) <= 1.2) { - shape = (options.squareShape || 'square'); - } + if (videoStream.Width && videoStream.Height && (videoStream.Width / videoStream.Height) <= 1.2) { + shape = (options.squareShape || 'square'); } className += ` ${shape}Card`; diff --git a/src/components/dialogHelper/dialogHelper.js b/src/components/dialogHelper/dialogHelper.js index 80b269fed5..130a1742cb 100644 --- a/src/components/dialogHelper/dialogHelper.js +++ b/src/components/dialogHelper/dialogHelper.js @@ -57,6 +57,7 @@ import '../../assets/css/scrollstyles.scss'; if ((shouldClose || !isOpened(dlg)) && unlisten) { unlisten(); + unlisten = null; } if (shouldClose) { @@ -64,6 +65,22 @@ import '../../assets/css/scrollstyles.scss'; } } + function finishClose() { + if (unlisten) { + unlisten(); + unlisten = null; + } + + dlg.dispatchEvent(new CustomEvent('close', { + bubbles: false, + cancelable: false + })); + + resolve({ + element: dlg + }); + } + function onBackCommand(e) { if (e.detail.command === 'back') { e.preventDefault(); @@ -79,6 +96,7 @@ import '../../assets/css/scrollstyles.scss'; if (unlisten) { unlisten(); + unlisten = null; } removeBackdrop(dlg); @@ -92,9 +110,13 @@ import '../../assets/css/scrollstyles.scss'; const state = history.location.state || {}; if (state.dialogs?.length > 0) { if (state.dialogs[state.dialogs.length - 1] === hash) { + unlisten = history.listen(finishClose); history.back(); } else if (state.dialogs.includes(hash)) { console.warn('[dialogHelper] dialog "%s" was closed, but is not the last dialog opened', hash); + + unlisten = history.listen(finishClose); + // Remove the closed dialog hash from the history state history.replace( `${history.location.pathname}${history.location.search}`, @@ -123,18 +145,9 @@ import '../../assets/css/scrollstyles.scss'; } } - //resolve(); - // if we just called history.back(), then use a timeout to allow the history events to fire first - setTimeout(() => { - dlg.dispatchEvent(new CustomEvent('close', { - bubbles: false, - cancelable: false - })); - - resolve({ - element: dlg - }); - }, 1); + if (!unlisten) { + finishClose(); + } } dlg.addEventListener('_close', onDialogClosed); diff --git a/src/components/focusManager.js b/src/components/focusManager.js index 0b0ae06211..740ff7c07d 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -384,10 +384,11 @@ import scrollManager from './scrollManager'; // See if there's a focusable container, and if so, send the focus command to that if (activeElement) { const nearestElementFocusableParent = dom.parentWithClass(nearestElement, 'focusable'); - if (nearestElementFocusableParent && nearestElementFocusableParent !== nearestElement) { - if (focusableContainer !== nearestElementFocusableParent) { - nearestElement = nearestElementFocusableParent; - } + if (nearestElementFocusableParent + && nearestElementFocusableParent !== nearestElement + && focusableContainer !== nearestElementFocusableParent + ) { + nearestElement = nearestElementFocusableParent; } } focus(nearestElement); diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index 34c10ffd33..6974f609ef 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -72,26 +72,25 @@ import toast from './toast/toast'; } } - if (item.IsFolder || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') { - if (item.CollectionType !== 'livetv') { - if (options.shuffle !== false) { - commands.push({ - name: globalize.translate('Shuffle'), - id: 'shuffle', - icon: 'shuffle' - }); - } - } + if ((item.IsFolder || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') + && item.CollectionType !== 'livetv' + && options.shuffle !== false + ) { + commands.push({ + name: globalize.translate('Shuffle'), + id: 'shuffle', + icon: 'shuffle' + }); } - if (item.MediaType === 'Audio' || item.Type === 'MusicAlbum' || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') { - if (options.instantMix !== false && !itemHelper.isLocalItem(item)) { - commands.push({ - name: globalize.translate('InstantMix'), - id: 'instantmix', - icon: 'explore' - }); - } + if ((item.MediaType === 'Audio' || item.Type === 'MusicAlbum' || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') + && options.instantMix !== false && !itemHelper.isLocalItem(item) + ) { + commands.push({ + name: globalize.translate('InstantMix'), + id: 'instantmix', + icon: 'explore' + }); } if (commands.length) { @@ -180,57 +179,49 @@ import toast from './toast/toast'; } const canEdit = itemHelper.canEdit(user, item); - if (canEdit) { - if (options.edit !== false && item.Type !== 'SeriesTimer') { - const text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata'); - commands.push({ - name: text, - id: 'edit', - icon: 'edit' - }); - } + if (canEdit && options.edit !== false && item.Type !== 'SeriesTimer') { + const text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata'); + commands.push({ + name: text, + id: 'edit', + icon: 'edit' + }); } - if (itemHelper.canEditImages(user, item)) { - if (options.editImages !== false) { - commands.push({ - name: globalize.translate('EditImages'), - id: 'editimages', - icon: 'image' - }); - } + if (itemHelper.canEditImages(user, item) && options.editImages !== false) { + commands.push({ + name: globalize.translate('EditImages'), + id: 'editimages', + icon: 'image' + }); } - if (canEdit) { - if (item.MediaType === 'Video' && item.Type !== 'TvChannel' && item.Type !== 'Program' && item.LocationType !== 'Virtual' && !(item.Type === 'Recording' && item.Status !== 'Completed')) { - if (options.editSubtitles !== false) { - commands.push({ - name: globalize.translate('EditSubtitles'), - id: 'editsubtitles', - icon: 'closed_caption' - }); - } - } + if (canEdit && item.MediaType === 'Video' && item.Type !== 'TvChannel' && item.Type !== 'Program' + && item.LocationType !== 'Virtual' + && !(item.Type === 'Recording' && item.Status !== 'Completed') + && options.editSubtitles !== false + ) { + commands.push({ + name: globalize.translate('EditSubtitles'), + id: 'editsubtitles', + icon: 'closed_caption' + }); } - if (options.identify !== false) { - if (itemHelper.canIdentify(user, item)) { - commands.push({ - name: globalize.translate('Identify'), - id: 'identify', - icon: 'edit' - }); - } + if (options.identify !== false && itemHelper.canIdentify(user, item)) { + commands.push({ + name: globalize.translate('Identify'), + id: 'identify', + icon: 'edit' + }); } - if (item.MediaSources) { - if (options.moremediainfo !== false) { - commands.push({ - name: globalize.translate('MoreMediaInfo'), - id: 'moremediainfo', - icon: 'info' - }); - } + if (item.MediaSources && options.moremediainfo !== false) { + commands.push({ + name: globalize.translate('MoreMediaInfo'), + id: 'moremediainfo', + icon: 'info' + }); } if (item.Type === 'Program' && options.record !== false) { @@ -240,11 +231,7 @@ import toast from './toast/toast'; id: 'record', icon: 'fiber_manual_record' }); - } - } - - if (item.Type === 'Program' && options.record !== false) { - if (!item.TimerId) { + } else { commands.push({ name: globalize.translate('Record'), id: 'record', @@ -277,26 +264,20 @@ import toast from './toast/toast'; }); } - if (!restrictOptions) { - if (options.share === true) { - if (itemHelper.canShare(item, user)) { - commands.push({ - name: globalize.translate('Share'), - id: 'share', - icon: 'share' - }); - } - } + if (!restrictOptions && options.share === true && itemHelper.canShare(item, user)) { + commands.push({ + name: globalize.translate('Share'), + id: 'share', + icon: 'share' + }); } - if (options.sync !== false) { - if (itemHelper.canSync(user, item)) { - commands.push({ - name: globalize.translate('Sync'), - id: 'sync', - icon: 'sync' - }); - } + if (options.sync !== false && itemHelper.canSync(user, item)) { + commands.push({ + name: globalize.translate('Sync'), + id: 'sync', + icon: 'sync' + }); } if (options.openAlbum !== false && item.AlbumId && item.MediaType !== 'Photo') { diff --git a/src/components/itemHelper.js b/src/components/itemHelper.js index 6773a6c79f..2a181d3424 100644 --- a/src/components/itemHelper.js +++ b/src/components/itemHelper.js @@ -48,10 +48,8 @@ export function getDisplayName(item, options = {}) { export function supportsAddingToCollection(item) { const invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer']; - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } + if (item.Type === 'Recording' && item.Status !== 'Completed') { + return false; } return !item.CollectionType && invalidTypes.indexOf(item.Type) === -1 && item.MediaType !== 'Photo' && !isLocalItem(item); @@ -74,10 +72,8 @@ export function supportsAddingToPlaylist(item) { return false; } - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } + if (item.Type === 'Recording' && item.Status !== 'Completed') { + return false; } if (isLocalItem(item)) { @@ -109,10 +105,8 @@ export function canEdit(user, item) { return false; } - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } + if (item.Type === 'Recording' && item.Status !== 'Completed') { + return false; } if (isLocalItem(item)) { @@ -133,23 +127,17 @@ export function isLocalItem(item) { export function canIdentify (user, item) { const itemType = item.Type; - if (itemType === 'Movie' || - itemType === 'Trailer' || - itemType === 'Series' || - itemType === 'BoxSet' || - itemType === 'Person' || - itemType === 'Book' || - itemType === 'MusicAlbum' || - itemType === 'MusicArtist' || - itemType === 'MusicVideo') { - if (user.Policy.IsAdministrator) { - if (!isLocalItem(item)) { - return true; - } - } - } - - return false; + return (itemType === 'Movie' + || itemType === 'Trailer' + || itemType === 'Series' + || itemType === 'BoxSet' + || itemType === 'Person' + || itemType === 'Book' + || itemType === 'MusicAlbum' + || itemType === 'MusicArtist' + || itemType === 'MusicVideo') + && user.Policy.IsAdministrator + && !isLocalItem(item); } export function canEditImages (user, item) { @@ -167,10 +155,8 @@ export function canEditImages (user, item) { return false; } - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } + if (item.Type === 'Recording' && item.Status !== 'Completed') { + return false; } return itemType !== 'Timer' && itemType !== 'SeriesTimer' && canEdit(user, item) && !isLocalItem(item); @@ -201,10 +187,8 @@ export function canShare (item, user) { if (item.Type === 'SeriesTimer') { return false; } - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } + if (item.Type === 'Recording' && item.Status !== 'Completed') { + return false; } if (isLocalItem(item)) { return false; @@ -301,11 +285,10 @@ export function canRefreshMetadata (item, user) { return false; } - if (item.Type !== 'Timer' && item.Type !== 'SeriesTimer' && item.Type !== 'Program' && item.Type !== 'TvChannel' && !(item.Type === 'Recording' && item.Status !== 'Completed')) { - if (!isLocalItem(item)) { - return true; - } - } + return item.Type !== 'Timer' && item.Type !== 'SeriesTimer' && item.Type !== 'Program' + && item.Type !== 'TvChannel' + && !(item.Type === 'Recording' && item.Status !== 'Completed') + && !isLocalItem(item); } return false; diff --git a/src/components/itemsrefresher.js b/src/components/itemsrefresher.js index 5a5d93e15d..2799a00b1a 100644 --- a/src/components/itemsrefresher.js +++ b/src/components/itemsrefresher.js @@ -94,16 +94,14 @@ function onPlaybackStopped(e, stopInfo) { const state = stopInfo.state; const eventsToMonitor = getEventsToMonitor(instance); - if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Video') { + if (state.NowPlayingItem?.MediaType === 'Video') { if (eventsToMonitor.indexOf('videoplayback') !== -1) { instance.notifyRefreshNeeded(true); return; } - } else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') { - if (eventsToMonitor.indexOf('audioplayback') !== -1) { - instance.notifyRefreshNeeded(true); - return; - } + } else if (state.NowPlayingItem?.MediaType === 'Audio' && eventsToMonitor.indexOf('audioplayback') !== -1) { + instance.notifyRefreshNeeded(true); + return; } } diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index ee75656367..eeb2946ec0 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -328,10 +328,8 @@ import ServerConnections from '../ServerConnections'; textlines.push(datetime.getDisplayTime(datetime.parseISO8601Date(item.StartDate))); } - if (options.showChannel) { - if (item.ChannelName) { - textlines.push(item.ChannelName); - } + if (options.showChannel && item.ChannelName) { + textlines.push(item.ChannelName); } let parentTitle = null; @@ -370,10 +368,8 @@ import ServerConnections from '../ServerConnections'; } if (item.IsFolder) { - if (options.artist !== false) { - if (item.AlbumArtist && item.Type === 'MusicAlbum') { + if (options.artist !== false && item.AlbumArtist && item.Type === 'MusicAlbum') { textlines.push(item.AlbumArtist); - } } } else { if (options.artist) { @@ -386,10 +382,8 @@ import ServerConnections from '../ServerConnections'; } } - if (item.Type === 'TvChannel') { - if (item.CurrentProgram) { - textlines.push(itemHelper.getDisplayName(item.CurrentProgram)); - } + if (item.Type === 'TvChannel' && item.CurrentProgram) { + textlines.push(itemHelper.getDisplayName(item.CurrentProgram)); } cssClass = 'listItemBody'; @@ -405,19 +399,17 @@ import ServerConnections from '../ServerConnections'; html += getTextLinesHtml(textlines, isLargeStyle); - if (options.mediaInfo !== false) { - if (!enableSideMediaInfo) { - const mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText'; + if (options.mediaInfo !== false && !enableSideMediaInfo) { + const mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText'; - html += `
`; - html += mediaInfo.getPrimaryMediaInfoHtml(item, { - episodeTitle: false, - originalAirDate: false, - subtitles: false + html += `
`; + html += mediaInfo.getPrimaryMediaInfoHtml(item, { + episodeTitle: false, + originalAirDate: false, + subtitles: false - }); - html += '
'; - } + }); + html += '
'; } if (enableOverview && item.Overview) { @@ -428,20 +420,18 @@ import ServerConnections from '../ServerConnections'; html += ''; - if (options.mediaInfo !== false) { - if (enableSideMediaInfo) { - html += '
'; - html += mediaInfo.getPrimaryMediaInfoHtml(item, { + if (options.mediaInfo !== false && enableSideMediaInfo) { + html += '
'; + html += mediaInfo.getPrimaryMediaInfoHtml(item, { - year: false, - container: false, - episodeTitle: false, - criticRating: false, - endsAt: false + year: false, + container: false, + episodeTitle: false, + criticRating: false, + endsAt: false - }); - html += '
'; - } + }); + html += '
'; } if (!options.recordButton && (item.Type === 'Timer' || item.Type === 'Program')) { diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index f21bc8f666..6f7876fcf1 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -129,17 +129,18 @@ import '../../elements/emby-button/emby-button'; } } - if ((item.Type === 'Episode' || item.MediaType === 'Photo') && options.originalAirDate !== false) { - if (item.PremiereDate) { - try { - //don't modify date to locale if episode. Only Dates (not times) are stored, or editable in the edit metadata dialog - date = datetime.parseISO8601Date(item.PremiereDate, item.Type !== 'Episode'); + if ((item.Type === 'Episode' || item.MediaType === 'Photo') + && options.originalAirDate !== false + && item.PremiereDate + ) { + try { + //don't modify date to locale if episode. Only Dates (not times) are stored, or editable in the edit metadata dialog + date = datetime.parseISO8601Date(item.PremiereDate, item.Type !== 'Episode'); - text = datetime.toLocaleDateString(date); - miscInfo.push(text); - } catch (e) { - console.error('error parsing date:', item.PremiereDate); - } + text = datetime.toLocaleDateString(date); + miscInfo.push(text); + } catch (e) { + console.error('error parsing date:', item.PremiereDate); } } @@ -239,17 +240,17 @@ import '../../elements/emby-button/emby-button'; } } - if (options.year !== false) { - if (item.Type !== 'Series' && item.Type !== 'Episode' && item.Type !== 'Person' && item.MediaType !== 'Photo' && item.Type !== 'Program' && item.Type !== 'Season') { - if (item.ProductionYear) { - miscInfo.push(item.ProductionYear); - } else if (item.PremiereDate) { - try { - text = datetime.parseISO8601Date(item.PremiereDate).getFullYear(); - miscInfo.push(text); - } catch (e) { - console.error('error parsing date:', item.PremiereDate); - } + if (options.year !== false && item.Type !== 'Series' && item.Type !== 'Episode' && item.Type !== 'Person' + && item.MediaType !== 'Photo' && item.Type !== 'Program' && item.Type !== 'Season' + ) { + if (item.ProductionYear) { + miscInfo.push(item.ProductionYear); + } else if (item.PremiereDate) { + try { + text = datetime.parseISO8601Date(item.PremiereDate).getFullYear(); + miscInfo.push(text); + } catch (e) { + console.error('error parsing date:', item.PremiereDate); } } } @@ -314,14 +315,12 @@ import '../../elements/emby-button/emby-button'; } export function getEndsAt(item) { - if (item.MediaType === 'Video' && item.RunTimeTicks) { - if (!item.StartDate) { - let endDate = new Date().getTime() + (item.RunTimeTicks / 10000); - endDate = new Date(endDate); + if (item.MediaType === 'Video' && item.RunTimeTicks && !item.StartDate) { + let endDate = new Date().getTime() + (item.RunTimeTicks / 10000); + endDate = new Date(endDate); - const displayTime = datetime.getDisplayTime(endDate); - return globalize.translate('EndsAtValue', displayTime); - } + const displayTime = datetime.getDisplayTime(endDate); + return globalize.translate('EndsAtValue', displayTime); } return null; diff --git a/src/components/nowPlayingBar/nowPlayingBar.js b/src/components/nowPlayingBar/nowPlayingBar.js index ddf0544727..b39c8bff00 100644 --- a/src/components/nowPlayingBar/nowPlayingBar.js +++ b/src/components/nowPlayingBar/nowPlayingBar.js @@ -444,12 +444,10 @@ import { appRouter } from '../appRouter'; options = options || {}; options.type = options.type || 'Primary'; - if (options.type === 'Primary') { - if (item.SeriesPrimaryImageTag) { - options.tag = item.SeriesPrimaryImageTag; + if (options.type === 'Primary' && item.SeriesPrimaryImageTag) { + options.tag = item.SeriesPrimaryImageTag; - return ServerConnections.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); - } + return ServerConnections.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); } if (options.type === 'Thumb') { diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 5d0f371f7d..1cbd99950a 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -44,10 +44,8 @@ function triggerPlayerChange(playbackManagerInstance, newPlayer, newTarget, prev return; } - if (newTarget && previousTargetInfo) { - if (newTarget.id === previousTargetInfo.id) { - return; - } + if (newTarget && previousTargetInfo && newTarget.id === previousTargetInfo.id) { + return; } Events.trigger(playbackManagerInstance, 'playerchange', [newPlayer, newTarget, previousPlayer]); @@ -501,10 +499,10 @@ function getPlaybackInfo(player, } // lastly, enforce player overrides for special situations - if (query.EnableDirectStream !== false) { - if (player.supportsPlayMethod && !player.supportsPlayMethod('DirectStream', item)) { - query.EnableDirectStream = false; - } + if (query.EnableDirectStream !== false + && player.supportsPlayMethod && !player.supportsPlayMethod('DirectStream', item) + ) { + query.EnableDirectStream = false; } if (player.getDirectPlayProtocols) { @@ -569,10 +567,10 @@ function getLiveStream(player, apiClient, item, playSessionId, deviceProfile, ma } // lastly, enforce player overrides for special situations - if (query.EnableDirectStream !== false) { - if (player.supportsPlayMethod && !player.supportsPlayMethod('DirectStream', item)) { - query.EnableDirectStream = false; - } + if (query.EnableDirectStream !== false + && player.supportsPlayMethod && !player.supportsPlayMethod('DirectStream', item) + ) { + query.EnableDirectStream = false; } return apiClient.ajax({ @@ -963,10 +961,8 @@ class PlaybackManager { self.isPlaying = function (player) { player = player || self._currentPlayer; - if (player) { - if (player.isPlaying) { - return player.isPlaying(); - } + if (player?.isPlaying) { + return player.isPlaying(); } return player != null && player.currentSrc() != null; @@ -975,10 +971,8 @@ class PlaybackManager { self.isPlayingMediaType = function (mediaType, player) { player = player || self._currentPlayer; - if (player) { - if (player.isPlaying) { - return player.isPlaying(mediaType); - } + if (player?.isPlaying) { + return player.isPlaying(mediaType); } if (self.isPlaying(player)) { @@ -1027,10 +1021,8 @@ class PlaybackManager { return true; } - if (item.LocationType === 'Virtual') { - if (itemType !== 'Program') { - return false; - } + if (item.LocationType === 'Virtual' && itemType !== 'Program') { + return false; } if (itemType === 'Program') { @@ -3300,10 +3292,10 @@ class PlaybackManager { reportPlayback(self, state, player, reportPlaylist, serverId, 'reportPlaybackProgress', progressEventName); } - if (streamInfo && streamInfo.liveStreamId) { - if (new Date().getTime() - (streamInfo.lastMediaInfoQuery || 0) >= 600000) { - getLiveStreamMediaInfo(player, streamInfo, self.currentMediaSource(player), streamInfo.liveStreamId, serverId); - } + if (streamInfo?.liveStreamId + && (new Date().getTime() - (streamInfo.lastMediaInfoQuery || 0) >= 600000) + ) { + getLiveStreamMediaInfo(player, streamInfo, self.currentMediaSource(player), streamInfo.liveStreamId, serverId); } } } @@ -3568,10 +3560,8 @@ class PlaybackManager { } getBufferedRanges(player = this._currentPlayer) { - if (player) { - if (player.getBufferedRanges) { - return player.getBufferedRanges(); - } + if (player?.getBufferedRanges) { + return player.getBufferedRanges(); } return []; @@ -3842,19 +3832,15 @@ class PlaybackManager { removeActivePlayer(name) { const playerInfo = this.getPlayerInfo(); - if (playerInfo) { - if (playerInfo.name === name) { - this.setDefaultPlayerActive(); - } + if (playerInfo?.name === name) { + this.setDefaultPlayerActive(); } } removeActiveTarget(id) { const playerInfo = this.getPlayerInfo(); - if (playerInfo) { - if (playerInfo.id === id) { - this.setDefaultPlayerActive(); - } + if (playerInfo?.id === id) { + this.setDefaultPlayerActive(); } } diff --git a/src/components/playback/playerSelectionMenu.js b/src/components/playback/playerSelectionMenu.js index f7eea17be1..9cbe2e5ac0 100644 --- a/src/components/playback/playerSelectionMenu.js +++ b/src/components/playback/playerSelectionMenu.js @@ -29,10 +29,8 @@ function mirrorIfEnabled(info) { if (info && playbackManager.enableDisplayMirroring()) { const getPlayerInfo = playbackManager.getPlayerInfo(); - if (getPlayerInfo) { - if (!getPlayerInfo.isLocalPlayer && getPlayerInfo.supportedCommands.indexOf('DisplayContent') !== -1) { - mirrorItem(info, playbackManager.getCurrentPlayer()); - } + if (getPlayerInfo && !getPlayerInfo.isLocalPlayer && getPlayerInfo.supportedCommands.indexOf('DisplayContent') !== -1) { + mirrorItem(info, playbackManager.getCurrentPlayer()); } } } @@ -85,11 +83,9 @@ function getIcon(target) { export function show(button) { const currentPlayerInfo = playbackManager.getPlayerInfo(); - if (currentPlayerInfo) { - if (!currentPlayerInfo.isLocalPlayer) { - showActivePlayerMenu(currentPlayerInfo); - return; - } + if (currentPlayerInfo && !currentPlayerInfo.isLocalPlayer) { + showActivePlayerMenu(currentPlayerInfo); + return; } const currentPlayerId = currentPlayerInfo ? currentPlayerInfo.id : null; diff --git a/src/components/playback/playersettingsmenu.js b/src/components/playback/playersettingsmenu.js index efeef4f354..c7f8f5a6da 100644 --- a/src/components/playback/playersettingsmenu.js +++ b/src/components/playback/playersettingsmenu.js @@ -238,7 +238,6 @@ function showWithUser(options, player, user) { return actionsheet.show({ items: menuItems, - resolveOnClick: true, positionTo: options.positionTo }).then(function (id) { return handleSelectedOption(id, options, player); diff --git a/src/components/playerstats/playerstats.js b/src/components/playerstats/playerstats.js index df15dac19d..225b0650c7 100644 --- a/src/components/playerstats/playerstats.js +++ b/src/components/playerstats/playerstats.js @@ -4,7 +4,7 @@ import globalize from '../../scripts/globalize'; import layoutManager from '../layoutManager'; import { playbackManager } from '../playback/playbackmanager'; import playMethodHelper from '../playback/playmethodhelper'; -import SyncPlay from '../../components/syncPlay/core'; +import SyncPlay from '../../plugins/syncPlay/core'; import './playerstats.scss'; import ServerConnections from '../ServerConnections'; diff --git a/src/components/playlisteditor/playlisteditor.js b/src/components/playlisteditor/playlisteditor.js index 440685fd9c..70ae0644d1 100644 --- a/src/components/playlisteditor/playlisteditor.js +++ b/src/components/playlisteditor/playlisteditor.js @@ -4,7 +4,7 @@ import dialogHelper from '../dialogHelper/dialogHelper'; import loading from '../loading/loading'; import layoutManager from '../layoutManager'; import { playbackManager } from '../playback/playbackmanager'; -import SyncPlay from '../../components/syncPlay/core'; +import SyncPlay from '../../plugins/syncPlay/core'; import * as userSettings from '../../scripts/settings/userSettings'; import { appRouter } from '../appRouter'; import globalize from '../../scripts/globalize'; diff --git a/src/components/recordingcreator/recordingbutton.js b/src/components/recordingcreator/recordingbutton.js index a05a44b2e5..f2d5376ea0 100644 --- a/src/components/recordingcreator/recordingbutton.js +++ b/src/components/recordingcreator/recordingbutton.js @@ -106,10 +106,8 @@ function getIndicatorIcon(item) { return 'fiber_manual_record'; } - if (item.SeriesTimerId) { - if (status !== 'Cancelled') { - return 'fiber_smart_record'; - } + if (item.SeriesTimerId && status !== 'Cancelled') { + return 'fiber_smart_record'; } return 'fiber_manual_record'; diff --git a/src/components/recordingcreator/recordingfields.js b/src/components/recordingcreator/recordingfields.js index 179b472bc3..ffc43b4bb4 100644 --- a/src/components/recordingcreator/recordingfields.js +++ b/src/components/recordingcreator/recordingfields.js @@ -63,15 +63,10 @@ function onTimerChangedExternally(e, apiClient, data) { const options = this.options; let refresh = false; - if (data.Id) { - if (this.TimerId === data.Id) { - refresh = true; - } - } - if (data.ProgramId && options) { - if (options.programId === data.ProgramId) { - refresh = true; - } + if (data.Id && this.TimerId === data.Id) { + refresh = true; + } else if (data.ProgramId && options && options.programId === data.ProgramId) { + refresh = true; } if (refresh) { @@ -83,15 +78,11 @@ function onSeriesTimerChangedExternally(e, apiClient, data) { const options = this.options; let refresh = false; - if (data.Id) { - if (this.SeriesTimerId === data.Id) { - refresh = true; - } + if (data.Id && this.SeriesTimerId === data.Id) { + refresh = true; } - if (data.ProgramId && options) { - if (options.programId === data.ProgramId) { - refresh = true; - } + if (data.ProgramId && options && options.programId === data.ProgramId) { + refresh = true; } if (refresh) { diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index 1dd5751129..1112a57c32 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -46,11 +46,9 @@ function getImageUrl(item, options, apiClient) { return apiClient.getScaledImageUrl(item.Id, options); } - if (options.type === 'Primary') { - if (item.AlbumId && item.AlbumPrimaryImageTag) { - options.tag = item.AlbumPrimaryImageTag; - return apiClient.getScaledImageUrl(item.AlbumId, options); - } + if (options.type === 'Primary' && item.AlbumId && item.AlbumPrimaryImageTag) { + options.tag = item.AlbumPrimaryImageTag; + return apiClient.getScaledImageUrl(item.AlbumId, options); } return null; diff --git a/src/components/subtitleeditor/subtitleeditor.js b/src/components/subtitleeditor/subtitleeditor.js index ead71f9cee..35d4943c58 100644 --- a/src/components/subtitleeditor/subtitleeditor.js +++ b/src/components/subtitleeditor/subtitleeditor.js @@ -114,10 +114,8 @@ function fillSubtitleList(context, item) { itemHtml += ''; itemHtml += ''; - if (!layoutManager.tv) { - if (s.Path) { - itemHtml += ''; - } + if (!layoutManager.tv && s.Path) { + itemHtml += ''; } itemHtml += ''; diff --git a/src/config.json b/src/config.json index 5b24006a48..3d80b1efec 100644 --- a/src/config.json +++ b/src/config.json @@ -44,6 +44,7 @@ "pdfPlayer/plugin", "logoScreensaver/plugin", "sessionPlayer/plugin", - "chromecastPlayer/plugin" + "chromecastPlayer/plugin", + "syncPlay/plugin" ] } diff --git a/src/controllers/dashboard/dashboard.js b/src/controllers/dashboard/dashboard.js index de722c751c..f700595c37 100644 --- a/src/controllers/dashboard/dashboard.js +++ b/src/controllers/dashboard/dashboard.js @@ -800,13 +800,11 @@ import confirm from '../../components/confirm/confirm'; }); } - if (ApiClient.isMinServerVersion('3.4.1.25')) { - if (!page.serverActivityLog) { - page.serverActivityLog = new ActivityLog({ - serverId: ApiClient.serverId(), - element: page.querySelector('.serverActivityItems') - }); - } + if (!page.serverActivityLog) { + page.serverActivityLog = new ActivityLog({ + serverId: ApiClient.serverId(), + element: page.querySelector('.serverActivityItems') + }); } refreshActiveRecordings(view, apiClient); diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index d5da82b740..a51bff1d50 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -1,6 +1,6 @@ import escapeHtml from 'escape-html'; import { playbackManager } from '../../../components/playback/playbackmanager'; -import SyncPlay from '../../../components/syncPlay/core'; +import SyncPlay from '../../../plugins/syncPlay/core'; import browser from '../../../scripts/browser'; import dom from '../../../scripts/dom'; import inputManager from '../../../scripts/inputManager'; diff --git a/src/elements/emby-input/emby-input.js b/src/elements/emby-input/emby-input.js index f9ea23f2ea..f62bcbf345 100644 --- a/src/elements/emby-input/emby-input.js +++ b/src/elements/emby-input/emby-input.js @@ -85,13 +85,9 @@ import 'webcomponents.js/webcomponents-lite'; passive: true }); - if (browser.orsay) { - if (this === document.activeElement) { - //Make sure the IME pops up if this is the first/default element on the page - if (document.attachIME) { - document.attachIME(this); - } - } + //Make sure the IME pops up if this is the first/default element on the page + if (browser.orsay && this === document.activeElement && document.attachIME) { + document.attachIME(this); } }; diff --git a/src/elements/emby-itemscontainer/emby-itemscontainer.js b/src/elements/emby-itemscontainer/emby-itemscontainer.js index 37edb8224c..4752613ddd 100644 --- a/src/elements/emby-itemscontainer/emby-itemscontainer.js +++ b/src/elements/emby-itemscontainer/emby-itemscontainer.js @@ -21,10 +21,8 @@ import Sortable from 'sortablejs'; const itemsContainer = this; const multiSelect = itemsContainer.multiSelect; - if (multiSelect) { - if (multiSelect.onContainerClick.call(itemsContainer, e) === false) { - return; - } + if (multiSelect?.onContainerClick.call(itemsContainer, e) === false) { + return; } itemShortcuts.onClick.call(itemsContainer, e); @@ -259,11 +257,9 @@ import Sortable from 'sortablejs'; itemsContainer.notifyRefreshNeeded(true); return; } - } else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') { - if (eventsToMonitor.indexOf('audioplayback') !== -1) { - itemsContainer.notifyRefreshNeeded(true); - return; - } + } else if (state.NowPlayingItem?.MediaType === 'Audio' && eventsToMonitor.indexOf('audioplayback') !== -1) { + itemsContainer.notifyRefreshNeeded(true); + return; } } @@ -298,10 +294,8 @@ import Sortable from 'sortablejs'; } } - if (layoutManager.desktop || layoutManager.mobile) { - if (this.getAttribute('data-multiselect') !== 'false') { - this.enableMultiSelect(true); - } + if (layoutManager.desktop || layoutManager.mobile && this.getAttribute('data-multiselect') !== 'false') { + this.enableMultiSelect(true); } if (layoutManager.tv) { diff --git a/src/elements/emby-slider/emby-slider.js b/src/elements/emby-slider/emby-slider.js index 0bb20270e6..04a8c94cf3 100644 --- a/src/elements/emby-slider/emby-slider.js +++ b/src/elements/emby-slider/emby-slider.js @@ -443,10 +443,8 @@ import '../emby-input/emby-input'; } for (const range of ranges) { - if (position != null) { - if (position >= range.end) { - continue; - } + if (position != null && position >= range.end) { + continue; } setRange(elem, range.start, range.end); diff --git a/src/elements/emby-tabs/emby-tabs.js b/src/elements/emby-tabs/emby-tabs.js index ce1fcee05d..723cb7e8fe 100644 --- a/src/elements/emby-tabs/emby-tabs.js +++ b/src/elements/emby-tabs/emby-tabs.js @@ -272,10 +272,8 @@ import '../../assets/css/scrollstyles.scss'; let sibling = elem[method]; while (sibling) { - if (sibling.classList.contains(buttonClass)) { - if (!sibling.classList.contains('hide')) { - return sibling; - } + if (sibling.classList.contains(buttonClass) && !sibling.classList.contains('hide')) { + return sibling; } sibling = sibling[method]; diff --git a/src/index.jsx b/src/index.jsx index 7ca4b92a24..81f3bcf43e 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -35,11 +35,6 @@ import './legacy/domParserTextHtml'; import './legacy/focusPreventScroll'; import './legacy/htmlMediaElement'; import './legacy/vendorStyles'; -import SyncPlay from './components/syncPlay/core'; -import { playbackManager } from './components/playback/playbackmanager'; -import SyncPlayNoActivePlayer from './components/syncPlay/ui/players/NoActivePlayer'; -import SyncPlayHtmlVideoPlayer from './components/syncPlay/ui/players/HtmlVideoPlayer'; -import SyncPlayHtmlAudioPlayer from './components/syncPlay/ui/players/HtmlAudioPlayer'; import { currentSettings } from './scripts/settings/userSettings'; import taskButton from './scripts/taskbutton'; import { HistoryRouter } from './components/HistoryRouter.tsx'; @@ -84,10 +79,10 @@ function init() { } function onGlobalizeInit() { - if (window.appMode === 'android') { - if (window.location.href.toString().toLowerCase().indexOf('start=backgroundsync') !== -1) { - return onAppReady(); - } + if (window.appMode === 'android' + && window.location.href.toString().toLowerCase().indexOf('start=backgroundsync') !== -1 + ) { + return onAppReady(); } document.title = globalize.translateHtml(document.title, 'core'); @@ -102,10 +97,7 @@ function onGlobalizeInit() { import('./assets/css/librarybrowser.scss'); - loadPlugins().then(function () { - initSyncPlay(); - onAppReady(); - }); + loadPlugins().then(onAppReady); } function loadPlugins() { @@ -137,27 +129,6 @@ function loadPlugins() { }); } -function initSyncPlay() { - // Register player wrappers. - SyncPlay.PlayerFactory.setDefaultWrapper(SyncPlayNoActivePlayer); - SyncPlay.PlayerFactory.registerWrapper(SyncPlayHtmlVideoPlayer); - SyncPlay.PlayerFactory.registerWrapper(SyncPlayHtmlAudioPlayer); - - // Listen for player changes. - Events.on(playbackManager, 'playerchange', (event, newPlayer, newTarget, oldPlayer) => { - SyncPlay.Manager.onPlayerChange(newPlayer, newTarget, oldPlayer); - }); - - // Start SyncPlay. - const apiClient = ServerConnections.currentApiClient(); - if (apiClient) SyncPlay.Manager.init(apiClient); - - // FIXME: Multiple apiClients? - Events.on(ServerConnections, 'apiclientcreated', (e, newApiClient) => SyncPlay.Manager.init(newApiClient)); - Events.on(ServerConnections, 'localusersignedin', () => SyncPlay.Manager.updateApiClient(ServerConnections.currentApiClient())); - Events.on(ServerConnections, 'localusersignedout', () => SyncPlay.Manager.updateApiClient(ServerConnections.currentApiClient())); -} - async function onAppReady() { console.debug('begin onAppReady'); diff --git a/src/libraries/navdrawer/navdrawer.js b/src/libraries/navdrawer/navdrawer.js index 8b786ea5fe..a152c1c203 100644 --- a/src/libraries/navdrawer/navdrawer.js +++ b/src/libraries/navdrawer/navdrawer.js @@ -289,34 +289,32 @@ class NavDrawer { setEdgeSwipeEnabled(enabled) { const options = this.options; - if (!options.disableEdgeSwipe) { - if (browser.touch) { - if (enabled) { - if (!this._edgeSwipeEnabled) { - this._edgeSwipeEnabled = true; - dom.addEventListener(this.edgeContainer, 'touchstart', this.onEdgeTouchStart, { - passive: true - }); - dom.addEventListener(this.edgeContainer, 'touchend', this.onEdgeTouchEnd, { - passive: true - }); - dom.addEventListener(this.edgeContainer, 'touchcancel', this.onEdgeTouchEnd, { - passive: true - }); - } - } else { - if (this._edgeSwipeEnabled) { - this._edgeSwipeEnabled = false; - dom.removeEventListener(this.edgeContainer, 'touchstart', this.onEdgeTouchStart, { - passive: true - }); - dom.removeEventListener(this.edgeContainer, 'touchend', this.onEdgeTouchEnd, { - passive: true - }); - dom.removeEventListener(this.edgeContainer, 'touchcancel', this.onEdgeTouchEnd, { - passive: true - }); - } + if (!options.disableEdgeSwipe && browser.touch) { + if (enabled) { + if (!this._edgeSwipeEnabled) { + this._edgeSwipeEnabled = true; + dom.addEventListener(this.edgeContainer, 'touchstart', this.onEdgeTouchStart, { + passive: true + }); + dom.addEventListener(this.edgeContainer, 'touchend', this.onEdgeTouchEnd, { + passive: true + }); + dom.addEventListener(this.edgeContainer, 'touchcancel', this.onEdgeTouchEnd, { + passive: true + }); + } + } else { + if (this._edgeSwipeEnabled) { + this._edgeSwipeEnabled = false; + dom.removeEventListener(this.edgeContainer, 'touchstart', this.onEdgeTouchStart, { + passive: true + }); + dom.removeEventListener(this.edgeContainer, 'touchend', this.onEdgeTouchEnd, { + passive: true + }); + dom.removeEventListener(this.edgeContainer, 'touchcancel', this.onEdgeTouchEnd, { + passive: true + }); } } } diff --git a/src/libraries/scroller.js b/src/libraries/scroller.js index 82fb79acb2..26b4a8370b 100644 --- a/src/libraries/scroller.js +++ b/src/libraries/scroller.js @@ -279,10 +279,8 @@ const scrollerFactory = function (frame, options) { const now = new Date().getTime(); - if (o.autoImmediate) { - if (!immediate && (now - (lastAnimate || 0)) <= 50) { - immediate = true; - } + if (o.autoImmediate && !immediate && (now - (lastAnimate || 0)) <= 50) { + immediate = true; } if (!immediate && o.skipSlideToWhenVisible && fullItemPos && fullItemPos.isVisible) { @@ -787,15 +785,13 @@ const scrollerFactory = function (frame, options) { passive: true }); } - } else if (o.horizontal) { + } else if (o.horizontal && o.mouseWheel) { // Don't bind to mouse events with vertical scroll since the mouse wheel can handle this natively - if (o.mouseWheel) { - // Scrolling navigation - dom.addEventListener(scrollSource, wheelEvent, scrollHandler, { - passive: true - }); - } + // Scrolling navigation + dom.addEventListener(scrollSource, wheelEvent, scrollHandler, { + passive: true + }); } dom.addEventListener(frame, 'click', onFrameClick, { diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index 947426ec26..aeced81b8b 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -452,11 +452,9 @@ function normalizeImages(state) { if (state && state.NowPlayingItem) { const item = state.NowPlayingItem; - if (!item.ImageTags || !item.ImageTags.Primary) { - if (item.PrimaryImageTag) { - item.ImageTags = item.ImageTags || {}; - item.ImageTags.Primary = item.PrimaryImageTag; - } + if ((!item.ImageTags || !item.ImageTags.Primary) && item.PrimaryImageTag) { + item.ImageTags = item.ImageTags || {}; + item.ImageTags.Primary = item.PrimaryImageTag; } if (item.BackdropImageTag && item.BackdropItemId === item.Id) { item.BackdropImageTags = [item.BackdropImageTag]; diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index d3a893e1dd..d7ae7f7841 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -67,16 +67,12 @@ function tryRemoveElement(elem) { } function enableNativeTrackSupport(currentSrc, track) { - if (track) { - if (track.DeliveryMethod === 'Embed') { - return true; - } + if (track?.DeliveryMethod === 'Embed') { + return true; } - if (browser.firefox) { - if ((currentSrc || '').toLowerCase().includes('.m3u8')) { - return false; - } + if (browser.firefox && (currentSrc || '').toLowerCase().includes('.m3u8')) { + return false; } if (browser.ps4) { @@ -92,11 +88,9 @@ function tryRemoveElement(elem) { return false; } - if (browser.iOS) { + if (browser.iOS && (browser.iosVersion || 10) < 10) { // works in the browser but not the native app - if ((browser.iosVersion || 10) < 10) { - return false; - } + return false; } if (track) { @@ -1500,10 +1494,11 @@ function tryRemoveElement(elem) { || document.pictureInPictureEnabled ) { list.push('PictureInPicture'); - } else if (window.Windows) { - if (Windows.UI.ViewManagement.ApplicationView.getForCurrentView().isViewModeSupported(Windows.UI.ViewManagement.ApplicationViewMode.compactOverlay)) { + } else if (window.Windows + && Windows.UI.ViewManagement.ApplicationView.getForCurrentView() + .isViewModeSupported(Windows.UI.ViewManagement.ApplicationViewMode.compactOverlay) + ) { list.push('PictureInPicture'); - } } if (browser.safari || browser.iOS || browser.iPad) { @@ -1564,13 +1559,7 @@ function tryRemoveElement(elem) { } const video = this.#mediaElement; - if (video) { - if (video.audioTracks) { - return true; - } - } - - return false; + return !!video?.audioTracks; } static onPictureInPictureError(err) { diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index 6997dc1732..50c6dae8a6 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -159,11 +159,9 @@ function normalizeImages(state, apiClient) { if (state && state.NowPlayingItem) { const item = state.NowPlayingItem; - if (!item.ImageTags || !item.ImageTags.Primary) { - if (item.PrimaryImageTag) { - item.ImageTags = item.ImageTags || {}; - item.ImageTags.Primary = item.PrimaryImageTag; - } + if (!item.ImageTags || !item.ImageTags.Primary && item.PrimaryImageTag) { + item.ImageTags = item.ImageTags || {}; + item.ImageTags.Primary = item.PrimaryImageTag; } if (item.BackdropImageTag && item.BackdropItemId === item.Id) { item.BackdropImageTags = [item.BackdropImageTag]; diff --git a/src/components/syncPlay/core/Controller.js b/src/plugins/syncPlay/core/Controller.js similarity index 100% rename from src/components/syncPlay/core/Controller.js rename to src/plugins/syncPlay/core/Controller.js diff --git a/src/components/syncPlay/core/Helper.js b/src/plugins/syncPlay/core/Helper.js similarity index 100% rename from src/components/syncPlay/core/Helper.js rename to src/plugins/syncPlay/core/Helper.js diff --git a/src/components/syncPlay/core/Manager.js b/src/plugins/syncPlay/core/Manager.js similarity index 99% rename from src/components/syncPlay/core/Manager.js rename to src/plugins/syncPlay/core/Manager.js index 16640c1df2..c41fe14fb7 100644 --- a/src/components/syncPlay/core/Manager.js +++ b/src/plugins/syncPlay/core/Manager.js @@ -9,7 +9,7 @@ import TimeSyncCore from './timeSync/TimeSyncCore'; import PlaybackCore from './PlaybackCore'; import QueueCore from './QueueCore'; import Controller from './Controller'; -import toast from '../../toast/toast'; +import toast from '../../../components/toast/toast'; import globalize from '../../../scripts/globalize'; /** diff --git a/src/components/syncPlay/core/PlaybackCore.js b/src/plugins/syncPlay/core/PlaybackCore.js similarity index 100% rename from src/components/syncPlay/core/PlaybackCore.js rename to src/plugins/syncPlay/core/PlaybackCore.js diff --git a/src/components/syncPlay/core/QueueCore.js b/src/plugins/syncPlay/core/QueueCore.js similarity index 99% rename from src/components/syncPlay/core/QueueCore.js rename to src/plugins/syncPlay/core/QueueCore.js index 81feac0aca..cdf1d56a1e 100644 --- a/src/components/syncPlay/core/QueueCore.js +++ b/src/plugins/syncPlay/core/QueueCore.js @@ -4,7 +4,7 @@ */ import globalize from '../../../scripts/globalize'; -import toast from '../../toast/toast'; +import toast from '../../../components/toast/toast'; import * as Helper from './Helper'; /** diff --git a/src/components/syncPlay/core/Settings.js b/src/plugins/syncPlay/core/Settings.js similarity index 100% rename from src/components/syncPlay/core/Settings.js rename to src/plugins/syncPlay/core/Settings.js diff --git a/src/components/syncPlay/core/index.js b/src/plugins/syncPlay/core/index.js similarity index 100% rename from src/components/syncPlay/core/index.js rename to src/plugins/syncPlay/core/index.js diff --git a/src/components/syncPlay/core/players/GenericPlayer.js b/src/plugins/syncPlay/core/players/GenericPlayer.js similarity index 100% rename from src/components/syncPlay/core/players/GenericPlayer.js rename to src/plugins/syncPlay/core/players/GenericPlayer.js diff --git a/src/components/syncPlay/core/players/PlayerFactory.js b/src/plugins/syncPlay/core/players/PlayerFactory.js similarity index 94% rename from src/components/syncPlay/core/players/PlayerFactory.js rename to src/plugins/syncPlay/core/players/PlayerFactory.js index 1de9aa5126..ab4170c9e7 100644 --- a/src/components/syncPlay/core/players/PlayerFactory.js +++ b/src/plugins/syncPlay/core/players/PlayerFactory.js @@ -16,7 +16,7 @@ class PlayerFactory { /** * Registers a wrapper to the list of players that can be managed. - * @param {GenericPlayer} wrapperClass The wrapper to register. + * @param {typeof GenericPlayer} wrapperClass The wrapper to register. */ registerWrapper(wrapperClass) { console.debug('SyncPlay WrapperFactory registerWrapper:', wrapperClass.type); @@ -25,7 +25,7 @@ class PlayerFactory { /** * Sets the default player wrapper. - * @param {GenericPlayer} wrapperClass The wrapper. + * @param {typeof GenericPlayer} wrapperClass The wrapper. */ setDefaultWrapper(wrapperClass) { console.debug('SyncPlay WrapperFactory setDefaultWrapper:', wrapperClass.type); diff --git a/src/components/syncPlay/core/timeSync/TimeSync.js b/src/plugins/syncPlay/core/timeSync/TimeSync.js similarity index 100% rename from src/components/syncPlay/core/timeSync/TimeSync.js rename to src/plugins/syncPlay/core/timeSync/TimeSync.js diff --git a/src/components/syncPlay/core/timeSync/TimeSyncCore.js b/src/plugins/syncPlay/core/timeSync/TimeSyncCore.js similarity index 100% rename from src/components/syncPlay/core/timeSync/TimeSyncCore.js rename to src/plugins/syncPlay/core/timeSync/TimeSyncCore.js diff --git a/src/components/syncPlay/core/timeSync/TimeSyncServer.js b/src/plugins/syncPlay/core/timeSync/TimeSyncServer.js similarity index 100% rename from src/components/syncPlay/core/timeSync/TimeSyncServer.js rename to src/plugins/syncPlay/core/timeSync/TimeSyncServer.js diff --git a/src/plugins/syncPlay/plugin.ts b/src/plugins/syncPlay/plugin.ts new file mode 100644 index 0000000000..e1b7c29cd6 --- /dev/null +++ b/src/plugins/syncPlay/plugin.ts @@ -0,0 +1,49 @@ +import { Events } from 'jellyfin-apiclient'; + +import { playbackManager } from '../../components/playback/playbackmanager'; +import ServerConnections from '../../components/ServerConnections'; +import SyncPlay from './core'; +import SyncPlayNoActivePlayer from './ui/players/NoActivePlayer'; +import SyncPlayHtmlVideoPlayer from './ui/players/HtmlVideoPlayer'; +import SyncPlayHtmlAudioPlayer from './ui/players/HtmlAudioPlayer'; + +class SyncPlayPlugin { + name: string; + id: string; + type: string; + priority: number; + + constructor() { + this.name = 'SyncPlay Plugin'; + this.id = 'syncplay'; + // NOTE: This should probably be a "mediaplayer" so the playback manager can handle playback logic, but + // SyncPlay needs refactored so it does not have an independent playback manager. + this.type = 'syncplay'; + this.priority = 1; + + this.init(); + } + + init() { + // Register player wrappers. + SyncPlay.PlayerFactory.setDefaultWrapper(SyncPlayNoActivePlayer); + SyncPlay.PlayerFactory.registerWrapper(SyncPlayHtmlVideoPlayer); + SyncPlay.PlayerFactory.registerWrapper(SyncPlayHtmlAudioPlayer); + + // Listen for player changes. + Events.on(playbackManager, 'playerchange', (_, newPlayer) => { + SyncPlay.Manager.onPlayerChange(newPlayer); + }); + + // Start SyncPlay. + const apiClient = ServerConnections.currentApiClient(); + if (apiClient) SyncPlay.Manager.init(apiClient); + + // FIXME: Multiple apiClients? + Events.on(ServerConnections, 'apiclientcreated', (_, newApiClient) => SyncPlay.Manager.init(newApiClient)); + Events.on(ServerConnections, 'localusersignedin', () => SyncPlay.Manager.updateApiClient(ServerConnections.currentApiClient())); + Events.on(ServerConnections, 'localusersignedout', () => SyncPlay.Manager.updateApiClient(ServerConnections.currentApiClient())); + } +} + +export default SyncPlayPlugin; diff --git a/src/components/syncPlay/ui/groupSelectionMenu.js b/src/plugins/syncPlay/ui/groupSelectionMenu.js similarity index 96% rename from src/components/syncPlay/ui/groupSelectionMenu.js rename to src/plugins/syncPlay/ui/groupSelectionMenu.js index 807899773f..106ee8e42d 100644 --- a/src/components/syncPlay/ui/groupSelectionMenu.js +++ b/src/plugins/syncPlay/ui/groupSelectionMenu.js @@ -1,12 +1,12 @@ import { Events } from 'jellyfin-apiclient'; import SyncPlay from '../core'; import SyncPlaySettingsEditor from './settings/SettingsEditor'; -import loading from '../../loading/loading'; -import toast from '../../toast/toast'; -import actionsheet from '../../actionSheet/actionSheet'; +import loading from '../../../components/loading/loading'; +import toast from '../../../components/toast/toast'; +import actionsheet from '../../../components/actionSheet/actionSheet'; import globalize from '../../../scripts/globalize'; import playbackPermissionManager from './playbackPermissionManager'; -import ServerConnections from '../../ServerConnections'; +import ServerConnections from '../../../components/ServerConnections'; import './groupSelectionMenu.scss'; /** diff --git a/src/components/syncPlay/ui/groupSelectionMenu.scss b/src/plugins/syncPlay/ui/groupSelectionMenu.scss similarity index 100% rename from src/components/syncPlay/ui/groupSelectionMenu.scss rename to src/plugins/syncPlay/ui/groupSelectionMenu.scss diff --git a/src/components/syncPlay/ui/playbackPermissionManager.js b/src/plugins/syncPlay/ui/playbackPermissionManager.js similarity index 96% rename from src/components/syncPlay/ui/playbackPermissionManager.js rename to src/plugins/syncPlay/ui/playbackPermissionManager.js index 2a70d7370a..816b57bca9 100644 --- a/src/components/syncPlay/ui/playbackPermissionManager.js +++ b/src/plugins/syncPlay/ui/playbackPermissionManager.js @@ -1,4 +1,4 @@ -import { appHost } from '../../apphost'; +import { appHost } from '../../../components/apphost'; /** * Creates an audio element that plays a silent sound. diff --git a/src/components/syncPlay/ui/players/HtmlAudioPlayer.js b/src/plugins/syncPlay/ui/players/HtmlAudioPlayer.js similarity index 100% rename from src/components/syncPlay/ui/players/HtmlAudioPlayer.js rename to src/plugins/syncPlay/ui/players/HtmlAudioPlayer.js diff --git a/src/components/syncPlay/ui/players/HtmlVideoPlayer.js b/src/plugins/syncPlay/ui/players/HtmlVideoPlayer.js similarity index 100% rename from src/components/syncPlay/ui/players/HtmlVideoPlayer.js rename to src/plugins/syncPlay/ui/players/HtmlVideoPlayer.js diff --git a/src/components/syncPlay/ui/players/NoActivePlayer.js b/src/plugins/syncPlay/ui/players/NoActivePlayer.js similarity index 99% rename from src/components/syncPlay/ui/players/NoActivePlayer.js rename to src/plugins/syncPlay/ui/players/NoActivePlayer.js index 699d31517b..c5f528938d 100644 --- a/src/components/syncPlay/ui/players/NoActivePlayer.js +++ b/src/plugins/syncPlay/ui/players/NoActivePlayer.js @@ -3,7 +3,7 @@ * @module components/syncPlay/ui/players/NoActivePlayer */ -import { playbackManager } from '../../../playback/playbackmanager'; +import { playbackManager } from '../../../../components/playback/playbackmanager'; import SyncPlay from '../../core'; import QueueManager from './QueueManager'; diff --git a/src/components/syncPlay/ui/players/QueueManager.js b/src/plugins/syncPlay/ui/players/QueueManager.js similarity index 100% rename from src/components/syncPlay/ui/players/QueueManager.js rename to src/plugins/syncPlay/ui/players/QueueManager.js diff --git a/src/components/syncPlay/ui/settings/SettingsEditor.js b/src/plugins/syncPlay/ui/settings/SettingsEditor.js similarity index 93% rename from src/components/syncPlay/ui/settings/SettingsEditor.js rename to src/plugins/syncPlay/ui/settings/SettingsEditor.js index 3f90725145..ede7e267a3 100644 --- a/src/components/syncPlay/ui/settings/SettingsEditor.js +++ b/src/plugins/syncPlay/ui/settings/SettingsEditor.js @@ -6,10 +6,10 @@ import { Events } from 'jellyfin-apiclient'; import SyncPlay from '../../core'; import { setSetting } from '../../core/Settings'; -import dialogHelper from '../../../dialogHelper/dialogHelper'; -import layoutManager from '../../../layoutManager'; -import loading from '../../../loading/loading'; -import toast from '../../../toast/toast'; +import dialogHelper from '../../../../components/dialogHelper/dialogHelper'; +import layoutManager from '../../../../components/layoutManager'; +import loading from '../../../../components/loading/loading'; +import toast from '../../../../components/toast/toast'; import globalize from '../../../../scripts/globalize'; import 'material-design-icons-iconfont'; @@ -18,8 +18,8 @@ import '../../../../elements/emby-select/emby-select'; import '../../../../elements/emby-button/emby-button'; import '../../../../elements/emby-button/paper-icon-button-light'; import '../../../../elements/emby-checkbox/emby-checkbox'; -import '../../../listview/listview.scss'; -import '../../../formdialog.scss'; +import '../../../../components/listview/listview.scss'; +import '../../../../components/formdialog.scss'; function centerFocus(elem, horiz, on) { import('../../../../scripts/scrollHelper').then((scrollHelper) => { diff --git a/src/components/syncPlay/ui/settings/editor.html b/src/plugins/syncPlay/ui/settings/editor.html similarity index 100% rename from src/components/syncPlay/ui/settings/editor.html rename to src/plugins/syncPlay/ui/settings/editor.html diff --git a/src/plugins/youtubePlayer/plugin.js b/src/plugins/youtubePlayer/plugin.js index 96d23c2f37..788dbfcfb1 100644 --- a/src/plugins/youtubePlayer/plugin.js +++ b/src/plugins/youtubePlayer/plugin.js @@ -333,10 +333,8 @@ class YoutubePlayer { setVolume(val) { const currentYoutubePlayer = this.currentYoutubePlayer; - if (currentYoutubePlayer) { - if (val != null) { - currentYoutubePlayer.setVolume(val); - } + if (currentYoutubePlayer && val != null) { + currentYoutubePlayer.setVolume(val); } } getVolume() { diff --git a/src/scripts/browser.js b/src/scripts/browser.js index b340a403f3..15e5cf6627 100644 --- a/src/scripts/browser.js +++ b/src/scripts/browser.js @@ -324,11 +324,9 @@ if (browser.mobile || browser.tv) { browser.slow = true; } -if (typeof document !== 'undefined') { - /* eslint-disable-next-line compat/compat */ - if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0)) { - browser.touch = true; - } +/* eslint-disable-next-line compat/compat */ +if (typeof document !== 'undefined' && ('ontouchstart' in window) || (navigator.maxTouchPoints > 0)) { + browser.touch = true; } browser.keyboard = hasKeyboard(browser); diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index 5c3b0b8ca8..9ac3c2b7eb 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -822,12 +822,12 @@ import browser from './browser'; maxH264Level = 52; } - if (browser.tizen || - videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, '')) { + if ((browser.tizen || + videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, '')) // These tests are passing in safari, but playback is failing - if (!browser.safari && !browser.iOS && !browser.web0s && !browser.edge && !browser.mobile) { - h264Profiles += '|high 10'; - } + && !browser.safari && !browser.iOS && !browser.web0s && !browser.edge && !browser.mobile + ) { + h264Profiles += '|high 10'; } let maxHevcLevel = 120; diff --git a/src/scripts/libraryBrowser.js b/src/scripts/libraryBrowser.js index 426b53eb45..b9fe249bd4 100644 --- a/src/scripts/libraryBrowser.js +++ b/src/scripts/libraryBrowser.js @@ -68,10 +68,8 @@ export function showLayoutMenu (button, currentLayout, views) { cancelable: false })); - if (!dispatchEvent) { - if (window.$) { - $(button).trigger('layoutchange', [id]); - } + if (!dispatchEvent && window.$) { + $(button).trigger('layoutchange', [id]); } } }); diff --git a/src/scripts/libraryMenu.js b/src/scripts/libraryMenu.js index 81f819f809..ce1918e196 100644 --- a/src/scripts/libraryMenu.js +++ b/src/scripts/libraryMenu.js @@ -9,7 +9,8 @@ import viewManager from '../components/viewManager/viewManager'; import { appRouter } from '../components/appRouter'; import { appHost } from '../components/apphost'; import { playbackManager } from '../components/playback/playbackmanager'; -import groupSelectionMenu from '../components/syncPlay/ui/groupSelectionMenu'; +import { pluginManager } from '../components/pluginManager'; +import groupSelectionMenu from '../plugins/syncPlay/ui/groupSelectionMenu'; import browser from './browser'; import globalize from './globalize'; import imageHelper from './imagehelper'; @@ -154,8 +155,14 @@ import '../assets/css/flexstyles.scss'; const policy = user.Policy ? user.Policy : user.localUser.Policy; - const apiClient = getCurrentApiClient(); - if (headerSyncButton && policy?.SyncPlayAccess !== 'None' && apiClient.isMinServerVersion('10.6.0')) { + if ( + // Button is present + headerSyncButton + // SyncPlay plugin is loaded + && pluginManager.plugins.filter(plugin => plugin.id === 'syncplay').length > 0 + // SyncPlay enabled for user + && policy?.SyncPlayAccess !== 'None' + ) { headerSyncButton.classList.remove('hide'); } } else { diff --git a/src/scripts/mouseManager.js b/src/scripts/mouseManager.js index 1ad3389c04..b00850a022 100644 --- a/src/scripts/mouseManager.js +++ b/src/scripts/mouseManager.js @@ -88,12 +88,10 @@ import dom from '../scripts/dom'; function onPointerEnter(e) { const pointerType = e.pointerType || (layoutManager.mobile ? 'touch' : 'mouse'); - if (pointerType === 'mouse') { - if (!isMouseIdle) { - const parent = focusManager.focusableParent(e.target); - if (parent) { - focusManager.focus(parent); - } + if (pointerType === 'mouse' && !isMouseIdle) { + const parent = focusManager.focusableParent(e.target); + if (parent) { + focusManager.focus(parent); } } } diff --git a/src/scripts/serverNotifications.js b/src/scripts/serverNotifications.js index d165593226..30d2171ae4 100644 --- a/src/scripts/serverNotifications.js +++ b/src/scripts/serverNotifications.js @@ -1,5 +1,5 @@ import { playbackManager } from '../components/playback/playbackmanager'; -import SyncPlay from '../components/syncPlay/core'; +import SyncPlay from '../plugins/syncPlay/core'; import { Events } from 'jellyfin-apiclient'; import inputManager from '../scripts/inputManager'; import focusManager from '../components/focusManager'; diff --git a/src/strings/tr.json b/src/strings/tr.json index 1afaa97347..7b1262c88e 100644 --- a/src/strings/tr.json +++ b/src/strings/tr.json @@ -914,7 +914,7 @@ "QuickConnectActivationSuccessful": "Başarıyla etkinleştirildi", "QuickConnect": "Hızlı Bağlantı", "LabelQuickConnectCode": "Hızlı Bağlantı kodu:", - "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "Bu ayarlar, bu cihaz tarafından başlatılan herhangi bir Chromecast oynatma için de geçerlidir.", + "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "Bu ayarlar, bu cihaz tarafından başlatılan herhangi bir ChromeCast oynatma için de geçerlidir.", "StopPlayback": "Oynatmayı durdur", "SyncPlayAccessHelp": "SyncPlay özelliği, oynatmayı diğer cihazlarla senkronize etmeyi sağlar. Bu kullanıcının SyncPlay sahip olduğu erişim düzeyini seçin.", "TitlePlayback": "Oynatma", @@ -1670,5 +1670,8 @@ "RememberSubtitleSelectionsHelp": "Altyazı dilini, son videoya en yakın eşleşmeye göre ayarlamayı dene.", "RememberAudioSelectionsHelp": "Ses dilini, son videoya en yakın eşleşmeye göre ayarlamayı dene.", "RememberAudioSelections": "Ses dilini önceki öğeye göre ayarla", - "RememberSubtitleSelections": "Altyazı dilini önceki öğeye göre ayarla" + "RememberSubtitleSelections": "Altyazı dilini önceki öğeye göre ayarla", + "TabContainers": "Barındırıcılar", + "OptionDateShowAdded": "Dizi Eklenme Tarihi", + "OptionDateEpisodeAdded": "Bölüm Eklenme Tarihi" }